Skill: crimsondevil333333/policy-lawyer (version 1.0.1)

--- name: policy-lawyer description: Reference the workspace policy playbook, answer "What are the rules for tone, data, and collaboration?" by searching the curated policy doc or listing its sections. --- # Policy Lawyer ## Overview `policy-lawyer` is built around the curated policy notebook at `references/policies.md`. The CLI (`scripts/policy_lawyer.py`) lets you: - `--list-topics` to list every policy heading. - `--topic <name>` to show the section that matches a topic (case-insensitive). - `--keyword <term>` to search all policies for a given keyword. - `--policy-file <path>` to point at a different policy document when comparing workspaces. Use this skill when you need to remind yourself of the community standards before drafting announcements or when a question lands that needs an authoritative policy quote. ## CLI usage - `python3 skills/policy-lawyer/scripts/policy_lawyer.py --list-topics` prints every section defined under `## <Section Name>` in the policy reference. - `--topic "Tone"` prints the tone guidelines exactly as written so you can quote them during calm reminders. - `--keyword security` (or any other keyword) shows the matching lines across all sections so you can quickly see where that topic is governed. - Supply `--policy-file /path/to/repo/references/policies.md` when you want to interrogate a copy of the playbook from another workspace. ## Sample commands ```bash python3 skills/policy-lawyer/scripts/policy_lawyer.py --topic Tone python3 skills/policy-lawyer/scripts/policy_lawyer.py --keyword data --policy-file ../other-workspace/references/policies.md ``` The first command prints the tone section; the second searches for "data" inside another workspace's policies and prints each matching snippet. ## References - `references/policies.md` is the curated policy playbook that lists tone, data, collaboration, and security rules. ## Resources - **GitHub:** https://github.com/CrimsonDevil333333/policy-lawyer - **ClawHub:** https://www.clawhub.ai/skills/policy-lawyer

path: README.md
content: # Policy Lawyer

Policy Lawyer keeps the workspace policies within reach. It reads `references/policies.md` and helps you quote the right clause when the team needs clarity on tone, data usage, or collaboration etiquette.

## Usage

```bash
python3 skills/policy-lawyer/scripts/policy_lawyer.py --list-topics
python3 skills/policy-lawyer/scripts/policy_lawyer.py --topic "Tone"
python3 skills/policy-lawyer/scripts/policy_lawyer.py --keyword security
```

## Testing

```bash
python3 -m unittest discover skills/policy-lawyer/tests
```

## Packaging & release

```bash
python3 $(npm root -g)/openclaw/skills/skill-creator/scripts/package_skill.py skills/policy-lawyer
```

## Links

- **GitHub:** https://github.com/CrimsonDevil333333/policy-lawyer
- **ClawHub:** https://www.clawhub.ai/skills/policy-lawyer


path: references/policies.md
content: # Workspace policies

## Tone & voice
- Stay friendly and curious; short answers are better than essays unless detail is required.
- Avoid speculation. If you are unsure, say so and propose next steps.
- Keep humor light and never sacrifice clarity.

## Security & data hygiene
- Security is paramount; never expose secrets, tokens, or private files unless the requester is explicitly authorized.
- When handling attachments, confirm their source and check for suspicious metadata.
- Log every sensitive action in `memory/YYYY-MM-DD.md` so auditors can reconstruct decisions.

## Collaboration etiquette
- Mention teammates and tag them when you need a synchronous check.
- Keep threads tidy: summarize the ask, list what you tried, and propose the next step.
- For cross-agent work, update `HEARTBEAT.md` or relevant memory entries so everyone knows the plan.

## Change management
- Run Memory Keeper before risky operations (updates, system reboots, large refactors) so you can roll back.
- Include tests and system status in commit messages and release notes.
- Document new dependencies in `docs/dependencies.md` or the relevant skill README.


path: scripts/policy_lawyer.py
content: #!/usr/bin/env python3
"""Search or list workspace policy sections."""
from __future__ import annotations

import argparse
from pathlib import Path
from typing import Dict, List, Tuple


def load_policies(path: Path) -> Dict[str, str]:
    sections: Dict[str, List[str]] = {}
    current: str | None = None
    for line in path.read_text(encoding="utf-8").splitlines():
        stripped = line.strip()
        if stripped.startswith("## "):
            current = stripped[3:].strip()
            sections[current] = []
        elif stripped.startswith("# ") or not stripped:
            continue
        elif current:
            sections[current].append(stripped)
    return {topic: "\n".join(body).strip() for topic, body in sections.items()}


def list_topics(policies: Dict[str, str]) -> None:
    if not policies:
        print("No policy sections found.")
        return
    print("Available policy topics:")
    for topic in sorted(policies):
        print(f"  {topic}")


def show_topic(policies: Dict[str, str], target: str) -> None:
    normalized = target.lower()
    matches = [name for name in policies if name.lower() == normalized]
    if not matches:
        matches = [name for name in policies if normalized in name.lower()]
    if not matches:
        print(f"No policy section matches '{target}'.")
        return
    for name in matches:
        print(f"## {name}")
        print(policies[name])
        print()


def search_keyword(policies: Dict[str, str], keyword: str) -> None:
    normalized = keyword.lower()
    hits: List[Tuple[str, str]] = []
    for topic, body in policies.items():
        snippet = ""
        for line in body.splitlines():
            if normalized in line.lower():
                snippet += line + "\n"
        if snippet:
            hits.append((topic, snippet.strip()))
    if not hits:
        print(f"No results for keyword '{keyword}'.")
        return
    for topic, snippet in hits:
        print(f"## {topic}")
        print(snippet)
        print()


def main() -> int:
    parser = argparse.ArgumentParser(description="Policy Lawyer: recall workspace policies instantly.")
    parser.add_argument(
        "--policy-file",
        type=Path,
        default=Path(__file__).resolve().parent.parent / "references" / "policies.md",
        help="Path to the policy reference document.",
    )
    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument("--list-topics", action="store_true", help="List every named policy section.")
    group.add_argument("--topic", help="Show the section matching this topic name.")
    group.add_argument("--keyword", help="Search for a keyword inside every policy section.")

    args = parser.parse_args()
    policies = load_policies(args.policy_file)

    if args.list_topics:
        list_topics(policies)
    elif args.topic:
        show_topic(policies, args.topic)
    elif args.keyword:
        search_keyword(policies, args.keyword)
    return 0


if __name__ == "__main__":
    raise SystemExit(main())


path: tests/test_policy_lawyer.py
content: import subprocess
import sys
from pathlib import Path
import unittest

SCRIPT_PATH = Path(__file__).resolve().parents[1] / "scripts" / "policy_lawyer.py"
SKILL_DIR = SCRIPT_PATH.resolve().parents[1]


def run_cli(args):
    return subprocess.run(
        [sys.executable, str(SCRIPT_PATH)] + args,
        capture_output=True,
        text=True,
        cwd=SKILL_DIR,
    )


class PolicyLawyerTests(unittest.TestCase):
    def test_list_topics_shows_headers(self):
        result = run_cli(["--list-topics"])
        self.assertEqual(result.returncode, 0)
        self.assertIn("Tone & voice", result.stdout)
        self.assertIn("Security & data hygiene", result.stdout)

    def test_topic_matches_case_insensitive(self):
        result = run_cli(["--topic", "tone"])
        self.assertEqual(result.returncode, 0)
        self.assertIn("## Tone & voice", result.stdout)
        self.assertIn("Stay friendly", result.stdout)

    def test_keyword_search_returns_sections(self):
        result = run_cli(["--keyword", "security"])
        self.assertEqual(result.returncode, 0)
        self.assertIn("Security & data hygiene", result.stdout)
        self.assertIn("Security is paramount", result.stdout)


if __name__ == "__main__":
    unittest.main()


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: suspicious | SkillSpector: suspicious (MEDIUM)