@tidyfactor/marketing 1.3.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.
- package/.tidyfactor +52 -0
- package/AGENTS.md +41 -0
- package/CHANGELOG.md +53 -0
- package/LICENSE +17 -0
- package/README.ar.md +299 -0
- package/README.de.md +44 -0
- package/README.es.md +44 -0
- package/README.fa.md +44 -0
- package/README.fr.md +44 -0
- package/README.md +320 -0
- package/README.pt.md +44 -0
- package/README.zh.md +44 -0
- package/SKILL-REGISTRY.md +36 -0
- package/SKILL.md +30 -0
- package/VISION.md +25 -0
- package/assets/hero-banner.png +0 -0
- package/assets/og-default.png +0 -0
- package/bin/add-skill.js +50 -0
- package/bin/create-kit.js +101 -0
- package/bin/remove-skill.js +24 -0
- package/brand.json +67 -0
- package/package.json +73 -0
- package/references/commands/advertising.md +27 -0
- package/references/commands/brief.md +17 -0
- package/references/commands/content.md +26 -0
- package/references/commands/email.md +26 -0
- package/references/commands/growth.md +27 -0
- package/references/commands/promotions.md +26 -0
- package/references/commands/social.md +27 -0
- package/references/commands/strategy.md +25 -0
- package/references/memory/ad-copy-templates.md +93 -0
- package/references/memory/arabic-writing.md +71 -0
- package/references/memory/decision-points.md +73 -0
- package/references/memory/frameworks.md +86 -0
- package/references/memory/lifecycle-flows.md +106 -0
- package/references/memory/metrics-benchmarks.md +70 -0
- package/references/memory/philosophy.md +16 -0
- package/references/memory/platform-specs.md +75 -0
- package/references/memory/promotions-math.md +56 -0
- package/references/memory/quality-bar.md +55 -0
- package/references/workflows/brief.md +72 -0
- package/references/workflows/campaign-launch.md +73 -0
- package/references/workflows/content-engine.md +68 -0
- package/references/workflows/email-lifecycle.md +55 -0
- package/references/workflows/paid-acquisition.md +66 -0
- package/references/workflows/promo-conversion.md +58 -0
- package/references/workflows/social-growth.md +65 -0
- package/references/workflows/viral-retention.md +63 -0
- package/tools/build-skill.js +206 -0
- package/tools/validate_skill.py +112 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
validate_skill.py — TidyFactor Marketing integrity and release validation script.
|
|
4
|
+
Verifies:
|
|
5
|
+
1. Version synchronization across .tidyfactor, package.json, brand.json, and CHANGELOG.md.
|
|
6
|
+
2. License consistency across files.
|
|
7
|
+
3. Link integrity between SKILL.md and referenced command/workflow/memory files.
|
|
8
|
+
4. Absence of hardcoded absolute machine paths in markdown files.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import sys
|
|
12
|
+
import os
|
|
13
|
+
import re
|
|
14
|
+
import json
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
ROOT = Path(__file__).resolve().parent.parent
|
|
18
|
+
|
|
19
|
+
# Set stdout/stderr encoding to UTF-8 on Windows
|
|
20
|
+
if sys.platform == "win32":
|
|
21
|
+
sys.stdout.reconfigure(encoding="utf-8")
|
|
22
|
+
sys.stderr.reconfigure(encoding="utf-8")
|
|
23
|
+
|
|
24
|
+
def validate():
|
|
25
|
+
failures = []
|
|
26
|
+
print("=" * 60)
|
|
27
|
+
print(" RUNNING TIDYFACTOR MARKETING RELEASE VALIDATION")
|
|
28
|
+
print("=" * 60)
|
|
29
|
+
|
|
30
|
+
# 1. Version Sync Check
|
|
31
|
+
print("\n[1] Checking SemVer synchronization across metadata...")
|
|
32
|
+
with open(ROOT / "package.json", "r", encoding="utf-8") as f:
|
|
33
|
+
pkg_ver = json.load(f).get("version")
|
|
34
|
+
with open(ROOT / ".tidyfactor", "r", encoding="utf-8") as f:
|
|
35
|
+
tf_ver = json.load(f).get("version")
|
|
36
|
+
with open(ROOT / "brand.json", "r", encoding="utf-8") as f:
|
|
37
|
+
brand_ver = json.load(f).get("version")
|
|
38
|
+
|
|
39
|
+
with open(ROOT / "CHANGELOG.md", "r", encoding="utf-8") as f:
|
|
40
|
+
changelog_content = f.read()
|
|
41
|
+
|
|
42
|
+
print(f" package.json : {pkg_ver}")
|
|
43
|
+
print(f" .tidyfactor : {tf_ver}")
|
|
44
|
+
print(f" brand.json : {brand_ver}")
|
|
45
|
+
|
|
46
|
+
if not (pkg_ver == tf_ver == brand_ver):
|
|
47
|
+
failures.append(f"Version mismatch: package.json({pkg_ver}) vs .tidyfactor({tf_ver}) vs brand.json({brand_ver})")
|
|
48
|
+
else:
|
|
49
|
+
print(f" [OK] Version {pkg_ver} synchronized across all JSON metadata.")
|
|
50
|
+
|
|
51
|
+
if f"## [{pkg_ver}]" not in changelog_content:
|
|
52
|
+
failures.append(f"CHANGELOG.md is missing release entry for version [{pkg_ver}].")
|
|
53
|
+
else:
|
|
54
|
+
print(f" [OK] CHANGELOG.md contains release entry for [{pkg_ver}].")
|
|
55
|
+
|
|
56
|
+
# 2. License Consistency Check
|
|
57
|
+
print("\n[2] Checking license consistency...")
|
|
58
|
+
with open(ROOT / "package.json", "r", encoding="utf-8") as f:
|
|
59
|
+
pkg_lic = json.load(f).get("license")
|
|
60
|
+
with open(ROOT / "README.md", "r", encoding="utf-8") as f:
|
|
61
|
+
readme_en = f.read()
|
|
62
|
+
with open(ROOT / "README.ar.md", "r", encoding="utf-8") as f:
|
|
63
|
+
readme_ar = f.read()
|
|
64
|
+
|
|
65
|
+
if "License-MIT" in readme_en or "License-MIT" in readme_ar:
|
|
66
|
+
failures.append("README contains MIT badge while package is licensed under Apache-2.0.")
|
|
67
|
+
else:
|
|
68
|
+
print(" [OK] License badges match Apache-2.0.")
|
|
69
|
+
|
|
70
|
+
# 3. Path reference and link checks from SKILL.md
|
|
71
|
+
print("\n[3] Checking SKILL.md referenced files exist on disk...")
|
|
72
|
+
with open(ROOT / "SKILL.md", "r", encoding="utf-8") as f:
|
|
73
|
+
skill_content = f.read()
|
|
74
|
+
|
|
75
|
+
# Find all references like references/commands/*.md, workflows/*.md, memory/*.md
|
|
76
|
+
refs = re.findall(r'(?:references/)?((?:commands|workflows|memory)/[a-zA-Z0-9_\-\.\*]+)', skill_content)
|
|
77
|
+
for ref in refs:
|
|
78
|
+
if "*" in ref:
|
|
79
|
+
continue
|
|
80
|
+
full_ref_path = ROOT / "references" / ref
|
|
81
|
+
if not full_ref_path.exists():
|
|
82
|
+
failures.append(f"Broken link in SKILL.md: references/{ref} does not exist on disk.")
|
|
83
|
+
else:
|
|
84
|
+
print(f" [OK] Found references/{ref}")
|
|
85
|
+
|
|
86
|
+
# 4. Check for personal/machine-specific absolute paths
|
|
87
|
+
print("\n[4] Auditing for leaked machine-specific absolute paths...")
|
|
88
|
+
leaked_path_pattern = re.compile(r'[a-zA-Z]:\\[wW]amp64\\', re.IGNORECASE)
|
|
89
|
+
for ext in ["*.md", "*.json", "*.js", "*.py"]:
|
|
90
|
+
for file_path in ROOT.rglob(ext):
|
|
91
|
+
if "dist" in file_path.parts or "__pycache__" in file_path.parts:
|
|
92
|
+
continue
|
|
93
|
+
with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
|
|
94
|
+
content = f.read()
|
|
95
|
+
if leaked_path_pattern.search(content):
|
|
96
|
+
rel = file_path.relative_to(ROOT)
|
|
97
|
+
failures.append(f"Leaked machine-specific absolute path found in {rel}")
|
|
98
|
+
|
|
99
|
+
print("\n" + "=" * 60)
|
|
100
|
+
if failures:
|
|
101
|
+
print(f"[FAIL] {len(failures)} validation error(s) found:")
|
|
102
|
+
for err in failures:
|
|
103
|
+
print(f" - {err}")
|
|
104
|
+
print("=" * 60)
|
|
105
|
+
sys.exit(1)
|
|
106
|
+
else:
|
|
107
|
+
print("[SUCCESS] ALL SKILL INTEGRITY CHECKS PASSED!")
|
|
108
|
+
print("=" * 60)
|
|
109
|
+
sys.exit(0)
|
|
110
|
+
|
|
111
|
+
if __name__ == "__main__":
|
|
112
|
+
validate()
|