Prompt Governance Category: Engineering Domain: AI Governance Overview The Prompt Governance skill provides tools for auditing prompts for security vulnerabilities, bias, and safety issues, plus managing a versioned catalog of approved prompts. Essential for organizations deploying LLM-based applications at scale. Quick Start Tools Overview | Tool | Purpose | Key Flags | |------|---------|-----------| | | Audit prompts for injection, bias, and safety | , , , | | | Manage versioned prompt catalog | , , , , | Workflows Prompt Review Process 1. Author writes or modifies a prompt 2. Run for autom…

, \"info\",\n \"Very short prompt\",\n \"Prompt is very short and may lack sufficient context for consistent results.\",\n \"Consider adding context, examples, or output format specifications.\"),\n (r'(?:etc|\\.\\.\\.)', \"info\",\n \"Vague continuation marker\",\n \"Using 'etc.' or '...' leaves ambiguity about expected behavior.\",\n \"Be explicit about all expected behaviors and outputs.\"),\n (r'(?:be\\s+creative|use\\s+your\\s+(?:judgment|discretion))', \"low\",\n \"Subjective instruction\",\n \"Subjective instructions lead to inconsistent outputs.\",\n \"Provide specific criteria, examples, or constraints instead of subjective directives.\"),\n]\n\nSEVERITY_ORDER = {\"critical\": 0, \"high\": 1, \"medium\": 2, \"low\": 3, \"info\": 4}\n\n\ndef estimate_tokens(text: str) -> int:\n \"\"\"Quick token estimation.\"\"\"\n return max(1, int(len(text) / 4.0 * 0.5 + len(text.split()) / 0.75 * 0.5))\n\n\ndef run_audit(text: str, checks: Optional[Set[str]] = None) -> AuditReport:\n \"\"\"Run full prompt audit.\"\"\"\n all_checks = checks or {\"injection\", \"bias\", \"safety\", \"quality\"}\n report = AuditReport(\n prompt_length=len(text),\n estimated_tokens=estimate_tokens(text),\n )\n\n lines = text.split(\"\\n\")\n pattern_groups = []\n\n if \"injection\" in all_checks:\n pattern_groups.append((\"injection\", INJECTION_PATTERNS))\n if \"bias\" in all_checks:\n pattern_groups.append((\"bias\", BIAS_PATTERNS))\n if \"safety\" in all_checks:\n pattern_groups.append((\"safety\", SAFETY_PATTERNS))\n if \"quality\" in all_checks:\n pattern_groups.append((\"quality\", QUALITY_PATTERNS))\n\n for category, patterns in pattern_groups:\n for pattern_str, severity, title, desc, rec in patterns:\n try:\n pattern = re.compile(pattern_str, re.IGNORECASE)\n except re.error:\n continue\n\n for i, line in enumerate(lines, 1):\n if pattern.search(line):\n match = pattern.search(line)\n matched_text = match.group()[:80] if match else line.strip()[:80]\n report.findings.append(AuditFinding(\n category=category,\n severity=severity,\n title=title,\n description=desc,\n matched_text=matched_text,\n recommendation=rec,\n line_number=i,\n ))\n\n # Check for missing safety elements\n if \"safety\" in all_checks:\n full_lower = text.lower()\n if \"do not\" not in full_lower and \"don't\" not in full_lower and \"must not\" not in full_lower:\n report.findings.append(AuditFinding(\n category=\"safety\",\n severity=\"info\",\n title=\"No negative constraints found\",\n description=\"Prompt lacks explicit 'do not' constraints. Consider adding boundaries.\",\n matched_text=\"[entire prompt]\",\n recommendation=\"Add explicit restrictions on what the model should NOT do.\",\n ))\n\n if \"format\" not in full_lower and \"json\" not in full_lower and \"structure\" not in full_lower:\n report.findings.append(AuditFinding(\n category=\"quality\",\n severity=\"info\",\n title=\"No output format specification\",\n description=\"Prompt doesn't specify an output format, leading to inconsistent responses.\",\n matched_text=\"[entire prompt]\",\n recommendation=\"Add output format instructions (e.g., JSON schema, markdown template).\",\n ))\n\n # Aggregate\n report.total_findings = len(report.findings)\n for f in report.findings:\n report.findings_by_severity[f.severity] = report.findings_by_severity.get(f.severity, 0) + 1\n report.findings_by_category[f.category] = report.findings_by_category.get(f.category, 0) + 1\n\n report.findings.sort(key=lambda x: SEVERITY_ORDER.get(x.severity, 4))\n\n # Determine overall risk and pass/fail\n if report.findings_by_severity.get(\"critical\", 0) > 0:\n report.overall_risk = \"critical\"\n report.pass_audit = False\n elif report.findings_by_severity.get(\"high\", 0) > 0:\n report.overall_risk = \"high\"\n report.pass_audit = False\n elif report.findings_by_severity.get(\"medium\", 0) > 0:\n report.overall_risk = \"medium\"\n report.pass_audit = True\n else:\n report.overall_risk = \"low\"\n report.pass_audit = True\n\n return report\n\n\ndef format_human(report: AuditReport) -> str:\n \"\"\"Format for human reading.\"\"\"\n lines = []\n lines.append(\"=\" * 65)\n lines.append(\"PROMPT AUDIT REPORT\")\n lines.append(\"=\" * 65)\n lines.append(f\"Prompt length: {report.prompt_length} chars, ~{report.estimated_tokens} tokens\")\n lines.append(f\"Total findings: {report.total_findings}\")\n verdict = \"PASS\" if report.pass_audit else \"FAIL\"\n lines.append(f\"Overall risk: {report.overall_risk.upper()}\")\n lines.append(f\"Audit result: {verdict}\")\n lines.append(\"\")\n\n lines.append(\"Findings by Severity:\")\n for sev in [\"critical\", \"high\", \"medium\", \"low\", \"info\"]:\n count = report.findings_by_severity.get(sev, 0)\n if count > 0:\n lines.append(f\" {sev.upper()}: {count}\")\n lines.append(\"\")\n\n if report.findings_by_category:\n lines.append(\"Findings by Category:\")\n for cat, count in sorted(report.findings_by_category.items()):\n lines.append(f\" {cat}: {count}\")\n lines.append(\"\")\n\n for i, f in enumerate(report.findings, 1):\n lines.append(\"-\" * 50)\n ln = f\" (line {f.line_number})\" if f.line_number else \"\"\n lines.append(f\"[{i}] [{f.severity.upper()}] [{f.category.upper()}] {f.title}{ln}\")\n lines.append(f\" Match: {f.matched_text}\")\n lines.append(f\" Issue: {f.description}\")\n lines.append(f\" Fix: {f.recommendation}\")\n lines.append(\"\")\n\n if report.total_findings == 0:\n lines.append(\"No issues found. Prompt passes audit.\")\n\n lines.append(\"=\" * 65)\n return \"\\n\".join(lines)\n\n\ndef format_json(report: AuditReport) -> str:\n \"\"\"Format as JSON.\"\"\"\n data = {\n \"prompt_length\": report.prompt_length,\n \"estimated_tokens\": report.estimated_tokens,\n \"total_findings\": report.total_findings,\n \"overall_risk\": report.overall_risk,\n \"pass_audit\": report.pass_audit,\n \"findings_by_severity\": report.findings_by_severity,\n \"findings_by_category\": report.findings_by_category,\n \"findings\": [asdict(f) for f in report.findings],\n }\n return json.dumps(data, indent=2)\n\n\ndef main():\n parser = argparse.ArgumentParser(\n description=\"Prompt Auditor - Audit prompts for injection, bias, and safety issues\"\n )\n input_group = parser.add_mutually_exclusive_group(required=True)\n input_group.add_argument(\"--file\", help=\"Path to prompt file\")\n input_group.add_argument(\"--text\", help=\"Prompt text to audit\")\n input_group.add_argument(\"--stdin\", action=\"store_true\", help=\"Read from stdin\")\n\n parser.add_argument(\"--checks\", help=\"Comma-separated checks to run: injection,bias,safety,quality (default: all)\")\n parser.add_argument(\"--format\", choices=[\"human\", \"json\"], default=\"human\",\n help=\"Output format (default: human)\")\n\n args = parser.parse_args()\n\n if args.file:\n path = Path(args.file)\n if not path.exists():\n print(f\"Error: File not found: {args.file}\", file=sys.stderr)\n sys.exit(1)\n text = path.read_text(encoding=\"utf-8\", errors=\"ignore\")\n elif args.text:\n text = args.text\n else:\n text = sys.stdin.read()\n\n checks = None\n if args.checks:\n checks = set(args.checks.split(\",\"))\n\n report = run_audit(text, checks)\n\n if args.format == \"json\":\n print(format_json(report))\n else:\n print(format_human(report))\n\n sys.exit(0 if report.pass_audit else 1)\n\n\nif __name__ == \"__main__\":\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":14007,"content_sha256":"f7a009d7c435768853ae0e12c31f1d3f5dd5573aa47db0e7aa2d5653db383df3"},{"filename":"scripts/prompt_catalog_manager.py","content":"#!/usr/bin/env python3\n\"\"\"\nPrompt Catalog Manager - Manage a catalog of approved prompts with versioning.\n\nProvides a local file-based prompt catalog with versioning, metadata tracking,\ndiff comparison, and search capabilities.\n\nAuthor: Claude Skills Engineering Team\nLicense: MIT\n\"\"\"\n\nimport argparse\nimport hashlib\nimport json\nimport os\nimport sys\nfrom datetime import datetime\nfrom dataclasses import dataclass, asdict, field\nfrom pathlib import Path\nfrom typing import List, Dict, Optional\nimport difflib\n\n\nCATALOG_FILE = \"catalog.json\"\nPROMPTS_DIR = \"versions\"\n\n\n@dataclass\nclass PromptEntry:\n \"\"\"A single prompt entry in the catalog.\"\"\"\n name: str\n version: str\n status: str # draft, review, approved, deployed, retired\n author: str\n created: str\n updated: str\n description: str\n tags: List[str]\n model_targets: List[str]\n content_hash: str\n content_file: str\n audit_status: str # pending, passed, failed\n token_estimate: int\n\n\n@dataclass\nclass Catalog:\n \"\"\"The prompt catalog.\"\"\"\n created: str\n updated: str\n total_prompts: int = 0\n entries: Dict[str, List[PromptEntry]] = field(default_factory=dict) # name -> versions\n\n\ndef _hash_content(content: str) -> str:\n \"\"\"SHA-256 hash of content.\"\"\"\n return hashlib.sha256(content.encode(\"utf-8\")).hexdigest()[:16]\n\n\ndef _estimate_tokens(text: str) -> int:\n \"\"\"Quick token estimate.\"\"\"\n return max(1, int(len(text) / 4.0 * 0.5 + len(text.split()) / 0.75 * 0.5))\n\n\ndef _next_version(versions: List[str]) -> str:\n \"\"\"Calculate next semantic version.\"\"\"\n if not versions:\n return \"1.0.0\"\n latest = sorted(versions, key=lambda v: [int(x) for x in v.split(\".\")])[-1]\n parts = latest.split(\".\")\n parts[-1] = str(int(parts[-1]) + 1)\n return \".\".join(parts)\n\n\ndef load_catalog(catalog_dir: Path) -> Catalog:\n \"\"\"Load catalog from disk.\"\"\"\n catalog_path = catalog_dir / CATALOG_FILE\n if not catalog_path.exists():\n return Catalog(\n created=datetime.now().isoformat(),\n updated=datetime.now().isoformat(),\n )\n\n data = json.loads(catalog_path.read_text(encoding=\"utf-8\"))\n catalog = Catalog(\n created=data.get(\"created\", \"\"),\n updated=data.get(\"updated\", \"\"),\n total_prompts=data.get(\"total_prompts\", 0),\n )\n for name, versions in data.get(\"entries\", {}).items():\n catalog.entries[name] = [\n PromptEntry(**v) for v in versions\n ]\n return catalog\n\n\ndef save_catalog(catalog: Catalog, catalog_dir: Path):\n \"\"\"Save catalog to disk.\"\"\"\n catalog.updated = datetime.now().isoformat()\n catalog.total_prompts = sum(len(v) for v in catalog.entries.values())\n\n data = {\n \"created\": catalog.created,\n \"updated\": catalog.updated,\n \"total_prompts\": catalog.total_prompts,\n \"entries\": {\n name: [asdict(e) for e in versions]\n for name, versions in catalog.entries.items()\n },\n }\n\n catalog_path = catalog_dir / CATALOG_FILE\n catalog_path.write_text(json.dumps(data, indent=2), encoding=\"utf-8\")\n\n\ndef init_catalog(catalog_dir: Path) -> str:\n \"\"\"Initialize a new prompt catalog.\"\"\"\n catalog_dir.mkdir(parents=True, exist_ok=True)\n (catalog_dir / PROMPTS_DIR).mkdir(exist_ok=True)\n\n catalog = Catalog(\n created=datetime.now().isoformat(),\n updated=datetime.now().isoformat(),\n )\n save_catalog(catalog, catalog_dir)\n return f\"Catalog initialized at {catalog_dir}\"\n\n\ndef add_prompt(catalog_dir: Path, name: str, content: str,\n author: str = \"unknown\", description: str = \"\",\n tags: Optional[List[str]] = None,\n model_targets: Optional[List[str]] = None,\n status: str = \"draft\") -> str:\n \"\"\"Add or update a prompt in the catalog.\"\"\"\n catalog = load_catalog(catalog_dir)\n versions_dir = catalog_dir / PROMPTS_DIR\n versions_dir.mkdir(exist_ok=True)\n\n # Determine version\n existing_versions = [e.version for e in catalog.entries.get(name, [])]\n version = _next_version(existing_versions)\n\n # Save content file\n content_hash = _hash_content(content)\n content_file = f\"{name}_v{version.replace('.', '_')}.txt\"\n (versions_dir / content_file).write_text(content, encoding=\"utf-8\")\n\n # Check for duplicate content\n for existing in catalog.entries.get(name, []):\n if existing.content_hash == content_hash:\n return f\"Duplicate: Content identical to {name} v{existing.version}. No new version created.\"\n\n entry = PromptEntry(\n name=name,\n version=version,\n status=status,\n author=author,\n created=datetime.now().isoformat(),\n updated=datetime.now().isoformat(),\n description=description,\n tags=tags or [],\n model_targets=model_targets or [],\n content_hash=content_hash,\n content_file=content_file,\n audit_status=\"pending\",\n token_estimate=_estimate_tokens(content),\n )\n\n if name not in catalog.entries:\n catalog.entries[name] = []\n catalog.entries[name].append(entry)\n\n save_catalog(catalog, catalog_dir)\n return f\"Added {name} v{version} ({entry.token_estimate} tokens, hash: {content_hash})\"\n\n\ndef list_prompts(catalog_dir: Path, show_all_versions: bool = False) -> str:\n \"\"\"List all prompts in the catalog.\"\"\"\n catalog = load_catalog(catalog_dir)\n\n if not catalog.entries:\n return \"Catalog is empty.\"\n\n lines = []\n lines.append(f\"Prompt Catalog ({catalog.total_prompts} total entries)\")\n lines.append(f\"Last updated: {catalog.updated}\")\n lines.append(\"=\" * 70)\n\n for name in sorted(catalog.entries.keys()):\n versions = catalog.entries[name]\n latest = versions[-1]\n\n lines.append(f\"\\n {name}\")\n lines.append(f\" Latest: v{latest.version} ({latest.status})\")\n lines.append(f\" Author: {latest.author}\")\n lines.append(f\" Tokens: ~{latest.token_estimate}\")\n lines.append(f\" Audit: {latest.audit_status}\")\n lines.append(f\" Tags: {', '.join(latest.tags) if latest.tags else 'none'}\")\n lines.append(f\" Versions: {len(versions)}\")\n\n if show_all_versions and len(versions) > 1:\n for v in versions:\n lines.append(f\" v{v.version} ({v.status}) - {v.created[:10]} [{v.audit_status}]\")\n\n return \"\\n\".join(lines)\n\n\ndef diff_versions(catalog_dir: Path, name: str,\n version_a: Optional[str] = None,\n version_b: Optional[str] = None) -> str:\n \"\"\"Show diff between two versions of a prompt.\"\"\"\n catalog = load_catalog(catalog_dir)\n versions_dir = catalog_dir / PROMPTS_DIR\n\n if name not in catalog.entries:\n return f\"Prompt '{name}' not found in catalog.\"\n\n versions = catalog.entries[name]\n if len(versions) \u003c 2 and not (version_a and version_b):\n return f\"Only one version of '{name}' exists. Nothing to diff.\"\n\n # Default to last two versions\n if not version_a:\n entry_a = versions[-2]\n else:\n entry_a = next((v for v in versions if v.version == version_a), None)\n if not entry_a:\n return f\"Version {version_a} not found for '{name}'.\"\n\n if not version_b:\n entry_b = versions[-1]\n else:\n entry_b = next((v for v in versions if v.version == version_b), None)\n if not entry_b:\n return f\"Version {version_b} not found for '{name}'.\"\n\n file_a = versions_dir / entry_a.content_file\n file_b = versions_dir / entry_b.content_file\n\n if not file_a.exists() or not file_b.exists():\n return \"Content files not found on disk.\"\n\n text_a = file_a.read_text(encoding=\"utf-8\").splitlines(keepends=True)\n text_b = file_b.read_text(encoding=\"utf-8\").splitlines(keepends=True)\n\n diff = difflib.unified_diff(\n text_a, text_b,\n fromfile=f\"{name} v{entry_a.version}\",\n tofile=f\"{name} v{entry_b.version}\",\n )\n diff_text = \"\".join(diff)\n\n if not diff_text:\n return f\"No differences between v{entry_a.version} and v{entry_b.version}.\"\n\n lines = []\n lines.append(f\"Diff: {name} v{entry_a.version} -> v{entry_b.version}\")\n lines.append(f\"Tokens: {entry_a.token_estimate} -> {entry_b.token_estimate} \"\n f\"({entry_b.token_estimate - entry_a.token_estimate:+d})\")\n lines.append(\"-\" * 50)\n lines.append(diff_text)\n return \"\\n\".join(lines)\n\n\ndef update_status(catalog_dir: Path, name: str, status: str,\n version: Optional[str] = None) -> str:\n \"\"\"Update the status of a prompt.\"\"\"\n catalog = load_catalog(catalog_dir)\n\n if name not in catalog.entries:\n return f\"Prompt '{name}' not found.\"\n\n valid_statuses = {\"draft\", \"review\", \"approved\", \"deployed\", \"retired\"}\n if status not in valid_statuses:\n return f\"Invalid status '{status}'. Must be one of: {', '.join(valid_statuses)}\"\n\n versions = catalog.entries[name]\n if version:\n entry = next((v for v in versions if v.version == version), None)\n if not entry:\n return f\"Version {version} not found.\"\n else:\n entry = versions[-1]\n\n old_status = entry.status\n entry.status = status\n entry.updated = datetime.now().isoformat()\n save_catalog(catalog, catalog_dir)\n\n return f\"Updated {name} v{entry.version}: {old_status} -> {status}\"\n\n\ndef search_prompts(catalog_dir: Path, query: str) -> str:\n \"\"\"Search prompts by name, tags, or description.\"\"\"\n catalog = load_catalog(catalog_dir)\n query_lower = query.lower()\n results = []\n\n for name, versions in catalog.entries.items():\n latest = versions[-1]\n searchable = f\"{name} {latest.description} {' '.join(latest.tags)}\".lower()\n if query_lower in searchable:\n results.append((name, latest))\n\n if not results:\n return f\"No prompts matching '{query}'.\"\n\n lines = [f\"Search results for '{query}' ({len(results)} found):\"]\n for name, entry in results:\n lines.append(f\" {name} v{entry.version} ({entry.status}) - {entry.description[:60]}\")\n return \"\\n\".join(lines)\n\n\ndef format_json_output(data: str) -> str:\n \"\"\"Wrap string output as JSON.\"\"\"\n return json.dumps({\"result\": data}, indent=2)\n\n\ndef main():\n parser = argparse.ArgumentParser(\n description=\"Prompt Catalog Manager - Manage versioned prompt catalog\"\n )\n parser.add_argument(\"--catalog-dir\", required=True, help=\"Path to catalog directory\")\n\n action = parser.add_mutually_exclusive_group(required=True)\n action.add_argument(\"--init\", action=\"store_true\", help=\"Initialize new catalog\")\n action.add_argument(\"--add\", action=\"store_true\", help=\"Add prompt to catalog\")\n action.add_argument(\"--list\", action=\"store_true\", help=\"List all prompts\")\n action.add_argument(\"--diff\", action=\"store_true\", help=\"Diff prompt versions\")\n action.add_argument(\"--status\", help=\"Update prompt status (draft/review/approved/deployed/retired)\")\n action.add_argument(\"--search\", help=\"Search prompts by query\")\n\n parser.add_argument(\"--name\", help=\"Prompt name (for --add, --diff, --status)\")\n parser.add_argument(\"--file\", help=\"Path to prompt content file (for --add)\")\n parser.add_argument(\"--text\", help=\"Prompt text (for --add)\")\n parser.add_argument(\"--author\", default=\"unknown\", help=\"Author name\")\n parser.add_argument(\"--description\", default=\"\", help=\"Prompt description\")\n parser.add_argument(\"--tags\", nargs=\"+\", help=\"Tags for the prompt\")\n parser.add_argument(\"--models\", nargs=\"+\", help=\"Target models\")\n parser.add_argument(\"--version-a\", help=\"First version for diff\")\n parser.add_argument(\"--version-b\", help=\"Second version for diff\")\n parser.add_argument(\"--all-versions\", action=\"store_true\", help=\"Show all versions in list\")\n parser.add_argument(\"--format\", choices=[\"human\", \"json\"], default=\"human\",\n help=\"Output format\")\n\n args = parser.parse_args()\n catalog_dir = Path(args.catalog_dir)\n\n if args.init:\n result = init_catalog(catalog_dir)\n elif args.add:\n if not args.name:\n print(\"Error: --name required for --add\", file=sys.stderr)\n sys.exit(1)\n if args.file:\n content = Path(args.file).read_text(encoding=\"utf-8\")\n elif args.text:\n content = args.text\n else:\n print(\"Error: --file or --text required for --add\", file=sys.stderr)\n sys.exit(1)\n result = add_prompt(catalog_dir, args.name, content,\n author=args.author, description=args.description,\n tags=args.tags, model_targets=args.models)\n elif args.list:\n result = list_prompts(catalog_dir, show_all_versions=args.all_versions)\n elif args.diff:\n if not args.name:\n print(\"Error: --name required for --diff\", file=sys.stderr)\n sys.exit(1)\n result = diff_versions(catalog_dir, args.name, args.version_a, args.version_b)\n elif args.status:\n if not args.name:\n print(\"Error: --name required for --status\", file=sys.stderr)\n sys.exit(1)\n result = update_status(catalog_dir, args.name, args.status)\n elif args.search:\n result = search_prompts(catalog_dir, args.search)\n else:\n parser.print_help()\n sys.exit(1)\n\n if args.format == \"json\":\n print(format_json_output(result))\n else:\n print(result)\n\n\nif __name__ == \"__main__\":\n main()\n","content_type":"text/x-python; charset=utf-8","language":"python","size":13530,"content_sha256":"d8bce47335a4cd8a927f86538cbbf6b5927b9340844f0a1e3056fe42620433eb"}],"content_json":{"type":"doc","content":[{"type":"heading","attrs":{"level":1},"content":[{"text":"Prompt Governance","type":"text"}]},{"type":"blockquote","content":[{"type":"paragraph","content":[{"text":"Category:","type":"text","marks":[{"type":"strong"}]},{"text":" Engineering ","type":"text"},{"text":"Domain:","type":"text","marks":[{"type":"strong"}]},{"text":" AI Governance","type":"text"}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Overview","type":"text"}]},{"type":"paragraph","content":[{"text":"The ","type":"text"},{"text":"Prompt Governance","type":"text","marks":[{"type":"strong"}]},{"text":" skill provides tools for auditing prompts for security vulnerabilities, bias, and safety issues, plus managing a versioned catalog of approved prompts. Essential for organizations deploying LLM-based applications at scale.","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Quick Start","type":"text"}]},{"type":"code_block","attrs":{"wrap":false,"language":"bash"},"content":[{"text":"# Audit a prompt for security and safety issues\npython scripts/prompt_auditor.py --file system_prompt.txt\n\n# Audit with specific focus\npython scripts/prompt_auditor.py --text \"You are a helpful assistant...\" --checks injection,bias,safety\n\n# Initialize a prompt catalog\npython scripts/prompt_catalog_manager.py --init --catalog-dir ./prompts\n\n# Add a prompt to the catalog\npython scripts/prompt_catalog_manager.py --add --name \"customer-support-v1\" --file prompt.txt --catalog-dir ./prompts\n\n# List all prompts in catalog\npython scripts/prompt_catalog_manager.py --list --catalog-dir ./prompts","type":"text"}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Tools Overview","type":"text"}]},{"type":"table","attrs":{"layout":null},"content":[{"type":"tr","content":[{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Tool","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Purpose","type":"text"}]}]},{"type":"th","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Key Flags","type":"text"}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"prompt_auditor.py","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Audit prompts for injection, bias, and safety","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--file","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"--text","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"--checks","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"--format","type":"text","marks":[{"type":"code_inline"}]}]}]}]},{"type":"tr","content":[{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"prompt_catalog_manager.py","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"Manage versioned prompt catalog","type":"text"}]}]},{"type":"td","attrs":{"colspan":1,"rowspan":1,"colwidth":null,"alignment":""},"content":[{"type":"paragraph","content":[{"text":"--init","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"--add","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"--list","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"--diff","type":"text","marks":[{"type":"code_inline"}]},{"text":", ","type":"text"},{"text":"--catalog-dir","type":"text","marks":[{"type":"code_inline"}]}]}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Workflows","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Prompt Review Process","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Author writes or modifies a prompt","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Run ","type":"text"},{"text":"prompt_auditor.py","type":"text","marks":[{"type":"code_inline"}]},{"text":" for automated checks","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Review findings and address critical issues","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Add approved prompt to catalog with ","type":"text"},{"text":"prompt_catalog_manager.py","type":"text","marks":[{"type":"code_inline"}]}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Deploy from catalog (never from ad-hoc sources)","type":"text"}]}]}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Prompt Versioning","type":"text"}]},{"type":"ordered_list","attrs":{"order":1,"listStyle":"number"},"content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Store all prompts in catalog with semantic versioning","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Use ","type":"text"},{"text":"--diff","type":"text","marks":[{"type":"code_inline"}]},{"text":" to compare versions before promotion","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Maintain audit trail of all prompt changes","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Roll back to previous versions when issues detected","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Reference Documentation","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Prompt Governance Framework","type":"text","marks":[{"type":"link","attrs":{"href":"references/prompt-governance-framework.md","title":null}}]},{"text":" - Policies, review processes, and compliance requirements","type":"text"}]}]}]},{"type":"heading","attrs":{"level":2},"content":[{"text":"Common Patterns","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Prompt Lifecycle","type":"text"}]},{"type":"paragraph","content":[{"text":"Draft -> Audit -> Review -> Approve -> Deploy -> Monitor -> Retire","type":"text"}]},{"type":"heading","attrs":{"level":3},"content":[{"text":"Governance Checklist","type":"text"}]},{"type":"bullet_list","content":[{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"No injection vulnerabilities","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"No harmful content generation potential","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Appropriate bias mitigation","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Clear scope boundaries","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Output format constraints","type":"text"}]}]},{"type":"list_item","content":[{"type":"paragraph","content":[{"text":"Error handling instructions","type":"text"}]}]}]},{"type":"hr","attrs":{"markup":"---"}}]},"metadata":{"date":"2026-06-05","name":"prompt-governance","author":"@skillopedia","source":{"stars":209,"repo_name":"claude-skills","origin_url":"https://github.com/borghei/claude-skills/blob/HEAD/engineering/prompt-governance/SKILL.md","repo_owner":"borghei","body_sha256":"56c93b66f80272ec8cb284e59646ac31f7d8cc74e0b12e9439a11c0534363a8b","cluster_key":"30f788a80ac12c2e2b419ab01daa7a2ece5fce47d9c79bfb21503ef7c4497e68","clean_bundle":{"format":"clean-skill-bundle-v1","source":"borghei/claude-skills/engineering/prompt-governance/SKILL.md","attachments":[{"id":"b8ee0d29-211e-56d8-9060-719869e23355","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/b8ee0d29-211e-56d8-9060-719869e23355/attachment.md","path":"references/prompt-governance-framework.md","size":2982,"sha256":"0bff31e36bdff478b0de612a19f5de184c850d37de28e3f9b9c348025280c4ff","contentType":"text/markdown; charset=utf-8"},{"id":"870ca009-3874-5ceb-9587-44df564f66cd","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/870ca009-3874-5ceb-9587-44df564f66cd/attachment.py","path":"scripts/prompt_auditor.py","size":14007,"sha256":"f7a009d7c435768853ae0e12c31f1d3f5dd5573aa47db0e7aa2d5653db383df3","contentType":"text/x-python; charset=utf-8"},{"id":"72d0dbf5-53a7-5b67-9f7b-7927fbada4be","key":"uploads/10433ee7-ad12-4ae0-b34e-97553e46c6c8/72d0dbf5-53a7-5b67-9f7b-7927fbada4be/attachment.py","path":"scripts/prompt_catalog_manager.py","size":13530,"sha256":"d8bce47335a4cd8a927f86538cbbf6b5927b9340844f0a1e3056fe42620433eb","contentType":"text/x-python; charset=utf-8"}],"bundle_sha256":"d22c11482c9f2a335cbe1adc5850bd6a7bf9d25c5e8d426822041bacd3b5e425","attachment_count":3,"text_attachments":3,"attachment_storage":"skillopedia-attachments-v1","binary_attachments":0,"excluded_attachments":[]},"cluster_size":1,"skill_md_path":"engineering/prompt-governance/SKILL.md","import_metadata":{"date":"2026-06-05","author":"@skillopedia","version":"v1","category":"security","category_label":"Security"},"exact_dupes_collapsed_into_this":0},"license":"MIT + Commons Clause","version":"v1","category":"security","metadata":{"tags":["prompt-governance","prompt-safety","prompt-audit","prompt-catalog","ai-compliance"],"author":"borghei","domain":"ai-governance","updated":"2026-04-02T00:00:00.000Z","version":"1.0.0","category":"engineering"},"import_tag":"clean-skills-v1","description":"This skill should be used when the user asks to \"audit prompts for safety\", \"check prompts for injection vulnerabilities\", \"manage a prompt catalog\", \"version control prompts\", or \"review prompt quality and compliance\".\n"}},"renderedAt":1782981615012}

Prompt Governance Category: Engineering Domain: AI Governance Overview The Prompt Governance skill provides tools for auditing prompts for security vulnerabilities, bias, and safety issues, plus managing a versioned catalog of approved prompts. Essential for organizations deploying LLM-based applications at scale. Quick Start Tools Overview | Tool | Purpose | Key Flags | |------|---------|-----------| | | Audit prompts for injection, bias, and safety | , , , | | | Manage versioned prompt catalog | , , , , | Workflows Prompt Review Process 1. Author writes or modifies a prompt 2. Run for autom…