[object Object]

← back to Wallco Ai

fix(settlement): strip negative-prompt suffix before substring matching

117c9e500d5f0ffed8af2f0119799a18467e4718 · 2026-05-25 00:30:39 -0700 · Steve Abrams

Attorney review (vp-compliance-policy, 2026-05-25) confirmed the runtime
text gate was out of sync with the SHA-locked Part B sub-skill, which
explicitly prescribes ignoring 'NO X' / 'without X' / 'excluding X'
context: presence in a negative-prompt block does NOT count as positive
design content.

Impact: every drunk_animals_tick prompt ends with 'FLOWERS ONLY, NO
leaves, NO foliage, NO monstera, NO palm, NO banana, NO tropical, NO
jungle, no text or watermark'. The substring matcher was reading those
tokens as evidence of leaves+palm+banana in the design, tripping Part A1
and Part B simultaneously and BLOCKing the prompt. 529/1358 recent ticks
(~39%) were killed by this false positive.

Defendant-favorable reading supports the fix: the binding regulates what
the DESIGN contains, not what tokens appear in the prompt string. The
post-gen vision check (settlement-post-gen-vision) remains the actual
safety net for rendered content.

Verified: 4 test cases (3 false-block prompts + 1 true-block prompt) all
classify correctly. Legit 'directional banana leaves in tossed scatter,
open space, multi-color' still BLOCKs.

Files:
- ~/.claude/skills/settlement-part-b-prohibited-elements/SKILL.md L58-60
  (binding spec — was authoritative; runtime was not honoring it)
- ~/.claude/skills/settlement/binding/SETTLEMENT-BINDING-TEXT.md
  (unchanged)

Files touched

Diff

commit 117c9e500d5f0ffed8af2f0119799a18467e4718
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Mon May 25 00:30:39 2026 -0700

    fix(settlement): strip negative-prompt suffix before substring matching
    
    Attorney review (vp-compliance-policy, 2026-05-25) confirmed the runtime
    text gate was out of sync with the SHA-locked Part B sub-skill, which
    explicitly prescribes ignoring 'NO X' / 'without X' / 'excluding X'
    context: presence in a negative-prompt block does NOT count as positive
    design content.
    
    Impact: every drunk_animals_tick prompt ends with 'FLOWERS ONLY, NO
    leaves, NO foliage, NO monstera, NO palm, NO banana, NO tropical, NO
    jungle, no text or watermark'. The substring matcher was reading those
    tokens as evidence of leaves+palm+banana in the design, tripping Part A1
    and Part B simultaneously and BLOCKing the prompt. 529/1358 recent ticks
    (~39%) were killed by this false positive.
    
    Defendant-favorable reading supports the fix: the binding regulates what
    the DESIGN contains, not what tokens appear in the prompt string. The
    post-gen vision check (settlement-post-gen-vision) remains the actual
    safety net for rendered content.
    
    Verified: 4 test cases (3 false-block prompts + 1 true-block prompt) all
    classify correctly. Legit 'directional banana leaves in tossed scatter,
    open space, multi-color' still BLOCKs.
    
    Files:
    - ~/.claude/skills/settlement-part-b-prohibited-elements/SKILL.md L58-60
      (binding spec — was authoritative; runtime was not honoring it)
    - ~/.claude/skills/settlement/binding/SETTLEMENT-BINDING-TEXT.md
      (unchanged)
---
 scripts/settlement-gate.js | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/scripts/settlement-gate.js b/scripts/settlement-gate.js
index f541674..c0f09b2 100644
--- a/scripts/settlement-gate.js
+++ b/scripts/settlement-gate.js
@@ -44,8 +44,28 @@ const ACCEPTABLE = [
 
 const has = (text, list) => list.some(t => text.includes(t));
 
+// Strip negative-prompt context per settlement-part-b SKILL.md lines 58-60:
+// "presence in negative-prompt block does NOT count as positive."
+// Cuts everything after the first negative-block boundary, then drops any
+// inline "NO X" / "no X" pairs that survived. Without this the gate
+// falsely trips on its own anti-prompts (e.g. "NO banana, NO palm, NO
+// leaves") and over-blocks ~40% of legitimate prompts. Attorney review
+// 2026-05-25 (vp-compliance-policy) confirmed runtime was out of sync
+// with the SHA-locked Part B sub-skill — this aligns runtime → binding.
+function stripNegations(text) {
+  let t = String(text || '');
+  const cuts = [/,\s*NO\s+/i, /,\s*no\s+/i, /\bwithout\s+/i, /\bexcluding\s+/i, /\bbut not\s+/i];
+  for (const re of cuts) {
+    const m = t.search(re);
+    if (m !== -1) { t = t.slice(0, m); break; }
+  }
+  t = t.replace(/\b(?:NO|no)\s+[a-z-]+/g, ' ');
+  return t;
+}
+
 function checkPrompt(prompt) {
-  const text = String(prompt || '').toLowerCase();
+  const raw  = String(prompt || '').toLowerCase();
+  const text = stripNegations(raw).toLowerCase();
 
   // Part A score
   const a1 = has(text, PART_A_LEAVES) && has(text, PART_A_DIRECTIONAL);

← 3732ed9 feat(design page): replace generic 14-hue tone wheel with 19  ·  back to Wallco Ai  ·  bg-tester picker: switch to unified /api/bg-textures, hide v 3a16b54 →