Commit 6f0ceb2
committed
Tool audit sweep: 4 BLOCKERS, 12 HIGH, 6 MEDIUM fixed across 23 files
After 4 parallel agent audits covering 47 tool surfaces, found and fixed:
BLOCKERS (4):
- Display banner CharBadge used 30/90 hardcoded limits for every size
regardless of which banner (Mobile Banner = 22/28, Wide Skyscraper = 25/80,
etc.). Imports DISPLAY_SIZES and looks up per-size h_max/d_max now.
- Google Shopping policy_warnings render was unreachable: outer `?.length`
truthy gate meant the zero-warnings "clean" message never fired. Now uses
Array.isArray() check.
- Google Shopping `category` field smart-fill aliased to brain.industry,
pre-populating "E-commerce" into the product-taxonomy field. Renamed to
product_category so smart-fill leaves it blank for explicit user input.
- Hashtags tool: HashtagOutput used config.initial.platform (frozen as
"instagram") to key into the recommended-set bucket. Non-IG platforms
always showed empty recommendations. Now discovers the key dynamically
with Object.keys().find(k => k.startsWith("recommended_set_for_")).
HIGH (12):
- Unconditional "IF AN IMAGE IS ATTACHED" prompt blocks in 5 optimizer
prompts (ad-fatigue, bid-strategy, ctr-optimizer, keyword-strategy,
landing-page) — now gated on `input.<screenshot_field>` matching the
fix already applied to audience-targeting. Each Input interface gains
its `?_screenshot?: unknown` field.
- LinkedIn `format.replace("_", " ")` only replaced first underscore;
"lead_gen_form" became "lead gen_form". Now uses /_/g regex.
- YouTube copy-button dropped beat timestamps; in-stream script lines
copied without their time markers. Now includes [t] in the copy text.
- Budget-planner buildTitle hardcoded `$${total_monthly}/mo`; INR user
would see "$50000" in saved history. Dropped the `$`.
- Budget-planner renderer + budget renderer: 12 hardcoded `$` literals
in AI-generated figures (waste, recovery, monthly_usd, etc.). All now
use getCurrency().symbol. Prompts also prefix amounts with currency code
so the AI generates figures in the user's chosen currency.
- Audience optimizer label "Budget / mo (USD)" → "Budget / mo" with
generic "Your selected currency" hint.
- Suggestions auto-run race: setTimeout(() => run(), 400) captured stale
null brain via closure, causing "No active Brand Brain" error on load
when a brain existed. New runWithBrain(b) accepts the brain directly.
- Launch wizard fallback retry dropped master abort signal; Stop button
couldn't cancel during fallback. Now uses anySignal(args.signal,
fallbackCtl.signal).
- Wizard + GeneratorShell + suggestions + competitors + frameworks +
learn/[concept] + batch.tsx: ALL now use `res.text || stream.text`
fallback so empty res.text from Gemini doesn't produce blank saved ads.
- Batch.tsx: no AbortController, no Stop button — N parallel calls
couldn't be cancelled. Now has master signal threaded to each llmStream
+ Stop button visible while running.
- learn/[concept]/Client.tsx: no AbortController; streaming continued
writing to state after unmount. Added abortRef + useEffect cleanup.
- BrandBrainForm: extract() did direct spread merge, destroying manual
edits. Now uses mergeFillEmpty. Also wired AbortController to all 3
AI call paths. save() redirect changed from "/" to "/brand".
- Landing-page tool: URL field was a dead string the AI couldn't fetch.
Updated label + hint to make this explicit; user pastes copy in the
textarea below.
- Spark-ads + suggestions: `$` hardcoded in scale-rules cap and campaign
budget display. Both now use getCurrency().symbol.
MEDIUM (6):
- campaign-kit prompt now imports BANNED_WORDS_RULE + HONESTY_CLAUSE
matching meta-ads / google-ads / linkedin-ads.
- content-calendar prompt computes estimated entry count (days × platforms
× cadence/wk) and instructs a HARD_ENTRY_CAP=35 with truncation_notice
to prevent silent JSON truncation on 1-month multi-platform requests
that previously exceeded the 6500-token budget.
- google-shopping price field placeholder no longer says "$24.99";
prompt guard: "(not provided — do not invent pricing)".
- Display, hashtags, google-shopping minor cleanup.
Verification: typecheck clean, 43/43 tests pass, next build compiles
from scratch. Touched 23 source files across app/, components/, lib/.
(Several audit findings were intentionally NOT acted on after re-inspection:
the "busyRef leak" in brand/new/page.tsx was incorrect — quickAddFromGoogleInternal
owns its own busyRef lifecycle including the finally cleanup, so the reroute
path is safe. Several optional-rendering nitpicks were also skipped as low-value.)1 parent dcea432 commit 6f0ceb2
27 files changed
Lines changed: 612 additions & 79 deletions
File tree
- app
- batch
- generate
- display
- google-shopping
- hashtags
- spark-ads
- youtube
- launch/wizard
- learn/[concept]
- optimize
- audience
- budget-planner
- budget
- landing-page
- suggestions
- components
- lib/prompts
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
0 commit comments