← back to Wallco Ai
snapshot: backup runtime state (3 files)
1e5fc814d56b1d129d23e14a70d277e3a5fd8689 · 2026-05-13 12:16:01 -0700 · SteveStudio2
Files touched
M data/designs.jsonM scripts/regen-bamboo-trellis-to-cane.jsA scripts/settlement-gate.js
Diff
commit 1e5fc814d56b1d129d23e14a70d277e3a5fd8689
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date: Wed May 13 12:16:01 2026 -0700
snapshot: backup runtime state (3 files)
---
data/designs.json | 341 ++++++++++++++++++++++++++++++++
scripts/regen-bamboo-trellis-to-cane.js | 1 +
scripts/settlement-gate.js | 146 ++++++++++++++
3 files changed, 488 insertions(+)
diff --git a/data/designs.json b/data/designs.json
index b70a230..5f0a813 100644
--- a/data/designs.json
+++ b/data/designs.json
@@ -71862,5 +71862,346 @@
"user_scale_good": null,
"user_stars": null,
"room_mockups": []
+ },
+ {
+ "id": 3497,
+ "kind": "seamless_tile",
+ "category": "colorways-imperial-garden-barone",
+ "dominant_hex": "#2b3c2d",
+ "saturation": 0.165,
+ "title": "Sage Origin No.3497",
+ "handle": "wallco-3497",
+ "image_url": "/designs/img/dig1984_1778699657258_998252679.png",
+ "filename": "dig1984_1778699657258_998252679.png",
+ "generator": "wallco.ai",
+ "seed": 998252679,
+ "is_published": true,
+ "created_at": "2026-05-13T19:14:17.373303+00:00",
+ "motifs": [
+ "floral",
+ "garden",
+ "chinoiserie",
+ "traditional"
+ ],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3498,
+ "kind": "seamless_tile",
+ "category": "colorways-imperial-garden-barone",
+ "dominant_hex": "#aab083",
+ "saturation": 0.222,
+ "title": "Olive Folio No.3498",
+ "handle": "wallco-3498",
+ "image_url": "/designs/img/dig1984_1778699664718_784717064.png",
+ "filename": "dig1984_1778699664718_784717064.png",
+ "generator": "wallco.ai",
+ "seed": 784717064,
+ "is_published": true,
+ "created_at": "2026-05-13T19:14:24.851997+00:00",
+ "motifs": [
+ "floral",
+ "garden",
+ "chinoiserie",
+ "traditional"
+ ],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3499,
+ "kind": "seamless_tile",
+ "category": "colorways-imperial-garden-barone",
+ "dominant_hex": "#999354",
+ "saturation": 0.291,
+ "title": "Honey Reverie No.3499",
+ "handle": "wallco-3499",
+ "image_url": "/designs/img/dig1984_1778699674623_1900836927.png",
+ "filename": "dig1984_1778699674623_1900836927.png",
+ "generator": "wallco.ai",
+ "seed": 1900836927,
+ "is_published": true,
+ "created_at": "2026-05-13T19:14:34.749891+00:00",
+ "motifs": [
+ "floral",
+ "garden",
+ "chinoiserie",
+ "traditional"
+ ],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3500,
+ "kind": "seamless_tile",
+ "category": "colorways-imperial-garden-barone",
+ "dominant_hex": "#294b2f",
+ "saturation": 0.293,
+ "title": "Sage Atelier No.3500",
+ "handle": "wallco-3500",
+ "image_url": "/designs/img/dig1984_1778699682239_1550949847.png",
+ "filename": "dig1984_1778699682239_1550949847.png",
+ "generator": "wallco.ai",
+ "seed": 1550949847,
+ "is_published": true,
+ "created_at": "2026-05-13T19:14:42.359749+00:00",
+ "motifs": [
+ "floral",
+ "garden",
+ "chinoiserie",
+ "traditional"
+ ],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3501,
+ "kind": "seamless_tile",
+ "category": "colorways-imperial-garden-barone",
+ "dominant_hex": "#ddedde",
+ "saturation": 0.308,
+ "title": "Sage Studio No.3501",
+ "handle": "wallco-3501",
+ "image_url": "/designs/img/dig1984_1778699690522_130051995.png",
+ "filename": "dig1984_1778699690522_130051995.png",
+ "generator": "wallco.ai",
+ "seed": 130051995,
+ "is_published": true,
+ "created_at": "2026-05-13T19:14:51.524677+00:00",
+ "motifs": [
+ "floral",
+ "garden",
+ "chinoiserie",
+ "traditional"
+ ],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3502,
+ "kind": "seamless_tile",
+ "category": "colorways-imperial-garden-barone",
+ "dominant_hex": "#8f9d8e",
+ "saturation": 0.071,
+ "title": "Ash Origin No.3502",
+ "handle": "wallco-3502",
+ "image_url": "/designs/img/dig1984_1778699699762_2138836705.png",
+ "filename": "dig1984_1778699699762_2138836705.png",
+ "generator": "wallco.ai",
+ "seed": 2138836705,
+ "is_published": true,
+ "created_at": "2026-05-13T19:14:59.897359+00:00",
+ "motifs": [
+ "floral",
+ "garden",
+ "chinoiserie",
+ "traditional"
+ ],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3503,
+ "kind": "seamless_tile",
+ "category": "colorways-imperial-garden-barone",
+ "dominant_hex": "#c3d5e6",
+ "saturation": 0.412,
+ "title": "Sapphire Folio No.3503",
+ "handle": "wallco-3503",
+ "image_url": "/designs/img/dig1984_1778699707050_1568366990.png",
+ "filename": "dig1984_1778699707050_1568366990.png",
+ "generator": "wallco.ai",
+ "seed": 1568366990,
+ "is_published": true,
+ "created_at": "2026-05-13T19:15:07.174861+00:00",
+ "motifs": [
+ "floral",
+ "garden",
+ "chinoiserie",
+ "traditional"
+ ],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3504,
+ "kind": "seamless_tile",
+ "category": "colorways-imperial-garden-barone",
+ "dominant_hex": "#ddf0fc",
+ "saturation": 0.838,
+ "title": "Sapphire Reverie No.3504",
+ "handle": "wallco-3504",
+ "image_url": "/designs/img/dig1984_1778699715240_2116154951.png",
+ "filename": "dig1984_1778699715240_2116154951.png",
+ "generator": "wallco.ai",
+ "seed": 2116154951,
+ "is_published": true,
+ "created_at": "2026-05-13T19:15:15.367337+00:00",
+ "motifs": [
+ "floral",
+ "garden",
+ "chinoiserie",
+ "traditional"
+ ],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3505,
+ "kind": "seamless_tile",
+ "category": "colorways-imperial-garden-barone",
+ "dominant_hex": "#dcdaee",
+ "saturation": 0.37,
+ "title": "Sapphire Atelier No.3505",
+ "handle": "wallco-3505",
+ "image_url": "/designs/img/dig1984_1778699723292_657474069.png",
+ "filename": "dig1984_1778699723292_657474069.png",
+ "generator": "wallco.ai",
+ "seed": 657474069,
+ "is_published": true,
+ "created_at": "2026-05-13T19:15:23.424239+00:00",
+ "motifs": [
+ "floral",
+ "garden",
+ "chinoiserie",
+ "traditional"
+ ],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3506,
+ "kind": "seamless_tile",
+ "category": "colorways-imperial-garden-barone",
+ "dominant_hex": "#c7e7f7",
+ "saturation": 0.75,
+ "title": "Sapphire Studio No.3506",
+ "handle": "wallco-3506",
+ "image_url": "/designs/img/dig1984_1778699730782_1421708586.png",
+ "filename": "dig1984_1778699730782_1421708586.png",
+ "generator": "wallco.ai",
+ "seed": 1421708586,
+ "is_published": true,
+ "created_at": "2026-05-13T19:15:30.916211+00:00",
+ "motifs": [
+ "floral",
+ "garden",
+ "chinoiserie",
+ "traditional"
+ ],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3507,
+ "kind": "seamless_tile",
+ "category": "colorways-imperial-garden-barone",
+ "dominant_hex": "#617386",
+ "saturation": 0.16,
+ "title": "Sapphire Origin No.3507",
+ "handle": "wallco-3507",
+ "image_url": "/designs/img/dig1984_1778699739126_597530073.png",
+ "filename": "dig1984_1778699739126_597530073.png",
+ "generator": "wallco.ai",
+ "seed": 597530073,
+ "is_published": true,
+ "created_at": "2026-05-13T19:15:39.257374+00:00",
+ "motifs": [
+ "floral",
+ "garden",
+ "chinoiserie",
+ "traditional"
+ ],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3508,
+ "kind": "seamless_tile",
+ "category": "drunk-animals",
+ "dominant_hex": "#a54e7d",
+ "saturation": 0.358,
+ "title": "Plum Saunter No.3508",
+ "handle": "wallco-3508",
+ "image_url": "/designs/img/1778699731291_1338592738.png",
+ "filename": "1778699731291_1338592738.png",
+ "generator": "wallco.ai",
+ "seed": 1338592738,
+ "is_published": false,
+ "created_at": "2026-05-13T19:15:40.027593+00:00",
+ "motifs": [],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
+ },
+ {
+ "id": 3509,
+ "kind": "seamless_tile",
+ "category": "stoned-animals",
+ "dominant_hex": "#6d6b55",
+ "saturation": 0.124,
+ "title": "Olive Halcyon No.3509",
+ "handle": "wallco-3509",
+ "image_url": "/designs/img/1778699731480_243463689.png",
+ "filename": "1778699731480_243463689.png",
+ "generator": "wallco.ai",
+ "seed": 243463689,
+ "is_published": false,
+ "created_at": "2026-05-13T19:15:42.91227+00:00",
+ "motifs": [],
+ "user_removed": false,
+ "user_color_good": null,
+ "user_style_good": null,
+ "user_scale_good": null,
+ "user_stars": null,
+ "room_mockups": []
}
]
\ No newline at end of file
diff --git a/scripts/regen-bamboo-trellis-to-cane.js b/scripts/regen-bamboo-trellis-to-cane.js
index bfc33a1..9393185 100644
--- a/scripts/regen-bamboo-trellis-to-cane.js
+++ b/scripts/regen-bamboo-trellis-to-cane.js
@@ -14,6 +14,7 @@ const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const { execSync, spawnSync } = require('child_process');
+const { gateOrExit } = require('./settlement-gate');
const KEY = process.env.GEMINI_API_KEY;
if (!KEY) { console.error('GEMINI_API_KEY missing'); process.exit(1); }
diff --git a/scripts/settlement-gate.js b/scripts/settlement-gate.js
new file mode 100644
index 0000000..f541674
--- /dev/null
+++ b/scripts/settlement-gate.js
@@ -0,0 +1,146 @@
+/**
+ * Settlement pre-generation gate — call BEFORE running any Gemini batch.
+ * Mirrors the rules in ~/.claude/skills/settlement/SKILL.md. Returns
+ * { verdict, partA, partB, acceptable, reason, rewrite } where verdict is
+ * one of 'BLOCK' | 'NEEDS_REVIEW' | 'OK'.
+ *
+ * Hard rule from skill: Claude does not generate or publish a wallpaper
+ * pattern until this gate returns OK. Generators that import this should
+ * exit (or skip the variant) on BLOCK, and require explicit env-flag
+ * override on NEEDS_REVIEW.
+ *
+ * No external API calls. Pure text-pattern check against the proposed
+ * prompt — fast, free, deterministic. Post-generation image-vision check
+ * lives in lib/settlement-checker.ts on the DW side.
+ */
+'use strict';
+
+const PART_A_LEAVES = [
+ 'palm', 'frond', 'banana leaf', 'monstera', 'leaves', 'leaf', 'foliage', 'jungle',
+];
+const PART_A_DIRECTIONAL = [
+ 'directional', 'varied angle', 'tossed', 'scatter', 'rotated', 'multi-angle',
+ 'overlapping', 'turning leaves', 'fanning',
+];
+const PART_A_OPEN_SPACE = [
+ 'open space', 'breathing room', 'breathing space', 'scatter', 'tossed', 'sparse',
+];
+const PART_A_MULTICOLOR_NEG = [
+ 'monochrome', 'single ink', 'one color', 'one-color', 'black ink', 'single-color',
+ 'silhouette', 'tonal',
+];
+
+const PART_B = [
+ 'banana', 'banana pod', 'grape', 'bird', 'birds', 'parrot', 'toucan',
+ 'butterfly', 'butterflies', 'moth',
+];
+
+const ACCEPTABLE = [
+ 'tree trunk', 'tree trunks', 'branch', 'branches', 'twig', 'bark',
+ 'monkey', 'sloth', 'lemur', 'orangutan', 'gibbon', 'tarsier',
+ 'fruit', 'cherry', 'apple', 'pear', 'pomegranate', 'fig', 'orange',
+ // NOTE: bananas/grapes excluded — those are Part B
+];
+
+const has = (text, list) => list.some(t => text.includes(t));
+
+function checkPrompt(prompt) {
+ const text = String(prompt || '').toLowerCase();
+
+ // Part A score
+ const a1 = has(text, PART_A_LEAVES) && has(text, PART_A_DIRECTIONAL);
+ const a2 = has(text, PART_A_OPEN_SPACE);
+ const a3Singlecolor = has(text, PART_A_MULTICOLOR_NEG);
+ // Multi-color is the default assumption unless the prompt explicitly says
+ // single-ink / monochrome / silhouette. "Palette: X + Y + Z" is multi-color.
+ const a3 = !a3Singlecolor && (text.includes('palette:') || text.match(/\b(red|blue|green|yellow|orange|pink|magenta|cyan|emerald|crimson|cobalt|amber)\b/) && !text.match(/\bblack and white\b/));
+
+ const partA = a1 && a2 && a3;
+
+ // Part B score
+ const partBFound = PART_B.filter(el => text.includes(el));
+ const partB = partBFound.length > 0;
+
+ // Acceptable cues
+ const acceptableFound = ACCEPTABLE.filter(el => text.includes(el));
+ const acceptable = acceptableFound.length > 0;
+
+ // Verdict
+ let verdict = 'OK';
+ let reason = '';
+ let rewrite = '';
+
+ if (partA && partB) {
+ verdict = 'BLOCK';
+ reason = `Settlement violation: Part A (directional ${PART_A_LEAVES.find(l => text.includes(l)) || 'leaves'} + open space + multi-color) AND Part B (${partBFound.join(', ')}) both present.`;
+ rewrite = `Drop one of:
+ - the directional-leaf scatter (render on cane lattice / trellis / geometric substrate instead), OR
+ - the open-space / tossed composition (use edge-to-edge coverage), OR
+ - the multi-color palette (go single-ink / silhouette / monochrome).
+Any one removal lands the prompt at OK while keeping the Part B element.`;
+ } else if (partA && !partB && !acceptable) {
+ verdict = 'NEEDS_REVIEW';
+ reason = `Part A satisfied (directional leaves + open space + multi-color) but no Acceptable element (tree trunk / branch / non-prohibited fruit or animal). Borderline — adding an Acceptable cue lands it at OK.`;
+ rewrite = `Add a tree-trunk or branch reference, or a non-prohibited animal (monkey/sloth/lemur) to make the design tropical-acceptable per the settlement.`;
+ }
+
+ return {
+ verdict,
+ partA: { satisfied: partA, a1, a2, a3 },
+ partB: { satisfied: partB, found: partBFound },
+ acceptable: { satisfied: acceptable, found: acceptableFound },
+ reason,
+ rewrite,
+ };
+}
+
+// Pretty-print the verdict in the format the skill prescribes.
+function format(prompt, result) {
+ const r = result;
+ let out = '';
+ out += `SETTLEMENT GATE — VERDICT\n`;
+ out += `=========================\n`;
+ out += `Prompt: ${String(prompt).slice(0, 100)}${prompt.length > 100 ? '…' : ''}\n`;
+ out += `Part A score: A1=${r.partA.a1} A2=${r.partA.a2} A3=${r.partA.a3} → ${r.partA.satisfied ? 'satisfied' : 'not satisfied'}\n`;
+ out += `Part B score: ${r.partB.found.length ? r.partB.found.join(', ') : 'none'}\n`;
+ out += `Acceptable: ${r.acceptable.found.length ? r.acceptable.found.join(', ') : 'none'}\n\n`;
+ out += `VERDICT: ${r.verdict}\n`;
+ if (r.reason) out += `\nREASON: ${r.reason}\n`;
+ if (r.rewrite) out += `\nREWRITE SUGGESTION:\n${r.rewrite}\n`;
+ return out;
+}
+
+// gateOrExit: convenience for batch generators — calls process.exit(2) on
+// BLOCK, prints a warning on NEEDS_REVIEW (but allows continue if env
+// SETTLEMENT_ALLOW_REVIEW=1), returns silently on OK.
+function gateOrExit(prompt, opts = {}) {
+ const r = checkPrompt(prompt);
+ if (r.verdict === 'BLOCK') {
+ console.error(format(prompt, r));
+ console.error('\nBlocked by settlement gate. Rewrite the prompt or set SETTLEMENT_OVERRIDE=1 (logs to design.notes).');
+ if (!process.env.SETTLEMENT_OVERRIDE) process.exit(2);
+ console.error('SETTLEMENT_OVERRIDE=1 — proceeding under explicit operator override.');
+ return { ...r, overridden: true };
+ }
+ if (r.verdict === 'NEEDS_REVIEW') {
+ console.error(format(prompt, r));
+ if (!process.env.SETTLEMENT_ALLOW_REVIEW) {
+ console.error('Needs review. Add SETTLEMENT_ALLOW_REVIEW=1 to proceed; new rows will be is_published=FALSE.');
+ process.exit(3);
+ }
+ }
+ return r;
+}
+
+module.exports = { checkPrompt, format, gateOrExit };
+
+if (require.main === module) {
+ const prompt = process.argv.slice(2).join(' ');
+ if (!prompt) {
+ console.error('Usage: node settlement-gate.js "<prompt text to check>"');
+ process.exit(1);
+ }
+ const r = checkPrompt(prompt);
+ console.log(format(prompt, r));
+ process.exit(r.verdict === 'BLOCK' ? 2 : r.verdict === 'NEEDS_REVIEW' ? 3 : 0);
+}
← 5c53e57 snapshot: backup uncommitted work (6 files)
·
back to Wallco Ai
·
settlement: pre-generation legal gate + wallco-ai/scripts/se bbf4173 →