@tritard/waterbrother 0.8.36 → 0.8.38

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.36",
3
+ "version": "0.8.38",
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/cli.js CHANGED
@@ -1219,7 +1219,8 @@ async function maybeReviseInteractiveFrontend({
1219
1219
  while (shouldAutoReviseFrontend({
1220
1220
  designReview: artifacts.designReview,
1221
1221
  slop: artifacts.designSlop,
1222
- revisionCount
1222
+ revisionCount,
1223
+ frontend: frontendExecutionContext.frontend || null
1223
1224
  })) {
1224
1225
  const passNumber = revisionCount + 1;
1225
1226
  const forceRebuild = shouldForceFrontendRebuild({
package/src/frontend.js CHANGED
@@ -251,6 +251,7 @@ const BENCHMARK_STARTERS = {
251
251
  "Section 4: material/specification or craftsmanship band with objection handling.",
252
252
  "Section 5: compact FAQ or guarantee block if still needed.",
253
253
  "No Tailwind starter shell, no fake reviews, no fake badges, no placeholder gallery, no emoji or dashed placeholder hero, no alert-based checkout, no keyboard shortcut chrome, no demo footer copy.",
254
+ "If you do not implement a real cart drawer or checkout flow, keep cart UI passive. Do not use alert/prompt fallbacks that explain what would happen in a real Shopify store.",
254
255
  "The hero must merchandise the product with a believable product surface and product-specific benefit language, not generic luxury-commerce filler.",
255
256
  "Use a real product image URL or an authored SVG/CSS product silhouette with material/shadow treatment. Never use text-only image placeholders."
256
257
  ]
@@ -280,7 +281,7 @@ const BENCHMARK_FEWSHOT_EXAMPLES = {
280
281
  ],
281
282
  bad: [
282
283
  "Generic luxury filler like considered life, timeless essentials, or modern living.",
283
- "Demo cart toasts, console narration, or 'in a real Shopify store' copy.",
284
+ "Demo cart toasts, alert-based cart fallbacks, or 'in a real Shopify store' copy.",
284
285
  "Placeholder gallery or weak hero that does not merchandise the product.",
285
286
  "Fake proof chrome like bestseller badges, sold-this-month counters, or made-up review totals."
286
287
  ]
@@ -296,6 +297,7 @@ const BENCHMARK_GRADERS = {
296
297
  ],
297
298
  store: [
298
299
  { key: "no_demo_js", label: "grader failed: benchmark store still contains demo JS behavior", pattern: /\b(?:alert\(|prompt\(|console\.log|showToast|static demo|in a real shopify store)\b/i, weight: 4, hardBlock: true },
300
+ { key: "no_fake_cart_fallback", label: "grader failed: benchmark store still uses fake cart or checkout fallback behavior", pattern: /\b(?:cart would open here|would go to checkout|would continue to checkout|would appear here)\b/i, weight: 4, hardBlock: true },
299
301
  { key: "no_fake_proof", label: "grader failed: benchmark store still uses fake proof or badge chrome", pattern: /\b(?:best seller|bestseller|\d[\d,]*\s+reviews|\d[\d,]*\s+\w+\s+sold\s+this\s+month|sold this month|as featured in|featured in|trusted by)\b/i, weight: 4, hardBlock: true },
300
302
  { key: "no_generic_luxury_copy", label: "grader failed: benchmark store still relies on generic luxury-commerce copy", pattern: /\b(?:objects for a considered life|considered life|timeless essentials|designed for modern living|carry less\. keep more\.)\b/i, weight: 3, hardBlock: true },
301
303
  { key: "product_specific_copy", label: "grader failed: benchmark store copy is missing product-specific merchandising detail", missing: /\b(?:material|materials|capacity|fits|carry|pocket|warranty|care|dimensions?|full-grain|canvas|leather|zip|strap)\b/i, weight: 2, hardBlock: false }
@@ -708,6 +710,58 @@ export async function inspectFrontendArtifacts({ cwd, receipt = null, frontend =
708
710
  flags.push(`benchmark ${frontend.siteType} still contains demo behavior or explanation copy`);
709
711
  score += 3;
710
712
  }
713
+ if (/cdn\.tailwindcss\.com/i.test(htmlText)) {
714
+ flags.push(`benchmark ${frontend.siteType} still contains Tailwind CDN starter theming`);
715
+ score += 4;
716
+ }
717
+ if (/(?:cdnjs\.cloudflare\.com\/ajax\/libs\/font-awesome|fontawesome)/i.test(htmlText)) {
718
+ flags.push(`benchmark ${frontend.siteType} still contains Font Awesome chrome`);
719
+ score += 3;
720
+ }
721
+ if (/\b(?:picsum\.photos|placehold\.co|placeholder\.com)\b/i.test(htmlText)) {
722
+ flags.push(`benchmark ${frontend.siteType} still contains placeholder imagery`);
723
+ score += 4;
724
+ }
725
+ if (/\b(?:metaKey && e\.key === ['"]k['"]|command palette|keyboard shortcuts?)\b/i.test(htmlText)) {
726
+ flags.push(`benchmark ${frontend.siteType} still contains fake keyboard or shortcut chrome`);
727
+ score += 4;
728
+ }
729
+ if (frontend.siteType === "store") {
730
+ if (/\b(?:cart would open here|would go to checkout|would continue to checkout|would appear here)\b/i.test(htmlText)) {
731
+ flags.push("benchmark store still contains fake cart or checkout fallback behavior");
732
+ score += 4;
733
+ }
734
+ if (/\b(?:best seller|bestseller|\d[\d,]*\s+reviews|\d[\d,]*\s+\w+\s+sold\s+this\s+month|sold this month|as featured in|featured in|trusted by)\b/i.test(htmlText)) {
735
+ flags.push("benchmark store still contains fake proof or badge chrome");
736
+ score += 4;
737
+ }
738
+ if (/\b(?:objects for a considered life|considered life|timeless essentials|designed for modern living|carry less\. keep more\.)\b/i.test(htmlText)) {
739
+ flags.push("benchmark store still contains generic luxury-commerce copy");
740
+ score += 3;
741
+ }
742
+ if (!/\b(?:material|materials|capacity|fits|carry|pocket|warranty|care|dimensions?|full-grain|canvas|leather|zip|strap)\b/i.test(htmlText)) {
743
+ flags.push("benchmark store still lacks product-specific merchandising detail");
744
+ score += 2;
745
+ }
746
+ }
747
+ if (frontend.siteType === "blog") {
748
+ if (/\bfont-family:\s*system-ui|font-family:\s*-apple-system|BlinkMacSystemFont|Segoe UI\b/i.test(htmlText)) {
749
+ flags.push("benchmark blog still leans on raw system-ui body typography");
750
+ score += 2;
751
+ }
752
+ if (/\b(?:Archive|Essays|Conversations|Featured Essay|Latest Dispatches|Notes|Print Edition|Submit Work|Journal)\b/i.test(htmlText)) {
753
+ flags.push("benchmark blog still contains publication-shell framing");
754
+ score += 4;
755
+ }
756
+ if (/\b(?:by [A-Z][A-Za-z]+(?:\s+[A-Z][A-Za-z]+)+|contributor|essay by|interview by)\b/i.test(htmlText)) {
757
+ flags.push("benchmark blog still contains named bylines or contributor credits");
758
+ score += 4;
759
+ }
760
+ if (/\b(?:architecture of silence|material memory|craft of attention|quiet power|brutalist interior|in praise of slowness|on attention|measure of restraint|deliberate life|value of slowness)\b/i.test(htmlText)) {
761
+ flags.push("benchmark blog still contains generic editorial filler copy");
762
+ score += 3;
763
+ }
764
+ }
711
765
  }
712
766
  }
713
767
 
@@ -735,8 +789,9 @@ export function mergeFrontendSlop(base = null, extra = null) {
735
789
  };
736
790
  }
737
791
 
738
- export function shouldAutoReviseFrontend({ designReview = null, slop = null, revisionCount = 0 } = {}) {
739
- if (revisionCount >= 3) return false;
792
+ export function shouldAutoReviseFrontend({ designReview = null, slop = null, revisionCount = 0, frontend = null } = {}) {
793
+ const maxPasses = frontend?.benchmarkMode && frontend?.siteType === "store" ? 5 : 3;
794
+ if (revisionCount >= maxPasses) return false;
740
795
  if (!designReview) return false;
741
796
  if (slop?.hardBlock) return true;
742
797
  if (designReview.verdict === "weak") return true;
@@ -747,6 +802,7 @@ export function shouldAutoReviseFrontend({ designReview = null, slop = null, rev
747
802
  export function shouldForceFrontendRebuild({ frontend = null, slop = null, revisionCount = 0 } = {}) {
748
803
  if (!frontend?.benchmarkMode) return false;
749
804
  if (!slop?.hardBlock) return false;
805
+ if (frontend.siteType === "store") return revisionCount < 4;
750
806
  return revisionCount < 2;
751
807
  }
752
808
 
package/src/workflow.js CHANGED
@@ -198,7 +198,7 @@ export async function runBuildWorkflow({
198
198
  let revisionCount = 0;
199
199
  const revisionHistory = [];
200
200
 
201
- while (shouldAutoReviseFrontend({ designReview, slop: designSlop, revisionCount })) {
201
+ while (shouldAutoReviseFrontend({ designReview, slop: designSlop, revisionCount, frontend: frontendCtx?.frontend || null })) {
202
202
  const passNumber = revisionCount + 1;
203
203
  const forceRebuild = shouldForceFrontendRebuild({ frontend: frontendCtx?.frontend, slop: designSlop, revisionCount });
204
204
  revisionHistory.push({