@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 +1 -1
- package/src/cli.js +2 -1
- package/src/frontend.js +59 -3
- package/src/workflow.js +1 -1
package/package.json
CHANGED
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,
|
|
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
|
-
|
|
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({
|