@tidyfactor/marketing 1.3.0 โ†’ 1.6.0

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.
Files changed (40) hide show
  1. package/.tidyfactor +53 -52
  2. package/CHANGELOG.md +47 -0
  3. package/README.ar.md +20 -9
  4. package/README.md +20 -9
  5. package/SKILL.md +46 -30
  6. package/bin/add-skill.js +65 -50
  7. package/brand.json +67 -67
  8. package/brand.yaml +55 -0
  9. package/manifest.json +256 -0
  10. package/package.json +5 -1
  11. package/references/commands/audit.md +34 -0
  12. package/references/commands/brief.md +7 -5
  13. package/references/memory/20-brain-baas-integration.md +89 -0
  14. package/references/memory/ad-copy-templates.md +94 -93
  15. package/references/memory/arabic-writing.md +1 -1
  16. package/references/memory/campaign-mindmap.md +85 -0
  17. package/references/memory/decision-points.md +74 -73
  18. package/references/memory/frameworks.md +87 -86
  19. package/references/memory/lifecycle-flows.md +107 -106
  20. package/references/memory/metrics-benchmarks.md +71 -70
  21. package/references/memory/naming-conventions.md +75 -0
  22. package/references/memory/philosophy.md +2 -0
  23. package/references/memory/platform-specs.md +76 -75
  24. package/references/memory/promotions-math.md +57 -56
  25. package/references/memory/quality-bar.md +56 -55
  26. package/references/workflows/brief.md +74 -35
  27. package/references/workflows/campaign-launch.md +1 -1
  28. package/references/workflows/content-engine.md +1 -1
  29. package/references/workflows/email-lifecycle.md +1 -1
  30. package/references/workflows/paid-acquisition.md +1 -1
  31. package/references/workflows/promo-conversion.md +1 -1
  32. package/references/workflows/social-growth.md +1 -1
  33. package/references/workflows/viral-retention.md +1 -1
  34. package/scripts/audit_copy.py +112 -0
  35. package/scripts/calc_promo_math.py +69 -0
  36. package/scripts/clean_orphaned_assets.py +108 -0
  37. package/tests/scenarios.md +87 -0
  38. package/tools/build-skill.js +4 -0
  39. package/tools/validate_skill.py +265 -112
  40. package/assets/og-default.png +0 -0
@@ -1,72 +1,111 @@
1
1
  # Marketing Discovery & Brief Workflow
2
2
 
3
- > **Outcome**: Generates an authoritative `.tidyfactor/marketing-brief.md` file capturing target market, brand voice, funnel stage, conversion model, and delivery scope.
3
+ > **Outcome**: Generates an authoritative `.tidyfactor/marketing-brief.md` baseline capturing target market, brand voice, funnel stage, conversion model, and delivery scope.
4
4
 
5
5
  ---
6
6
 
7
- ## ๐Ÿ“‹ Step 0: Check Existing Baseline
7
+ ## ๐Ÿ“‹ Step 0: Context Delta Resolution Engine
8
8
 
9
- 1. Check if `.tidyfactor/marketing-brief.md` already exists on disk.
10
- 2. If it exists and user did not specify `--force` or `--reset`:
11
- - Display the active brief summary.
12
- - Ask if the user wants to keep the existing baseline or update specific parameters.
9
+ Before asking any questions, execute the mechanical resolution formula:
13
10
 
14
- ---
11
+ $$\text{Unknowns} = \text{Required Decisions} - (\text{Discovered Facts} \cup \text{Brain KIs})$$
15
12
 
16
- ## ๐Ÿ’ฌ Step 1: Conduct 3-Question Targeted Discovery
13
+ ### 1. Required Decisions Set (from `manifest.json["decision_gates"]`):
14
+ - `target_market`: Regional calibration (GCC, Egypt/Levant, Global B2B SaaS, Bilingual MENA).
15
+ - `brand_voice`: Voice archetype (Authoritative Challenger, Empathetic Guide, Elite Luxury, High-Energy Direct Response).
16
+ - `funnel_stage`: Conversion focus (Top / Middle / Bottom of funnel).
17
+ - `core_offer`: Headline value proposition and transaction vehicle.
17
18
 
18
- If no baseline exists, present at most 3 clear, structured questions in a single turn:
19
+ ### 2. Discovered Facts (Auto-Sensing + Local Staleness Tracking):
20
+ - Inspect `brand.yaml`, `brand.json`, and `BRAND-GUIDELINES.md` on disk.
21
+ - If `track_staleness: true` is configured, verify file hash/mtime against stored snapshot.
22
+ - Any decision successfully extracted from local disk is removed from $\text{Unknowns}$.
19
23
 
20
- ### Question 1: Target Market & Regional Tone (M1)
21
- - **A) Gulf / GCC (Saudi Arabia ๐Ÿ‡ธ๐Ÿ‡ฆ, UAE ๐Ÿ‡ฆ๐Ÿ‡ช, Kuwait ๐Ÿ‡ฐ๐Ÿ‡ผ, Qatar ๐Ÿ‡ถ๐Ÿ‡ฆ)** โ€” High prestige, trust-first, WhatsApp/Installments framing, modern polished Arabic.
22
- - **B) Egypt & Levant (Egypt ๐Ÿ‡ช๐Ÿ‡ฌ, Jordan ๐Ÿ‡ฏ๐Ÿ‡ด)** โ€” Practical ROI, high energy, relatable wit, cash-on-delivery & InstaPay framing.
23
- - **C) Global / B2B SaaS** โ€” Direct, metric-dense, self-serve focused, English-first.
24
- - **D) Bilingual / Unified MENA** (Default).
24
+ ### 3. Fail-Open MCP Brain Acceleration:
25
+ - If unresolved unknowns remain AND `search_knowledge_base` is available:
26
+ - Query `search_knowledge_base(query="marketing persona brand voice", scope="project")`.
27
+ - If a valid marketing KI exists, populate the context and remove from $\text{Unknowns}$.
28
+ - **Fail-Open Invariant**: If Brain MCP is unavailable or offline, skip instantly with 0ms delay without warnings.
25
29
 
26
- ### Question 2: Brand Voice Archetype (M2)
27
- - **A) Authoritative Challenger** (Direct, contrarian, proof-backed, no-nonsense).
28
- - **B) Empathetic Guide** (Supportive, story-driven, transformational, warm).
29
- - **C) Elite Luxury / High-End** (Minimalist, aspirational, refined confidence).
30
- - **D) High-Energy Direct Response** (Urgent, benefit-stacked, conversion-focused).
30
+ ---
31
31
 
32
- ### Question 3: Funnel Focus & Core Offer (M3 + M4)
33
- - **A) Top-of-Funnel Lead Magnet** (Free guide, checklist, audit, quiz).
34
- - **B) Middle-of-Funnel Trial / Demo** (Product-led trial, 1-on-1 strategy call).
35
- - **C) Bottom-of-Funnel Direct Sale / Promo** (E-commerce purchase, limited-time launch offer).
32
+ ## ๐Ÿ’ฌ Step 1: Interactive Modal Protocol (CDL v2.0)
33
+
34
+ If $\text{Unknowns} = \emptyset$:
35
+ - Display the synthesized 4-line baseline summary.
36
+ - Suggest next commands (`/strategy`, `/advertising`, `/email`, `/content`) immediately.
37
+
38
+ If $\text{Unknowns} \neq \emptyset$:
39
+ - **Interactive Wizard Invariant**: Present genuine Unknowns exclusively via the native interactive question tool (`ask_question`). Never dump static text questionnaires or bullet lists in chat.
40
+ - **Zero Robotic Preamble**: Forbid greetings or conversational filler.
41
+
42
+ ### Operational Mode Selection:
43
+
44
+ #### [MODE A] Smart 3-Round Protocol (๐ŸŽฏ ุงู„ุงุฑุชุฌุงู„ ุงู„ุฐูƒูŠ ุงู„ู…ู‚ูŠุฏ)
45
+ Presents structured choices one step at a time via `ask_question`:
46
+ 1. **Round 1 (Target Market & Regional Nuance)**:
47
+ - `(Recommended) Bilingual / Unified MENA` โ€” Pan-Arab modern standard paired with English tech terminology.
48
+ - `Gulf / GCC (Saudi Arabia ๐Ÿ‡ธ๐Ÿ‡ฆ, UAE ๐Ÿ‡ฆ๐Ÿ‡ช, Kuwait ๐Ÿ‡ฐ๐Ÿ‡ผ, Qatar ๐Ÿ‡ถ๐Ÿ‡ฆ)` โ€” Prestige, trust-first, WhatsApp/Installment framing.
49
+ - `Egypt & Levant (Egypt ๐Ÿ‡ช๐Ÿ‡ฌ, Jordan ๐Ÿ‡ฏ๐Ÿ‡ด)` โ€” Practical ROI, high energy, relatable wit, InstaPay framing.
50
+ - `Global / B2B SaaS` โ€” Direct, metric-dense, self-serve focused, English-first.
51
+ 2. **Round 2 (Brand Voice Archetype)**:
52
+ - `(Recommended) Authoritative Challenger` โ€” Direct, contrarian, proof-backed, zero-nonsense.
53
+ - `Empathetic Guide` โ€” Supportive, story-driven, transformational, warm.
54
+ - `Elite Luxury / High-End` โ€” Minimalist, aspirational, refined confidence.
55
+ - `High-Energy Direct Response` โ€” Urgent, benefit-stacked, conversion-focused.
56
+ 3. **Round 3 (Funnel Focus & Core Offer)**:
57
+ - `(Recommended) Bottom-of-Funnel Direct Sale / Promo` โ€” Immediate transaction, launch offer.
58
+ - `Middle-of-Funnel Trial / Demo` โ€” Product-led trial, strategy session.
59
+ - `Top-of-Funnel Lead Magnet` โ€” Free high-value guide, benchmark, audit.
60
+
61
+ #### [MODE B] Debate Mode (๐Ÿ”ฅ ุงู„ุงุณุชุฌูˆุงุจ ูˆุงู„ู…ู†ุงุธุฑุฉ ุงู„ู„ุงู†ู‡ุงุฆูŠุฉ)
62
+ - Activated via `/debate`, explicit user prompt ("ู…ู†ุงุธุฑุฉ" / "ุงุณุชุฌูˆุจู†ูŠ"), or Mode A escalation.
63
+ - Relentlessly challenges marketing assumptions, price elasticity, CAC-to-LTV payback periods, and unproven claims.
64
+ - Presents binary architectural trade-offs one step at a time via `ask_question`.
65
+ - Terminates only upon explicit user trigger (`"END DEBATE"` / `"ุงุนุชู…ุงุฏ"`), emitting a formal synthesis.
36
66
 
37
67
  ---
38
68
 
39
- ## ๐Ÿ’พ Step 2: Write `.tidyfactor/marketing-brief.md`
40
-
41
- Format and persist the confirmed choices:
69
+ ## ๐Ÿ’พ Step 2: Persist Baseline & Single-Direction Brain Push
42
70
 
71
+ 1. Format and write `.tidyfactor/marketing-brief.md`:
43
72
  ```markdown
44
73
  # Marketing Brief Baseline
45
74
 
46
75
  - **Product / Brand**: [Extracted or Confirmed Name]
47
- - **Target Market (M1)**: [Confirmed Selection]
48
- - **Brand Voice (M2)**: [Confirmed Archetype]
49
- - **Funnel Stage (M3)**: [Top / Middle / Bottom]
50
- - **Core Offer (M4)**: [Lead Magnet / Trial / Direct Transaction]
51
- - **Deliverable Scope (M5)**: [Sprint Copy / Multi-Channel Blueprint]
76
+ - **Target Market**: [GCC / Egypt & Levant / Global / Unified MENA]
77
+ - **Brand Voice**: [Authoritative / Empathetic / Luxury / Direct Response]
78
+ - **Funnel Stage**: [Top / Middle / Bottom]
79
+ - **Core Offer**: [Lead Magnet / Trial / Direct Transaction]
80
+ - **Deliverable Scope**: [Sprint Copy / Multi-Channel Blueprint]
52
81
  - **Last Updated**: [Current Date]
53
82
  ```
54
83
 
84
+ 2. Format YAML snapshot `.tidyfactor/marketing-brief.snapshot.yaml` for deterministic local staleness tracking (Rule 15).
85
+
86
+ 3. **Anti-Dual-Write Outbound Push (`--sync-brain`)**:
87
+ - The local file is ALWAYS the single source of truth.
88
+ - When explicitly passed `--sync-brain`, format the deliverable as an Atomic KI and push to Brain MCP via `extract_knowledge_item`.
89
+ - Never perform simultaneous dual writes.
90
+
55
91
  ---
56
92
 
57
- ## ๐ŸŽฏ Step 3: Self-Critique & Handoff
93
+ ## ๐ŸŽฏ Step 3: Self-Critique & Actionable Summary
58
94
 
59
95
  Stamp the 7-axis critique:
60
96
  ```markdown
61
97
  /* Pre-emit critique: P5 H5 E5 S5 R5 V5 D5 */
62
98
  ```
99
+ Display a concise summary and suggest the next logical marketing command (`/strategy`, `/advertising`, `/email`, `/content`, `/audit`).
63
100
 
64
101
  ---
65
102
 
66
- ## ## Validation checklist
103
+ ## Validation checklist
67
104
 
105
+ - [ ] Context Delta Resolution computed prior to prompting user.
106
+ - [ ] No questions asked for parameters already discovered on disk.
107
+ - [ ] Unknowns presented via native interactive modal tool (`ask_question`).
68
108
  - [ ] `.tidyfactor/marketing-brief.md` created or verified on disk.
69
- - [ ] Exactly 3 or fewer questions asked in a single round.
70
109
  - [ ] Regional calibration (GCC, Egypt, Global) explicitly recorded.
71
110
  - [ ] Brand voice archetype explicitly recorded.
72
- - [ ] Confirmed baseline summary displayed to user with next command suggestions (`/strategy`, `/advertising`, `/email`, `/content`).
111
+ - [ ] Confirmed baseline summary displayed to user with next command suggestions.
@@ -60,7 +60,7 @@ Before emitting the final strategy, evaluate against all 7 axes from `../memory/
60
60
 
61
61
  ---
62
62
 
63
- ## Validation Checklist
63
+ ## Validation checklist
64
64
 
65
65
  - [ ] CDL brief parameters resolved from `.tidyfactor/marketing-brief.md` or prompt defaults
66
66
  - [ ] Canonical positioning statement formulated with concrete proof (no generic slogans)
@@ -56,7 +56,7 @@ Before emitting the final content assets, evaluate against all 7 axes from `../m
56
56
 
57
57
  ---
58
58
 
59
- ## Validation Checklist
59
+ ## Validation checklist
60
60
 
61
61
  - [ ] CDL brief parameters resolved from `.tidyfactor/marketing-brief.md` or prompt defaults
62
62
  - [ ] Every post includes a 0-3s attention hook matching platform specs
@@ -44,7 +44,7 @@ Before emitting the final email copy or flows, evaluate against all 7 axes from
44
44
 
45
45
  ---
46
46
 
47
- ## Validation Checklist
47
+ ## Validation checklist
48
48
 
49
49
  - [ ] CDL brief parameters resolved from `.tidyfactor/marketing-brief.md` or prompt defaults
50
50
  - [ ] Lead magnet promises a specific, actionable win achievable in < 10 minutes
@@ -54,7 +54,7 @@ Before emitting ad copy or landing page wireframes, evaluate against all 7 axes
54
54
 
55
55
  ---
56
56
 
57
- ## Validation Checklist
57
+ ## Validation checklist
58
58
 
59
59
  - [ ] CDL brief parameters resolved from `.tidyfactor/marketing-brief.md` or prompt defaults
60
60
  - [ ] At least 3 distinct psychological ad copy angles produced
@@ -46,7 +46,7 @@ Before emitting pricing, promotions, or sale mechanics, evaluate against all 7 a
46
46
 
47
47
  ---
48
48
 
49
- ## Validation Checklist
49
+ ## Validation checklist
50
50
 
51
51
  - [ ] CDL brief parameters resolved from `.tidyfactor/marketing-brief.md` or prompt defaults
52
52
  - [ ] Discount structure verified against gross margins to prevent profit erosion
@@ -53,7 +53,7 @@ Before emitting social media playbooks or profile copy, evaluate against all 7 a
53
53
 
54
54
  ---
55
55
 
56
- ## Validation Checklist
56
+ ## Validation checklist
57
57
 
58
58
  - [ ] CDL brief parameters resolved from `.tidyfactor/marketing-brief.md` or prompt defaults
59
59
  - [ ] Bio is optimized with clear target, authority proof, and single action CTA
@@ -51,7 +51,7 @@ Before emitting loyalty programs, referral systems, or outreach scripts, evaluat
51
51
 
52
52
  ---
53
53
 
54
- ## Validation Checklist
54
+ ## Validation checklist
55
55
 
56
56
  - [ ] CDL brief parameters resolved from `.tidyfactor/marketing-brief.md` or prompt defaults
57
57
  - [ ] Retention drop-off point diagnosed before prescribing loyalty mechanics
@@ -0,0 +1,112 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ TidyFactor Marketing Copy Quality Auditor
4
+ Scans direct-response marketing copy, ad headlines, and landing page scripts
5
+ for AI anti-patterns, banned cliches, robotic phrasing, and angle diversity.
6
+ """
7
+
8
+ import sys
9
+ import os
10
+ import re
11
+ import json
12
+ import argparse
13
+ from pathlib import Path
14
+
15
+ # Ensure UTF-8 output on Windows console
16
+ if sys.stdout and hasattr(sys.stdout, "reconfigure"):
17
+ sys.stdout.reconfigure(encoding="utf-8", errors="replace")
18
+ if sys.stderr and hasattr(sys.stderr, "reconfigure"):
19
+ sys.stderr.reconfigure(encoding="utf-8", errors="replace")
20
+
21
+ BANNED_AI_CLICHES = [
22
+ # English Slop
23
+ r"\bunleash\b", r"\belevate\b", r"\bgame-changer\b", r"\brevolutionize\b",
24
+ r"\bseamlessly\b", r"\btap into\b", r"\bdive deep\b", r"\bdelve into\b",
25
+ r"\bunlock your potential\b", r"\bin today's fast-paced world\b",
26
+ r"\blook no further\b", r"\bcutting-edge\b", r"\bstate-of-the-art\b",
27
+ # Arabic Slop
28
+ r"ููŠ ุนุงู„ู…ู†ุง ุงู„ูŠูˆู… ุงู„ู…ุชุณุงุฑุน", r"ููŠ ุนุตุฑ ุงู„ุชูƒู†ูˆู„ูˆุฌูŠุง", r"ุฃุทู„ู‚ ุงู„ุนู†ุงู†",
29
+ r"ุงู†ุบู…ุณ ููŠ", r"ุบูŠู‘ุฑ ู‚ูˆุงุนุฏ ุงู„ู„ุนุจุฉ", r"ุญู„ูˆู„ ุณุญุฑูŠุฉ", r"ูุฑูŠุฏุฉ ู…ู† ู†ูˆุนู‡ุง",
30
+ r"ู†ู‚ุฏู… ู„ูƒู… ุจูƒู„ ูุฎุฑ", r"ู„ุง ุฏุงุนูŠ ู„ู„ุจุญุซ ุจุนุฏ ุงู„ุขู†", r"ุจูˆุงุจุชูƒ ู†ุญูˆ"
31
+ ]
32
+
33
+ def audit_text_content(text: str, file_name: str = "inline-copy") -> dict:
34
+ issues = []
35
+ lines = text.splitlines()
36
+
37
+ # 1. Check for AI Cliches & Marketing Slop
38
+ for idx, line in enumerate(lines, start=1):
39
+ for pattern in BANNED_AI_CLICHES:
40
+ matches = re.finditer(pattern, line, re.IGNORECASE)
41
+ for m in matches:
42
+ issues.append({
43
+ "type": "banned_cliche",
44
+ "severity": "high",
45
+ "line": idx,
46
+ "matched": m.group(0),
47
+ "message": f"Banned marketing clichรฉ detected: '{m.group(0)}'. Replace with concrete proof or specific benefit."
48
+ })
49
+
50
+ # 2. Check for Pre-emit critique stamp
51
+ has_critique = bool(re.search(r"/\*\s*Pre-emit critique:[^\*]+\*/", text, re.IGNORECASE))
52
+ if not has_critique and not text.startswith("#"):
53
+ issues.append({
54
+ "type": "missing_critique_stamp",
55
+ "severity": "medium",
56
+ "line": 1,
57
+ "message": "Missing 7-axis pre-emit critique stamp: /* Pre-emit critique: P5 H5 E5 S5 R5 V5 D5 */"
58
+ })
59
+
60
+ # 3. Calculate Score
61
+ high_issues = [i for i in issues if i["severity"] == "high"]
62
+ med_issues = [i for i in issues if i["severity"] == "medium"]
63
+
64
+ score = max(0, 100 - (len(high_issues) * 20) - (len(med_issues) * 10))
65
+ passed = len(high_issues) == 0 and score >= 80
66
+
67
+ return {
68
+ "file": file_name,
69
+ "score": score,
70
+ "passed": passed,
71
+ "total_issues": len(issues),
72
+ "issues": issues,
73
+ "timestamp": "2026-09-02T06:00:00Z"
74
+ }
75
+
76
+ def main():
77
+ parser = argparse.ArgumentParser(description="TidyFactor Marketing Copy Auditor")
78
+ parser.add_argument("target", nargs="?", help="Path to copy file or markdown script")
79
+ parser.add_argument("--text", help="Direct copy string to audit")
80
+ parser.add_argument("--json", action="store_true", help="Output pure JSON format")
81
+
82
+ args = parser.parse_args()
83
+
84
+ if args.text:
85
+ content = args.text
86
+ filename = "string-input"
87
+ elif args.target and Path(args.target).exists():
88
+ target_path = Path(args.target)
89
+ content = target_path.read_text(encoding="utf-8", errors="replace")
90
+ filename = str(target_path)
91
+ else:
92
+ # Default sample check
93
+ content = "ููŠ ุนุงู„ู…ู†ุง ุงู„ูŠูˆู… ุงู„ู…ุชุณุงุฑุนุŒ ู†ู‚ุฏู… ู„ูƒู… ุจูƒู„ ูุฎุฑ ุงู„ุญู„ ุงู„ุณุญุฑูŠ ู„ุชุบูŠูŠุฑ ู‚ูˆุงุนุฏ ุงู„ู„ุนุจุฉ."
94
+ filename = "demo-sample"
95
+
96
+ result = audit_text_content(content, filename)
97
+
98
+ if args.json:
99
+ print(json.dumps(result, indent=2, ensure_ascii=False))
100
+ else:
101
+ status_str = "[PASS]" if result["passed"] else "[FAIL]"
102
+ print(f"\n{status_str} Marketing Copy Quality Audit โ€” Score: {result['score']}/100")
103
+ print(f"Target: {result['file']}")
104
+ print(f"Issues Found: {result['total_issues']}\n")
105
+ for iss in result["issues"]:
106
+ print(f" - [Line {iss.get('line', '?')}] [{iss['severity'].upper()}] {iss['message']}")
107
+ print()
108
+
109
+ sys.exit(0 if result["passed"] else 1)
110
+
111
+ if __name__ == "__main__":
112
+ main()
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ TidyFactor Marketing Promotion & Margin Protection Calculator
4
+ Calculates break-even ROAS, gross margin impact, and discount thresholds.
5
+ """
6
+
7
+ import sys
8
+ import json
9
+ import argparse
10
+
11
+ # Ensure UTF-8 output on Windows console
12
+ if sys.stdout and hasattr(sys.stdout, "reconfigure"):
13
+ sys.stdout.reconfigure(encoding="utf-8", errors="replace")
14
+ if sys.stderr and hasattr(sys.stderr, "reconfigure"):
15
+ sys.stderr.reconfigure(encoding="utf-8", errors="replace")
16
+
17
+ def calculate_promo_metrics(cogs: float, price: float, discount_percent: float, ad_spend_per_order: float = 0.0) -> dict:
18
+ if price <= 0:
19
+ raise ValueError("Price must be greater than 0")
20
+
21
+ discount_amount = price * (discount_percent / 100.0)
22
+ discounted_price = price - discount_amount
23
+ gross_profit = discounted_price - cogs - ad_spend_per_order
24
+ gross_margin_percent = (gross_profit / discounted_price) * 100.0 if discounted_price > 0 else 0.0
25
+
26
+ # Break-even ROAS = 1 / Gross Margin before ads
27
+ margin_before_ads = (discounted_price - cogs) / discounted_price if discounted_price > 0 else 0.0
28
+ breakeven_roas = (1.0 / margin_before_ads) if margin_before_ads > 0 else 0.0
29
+
30
+ is_margin_safe = gross_margin_percent >= 30.0 and gross_profit > 0
31
+
32
+ return {
33
+ "original_price": round(price, 2),
34
+ "discount_percent": round(discount_percent, 2),
35
+ "discount_amount": round(discount_amount, 2),
36
+ "discounted_price": round(discounted_price, 2),
37
+ "cogs": round(cogs, 2),
38
+ "ad_spend_per_order": round(ad_spend_per_order, 2),
39
+ "net_gross_profit": round(gross_profit, 2),
40
+ "net_gross_margin_percent": round(gross_margin_percent, 2),
41
+ "breakeven_roas": round(breakeven_roas, 2),
42
+ "is_margin_safe": is_margin_safe,
43
+ "recommendation": "SAFE_TO_RUN" if is_margin_safe else "HIGH_RISK_MARGIN_COMPRESSION"
44
+ }
45
+
46
+ def main():
47
+ parser = argparse.ArgumentParser(description="TidyFactor Margin & Promo Calculator")
48
+ parser.add_argument("--price", type=float, default=100.0, help="Original product price")
49
+ parser.add_argument("--cogs", type=float, default=30.0, help="Cost of Goods Sold (COGS)")
50
+ parser.add_argument("--discount", type=float, default=20.0, help="Discount percentage (e.g. 20 for 20%)")
51
+ parser.add_argument("--cac", type=float, default=15.0, help="Estimated ad spend / CAC per order")
52
+ parser.add_argument("--json", action="store_true", help="Output pure JSON")
53
+
54
+ args = parser.parse_args()
55
+
56
+ result = calculate_promo_metrics(args.cogs, args.price, args.discount, args.cac)
57
+
58
+ if args.json:
59
+ print(json.dumps(result, indent=2))
60
+ else:
61
+ print("\n๐Ÿ’ฐ TidyFactor Margin & Promotion Math Report")
62
+ print(f" Price: ${result['original_price']} -> Discounted: ${result['discounted_price']} (-{result['discount_percent']}%)")
63
+ print(f" COGS: ${result['cogs']} | Est. CAC: ${result['ad_spend_per_order']}")
64
+ print(f" Net Gross Profit: ${result['net_gross_profit']} ({result['net_gross_margin_percent']}%)")
65
+ print(f" Break-Even ROAS Target: {result['breakeven_roas']}x")
66
+ print(f" Status: {result['recommendation']}\n")
67
+
68
+ if __name__ == "__main__":
69
+ main()
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ clean_orphaned_assets.py โ€” TidyFactor Asset & Folder Structure Hygiene Engine.
4
+ Detects and remediates:
5
+ 1. Binary duplicate image assets using SHA-256 hashing.
6
+ 2. Unreferenced orphan images in `assets/`.
7
+ 3. Advises WebP compression for raster assets > 50KB.
8
+ """
9
+
10
+ import os
11
+ import sys
12
+ import hashlib
13
+ import re
14
+ import argparse
15
+ from pathlib import Path
16
+
17
+ # Ensure UTF-8 output on Windows console
18
+ if sys.platform == "win32":
19
+ sys.stdout.reconfigure(encoding="utf-8")
20
+ sys.stderr.reconfigure(encoding="utf-8")
21
+
22
+ def compute_sha256(filepath: Path) -> str:
23
+ h = hashlib.sha256()
24
+ with open(filepath, "rb") as f:
25
+ while chunk := f.read(8192):
26
+ h.update(chunk)
27
+ return h.hexdigest()
28
+
29
+ def scan_assets(root: Path):
30
+ assets_dir = root / "assets"
31
+ if not assets_dir.exists():
32
+ print("[INFO] No assets/ directory found.")
33
+ return 0
34
+
35
+ image_extensions = {".png", ".jpg", ".jpeg", ".webp", ".svg", ".gif"}
36
+ asset_files = [p for p in assets_dir.iterdir() if p.is_file() and p.suffix.lower() in image_extensions]
37
+
38
+ # 1. SHA-256 Duplication Check
39
+ hashes = {}
40
+ duplicates = []
41
+ for asset in asset_files:
42
+ digest = compute_sha256(asset)
43
+ if digest in hashes:
44
+ duplicates.append((asset, hashes[digest]))
45
+ else:
46
+ hashes[digest] = asset
47
+
48
+ # 2. Markdown Reference Check
49
+ md_files = list(root.rglob("*.md")) + [root / "brand.yaml", root / "brand.json"]
50
+ all_content = ""
51
+ for md in md_files:
52
+ if "dist" in md.parts or ".git" in md.parts or "__pycache__" in md.parts:
53
+ continue
54
+ if md.exists():
55
+ all_content += md.read_text(encoding="utf-8", errors="ignore") + "\n"
56
+
57
+ orphans = []
58
+ for asset in asset_files:
59
+ # Match asset name in text
60
+ if asset.name not in all_content:
61
+ orphans.append(asset)
62
+
63
+ print("=" * 60)
64
+ print(" TIDYFACTOR MARKETING ASSET HYGIENE AUDIT")
65
+ print("=" * 60)
66
+ print(f"Total assets analyzed: {len(asset_files)}")
67
+
68
+ print(f"\n[1] Duplicate Asset Check (SHA-256):")
69
+ if duplicates:
70
+ print(f" [WARN] Found {len(duplicates)} duplicate asset(s):")
71
+ for dup, orig in duplicates:
72
+ print(f" - {dup.name} is identical to {orig.name}")
73
+ else:
74
+ print(" [OK] Zero binary duplicates found.")
75
+
76
+ print(f"\n[2] Orphan Asset Check:")
77
+ if orphans:
78
+ print(f" [WARN] Found {len(orphans)} unreferenced orphan asset(s):")
79
+ for orph in orphans:
80
+ print(f" - {orph.name} ({orph.stat().st_size / 1024:.1f} KB)")
81
+ else:
82
+ print(" [OK] Zero unreferenced orphan assets found.")
83
+
84
+ print(f"\n[3] Large Raster File Check (>50KB):")
85
+ large_rasters = [a for a in asset_files if a.suffix.lower() in {".png", ".jpg", ".jpeg"} and a.stat().st_size > 50 * 1024]
86
+ if large_rasters:
87
+ for lr in large_rasters:
88
+ print(f" [INFO] {lr.name}: {lr.stat().st_size / 1024:.1f} KB. Recommend WebP conversion for ~80% savings.")
89
+ else:
90
+ print(" [OK] All raster assets optimized or under 50KB.")
91
+
92
+ print("=" * 60)
93
+ return len(duplicates) + len(orphans)
94
+
95
+ def main():
96
+ parser = argparse.ArgumentParser(description="TidyFactor Asset Hygiene Engine")
97
+ parser.add_argument("--check", action="store_true", help="Run audit and return non-zero if issues exist")
98
+ args = parser.parse_args()
99
+
100
+ root = Path(__file__).resolve().parent.parent
101
+ issues_count = scan_assets(root)
102
+
103
+ if args.check and issues_count > 0:
104
+ sys.exit(1)
105
+ sys.exit(0)
106
+
107
+ if __name__ == "__main__":
108
+ main()
@@ -0,0 +1,87 @@
1
+ # Test Scenarios: tidyfactor-marketing
2
+
3
+ Comprehensive evaluation scenarios validating deterministic command dispatch, Contextual Decision Layer auto-sensing, Arabic direct-response generation, margin math protection, and automated copy linting.
4
+
5
+ ---
6
+
7
+ ## Scenario 1: E-Commerce 72-Hour Flash Sale with Margin Guardrails (GCC / KSA ๐Ÿ‡ธ๐Ÿ‡ฆ)
8
+
9
+ ### Objective
10
+ Generate a margin-safe promotional strategy and high-urgency WhatsApp/Instagram copy for a Saudi Arabian DTC brand launching a 72-hour flash sale.
11
+
12
+ ### Inputs & Context
13
+ - **Product**: Leather Travel Bag
14
+ - **Price**: 400 SAR, **COGS**: 120 SAR, **Proposed Discount**: 25% (100 SAR off)
15
+ - **Target Market**: Saudi Arabia (Riyadh, Jeddah)
16
+ - **Channel**: WhatsApp Broadcast + Instagram Story Ads (9:16)
17
+
18
+ ### Expected Execution & Checks
19
+ 1. **Margin Safety Gate**: `calc_promo_math.py` confirms:
20
+ - Discounted Price: 300 SAR
21
+ - Net Gross Margin: 60% (>30% threshold)
22
+ - Status: `SAFE_TO_RUN`
23
+ 2. **Copy Generation**:
24
+ - High-urgency hook without slop (`"ุฃุทู„ู‚ ุงู„ุนู†ุงู†"` โŒ forbidden).
25
+ - Trust and payment framing: Mada, Tabby, Tamara 4-installment split.
26
+ - 7-axis pre-emit critique stamp included.
27
+
28
+ ---
29
+
30
+ ## Scenario 2: B2B Multi-Tenant SaaS Phased Launch (Global / English)
31
+
32
+ ### Objective
33
+ Formulate a complete T-30 to T+14 launch sequence, positioning statement, and competitive differentiation for an AI agent observability tool.
34
+
35
+ ### Inputs & Context
36
+ - **Product**: AgentTrace (Observability for AI Coding Agents)
37
+ - **Pricing**: $49/seat/month
38
+ - **Primary Moat**: Zero-runtime latency, SQLite-native trace indexing.
39
+
40
+ ### Expected Execution & Checks
41
+ 1. **Positioning Matrix**: Formulates statement: *For [engineering leaders] who [struggle with invisible agent regressions], [AgentTrace] is an [observability engine] that [indexes traces locally in SQLite with 0ms runtime overhead] unlike [Datadog/LangSmith]*.
42
+ 2. **Phased Roadmap**:
43
+ - T-30 to T-15: Technical teardown blogs and waitlist alpha.
44
+ - T-14 to T-1: Private beta with 50 design partners.
45
+ - T-0: Product Hunt, Hacker News Show HN, and Twitter thread.
46
+ - T+1 to T+14: Onboarding case studies and customer referral loop.
47
+ 3. **Checklist Validation**: Workflow satisfies 100% of `references/workflows/campaign-launch.md` checklist.
48
+
49
+ ---
50
+
51
+ ## Scenario 3: 3-Stage Abandoned Cart Recovery Sequence (Egypt ๐Ÿ‡ช๐Ÿ‡ฌ)
52
+
53
+ ### Objective
54
+ Build a culturally calibrated 3-email abandoned cart recovery flow for an Egyptian fashion brand utilizing local payment incentives (InstaPay, Cash on Delivery).
55
+
56
+ ### Inputs & Context
57
+ - **Market**: Egypt (Cairo, Alexandria)
58
+ - **Currency**: EGP
59
+ - **Average Order Value**: 850 EGP
60
+ - **Tone**: Friendly, relatable, solution-oriented Egyptian Arabic.
61
+
62
+ ### Expected Execution & Checks
63
+ 1. **Flow Structure**:
64
+ - Email 1 (1 hour post-abandonment): Gentle reminder, photo of cart items, customer service WhatsApp link.
65
+ - Email 2 (24 hours post-abandonment): Overcoming objections, sizing guide, InstaPay instant discount.
66
+ - Email 3 (48 hours post-abandonment): Final urgency notice, reserving items for 12 hours.
67
+ 2. **Quality Bar**: Free of generic translation artifacts; utilizes authentic Egyptian phrasing with clear CTAs.
68
+
69
+ ---
70
+
71
+ ## Scenario 4: Direct-Response Ad Copy Multi-Angle Audit
72
+
73
+ ### Objective
74
+ Generate 3 distinct psychological ad copy angles (Pain, ROI, Proof) and verify zero AI marketing clichรฉs via automated linter.
75
+
76
+ ### Inputs & Context
77
+ - **Offer**: Fast-track web performance audit service.
78
+ - **Audience**: Agency owners and e-commerce founders.
79
+
80
+ ### Expected Execution & Checks
81
+ 1. **Angles Emitted**:
82
+ - Angle 1 (Pain): Frustration of paying high Meta ad spend while 60% bounce on slow mobile pages.
83
+ - Angle 2 (ROI/Logic): Every 100ms speed improvement raises conversion rate by 1.1%, recovering lost ad spend.
84
+ - Angle 3 (Social Proof): Before/after case study showing Lighthouse score 34 โ†’ 98 and 2.4x ROAS increase.
85
+ 2. **Linter Execution**:
86
+ - Runs `python scripts/audit_copy.py target.md --json`.
87
+ - Result: `passed: true`, `score: 100`, zero banned clichรฉs detected.
@@ -28,10 +28,14 @@ const OUT_FILE =
28
28
  const ROOT_COPIES = [
29
29
  "SKILL.md",
30
30
  "references",
31
+ "scripts",
32
+ "manifest.json",
31
33
  "tools",
32
34
  "bin",
33
35
  "assets",
36
+ "brand.yaml",
34
37
  "brand.json",
38
+ "tests",
35
39
  ".tidyfactor",
36
40
  "package.json",
37
41
  "AGENTS.md",