diff --git a/c-level-advisor/coo-advisor/scripts/ops_efficiency_analyzer.py b/c-level-advisor/coo-advisor/scripts/ops_efficiency_analyzer.py index 0732c53..1dfb005 100644 --- a/c-level-advisor/coo-advisor/scripts/ops_efficiency_analyzer.py +++ b/c-level-advisor/coo-advisor/scripts/ops_efficiency_analyzer.py @@ -18,7 +18,7 @@ import sys import argparse import math from datetime import datetime -from typing import Any +from typing import Any, Optional # --------------------------------------------------------------------------- @@ -458,7 +458,7 @@ def _dept_revenue_benchmark(dept_name: str, stage: str) -> int: return stage_data.get(dept_key, stage_data["default"]) -def _efficiency_status(efficiency_pct: float | None) -> str: +def _efficiency_status(efficiency_pct: Optional[float]) -> str: if efficiency_pct is None: return "N/A" if efficiency_pct >= 90: diff --git a/c-level-advisor/cto-advisor/scripts/team_scaling_calculator.py b/c-level-advisor/cto-advisor/scripts/team_scaling_calculator.py index 22a9bd5..6684225 100644 --- a/c-level-advisor/cto-advisor/scripts/team_scaling_calculator.py +++ b/c-level-advisor/cto-advisor/scripts/team_scaling_calculator.py @@ -323,8 +323,30 @@ class TeamScalingCalculator: 'designer': 120000, 'data_engineer': 140000 }, - 'EU': {k: v * 0.8 for k, v in salary_bands.get('US', {}).items()}, - 'APAC': {k: v * 0.6 for k, v in salary_bands.get('US', {}).items()} + 'EU': { + 'engineering_manager': 160000, + 'tech_lead': 144000, + 'senior_engineer': 128000, + 'mid_engineer': 96000, + 'junior_engineer': 68000, + 'devops': 120000, + 'qa': 80000, + 'product_manager': 120000, + 'designer': 96000, + 'data_engineer': 112000 + }, + 'APAC': { + 'engineering_manager': 120000, + 'tech_lead': 108000, + 'senior_engineer': 96000, + 'mid_engineer': 72000, + 'junior_engineer': 51000, + 'devops': 90000, + 'qa': 60000, + 'product_manager': 90000, + 'designer': 72000, + 'data_engineer': 84000 + } } location_salaries = salary_bands.get(location, salary_bands['US']) @@ -493,24 +515,48 @@ def calculate_team_scaling(current_state: Dict, growth_targets: Dict) -> str: return '\n'.join(output) if __name__ == "__main__": - # Example usage - example_current = { - 'headcount': 25, - 'velocity': 450, - 'roles': { - 'engineering_manager': 2, - 'tech_lead': 3, - 'senior_engineer': 8, - 'mid_engineer': 10, - 'junior_engineer': 2 - }, - 'attrition_rate': 12, - 'location': 'US' - } - - example_targets = { - 'target_headcount': 75, - 'timeline_quarters': 4 - } - - print(calculate_team_scaling(example_current, example_targets)) + import argparse + + parser = argparse.ArgumentParser( + description="Engineering Team Scaling Calculator - Optimize team growth and structure" + ) + parser.add_argument( + "input_file", nargs="?", default=None, + help="JSON file with current_state and growth_targets (default: run with sample data)" + ) + parser.add_argument( + "--json", action="store_true", + help="Output raw JSON instead of formatted report" + ) + args = parser.parse_args() + + if args.input_file: + with open(args.input_file) as f: + data = json.load(f) + current_state = data["current_state"] + growth_targets = data["growth_targets"] + else: + current_state = { + 'headcount': 25, + 'velocity': 450, + 'roles': { + 'engineering_manager': 2, + 'tech_lead': 3, + 'senior_engineer': 8, + 'mid_engineer': 10, + 'junior_engineer': 2 + }, + 'attrition_rate': 12, + 'location': 'US' + } + growth_targets = { + 'target_headcount': 75, + 'timeline_quarters': 4 + } + + if args.json: + calculator = TeamScalingCalculator() + results = calculator.calculate_scaling_plan(current_state, growth_targets) + print(json.dumps(results, indent=2)) + else: + print(calculate_team_scaling(current_state, growth_targets)) diff --git a/commands/tech-debt.md b/commands/tech-debt.md index 9fe0cab..042300a 100644 --- a/commands/tech-debt.md +++ b/commands/tech-debt.md @@ -1,6 +1,6 @@ --- name: tech-debt -description: Score, track, and prioritize technical debt. Usage: /tech-debt [options] +description: Scan, prioritize, and report technical debt. Usage: /tech-debt [options] --- # /tech-debt diff --git a/engineering-team/code-reviewer/scripts/pr_analyzer.py b/engineering-team/code-reviewer/scripts/pr_analyzer.py index 4cfd1b5..2678043 100755 --- a/engineering-team/code-reviewer/scripts/pr_analyzer.py +++ b/engineering-team/code-reviewer/scripts/pr_analyzer.py @@ -455,7 +455,7 @@ def main(): help="Base branch for comparison (default: main)" ) parser.add_argument( - "--head", "-h", + "--head", default="HEAD", help="Head branch/commit for comparison (default: HEAD)" ) diff --git a/engineering-team/senior-data-engineer/scripts/pipeline_orchestrator.py b/engineering-team/senior-data-engineer/scripts/pipeline_orchestrator.py index e5cbda9..1932fc5 100755 --- a/engineering-team/senior-data-engineer/scripts/pipeline_orchestrator.py +++ b/engineering-team/senior-data-engineer/scripts/pipeline_orchestrator.py @@ -15,7 +15,11 @@ Usage: import os import sys import json -import yaml +try: + import yaml + HAS_YAML = True +except ImportError: + HAS_YAML = False import logging import argparse from pathlib import Path @@ -774,7 +778,10 @@ Examples: # Load config if provided if args.config: with open(args.config) as f: - config_data = yaml.safe_load(f) + if HAS_YAML: + config_data = yaml.safe_load(f) + else: + config_data = json.load(f) config = PipelineConfig(**config_data) else: # Build config from arguments diff --git a/engineering/skill-tester/scripts/quality_scorer.py b/engineering/skill-tester/scripts/quality_scorer.py index 29f4ea8..e687a58 100644 --- a/engineering/skill-tester/scripts/quality_scorer.py +++ b/engineering/skill-tester/scripts/quality_scorer.py @@ -23,7 +23,22 @@ import sys from datetime import datetime from pathlib import Path from typing import Dict, List, Any, Optional, Tuple -import yaml +try: + import yaml +except ImportError: + # Minimal YAML subset: parse simple key: value frontmatter without pyyaml + class _YamlStub: + class YAMLError(Exception): + pass + @staticmethod + def safe_load(text): + result = {} + for line in text.strip().splitlines(): + if ':' in line: + key, _, value = line.partition(':') + result[key.strip()] = value.strip() + return result if result else None + yaml = _YamlStub() class QualityDimension: diff --git a/engineering/skill-tester/scripts/skill_validator.py b/engineering/skill-tester/scripts/skill_validator.py index b42ff22..53d93bd 100644 --- a/engineering/skill-tester/scripts/skill_validator.py +++ b/engineering/skill-tester/scripts/skill_validator.py @@ -19,7 +19,22 @@ import ast import json import re import sys -import yaml +try: + import yaml +except ImportError: + # Minimal YAML subset: parse simple key: value frontmatter without pyyaml + class _YamlStub: + class YAMLError(Exception): + pass + @staticmethod + def safe_load(text): + result = {} + for line in text.strip().splitlines(): + if ':' in line: + key, _, value = line.partition(':') + result[key.strip()] = value.strip() + return result if result else None + yaml = _YamlStub() import datetime as dt from pathlib import Path from typing import Dict, List, Any, Optional, Tuple diff --git a/marketing-skill/ad-creative/scripts/ad_copy_validator.py b/marketing-skill/ad-creative/scripts/ad_copy_validator.py index a6c7485..81101d0 100644 --- a/marketing-skill/ad-creative/scripts/ad_copy_validator.py +++ b/marketing-skill/ad-creative/scripts/ad_copy_validator.py @@ -416,12 +416,25 @@ SAMPLE_ADS = [ # --------------------------------------------------------------------------- def main(): + import argparse + + parser = argparse.ArgumentParser( + description="Validates ad copy against platform specs. " + "Checks character counts, rejection triggers, and scores each ad 0-100." + ) + parser.add_argument( + "file", nargs="?", default=None, + help="Path to a JSON file containing ad data. " + "If omitted, reads from stdin or runs embedded sample." + ) + args = parser.parse_args() + # Load from file or stdin, else use sample ads = None - if len(sys.argv) > 1: + if args.file: try: - with open(sys.argv[1]) as f: + with open(args.file) as f: data = json.load(f) ads = data if isinstance(data, list) else [data] except Exception as e: diff --git a/marketing-skill/analytics-tracking/scripts/tracking_plan_generator.py b/marketing-skill/analytics-tracking/scripts/tracking_plan_generator.py index 7bb6994..e734922 100644 --- a/marketing-skill/analytics-tracking/scripts/tracking_plan_generator.py +++ b/marketing-skill/analytics-tracking/scripts/tracking_plan_generator.py @@ -352,18 +352,33 @@ def print_report(result, inputs): def main(): - if len(sys.argv) > 1 and sys.argv[1] != "--json": - with open(sys.argv[1]) as f: + import argparse + + parser = argparse.ArgumentParser( + description="Tracking plan generator — produces event taxonomy, GTM config, and GA4 dimension recommendations." + ) + parser.add_argument( + "input_file", nargs="?", default=None, + help="JSON file with business config (default: run with sample SaaS data)" + ) + parser.add_argument( + "--json", action="store_true", + help="Output full config as JSON" + ) + args = parser.parse_args() + + if args.input_file: + with open(args.input_file) as f: inputs = json.load(f) else: - if "--json" not in sys.argv: + if not args.json: print("No input file provided. Running with sample data...\n") inputs = SAMPLE_INPUT result = generate_tracking_plan(inputs) print_report(result, inputs) - if "--json" in sys.argv: + if args.json: print(json.dumps(result, indent=2)) diff --git a/marketing-skill/churn-prevention/scripts/churn_impact_calculator.py b/marketing-skill/churn-prevention/scripts/churn_impact_calculator.py index ecd64c2..0861952 100644 --- a/marketing-skill/churn-prevention/scripts/churn_impact_calculator.py +++ b/marketing-skill/churn-prevention/scripts/churn_impact_calculator.py @@ -164,8 +164,23 @@ def print_report(result): def main(): - if len(sys.argv) > 1: - with open(sys.argv[1]) as f: + import argparse + + parser = argparse.ArgumentParser( + description="Churn impact calculator — models revenue impact of churn reduction improvements." + ) + parser.add_argument( + "input_file", nargs="?", default=None, + help="JSON file with churn metrics (default: run with sample data)" + ) + parser.add_argument( + "--json", action="store_true", + help="Output results as JSON" + ) + args = parser.parse_args() + + if args.input_file: + with open(args.input_file) as f: inputs = json.load(f) else: print("No input file provided. Running with sample data...\n") @@ -176,8 +191,7 @@ def main(): result = calculate(inputs) print_report(result) - # Also dump JSON for programmatic use - if "--json" in sys.argv: + if args.json: print(json.dumps(result, indent=2)) diff --git a/marketing-skill/cold-email/scripts/email_sequence_analyzer.py b/marketing-skill/cold-email/scripts/email_sequence_analyzer.py index 7717a6c..8fe8570 100644 --- a/marketing-skill/cold-email/scripts/email_sequence_analyzer.py +++ b/marketing-skill/cold-email/scripts/email_sequence_analyzer.py @@ -439,16 +439,29 @@ SAMPLE_SEQUENCE = [ # ─── Main ───────────────────────────────────────────────────────────────────── def main(): - if len(sys.argv) > 1: - arg = sys.argv[1] - if arg == "-": + import argparse + + parser = argparse.ArgumentParser( + description="Analyzes a cold email sequence for quality signals. " + "Evaluates word count, reading level, personalization, CTA clarity, " + "spam triggers, and subject lines. Scores each email 0-100." + ) + parser.add_argument( + "file", nargs="?", default=None, + help="Path to a JSON file containing the email sequence. " + "Use '-' to read from stdin. If omitted, runs embedded sample." + ) + args = parser.parse_args() + + if args.file: + if args.file == "-": sequence = json.load(sys.stdin) else: try: - with open(arg, "r", encoding="utf-8") as f: + with open(args.file, "r", encoding="utf-8") as f: sequence = json.load(f) except FileNotFoundError: - print(f"Error: File not found: {arg}", file=sys.stderr) + print(f"Error: File not found: {args.file}", file=sys.stderr) sys.exit(1) except json.JSONDecodeError as e: print(f"Error: Invalid JSON: {e}", file=sys.stderr) diff --git a/marketing-skill/content-humanizer/scripts/humanizer_scorer.py b/marketing-skill/content-humanizer/scripts/humanizer_scorer.py index 55d52a3..ac00977 100644 --- a/marketing-skill/content-humanizer/scripts/humanizer_scorer.py +++ b/marketing-skill/content-humanizer/scripts/humanizer_scorer.py @@ -448,7 +448,25 @@ def print_report(result: dict, label: str = "") -> None: def main(): - if len(sys.argv) == 1: + import argparse + + parser = argparse.ArgumentParser( + description="Scores content 0-100 on 'humanity' by detecting AI writing patterns. " + "Checks AI vocabulary, sentence variance, passive voice, hedging, " + "em-dash overuse, and paragraph variety." + ) + parser.add_argument( + "file", nargs="?", default=None, + help="Path to a text file to analyze. If omitted, runs demo comparing " + "human vs AI sample content." + ) + parser.add_argument( + "--json", action="store_true", + help="Also output results as JSON." + ) + args = parser.parse_args() + + if args.file is None: # Demo mode: compare human vs AI sample print("[Demo mode — comparing human vs AI sample content]") print() @@ -468,18 +486,17 @@ def main(): print(f" Difference: {r1['humanity_score'] - r2['humanity_score']} points") print() else: - filepath = sys.argv[1] try: - with open(filepath, 'r', encoding='utf-8') as f: + with open(args.file, 'r', encoding='utf-8') as f: text = f.read() except FileNotFoundError: - print(f"Error: file not found: {filepath}", file=sys.stderr) + print(f"Error: file not found: {args.file}", file=sys.stderr) sys.exit(1) result = score_humanity(text) - print_report(result, filepath) + print_report(result, args.file) - if "--json" in sys.argv: + if args.json: print(json.dumps(result, indent=2)) diff --git a/marketing-skill/content-production/scripts/brand_voice_analyzer.py b/marketing-skill/content-production/scripts/brand_voice_analyzer.py index 92ab6f7..074efda 100644 --- a/marketing-skill/content-production/scripts/brand_voice_analyzer.py +++ b/marketing-skill/content-production/scripts/brand_voice_analyzer.py @@ -174,12 +174,24 @@ def analyze_content(content: str, output_format: str = 'json') -> str: if __name__ == "__main__": import sys - - if len(sys.argv) > 1: - with open(sys.argv[1], 'r') as f: + import argparse + + parser = argparse.ArgumentParser( + description="Brand Voice Analyzer - Analyzes content to establish and maintain brand voice consistency" + ) + parser.add_argument( + "file", nargs="?", default=None, + help="Text file to analyze" + ) + parser.add_argument( + "--format", choices=["json", "text"], default="text", + help="Output format (default: text)" + ) + args = parser.parse_args() + + if args.file: + with open(args.file, 'r') as f: content = f.read() - - output_format = sys.argv[2] if len(sys.argv) > 2 else 'text' - print(analyze_content(content, output_format)) + print(analyze_content(content, args.format)) else: - print("Usage: python brand_voice_analyzer.py [json|text]") + print("Usage: python brand_voice_analyzer.py [--format json|text]") diff --git a/marketing-skill/content-production/scripts/content_scorer.py b/marketing-skill/content-production/scripts/content_scorer.py index f87fbf0..58f045e 100644 --- a/marketing-skill/content-production/scripts/content_scorer.py +++ b/marketing-skill/content-production/scripts/content_scorer.py @@ -401,11 +401,31 @@ def print_report(result: dict, title: str, keyword: str) -> None: def main(): + import argparse + + parser = argparse.ArgumentParser( + description="Scores content 0-100 on readability, SEO, structure, and engagement." + ) + parser.add_argument( + "file", nargs="?", default=None, + help="Path to a text/markdown file to analyze. If omitted, runs demo " + "with embedded sample content." + ) + parser.add_argument( + "keyword", nargs="?", default="", + help="Target SEO keyword to check density and placement." + ) + parser.add_argument( + "--json", action="store_true", + help="Also output results as JSON." + ) + args = parser.parse_args() + title = "" - keyword = "" + keyword = args.keyword text = "" - if len(sys.argv) == 1: + if args.file is None: # Demo mode — use embedded sample print("[Demo mode — using embedded sample content]") text = SAMPLE_CONTENT @@ -413,13 +433,11 @@ def main(): keyword = SAMPLE_KEYWORD else: # Read from file - filepath = sys.argv[1] - keyword = sys.argv[2] if len(sys.argv) > 2 else "" try: - with open(filepath, 'r', encoding='utf-8') as f: + with open(args.file, 'r', encoding='utf-8') as f: text = f.read() except FileNotFoundError: - print(f"Error: file not found: {filepath}", file=sys.stderr) + print(f"Error: file not found: {args.file}", file=sys.stderr) sys.exit(1) # Extract title from first H1 or first line @@ -438,7 +456,7 @@ def main(): print_report(result, title, keyword) # JSON output for programmatic use - if "--json" in sys.argv: + if args.json: print(json.dumps(result, indent=2)) diff --git a/marketing-skill/content-production/scripts/seo_optimizer.py b/marketing-skill/content-production/scripts/seo_optimizer.py index 8e77aee..c33931a 100644 --- a/marketing-skill/content-production/scripts/seo_optimizer.py +++ b/marketing-skill/content-production/scripts/seo_optimizer.py @@ -406,14 +406,28 @@ def optimize_content(content: str, keyword: str = None, if __name__ == "__main__": import sys - - if len(sys.argv) > 1: - with open(sys.argv[1], 'r') as f: + import argparse + + parser = argparse.ArgumentParser( + description="SEO Content Optimizer - Analyzes and optimizes content for SEO" + ) + parser.add_argument( + "file", nargs="?", default=None, + help="Text file to analyze" + ) + parser.add_argument( + "--keyword", "-k", default=None, + help="Primary keyword to optimize for" + ) + parser.add_argument( + "--secondary", "-s", default=None, + help="Comma-separated secondary keywords" + ) + args = parser.parse_args() + + if args.file: + with open(args.file, 'r') as f: content = f.read() - - keyword = sys.argv[2] if len(sys.argv) > 2 else None - secondary = sys.argv[3] if len(sys.argv) > 3 else None - - print(optimize_content(content, keyword, secondary)) + print(optimize_content(content, args.keyword, args.secondary)) else: - print("Usage: python seo_optimizer.py [primary_keyword] [secondary_keywords]") + print("Usage: python seo_optimizer.py [--keyword primary] [--secondary kw1,kw2]") diff --git a/marketing-skill/free-tool-strategy/scripts/tool_roi_estimator.py b/marketing-skill/free-tool-strategy/scripts/tool_roi_estimator.py index e5271fe..adc895a 100644 --- a/marketing-skill/free-tool-strategy/scripts/tool_roi_estimator.py +++ b/marketing-skill/free-tool-strategy/scripts/tool_roi_estimator.py @@ -330,11 +330,25 @@ DEFAULT_PARAMS = { # --------------------------------------------------------------------------- def main(): + import argparse + + parser = argparse.ArgumentParser( + description="Estimates ROI of building a free marketing tool. " + "Models return given build cost, maintenance, traffic, " + "conversion rate, and lead value." + ) + parser.add_argument( + "file", nargs="?", default=None, + help="Path to a JSON file with tool parameters. " + "If omitted, reads from stdin or runs embedded sample." + ) + args = parser.parse_args() + params = None - if len(sys.argv) > 1: + if args.file: try: - with open(sys.argv[1]) as f: + with open(args.file) as f: params = json.load(f) except Exception as e: print(f"Error reading file: {e}", file=sys.stderr) diff --git a/marketing-skill/marketing-context/scripts/context_validator.py b/marketing-skill/marketing-context/scripts/context_validator.py index 1394f3c..8952b83 100644 --- a/marketing-skill/marketing-context/scripts/context_validator.py +++ b/marketing-skill/marketing-context/scripts/context_validator.py @@ -123,8 +123,25 @@ def print_report(results: dict): def main(): - if len(sys.argv) > 1: - filepath = Path(sys.argv[1]) + import argparse + + parser = argparse.ArgumentParser( + description="Validates marketing context completeness. " + "Scores 0-100 based on required and optional section coverage." + ) + parser.add_argument( + "file", nargs="?", default=None, + help="Path to a marketing context markdown file. " + "If omitted, runs demo with embedded sample data." + ) + parser.add_argument( + "--json", action="store_true", + help="Also output results as JSON." + ) + args = parser.parse_args() + + if args.file: + filepath = Path(args.file) if not filepath.exists(): print(f"Error: File not found: {filepath}", file=sys.stderr) sys.exit(1) @@ -194,7 +211,7 @@ def main(): results = validate_context(content) print_report(results) - if "--json" in sys.argv: + if args.json: print(f"\n{json.dumps(results, indent=2)}") diff --git a/marketing-skill/marketing-ops/scripts/campaign_tracker.py b/marketing-skill/marketing-ops/scripts/campaign_tracker.py index 66dc0dd..e99edf2 100644 --- a/marketing-skill/marketing-ops/scripts/campaign_tracker.py +++ b/marketing-skill/marketing-ops/scripts/campaign_tracker.py @@ -119,8 +119,23 @@ def print_report(analysis: dict): def main(): - if len(sys.argv) > 1: - filepath = Path(sys.argv[1]) + import argparse + + parser = argparse.ArgumentParser( + description="Track campaign status across marketing skills — tasks, owners, deadlines." + ) + parser.add_argument( + "input_file", nargs="?", default=None, + help="JSON file with campaign data (default: run with sample data)" + ) + parser.add_argument( + "--json", action="store_true", + help="Also output results as JSON" + ) + args = parser.parse_args() + + if args.input_file: + filepath = Path(args.input_file) if filepath.exists(): campaign = json.loads(filepath.read_text()) else: @@ -133,7 +148,7 @@ def main(): analysis = analyze_campaign(campaign) print_report(analysis) - if "--json" in sys.argv: + if args.json: print(f"\n{json.dumps(analysis, indent=2)}") diff --git a/marketing-skill/pricing-strategy/scripts/pricing_modeler.py b/marketing-skill/pricing-strategy/scripts/pricing_modeler.py index 89f18ae..ece1342 100644 --- a/marketing-skill/pricing-strategy/scripts/pricing_modeler.py +++ b/marketing-skill/pricing-strategy/scripts/pricing_modeler.py @@ -207,11 +207,26 @@ def print_report(result, inputs): def main(): - if len(sys.argv) > 1 and sys.argv[1] != "--json": - with open(sys.argv[1]) as f: + import argparse + + parser = argparse.ArgumentParser( + description="Pricing modeler — projects revenue at different price points and recommends tier structure." + ) + parser.add_argument( + "input_file", nargs="?", default=None, + help="JSON file with pricing data (default: run with sample data)" + ) + parser.add_argument( + "--json", action="store_true", + help="Output results as JSON" + ) + args = parser.parse_args() + + if args.input_file: + with open(args.input_file) as f: inputs = json.load(f) else: - if "--json" not in sys.argv: + if not args.json: print("No input file provided. Running with sample data...\n") inputs = SAMPLE_INPUT @@ -260,7 +275,7 @@ def main(): print_report(result, inputs) - if "--json" in sys.argv: + if args.json: print(json.dumps(result, indent=2)) diff --git a/marketing-skill/referral-program/scripts/referral_roi_calculator.py b/marketing-skill/referral-program/scripts/referral_roi_calculator.py index 31325f3..431b0c2 100644 --- a/marketing-skill/referral-program/scripts/referral_roi_calculator.py +++ b/marketing-skill/referral-program/scripts/referral_roi_calculator.py @@ -353,11 +353,25 @@ def run(params): # --------------------------------------------------------------------------- def main(): + import argparse + + parser = argparse.ArgumentParser( + description="Calculates referral program ROI. " + "Models economics given LTV, CAC, referral rate, reward cost, " + "and conversion rate." + ) + parser.add_argument( + "file", nargs="?", default=None, + help="Path to a JSON file with referral program parameters. " + "If omitted, reads from stdin or runs embedded sample." + ) + args = parser.parse_args() + params = None - if len(sys.argv) > 1: + if args.file: try: - with open(sys.argv[1]) as f: + with open(args.file) as f: params = json.load(f) except Exception as e: print(f"Error reading file: {e}", file=sys.stderr) diff --git a/marketing-skill/schema-markup/scripts/schema_validator.py b/marketing-skill/schema-markup/scripts/schema_validator.py index ce334c3..b81a059 100644 --- a/marketing-skill/schema-markup/scripts/schema_validator.py +++ b/marketing-skill/schema-markup/scripts/schema_validator.py @@ -390,16 +390,28 @@ SAMPLE_HTML = """ # ─── Main ───────────────────────────────────────────────────────────────────── def main(): - if len(sys.argv) > 1: - arg = sys.argv[1] - if arg == "-": + import argparse + + parser = argparse.ArgumentParser( + description="Extracts and validates JSON-LD structured data from HTML. " + "Scores 0-100 per schema block based on required/recommended field coverage." + ) + parser.add_argument( + "file", nargs="?", default=None, + help="Path to an HTML file to validate. " + "Use '-' to read from stdin. If omitted, runs embedded sample." + ) + args = parser.parse_args() + + if args.file: + if args.file == "-": html = sys.stdin.read() else: try: - with open(arg, "r", encoding="utf-8") as f: + with open(args.file, "r", encoding="utf-8") as f: html = f.read() except FileNotFoundError: - print(f"Error: File not found: {arg}", file=sys.stderr) + print(f"Error: File not found: {args.file}", file=sys.stderr) sys.exit(1) else: print("No file provided — running on embedded sample HTML.\n") diff --git a/marketing-skill/site-architecture/scripts/sitemap_analyzer.py b/marketing-skill/site-architecture/scripts/sitemap_analyzer.py index 6b30c1f..b964062 100644 --- a/marketing-skill/site-architecture/scripts/sitemap_analyzer.py +++ b/marketing-skill/site-architecture/scripts/sitemap_analyzer.py @@ -328,12 +328,24 @@ def load_content(source: str) -> str: def main(): - if len(sys.argv) > 1: - arg = sys.argv[1] - if arg == "-": + import argparse + + parser = argparse.ArgumentParser( + description="Analyzes sitemap.xml files for structure, depth, and potential issues. " + "Reports depth distribution, URL patterns, orphan candidates, and duplicates." + ) + parser.add_argument( + "file", nargs="?", default=None, + help="Path to a sitemap.xml file or URL (https://...). " + "Use '-' to read from stdin. If omitted, runs embedded sample." + ) + args = parser.parse_args() + + if args.file: + if args.file == "-": content = sys.stdin.read() else: - content = load_content(arg) + content = load_content(args.file) else: print("No file or URL provided — running on embedded sample sitemap.\n") content = SAMPLE_SITEMAP diff --git a/product-team/product-manager-toolkit/scripts/customer_interview_analyzer.py b/product-team/product-manager-toolkit/scripts/customer_interview_analyzer.py index cd56a8d..5c9762f 100644 --- a/product-team/product-manager-toolkit/scripts/customer_interview_analyzer.py +++ b/product-team/product-manager-toolkit/scripts/customer_interview_analyzer.py @@ -412,8 +412,22 @@ def format_single_interview(analysis: Dict) -> str: def main(): import sys - - if len(sys.argv) < 2: + import argparse + + parser = argparse.ArgumentParser( + description="Customer Interview Analyzer - Extracts insights, patterns, and opportunities from user interviews" + ) + parser.add_argument( + "file", nargs="?", default=None, + help="Interview transcript text file to analyze" + ) + parser.add_argument( + "--json", action="store_true", + help="Output results as JSON" + ) + args = parser.parse_args() + + if not args.file: print("Usage: python customer_interview_analyzer.py ") print("\nThis tool analyzes customer interview transcripts to extract:") print(" - Pain points and frustrations") @@ -422,17 +436,14 @@ def main(): print(" - Sentiment analysis") print(" - Key themes and quotes") sys.exit(1) - - # Read interview transcript - with open(sys.argv[1], 'r') as f: + + with open(args.file, 'r') as f: interview_text = f.read() - - # Analyze + analyzer = InterviewAnalyzer() analysis = analyzer.analyze_interview(interview_text) - - # Output - if len(sys.argv) > 2 and sys.argv[2] == 'json': + + if args.json: print(json.dumps(analysis, indent=2)) else: print(format_single_interview(analysis)) diff --git a/product-team/saas-scaffolder/scripts/project_bootstrapper.py b/product-team/saas-scaffolder/scripts/project_bootstrapper.py index 7c64cad..6ddb587 100644 --- a/product-team/saas-scaffolder/scripts/project_bootstrapper.py +++ b/product-team/saas-scaffolder/scripts/project_bootstrapper.py @@ -267,6 +267,9 @@ def generate_docker_compose(config: Dict[str, Any]) -> str: compose["volumes"]["mongodata"] = {} # Manual YAML-like output (avoid pyyaml dependency) + nl = "\n" + depends_on = f" depends_on:{nl} - db" if db else "" + vol_line = " pgdata:" if db == "postgresql" else " mongodata:" if db == "mongodb" else " {}" return f"""version: '3.8' services: @@ -278,12 +281,12 @@ services: - .env volumes: - .:/app -{f' depends_on:\\n - db' if db else ''} +{depends_on} {generate_db_service(db)} {generate_redis_service(config)} volumes: -{f' pgdata:' if db == 'postgresql' else f' mongodata:' if db == 'mongodb' else ' {}'} +{vol_line} """ diff --git a/product-team/ui-design-system/scripts/design_token_generator.py b/product-team/ui-design-system/scripts/design_token_generator.py index 119508c..ddc7f30 100644 --- a/product-team/ui-design-system/scripts/design_token_generator.py +++ b/product-team/ui-design-system/scripts/design_token_generator.py @@ -547,33 +547,44 @@ class DesignTokenGenerator: def main(): import sys - + import argparse + + parser = argparse.ArgumentParser( + description="Design Token Generator - Creates consistent design system tokens for colors, typography, spacing, and more." + ) + parser.add_argument( + "brand_color", nargs="?", default="#0066CC", + help="Hex brand color (default: #0066CC)" + ) + parser.add_argument( + "--style", choices=["modern", "classic", "playful"], default="modern", + help="Design style (default: modern)" + ) + parser.add_argument( + "--format", choices=["json", "css", "scss", "summary"], default="json", + dest="output_format", + help="Output format (default: json)" + ) + args = parser.parse_args() + generator = DesignTokenGenerator() - - # Get parameters - brand_color = sys.argv[1] if len(sys.argv) > 1 else "#0066CC" - style = sys.argv[2] if len(sys.argv) > 2 else "modern" - output_format = sys.argv[3] if len(sys.argv) > 3 else "json" - - # Generate tokens - tokens = generator.generate_complete_system(brand_color, style) - - # Output - if output_format == 'summary': + tokens = generator.generate_complete_system(args.brand_color, args.style) + + if args.output_format == 'summary': print("=" * 60) print("DESIGN SYSTEM TOKENS") print("=" * 60) - print(f"\n🎨 Style: {style}") - print(f"🎨 Brand Color: {brand_color}") - print("\n📊 Generated Tokens:") - print(f" • Colors: {len(tokens['colors'])} palettes") - print(f" • Typography: {len(tokens['typography'])} categories") - print(f" • Spacing: {len(tokens['spacing'])} values") - print(f" • Shadows: {len(tokens['shadows'])} styles") - print(f" • Breakpoints: {len(tokens['breakpoints'])} sizes") - print("\n💾 Export formats available: json, css, scss") + print(f"\n Style: {args.style}") + print(f" Brand Color: {args.brand_color}") + print("\n Generated Tokens:") + print(f" - Colors: {len(tokens['colors'])} palettes") + print(f" - Typography: {len(tokens['typography'])} categories") + print(f" - Spacing: {len(tokens['spacing'])} values") + print(f" - Shadows: {len(tokens['shadows'])} styles") + print(f" - Breakpoints: {len(tokens['breakpoints'])} sizes") + print("\n Export formats available: json, css, scss") else: - print(generator.export_tokens(tokens, output_format)) + print(generator.export_tokens(tokens, args.output_format)) if __name__ == "__main__": main()