Spaces:
Sleeping
Sleeping
jasondo OpenAI Codex commited on
Commit Β·
628bf77
1
Parent(s): a6f63e9
Document server-side confidence threshold
Browse filesCo-authored-by: OpenAI Codex <codex@openai.com>
- FEATURE.md +208 -181
- README.md +8 -6
FEATURE.md
CHANGED
|
@@ -1,200 +1,227 @@
|
|
| 1 |
-
# FEATURE: Confidence Threshold
|
| 2 |
|
| 3 |
-
Status: Implemented and synced to the private Space, June 14, 2026.
|
|
|
|
|
|
|
| 4 |
Author of spec: codebase review pass, June 14, 2026.
|
| 5 |
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
- **
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
`
|
| 37 |
-
`
|
| 38 |
-
|
| 39 |
-
`
|
| 40 |
-
`
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
`index.html:
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
|
|
|
| 51 |
|
| 52 |
## Product decisions (confirmed with user, June 14, 2026)
|
| 53 |
|
| 54 |
-
1. **
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
|
| 68 |
## Implementation plan (for Codex)
|
| 69 |
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
```
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
```
|
| 88 |
-
|
| 89 |
-
-
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
|
| 105 |
-
current threshold
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
|
| 109 |
-
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
`
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
###
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
`
|
| 127 |
-
|
| 128 |
-
-
|
| 129 |
-
|
| 130 |
-
|
| 131 |
-
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 136 |
|
| 137 |
## Out of scope / explicitly NOT doing
|
| 138 |
|
| 139 |
-
- No
|
| 140 |
-
|
| 141 |
-
- No
|
| 142 |
-
(
|
| 143 |
-
- No
|
| 144 |
-
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
- Added a toolbar confidence threshold slider in `index.html`, defaulting to
|
| 150 |
-
`0.5` / `50%`.
|
| 151 |
-
- The browser now recomputes render mode from the cached analysis confidence and
|
| 152 |
-
current slider value, overriding advisory server `render_mode`.
|
| 153 |
-
- Slider input re-renders from `window.lastScenePayload` only; it does not call
|
| 154 |
-
`/analyze_image` or `/generate_scene`.
|
| 155 |
-
- Added `DEFAULT_CONFIDENCE_THRESHOLD = 0.5` in `snap2sim/schema.py` for the
|
| 156 |
-
server's advisory fallback.
|
| 157 |
-
- Local verification passed: schema/parser check, FastAPI `TestClient` root /
|
| 158 |
-
`/analyze_image` / `/generate_scene`, browser slider downgrade/promote with
|
| 159 |
-
no network calls, annotated-photo fallback, keyboard slider operation, mobile
|
| 160 |
-
no horizontal overflow, and canvas pointer targeting after normal overlay
|
| 161 |
-
hiding.
|
| 162 |
-
- GitHub Actions sync run `27515143658` deployed commit `a0540e9` to the
|
| 163 |
-
private Hugging Face Space. The Space reported the same SHA and remained
|
| 164 |
-
private. Authenticated deployed verification confirmed the updated root shell
|
| 165 |
-
contains the slider, a synthetic target image returned `Target Reticle` at
|
| 166 |
-
`0.7` confidence with 3 parts, and `/generate_scene` returned
|
| 167 |
-
`renderer: three`, `render_mode: three`, and no HTML field.
|
| 168 |
|
| 169 |
## Verification checklist
|
| 170 |
|
| 171 |
-
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 185 |
- `INFERENCE_BACKEND=local` sample mode still renders the example analysis with
|
| 186 |
-
the slider present.
|
| 187 |
-
-
|
| 188 |
-
|
| 189 |
|
| 190 |
## Touch points (file/line reference)
|
| 191 |
|
| 192 |
-
- `
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
- `
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
- `
|
| 200 |
-
- `
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# FEATURE: Confidence Threshold β Apply Only at Analysis & Generation
|
| 2 |
|
| 3 |
+
Status: **Implemented and synced to the private Space, June 14, 2026.**
|
| 4 |
+
Supersedes the prior implemented version of this file (commit `a0540e9`,
|
| 5 |
+
"Add confidence threshold control").
|
| 6 |
Author of spec: codebase review pass, June 14, 2026.
|
| 7 |
|
| 8 |
+
> **Why this supersedes the prior spec.** The slider already exists, but it was
|
| 9 |
+
> built as a *client-authoritative, live re-render* control: moving it instantly
|
| 10 |
+
> recomputes the render mode from cached analysis in the browser, and the server
|
| 11 |
+
> never sees the chosen threshold. The user has reversed all three of those
|
| 12 |
+
> decisions. The threshold must now be **applied only when analysis and
|
| 13 |
+
> generation run**, enforced **server-side**, and the slider must be usable
|
| 14 |
+
> **before the first upload**.
|
| 15 |
+
|
| 16 |
+
## Findings β prior behavior before this re-spec
|
| 17 |
+
|
| 18 |
+
A confidence-threshold slider already existed and worked, but not the way the
|
| 19 |
+
user wanted in this re-spec.
|
| 20 |
+
|
| 21 |
+
1. **Slider UI exists.** `index.html:593-597` β `#confidenceThreshold`
|
| 22 |
+
(`type="range"`, `min=0 max=1 step=0.05 value=0.5`), with a live `#thresholdValue`
|
| 23 |
+
label. It carries the `disabled` attribute and is only enabled after a run.
|
| 24 |
+
|
| 25 |
+
2. **Slider applies live, client-side, from cache.** The `input` handler at
|
| 26 |
+
`index.html:722-725` calls `updateConfidenceThreshold()` then
|
| 27 |
+
`scheduleThresholdRender()` (`index.html:1279-1286`), which debounces 90 ms and
|
| 28 |
+
re-runs `renderScenePayload(window.lastScenePayload)` against the **cached**
|
| 29 |
+
analysis. No network call β but it re-renders on *every drag*, decoupled from
|
| 30 |
+
any analysis/generation step.
|
| 31 |
+
|
| 32 |
+
3. **Threshold is applied client-side only.** `chooseRenderMode()`
|
| 33 |
+
(`index.html:821-833`) compares `analysis.confidence` against the JS
|
| 34 |
+
`confidenceThreshold` var. It **ignores** the `render_mode` the server already
|
| 35 |
+
returned in the payload.
|
| 36 |
+
|
| 37 |
+
4. **The server never receives the threshold.** `/generate_scene`
|
| 38 |
+
(`app.py:101-108` β `_generate_scene` at `app.py:116-117` β
|
| 39 |
+
`InferenceClient.generate_scene` at `backend.py:47-51`) calls
|
| 40 |
+
`select_render_mode(valid_analysis)` (`schema.py:219-236`), which always uses
|
| 41 |
+
the hardcoded `DEFAULT_CONFIDENCE_THRESHOLD = 0.5` (`schema.py:216`). The
|
| 42 |
+
server's `render_mode` is computed with `0.5` regardless of the slider.
|
| 43 |
+
|
| 44 |
+
5. **Slider availability is gated on a completed run.** It is `disabled` in markup
|
| 45 |
+
(`index.html:595`), disabled in `resetScene()` (`index.html:769`), and
|
| 46 |
+
`setBusy()` (`index.html:1263`) keeps it disabled whenever
|
| 47 |
+
`!window.lastScenePayload`. So it cannot be set before the first analysis.
|
| 48 |
+
|
| 49 |
+
**Conclusion:** the threshold is currently a *live, browser-only* control that
|
| 50 |
+
never reaches the analysis/generation pipeline β the opposite of "only used upon
|
| 51 |
+
analysis and generation." This spec changes it to a value that is captured and
|
| 52 |
+
enforced **at generation time, server-side**, and that only takes effect on the
|
| 53 |
+
next run.
|
| 54 |
|
| 55 |
## Product decisions (confirmed with user, June 14, 2026)
|
| 56 |
|
| 57 |
+
1. **Apply timing: next run only.** Moving the slider does **nothing
|
| 58 |
+
immediately** β no live re-render of cached analysis. The new threshold is
|
| 59 |
+
captured and applied only the next time analysis + generation runs (next
|
| 60 |
+
upload / re-run). Remove the live client-side re-render entirely.
|
| 61 |
+
2. **Enforcement: server pipeline.** The slider value is sent to
|
| 62 |
+
`/generate_scene`, and the server's `select_render_mode()` uses the user's
|
| 63 |
+
threshold instead of the hardcoded `0.5`. The server's returned `render_mode`
|
| 64 |
+
becomes the source of truth; the client trusts it.
|
| 65 |
+
3. **Pre-run state: enabled up front.** The slider is usable before the first
|
| 66 |
+
upload so the chosen threshold is in effect for the very first
|
| 67 |
+
analysis/generation.
|
| 68 |
+
|
| 69 |
+
Unchanged from prior spec (still true):
|
| 70 |
+
- **Downgrade chain stays:** below threshold, skip the 3D Three.js render and
|
| 71 |
+
fall back to `annotate` (annotated source photo), then `unavailable`. The
|
| 72 |
+
slider only moves the cutoff; no new hard-block state.
|
| 73 |
+
- **No re-running model inference on slider move** (analysis is the expensive
|
| 74 |
+
Modal GPU call; it is never re-triggered by the slider).
|
| 75 |
|
| 76 |
## Implementation plan (for Codex)
|
| 77 |
|
| 78 |
+
Changes span the browser (`index.html`) and the server
|
| 79 |
+
(`app.py`, `snap2sim/backend.py`, `snap2sim/schema.py`).
|
| 80 |
+
|
| 81 |
+
### 1. Server: accept and enforce a threshold at generation
|
| 82 |
+
|
| 83 |
+
- `snap2sim/schema.py` β `select_render_mode(analysis, threshold=DEFAULT_CONFIDENCE_THRESHOLD)`:
|
| 84 |
+
- Add a `threshold` parameter, defaulting to `DEFAULT_CONFIDENCE_THRESHOLD`.
|
| 85 |
+
- Coerce/clamp: if `threshold` is not a number, fall back to the default; clamp
|
| 86 |
+
into `[0.0, 1.0]`.
|
| 87 |
+
- Replace the hardcoded `DEFAULT_CONFIDENCE_THRESHOLD` in the `low_confidence`
|
| 88 |
+
line (`schema.py:229`) with the (clamped) `threshold`.
|
| 89 |
+
- `snap2sim/backend.py` β `InferenceClient.generate_scene(analysis, threshold=None)`
|
| 90 |
+
(`backend.py:47`):
|
| 91 |
+
- Accept an optional `threshold`; when `None`/invalid use
|
| 92 |
+
`DEFAULT_CONFIDENCE_THRESHOLD`.
|
| 93 |
+
- Pass it through to `select_render_mode(valid_analysis, threshold)`.
|
| 94 |
+
- `app.py`:
|
| 95 |
+
- `/generate_scene` HTTP route (`app.py:106-108`): read
|
| 96 |
+
`payload.get("confidence_threshold")` and pass to `_generate_scene`.
|
| 97 |
+
- `@app.api(name="generate_scene")` (`app.py:101-103`): add an optional
|
| 98 |
+
`confidence_threshold` parameter (default keeps the existing `/run_pipeline`
|
| 99 |
+
Gradio API backward compatible).
|
| 100 |
+
- `_generate_scene(analysis, threshold)` (`app.py:116-117`): forward the
|
| 101 |
+
threshold to `InferenceClient(...).generate_scene(analysis, threshold)`.
|
| 102 |
+
- Validate at the boundary: coerce to `float`, clamp `[0, 1]`, default on
|
| 103 |
+
missing/invalid. Do not raise on a bad threshold β fall back to the default so
|
| 104 |
+
a malformed client value can't break generation.
|
| 105 |
+
|
| 106 |
+
Result: `/generate_scene` returns a `render_mode` computed with the user's
|
| 107 |
+
threshold. Existing callers that omit `confidence_threshold` still get the `0.5`
|
| 108 |
+
default β backward compatible.
|
| 109 |
+
|
| 110 |
+
### 2. Client: send the threshold at generation, stop live re-render
|
| 111 |
+
|
| 112 |
+
- **Capture and send at run time.** In `runPipeline()` (`index.html:727-759`),
|
| 113 |
+
include the current threshold in the generate call:
|
| 114 |
+
`postJson("/generate_scene", { analysis, confidence_threshold: confidenceThreshold })`
|
| 115 |
+
(`index.html:749`). The value is read at the moment of the call, so later slider
|
| 116 |
+
drags don't affect the in-flight run.
|
| 117 |
+
- **Trust the server's render mode.** Change `renderScenePayload()`
|
| 118 |
+
(`index.html:805-819`) / `chooseRenderMode()` (`index.html:821-833`) so the
|
| 119 |
+
decision uses `payload.render_mode` as the primary choice, with the existing
|
| 120 |
+
capability guards (`hasUsableGeometry`, `hasAnnotations`) only to *downgrade*
|
| 121 |
+
when data is missing β never to upgrade past what the server allowed. Remove the
|
| 122 |
+
client-side `confidence vs confidenceThreshold` comparison (the server now owns
|
| 123 |
+
that). `chooseRenderMode` should take the payload (or render_mode) rather than
|
| 124 |
+
recomputing from confidence.
|
| 125 |
+
- **Remove the live re-render.** Delete `scheduleThresholdRender()`
|
| 126 |
+
(`index.html:1279-1286`) and the `thresholdRenderTimer` state
|
| 127 |
+
(`index.html:675`). The slider `input` handler (`index.html:722-725`) should
|
| 128 |
+
now only call `updateConfidenceThreshold()` β update the `confidenceThreshold`
|
| 129 |
+
var and the `#thresholdValue` label. No render, no network call.
|
| 130 |
+
|
| 131 |
+
### 3. Client: enable the slider up front
|
| 132 |
+
|
| 133 |
+
- Remove the `disabled` attribute from the markup (`index.html:595`).
|
| 134 |
+
- In `resetScene()` (`index.html:761-776`), stop disabling the slider
|
| 135 |
+
(`index.html:769`) β it should remain available between runs.
|
| 136 |
+
- In `setBusy()` (`index.html:1259-1264`), disable the slider **only while a
|
| 137 |
+
request is in flight** (`active`), not based on `window.lastScenePayload`
|
| 138 |
+
(`index.html:1263`). This lets the user set the threshold before the first
|
| 139 |
+
upload and adjust it between runs, while preventing edits mid-request.
|
| 140 |
+
- Keep the default at `0.5` / `50%` so first-run behavior is unchanged when the
|
| 141 |
+
user never touches the slider.
|
| 142 |
+
|
| 143 |
+
### 4. Optional: reflect "applies on next run" in the UI
|
| 144 |
+
|
| 145 |
+
Because the slider no longer re-renders live, consider a subtle affordance so the
|
| 146 |
+
change isn't silent β e.g. update the label to hint the value applies to the next
|
| 147 |
+
analysis (tooltip or helper text). Low priority; keep it lightweight and
|
| 148 |
+
accessible (don't regress the existing `aria-live` label).
|
| 149 |
|
| 150 |
## Out of scope / explicitly NOT doing
|
| 151 |
|
| 152 |
+
- **No live re-render from cached analysis** (decision #1 β this is the behavior
|
| 153 |
+
being removed).
|
| 154 |
+
- **No re-running model inference (`/analyze_image`) when the slider moves**
|
| 155 |
+
(analysis is the expensive Modal GPU call).
|
| 156 |
+
- **No hard-block "confidence too low" state** β the `three -> annotate ->
|
| 157 |
+
unavailable` downgrade chain stays.
|
| 158 |
+
- **No model-authored HTML/JS/markup injection.** Rendering stays deterministic
|
| 159 |
+
Three.js from validated JSON (`SECURITY.md` Agent Guidance). The threshold is a
|
| 160 |
+
non-credential UX/quality control; sending it to a same-origin endpoint is fine.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 161 |
|
| 162 |
## Verification checklist
|
| 163 |
|
| 164 |
+
- **Server, default:** `/generate_scene` without `confidence_threshold` returns
|
| 165 |
+
the same `render_mode` as today (regression β `0.5` default). Add/extend a unit
|
| 166 |
+
check: `select_render_mode(analysis, 0.9)` downgrades a `0.7`-confidence
|
| 167 |
+
geometry payload to `annotate`/`unavailable`; `select_render_mode(analysis, 0.1)`
|
| 168 |
+
keeps it `three`.
|
| 169 |
+
- **Server, clamp/coerce:** out-of-range (`-1`, `5`) and non-numeric thresholds
|
| 170 |
+
fall back/clamp without raising; `/generate_scene` still returns a valid payload.
|
| 171 |
+
- **Client, next-run-only:** moving the slider after a run does **not** trigger
|
| 172 |
+
any network request and does **not** change the current render (confirm via
|
| 173 |
+
devtools Network + visual). The new value only takes effect after the next
|
| 174 |
+
upload / re-run.
|
| 175 |
+
- **Client, enforced server-side:** raising the threshold above the analysis's
|
| 176 |
+
confidence and re-running downgrades the 3D cutaway to annotated photo / then
|
| 177 |
+
unavailable; lowering it and re-running promotes back to 3D when geometry exists.
|
| 178 |
+
- **Client, pre-run:** the slider is interactive before the first upload, disabled
|
| 179 |
+
only while a request is in flight, and re-enabled afterward.
|
| 180 |
+
- **Accessibility/layout (regression):** slider keyboard-operable, `#thresholdValue`
|
| 181 |
+
announced, does not block canvas OrbitControls (the pointer-events bug fixed in
|
| 182 |
+
the REVIEW2.md pass), and no mobile horizontal overflow.
|
| 183 |
- `INFERENCE_BACKEND=local` sample mode still renders the example analysis with
|
| 184 |
+
the slider present and the threshold honored at generation.
|
| 185 |
+
- Existing local checks pass: schema/parser checks and FastAPI `TestClient` for
|
| 186 |
+
`/`, `/analyze_image`, `/generate_scene`.
|
| 187 |
|
| 188 |
## Touch points (file/line reference)
|
| 189 |
|
| 190 |
+
- `snap2sim/schema.py:219-236` `select_render_mode()` β add `threshold` param,
|
| 191 |
+
clamp, use it instead of the hardcoded default at `schema.py:229`.
|
| 192 |
+
- `snap2sim/backend.py:47-51` `generate_scene()` β accept + forward `threshold`.
|
| 193 |
+
- `app.py:101-108` `generate_scene_api` / `generate_scene_http` β accept
|
| 194 |
+
`confidence_threshold`; `app.py:116-117` `_generate_scene` β forward it; clamp
|
| 195 |
+
at the boundary.
|
| 196 |
+
- `index.html:595` slider markup β remove `disabled`.
|
| 197 |
+
- `index.html:722-725` slider `input` handler β drop the live re-render call.
|
| 198 |
+
- `index.html:749` `/generate_scene` call β send `confidence_threshold`.
|
| 199 |
+
- `index.html:761-776` `resetScene()` / `index.html:1259-1264` `setBusy()` β
|
| 200 |
+
enable slider up front, disable only while busy.
|
| 201 |
+
- `index.html:805-833` `renderScenePayload()` / `chooseRenderMode()` β trust
|
| 202 |
+
server `render_mode`; drop client-side threshold comparison.
|
| 203 |
+
- `index.html:675` `thresholdRenderTimer` + `index.html:1279-1286`
|
| 204 |
+
`scheduleThresholdRender()` β remove.
|
| 205 |
+
|
| 206 |
+
## Implementation result
|
| 207 |
+
|
| 208 |
+
- Implemented in commit `a6f63e9` (`Enforce confidence threshold during generation`).
|
| 209 |
+
- The slider is enabled before the first upload and disabled only while a request
|
| 210 |
+
is in flight.
|
| 211 |
+
- The browser sends `confidence_threshold` only with `/generate_scene`; slider
|
| 212 |
+
movement does not call `/analyze_image`, call `/generate_scene`, or re-render
|
| 213 |
+
cached analysis.
|
| 214 |
+
- `/generate_scene` clamps/coerces the threshold server-side and returns the
|
| 215 |
+
authoritative `render_mode`; the browser only downgrades when geometry or
|
| 216 |
+
annotation data is missing.
|
| 217 |
+
- Local verification passed for default/high/low/malformed/clamped thresholds,
|
| 218 |
+
FastAPI `TestClient`, next-run-only browser behavior, high-threshold
|
| 219 |
+
downgrade, low-threshold promotion, keyboard slider operation, mobile
|
| 220 |
+
no-overflow layout, and canvas pointer targeting.
|
| 221 |
+
- GitHub Actions sync run `27515950105` deployed commit `a6f63e9` to the private
|
| 222 |
+
Hugging Face Space. The Space reported SHA
|
| 223 |
+
`a6f63e9a0b76315bb223a09a71f4c027a29877fb` and remained private.
|
| 224 |
+
- Authenticated private-Space verification passed: the root served the updated
|
| 225 |
+
shell, a synthetic image returned `optical sight` at `0.7` confidence with 3
|
| 226 |
+
parts, high threshold returned `photo` / `annotate`, low threshold returned
|
| 227 |
+
`three` / `three`, and no HTML field was present.
|
README.md
CHANGED
|
@@ -123,23 +123,25 @@ Runtime flow:
|
|
| 123 |
|
| 124 |
1. Browser encodes the uploaded photo and posts it to `/analyze_image`.
|
| 125 |
2. Backend returns the validated mechanism JSON.
|
| 126 |
-
3. Browser posts the analysis
|
| 127 |
-
descriptor.
|
| 128 |
4. Browser renders deterministic Three.js primitives when geometry is usable,
|
| 129 |
or overlays text-only callouts on the uploaded photo when the model only has
|
| 130 |
image-space annotations.
|
| 131 |
5. A browser-side confidence slider controls the minimum analysis confidence
|
| 132 |
-
needed for the 3D cutaway. Moving it
|
| 133 |
-
|
| 134 |
6. `/generate_scene` returns a validated
|
| 135 |
`{ "renderer": "...", "render_mode": "...", "analysis": ... }` descriptor
|
| 136 |
-
instead of model-authored HTML.
|
|
|
|
|
|
|
| 137 |
|
| 138 |
The shell uses Chakra Petch and Fira Code from Bunny Fonts, an asymmetric
|
| 139 |
63/37 viewport/readout split, a blueprint grid, amber/cyan instrument-panel
|
| 140 |
colors, explicit Modal cold-start messaging, source-photo preview, and a
|
| 141 |
play/pause control. The confidence slider defaults to 50%, matching the
|
| 142 |
-
server's
|
| 143 |
visible render mode.
|
| 144 |
|
| 145 |
The browser no longer injects model-authored HTML into the DOM. The model's
|
|
|
|
| 123 |
|
| 124 |
1. Browser encodes the uploaded photo and posts it to `/analyze_image`.
|
| 125 |
2. Backend returns the validated mechanism JSON.
|
| 126 |
+
3. Browser posts the analysis plus the current confidence threshold to
|
| 127 |
+
`/generate_scene` for a validated scene descriptor.
|
| 128 |
4. Browser renders deterministic Three.js primitives when geometry is usable,
|
| 129 |
or overlays text-only callouts on the uploaded photo when the model only has
|
| 130 |
image-space annotations.
|
| 131 |
5. A browser-side confidence slider controls the minimum analysis confidence
|
| 132 |
+
needed for the 3D cutaway. Moving it only updates the next-run value; it does
|
| 133 |
+
not re-render cached analysis or call the model.
|
| 134 |
6. `/generate_scene` returns a validated
|
| 135 |
`{ "renderer": "...", "render_mode": "...", "analysis": ... }` descriptor
|
| 136 |
+
instead of model-authored HTML. The returned `render_mode` is the source of
|
| 137 |
+
truth for the visible renderer, with the browser only downgrading when
|
| 138 |
+
required data is missing.
|
| 139 |
|
| 140 |
The shell uses Chakra Petch and Fira Code from Bunny Fonts, an asymmetric
|
| 141 |
63/37 viewport/readout split, a blueprint grid, amber/cyan instrument-panel
|
| 142 |
colors, explicit Modal cold-start messaging, source-photo preview, and a
|
| 143 |
play/pause control. The confidence slider defaults to 50%, matching the
|
| 144 |
+
server's fallback threshold, and the generation route is authoritative for the
|
| 145 |
visible render mode.
|
| 146 |
|
| 147 |
The browser no longer injects model-authored HTML into the DOM. The model's
|