Files
UHD_Media_Tool/docs/porting/license-and-provenance.md
T
rootandClaude Opus 5.5 b343dddbf6 docs: 清理过程文档,CHANGELOG 补齐 0.3.8–0.3.14
- 删除 docs/plan 下 00–18 的计划、评审、验收、发布记录与升级证据,docs/spikes 与 spikes 验证代码
  (保留 spikes/movieclaw-src 本地克隆),以及 4 份一次性审查 / 调研;全部可在 ceb66f8 查到
- MP 对照移到 docs/porting/moviepilot-v3-comparison.md;经验教训改为 docs/plan/lessons.md(补第 25 条)
- docs/plan/README.md:文档放哪、当前状态、待办
- 引用改写:代码注释指向在维护的文档,其余注明已删除与 git 位置;清掉原有 6 个失效链接
- README 开头改为当前状态与入口;CHANGELOG 补齐 0.3.8–0.3.14 与工程变更

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-02 16:08:09 +08:00

16 KiB
Raw Blame History

许可证核对与来源登记(MoviePilot / MovieClaw)

本文依据 REQ §14.2 和任务书 §1"参考源码"一栏,属于工程合规边界的说明,不是法律意见。在对外分发或商业化之前,必须针对具体要发行的产品另行做法律审查(REQ §14.2 末段)。

1. 核对结论

项 MoviePilot MovieClaw
仓库 https://github.com/jxxghp/MoviePilot(分支 v3) https://github.com/movieclaw/movieclaw(main)
本次核对的提交 e6820a83ab05e8a00eb0e14adf0f357faa965c7e(2026-08-30,version.py = v3.0.0)。本地路径 /opt/moviepilot-plus/upstream/MoviePilot,是单提交浅克隆 fc9eb7248dd9c4f7cd8f3fbd704a357b0b766b90(REQ 附录 [S16])。本机没有源码(find /opt -maxdepth 3 -iname "*claw*" 没有结果),是通过 GitHub API 和 raw 取到该提交的 LICENSE、pyproject.toml 以及站点配置原文(见 moviepilot-downloader-and-sites.md §0)
REQ 附录快照 33da9ce65d5020a8e087584a3321c1ff353c1921:本地仓库里没有这个对象,无法逐行比对。以本表提交为准,引用行号时必须写明提交 与附录一致
仓库许可 根目录 LICENSE 是 GNU GPL v3 全文(674 行,md5 1ebbd3e34237af26da5dc08a4e440464) 该提交的 LICENSE 是 修改版 Apache-2.0,附加非商业条件;LICENSE 第 44-45 行写明"v0.27.0 及之前发布的版本以 MIT 许可证发布……本许可证适用于 v0.27.0 之后发布的版本"
包元数据 pyproject.toml 没有 license 字段 pyproject.toml 第 7 行 version = "0.27.0",第 11 行 license = { text = "MovieClaw License (Apache-2.0 with non-commercial conditions)" }
MovieClaw 附加条件要点 — 两者冲突时附加条件优先;免费使用仅限非商业(个人/家庭自用、亲友间非营利共享、学习研究教学);公司内部使用也算商业使用,需要书面授权;再分发要附许可全文,衍生版本继续适用本许可。本项目给用户个人和家庭的媒体设施使用,是否落在"非商业"范围内要由用户确认;在确认之前,对 MovieClaw 一律只参考字段结构(data-ref)
附加声明 README.md 第 17 行写"仅用于学习交流使用,请勿在任何国内平台宣传该项目",第 79-80 行免责申明写"不得用于商业用途……不建议对用户认证机制进行规避或修改并公开发布"。这些是 README 里的声明,不是 LICENSE 的附加条款。GPLv3 §7 不允许附加"进一步限制",但按 REQ §14.2 的要求,本项目仍然尊重这些声明,不把它们解读成可以忽略的内容 附加条件写在 LICENSE 正文里,有约束力:商业使用需要书面授权,衍生版本继续适用同样的条款
版本字段陷阱 — main 的 pyproject 版本号仍是 0.27.0,但 LICENSE 已经是附条件版本。不能根据版本号推定 main 是 MIT(REQ §14.2 原话)。要按 MIT 使用,只能引用已经核实过的 v0.27.0 及更早的 tag,而且要逐个文件核对那个 tag 附带的许可

1.1 MP 中的非源码或闭源部分(不得作为参考源)

组件 位置 状态 处理
SitesHelper(站点认证、流控、站点索引定义) app/application/site/sites.cpython-314-x86_64-linux-gnu.so,已被 .gitignore:4 忽略;仓库只有 sites.pyi 类型存根 闭源二进制,由 docker/Dockerfile:261-262 从 jxxghp/MoviePilot-Resources 下载 不反编译,不参考。 站点选择器改以 MovieClaw 配置和我们自己抓取的页面为准
站点样例配置 tests/test_rust_accel.py 里有少量站点 indexer 样例(公开测试数据) GPL-3.0 只用来理解字段语义,不作为选择器的来源
站点定义数据 app/application/site/user.sites.v3.bin,已被 .gitignore:12 忽略,内容加密 同上 不解密,不使用
Rust 加速 moviepilot_rust 0.3.3 以 wheel 形式安装在 .venv,源码仓库是 jxxghp/MoviePilot-Rust wheel 附带的 LICENSE 是 GPLv3 只对照 Python 参考路径(见 moviepilot-metadata-recognition.md §0.1)
内嵌的 tmdbv3api app/modules/themoviedb/tmdbv3api/*,文件头没有许可说明,仓库里也没有单独的 LICENSE/NOTICE 来源推测是 AnthonyBloomer/tmdbv3api(MIT),但未核实 不使用;本项目直接调 TMDB REST v3
第三方运行依赖 anitopy~=2.1.1、cn2an~=0.5.24、pinyin2hanzi~=0.1.1、regex、zhconv 等(pyproject.toml) 各有各的许可 本项目如需等价的 npm 库,另行选型并单独登记,不因为 MP 用过就默认可用

2. 本项目的迁移边界

任务书 00-first-version-plan(已删除,见 git ceb66f8) §1 规定:"MoviePilot:GPLv3,只做行为对照与 TS 重写,不复制文件"。REQ §14.1 允许"以具体实现为参考迁移业务逻辑"。两条放在一起执行时,按下表办。

允许 不允许
阅读上游源码,理解调用链、条件分支、状态机和数据结构,用我们自己的语言写成行为对照记录(也就是 docs/porting/*.md) 把 .py、.yaml 文件或者大段代码原样放进仓库,包括放进注释或测试 fixture
用本机上游解释器运行上游代码,只为得到行为输出,作为 parity 期望值(脚本放在仓库外,或放在 packages/testkit/scripts/ 并标注"可选、需要本机 MP") 让 CI 依赖上游代码;把上游模块作为运行时依赖;通过子进程调用 MP
按对照记录独立编写 TS 实现,命名、结构和类型遵循本项目约定 逐行机械翻译(包括让 AI 逐行改写)后当作原创。REQ §14.2:跨语言翻译或 AI 改写不会自动让移植成为没有来源的独立原创
引用事实性常量:协议字段名(qB WebUI API、M-Team API、TMDB API)、站点公开的 HTML 结构、行业通用词表(WEB-DL、REMUX、DDP5.1) 照搬上游整理过的数据表:RELEASE_GROUPS 站点到组名的正则表(app/domain/meta/releasegroup.py:26)、StreamingPlatforms 平台码表(app/domain/meta/streamingplatform.py,约 270 条)、_name_nostring_re 干扰词表。这类表要自行编制,并在 ledger 里写明来源(例如公开的 scene/P2P 命名规范、站点官方规则页)
上游测试里的标题字符串(事实数据)可以作为输入语料 整份拷贝 tests/cases/meta.py 这类测试文件;期望值必须由我们自己按 REQ 判定,不是照抄上游的 target
MovieClaw:阅读 YAML 的字段结构,参考其字段设计 在没有书面授权时拷贝 MovieClaw main 的配置或代码(附条件许可);把 main 的内容当作 MIT 使用
MovieClaw tag v0.27.0(c79bb1b0,MIT) 的资产可以原样复制或转换(kind=copied-mit),前提是保留 MIT 全文与 Copyright (c) 2026 MovieClaw(packages/adapters/src/sites/definitions/NOTICE-MovieClaw.md),每个产物写明来源提交与路径(站点定义 JSON 的 provenance 字段),且只经 git show v0.27.0:<path> 读取(用户 2026-09-27 确认,依据 movieclaw-assessment.md §1) 复制 v0.27.0 之后(251f1988 起附条件许可)的任何内容;复制 MC 仓库内自带独立许可的第三方子组件(skill-creator Apache-2.0、liquid-glass)而不遵守其各自许可

对每个 PR 的要求:只要实现参考了上游,PR 描述里就必须写"参考:docs/porting/<文件>#<节>",并在 §3 ledger 里补一行,登记状态为 behavior-ref。只有真的复制了代码或数据时,才登记为 copied;按目前的边界,不应出现 copied。例外是 copied-mit:复制 MIT 许可的资产(目前仅 MovieClaw v0.27.0),必须 notice_required=是 并附 NOTICE。

2.1 分发时的注意事项(首期不分发,先写在这里)

  • 本项目用于内部部署(REQ §1.1.1)。内部使用不是忽略上游条款的理由(REQ §14.2)。
  • 如果以后出现 copied 条目:MP 来源的部分会让整个分发物受 GPLv3 约束(需要同许可、提供源码、保留声明);MovieClaw main 来源的部分需要书面授权。发现这种情况要先移除,再讨论。
  • Docker 镜像不得包含 MP 或 MovieClaw 的任何文件,也不得在构建时下载 MoviePilot-Resources。

3. Component ledger

3.1 字段模板

字段 说明
id CL-<序号>
our_module 本项目的文件或函数,例如 packages/domain/src/title/parse.ts#parseReleaseTitle
kind behavior-ref(只参考行为)/ data-ref(参考了数据结构,内容自行编制)/ copied(复制,原则上禁止)/ copied-mit(复制 MIT 资产,须保留 NOTICE,见 §2)/ dependency(npm 依赖)
upstream 仓库 URL
commit_or_version 精确提交或 tag,不能写 main
upstream_paths 文件:函数:行号
license 上游在该提交下的许可
porting_doc docs/porting/*.md#节
modifications 和上游行为的差异摘要,要引用对照文档里的"调整项"
notice_required 是 / 否(copied 或 MIT/Apache 依赖要保留版权声明)
distribution internal-only / image / source
reviewer、date 登记人和日期

3.2 初始登记(W0-C)

id our_module(建议) kind upstream commit upstream_paths license porting_doc modifications notice distribution
CL-001 packages/domain/src/title/parse.ts behavior-ref MoviePilot e6820a8 app/domain/metainfo.py:495,533;app/domain/meta/metavideo.py:163-874;app/domain/meta/metabase.py:244-431,719 GPL-3.0 metadata-recognition §2-§3 新增 airDate、issue、cut、packHint、未知发布组兜底;调整了 merge 条件 否 internal-only
CL-002 packages/domain/src/title/custom-words.ts、episode-format.ts behavior-ref MoviePilot e6820a8 app/domain/meta/words.py:54-221;app/application/formatting.py:84-230 GPL-3.0 metadata-recognition §4 禁用 eval,规则版本化,偏移范围收窄 否 internal-only
CL-003 packages/domain/src/title/release-groups.ts data-ref MoviePilot e6820a8 app/domain/meta/releasegroup.py:26,117,127 GPL-3.0 metadata-recognition §5 只参考"站点到组名"的结构和界定符语义,组名表自行编制 否 internal-only
CL-004 packages/domain/src/identity/tmdb-match.ts、packages/adapters/src/tmdb/* behavior-ref MoviePilot e6820a8 app/modules/themoviedb/__init__.py:190-930;app/modules/themoviedb/tmdbapi.py:130-770,961-1045;cache.py:143-265 GPL-3.0 metadata-recognition §7-§8 候选打分,人工锁定,缓存放 PG 否 internal-only
CL-005 packages/adapters/src/nfo/writer.ts、packages/tasks/src/refresh-metadata.ts behavior-ref MoviePilot e6820a8 app/chain/scraping.py:148-395;app/modules/themoviedb/scraper.py:35-420 GPL-3.0 metadata-recognition §10 刮削改为独立任务;uniqueid 里写本地 UUID 否 internal-only
CL-006 packages/domain/src/organize/*、packages/adapters/src/fs/*、packages/tasks/src/verify-and-import.ts behavior-ref MoviePilot e6820a8 见 moviepilot-transfer.md §2 各表 GPL-3.0 transfer §2-§4 见 transfer §3 的必须偏离表 否 internal-only
CL-007 packages/adapters/src/qbittorrent/* behavior-ref MoviePilot e6820a8 app/modules/qbittorrent/__init__.py、qbittorrent.py(行号见 downloader-and-sites 文档) GPL-3.0 downloader-and-sites §qB 标签接管,删数据前做引用检查 否 internal-only
CL-008 packages/adapters/src/sites/nexusphp/* behavior-ref MoviePilot e6820a8 app/modules/indexer/spider/*、app/modules/indexer/parser/nexus_php.py、nexus_audiences.py GPL-3.0 downloader-and-sites §站点 站点定义自行编制;不使用闭源 SitesHelper 否 internal-only
CL-009(retired → CL-012) packages/adapters/src/sites/nexusphp/configs/audiences.ts data-ref MovieClaw fc9eb72 src/movieclaw_tracker/sites/configs/audiences.yaml MovieClaw License(Apache-2.0 加非商业条件) downloader-and-sites §MovieClaw 只参考字段结构;选择器值以我们自己抓取的观众页面为准重新编写 否(未复制) internal-only
CL-010(retired → CL-013) packages/adapters/src/sites/mteam/* behavior-ref + data-ref MovieClaw + MoviePilot fc9eb72 / e6820a8 MC:sites/configs/mteam.yaml、sites/custom/mteam.py;MP:app/modules/indexer/parser/mtorrent.py MC 附条件 / GPL-3.0 downloader-and-sites §M-Team API 字段以 M-Team 公开 API 为准,按 API Key 模式实现 否 internal-only
CL-011 packages/testkit/fixtures/title-parity.json data-ref MoviePilot e6820a8 输入语料参考 tests/cases/meta.py;期望值自行判定 GPL-3.0(原测试文件) metadata-recognition §9 只取标题字符串,必要时脱敏 否 internal-only
CL-012 packages/adapters/src/sites/definitions/*.json(23 站)、definitions/manifest.generated.ts、spider/mc-selector.ts、scripts/mp-sync/movieclaw-import.mjs copied-mit MovieClaw v0.27.0(c79bb1b0) src/movieclaw_tracker/sites/configs/*.yaml;selectors.py NexusPHPSelectors 默认值;frameworks/nexusphp.py _css_text MIT downloader-and-sites §W1-3c YAML 转为 MP indexer schema + umt;观众/馒头/HHClub/CHD 由 scripts/mp-sync/movieclaw-overrides/*.json 覆盖;除 4 主力站外 enabled:false 是(definitions/NOTICE-MovieClaw.md) internal-only
CL-013 packages/adapters/src/sites/mteam/* behavior-ref + copied-mit MovieClaw + MoviePilot v0.27.0(c79bb1b0)/ e6820a8 MC:sites/configs/mteam.yaml(→ definitions/mteam.json)、sites/custom/mteam.py(字段对照);MP:app/modules/indexer/spider/mtorrent.py、parser/mtorrent.py MIT / GPL-3.0 downloader-and-sites §M-Team 定义由 MC 转换 + W1-3b 值覆盖;API 行为按 MP 是(MC 部分) internal-only

新增 npm 依赖(例如 anitopy 的等价实现、re2、fast-xml-parser)按 kind=dependency 登记,填锁定版本和 SPDX。

3.3 ledger 的维护规则

  1. ledger 以本文件 §3.2 为唯一登记处,按 id 追加,不删除旧行;撤销时把行标记为 retired。
  2. 上游提交升级时,新增一行,写新的提交号,不覆盖旧行。对照文档里的行号也要按新提交重新核对。
  3. copied 行出现时,CI 必须失败。建议在 scripts/ 里加一个检查:ledger 中 kind=copied 的行数必须为 0。copied-mit 不在此列,但必须有 NOTICE 文件且 notice=是。
  4. 审核人检查三件事:PR 里有没有"参考:"链接;ledger 有没有对应行;diff 中有没有大段和上游高度相似的代码(可以用 jscpd 这类工具,把上游目录作为外部语料做一次抽样检查)。

4. 待办与未决

项 状态
REQ 附录快照 33da9ce 和本地 e6820a8 的差异 未比对,本地没有该对象。需要时 git fetch --depth=1 origin 33da9ce... 再比对(需要网络)
MovieClaw 是否有可用的 ≤v0.27.0 MIT tag,以及 tag 内的文件许可 未核对。只有在决定复用 MovieClaw 历史代码时才需要做
tmdbv3api 内嵌副本的来源和许可 未核实;本项目不使用它
对外分发 首期不做;如果要做,先完成法律审查