Skip to content

focus: a reading that cannot rise is not a measurement - #34

Merged
widgetii merged 2 commits into
mainfrom
focus-clamp
Sep 24, 2026
Merged

widgetii merged 2 commits into
mainfrom
focus-clamp

Conversation

@widgetii

Copy link
Copy Markdown
Member

Found by running v0.16.0's sweep against a real lens on an 85H50AI.

The bank being measured moved 2.6× across a defocus sweep on its own sum — and the sweep reported "falls to 1/1.0". Its peak zone sat on 65,535 at both ends; 34 of 255 zones were pinned there.

The bug

The per-zone accumulators are u16. A zone at the top of that range has stopped measuring: the filter's real response went higher and the counter could not say so. A pinned value cannot fall, so a sweep taken across one reports that nothing changed — which is indistinguishable from a filter that genuinely cannot see focus, and needs the opposite fix. Cut the gain, or change the filter. They must not produce the same number.

The fix

summarise() returns two new fields:

  • saturated — how many zones are at the ceiling
  • peakSaturated — whether the zone that set the peak is one of them, which is what actually makes a sweep flat

Reported, not subtracted. Dropping a pinned zone from the peak would hand back some lower zone's value as though it were a measurement; the honest answer is that the peak is real but cannot rise, and the caller is told so.

Only h2 and v2 count — the two the blend is made of. h1 and v1 belong to the other bank and can sit at the ceiling all day without touching the value this page reports.

This is not clipped. That one is about the picture: pixels over the high-luma threshold, a specular highlight in an otherwise fine zone. A saturated zone can be perfectly exposed. What is full is the counter, and the cause is the filter's gain, not the scene.

What the operator sees

The live grid names the count, and whether the sharpest zone is among them. The sweep counts pinned readings at every position and, given any, refuses to state a ratio at all — saying which knob fixes it instead of returning a number that looks like a measurement.

A filter that is merely flat still gets its honest 1/1.0. Being pinned is the only thing that buys an excuse, and there is a test for that direction too.

Tests

Six assertions in tools/smoke.mjs, four in tests/ui-check.html. Every guard mutation-tested — breaking it turns exactly the checks written for it red:

break red
sweep still reports a ratio when pinned refuses to give a ratio; says which knob fixes it
sweep does not notice pinning same two
live grid stays quiet about a full counter says when the counter is full; and that it is the sharpest zone
v2 at the ceiling ignored v2 at the ceiling counts too
peak never called pinned 4 checks
nothing ever saturated 7 checks

node tools/smoke.mjs and node tools/ui-check.mjs both pass.

Found by running the sweep against a real lens. On an 85H50AI the bank being
measured moved 2.6x across a defocus sweep on its own sum -- and the sweep
reported "falls to 1/1.0", because its peak zone sat on 65535 at both ends.
34 of 255 zones were pinned there.

The per-zone accumulators are u16, and a zone at the top of that range has
stopped measuring: the filter's real response went higher and the counter
could not say so. A pinned value cannot fall, so a sweep across one reports
that nothing changed -- indistinguishable from a filter that genuinely
cannot see focus, and needing the opposite fix. Cut the gain, or change the
filter. They must not produce the same number.

summarise() now returns `saturated` and `peakSaturated`. Reported, not
subtracted: dropping a pinned zone would hand back some lower zone's value
as though it were the peak. Only h2 and v2 count, the two the blend is made
of -- h1 and v1 belong to the other bank and never reach the reported value.

This is NOT `clipped`, which is about the picture: pixels over the high-luma
threshold, a specular highlight in an otherwise fine zone. A saturated zone
can be perfectly exposed. What is full is the counter, and the cause is the
filter's gain, not the scene.

The live grid names the count and whether the sharpest zone is among them.
The sweep counts pinned readings at every position and, given any, refuses
to state a ratio at all -- it says which knob fixes it instead. A filter
that is merely flat still gets its honest 1/1.0; being pinned is the only
thing that buys an excuse.

Ten checks, every guard mutation-tested: breaking it turns exactly the
checks written for it red.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Detect saturated focus zones and reject invalid sweep ratios

🐞 Bug fix 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Detects focus zones whose active filter counters have reached the u16 ceiling.
• Warns operators and suppresses misleading ratios when sweep peaks are saturated.
• Covers saturated, unsaturated, inactive-bank, dark-zone, and live-grid behavior.
Diagram

graph TD
  G["Camera Grid"] --> S["Grid Summary"] --> W["Sweep Readings"] --> D{"Pinned peak?"}
  D -->|Yes| X["Gain Warning"]
  D -->|No| R["Sweep Ratio"]
  S --> L["Live Grid"]
Loading
High-Level Assessment

The chosen approach is appropriate: preserve the measured peak, expose saturation as separate metadata, and reject only comparisons affected by a pinned peak. Excluding saturated zones was considered but would substitute a lower value and falsely present it as the true peak; treating saturation as clipping would also conflate filter-gain limits with scene exposure.

Files changed (6) +220 / -4

Bug fix (4) +148 / -4
aftune.jsExpose focus-counter saturation in distributed summaries +35/-0

Expose focus-counter saturation in distributed summaries

• Adds the u16 zone ceiling and detects saturation only in the h2/v2 banks used by the reported blend. Grid summaries now include the saturated-zone count and whether the selected measured peak is saturated.

dist/aftune.js

editor.jsWarn about pinned counters and reject invalid distributed sweep ratios +39/-2

Warn about pinned counters and reject invalid distributed sweep ratios

• Shows live warnings for saturated zones, including whether the sharpest zone is affected. Lens sweeps count saturated peaks at every position and return corrective gain guidance instead of a misleading focus ratio.

dist/editor.js

aftune.jsAdd saturation metadata to focus summaries +35/-0

Add saturation metadata to focus summaries

• Defines the 65,535 accumulator ceiling and checks only the h2/v2 inputs contributing to the active blend. Reports saturation without removing pinned zones from peak selection and distinguishes peak saturation from general zone saturation.

src/aftune.js

editor.jsPrevent saturated sweeps from reporting false focus falloff +39/-2

Prevent saturated sweeps from reporting false focus falloff

• Adds live-grid saturation guidance and tracks pinned peak readings across the complete lens sweep. Suppresses the ratio whenever any sweep peak is saturated while preserving normal reporting for genuinely flat, unsaturated filters.

src/editor.js

Tests (2) +72 / -0
ui-check.htmlCover saturation warnings and sweep refusal behavior +38/-0

Cover saturation warnings and sweep refusal behavior

• Adds UI checks proving pinned sweeps refuse ratios and direct operators to lower the first gain. Also verifies unsaturated flat sweeps still report normally and live status identifies saturated sharpest zones.

tests/ui-check.html

smoke.mjsTest focus saturation classification and peak handling +34/-0

Test focus saturation classification and peak handling

• Covers exact and below-ceiling values, both active blend banks, ignored inactive banks, retained saturated peaks, and saturated zones excluded from measured peak selection because they are dark.

tools/smoke.mjs

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Tied pinned peaks still produce ratios ✓ Resolved 🐞 Bug ≡ Correctness
Description
summarise() chooses the first maximum with strict > and sets peakSaturated from only that
zone, even when another measured zone tied at the same peak is saturated. If an unsaturated zone
such as {h2: 65534, v2: 5} precedes {h2: 65535, v2: 0}, both blend to 55295 but the sweep
records no pin and presents the invalid ratio.
Code

src/aftune.js[146]

+		peakSaturated: peakAt >= 0 && sat[peakAt],
Evidence
Peak selection retains the first equal maximum, while the new flag examines only that selected
index. The sweep increments pinned exclusively from this flag and suppresses the ratio only when
pinned is nonzero, so a later saturated tie reaches the normal ratio output.

src/aftune.js[125-146]
src/editor.js[3403-3408]
src/editor.js[3735-3744]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A saturated measured zone can tie an earlier unsaturated zone for the maximum blended value. Because peak selection retains the first zone and `peakSaturated` checks only its index, the sweep can incorrectly report a ratio despite a pinned peak.
## Fix Focus Areas
- src/aftune.js[125-146]
- dist/aftune.js[125-146]
- tools/smoke.mjs[1138-1170]
## Recommended Fix
Set `peakSaturated` when any measured zone whose blended value equals the selected peak is saturated, rather than checking only `peakAt`. Apply the equivalent generated distribution change and add a regression test with an unsaturated zone preceding an equal blended-value saturated zone.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can choose which labels appear on a finding, and whether they show icons or text

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/aftune.js Outdated
Review caught a real hole. Peak selection keeps the first strict maximum,
so a saturated zone can tie with an unsaturated one and lose: {h2: 65534,
v2: 5} and {h2: 65535, v2: 0} both blend to 55295. Reading the flag off the
winning index alone let grid ORDER decide whether the reading was
trustworthy -- the pinned zone was equally the peak, and the sweep went on
to print a ratio over it.

If anything at the top of the grid cannot rise, the peak cannot rise.
@widgetii

Copy link
Copy Markdown
Member Author

Real, and the example is exact — fixed in 867fa3f.

trunc((65534*54 + 5*10)/64) and trunc((65535*54 + 0)/64) both come to 55295, peak selection keeps the first strict maximum, so the unsaturated zone wins and the pinned one — equally the peak — was never consulted. Grid order decided whether the reading was trustworthy.

peakSaturated now asks whether any measured zone tied at the peak value is saturated:

peakSaturated: peakAt >= 0 &&
    fv.some((v, i) => v === peak && state[i] === 'measured' && sat[i]),

If anything at the top of the grid cannot rise, the peak cannot rise.

Tested with that exact pair, in both orders, with the tie itself asserted first so the test cannot quietly stop being a tie if the blend constants ever change. Mutation-checked: restoring sat[peakAt] turns "a pinned zone tied at the peak still condemns it" red and nothing else.

node tools/smoke.mjs and node tools/ui-check.mjs both pass.

@widgetii
widgetii merged commit 2e98997 into main Sep 24, 2026
1 check passed
@widgetii
widgetii deleted the focus-clamp branch September 24, 2026 17:44
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.

1 participant