@tritard/waterbrother 0.8.21 → 0.8.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tritard/waterbrother",
3
- "version": "0.8.21",
3
+ "version": "0.8.23",
4
4
  "description": "Waterbrother: Grok-powered coding CLI with local tools, sessions, operator modes, and approval controls",
5
5
  "type": "module",
6
6
  "bin": {
package/src/agent.js CHANGED
@@ -59,12 +59,12 @@ When you use tools:
59
59
  - define the typography, color system, spacing rhythm, and motion restraint through the code you write
60
60
  - avoid fake press badges, fake testimonials, fake founder lore, and placeholder image services unless explicitly requested
61
61
  - avoid generic Tailwind CDN template output and default premium-blog serif/sans pairings
62
- - avoid invented publication brands, named authors, issue numbers, staff credits, or editorial worldbuilding unless the user explicitly asked for fictional framing
63
62
  - avoid browser-default Georgia/Times plus system-sans typography as a final design answer
64
63
  - avoid fake keyboard shortcuts, fake command palettes, and demo-only interaction chrome
65
- - avoid generic reflective-editorial copy about slowness, attention, or the examined life unless the user explicitly asked for that voice
66
- - prefer fewer sections and at least one asymmetrical or compositionally distinctive move over a fully balanced template layout
67
64
  - prefer fewer stronger sections over a busy page with fake search, fake filters, or filler widgets
65
+ - adapt the above rules to the site type; docs and dashboards may need clearer repetitive utility layouts than editorial or portfolio pages
66
+ - for ecommerce/store tasks, prioritize merchandising, trust, objection handling, and purchase flow over editorial atmosphere
67
+ - only apply benchmark-grade strictness about publication framing, reflective-editorial copy, and forced asymmetry when the task is clearly a benchmark/comparison ask
68
68
  - After making code or file edits:
69
69
  - lead with the file path or paths you changed
70
70
  - summarize concrete changes, not vibes or quality claims
@@ -124,9 +124,16 @@ function buildSystemPrompt(profile, experienceMode = "standard", autonomyMode =
124
124
  `- tone: ${frontend.tone || "unknown"}`,
125
125
  `- content mode: ${frontend.contentMode || "designed-placeholder"}`,
126
126
  `- asset policy: ${frontend.assetPolicy || "no-placeholder-images-unless-explicit"}`,
127
- `- layout starter: ${frontend.layoutStarter || "choose a strong non-generic section grammar"}`
127
+ `- layout starter: ${frontend.layoutStarter || "choose a strong non-generic section grammar"}`,
128
+ `- benchmark mode: ${frontend.benchmarkMode ? "on" : "off"}`
128
129
  ].join("\n")
129
130
  );
131
+ if (Array.isArray(frontend.siteTypeRules) && frontend.siteTypeRules.length > 0) {
132
+ ctxLines.push(`Site-type rules:\n- ${frontend.siteTypeRules.join("\n- ")}`);
133
+ }
134
+ if (Array.isArray(frontend.benchmarkSiteTypeRules) && frontend.benchmarkSiteTypeRules.length > 0) {
135
+ ctxLines.push(`Benchmark site-type rules:\n- ${frontend.benchmarkSiteTypeRules.join("\n- ")}`);
136
+ }
130
137
  }
131
138
  if (executionContext.reminders) ctxLines.push(`Scope reminders:\n${executionContext.reminders}`);
132
139
  if (ctxLines.length > 0) base += `\n\nExecution context:\n${ctxLines.join("\n")}`;
package/src/frontend.js CHANGED
@@ -49,7 +49,35 @@ Rules:
49
49
 
50
50
  const BENCHMARK_FRONTEND_PROMPT = /\b(?:benchmark|squarespace quality|ultimate design|first class|on par|codex|claude code|cc)\b/i;
51
51
 
52
+ const UNIVERSAL_FRONTEND_REMINDERS = [
53
+ "Choose one visual direction and stay consistent across typography, spacing, color, and motion.",
54
+ "Choose a real type system with deliberate character. Browser-default Georgia/Times plus system sans is not an acceptable final design direction.",
55
+ "Prefer hand-authored CSS variables and layout rules over generic template utility sprawl when feasible.",
56
+ "Cut fake credibility elements, fake brands, fake testimonials, and filler interface chrome unless explicitly requested.",
57
+ "Do not add fake keyboard shortcuts, fake command palettes, or demo-only interactive chrome unless the interface truly needs them.",
58
+ "Avoid placeholder image services, Inter/Playfair default pairings, Tailwind CDN starter aesthetics, and generic premium-blog tropes.",
59
+ "Prefer fewer sections with stronger hierarchy over a long page full of low-value widgets."
60
+ ];
61
+
62
+ const BENCHMARK_FRONTEND_REMINDERS = [
63
+ "For benchmark frontend tasks, cut generic reflective-editorial copy. Use sharper, more concrete language or neutral structural placeholders instead of atmosphere-writing.",
64
+ "For benchmark frontend tasks, force at least one asymmetrical or compositionally distinctive move instead of a fully balanced template layout.",
65
+ "Benchmark mode: treat fake issue framing, fake publication history, fake keyboard shortcuts, and invented named contributors as disallowed outputs. Use neutral structural placeholders if needed."
66
+ ];
67
+
68
+ const BENCHMARK_SITE_TYPE_RULES = {
69
+ blog: [
70
+ "Benchmark blog mode: use neutral structural placeholders or concrete subject matter instead of publication worldbuilding or reflective-editorial atmosphere prose."
71
+ ],
72
+ store: [
73
+ "Benchmark ecommerce mode: prioritize conversion architecture over editorial styling. The page should sell, not just look clean.",
74
+ "Benchmark ecommerce mode: include proof, objection handling, and trust signals that belong on a real single-product PDP.",
75
+ "Benchmark ecommerce mode: do not leave the main merchandising surface as a literal placeholder or demo box."
76
+ ]
77
+ };
78
+
52
79
  const SITE_TYPES = [
80
+ ["store", /\b(shopify|ecommerce|e-commerce|store|shop|product page|pdp|single product|product detail page)\b/i],
53
81
  ["blog", /\b(blog|journal|essays?|articles?|publication|editorial)\b/i],
54
82
  ["landing", /\b(landing page|homepage|home page|marketing site|product site|launch page|hero section)\b/i],
55
83
  ["portfolio", /\b(portfolio|studio site|agency site|showcase)\b/i],
@@ -58,6 +86,7 @@ const SITE_TYPES = [
58
86
  ];
59
87
 
60
88
  const ARCHETYPES = [
89
+ ["single-product-commerce", /\b(shopify|ecommerce|e-commerce|single product|product page|pdp|store)\b/i],
61
90
  ["editorial-minimal", /\b(editorial|minimal|literary|journal|quiet)\b/i],
62
91
  ["luxury-magazine", /\b(luxury|magazine|fashion|elegant|squarespace)\b/i],
63
92
  ["founder-journal", /\b(founder|memo|notebook|letter|essay)\b/i],
@@ -73,6 +102,36 @@ const AUDIENCE_HINTS = [
73
102
  ["operators", /\b(founders?|operators?|engineers?|designers?)\b/i]
74
103
  ];
75
104
 
105
+ const SITE_TYPE_RULES = {
106
+ blog: [
107
+ "For blogs and editorial sites, prefer structural placeholder labels over inventing fictional publication brands, named editors, or fake biographical lore.",
108
+ "Do not invent issue numbers, seasonal issue metadata, staff credits, or named authors/photographers unless the user explicitly asked for fictional worldbuilding.",
109
+ "Do not add a newsletter/signup block unless the user explicitly asked for one or the site type clearly requires capture."
110
+ ],
111
+ landing: [
112
+ "For landing pages, prioritize the value proposition, proof, and one primary action over editorial atmosphere.",
113
+ "CTA sections are acceptable when they are genuinely part of the requested product flow; avoid fake testimonials or fake customer logos."
114
+ ],
115
+ portfolio: [
116
+ "For portfolios, let work samples, case studies, and identity carry the page rather than editorial filler.",
117
+ "Do not add newsletter/signup blocks or publication framing unless explicitly requested."
118
+ ],
119
+ docs: [
120
+ "For docs and help centers, clarity and information scent matter more than asymmetry or art direction.",
121
+ "Balanced, repetitive utility layouts are acceptable when they improve scanability."
122
+ ],
123
+ dashboard: [
124
+ "For dashboards and app UI, useful controls and information density matter more than editorial composition.",
125
+ "Do not remove necessary navigation or controls just to make the page feel minimal."
126
+ ],
127
+ store: [
128
+ "For ecommerce and single-product store pages, prioritize merchandising clarity, trust, and purchase flow over editorial atmosphere.",
129
+ "Include a clear product hierarchy near the buy action: product name, price, variant controls, purchase CTA, and shipping/returns or guarantee context.",
130
+ "Use proof and objection handling where appropriate: reviews, trust indicators, fit/material guidance, FAQ, shipping, or returns.",
131
+ "Do not add fake command palettes, fake app chrome, or non-commerce sections that distract from purchase intent."
132
+ ]
133
+ };
134
+
76
135
  const ARCHETYPE_RULES = {
77
136
  "editorial-minimal": [
78
137
  "Use restrained editorial hierarchy with fewer, larger blocks of content.",
@@ -109,6 +168,12 @@ const ARCHETYPE_RULES = {
109
168
  "Do not add fake command-palette or keyboard-shortcut gimmicks unless the interface truly needs them.",
110
169
  "Target type palette: sharp grotesk or mono-accent system with disciplined scale and hard contrast."
111
170
  ],
171
+ "single-product-commerce": [
172
+ "Use a commerce-first hierarchy: product image, offer, price, variants, CTA, trust, and objection handling should be visually obvious.",
173
+ "Favor sharp sans-serif typography with disciplined emphasis; avoid editorial-magazine drift.",
174
+ "The hero surface must merchandise the product, not just reserve space for a placeholder.",
175
+ "Target type palette: assertive commerce sans with compact utility text and a restrained accent display if needed."
176
+ ],
112
177
  "quiet-portfolio": [
113
178
  "Let work and case-study structure carry the page, not decorative chrome.",
114
179
  "Use calm spacing and image framing with minimal interface noise.",
@@ -146,6 +211,10 @@ const LAYOUT_STARTERS = {
146
211
  "landing:high-contrast-tech": [
147
212
  "Preferred layout starter: sharp hero + proof strip + product detail band + focused CTA footer.",
148
213
  "Avoid generic 6-section SaaS marketing pages unless explicitly requested."
214
+ ],
215
+ "store:single-product-commerce": [
216
+ "Preferred layout starter: media gallery + purchase stack + trust strip + proof/reviews + FAQ or care/shipping objections.",
217
+ "Do not stop at a clean two-column PDP shell; include the conversion architecture a strong Shopify single-product page needs."
149
218
  ]
150
219
  };
151
220
 
@@ -172,6 +241,11 @@ const SLOP_PATTERNS = [
172
241
  { key: "fake_social_proof", label: "fake reader count or social proof", pattern: /\b(?:\d+\s+readers joined this month|\d+\s+subscribers?|trusted by)\b/i, weight: 2 }
173
242
  ];
174
243
 
244
+ function getBenchmarkSiteTypeRules(siteType, benchmarkMode) {
245
+ if (!benchmarkMode) return [];
246
+ return BENCHMARK_SITE_TYPE_RULES[siteType] || [];
247
+ }
248
+
175
249
  function getLayoutStarter(siteType, archetype) {
176
250
  return LAYOUT_STARTERS[`${siteType}:${archetype}`] || null;
177
251
  }
@@ -252,6 +326,10 @@ function inferAssetPolicy(text) {
252
326
  return "no-placeholder-images-unless-explicit";
253
327
  }
254
328
 
329
+ function getSiteTypeRules(siteType) {
330
+ return SITE_TYPE_RULES[siteType] || [];
331
+ }
332
+
255
333
  export function isFrontendGenerationPrompt(promptText = "", profile = "coder") {
256
334
  const text = String(promptText || "").trim();
257
335
  if (!text) return false;
@@ -275,25 +353,21 @@ export function buildFrontendExecutionContext({ promptText = "", profile = "code
275
353
  if (benchmarkMode && siteType === "blog" && contentMode === "designed-placeholder") {
276
354
  contentMode = "structural-placeholder";
277
355
  }
356
+ if (benchmarkMode && siteType === "store" && contentMode === "designed-placeholder") {
357
+ contentMode = "conversion-placeholder";
358
+ }
278
359
  const assetPolicy = inferAssetPolicy(text);
279
360
  const layoutStarter = getLayoutStarter(siteType, archetype);
361
+ const siteTypeRules = getSiteTypeRules(siteType);
362
+ const benchmarkSiteTypeRules = getBenchmarkSiteTypeRules(siteType, benchmarkMode);
280
363
  const reminders = [
281
364
  `Frontend brief: site type = ${siteType}, archetype = ${archetype}, audience = ${audience}, tone = ${tone}.`,
282
365
  `Content mode: ${contentMode}. Asset policy: ${assetPolicy}.`,
283
366
  layoutStarter ? `Layout starter: ${layoutStarter[0]}` : "",
284
- "Choose one visual direction and stay consistent across typography, spacing, color, and motion.",
285
- "Choose a real type system with deliberate character. Browser-default Georgia/Times plus system sans is not an acceptable final design direction.",
286
- "Prefer hand-authored CSS variables and layout rules over generic template utility sprawl when feasible.",
287
- "Cut fake credibility elements, fake brands, fake testimonials, and filler interface chrome unless explicitly requested.",
288
- "For blogs and editorial sites, prefer structural placeholder labels over inventing fictional publication brands, named editors, or fake biographical lore.",
289
- "Do not invent issue numbers, seasonal issue metadata, staff credits, or named authors/photographers unless the user explicitly asked for fictional worldbuilding.",
290
- "Do not add a newsletter/signup block unless the user explicitly asked for one or the site type clearly requires capture.",
291
- "Do not add fake keyboard shortcuts, fake command palettes, or demo-only interactive chrome unless the interface truly needs them.",
292
- "Avoid placeholder image services, Inter/Playfair default pairings, Tailwind CDN starter aesthetics, and generic premium-blog tropes.",
293
- "Prefer fewer sections with stronger hierarchy over a long page full of low-value widgets.",
294
- "For benchmark frontend tasks, cut generic reflective-editorial copy. Use sharper, more concrete language or neutral structural placeholders instead of atmosphere-writing.",
295
- "For benchmark frontend tasks, force at least one asymmetrical or compositionally distinctive move instead of a fully balanced template layout.",
296
- benchmarkMode ? "Benchmark mode: treat fake issue framing, fake publication history, fake keyboard shortcuts, and invented named contributors as disallowed outputs. Use neutral structural placeholders if needed." : "",
367
+ ...UNIVERSAL_FRONTEND_REMINDERS,
368
+ ...siteTypeRules,
369
+ ...(benchmarkMode ? BENCHMARK_FRONTEND_REMINDERS : []),
370
+ ...benchmarkSiteTypeRules,
297
371
  ...(layoutStarter ? [layoutStarter[1]] : []),
298
372
  ...(ARCHETYPE_RULES[archetype] || [])
299
373
  ].join("\n");
@@ -307,7 +381,9 @@ export function buildFrontendExecutionContext({ promptText = "", profile = "code
307
381
  contentMode,
308
382
  assetPolicy,
309
383
  layoutStarter: layoutStarter ? layoutStarter[0] : null,
310
- benchmarkMode
384
+ benchmarkMode,
385
+ siteTypeRules,
386
+ benchmarkSiteTypeRules
311
387
  },
312
388
  reminders
313
389
  };
@@ -343,6 +419,18 @@ export function detectFrontendSlop({ promptText = "", assistantText = "", receip
343
419
  }
344
420
  const siteType = pickByPattern(String(promptText || ""), SITE_TYPES, "landing");
345
421
  const benchmarkMode = isBenchmarkFrontendTask(promptText);
422
+ if (siteType === "store" && benchmarkMode && /\b(?:product image|visual placeholder|replace with real product photography)\b/i.test(haystack)) {
423
+ flags.push("benchmark store left the primary merchandising surface as a placeholder");
424
+ score += 4;
425
+ }
426
+ if (siteType === "store" && benchmarkMode && !/\b(?:review|reviews|testimonial|rated|stars?|customers?)\b/i.test(haystack)) {
427
+ flags.push("benchmark store lacks social proof or review architecture");
428
+ score += 2;
429
+ }
430
+ if (siteType === "store" && benchmarkMode && !/\b(?:faq|shipping|returns|guarantee|size guide|fit|materials?|care)\b/i.test(haystack)) {
431
+ flags.push("benchmark store lacks objection-handling content");
432
+ score += 2;
433
+ }
346
434
  if (siteType === "blog" && !hasExplicitNewsletterRequest(promptText) && /\bnewsletter|subscribe|email\b/i.test(haystack)) {
347
435
  flags.push("newsletter block added without being requested");
348
436
  score += 3;
@@ -355,12 +443,12 @@ export function detectFrontendSlop({ promptText = "", assistantText = "", receip
355
443
  flags.push("fake keyboard or command-palette gimmick");
356
444
  score += 3;
357
445
  }
358
- if (siteType === "blog" && benchmarkMode && /\b(?:measure of time in ordinary things|quiet rituals|architecture of memory|cult of productivity|considered writing|the slow accumulation of days|craft of attention|in defense of silence)\b/i.test(haystack)) {
446
+ if (siteType === "blog" && benchmarkMode && /\b(?:measure of time in ordinary things|quiet rituals|architecture of memory|cult of productivity|considered writing|the slow accumulation of days|craft of attention|in defense of silence|meditation on permanence and ephemerality|stillness and the act of looking|deliberate observation)\b/i.test(haystack)) {
359
447
  flags.push("benchmark blog fell back to reflective-editorial atmosphere copy");
360
448
  score += 3;
361
449
  }
362
450
  const editorialLayoutHits = GENERIC_EDITORIAL_LAYOUT_PATTERNS.filter((pattern) => pattern.test(haystack)).length;
363
- if (siteType === "blog" && editorialLayoutHits >= 3) {
451
+ if (siteType === "blog" && benchmarkMode && editorialLayoutHits >= 3) {
364
452
  flags.push("generic editorial starter layout");
365
453
  score += 2;
366
454
  }
@@ -369,7 +457,7 @@ export function detectFrontendSlop({ promptText = "", assistantText = "", receip
369
457
  return {
370
458
  score,
371
459
  flags,
372
- hardBlock: flags.some((flag) => /fictional publication identity|fake keyboard|reflective-editorial atmosphere/.test(flag)),
460
+ hardBlock: flags.some((flag) => /fictional publication identity|fake keyboard|reflective-editorial atmosphere|primary merchandising surface as a placeholder/.test(flag)),
373
461
  severe: score >= 5,
374
462
  summary: flags.length > 0 ? `frontend slop flags: ${flags.join(", ")}` : "no deterministic frontend slop flags"
375
463
  };
@@ -410,6 +498,7 @@ export function buildFrontendRevisionPrompt({
410
498
  "Remove fake keyboard shortcuts, fake command palettes, and demo-only interaction flourishes that do not help the page.",
411
499
  "Cut reflective-editorial filler copy and replace it with either concrete language or neutral structural placeholders.",
412
500
  "For benchmark blog tasks, default to neutral structural placeholder content instead of invented publication framing, issue metadata, or named contributors.",
501
+ "For benchmark store tasks, do not leave the product image area as a labeled placeholder. Use product-shaped merchandising composition, proof, and objection-handling blocks instead.",
413
502
  "Reduce section count if needed and push one stronger asymmetrical composition instead of a sequence of balanced blocks.",
414
503
  "Simplify the page if needed. Stronger direction with fewer elements is preferred over busier generic output.",
415
504
  "Rewrite the weakest sections rather than making superficial tweaks."