← back to Wallco Ai
harden settlement vision fallback (debugger pass): reject non-boolean 'violates' from Gemini→fall through; clamp partial-JSON ollama results to NEEDS REVIEW (close silent false-OK on garbled output)
a3e804860191e6fe845185a31f79241c224fb86a · 2026-06-09 16:03:01 -0700 · Steve
Files touched
M scripts/settlement_postgen_vision_check.js
Diff
commit a3e804860191e6fe845185a31f79241c224fb86a
Author: Steve <steve@designerwallcoverings.com>
Date: Tue Jun 9 16:03:01 2026 -0700
harden settlement vision fallback (debugger pass): reject non-boolean 'violates' from Gemini→fall through; clamp partial-JSON ollama results to NEEDS REVIEW (close silent false-OK on garbled output)
---
scripts/settlement_postgen_vision_check.js | 34 ++++++++++++++++++++++++------
1 file changed, 28 insertions(+), 6 deletions(-)
diff --git a/scripts/settlement_postgen_vision_check.js b/scripts/settlement_postgen_vision_check.js
index 84f9d9f..b026ea7 100644
--- a/scripts/settlement_postgen_vision_check.js
+++ b/scripts/settlement_postgen_vision_check.js
@@ -143,7 +143,15 @@ async function ollamaVision(b64, prompt) {
logGemini(j, { app: 'wallco-ai', note: 'settlement-postgen-vision', model: GEMINI_MODEL });
} catch {}
const text = j.candidates?.[0]?.content?.parts?.find(p => p.text)?.text;
- result = parseJsonLoose(text);
+ const parsed = parseJsonLoose(text);
+ // Integrity check: if `violates` is not a boolean the response is structurally
+ // incomplete (garbled/truncated model output). Treat as a failed Gemini parse
+ // and fall through to the local ollama fallback rather than silently returning OK.
+ if (parsed && typeof parsed.violates === 'boolean') {
+ result = parsed;
+ } else if (parsed) {
+ console.error(`Gemini returned parseable JSON but missing boolean 'violates' field — falling back to local ollama vision`);
+ }
} else {
console.error(`Gemini HTTP ${r.status}: ${(await r.text()).slice(0, 200)} — falling back to local ollama vision`);
}
@@ -164,15 +172,29 @@ async function ollamaVision(b64, prompt) {
const elapsed = ((Date.now() - t0) / 1000).toFixed(1);
if (!result) { console.error('both Gemini and local ollama vision unavailable — fail-closed'); process.exit(1); }
- // CLAMP: a LOCAL-model "violation" is advisory, not authoritative. Local
+ // CLAMP: a LOCAL-model verdict is advisory, not authoritative. Local
// vision (gemma3/llava) is good enough to CLEAR a clean design (OK) but can
// err on positives — so never let it drive a destructive BLOCK/unpublish.
// Downgrade a local-fallback violation to NEEDS REVIEW (sweep leaves those
// published + flagged); only Gemini can produce a sweep-triggering BLOCK.
- if (source.startsWith('ollama') && result && result.violates) {
- result.violates = false;
- result.needsReview = true;
- result.reasoning = '[local-vision fallback flagged a possible violation — downgraded to NEEDS REVIEW pending authoritative Gemini re-check] ' + (result.reasoning || '');
+ //
+ // Also handles the partial-JSON case: if ollama returned a parsed object but
+ // `violates` is not a boolean (missing/null/undefined from a truncated response),
+ // the verdict is indeterminate — treat as NEEDS REVIEW rather than silently OK.
+ // A missing `violates` field means the model didn't reach a conclusion; it is
+ // NOT equivalent to "clean".
+ if (source.startsWith('ollama') && result) {
+ if (result.violates === true) {
+ result.violates = false;
+ result.needsReview = true;
+ result.reasoning = '[local-vision fallback flagged a possible violation — downgraded to NEEDS REVIEW pending authoritative Gemini re-check] ' + (result.reasoning || '');
+ } else if (typeof result.violates !== 'boolean') {
+ // Partial/truncated JSON from local model — missing the decisive field.
+ // Cannot treat as clean; flag for authoritative Gemini re-check.
+ result.violates = false;
+ result.needsReview = true;
+ result.reasoning = '[local-vision fallback returned incomplete JSON (no boolean violates field) — flagged NEEDS REVIEW pending authoritative Gemini re-check] ' + (result.reasoning || '');
+ }
}
console.log('\n=== SETTLEMENT POST-GEN VISION CHECK ===');
← a717efc feat(design-curator): 🛋 Room setting button — generate room
·
back to Wallco Ai
·
deploy: ship settlement vision-check + tick-guard to prod (h d2decec →