diff --git a/.agent/skills/pdf-fidelity-restore/SKILL.md b/.agent/skills/pdf-fidelity-restore/SKILL.md index 1313a2b90..9f056e5f0 100644 --- a/.agent/skills/pdf-fidelity-restore/SKILL.md +++ b/.agent/skills/pdf-fidelity-restore/SKILL.md @@ -35,12 +35,17 @@ Markdown,并通过浏览器逐页对比将差异修复至完全一致。 4. **等待完成**:轮询文档 `markdown_extract_status` 至 `completed`(失败则查 `markdown_extract_error` 并 `refresh_markdown` 重试)。 5. **渲染核对**:在 Documents 页 View 渲染结果(react-markdown + remark-gfm/math + rehype-katex/raw/highlight/sanitize)。 6. **逐页对比**:按上「一比一还原范围」逐页 / 逐模块比对源 PDF 与渲染 Markdown,逐条记录差异(页号 + 类别 + 现象)。 -7. **发现一处修一处(分层修复路由)**: - - **渲染层**:`DocumentMarkdownRenderer` / sanitize schema / `DocumentImage`(图片宽高、表格、KaTeX、代码高亮、figure/figcaption、TOC 锚点)。 - - **摄取层**:图片链接重写、资产存储、元数据(`knowledge/ingestion/extraction.py`、`knowledge/_shared.py`)。 - - **管线层**:perceives 引擎选型、分批边界、跨片合并(图片去重、边界图注补救)、图片分辨率与显示尺寸提取(`perceives/ops/pdf.py`)。 +7. **发现一处修一处(三杠杆分层修复路由 + 归因)**:每个缺陷先走「双源验证决策树」归因到杠杆/层,再定点改(单轮一个逻辑根因,≤3 文件 ≤2 杠杆): + - **①工程代码·管线层**:perceives 引擎选型、分批边界、跨片合并(图片去重、边界图注补救)、图片分辨率与显示尺寸提取(`pipeline/stages/pdf/*`、`engine_selector.py`、`ops/pdf.py`)。 + - **①工程代码·摄取层**:图片链接重写、资产存储、元数据(`knowledge/ingestion/extraction.py`、`knowledge/_shared.py`)。 + - **①工程代码·导出层**:wiki 发布资产 bake / 链接重写(`knowledge/lifecycle/wiki_export_service.py`)。 + - **①工程代码·渲染层 wiki**:`MarkdownRenderer.tsx` / `ZoomableImage` / `ResponsiveTable` / `CodeBlock` / sanitize schema(图片宽高、表格、KaTeX、代码高亮、TOC 锚点)。 + - **①工程代码·渲染层 ui**:`DocumentMarkdownRenderer.tsx` / `DocumentImage` figcaption / `parsePixelValue` / `documentSanitizeSchema`(注意 wiki 与 ui 的 sanitize `style` 放行 / figcaption 行为不对称)。 + - **②Skills 本体**:本 Skill 的规则集——发现的跨 doc 结构性 insight 回写此处(如「图注双源铁律」),升级归因路由表。 + - **③流程自身**:巡检/还原流程的采样、评分、归因编排(慎改,影响面大)。 + - **双源验证决策树(归因前必走,防误归到 perceives)**:Step A 缺陷在候选 Markdown 源码里?是→管线/摄取;否→渲染层或流程伪缺陷。Step B 图片链接形式判摄取/导出。Step C wiki 错还是 ui 错→render_wiki/render_ui;皆对仅旧模拟栈错→流程伪缺陷(不计分)。 - **热更铁律(改 perceives `src/` 后必做,否则改动不生效)**:① 重启 perceives MCP 进程(Python 无热重载);② 清 checkpoint `rm -rf /output/.batch_state/*`(auto_batch resume 按 PDF 内容 SHA-1 缓存切片,不清则复用旧切片、跳过新代码,且完成异常快)。 - 改后经 `refresh_markdown` 重摄取或重载页面(**已清 checkpoint**),复核该项。 + 改后经 `refresh_markdown(resume=false)` 重摄取(**清 checkpoint 全量重跑**)或重载页面,复核该项。 8. **循环**:重复 6–7,直到逐页校验清单全绿;保留关键页源 PDF vs 渲染 Markdown 对比截图为证。 ## 逐页校验清单 @@ -54,17 +59,22 @@ Markdown,并通过浏览器逐页对比将差异修复至完全一致。 - [ ] 代码块语言识别与高亮正确 - [ ] 脚注 / 注释完整 -## 关键洞察(R10 沉淀) +## 关键洞察(R10 / 三杠杆改造 沉淀) - **auto_batch 切片间无共享可变状态**:引擎实例在 pool 复用时产物落盘目录须 per-call 唯一(`tempfile.mkdtemp`);级联/册封类状态(如 `_first_h1_seen`)须显式接收 `slice_index`,否则跨切片泄漏(标题层级错乱 / 公式重现)。 - **1:1 验收必须走到浏览器渲染态**:figure 过度捕获、KaTeX ParseError、公式双份等缺陷在 DB markdown 层不可见,仅浏览器渲染后暴露。 - **figure 图注双源风险**:多数图注已烘入 figure region PNG 像素,故 wiki/ui **不得**再从 `alt` 渲染 `figcaption`(会双图注);caption 语义由 `alt` 承载(无障碍 + 去重指纹),视觉由图内像素承载。 +- **三套渲染栈系统性差异**:旧 `_fidelity_render`(Python-Markdown 近似)/ wiki(react-markdown + remark/rehype)/ ui(另一套 react-markdown + sanitize)三栈不同——公式/Mermaid/figure/figcaption/图片尺寸/代码高亮会假阳性/假阴性。对照须用**真实 wiki 渲染栈**(巡检经 `patrol_wiki_env` 起 `next dev` 真页截图,非模拟渲染)。 +- **全绿率评分口径**:`score = round(pass_pages/total_pages×100)`(逐页校验清单全绿率),替代主观「100-Σ扣分」——CC 自评与 Judge 复核锁同一份程序化预筛 + defects,根治 ±20 振荡(ISSUE-128)。 +- **双源验证防误归因**:渲染层缺陷(候选 MD 正确、渲染器渲染错)会被误归到 perceives;归因前必走「候选 MD 源码层 vs 渲染层」双源决策树(见步骤 7)。 +- **inner-loop staging wiki 不 bake/serve 图片(V1 工具链限制,process 层 carve-out)**:`patrol_wiki_env publish-candidate` 仅写 entry Markdown、不烘焙资产;staging dev server(主仓 `negentropy-wiki`,`public/assets/` 无文档资产)对候选 MD 的 `./images/...` 相对引用返回 500/断图,`patrol_page_check` 报 `dom_broken_images=N`(且 Next SPA 对未匹配路由回退 200 HTML,curl 状态码会骗人,须看 content-type/PNG 头)。此为 **staging 工具链 V1 限制,非文档/渲染缺陷**——图资产本身忠实(全分辨率 PNG 落盘 `/.../images/`),生产经 `WikiExportService.export_single_entry(bake=True)` 烘焙到 `public/assets/{doc}/` 后由 ZoomableImage 正常渲染。**inner loop 见全图断 → 记 process carve-out(不扣分、不逐图排查);图片保真改由 (a) 直接核对落盘 PNG 资产尺寸/完整性 或 (b) Real-Render Gate bake 后截图二选一坐实。** ## 反模式(严禁) - 跳过逐页核对即声明完成; - 只比文字而忽略图 / 表 / 公式 / 代码 / 注释; -- 图片不还原原始显示尺寸(宽高)。 +- 图片不还原原始显示尺寸(宽高); +- 在 inner loop 对「全图断」(staging serving V1 限制)逐图排查或误归到 pipeline/render——context 耗尽根因;先认 staging carve-out,图片保真走资产直查或 Gate。 ## 完成判据 diff --git a/.agent/skills/science-video-pipeline/SKILL.md b/.agent/skills/science-video-pipeline/SKILL.md new file mode 100644 index 000000000..b26e7cbac --- /dev/null +++ b/.agent/skills/science-video-pipeline/SKILL.md @@ -0,0 +1,35 @@ +--- +name: science-video-pipeline +description: 把论文/综述做成动效图解科普视频的九阶段流水线(论文精读提取→策划→逐字稿 SSOT→双重校验→分镜→TTS 声音克隆→Remotion 场景实现→草渲抽帧 QA→终渲交付)。Use when producing or iterating an apps/negentropy-influence/episodes/*-video/ episode: narration.md, storyboard.md, IndexTTS voice cloning, Remotion scenes, frame QA, or final render; or when scaffolding a new episode. +allowed-tools: Read, Write, Edit, Glob, Grep, Bash +--- + +# 科普视频制作流水线(导航壳) + +本 Skill 是路由层:内容 SSOT 在 `apps/negentropy-influence/pipeline/skills/01–09.md`,工具 SSOT 在 +`apps/negentropy-influence/pipeline/scripts/`,不在此复制任何正文(防第二事实源)。 + +## 九阶段速查 + +| Stage | 做什么 | 规格链接 | 工具/命令(编排入口 `pipeline.py`) | 通过门 | +|---|---|---|---|---| +| ① 信源精读取证 | **A 型论文**:并行子代理逐章 + 官方站点补充;**B 型文档/代码/课程站点**:固定提交取证 + 证据三级 | [01](../../../apps/negentropy-influence/pipeline/skills/01-source-extraction.md) | A 型 `paper_extract.py`(map/text/captions/find/render);B 型 `source_ledger.py`(fetch/list/verify/sync/audit——sync/audit 消费系列级 [source-map](../../../apps/negentropy-influence/source-map/claude-code-explained.md)) | 全部断言可回溯;RISKY=0 | +| ② 策划 | 受众/结构/视觉契约(色彩语义) | [02](../../../apps/negentropy-influence/pipeline/skills/02-planning.md) | — | planning.md 六节齐 | +| ③ 逐字稿 | narration.md ★单一事实源 | [03](../../../apps/negentropy-influence/pipeline/skills/03-narration.md) | `pipeline.py build` | `build_narration.py` 通过 | +| ④⑤ 双重校验 + 分镜 | 真实性回溯 + 易懂性;beat 覆盖性 | [04](../../../apps/negentropy-influence/pipeline/skills/04-verification.md) / [05](../../../apps/negentropy-influence/pipeline/skills/05-storyboard.md) | `pipeline.py check`(+`--check-scenes`) | RISKY=0;覆盖率无缺句 | +| ⑥ TTS 配音 | 本人音色克隆(IndexTTS-2.5) | [07](../../../apps/negentropy-influence/pipeline/skills/07-tts-voice.md) | `pipeline.py tts --plan` | refs 指纹门 + 试听 + ETA | +| ⑦ Remotion 场景 | 代码动画实现(动效走 `src/motion/` 运动模型,分镜动效列 `@动词` 标注) | [06](../../../apps/negentropy-influence/pipeline/skills/06-remotion-implementation.md) | `tsc --noEmit` + `node --test scripts/motion.test.ts` | 七条渲染红线 + 运动层铁律 | +| ⑧ 草渲 + 抽帧 QA | 半分辨率快速迭代(`--beat-heads` 入场瞬态补盲;重制回归 `--compare`) | [08](../../../apps/negentropy-influence/pipeline/skills/08-render-qa.md) | `pipeline.py render` + `qa` | 自动体检零 FAIL | +| ⑨ 终渲 + 交付 | 1080p30 + srt/vtt | [09](../../../apps/negentropy-influence/pipeline/skills/09-final-render.md) | `render --final` + `captions` | 实测时长在预算窗 | + +## 关键不变量 + +- 逐字稿只改 `narration.md`;`narration.json`/`manifest.json` 是派生物。 +- **口播永不出现他集标题与集数序号**——顺序只在视觉层与 [series.json](../../../apps/negentropy-influence/series.json)(校验:`check_series.py`)。 + 多系列(顶层 `seriesList[]`)语义:反串线规则**跨系列全局**,顺序类规则**按系列内**判定。 +- **证据分级**:B 型信源里「他人对闭源产品源码的分析」属三级证据,口播必须带归属句, + 不得表述为产品既成事实;活数据(行数、总量、star 数)不进口播。 +- 每集 `pipeline.toml` 是可执行参数的唯一来源;README 不复制命令行参数。 +- 时序常数只在 `video/src/timing.json`(timing.ts 与 Python 共读);运动语汇(时长/缓动/弹簧/错峰)只在 `video/src/motion/`(frozen,改 = 模板 + 8 集同步)。 +- 声音样本是生物特征:不入库(`voices/refs.toml` 只存指纹),试听后即删。 +- 新集脚手架与复用边界(Python 集中 SSOT / Remotion 复制不共享)见 [pipeline/README.md](../../../apps/negentropy-influence/pipeline/README.md)。 diff --git a/.github/workflows/negentropy-perceives-ci.yml b/.github/workflows/negentropy-perceives-ci.yml index 9f171b1a0..3be832723 100644 --- a/.github/workflows/negentropy-perceives-ci.yml +++ b/.github/workflows/negentropy-perceives-ci.yml @@ -201,6 +201,20 @@ jobs: # PYSEC-2025-211..218 同约束),待交集支持 5.3.0+ 后升级 --ignore-vuln CVE-2026-4372 + # transformers PYSEC-2026-2290(CVE-2026-5241):LightGlue 模型加载路径 RCE—— + # 恶意 config.json 覆盖 trust_remote_code=False 触发远程代码执行。与上方 CVE-2026-4372 + # 同威胁模型:本项目仅加载第一方模型 artifact、不加载不可信 HF 仓库/config,攻击向量 + # 不可达;且 upstream 无已发布修复版本(Last affected 5.2.0,fix 仅在未发布 commit), + # transformers 锁定 <5.0.0 亦受 marker-pdf / surya 兼容交集制约 + --ignore-vuln PYSEC-2026-2290 + + # transformers CVE-2026-9856(GHSA-xrqw-3rrv-vx5w):save_pretrained 路径穿越 + # 任意写文件——需加载/保存恶意 HF 仓库模型触发。与上方 CVE-2026-4372 同威胁模型: + # 本项目仅加载第一方模型 artifact、不加载不可信 HF 仓库,攻击向量不可达; + # 修复版本 5.10.0,而 transformers 锁定 <5.0.0 受 marker-pdf / surya 兼容交集 + # 制约(与上方 PYSEC-2025-211..218 同约束),待上游适配后升级 + --ignore-vuln CVE-2026-9856 + # torch 2.10.0 本地内存破坏 / DoS,需攻击者构造恶意 tensor / pt2 文件; # 本项目仅加载第一方模型 artifact,无不可信输入路径,upstream 暂无 fix --ignore-vuln PYSEC-2025-189 @@ -217,6 +231,14 @@ jobs: # torch 2.10.0 CVE-2025-3000:本地内存破坏 / DoS,同上(需构造恶意 tensor;本项目仅加载第一方模型 artifact,upstream 暂无 fix) --ignore-vuln CVE-2025-3000 + + # setuptools PYSEC-2026-3447(CVE-2026-59890,CVSS 6.1):MANIFEST.in 排除规则在 + # macOS APFS/HFS+ 上因缺 Unicode(NFD/NFC)归一化被绕过,构建 sdist 时可能误打包应 + # 排除文件(本地向量、需在受影响 macOS 文件系统上构建 sdist)。本项目 CI 在 Linux + # 构建(非 APFS/HFS+)、产物不含敏感文件,攻击向量不可达;修复仅在 setuptools 83.0.0, + # 为保持既有 82.0.1 运行时 pin(见 pyproject,undetected-chromedriver 相关)不变、 + # 不为不可达低危 flaw 变更 build 后端版本,故此处 ignore 而不升级 + --ignore-vuln PYSEC-2026-3447 ) uv run pip-audit "${ignore_args[@]}" diff --git a/.github/workflows/twin-files-consistency.yml b/.github/workflows/twin-files-consistency.yml new file mode 100644 index 000000000..dba900bc7 --- /dev/null +++ b/.github/workflows/twin-files-consistency.yml @@ -0,0 +1,43 @@ +name: Twin Files Consistency + +# 孪生文件(逐字节副本)一致性校验 —— 横切关注点,正交于各 app CI。 +# +# 某些模块因构建边界无法提为共享包,只能以逐字节副本形式在多处持有。 +# 副本的固有风险是单边漂移:改了一处忘了另一处,缺陷从此静默分叉。 +# 本 job 校验登记表内每组副本精确字节相等,漂移时打印统一 diff 指明同步方向。 +# +# 登记表与判据详见 scripts/check_twin_files.py。pre-commit 侧有同名钩子做本地前置拦截; +# CI 侧是兜底 —— 未装 hooks 或 --no-verify 绕过的提交仍会在此被拦下。 +# +# fail-only:检测到漂移即阻塞合并,不自动同步(哪份权威取决于改动意图,机器不该代猜)。 + +on: + pull_request: + paths: + - "scripts/check_twin_files.py" + - "apps/negentropy-wiki/src/components/markdown/remark-math-sanitize.ts" + - "apps/negentropy-ui/utils/remark-math-sanitize.ts" + - ".github/workflows/twin-files-consistency.yml" + push: + branches: [master, main] + paths: + - "scripts/check_twin_files.py" + - "apps/negentropy-wiki/src/components/markdown/remark-math-sanitize.ts" + - "apps/negentropy-ui/utils/remark-math-sanitize.ts" + +permissions: + contents: read + +jobs: + twin-files-consistency: + name: Twin Files Check + runs-on: ubuntu-latest + timeout-minutes: 3 + steps: + - uses: actions/checkout@v4 + + - name: Set up uv + uses: astral-sh/setup-uv@v6 + + - name: Check twin files are byte-identical + run: uv run --no-project scripts/check_twin_files.py diff --git a/.gitignore b/.gitignore index d768e2932..3679f4f96 100644 --- a/.gitignore +++ b/.gitignore @@ -293,3 +293,34 @@ benchmarks/runs/ # PDF Fidelity Patrol 临时候选产物(评估用重转 Markdown,正常落 worktree 外暂存目录; # 此条兜底 agent 路径漂移误在 worktree 写候选的极端场景,确保其永不进 commit/PR) patrol-candidate.md + +# 科普视频工程(apps/negentropy-influence/episodes/-video)本地产物: +# tts.py 逐句音频 + manifest、Remotion 渲染产物均环境相关,不入 git。 +# 注:工程内的 .gitignore 被上方根级裸 `.gitignore` 规则挡住无法提交,规则须维护在此处。 +# 通配到集:`*` 只吃一级目录名(= 分集目录),故**新增分集无需再改本文件** +# —— 此前逐集枚举导致新集的音频产物在补齐 5 行前完全未被覆盖。 +# `out/` 已由上方通用规则(第 223 行 `out/`,非锚定)覆盖,此处不再逐集重复。 +apps/negentropy-influence/episodes/*/video/public/audio/ +apps/negentropy-influence/episodes/**/*.mp4 +apps/negentropy-influence/episodes/**/*.mp3 +apps/negentropy-influence/episodes/**/*.wav + +# 声音克隆参考样本(apps/negentropy-influence/pipeline/voices/):个人声音属生物 +# 特征信息,绝不入库。目录级忽略 + 白名单例外(README 与 refs.toml 指纹清单—— +# 后者只存哈希与生成参数,不含音频字节),防漏网音频格式(ogg/opus/wma 等)。 +# 注:必须写 `/*` 而非 `/` —— git 无法用 `!` 把被排除**目录**内的文件重新纳入。 +apps/negentropy-influence/pipeline/voices/* +!apps/negentropy-influence/pipeline/voices/README.md +!apps/negentropy-influence/pipeline/voices/refs.toml + +# negentropy-influence 的 uv 锁文件:该子项目**刻意不是可构建的 Python 包** +# (pyproject.toml 无 `[project]` 表,全部脚本走 `uv run --no-project` + 调用点 +# `--with` 注入依赖),故它不该有锁文件。但漏打 `--no-project` 时 uv 会当场把本 +# 目录当项目根,生成 `uv.lock` 与 `.venv/`——后者已由上方通用 `.venv` 规则覆盖, +# 前者没有,于是留下一个**可提交**的产物,一旦入库就与「不参与任何 uv workspace」 +# 的声明直接矛盾。 +# ⚠️ 必须逐路径锚定:兄弟子项目(negentropy / negentropy-perceives / cognizes) +# 的 uv.lock 是**受版本控制的依赖 SSOT**,裸 `uv.lock` 规则会把它们一起吞掉。 +# 执法(双向:本条命中 + 兄弟三份不被误伤)见 +# apps/negentropy-influence/pipeline/tests/test_subproject_hygiene.py。 +apps/negentropy-influence/uv.lock diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1ad52650e..3082ec1de 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -24,6 +24,9 @@ repos: args: [--markdown-linebreak-ext=md] - id: end-of-file-fixer - id: check-yaml + # pnpm 12 起根 pnpm-lock.yaml 是多文档 YAML(packageManagerDependencies 独占首个 + # 文档,见 ISSUE-175);只豁免这份机器产物,手写 YAML 仍受单文档校验约束。 + exclude: ^pnpm-lock\.yaml$ - id: check-toml - id: check-merge-conflict - id: check-added-large-files @@ -46,6 +49,18 @@ repos: files: ^apps/negentropy/ types_or: [python, pyi] + # ── Python: negentropy-influence/pipeline(科普视频公共管线) ────────── + # 与 negentropy 同一 ruff 修订版;此前仅覆盖 apps/negentropy/,管线脚本无 lint 门 + - id: ruff + name: ruff lint (influence-pipeline) + args: [--fix, --exit-non-zero-on-fix] + files: ^apps/negentropy-influence/pipeline/ + types_or: [python, pyi] + - id: ruff-format + name: ruff format (influence-pipeline) + files: ^apps/negentropy-influence/pipeline/ + types_or: [python, pyi] + # ── Node.js: apps/negentropy-ui ────────────────────────────────────────── # ESLint v9 flat config(eslint.config.mjs),零警告策略(--max-warnings=0) - repo: local @@ -106,3 +121,37 @@ repos: entry: uv run scripts/sync_versions.py check files: ^(VERSION|scripts/sync_versions\.py|package\.json|apps/negentropy/(pyproject\.toml|uv\.lock)|apps/negentropy-ui/package\.json|apps/negentropy-wiki/package\.json|apps/negentropy-perceives/(pyproject\.toml|uv\.lock)|packages/agents-chat-core/package\.json)$ pass_filenames: false + + # ── 孪生文件(逐字节副本)一致性执法 ───────────────────────────────────── + # 某些模块因构建边界无法提为共享包,只能以逐字节副本形式多处持有(登记表见脚本)。 + # 本钩子把「改一处必须同步另一处」从人工纪律升格为机器保证,漂移时打印统一 diff。 + # ⚠️ files: 覆盖登记表内全部路径 + 脚本自身;新增副本组时须同步扩充此正则, + # 否则钩子对新组**静默失效**(pre-commit 跳过不报错)。改动后须验证: + # 暂存一处副本改动,确认钩子 Passed 而非 Skipped。 + # 注:pre-commit 会 stash 未暂存改动、仅对暂存内容执行,故同组副本**必须整组 + # 一同 git add**;只暂存一侧会因另一侧仍是 HEAD 版本而判定漂移 —— 这正是 + # 期望语义:它连「部分同步的提交」也一并拦住。 + - repo: local + hooks: + - id: twin-files-consistency + name: Twin files consistency + language: system + entry: uv run --no-project scripts/check_twin_files.py + files: ^(scripts/check_twin_files\.py|apps/negentropy-wiki/src/components/markdown/remark-math-sanitize\.ts|apps/negentropy-ui/utils/remark-math-sanitize\.ts)$ + pass_filenames: false + + # ── 科普视频系列一致性(series.json 执法) ─────────────────────────────── + # 规则:口播反串线(自身标题排除)/多标题顺序/序号绑定/清单完整性/相对链接死链。 + # 注意:挂在内容修复之后落地;顺序调整类变更须先改 series.json 再动散文。 + # ⚠️ files: 写错是**静默**失效(钩子直接跳过、不报错),entry 写错才会响。 + # 改动本条后须验证:暂存一处子项目内改动,确认钩子 Passed 而非 Skipped。 + # `.agent/skills/science-video-pipeline/` 亦须在列 —— 该路由壳有 13 条入树 + # 链接受规则 5 执法,只改它的提交必须能触发本钩子。 + - repo: local + hooks: + - id: series-consistency-check + name: Series consistency (series.json) + language: system + entry: uv run --no-project apps/negentropy-influence/pipeline/scripts/check_series.py + files: ^(apps/negentropy-influence/|\.agent/skills/science-video-pipeline/|docs/\.agents/knowledge-map\.md|CHANGELOG\.md) + pass_filenames: false diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index d6623cea6..000000000 --- a/AGENTS.md +++ /dev/null @@ -1,57 +0,0 @@ -# AGENTS.md - -## Collaboration Protocol (协作协议) - -本文件旨在规范 AI Agent(Claude Code、Antigravity 等)在本项目中的代码与文档协作行为。项目定位详见 [README.md](./README.md)。 - -- **Core Language**: Output MUST be in **Chinese (Simplified)** unless serving code/technical constraints. -- **Tone**: Professional, precise, and evidence-based. - -## Engineering Code of Conduct (工程行为准则) - -**Core Philosophy**: **Entropy Reduction (熵减)**. 通过上下文锚定、复用驱动与标准化流水线,对抗软件系统的无序熵增。 - -### 道 (Mindset - 认知心法) - -- **Context-Driven (上下文驱动)**: 上下文是第一性要素 (Context Quality First)。任何变更需建立在深度理解之上(CDD),拒绝基于关键字匹配的机械式修改。 -- **Minimal Intervention (最小干预)**: 遵循奥卡姆剃刀与 YAGNI 原则,仅实施必要的变更,推崇演进式设计 (Evolutionary Design) 而非过度设计。 -- **Evidence-Based (循证工程)**: 杜绝主观臆断,核心决策需以**最新**且**权威**的文献(IEEE 格式)为佐证,构建“设计-实现-验证”的完整反馈闭环,确保每一项工程行动都能产生可观测的反馈信号(测试、日志、监控),以验证假设并指导迭代。 -- **Systemic Integrity (系统完整性)**: 具备全局视角与二阶思维 (Second-Order Thinking),评估变更对上下游依赖及整个生态(Engine, Adapter, Agent, UI)的“涟漪效应”,不只关注变更的直接结果,更要预测“结果的结果”(如引入缓存导致的陈旧数据、重试机制引发的雪崩),优先保障整体稳定性与逻辑自洽。 -- **Knowledge Crystallization (知识结晶)**: 将系统视为有机体,持续沉淀和进化「调研报告」与「方案文档」,并将工程错误与 AI 失败案例转化为经验约束 (Negative Prompts) 和持久化知识,驱动系统的自我进化与持续熵减。 -- **Proactive Navigation (主动导航)**: 智能体不应止步于被动响应,需即时转化为“领航者”。在交付任务结果的同时,**必须**基于上下文预判并提出**下一步最佳行动建议 (Next Best Action)**,不仅交付“答案”,更要交付“路径”,消除用户决策的认知摩擦。 - -### 法 (Strategy - 架构原则) - -- **Plan-First Default (规划先行)**: 面对任何非琐碎任务(预估步骤 > 3 或涉及架构级决策),**必须**率先进入 Plan 模式。规划产物需明确界定:功能边界、边缘 Case 应对策略、与现有逻辑的交互锚点以及预计改动的爆炸半径。 -- **Subagent Strategy (子代理并发策略)**: 面对高复杂度命题,严禁主 Agent 单点统揽。应贯彻“算力换空间”思路,果断编排 Subagent 进行任务拆解与并行攻坚,主 Agent 的职责需严格收敛于上下文协同与最终成果的组装整合。 -- **Verification Before Done (交付前验证定式)**: 严禁在缺乏确凿运行证据的情况下标记任务为“已完成”。交付阶段**强制要求**提供客观自证材料:Diff 变更分析、测试用例覆盖、实施日志截图及核心链路边缘 Case 验证结果,并时刻以“方案是否能通过 Staff Engineer 严格审查”的视角自检。 -- **Reuse-Driven (复用驱动)**: Compose over Reinvent。系统变更**必须**主动参考业界经典设计模式与最佳实践。在进入实质性编码前,需率先对相关领域的成熟范式进行深度调研,并结合当前项目上下文输出充分的关联分析与方案梳理。坚决贯彻“拿来主义”,优先通过组合与集成来构建系统,防范闭门造车与重复造轮子。 -- **Boundary Management (边界管理)**: 严控模块/Agent 间的职责边界与契约,确保高内聚低耦合,防范隐式依赖穿透。 -- **Orthogonal Decomposition (正交分解)**: 坚持“正交地提取概念主体”。识别系统中独立变化的维度并进行解耦(如机制与策略分离),确保单一概念主体的变更具备局部性,避免逻辑纠缠。 -- **Single Source of Truth (单一事实源)**:严格维护唯一的权威定义源。引用时**必须**使用轻量级指针 (Link/ID) 而非数据副本 (Copy-Paste),从根源消除断裂 (Split-Brain) 风险。 - -### 术 (Tactics - 执行规范) - -- **Structured AI-Pair Pipeline (规范化 AI 结对流水线)**: 遵循 **Specification-Driven (规约驱动)** + **Context-Anchored (上下文锚定)** + **AI-Pair (AI 结对)** 模式,将开发固化为可审计的流水线,避免代码腐化为无法维护的“大泥球 (Big Ball of Mud)”。 -- **Operational Excellence (卓越运营)**: - 1. **Git Discipline**: 默认严禁调用 git commit;当用户显式要求提交时,一律使用 Claude Code 的自定义 Slash Command: `/commit-no-push` 进行操作(若非 Claude Code 运行环境,则读取 /commit-no-push 命令中的规则执行)。严禁执行 Rebase; - 2. **Temp Management**: 临时产物(执行计划等)一律收敛至 `.temp/` 并及时清理; - 3. **Link Validity**: 确保所有引用的 URL 可访问且具备明确的上下文价值; - 4. **Testing**: 统一在 tests/ 下维护测试用例,区分单元测试(unit)和集成测试(integration),所有测试的本地运行总时间控制在 3 min 以内; - 5. **Pre-commit Hooks**: 首次克隆仓库使用 `uv run pre-commit install` 激活本地 Git hooks,使 Ruff lint(含 auto-fix)、Ruff format 及通用代码卫生检查在每次 commit 前自动运行。若 hooks 自动修复了问题,提交会被中断,执行 `git add -p` 审阅修复内容后重新提交即可; - 6. **Issue**: 在 [issue.md](docs/.agents/issue.md) 中维护你处理过的 Issue 摘要(问题描述、表因根因、处理方式、后续防范、同类问题影响与处理注意事项等),便于同类问题的跨上下文处理;注意识别相同 Issue,不要同 Issue 多处维护; -- **Package Management Standardization (包管理规范)**: - 1. **Python**: 严禁使用 pip/poetry,**必须**统一使用 `uv` 进行包管理与脚本执行(如 `uv run`); - 2. **JavaScript/TypeScript**: 严禁使用 npm/yarn,**必须**统一使用 `pnpm` 进行包管理与脚本执行; -- **Database Management**: 谨慎操作,数据迁移、测试等操作严禁将现有数据删除,谨慎操作数据迁移的回滚,防止数据被清理。 -- **Browser Validation Protocol (浏览器验证准则)**:Agent 不得自行完成、绕过或模拟任何 OAuth / SSO 认证流程,所有登录态均来源于用户已认证的 Chrome 主 profile(真实用户登录态)。完整协议(连通性自检、凭证管理、E2E 集成、实机回归等)详见 [浏览器验证协议](./docs/.agents/browser-validation.md); - 1. **安全红线**:禁止在 Sandbox 浏览器中跳转 Google 同意屏;禁止以模拟用户或第三方账号替代真实登录态;禁止要求用户在 chat 中粘贴密码、Cookie 或验证码; -- **Knowledge Map (知识索引)**:项目所有文档索引统一维护在 [知识索引](./docs/.agents/knowledge-map.md),并在文档目录变更时即时同步跟新; -- **Documentation Standards (文档规范)**: - 1. **Visual Documentation (图文并茂)**: 对于复杂逻辑,优先 **Mermaid Visualization Norms (Mermaid 可视化规范)**,构建“图文并茂”的直观文档; - - **色彩语义与兼容性**:为图表节点配置具备语义辨识度的色彩,并确保在深色模式(Dark Mode)下具有极高的对比度与清晰度; - - **逻辑模块化解构**:针对业务跨度较大的架构流程,强制采用 `subgraph` 容器进行层级解构与边界划分,以增强图表的自解说(Self-explaining)能力; - 2. **语言叙事**:用语精准,叙事完备,行文专业,聚焦核心,篇幅精炼,形象具体,体现真实作用与用户吸引性,字数恰当; - 3. **Direct Hyperlinking (直接跳转)**: 在文档中提及 Repo 内其他资源(文档/代码)时,**必须**构建可跳转的相对路径链接(如 `[Doc Name](./path.md)`),严禁使用“死文本”引用,以降低信息检索熵; - 4. **实操截图**:文档需要引入必要的浏览器实操截图时,需自行通过默认浏览器打开相关页面,通过实操现场截图并保留到文档路径进行文档引用; -- **Reference Specifications (IEEE)**:为保障工程决策的可追溯性与学术严谨性,核心引用需遵循 [reference-specifications.md](docs/.agents/reference-specifications.md)IEEE 标准引用格式; diff --git a/CHANGELOG.md b/CHANGELOG.md index c6c07775b..2416391b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,64 @@ 本文件遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/) 约定,版本号遵循 [SemVer](https://semver.org/lang/zh-CN/)。 ## [Unreleased] +- **五集草渲交付(Harness Engineering 改造版,待用户审核后终渲)**:13:58 / 13:10 / 13:07 / 13:07 / 13:08(合计 66.5 分钟草渲口径,帧数均按 `total_duration_in_frames` 复算)。全部新断言锚定官方文档与 Anthropic 工程博客([code.claude.com/docs](https://code.claude.com/docs) 取数2026年8月);去站点化完成(`check_series.py` 规则 7 全绿);五集内容门(含分镜覆盖/读法陷阱/时长双口径)FAIL 0 · WARN 0;七幕抽帧自动体检 FAIL 0(08-23 草渲口径);16 个高风险新图解帧(命名帧/六闸流水线/谁持有计划四象/三禁止章/worktree 四道闸/管家进程/存活矩阵/两条腿/前缀缓存条/三相环/31 事件嵌套/auto 视野分屏/裸名 deny/五辐条/三症状卡/下期卡)逐帧目检通过——无重叠、无字幕带侵入、无文字侧倒(目检基线为 08-23 草渲版;08-24 评审补的六处图解经 `remotion still` 逐帧复检,EP5 两处评审 bug【6-D resume 卡永不渲染的时序死门、分水岭竖线压卡】已修并复渲验证)。配音:716 句基线缓存迁移命中 + 改写句全部重配(sunny-steady + me-bright 不变,两次补配共 ~180 句)。 + +- **《Claude Code 通俗全解》更名《Claude Code Harness Engineering》+ 去站点化改造启动**:系列定位从「介绍开源课程」升级为「拆解 harness 工程」(官方术语表已正式定义 Agentic harness,how-it-works 页明确「Claude Code 是 harness、Claude 是里面的模型」)。五集标题统一收进五层命名体系——[《执行层:一个循环,就是全部》](apps/negentropy-influence/episodes/claude-code-explained-video/README.md) → [《规划层:模型的视野是安排出来的》](apps/negentropy-influence/episodes/claude-code-planning-video/README.md) → [《记忆层:会丢的和不能丢的》](apps/negentropy-influence/episodes/claude-code-memory-video/README.md) → [《时机层:谁来按下开始》](apps/negentropy-influence/episodes/claude-code-concurrency-video/README.md) → [《协作层:从一个到一群》](apps/negentropy-influence/episodes/claude-code-multiagent-video/README.md)(标题只进画面与元数据不进口播,配音成本零)。配套基建:`check_series.py` 新增**规则 7 去站点化门**(观众可见层禁课程站点标识,按系列豁免论文系「站点」一词,8 个新测试用例);skills/06 沉淀五层 HarnessStack 母题规格 + 五集统一动效语法 + 信源卡新四行;5 集 716 句配音缓存自 istanbul-v6 迁移并验证 100% 命中(`tts --plan` 全零待合成)。 + + +### Added + +- **新系列《Claude Code 通俗全解》四集连发 + 首集画面优化**([series.md](apps/negentropy-influence/series.md) 现两系列 8 集): + - **EP1 [《拆开 Claude Code:让 AI 动手的四层机制》](apps/negentropy-influence/episodes/claude-code-explained-video/README.md) tier-i 画面优化**(零口播零配音改动,缓存 170/170 命中零重合成):P6 三挂件卡物理咬合上环 + 双钉信源卡;P0 走秒芯片/轮次钢印/载荷箭头;P5 环第 6 次出场 + 20–28 行实测基准带;1-D 诚实角注;3-C 三判定小抄;emoji 全部换绘制图形。成片 **14:14.73**(narration/timing 零改动 ⇒ 时长不变,`total_duration_in_frames` 复算恒为 25642 帧 @30fps),七幕抽帧 **FAIL 0 · WARN 1**(0-D 标题卡跨两句静止,刻意)。
**评审三修**(自动判据盲区,逐帧目视定位):6-A 挂件卡 `rotate(ang)` 罩住整个 `` 致「闸门」侧倒 90°/「插口」倒置、卡片压环线 —— 卡片组反向抵消 + 挂脚长度由 `RING_R` 反算 + 挂点角避开四节点文案;5-B 基准带锚在区间上界致整体上浮 ~60px —— 改锚下界 + 标注移出柱区;3-C 小抄遮住闸门名「拒绝表/规则匹配」—— 上移收在闸柱之上。同轮修正两处失实交付数字(14:12.52→14:14.73、WARN 0→WARN 1),成因正是 ISSUE-168 的形态。 + - **EP2 [《AI 的视野是安排出来的:写下来的计划,另开的桌子》](apps/negentropy-influence/episodes/claude-code-planning-video/README.md)**(s05/s06/s07/s10/s11 五章,鸢紫 `#9C90EE` 己色):一张桌子比喻体系(钉清单/副桌/目录卡/垫纸/补救梯);深挖 s06「分叉为缓存而生·五要素字节级一致」与 s10「唯一不许进缓存的外接工具段」;134 句 3906 字成片 **13:14.00**(23820 帧 @30fps)。 + - **EP3 [《AI 的记忆:会丢的和不能丢的》](apps/negentropy-influence/episodes/claude-code-memory-video/README.md)**(s08/s09,苔绿 `#A9C46C`):★「丢失不用颜色画」——被压内容向 dim 褪色即遗忘;四级腾位**顺序论证**(入库必须先于折叠·换序自毁演示)、摘要帮工纪律、「tab→风格偏好」转折、先抢救再碎纸的时间铰链、做梦四道闸;140 句 3900 字成片 **13:14.47**(23834 帧 @30fps)。 + - **EP4 [《AI 会自己开工吗?后台与定时》](apps/negentropy-influence/episodes/claude-code-concurrency-video/README.md)**(s13/s14,霜蓝 `#7FB2E0`):★环一秒不停题眼(工作块走环外旁轨);洗衣机与闹钟比喻;单线程真相、看门狗、五格时间表、确定性抖动防踩踏;139 句 3882 字成片 **13:08.90**(23667 帧 @30fps,含 p1-10 旁轨侵入修复重渲)。 + - **EP5 [《一群 AI 怎么干活:看板、信箱与各自的桌子》](apps/negentropy-influence/episodes/claude-code-multiagent-video/README.md)**(s12/s15–s20 七章,赭金 `#D9B36B`):★N 队友同色铭牌区分(反枚举最难考验);递进四问主线(活挂哪/话从哪/怎么谈判/谁的桌子);信箱=文件读一条划一条、编号握手、脏桌不删;s20 作收束装置——「机制很多,循环一个」系列终曲帧(环从传送带中央升起重描一遍);133 句 3912 字成片 **13:03.27**(23498 帧 @30fps),七幕抽帧 **FAIL 0 · WARN 0**(系列唯一全零)。 +- **系列级信源地图(source-map)与多章批量取证基建**:站点↔仓库**修订分叉**的系列级唯一登记处(ISSUE-165 根因再上探:站点整站是课程 20 章旧修订 `67a9126c`,main 已整合为 17 章版,故双钉——ep1 钉 main、ep2–5 钉站点同源修订);机器版 TOML 供 `source_ledger.py sync/audit` 派生台账条目名并离线执法三断言(条目齐/无跨集混入/pinned_ref 一致);各集 source-notes 只链接不重述;取证字节归档 `research/source-archive/`(钉在未合并分支的耐久性)。[skills/01](apps/negentropy-influence/pipeline/skills/01-source-extraction.md) 增「多章批量取证」规格。 +- **管线新门与工具**(刻意不写测试条数——每加一个用例就漂,判据见 [pyproject.toml](apps/negentropy-influence/pyproject.toml) 的 pytest 节注释):`check_series.py` 三新门(规则 4 反向登记门——未登记目录写下 narration 即 FAIL、脚手架期 WARN 分级防死锁;系列内 accents 精确撞色 FAIL + 已用色 INFO 行;规则 6 可渲染性——storyboard 定稿后 scenes 须与 Main.tsx 注册表互对齐);`pipeline.py --series` 白名单扇出(仅 status/doctor/build/check,tts/render 刻意不可扇出);`check_script.py --pre-tts` 预算前置门(时长窗 + 读法陷阱 + 发音标注,`pipeline.py tts` 自动调用);`pron_marks.POLYPHONE_CANDIDATES` 常量 + `--pron-candidates` 扫描报告;`timeline.blend()` + `qa_frames.py --stills-plan`(分幕 A/V 复检算术半自动化);扇出的 flag 转发以 `sub_argv` 切片实现(**不按 Namespace 重建**,见 ISSUE-172);`tts_progress.py` 热漂移旁路监视(s/char 滚动中位 vs 空闲基线,越阈**先分因**:loadavg/therm 二分——竞争=产物无损重排期,节流才中止验证环境);模板 `motifs.tsx` chrome 层播种(seeded 档,7 个通用组件从 ep1 抽出,创作母题仍复制适配不做共享包);`theme.ts.tmpl` 补 `danger` token。 +- **取证字节归档的许可合规**:四集 `research/source-archive/` 各带上游同一固定提交下的 `LICENSE` 字节副本(MIT,© shareAI Lab,sha256 `204ff5ee…`)+ `README.md` 出处表;[skills/01](apps/negentropy-influence/pipeline/skills/01-source-extraction.md) 增「归档即分发」一步,并写明这是单一事实源纪律的**唯一显式例外**(各集目录是可单独取出的交付单位,声明收敛一处则取出即丢);`test_source_map.py` 两条门执法(有归档必有声明、LICENSE 非空且含 Copyright 行)。见 ISSUE-173。 +- **六个实战修复立 issue**:[ISSUE-168](docs/.agents/issue.md)(`qa_frames --scene` 单值 store 使多幕体检静默只查末幕——argparse 静默丢弃先传的 flag 而 `FAIL 0` 不携带检查面,改 `action="append"` + 每幕独立抽样防短幕被整幕跨过);[ISSUE-169](docs/.agents/issue.md)(TTS 漂移判据把负载竞争误当热节流——基线 1.868 s/char 取自**机器空闲**长跑的前置条件没写在判据旁,越阈文案改先分因后处置)。EP4 的 p1-10 旁轨安全带侵入(WorkBlock 滑过轨道底部 y934 压带)由几何判据抓出、`TRACK_CY` 上移 40px 修复复检消失——判据与渲染实现对账的又一次实证。评审复核再收两条:[ISSUE-170](docs/.agents/issue.md)(抽帧体检对**入场瞬态**结构性失明——EP1 6-A 挂件卡入场 10 帧下沿压到 y≈1047 而落位态干净,每幕 ~8 帧的采样密度覆盖不到亚秒越界;改为按「卡片下沿贴住 `SAFE_TOP_Y = 1080 - 160`」逐卡反算入场起步倍率,与 `qa_frames.SUBTITLE_BAND_PX` 同口径,并重渲 EP1 终片对照);[ISSUE-171](docs/.agents/issue.md)(EP2–EP5 交付时长统一短 2.19 秒——数字非按 `total_duration_in_frames` 复算,又被抄到 series.json / series.md / README / CHANGELOG 四处;四处已按复算值回填并**把帧数复算式与数字写在一起**,容量单位统一为 MB)。
**评审五修**再收两条:[ISSUE-172](docs/.agents/issue.md)(`pipeline.py --series` 扇出丢弃子命令 flag——`--series X check --check-scenes` 里 argparse 解析了却没转发,五集全按窄检查跑完而汇总照样逐集打 ✅;改为 `sub_argv` 原样切片转发 + `GLOBAL_OPTS_WITH_VALUE` 防「系列 id 与子命令同名」切错位 + 判定行打出转发面,是 ISSUE-168「静默缩小检查面」的第四个面);[ISSUE-173](docs/.agents/issue.md)(归档了 32 文件 / 15946 行上游 MIT 源码却没带许可声明——取证与再分发是同一动作的两个面,合规判据只挂在后一面上)。同轮订正三处文档漂移:`pipeline/README.md` 与知识索引的 check_series「五规则」抄件未随规则 6 更新、知识索引的新系列条目仍停在 1 集、`check_series.py` 规则 6 内一行注释把兜底门错指为「规则 4 的 theme.ts WARN」(实为 `verify_skeleton` 的 regioned 受门档)。 + +### Changed + +- **`media/` 迁移为 `apps/negentropy-influence/`(分层布局)+ 公共层四项抽取**:子项目从仓库根迁入 `apps/` 约定位置,「机制」(`pipeline/`)与「内容」(`episodes/-video/`)边界显式化。迁移本身是 191 文件 R100 纯重命名(0 增 0 删),语义修复独立成提交。四项基建: + ① **路径锚点抽取**([paths.py](apps/negentropy-influence/pipeline/scripts/paths.py) + `.influence-root` 哨兵):替换三处「数目录层数」的 `parents[N]`——迁移已实证其脆弱(错位后 tts.ref 解析失败、check_series 门静默失效、生物特征小样写错位置,三种失败**都不报错**)。`tts.ref` 与 `series.json` 的 `path` 同步改为**子项目根相对**(缓存摘要只含字节 sha1 不含路径,零句缓存失效)。 + ② **产物 ignore 通配化**(根 `.gitignore` 28 行→16 行):迁移后实测 `voices/*.wav`、逐句 mp3、`.engine`、`*.wav` 全部会变为**可提交**(`check-added-large-files` 阈值 1024KB 拦不住 768KB 的声音样本);通配到分集级同时修掉既存漏洞——**新集在补齐那 5 行之前完全没有覆盖**,新集清单第 3 步随之删除。 + ③ **[stages.toml](apps/negentropy-influence/pipeline/stages.toml) 九阶段唯一声明**:杀掉「散文/子命令/mermaid/路由表」四处分裂脑;序号↔文件号错位(⑥↔07、⑦↔06)显式化 + `test_stages.py` 执法;9 篇 H1 统一为 `# Stage <序号> <名字>`。 + ④ **`pipeline.toml` schema 与默认值层**([config.py](apps/negentropy-influence/pipeline/scripts/config.py)):每集 11 键收缩到 6 键(机制常数进代码、`episode.title` 删除、`engine` 留作策略声明、`server` 走环境变量);**等价变换已证明**(解析填默认后全部 schema 键 4 集逐一相等);修掉一个**静默跳过的门**(缺 toml 时时长预算退化为 [0,999]——现在点名 WARN);`episode.slug` 从死数据升级为「与工程目录名一致」的身份校验(拦手抄来的陈旧 toml);`doctor` 打印带来源标注的配置表。 + ⑤ **骨架模板三件套**([templates/video-skeleton/](apps/negentropy-influence/pipeline/templates/video-skeleton/skeleton.toml)):复制源头从「任一既有集」收敛为**命名模板**(scaffold.py 实例化 + verify_skeleton.py 按系列分组 md5 漂移门),把「改一处须同步」从纸面义务变成秒级判据——此前 391 行冻结基建有 4 个同权真理声明者且义务从未执行过(实测 Main.tsx/cards.tsx 均已漂移,3 处既存漂移登记在案)。README §四「复制适配不做共享包」的决策**不被推翻、而是被补完**(运行期仍是物理副本、仍 `--ignore-workspace` 独立可渲染)。 + ⑥ **`$I`/`$R`/`$P`/`$V` 路径变量约定 + skills 死链执法**:命令变量化,**位置字面量全仓只写在 `I=` 一行**、其余变量派生自它(定义只在 pipeline/README.md 一处,`test_docs_paths.py` 守围栏块/行内/脚本文件头三种形态);散文链接保持相对路径(规则 5 执法);`.agent/skills/science-video-pipeline` 路由壳的 13 条链接**此前完全无死链校验**,现入 `check_series` 受检面;4 集 README 的三种互不一致调用风格统一为 `./node_modules/.bin/` 直调。 + 评审加固(同轮):**锚点混用成门**——`$R + pipeline/voices/…` 这类「在任何 CWD 下都不成立」的命令一度散在 7 个文件里(不是 Markdown 链接,规则 5 看不到),样本路径统一走 `$V` 并加正控;**`[[drift]]` 豁免按指纹钉住**(不钉指纹 = 该文件此后永久免检,而 Main.tsx 每集都要动),偏离内容一变即报 `DRIFT-CHANGED`,且 I2 与 I1 共用逃逸口(否则单集系列登记后 `--strict` 永远红、登记者无路可走);**模板 Main.tsx 的 regioned 区清空**(此前带着某一集的 7 条 `./scenes/*` import,新集开箱即 7 个 module-not-found;归一化恰好剥掉这两段,故清空不动任何既有集指纹);**scaffold 占位符自身合规**(`ref_sha1` 11 位曾让新集连 Stage ③ `build` 都跑不起来——`load_config` 对每个子命令都以 `scope=None` 全节校验);**`pipeline.py qa --video` 改为工程相对**(本入口以 `cwd=<工程>` 启动 qa_frames,`$P/out/…` 必落空——与直调 `qa_frames.py` 的写法**不可互抄**,两处均已成门);**漂移正控迁到 tmp_path 镜像子项目**(此前直接改写受版本控制的已发布分集文件,Ctrl-C 即留脏、并行跑测试互踩;沿用 `test_check_series.py` 的 `.influence-root` 假子项目做法)。 + 评审第三轮:**seeded↔frozen 接口成门**——模板 `theme.ts` 把 serif/sans/mono 拆进了独立的 `font` 导出,而 frozen 档的 `cards.tsx`/`Subtitle.tsx` 读的是 `theme.serif`/`theme.sans`,实测 scaffold 出的新集开箱即 6 个 TS2339;根因是「模板≡真集 ⟹ 真集 tsc 传递性验证模板」这条推理只覆盖**受门档位**,theme.ts 属 seeded、漂移门报 0 处也证明不了新集可编译,故补零依赖静态判据(frozen/regioned 组件读到的每个 `theme.X` 必须在 seed 的 `theme` 字面量内);**位置字面量执法面扩到 `.py` 与各集 README**(`pipeline.py` 文件头曾写 `R=apps/…; P=apps/…` 把字面量复制两遍,而当时的定义检查只扫 `skills/*.md`;模板 README 亦曾内联一份、会随新集线性繁殖,且 `$P` 只在散文里、bash 块照抄即空串——现改为块内 `P=$I/episodes/{{SLUG}}`,与 4 集既有写法一致);**默认值副本清零**(新增 `config.default()`;`check_script` 那份内联 `280` 是**可达**的第二事实源——`load(required=False)` 缺文件时不走 `resolve()`,`pipeline.py` 另有 6 处不可达重复,其中 `style` 的 `"sunny-steady"` 是 SCHEMA 里根本没有的凭空默认,一并删掉,改由 doctor 明说「未配置 tts.ref」而非把它报成「样本缺失」)。 + 评审第四轮:**`overridable` 的覆写许可对 I2 同样生效**——I2 原先不看档位,「全系列都行使许可」即报 STALE,而**单集系列行使一次即是全系列**(claude-code-explained 今天就是),于是档位声明的「只报 INFO,不 FAIL」只在多集系列成立,还逼人为一次合法覆写去登记 `[[drift]]`;实测该集 `timing.json` 改一个 `sceneGapSec` 就让 `--strict` 由 0 变 1。**测试不再改动受版本控制的真集文件**——`test_missing_config_announces_skipped_gate` 曾删掉某集 `pipeline.toml` 再 `finally` 放回(Ctrl-C 即把该集**唯一的可执行参数源**留在删除态,正是第三轮已在 test_skeleton 修掉的同一模式),改用 conftest 本就无 toml 的临时工程夹具,并加**会话级快照守卫**(`episodes/` 树 138 文件 / 3 ms,mtime 参与比对 ⇒「删掉再原样写回」也会红);**刻意不用静态扫描**——原违规的路径构造与 `unlink()` 分处两行,单行正则必漏,而漏报的门等于没门(本轮初稿写过这样一个门,自查时废弃)。**子命令清单三份抄件成门**:`stages` 上线时 `pipeline.py` 文件头 / `pipeline/README.md` / 子项目 README 三处**全部**漏更(此前守卫只查 `stages.toml`→parser 单向,看不见反向缺口),现按 argparse 真实注册表逐项对齐。另修三处失实文档:`scaffold.py` 文件头称「`check_series.py` 会对漏登记大声 FAIL」(实际它只遍历 series.json、看不见孤儿目录,与本文件 step 6 及 README 自相矛盾)、`skeleton.toml` 的「11 个 frozen 全部单哈希」(实为 14 个且 `cards.tsx` 有一条已登记偏离——结论不变,但判据应是「无**跨系列**偏离」)、两集 README 步骤 3 残留的 `pnpm dev`(同一代码块的步骤 4/6 已改 `.bin` 直调)。另补一个 ignore 缺口:本子项目 `pyproject.toml` 刻意无 `[project]`,但 uv 没有「拒绝成为项目」的开关——漏打 `--no-project` 的一次 `uv run` 就会当场生成 `uv.lock`(`.venv/` 有通用规则兜着,锁文件没有),留下一个**可提交**且与「不参与任何 uv workspace」声明相悖的产物(评审期实测触发过一次);拦法**必须逐路径锚定**,裸 `uv.lock` 规则会连兄弟子项目(negentropy / negentropy-perceives / cognizes)受版本控制的依赖 SSOT 一起吞掉,故判据做成**双向**的(本条命中 + 兄弟三份不被误伤,两个方向各有正控)。 + 评审第五轮:**「节应为表」这条 FAIL 也纳入 `scope`**——它此前无条件进 `fails`,于是把 `tts` 写成标量就能让 `check_script.py`(scope={"narration"})以 1 退出:④⑤ 内容门因为一个**它不消费的节**而拒绝检查分镜覆盖性,正是 scope 机制要挡住的形态(必填性与取值域那两半早已按 scope 分流,结构病漏了);越界者**降为 WARN 而非丢弃**(畸形节对谁都值得知道,只是不该替别人拦门),编排器 `scope=None` 的硬失败行为逐字不变。另修一处失实声明:`episode.slug` 的说明写「且能在 series.json 中命中」,而 `validate()` 只比目录名、本模块全程不读 series.json(同一措辞还出现在 `pipeline/README.md` 字段表标为「跨源身份校验」与本条目 ④)——登记校验实际归 `verify_skeleton.py` 的孤儿警告(**非阻塞**,`--strict` 也不失败),故把声明收敛到实际执法范围,执法落点只留一个;判据钉在**导入面**而非源码 grep:「series.json」这几个字如今正出现在 `validate()` 的注释里(声明它刻意不做这件事),grep 会两边同时为真、当场假通过(同第三轮 theme 判据的翻车模式,本轮初稿即栽在这里、被负控抓住),真要在门内读它必须新增 `json`/`paths` 之一的导入。并校正 `config.py` 内注的一处**同分支自相矛盾**(称「现行脚手架恰恰就是 cp -r」,而同一分支已把它换成 `scaffold.py` 模板渲染——`cp -r` 老路仍走得通、现存四集即如此,校验价值不变但表述须与本分支一致)。三条新门各配负控:撤掉 scope 分流→旧码泄漏 FAIL 必红、注入 `json` 导入必红、注入「未登记即 FAIL」→行为判据必红。 + 测试全绿(每条新守卫均做正控:注入漂移必红、还原转绿——第三轮的 theme 判据首版曾因未先切出 `theme` 字面量而假通过,被正控当场抓住;第四轮三条新门逐条撤掉修复复验必红);4 集内容门/主题对比度与迁移前基线逐项一致;`pnpm ls -r` 仍恰 5 项目、根 lockfile 零变更、4 集 `tsc --noEmit` 全过、全仓 `media/` 引用归零(`--text --hidden --no-ignore` 三旗扫描)。⚠️ 各兄弟 worktree 的 gitignored TTS 产物**留在旧路径**(2026-08-22 实测:`philadelphia-v2` 170 mp3 + 2 mp4 + 1 wav、`curitiba-v2` 1 wav;原清单里的 `canberra`(187 mp3)该 worktree 已不存在,故总量由 357 修正为 170 mp3)。搬迁 runbook 见 [PR #1111](https://github.com/ThreeFish-AI/negentropy/pull/1111) 正文,**前提是该 worktree 已拿到该变更**(`apps/negentropy-influence/episodes/` 存在)——三者当时**无一满足**,且 `philadelphia-v2` 还在 `media/` 内有进行中工作(其 `pipeline.py` 仍是 `parents[2]` 旧锚点),此刻搬迁会让它的 `tts.py` 丢缓存而整集重合成。故须待各 worktree 更新分支后再逐个执行;全程禁 `git clean -xdf`。 +- **收敛 `Main.tsx` 的两条骨架漂移登记(逃逸口用完即收)**:漂移门上线时,`self-improving-agents-video` 与 `self-evolving-coding-agents-video` 的 `Main.tsx` 落后于模板一处注释扩写与换行调整,当时**刻意只登记不收敛**(要动两个已发布集,属独立决策)。现对齐到模板并删除那两条 `[[drift]]`,登记表由 3 条降为 1 条(仅剩 `cards.tsx` 的 `ChapterCard`)。**零行为变化、两集无需重渲**:归一化 diff 证明差异仅为注释文字与 JSX 属性折行,`` 的 `durationInFrames`/`fadeIn`/`fadeOut` 三个表达式逐字相同;两集 `tsc --noEmit` 退出 0。收敛的意义在登记表本身——逃逸口不回收,它就会从「当前合法偏离的完整枚举」退化成「历史遗留清单」,而后者没人敢清、等于门被慢性关掉。负控:只删登记不改文件 → 门报 2 处 DRIFT 并退出 1(证明这次删除是被文件收敛**挣来的**,不是把判据放宽)。 + +### Added + +- **新系列「Claude Code 通俗全解」首集 + 管线多系列化与 B 型信源取证基建**:新增 [《拆开 Claude Code:让 AI 动手的四层机制》](apps/negentropy-influence/episodes/claude-code-explained-video/README.md)(陶土橙 `#D97757` 内核 / 石青 `#64C4C0` 外挂机制 / 警示红 `#EF6461` 拒绝闸门,三色对 `#0E1116` 实测 6.06 / 9.18 / 6.00 : 1;170 句 4048 字 7 幕 39 镜;配音 `sunny-steady` + `me-bright.wav`),选题为开源课程 [Learn Claude Code](https://learn.shareai.run/zh/s01/) 的工具与执行四章(s01 Agent Loop / s02 Tool Use / s03 Permission / s04 Hooks)。为此做三件基建: + ① **`apps/negentropy-influence/series.json` 多系列化**:顶层由单 `series` 对象改为 `seriesList[]`,`check_series.py` 相应分层——**反串线规则(1)跨系列全局生效**(两系列口播互不引用),**顺序类规则(2/3/4)按系列内判定**(`episode` 的 `1..N` 连续性只在系列内成立,slug 仍全局唯一);`test_check_series.py` 增 6 例多系列语义用例(各系列各有第 1 集不误报、跨系列标题不比顺序、跨系列反串线仍 FAIL、跨系列 slug 重复 FAIL)。 + ② **Stage ① 泛化为两类信源**:`skills/01-paper-extraction.md` → [`01-source-extraction.md`](apps/negentropy-influence/pipeline/skills/01-source-extraction.md),A 型论文正文原样保留,新增 **B 型(文档/代码/课程站点)** 大节——双轨取证(仓库 @ **固定 commit** + 站点正文)、**证据三级**(一级仓库实测可断言 / 二级站点正文 / 三级「他人对闭源产品源码的分析」**必须带归属句**,不得说成产品既成事实)、数字纪律(口径须可复算、复算不出就只说趋势、活数据不进口播)、二次信源分歧清单必备。配套新工具 [`source_ledger.py`](apps/negentropy-influence/pipeline/scripts/source_ledger.py)(fetch/list/verify,仿 `refs.py` 的清单+指纹设计;`repo` 类校验 `--pinned-ref` 出现在 URL 中且 raw 指纹漂移即 FAIL,`site` 类只比**剥标签归一后的正文**指纹、漂移报 WARN——构建产物哈希天天变,比 raw 毫无信噪比)+ `test_source_ledger.py` 11 例;`apps/negentropy-influence/pipeline/tests/` 由 46 → **130 项**全绿(含合并 #1109 带入的 pron_marks / prospect_ref / tts_bench / digest 参数化用例)。 + ③ **两条实测口径沉淀**:`skills/02` 写明 **`chars_per_min = 280` 不是纯语速而是含停顿的等效口径**(EP1 实测纯语速 301 字/分 + 停顿开销 68 s,两者抵消使「字数 ÷ 280」对全片时长误差仅 1%),并给出推论「**字数是硬约束,句数不是**」(本集实测:263 句合并到 229 句,字数只从 5054 掉到 4909,时长几乎没动——压时长必须真删内容);`skills/06` 新增**可复用视觉母题库**(终端打字 / 恒定视觉锚 / 字典分发表 / 闸门路由 / 插槽注册板 / 反枚举并列项)并显式化一条此前隐含的边界:**A 档冻结清单的同步义务限于同系列内**,新系列首集建立自己的基线(否则「复制不共享」的隔离初衷会被跨系列同步义务反向击穿)。 + 内容侧的两处校准值得单列:课程站点标注的章节行数(102/135/180/232)在固定提交上**用任何口径都复算不出**(s04 声称 232 而实测非空仅 213),判定为早期提交遗留值 → 口播只说趋势、画面给实测值 + 口径 + 取数日期;课程反复说的「循环里只改了一行」经逐章 diff 实测**只在 s02 成立**(s03 是插入 5 行门、s04 另长出 Stop 钩子续跑分支),故口播改用更准也更有力的口径——「**骨架四章一字未改,变的只有『执行』那一步怎么写**」(实测支撑:程序总行 141 → 255 增 81%,而 `agent_loop` 恒在 20–28 行)。另实测确认 pnpm ≥ 11 的 `ERR_PNPM_IGNORED_BUILDS: esbuild`(ISSUE-076)**对本工程无害**——平台二进制是 optionalDependency、不依赖 postinstall,旧写法下 `remotion bundle` 端到端通过,故刻意不改 A 档冻结文件去消音。 +- **科普视频公共管线基建升级**:`pipeline.py` 单入口编排(status/doctor/build/check/tts/captions/render/qa/all/clean-samples,阶段契约与派生式新鲜度——零状态文件防第二事实源)+ 每集 `pipeline.toml` 声明式配置(可执行参数不再散落 README,治 ISSUE-161 类漂移)+ `timing.json` 时序常数 SSOT(timing.ts 同步 import、Python 侧 timeline.py 共读,双语言镜像漂移结构性消灭)+ 七件新工具:`check_script`(④⑤门:分镜覆盖性/时长预算双口径/淡入不变式/--check-scenes 分镜↔代码互比——当场抓出两集既存分镜漂移)、`check_series`(系列顺序五规则执法 [series.json](apps/negentropy-influence/series.json),自身标题排除使纯 grep 不可能做到的反串线 lint 成为可能)、`captions`(srt/vtt,cue 终点不含停顿)、`qa_frames --check/--check-theme`(黑帧/字幕带侵入[连通亮段法]/冻帧/字幕缺失 + WCAG 对比度)、`paper_extract`(Stage ① 取证五子命令)、`refs.py` + `voices/refs.toml`(参考样本指纹清单,只存哈希不存音频)、`tts.py --expect-ref-sha1` 指纹硬校验与 `.engine` 音色签名护栏 + `--allow-voice-switch` 显式放行(ISSUE-163 的拦截层);`apps/negentropy-influence/pipeline/tests/` 45 项(digest 黄金哈希守「缓存零失效」)全绿 2s;pre-commit ruff 扩至 `^apps/negentropy-influence/pipeline/`;技能规格补齐 skills/07–09 并挂载路由型真 Skill [.agent/skills/science-video-pipeline](.agent/skills/science-video-pipeline/SKILL.md)(零正文复制)。 +- **系列发布顺序 SSOT 与 Remotion 最佳实践三集落地**:新增 `apps/negentropy-influence/series.json`/`series.md`(三集顺序 + 「序号不进口播」系列纪律——发布顺序变更的 TTS 代价恒为零);`@remotion/media` `