[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M72WPJ7DRTC09HEXYYRDRMWC":3,"skill-same:01M72WPJ7DRTC09HEXYYRDRMWC":46},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":24,"commitSha":25,"skillDirectory":26,"forksCount":27,"repositoryHtmlUrl":28,"repositoryHomepageUrl":29,"ownerHtmlUrl":30,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":31,"install":32,"resources":45},"01M72WPJ7DRTC09HEXYYRDRMWC","academic-pdf-redaction",null,"Redact text from PDF documents for blind review anonymization","agentscope-ai\u002FPawBench","agentscope-ai","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F211762292?v=4","01M6CRT6543BZGGVK3P85GC08Q","AgentScope-AI","01M72WJAXCYDAXK74090327ER7",127,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fagentscope-ai\u002FPawBench\u002Fblob\u002Fmain\u002Fdata\u002Fpawbench-v1.0\u002Fassets\u002FT135_skillsbench_paper-anonymizer\u002Fskills\u002Facademic-pdf-redaction\u002FSKILL.md",[],[],"2026-11-10 22:39:42",false,"---\nname: academic-pdf-redaction\ndescription: Redact text from PDF documents for blind review anonymization\n---\n\n# PDF Redaction for Blind Review\n\nRedact identifying information from academic papers for blind review.\n\n## CRITICAL RULES\n\n1. **PRESERVE References section** - Self-citations MUST remain intact\n2. **ONLY redact specific text matches** - Never redact entire pages\u002Fregions\n3. **VERIFY output** - Check that 80%+ of original text remains\n\n## Common Pitfalls to AVOID\n\n```python\n# ❌ WRONG - This removes ALL text from the page:\nfor block in page.get_text(\"blocks\"):\n    page.add_redact_annot(fitz.Rect(block[:4]))\n\n# ❌ WRONG - Drawing rectangles over text:\npage.draw_rect(fitz.Rect(0, 0, 600, 100), fill=(0,0,0))\n\n# ✅ CORRECT - Only redact specific search matches:\nfor rect in page.search_for(\"John Smith\"):\n    page.add_redact_annot(rect)\n```\n\n## Patterns to Redact (Before References Only)\n\n**IMPORTANT: Use FULL names\u002Fphrases, not partial matches!**\n- ✅ \"John Smith\" (full name)\n- ❌ \"Smith\" (partial - would incorrectly match \"Smith et al.\" citations in References)\n\n1. **Author names** - FULL names only (e.g., \"John Smith\", not just \"Smith\")\n2. **Affiliations** - Universities, companies (e.g., \"Duke University\")\n3. **Email addresses** - Pattern: `*@*.edu`, `*@*.com`\n4. **Venue names** - Conference\u002Fworkshop names (e.g., \"ICML 2024\", \"ICML Workshop\")\n5. **arXiv identifiers** - Pattern: `arXiv:XXXX.XXXXX`\n6. **DOIs** - Pattern: `10.XXXX\u002F...`\n7. **Acknowledgement names** - Names in \"Acknowledgements\" section\n8. **Equal contribution footnotes** - e.g., \"Equal contribution\", \"* Equal contribution\"\n\n## PyMuPDF (fitz) - Recommended Approach\n\n```python\nimport fitz\nimport os\n\ndef redact_with_pymupdf(input_path: str, output_path: str, patterns: list[str]):\n    \"\"\"Redact specific patterns from PDF using PyMuPDF.\"\"\"\n    doc = fitz.open(input_path)\n    original_len = sum(len(p.get_text()) for p in doc)\n\n    # Find References page - stop redacting there\n    references_page = None\n    for i, page in enumerate(doc):\n        if \"references\" in page.get_text().lower():\n            references_page = i\n            break\n\n    for page_num, page in enumerate(doc):\n        if references_page is not None and page_num >= references_page:\n            continue  # Skip References section\n\n        for pattern in patterns:\n            # ONLY redact exact search matches\n            for rect in page.search_for(pattern):\n                page.add_redact_annot(rect, fill=(0, 0, 0))\n        page.apply_redactions()\n\n    os.makedirs(os.path.dirname(output_path), exist_ok=True)\n    doc.save(output_path)\n    doc.close()\n\n    # MUST verify after saving\n    verify_redaction(input_path, output_path)\n```\n\n## REQUIRED: Verification Function\n\n**Always run this after ANY redaction to catch errors early:**\n\n```python\nimport fitz\n\ndef verify_redaction(original_path, output_path):\n    \"\"\"Verify redaction didn't corrupt the PDF.\"\"\"\n    orig = fitz.open(original_path)\n    redc = fitz.open(output_path)\n\n    orig_len = sum(len(p.get_text()) for p in orig)\n    redc_len = sum(len(p.get_text()) for p in redc)\n\n    print(f\"Original: {len(orig)} pages, {orig_len} chars\")\n    print(f\"Redacted: {len(redc)} pages, {redc_len} chars\")\n    print(f\"Retained: {redc_len\u002Forig_len:.1%}\")\n\n    # DEFENSIVE CHECKS - fail fast if something went wrong\n    if len(redc) != len(orig):\n        raise ValueError(f\"Page count changed: {len(orig)} -> {len(redc)}\")\n    if redc_len \u003C 1000:\n        raise ValueError(f\"PDF corrupted: only {redc_len} chars remain!\")\n    if redc_len \u003C orig_len * 0.7:\n        raise ValueError(f\"Too much removed: kept only {redc_len\u002Forig_len:.0%}\")\n\n    orig.close()\n    redc.close()\n    print(\"✓ Verification passed\")\n```\n","# PDF Redaction for Blind Review\n\nRedact identifying information from academic papers for blind review.\n\n## CRITICAL RULES\n\n1. **PRESERVE References section** - Self-citations MUST remain intact\n2. **ONLY redact specific text matches** - Never redact entire pages\u002Fregions\n3. **VERIFY output** - Check that 80%+ of original text remains\n\n## Common Pitfalls to AVOID\n\n```python\n# ❌ WRONG - This removes ALL text from the page:\nfor block in page.get_text(\"blocks\"):\n    page.add_redact_annot(fitz.Rect(block[:4]))\n\n# ❌ WRONG - Drawing rectangles over text:\npage.draw_rect(fitz.Rect(0, 0, 600, 100), fill=(0,0,0))\n\n# ✅ CORRECT - Only redact specific search matches:\nfor rect in page.search_for(\"John Smith\"):\n    page.add_redact_annot(rect)\n```\n\n## Patterns to Redact (Before References Only)\n\n**IMPORTANT: Use FULL names\u002Fphrases, not partial matches!**\n- ✅ \"John Smith\" (full name)\n- ❌ \"Smith\" (partial - would incorrectly match \"Smith et al.\" citations in References)\n\n1. **Author names** - FULL names only (e.g., \"John Smith\", not just \"Smith\")\n2. **Affiliations** - Universities, companies (e.g., \"Duke University\")\n3. **Email addresses** - Pattern: `*@*.edu`, `*@*.com`\n4. **Venue names** - Conference\u002Fworkshop names (e.g., \"ICML 2024\", \"ICML Workshop\")\n5. **arXiv identifiers** - Pattern: `arXiv:XXXX.XXXXX`\n6. **DOIs** - Pattern: `10.XXXX\u002F...`\n7. **Acknowledgement names** - Names in \"Acknowledgements\" section\n8. **Equal contribution footnotes** - e.g., \"Equal contribution\", \"* Equal contribution\"\n\n## PyMuPDF (fitz) - Recommended Approach\n\n```python\nimport fitz\nimport os\n\ndef redact_with_pymupdf(input_path: str, output_path: str, patterns: list[str]):\n    \"\"\"Redact specific patterns from PDF using PyMuPDF.\"\"\"\n    doc = fitz.open(input_path)\n    original_len = sum(len(p.get_text()) for p in doc)\n\n    # Find References page - stop redacting there\n    references_page = None\n    for i, page in enumerate(doc):\n        if \"references\" in page.get_text().lower():\n            references_page = i\n            break\n\n    for page_num, page in enumerate(doc):\n        if references_page is not None and page_num >= references_page:\n            continue  # Skip References section\n\n        for pattern in patterns:\n            # ONLY redact exact search matches\n            for rect in page.search_for(pattern):\n                page.add_redact_annot(rect, fill=(0, 0, 0))\n        page.apply_redactions()\n\n    os.makedirs(os.path.dirname(output_path), exist_ok=True)\n    doc.save(output_path)\n    doc.close()\n\n    # MUST verify after saving\n    verify_redaction(input_path, output_path)\n```\n\n## REQUIRED: Verification Function\n\n**Always run this after ANY redaction to catch errors early:**\n\n```python\nimport fitz\n\ndef verify_redaction(original_path, output_path):\n    \"\"\"Verify redaction didn't corrupt the PDF.\"\"\"\n    orig = fitz.open(original_path)\n    redc = fitz.open(output_path)\n\n    orig_len = sum(len(p.get_text()) for p in orig)\n    redc_len = sum(len(p.get_text()) for p in redc)\n\n    print(f\"Original: {len(orig)} pages, {orig_len} chars\")\n    print(f\"Redacted: {len(redc)} pages, {redc_len} chars\")\n    print(f\"Retained: {redc_len\u002Forig_len:.1%}\")\n\n    # DEFENSIVE CHECKS - fail fast if something went wrong\n    if len(redc) != len(orig):\n        raise ValueError(f\"Page count changed: {len(orig)} -> {len(redc)}\")\n    if redc_len \u003C 1000:\n        raise ValueError(f\"PDF corrupted: only {redc_len} chars remain!\")\n    if redc_len \u003C orig_len * 0.7:\n        raise ValueError(f\"Too much removed: kept only {redc_len\u002Forig_len:.0%}\")\n\n    orig.close()\n    redc.close()\n    print(\"✓ Verification passed\")\n```\n",{"name":5,"description":7},"main","0f794a8bb6c27aa9ee4091b2691fa30e4ed9cc8f","data\u002Fpawbench-v1.0\u002Fassets\u002FT135_skillsbench_paper-anonymizer\u002Fskills\u002Facademic-pdf-redaction",24,"https:\u002F\u002Fgithub.com\u002Fagentscope-ai\u002FPawBench","https:\u002F\u002Fagentscope-ai.github.io\u002FPawBench\u002F","https:\u002F\u002Fgithub.com\u002Fagentscope-ai","2026-08-03 20:09:53",{"source":8,"skillName":5,"commands":33,"prompt":43,"zipAvailable":44},[34,37,40],{"tool":35,"command":36},"npx","npx skills add agentscope-ai\u002FPawBench --skill academic-pdf-redaction",{"tool":38,"command":39},"bunx","bunx skills add agentscope-ai\u002FPawBench --skill academic-pdf-redaction",{"tool":41,"command":42},"pnpm","pnpm dlx skills add agentscope-ai\u002FPawBench --skill academic-pdf-redaction","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fagentscope-ai\u002FPawBench\u002Fblob\u002Fmain\u002Fdata\u002Fpawbench-v1.0\u002Fassets\u002FT135_skillsbench_paper-anonymizer\u002Fskills\u002Facademic-pdf-redaction\u002FSKILL.md",true,[],[47,53,60,67,74,81],{"skillNo":48,"name":49,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":50,"categories":51,"keywords":52,"publishedAt":19},"01M72WQCJKBJZB6SC8MMYK3C8R","data-reconciliation","https:\u002F\u002Fgithub.com\u002Fagentscope-ai\u002FPawBench\u002Fblob\u002Fmain\u002Fdata\u002Fpawbench-v1.0\u002Fassets\u002FT140_skillsbench_xlsx-recover-data\u002Fskills\u002Fdata-reconciliation\u002FSKILL.md",[],[],{"skillNo":54,"name":55,"nameZh":6,"description":56,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":57,"categories":58,"keywords":59,"publishedAt":19},"01M72WQ8R4DZKK1CT397C0ARQD","hierarchical-taxonomy-clustering","Build unified multi-level category taxonomy from hierarchical product category paths from any e-commerce companies using embedding-based recursive clustering with intelligent category naming via weighted word frequency analysis.","https:\u002F\u002Fgithub.com\u002Fagentscope-ai\u002FPawBench\u002Fblob\u002Fmain\u002Fdata\u002Fpawbench-v1.0\u002Fassets\u002FT139_skillsbench_taxonomy-tree-merge\u002Fskills\u002Fhierarchical-taxonomy-clustering\u002FSKILL.md",[],[],{"skillNo":61,"name":62,"nameZh":6,"description":63,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":64,"categories":65,"keywords":66,"publishedAt":19},"01M72WQ1989ZX613G3PY8Z492J","nlp-research-repo-package-installment","Align Python version and repo-declared dependencies (requirements.txt \u002F environment.yml) before installing packages for NLP research code reproduction.","https:\u002F\u002Fgithub.com\u002Fagentscope-ai\u002FPawBench\u002Fblob\u002Fmain\u002Fdata\u002Fpawbench-v1.0\u002Fassets\u002FT138_skillsbench_simpo-code-reproduction\u002Fskills\u002Fnlp-research-repo-package-installment\u002FSKILL.md",[],[],{"skillNo":68,"name":69,"nameZh":6,"description":70,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":71,"categories":72,"keywords":73,"publishedAt":19},"01M72WPZ828E746PAB3WCCQARW","state-space-linearization","Linearizing nonlinear dynamics around operating points for control design.","https:\u002F\u002Fgithub.com\u002Fagentscope-ai\u002FPawBench\u002Fblob\u002Fmain\u002Fdata\u002Fpawbench-v1.0\u002Fassets\u002FT137_skillsbench_r2r-mpc-control\u002Fskills\u002Fstate-space-linearization\u002FSKILL.md",[],[],{"skillNo":75,"name":76,"nameZh":6,"description":77,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":78,"categories":79,"keywords":80,"publishedAt":19},"01M72WPXFXKWDFVTGAYX0B1TSA","mpc-horizon-tuning","Selecting MPC prediction horizon and cost matrices for web handling.","https:\u002F\u002Fgithub.com\u002Fagentscope-ai\u002FPawBench\u002Fblob\u002Fmain\u002Fdata\u002Fpawbench-v1.0\u002Fassets\u002FT137_skillsbench_r2r-mpc-control\u002Fskills\u002Fmpc-horizon-tuning\u002FSKILL.md",[],[],{"skillNo":82,"name":83,"nameZh":6,"description":84,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":85,"categories":86,"keywords":87,"publishedAt":19},"01M72WPW3863555HM0CACRCCFK","integral-action-design","Adding integral action to MPC for offset-free tension tracking.","https:\u002F\u002Fgithub.com\u002Fagentscope-ai\u002FPawBench\u002Fblob\u002Fmain\u002Fdata\u002Fpawbench-v1.0\u002Fassets\u002FT137_skillsbench_r2r-mpc-control\u002Fskills\u002Fintegral-action-design\u002FSKILL.md",[],[]]