{
  "$schema": "https://bestaiskill.com/schemas/agent-install/2.json",
  "skill": "youtube-to-ebook",
  "built": "2026-10-26",
  "control_level": 4,
  "control_level_label": "L4 高权限",
  "capabilities": [
    "execute_command",
    "install_deps",
    "network",
    "write_file"
  ],
  "required_controls": {
    "agent": [
      "sandbox_recommended",
      "graded_authorization"
    ],
    "admin": [
      "approval_process",
      "rollback_support",
      "full_audit"
    ]
  },
  "evidence": [
    {
      "file": "scripts/",
      "summary": "Local script/command execution: python main.py (main pipeline; entry point specified in README/SKILL.md)"
    },
    {
      "file": "scripts/ 或 SKILL.md",
      "summary": "Dynamic external language package dependency installation declared"
    },
    {
      "file": "网络端点",
      "summary": "External network access declared: googleapis.com YouTube Data API v3 (channels.list / playlistItems.list, with dev key)"
    },
    {
      "file": "本地工作目录",
      "summary": "File I/O and artifact output: processed_videos.json (tracks processed videos within project root)"
    }
  ],
  "verification": {
    "method": "第二遍独立重读 + 反查（换角度抓第一遍的错）：① 逐文件核对 import 与真实调用点（requests/googleapiclient/anthropic/ebooklib/smtplib/subprocess），确认每条 external_dep 都能落到代码行；② 全仓 URL 正则 + 关键词扫描，无隐藏端点、无 .env 提交、无 key 硬编码；③ 用脚本比对『模块 × 库』矩阵，发现 youtube-transcript-api 与 argparse 在所有 .py 中零引用——据此推翻 SKILL.md/README 的两处描述；④ 把 SKILL.md/README 的项目结构表与实际 git 清单对照，发现 channels.txt 与 `python main.py --channels` 均不存在；⑤ 文档『不要用云服务器/GitHub Actions』与仓库自带 newsletter.yml 正面冲突，逐字复核双方原文后记为 discrepancy；⑥ 元数据核对 gh api（555★ / license=null / pushed_at 2026-01-28T22:46:31Z）与本地 HEAD 7f67fd6 一致，license 以『README 声称 MIT 但无 LICENSE 文件』如实记录。",
    "second_pass": [
      {
        "item": "四阶段流水线与去重逻辑",
        "status": "ok",
        "detail": "main.py 五个 import 与方法体逐行核对；video_tracker.py 的 load/save/is_video_processed/mark_video_processed 与 processed_videos.json 路径均存在。"
      },
      {
        "item": "字幕来自 Supadata（而非 SKILL.md 所述 youtube-transcript-api）",
        "status": "discrepancy",
        "detail": "代码侧唯一实现是 Supadata（get_transcripts.py 顶部注释与 SUPADATA_TRANSCRIPT_URL 常量）；但 SKILL.md『Known Pitfalls』#3 仍在教 'ytt_api = YouTubeTranscriptApi(); transcript = ytt_api.fetch(video_id)'，requirements.txt 也仍列 youtube-transcript-api——全仓 .py 无一处 import youtube_transcript_api。文档描述的是已被替换掉的旧实现。"
      },
      {
        "item": "『云服务会被 YouTube 封，请本地跑』与仓库自带 Actions 工作流",
        "status": "discrepancy",
        "detail": "SKILL.md『### 6. Cloud Automation Blocked … Solution: Run automation locally on your Mac using launchd』、README『| Cloud servers blocked | Run locally, not GitHub Actions |』，但 .github/workflows/newsletter.yml 仍是完整的 ubuntu-latest 定时任务（cron '0 15 * * 3'），且注入 5 个 secrets。两种说法不能同时成立；从代码看 Supadata 正是为绕开该封锁而引入（'Supadata doesn't get blocked by YouTube'），故云路径更可能是『能跑但不保证字幕』。"
      },
      {
        "item": "配置入口 channels.txt 与 `python main.py --channels`",
        "status": "discrepancy",
        "detail": "SKILL.md 命令表写 '| `python main.py --channels` | Edit channel list |'、Key Files 与 README 结构表都列 channels.txt；实际 main.py 无 argparse（全仓 .py 无 argparse 引用），频道是 get_videos.py 的 CHANNELS 常量，dashboard 通过 CHANNELS_FILE = get_videos.py 改源码。channels.txt 在仓库中不存在。"
      },
      {
        "item": "SUPADATA_API_KEY 的文档覆盖",
        "status": "discrepancy",
        "detail": ".env.example 只有 YOUTUBE_API_KEY / ANTHROPIC_API_KEY / GMAIL_ADDRESS / GMAIL_APP_PASSWORD 四项，而 get_transcripts.py 在无该 key 时直接返回 None（『⚠ SUPADATA_API_KEY not set in .env file』）导致流水线无字幕。文档缺失这把必需 key（CI workflow 里反而有 secrets.SUPADATA_API_KEY）。"
      },
      {
        "item": "许可声明一致性",
        "status": "discrepancy",
        "detail": "README 末段写 'MIT - Use freely, modify as needed.'，但 git ls-tree 无 LICENSE 文件，gh api license=null（spdx 未识别）。已在 meta.license 如实标注冲突，未按 MIT 硬写。"
      },
      {
        "item": "邮件投递与留档细节",
        "status": "ok",
        "detail": "SMTP_SSL('smtp.gmail.com', 465) + server.login + sendmail；MIMEBase('application','epub+zip') 附件；save_newsletter_archive 写 html/epub/json 三件套；成功后 os.remove 临时 EPUB——与 SKILL.md『Email Delivery (Optional)』一致。"
      },
      {
        "item": "dashboard 的破坏性写回（源码/plist）",
        "status": "ok",
        "detail": "save_channels 重写 get_videos.py 的 CHANNELS 块、风格保存重写 write_articles.py 内 prompt、save_schedule 重写 ~/Library/LaunchAgents plist 并 launchctl bootout/bootstrap —— 已在 file_writes 与 injection_surface 记入；另确认 requirements.txt 未含 streamlit（README 要求单独 pip install）。"
      },
      {
        "item": "外部依赖清单完整性",
        "status": "ok",
        "detail": "全仓扫描仅出现上述端点（googleapis/youtube shorts/supadata/anthropic/smtp.gmail.com/fonts.googleapis.com）；无自建服务、无遥测、无第三方 SDK 除 google-api-python-client/anthropic/ebooklib/markdown/dotenv/requests。"
      },
      {
        "item": "个人路径与隐私残留",
        "status": "ok",
        "detail": "run_newsletter.sh 硬编码 '/Users/bytedance/youtube-newsletter/…'（作者本机路径），README 也以本机路径排障；未发现真实凭证或私人数据被提交。"
      },
      {
        "item": "license/stars/commit 元数据",
        "status": "ok",
        "detail": "gh api repos/zarazhangrui/youtube-to-ebook：555★、pushed_at=2026-01-28T22:46:31Z、archived=false、license=null；本地 HEAD=7f67fd6b55a272012df3767cf6d8c54bd2d7a9f3，与任务书 pin 一致。"
      }
    ],
    "level": 1,
    "level_label": "V1 已固定",
    "commit": "7f67fd6b55a272012df3767cf6d8c54bd2d7a9f3",
    "sha256": "2f7c07f82fd3668b581fd9c9df321c0cdfc8aedecfa250cb67e9f09c8164d484",
    "reviewed_by": null,
    "reviewed_at": null
  },
  "assessed_at": "2026-10-25",
  "method_version": "2.0",
  "mirror": {
    "archive": "https://skillpub.pages.dev/r2/v/2026-09-15/youtube-to-ebook.tar.gz",
    "sha256": "2f7c07f82fd3668b581fd9c9df321c0cdfc8aedecfa250cb67e9f09c8164d484",
    "commit": "7f67fd6b55a272012df3767cf6d8c54bd2d7a9f3"
  },
  "original": {
    "github": "https://github.com/zarazhangrui/youtube-to-ebook",
    "path": "",
    "commit": "7f67fd6b55a272012df3767cf6d8c54bd2d7a9f3"
  }
}