Skip to content

fix(ios): show proposed battery locations without claiming confirmed fit - #212

Open
SamGu-NRX wants to merge 11 commits into
codex/candidate-20261003from
fix/provisional-placement-20261003
Open

SamGu-NRX wants to merge 11 commits into
codex/candidate-20261003from
fix/provisional-placement-20261003

Conversation

@SamGu-NRX

@SamGu-NRX SamGu-NRX commented Oct 3, 2026 •

Copy link
Copy Markdown
Owner

What changed

A passing placement calculation now produces "A possible battery spot", not "A battery fits here". The location, cable estimate and AR preview remain useful, while the result explains that the scan has not confirmed all the space a battery needs.

  • The shared result-reading model has a candidate answer and no affirmative fits case. A candidate requires a spot and nonempty, all-passing checks. Inconsistent pass data goes to installer review.
  • The card, Details, AR labels and spoken descriptions distinguish a proposed location from confirmed clearance. Passing calculation rows remain in Details with their measurements, without unqualified positive reasons. Passed regions use the proposal's blue rather than clear-ground green.
  • A result gives a neutral light haptic instead of the success signal. Returning from AR gives no repeated signal.

This follows #210 and targets its frozen codex/candidate-20261003 branch. The branch also preserves main's #194 push-review configuration. No source PR base has been advanced.

Why

The solver can rely on observed regions beyond the smaller area the homeowner confirms. The current result contract does not identify all supporting regions, and neither a camera view nor the presence of LiDAR proves that those regions are empty. A useful proposed location should not be presented as a verified fit.

The homeowner's answer, retry path and settled-confirmation shortcut all use the same result reading. A previous "It's clear" answer cannot upgrade it to a confirmed fit.

UI changes

The card keeps the proposed location and explains the on-site check. Details labels checks as calculations on recorded data. AR keeps the battery preview and calls it proposed. Actual negative and unsure checks retain their meaning and available follow-up actions.

After-only captures: no earlier hosted run captured a passing result, so there is no matching "before" frame. All frames come from hosted run 37170744330 at 0fb7380 on the iPhone 17 Simulator (iOS 26.5). The engine frames use the real engine on the synthetic replay, with test-served answers. The others use Fixtures/results answers, which the demo labels as samples.

Real engine: result Real engine: AR
Result card for the real engine: "A possible battery spot", 4 ft 3 in right of the meter with 3 ft of cable, a note that the scan couldn't confirm all the space and an installer needs to check the fit on site, and "See this spot on your wall" AR view: title "A possible battery spot", detail "4 ft 3 in right of your meter, 3 ft of cable. An installer needs to check the fit on site.", the battery drawn on the wall, Done
Details (sample pass answer) Rejected wall (sample)
Details headed "What the server calculated", with a note that a passing check means the recorded measurements meet the rule, not that the space is confirmed clear; passing rows show an outline check and their measurements "Not on this wall": the closest spot fails distance from doors and windows, measured 5 in against a rule of at least 3 ft, with a red fail line and "Scan another wall"
Real engine AR at the largest text size, folded Same, Details open
AR at AX-XXXL: the card shows only "A possible battery spot" and Details, leaving 400 pt of camera between the card and Done with the battery visible AR at AX-XXXL with Details open: "4 ft 3 in right of your meter, 3 ft of cable. An installer needs to check the fit on site."

The test measured 400 pt of open camera between the folded card and Done, both before and after opening Details.

Verification

  • Added package tests for the candidate mapping, inconsistent pass data, unknown checks, negative results and unchanged response binding/data.
  • Added real-engine replay tests for retry plus a clear answer and reuse of a settled confirmation. Added default-size and largest-text presentation checks covering the card, Details, AR and a rejected wall.
  • Hosted run 37170744330 at 0fb7380 passed: 714 package tests in 96 suites, and 92 UI tests with 1 skipped and none failing, including all six ProvisionalPlacementUITests. The previous head, c9295df, passed the same way in 37166686298.
  • Earlier runs on this PR failed and were fixed:
    • 37162046960: a test answer set unsure_cause to null, which the schema doesn't allow.
    • 37162669527: three new tests matched more than one element for result.details.
  • An independent source review prompted corrections to contradictory summary text and the panel footnote. A prep-for-prod review prompted the AR card fold at the accessibility sizes: there, while the spot is in view, the card keeps its title and folds the placement and caveat under Details, using the existing per-screen CameraChrome(aims:).

Risk

This contains the claim shown to the homeowner. It does not repair the underlying observation/confirmation-area mismatch, prove geometry or obstacle detection, or establish physical-phone acceptance. The supporting-region contract remains open.

Known accessibility limits, unchanged here:

  • Clearance zones are still told apart by color alone, as they were before this PR.
  • The off-screen spot arrow uses fixed screen regions, not the measured camera window. At the largest text size the folded card's bottom (y 368) sits below the arrow's assumed top (y 260), so a spot projected in that band could count as in view while the card covers it. No capture shows the arrow, so this is unverified.

Raw server answers, response hashes, scene exports and packet data are unchanged. The app does not arrange an installer visit or send a review request. Working-space uncertainty and sample-result disclosures remain distinct.

Checklist

  • The scope is focused; related changes belong together
  • I explained what changed and why
  • I included images for visible changes (after only: no earlier run captured a passing result)
  • N/A: no new animation; physical haptic behavior still needs device verification

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Scan results now present qualifying locations as possible battery spots, rather than confirmed fits, with an on-site fit-check reminder.
    • Result details focus on checks that need attention and clarify that passing checks reflect recorded measurements.
  • Updates
    • Proposed spots are labeled consistently in 3D and AR views, with updated clearance-zone colors and clearer AR guidance.
    • Scan transitions now use distinct haptic feedback for meter pinning and result arrival.
    • Result cards now prioritize checks that need attention and handle proposed spots consistently across supported actions.

SamGu-NRX and others added 6 commits October 1, 2026 14:42
…261001

chore(review): run Greptile again when PR commits change
Preserve main's push-review configuration while carrying the unchanged
tested 485f1a6 app into a separate continuation branch.

Co-Authored-By: Claude Code <noreply@anthropic.com>
The server's checks pass on observed space beyond the area the homeowner
confirms in the spot check, some of it inferred rather than seen (a walked
path, a photo's view), and the answer doesn't say which. The app can't tell
that all the space a battery needs was confirmed (B17), so no result says a
battery fits.

ResultReading's affirmative answer becomes `candidate`: "A possible battery
spot", with a note that the scan couldn't confirm all the space and an
installer needs to check the fit on site. Every path that read as a fit
goes through it, policy-only manual review included, so a retry, a clear
answer or a settled earlier answer can't restore one. The other answers are
unchanged, and so are the server's answer, its binding, the scene and the
packet.

Every result surface agrees. The card shows only failing and unsure checks.
Details calls its list the server's calculations on what the scan recorded,
drops a pass's positive server reason (keeping its measurement), and hides a
candidate's pass summary. The AR title, overlay and off-screen direction
name the proposed spot, and passing clearance zones draw in the proposal's
blue rather than clear-ground green. The result arrives with a light tap
instead of the success haptic (B26).

The card's pass ranking was the only use of ResultReading.margin, so it is
removed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
ResultReading.answer read any pass decision as a candidate, so a pass with
no spot or no checks still said "A possible battery spot", and the new
exhaustive test caught it. A candidate now needs a spot and at least one
check, every one passing; a pass that contradicts itself goes to an
installer, with its checks shown as sent. A reject without a spot stays
"Not on this wall", and the exhaustive test now checks that too.

Details' pass word is now "Passes on recorded data", under the existing
note on what the list is. The real-engine UI tests terminate their app, and
the render sweep leaves out the scope note's own "not ... confirmed clear".

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Details hid only a candidate's summary, assuming any other summary explains
what failed. A pass the reading sends to an installer still carries the
server's pass summary, and the demo's review answer said "A spot 3 ft right
of your meter fits" under One more look (Sol review). Details now hides the
summary of any pass decision as well as any candidate; manual review and
reject summaries stay. The demo's review summary names the best spot
without calling it a fit, and the panel footnote says the scan suggests
where the battery could go rather than covering where it can.

A UI test opens Details on the demo's review and overlap answers and checks
the summary is there and claims no fit.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@SamGu-NRX SamGu-NRX added the full-ui iOS CI also runs the every-state accessibility audit (about 10 more minutes). label Oct 3, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-04T02:24:20.921790Z 0fb7380 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions github-actions Bot added the size:L 100-499 effective changed lines. label Oct 3, 2026
@coderabbitai

coderabbitai Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

🧰 Additional context used
📚 Code guidelines (1)
ios/README.md — auto-discovered

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 96b6a4db-faea-4938-9bd8-ad2c1cf5be80
📥 Commits

Reviewing files that changed from the base of the PR and between c9295df and 0fb7380.

📒 Files selected for processing (2)
  • ios/HouseScan/UI/Screens/ResultARScreen.swift
  • ios/HouseScanUITests/ProvisionalPlacementUITests.swift

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The iOS result model and screens now present qualifying passing results as possible battery spots, not confirmed fits. Check details identify recorded-data outcomes, and meter pinning and result arrival use separate haptics. Greptile reviews are enabled for open and push events.

Changes

Provisional Placement Results

Layer / File(s) Summary
Candidate result interpretation
ios/HouseScanKit/Sources/HouseScanKit/Scene/ResultReading.swift, ios/HouseScan/Contract/ResultPresentation+Reading.swift, ios/HouseScanKit/Sources/HouseScanKit/Scene/ResultCardActions.swift, ios/HouseScanKit/Tests/HouseScanKitTests/*
Qualifying pass and manual-review results with a spot and all passing checks map to .candidate. Margin data and passing card lines are removed. Unit tests cover candidate constraints, retained server data, card lines, and primary actions.
Candidate result and check presentation
ios/HouseScan/UI/Copy/ScanCopy.swift, ios/HouseScan/UI/Screens/ResultScreen.swift, ios/HouseScan/UI/Preview/DemoEngine.swift, ios/HouseScan/UI/Result/ResultScene3D.swift, ios/HouseScan/UI/Theme/Theme.swift
Result copy identifies a possible spot and explains that checks use recorded measurements. Candidate cards show the fit-check note. Passing checks omit positive reasons, and clearance zones use the zone palette.
AR instructions and placement UI tests
ios/HouseScan/UI/Copy/ScanCopy.swift, ios/HouseScan/UI/Screens/ResultARScreen.swift, ios/HouseScanUITests/ProvisionalPlacementUITests.swift
AR labels and instructions use shared candidate copy and include an on-site fit check for candidate results. UI tests cover candidate presentation, replay flows, rejected results, and large text.

Scan Haptic Feedback

Layer / File(s) Summary
Separate meter and result haptics
ios/HouseScan/UI/ScanRootView.swift
Meter pinning triggers a success haptic. Result arrival triggers a light impact, except when returning from AR.

Greptile Review Setup

Layer / File(s) Summary
Configure review events and guidance
.greptile/config.json, CONTRIBUTING.md
Greptile automatic review is enabled for open and push events. Contribution guidance describes the configuration and manual review commands.

Priority: ➖ Normal

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

Change: Bug fix

Suggested reviewers: aidenjohnston

Merge Risk: ⚪ Minimal · up to 0fb73

The change presents passing results as possible battery spots, not confirmed fits. No merge-blocking issue was found in the reviewed changes. Physical-device haptic behavior still needs verification, as the author notes.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 0fb73

The change makes placement advice more conservative: passing calculations describe a possible spot, not a verified fit. The inspected confirmation and AR flows do not upgrade that answer or grant new camera authority. Remaining uncertainty concerns complete before-and-after coverage and the effective permissions of automated repository reviews.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The inspected contract change primarily affects homeowner-facing interpretation of placement data and available follow-up actions. The changed AR entrypoints remain downstream presentation consumers; they do not establish a new privileged command or camera-authority path.

Trust Boundaries and Controls

  • observed — Classification does not accept a server passing decision alone as sufficient for a candidate: it additionally requires a spot and nonempty, all-passing checks. Homeowner confirmations affect confirmation and follow-up state rather than assigning a new placement answer.
  • observed — spotIsClean is narrower than candidate classification and can be true while another check fails or remains unsure. AR uses it for preview selection, but uses the shared answer for instructions and calls the overlay proposed. This distinction is not evidence of confirmed clearance.

Resilience and Maintainability Implications

  • observed — A UI test exercises a repeated answer settled by an earlier confirmation and asserts that both result and AR still describe a candidate, including the installer caveat. This is source-level regression evidence, not evidence that the test passed in this review.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.63% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 59 functions across 13 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: presenting battery locations as proposed rather than confirmed fits.
Description check ✅ Passed The description covers the required sections: changes, rationale, UI behavior, verification, risks, and checklist. It also includes relevant captures and reports test results and known limitations.
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.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@codemetrics-ai

codemetrics-ai Bot commented Oct 3, 2026

Copy link
Copy Markdown

Note

Review skipped

Codemetrics is installed on this repository, but it hasn't been added to your team yet.

To enable AI code reviews for this repo, go to your dashboard and add BaseScanning to your team's repositories.

@greptile-apps

greptile-apps Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium risk] Changes how battery placement results are presented to users.

The PR appears safe to merge based on the reviewed changes.

Summary

The PR changes passing placement results from confirmed-fit language to proposed-location language. It keeps measurements in Details, updates AR labels and clearance colors, changes the result haptic, and adds package and UI coverage.

Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Server placement result] --> B[ResultReading]
  B -->|Spot and nonempty all-pass checks| C[Candidate]
  B -->|Other outcomes| D[Review, another look, or rejection]
  C --> E[Possible-spot card and Details]
  C --> F[Proposed AR preview]
Loading

Reviews (4) · Last reviewed commit: "Measure the AR camera window from the ca..."

SamGu-NRX and others added 2 commits October 3, 2026 18:35
The prep-for-prod review found the AX5 check ran only on a demo answer,
which is a sample with a different AR instruction, while the real
candidate's longer instruction ran only at the default size. The settled
engine test now runs at the largest text size, opens the AR view, checks
its instruction names a possible spot and what the fit still needs, and
that Done stays reachable, with screenshots of the card, its note and the
AR view.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The result schema's unsure_cause is an enum without null, so the bound
all-pass answer in readingAPassLeavesTheAnswerAsTheServerSentIt failed
validation (Actions run 37162046960, the run's only failure out of 714
package tests). Both that test and the UI test's passing answer now remove
the key instead of setting it to null. Both answers validate against the
schema with Python's jsonschema.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@SamGu-NRX

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: 8e9b07c931

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

… UI tests

Three demo-answer tests failed at the scroll helper with "Multiple matching
elements found" (Actions run 37162669527): Details' DisclosureGroup puts
its identifier, result.details, on more than one element, and reading a
frame or tapping needs exactly one. Every lookup in the file now takes the
first match, as ResultCardUITests' element helper does. The engine tests,
the reject test and every other suite in that run passed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@SamGu-NRX

Copy link
Copy Markdown
Owner Author

@codex review

At AX-XXXL the AR card held the title, the placement and the on-site caveat
in full and covered nearly the whole camera (run 37162669527,
resultAR-candidate-settled-AX5), so "See this spot on your wall" showed
little of the spot. While the phone tracks and the result has a spot, the
AR screen now sets CameraChrome's existing `aims`: at the accessibility
sizes the card keeps its title ("A possible battery spot", or the sample's
"Example spot, not your result") and folds the rest under Details, leaving
at least the chrome's 180 pt camera window. "Point at your meter" while
tracking is lost keeps every word in view. CameraChrome itself is unchanged.

The settled engine test, at AX-XXXL, checks the folded card, measures the
open camera between it and Done, opens Details to read the placement and
caveat, folds it again, measures again, and returns with Done, with
screenshots of each state.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: c9295df217

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

…creen

The open-camera check measured from the Details label, which leaves out the
card's padding under it, and could count space off screen (Sol review of
a7b4ec3). It now adds that padding, clips both edges to the window, and
requires Done to be hittable before measuring.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@SamGu-NRX

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@SamGu-NRX

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: 0fb7380ce4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@SamGu-NRX

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

This branch has not been deployed

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

Labels

full-ui iOS CI also runs the every-state accessibility audit (about 10 more minutes). size:L 100-499 effective changed lines.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant