<p align="center">
  <a href="https://kdnsna.github.io/pptlint/">🏠 产品首页</a> ·
  <a href="https://kdnsna.github.io/pptlint/lab/">🔬 案例实验室</a> ·
  <a href="https://kdnsna.github.io/pptlint/proof-loop/comparison.html">📈 真实 Proof Loop</a> ·
  <a href="README.zh-CN.md">English</a>
</p>

<p align="center">
  <img src="site/assets/readme-hero.svg" alt="PPTLint — PowerPoint 交付前质量检查" width="1200">
</p>

<p align="center">
  <a href="https://github.com/kdnsna/pptlint/actions/workflows/ci.yml"><img src="https://github.com/kdnsna/pptlint/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
  <a href="https://kdnsna.github.io/pptlint/"><img src="https://github.com/kdnsna/pptlint/actions/workflows/pages.yml/badge.svg" alt="Pages"></a>
  <a href="https://pypi.org/project/pptlint/"><img src="https://img.shields.io/pypi/v/pptlint.svg" alt="PyPI"></a>
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-10233f.svg" alt="License"></a>
  <img src="https://img.shields.io/badge/local-read--only-10233f.svg" alt="local">
</p>

<table>
  <tr>
    <td width="33%" align="center" valign="top">
      <div style="border:1px solid #ECECF1;border-radius:16px;overflow:hidden;box-shadow:0 8px 24px rgba(10,22,40,0.10);background:#ffffff;">
        <div style="background-color:#E85D2C;background:linear-gradient(135deg,#E85D2C 0%,#F2874E 100%);padding:22px 18px;text-align:center;">
          <div style="font-size:30px;line-height:1;">🏠</div>
        </div>
        <div style="padding:18px 18px 22px;">
          <h3 style="margin:0 0 8px;color:#0A1628;font-size:18px;">产品首页</h3>
          <p style="margin:0 0 16px;color:#6B7280;font-size:14px;line-height:1.6;">30 秒看懂 PPTLint 在交付前帮你挡住什么，以及它为什么“只读不改”。</p>
          <a href="https://kdnsna.github.io/pptlint/" style="display:inline-block;padding:9px 20px;background:#E85D2C;color:#ffffff;border-radius:9px;text-decoration:none;font-weight:600;font-size:14px;">立即访问 →</a>
        </div>
      </div>
    </td>
    <td width="33%" align="center" valign="top">
      <div style="border:1px solid #ECECF1;border-radius:16px;overflow:hidden;box-shadow:0 8px 24px rgba(10,22,40,0.10);background:#ffffff;">
        <div style="background-color:#E85D2C;background:linear-gradient(135deg,#E85D2C 0%,#F2874E 100%);padding:22px 18px;text-align:center;">
          <div style="font-size:30px;line-height:1;">🔬</div>
        </div>
        <div style="padding:18px 18px 22px;">
          <h3 style="margin:0 0 8px;color:#0A1628;font-size:18px;">案例实验室</h3>
          <p style="margin:0 0 16px;color:#6B7280;font-size:14px;line-height:1.6;">12 个一眼能懂的前后对比，覆盖投屏翻车、换电脑变样、隐私外发与可编辑交接。</p>
          <a href="https://kdnsna.github.io/pptlint/lab/" style="display:inline-block;padding:9px 20px;background:#E85D2C;color:#ffffff;border-radius:9px;text-decoration:none;font-weight:600;font-size:14px;">立即访问 →</a>
        </div>
      </div>
    </td>
    <td width="33%" align="center" valign="top">
      <div style="border:1px solid #ECECF1;border-radius:16px;overflow:hidden;box-shadow:0 8px 24px rgba(10,22,40,0.10);background:#ffffff;">
        <div style="background-color:#E85D2C;background:linear-gradient(135deg,#E85D2C 0%,#F2874E 100%);padding:22px 18px;text-align:center;">
          <div style="font-size:30px;line-height:1;">📈</div>
        </div>
        <div style="padding:18px 18px 22px;">
          <h3 style="margin:0 0 8px;color:#0A1628;font-size:18px;">真实 Proof Loop</h3>
          <p style="margin:0 0 16px;color:#6B7280;font-size:14px;line-height:1.6;">同一份 PPT 按当前规则从 83 分到 100 分，修改前后文件、完整报告和机器可读数据全部公开。</p>
          <a href="https://kdnsna.github.io/pptlint/proof-loop/comparison.html" style="display:inline-block;padding:9px 20px;background:#E85D2C;color:#ffffff;border-radius:9px;text-decoration:none;font-weight:600;font-size:14px;">立即访问 →</a>
        </div>
      </div>
    </td>
  </tr>
</table>

<div style="border-left:4px solid #E85D2C;background:#FFF7F2;padding:14px 18px;border-radius:0 10px 10px 0;color:#0A1628;font-size:15px;line-height:1.7;margin:26px 0;">
  <strong>PPT 做完以后，别急着发。</strong> 你电脑上看不出来的问题，往往会在领导、客户或会议室的电脑上暴露。
</div>

<p align="center">
  <a href="https://kdnsna.github.io/pptlint/lab/">
    <img src="site/assets/readme-hero.svg" alt="同一份可编辑 PPT 修改前后对比：83 分到 100 分" width="860">
  </a>
</p>

<p align="center">
  <sub>同一份可编辑 PPT，交付修复前（左）与修复后（右）——按当前规则从 83 到 100。点击查看 12 个前后对比案例 →</sub>
</p>

## 它解决的不是“好不好看”，而是“能不能放心发”

一份 PPT 在自己电脑上看着正常，并不代表已经适合交付：

- **会上出丑**：字体替换后标题换行，最后一行被截掉，两个文本框压在一起；
- **换电脑变样**：特殊字体、外部 Excel、音视频或动画离开原电脑后失效；
- **别人无法接手**：整页其实是一张图，对方想改一个数字也选不中；
- **内部内容被带出去**：讲者备注、隐藏页、批注、作者信息或本地链接仍留在文件里；
- **文件本身不稳**：包内对象缺失、重复媒体过多，打开时弹出修复或等待很久。

PPTLint 默认在本机只读检查 `.pptx`，生成离线 HTML 与 JSON 报告。它**不上传文件、不调用模型、永不修改源文件、不收集遥测数据**。只有你逐项授权 `fix` 操作时，它才会写入一份新的清理副本。

## 一分钟开始

把下面这句话发给 Codex、Claude Code 或其他 Coding Agent：

```text
请安装 PPTLint，检查这份 PowerPoint 是否适合发给客户。
按“必须修、建议看、可以忽略”告诉我先处理哪几页，
并给出在 PowerPoint 里的具体操作。不要修改原文件。
```

或者直接运行：

```bash
uvx pptlint check output.pptx --scenario present --lang zh-CN
```

希望检查完成后直接打开本地报告，可以使用：

```bash
uvx pptlint start output.pptx --scenario present --lang zh-CN
```

排查安装、Python 或真实渲染器问题时运行 `uvx pptlint doctor`；反馈问题时优先附上该诊断结果，不要上传原 PPT。

### 不想看命令：打开本地拖放版

```bash
uvx --refresh pptlint app
```

它会在本机随机端口打开中文页面。你可以拖入原 PPT、勾选允许清理的隐私内容、复制完整 Agent 任务，再拖入修改后副本导出 Proof Pack。页面只绑定 `127.0.0.1`，每次启动都有新令牌；关闭后临时文件自动删除，也不会请求外部字体、统计、模型或接口。

默认 `present` 代表会议室投屏。屏幕阅读或文档型 PPT 可改用：

```bash
uvx pptlint check output.pptx --scenario screen --lang zh-CN
uvx pptlint check output.pptx --scenario document --lang zh-CN
```

每次检查都会生成：

- `pptlint-report.html`：给人看的离线报告，先说后果，再说处理方法；
- `pptlint-report.json`：给 Agent、CI 和其他工具读取的稳定数据。

完整报告可能包含页面预览、文字和文档属性，应与原 PPT 同级保护。如需提交问题或发给外部协作者，先生成安全分享版：

```bash
uvx pptlint check output.pptx --lang zh-CN --report-mode shareable --output pptlint-safe
```

安全分享版会隐藏文件名、页面标题、预览和对象级证据，但保留规则、结论和处理步骤。

## 先看证据，再决定要不要用

- [🏠 产品首页](https://kdnsna.github.io/pptlint/)：30 秒理解 PPTLint 在交付前帮你挡住什么。
- [🔬 案例实验室](https://kdnsna.github.io/pptlint/lab/)：12 个交付风险前后对比，覆盖投屏、换电脑、隐私、可编辑交接、文件体积和团队规范。
- [📈 真实 Proof Loop](https://kdnsna.github.io/pptlint/proof-loop/comparison.html)：同一份 9 页可编辑 PPT 按当前规则从 83 → 100，修改前后文件、完整报告和机器可读数据全部公开。
- [修改前 PPTX](examples/proof-loop/before.pptx) 与 [修改后 PPTX](examples/proof-loop/after.pptx)。
- [检查方法档案](https://kdnsna.github.io/pptlint/benchmark/)：说明 PPTLint 如何面对不同 AI PPT 项目。

真实 Proof Loop 使用同一份 9 页可编辑 PPT。报告中的 103 项问题和提醒得到处理，修改后没有新增高置信问题。**100 分只是规则检查结果，不是审美满分，也不是绝对零风险。**

## 报告直接给出三种结论

| 结论 | 普通用户该做什么 |
|---|---|
| <span style="color:#10B981;font-weight:700;">✅ 可以交付</span> | 没有发现高置信的交付问题，仍应做最终人工预览 |
| <span style="color:#D97706;font-weight:700;">👀 建议检查</span> | 打开报告点名的页面，确认低置信或需要业务判断的内容 |
| <span style="color:#DC2626;font-weight:700;">⛔ 暂勿交付</span> | 先处理报告列出的阻断问题，再另存副本并复检 |

同一条规则在 200 个对象上重复出现时，HTML 会合并成一个问题组；完整对象级证据仍保留在 JSON 中。PPTLint 不会用几百条重复提醒制造焦虑。

## 修改后生成完整对比证据

始终保留原文件，只修改独立副本：

```bash
uvx pptlint proof before.pptx after.pptx \
  --scenario present --lang zh-CN --output comparison
```

它会生成修改前、修改后和对比报告，明确列出：已经处理、仍然存在、修改后新增的问题。

如果要把修复工作交给 Agent：

```bash
uvx pptlint plan pptlint-report.json --format json --output repair-plan.json
uvx pptlint plan pptlint-report.json --adapter generic-agent --lang zh-CN --output repair-brief.md
uvx pptlint plan pptlint-report.json --adapter ultimate-ppt-master --lang zh-CN --output ultimate-brief.md
uvx pptlint plan pptlint-report.json --adapter powerpoint-copilot --lang zh-CN --output copilot-prompt.md
```

修复计划会覆盖报告中的全部问题，而不是只取前三项。每项都说清位置、实际后果、谁适合处理以及复检条件；未知规则一律要求人工判断，不会擅自编造修改指令。

### 明确授权后清理隐私副本

PPTLint 只能自动处理三类低风险内容，而且每一项都必须单独写 `--apply`：

```bash
uvx pptlint fix input.pptx \
  --output input.delivery.pptx \
  --apply clear-personal-metadata \
  --apply remove-comments \
  --apply remove-speaker-notes
```

源文件不会被覆盖，已存在的输出也不会被覆盖。成功后会同时生成清理回执、修改前后报告和对比证据。隐藏页、外部链接、字号、位置、遮挡、整页图片和品牌字体都不会被自动修改。

## 团队交付规范

生成一份安全的 YAML 模板：

```bash
uvx pptlint policy init pptlint-policy.yml
uvx pptlint check output.pptx --policy pptlint-policy.yml --lang zh-CN
```

策略可以约束批准字体、品牌色、最小字号、外部链接、备注、隐藏页和图片说明。未知字段会直接报错，不会悄悄忽略。

确有业务原因需要保留例外时，在策略中记录规则、页面、原因和到期日：

```yaml
exceptions:
  - ruleId: readability.small-font
    slides: [12]
    reason: 法律免责声明已经材料责任人确认
    expires: 2026-12-31
```

生效和过期的例外都会记录在报告中；没有理由的例外会被拒绝。

## 检查范围与边界

| 你真正关心的问题 | PPTLint 检查什么 |
|---|---|
| 文件能否正常打开 | PPTX 包结构、关系、内容类型、媒体、页面列表和真实渲染 |
| 会议室里是否看得清 | 越界、实质重叠、裁切风险、字号、对比度和页面比例 |
| 换电脑后是否稳定 | 字体、外部文件、动画、转场、音视频和备注关系 |
| 别人能否继续编辑 | 原生文字、表格、图表、形状，以及整页图片覆盖 |
| 是否把内部内容带出去 | 备注、批注、隐藏页、作者信息、本地文件和外部链接 |
| 文件是否便于交接 | 文件体积、重复媒体、嵌入字体和动态内容事实 |

PPTLint 不判断审美、论点、事实正确性或说服力；低置信提醒不会阻断交付。如果要先生成或人工修复 PPT，可以使用 [Ultimate PPT Master](https://github.com/kdnsna/ultimate-ppt-master-skill)，再由 PPTLint 独立复检。

## GitHub Actions

```yaml
- uses: kdnsna/pptlint@v1
  with:
    path: output.pptx
    profile: ai-generated
    renderer: wireframe
```

即使检查没有通过，HTML 和 JSON 报告仍会上传。Action 默认生成 `shareable` 安全分享版；仅在受控仓库确需页面预览时设置 `report-mode: full`。

## 稳定接口与开发

- 当前报告：[`pptlint-report/v2`](schema/pptlint-report-v2.schema.json)
- 旧版报告：[`decklint-report/v1`](schema/decklint-report-v1.schema.json)
- 前后对比：[`decklint-comparison/v1`](schema/decklint-comparison-v1.schema.json)
- 修复计划：[`pptlint-repair-plan/v1`](schema/pptlint-repair-plan-v1.schema.json)
- 清理回执：[`pptlint-repair-receipt/v1`](schema/pptlint-repair-receipt-v1.schema.json)
- 修复验证：[`pptlint-repair-verification/v1`](schema/pptlint-repair-verification-v1.schema.json)
- 验证凭证：[`pptlint-verified/v1`](schema/pptlint-verified-v1.schema.json)
- 公开 AI-PPT 兼容性验证：[33 份真实 PPTX 的来源和结果](validation/README.md)
- 退出码 `0`：完成；`1`：需要修改；`2`：文件或运行错误。

```bash
uv venv --python 3.13
uv pip install -e '.[dev]'
PYTHONPATH=src .venv/bin/python -m pytest
.venv/bin/ruff check src tests tools
```

`decklint` 作为兼容别名继续保留；所有新用户文档和命令统一使用 `pptlint`。

---

<p align="center">
  <strong>MIT · 本地 · 默认只读 · 永不改原文件 · 不上传 · 不调用模型 · 不收集遥测</strong>
</p>
