From fd9fd2b86bdbe2a80ea17794a55dc68e81c5da80 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sun, 23 Aug 2026 06:53:55 +0800 Subject: [PATCH 01/41] =?UTF-8?q?feat(influence):=20=E7=B3=BB=E5=88=97?= =?UTF-8?q?=E6=9B=B4=E5=90=8D=E3=80=8AClaude=20Code=20Harness=20Engineerin?= =?UTF-8?q?g=E3=80=8B=E2=80=94=E2=80=94=E4=BA=94=E5=B1=82=E6=A0=87?= =?UTF-8?q?=E9=A2=98=E4=BD=93=E7=B3=BB=20+=20=E5=8E=BB=E7=AB=99=E7=82=B9?= =?UTF-8?q?=E5=8C=96=E6=B8=85=E9=9B=B6=20+=20=E8=A7=84=E5=88=99=207=20?= =?UTF-8?q?=E6=89=A7=E6=B3=95=E8=90=BD=E5=9C=B0;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 系列定位从「介绍开源课程」升级为「拆解 harness 工程」:官方术语表已正式定义 Agentic harness, how-it-works 页明确「Claude Code 是 harness、Claude 是里面的模型」,官方博客《A harness for every task》直接使用该词——更名有权威出处。 - **五层标题体系**(标题只进画面与元数据不进口播,配音成本零):执行层《一个循环,就是全部》→ 规划层《模型的视野是安排出来的》→ 记忆层《会丢的和不能丢的》→ 时机层《谁来按下开始》→ 协作层《从一个到一群》;series.json/md、五集 planning/README/场景标题卡、knowledge-map、 source-map 头部同步(series.id 与 slug 不动——台账派生命名的锚)。 - **去站点化清零**(60 句口播 + 25 处画面字符串 + 分镜信源卡行):三级证据归属不点名化 (「课程作者拆过源码,他说…」→「有人拆过它的源码——」),章号角标去 sNN 前缀保机制英文名, State 表 ch 列改机制域,P6 信源卡换「官方文档/工程博客/源码分析/实测口径」四行——观众层 匿名化、仓内 research/ 取证链保留具名归属。 - **check_series 规则 7**:观众可见层禁课程站点标识(按系列豁免论文系「站点」一词), 负控验证改造前 259 FAIL 全落课程系、清零后 FAIL 0 · WARN 0;8 个新测试用例。 - skills/06 沉淀五层 HarnessStack 母题规格 + 五集统一动效语法(flow/pushIn/glow/meter/settle) + 信源卡新四行;CHANGELOG 登记。 - TTS 影响实测:60 句改写 ⇒ 5 集共 60 句待重配(156/121/127/131/121 命中),音色样本 me-bright 已按指纹重建(sha1 54b699cce97f 一致)。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- CHANGELOG.md | 2 + .../claude-code-concurrency-video/README.md | 2 +- .../script/narration.json | 16 ++-- .../script/narration.md | 18 ++-- .../script/planning.md | 4 +- .../script/storyboard.md | 4 +- .../video/src/scenes/P0Wait.tsx | 2 +- .../video/src/scenes/P1Dereg.tsx | 6 +- .../video/src/scenes/P2Rejoin.tsx | 8 +- .../video/src/scenes/P3Watchdog.tsx | 6 +- .../video/src/scenes/P4Timer.tsx | 10 +- .../video/src/scenes/P5Truths.tsx | 12 +-- .../video/src/scenes/P6Ending.tsx | 16 ++-- .../claude-code-explained-video/README.md | 4 +- .../script/narration.json | 28 +++--- .../script/narration.md | 48 +++++----- .../script/planning.md | 4 +- .../script/storyboard.md | 8 +- .../video/src/scenes/P0Hook.tsx | 2 +- .../video/src/scenes/P1Loop.tsx | 28 +++--- .../video/src/scenes/P2Dispatch.tsx | 6 +- .../video/src/scenes/P3Gates.tsx | 10 +- .../video/src/scenes/P4Hooks.tsx | 8 +- .../video/src/scenes/P6Ending.tsx | 14 +-- .../claude-code-memory-video/README.md | 2 +- .../script/narration.json | 26 +++--- .../script/narration.md | 28 +++--- .../script/planning.md | 4 +- .../script/storyboard.md | 6 +- .../video/src/scenes/P0Reject.tsx | 2 +- .../video/src/scenes/P1Desk.tsx | 6 +- .../video/src/scenes/P2Tidy.tsx | 6 +- .../video/src/scenes/P3Helper.tsx | 6 +- .../video/src/scenes/P4Ledger.tsx | 8 +- .../video/src/scenes/P5Hinge.tsx | 8 +- .../video/src/scenes/P6Ending.tsx | 12 +-- .../claude-code-multiagent-video/README.md | 2 +- .../script/narration.json | 24 ++--- .../script/narration.md | 28 +++--- .../script/planning.md | 4 +- .../script/storyboard.md | 6 +- .../video/src/scenes/P0Hook.tsx | 2 +- .../video/src/scenes/P1Board.tsx | 4 +- .../video/src/scenes/P2Mail.tsx | 6 +- .../video/src/scenes/P3Handshake.tsx | 4 +- .../video/src/scenes/P4Autonomy.tsx | 2 +- .../video/src/scenes/P5Desks.tsx | 4 +- .../video/src/scenes/P6Finale.tsx | 16 ++-- .../claude-code-planning-video/README.md | 2 +- .../script/narration.json | 26 +++--- .../script/narration.md | 30 +++--- .../script/planning.md | 4 +- .../script/storyboard.md | 6 +- .../video/src/scenes/P0Hook.tsx | 2 +- .../video/src/scenes/P1Plan.tsx | 8 +- .../video/src/scenes/P2SideDesk.tsx | 6 +- .../video/src/scenes/P3Manual.tsx | 6 +- .../video/src/scenes/P4Ladder.tsx | 8 +- .../video/src/scenes/P6Ending.tsx | 16 ++-- .../pipeline/scripts/check_series.py | 67 +++++++++++++ .../skills/06-remotion-implementation.md | 35 +++++++ .../pipeline/tests/test_check_series.py | 93 +++++++++++++++++++ apps/negentropy-influence/series.json | 34 +++---- apps/negentropy-influence/series.md | 18 ++-- .../source-map/claude-code-explained.md | 2 +- docs/.agents/knowledge-map.md | 2 +- 66 files changed, 523 insertions(+), 324 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b2cf1ca..74311373 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ 本文件遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/) 约定,版本号遵循 [SemVer](https://semver.org/lang/zh-CN/)。 ## [Unreleased] +- **《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 diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/README.md b/apps/negentropy-influence/episodes/claude-code-concurrency-video/README.md index c8604c19..237a75b2 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/README.md +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/README.md @@ -1,4 +1,4 @@ -# 《AI 会自己开工吗?后台与定时》科普视频工程 +# 《时机层:谁来按下开始》科普视频工程 **已交付**。发布顺序见 [../../series.json](../../series.json)。 diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json index 247a074c..f1a9852d 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json @@ -137,7 +137,7 @@ { "id": "p1-11", "scene": "P1", - "text": "这里有个容易被想岔的点,课程作者拆过源码,他说了个大实话:" + "text": "这里有个容易被想岔的点,有人拆过它的源码——了个大实话:" }, { "id": "p1-12", @@ -232,7 +232,7 @@ { "id": "p2-06", "scene": "P2", - "text": "递进去的时机也有讲究。课程作者拆过源码,他说队列其实分两级:" + "text": "递进去的时机也有讲究。有人拆过它的源码——队列其实分两级:" }, { "id": "p2-07", @@ -272,7 +272,7 @@ { "id": "p2-14", "scene": "P2", - "text": "课程作者数过,产品里能丢后台的有七种——跑命令、本地分身、远程分身、" + "text": "有人数过,产品里能丢后台的有七种——跑命令、本地分身、远程分身、" }, { "id": "p2-15", @@ -342,7 +342,7 @@ { "id": "p3-01", "scene": "P3", - "text": "后台还有个可爱的设计,课程作者管它叫看门狗。" + "text": "后台还有个可爱的设计,有人管它叫看门狗。" }, { "id": "p3-02", @@ -517,7 +517,7 @@ { "id": "p5-01", "scene": "P5", - "text": "时间表这层,课程作者讲了三个真话,一个比一个有意思。" + "text": "时间表这层,有三个真话,一个比一个有意思。" }, { "id": "p5-02", @@ -682,16 +682,16 @@ { "id": "p6-13", "scene": "P6", - "text": "本片内容来自开源课程《Learn Claude Code》的并发两章," + "text": "本片机制依据官方文档与公开工程实践,取数日期在画面上。" }, { "id": "p6-14", "scene": "P6", - "text": "代码取自课程仓库的固定版本,取证字节已随片归档,链接在简介里。" + "text": "涉及产品内部的部分,来自第三方的源码分析,片中已逐处标注。" }, { "id": "p6-15", "scene": "P6", - "text": "涉及产品内部的部分,均为课程作者的源码分析,片中已逐处标注。下期见。" + "text": "涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注。下期见。" } ] diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md index 867e85b5..554a2558 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md @@ -11,7 +11,7 @@ ## P0 十分钟干等 > 画面:系列终端。依赖安装进度条缓慢爬行;旁边一枚计费表跟着时间狂转。 -> 角标:s13 Background Tasks · "Slow Operations Go to the Background" +> 角标:Background Tasks · "Slow Operations Go to the Background" - [p0-01] 你让它装一个依赖。进度条开始爬,一分钟,三分钟,十分钟。 - [p0-02] 这十分钟它在干什么?什么也没干。就等着。 @@ -47,7 +47,7 @@ - [p1-08] 意思是:这活派出去了,好了会叫你。然后循环接着转,去干下一件。 - [p1-09] 这个安排有个前提要交代:那个跑后台的活,是个「守护」的身份—— - [p1-10] 主人退场,它跟着退场。不会出现程序都关了、后台还在偷偷跑的情况。 -- [p1-11] 这里有个容易被想岔的点,课程作者拆过源码,他说了个大实话: +- [p1-11] 这里有个容易被想岔的点,有人拆过它的源码——了个大实话: - [p1-12] 所谓后台,根本不是一个并行的宇宙。整套系统跑在单线程里, - [p1-13] 后台的真实含义,只是「这一步不等它了」。 - [p1-14] 等待被拿掉了,不是并发被造出来了。 @@ -73,7 +73,7 @@ - [p2-03] 一次调用,永远对应一条结果,这个配对关系不许破坏。 - [p2-04] 所以真结果回来时,不能冒充那条占位,它得换一个身份: - [p2-05] 变成一张完成通知,排进队列;下一轮跟别的结果合并成一条消息递进去。 -- [p2-06] 递进去的时机也有讲究。课程作者拆过源码,他说队列其实分两级: +- [p2-06] 递进去的时机也有讲究。有人拆过它的源码——队列其实分两级: - [p2-07] 「下一轮」和「稍后」。后台完成的通知,默认排在「稍后」—— - [p2-08] 也就是说它不插队。你新输入的一句话,永远排在它的前面。 - [p2-09] 打个比方:门口的信箱。活干完往里投信,开不开箱,看主人何时路过。 @@ -81,7 +81,7 @@ - [p2-11] 你正问它一个正经问题,后台忽然蹦出来「装依赖好了」, - [p2-12] 话头被截走,它的思路也跟着跑了。排队,保护的是对话的完整性。 - [p2-13] 顺带说两个小东西。一个是活不止一种:跑命令只是其中之一, -- [p2-14] 课程作者数过,产品里能丢后台的有七种——跑命令、本地分身、远程分身、 +- [p2-14] 有人数过,产品里能丢后台的有七种——跑命令、本地分身、远程分身、 - [p2-15] 进程内队友、工作流、监控外接,还有个整理记忆的,名字叫做梦。 - [p2-16] 另一个是每批工具干完,有个小模型顺手给这批活贴一张标签, - [p2-17] 三十个字左右,像一条提交说明——给它自己回看用的,不进正片。 @@ -102,7 +102,7 @@ > 对准输出线末端的「(y/n)」提示。 > 角标:watchdog · 45s 停滞检测 -- [p3-01] 后台还有个可爱的设计,课程作者管它叫看门狗。 +- [p3-01] 后台还有个可爱的设计,有人管它叫看门狗。 - [p3-02] 后台命令有时候会卡住——不是坏了,是它停下来问了个问题。 - [p3-03] 比如「要不要继续?」——然后干等一个等不来的回答。 - [p3-04] 所以有一只狗盯着每条后台命令的输出:四十五秒没有新动静,它就去看看, @@ -150,7 +150,7 @@ > 画面:★深挖帧——一排相同的表全指向 9:00,各按算好的偏移错峰落下;退休章;诚实边界帧。 > 角标:jitter(确定性哈希 · 周期 10% · 封顶 15 分钟)· 7 天退休(上限 30 天)· 上限 50 -- [p5-01] 时间表这层,课程作者讲了三个真话,一个比一个有意思。 +- [p5-01] 时间表这层,有三个真话,一个比一个有意思。 - [p5-02] 第一个真话:全世界的定时器,都卡在整点。 - [p5-03] 你写「每天九点」,别人也写「每天九点」。千万个任务同一秒一起冲出去, - [p5-04] 服务还没怎么样,先被自己人踩踏了。所以产品故意让每个任务迟到一点。 @@ -189,6 +189,6 @@ - [p6-10] 它的自主,到此为止是「守时的自主」——时间到点自己开工, - [p6-11] 至于「自己决定该干什么活」,那是更大的一步,我们后面再拆。 - [p6-12] 到那时你会发现还是同样的套路:先把等待摘掉,再把决定挪走。 -- [p6-13] 本片内容来自开源课程《Learn Claude Code》的并发两章, -- [p6-14] 代码取自课程仓库的固定版本,取证字节已随片归档,链接在简介里。 -- [p6-15] 涉及产品内部的部分,均为课程作者的源码分析,片中已逐处标注。下期见。 +- [p6-13] 本片机制依据官方文档与公开工程实践,取数日期在画面上。 +- [p6-14] 涉及产品内部的部分,来自第三方的源码分析,片中已逐处标注。 +- [p6-15] 涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注。下期见。 diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/planning.md b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/planning.md index d5a9108c..c6cfa052 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/planning.md +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/planning.md @@ -1,4 +1,4 @@ -# 策划案:《AI 会自己开工吗?后台与定时》 +# 策划案:《时机层:谁来按下开始》 > 事实源:[../research/source-notes.md](../research/source-notes.md)(信源清单 [../research/sources.toml](../research/sources.toml)) > 逐字稿 SSOT:[narration.md](./narration.md) · 分镜:[storyboard.md](./storyboard.md) @@ -8,7 +8,7 @@ | 项 | 定义 | |---|---| -| 系列 | Claude Code 通俗全解(独立成片) | +| 系列 | Claude Code Harness Engineering(独立成片) | | 平台 / 形态 | B 站 / YouTube 1080p30,代码动画 + 本人克隆音色,无 BGM、无 emoji | | 时长 | `target_minutes = [13.0, 14.6]`;≈3900 字 | | 受众 | 普通人:都体验过「让 AI 装个依赖然后干等」;没想过「等待」本身是被设计掉的 | diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md index d2c314b9..7af52837 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md @@ -20,7 +20,7 @@ |---|---|---|---| | 1-A | p1-01..05 | 主循环环居中持续转(题眼);bash 工具卡上「后台执行」开关被勾选;关键词兜底:命令文本里 install/build 词被高亮 | 开关咔哒勾上;命令词高亮逐个闪;两条路(勾选/兜底)汇入同一出口 | | 1-B | p1-06..10 | ★环外旁轨浮现:慢命令块滑出环上旁轨自己跑;环口贴占位条(带编号 bg_0001);循环继续转 | 命令块沿弧线滑出;占位条「啪」贴回环口;环的转速不变(全程匀速) | -| 1-C | p1-11..15 | 【三】单线程真相帧:画面收缩成一条单线轨道——所谓「并行」的幻象被揭穿:所有块在同一条线上交错排布 | 双轨假象先展示→轨道合并动画→块在单线上排队交替走;角标「课程作者的源码分析」 | +| 1-C | p1-11..15 | 【三】单线程真相帧:画面收缩成一条单线轨道——所谓「并行」的幻象被揭穿:所有块在同一条线上交错排布 | 双轨假象先展示→轨道合并动画→块在单线上排队交替走;角标「第三方的源码分析」 | | 1-D | p1-16..24 | 占位条特写(编号放大);风筝比喻:后台块拴绳飞在环外,绳头在循环手里 | 编号字放大定格;风筝线描线(`later`),收放各一次 | ## P2 干完怎么接回来 @@ -66,4 +66,4 @@ |---|---|---|---| | 6-A | p6-01..06 | 三种开始三段位置图(人在环上/人在环外/没有人)→ 环一秒不停的回收:三图右上角同一个环持续转 | 三段图依次亮起;共享的小环匀速转动贯穿 | | 6-B | p6-07..12 | 一句话合同金句卡「按下的不一定是它,等的一定不是你」+「守时的自主」边界两句 | 金句卡(`core`)淡入;边界两句以小字跟随 | -| 6-C | p6-13..15 | 信源卡(课程/站点/仓库/钉版 67a9126c/归档/MIT/诚实行)→ 身份卡 → 渐黑(末 beat 总时长推导,红线四) | 逐行浮现;身份卡;末 1.2s 线性压暗 | +| 6-C | p6-13..15 | 信源卡(官方文档+取数日期 / 第三方源码分析已逐处标注 / 数字均为实测口径)→ 身份卡 → 渐黑(末 beat 总时长推导,红线四) | 逐行浮现;身份卡;末 1.2s 线性压暗 | diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx index 6659a5f9..a0f82a1c 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx @@ -80,7 +80,7 @@ const StallBar: React.FC<{tickAt: number; costAt: number; zeroAt: number}> = ({t }); return ( - +
- + @@ -185,7 +185,7 @@ const OffLoopSideTrack: React.FC<{slideAt: number; stubAt: number; nextAt: numbe }); return ( - + {/* 旁轨:later 虚线弧(120°→310°),环外一层 */} = ({mergeA ) : null} - {'单线程真相 —— 课程作者的源码分析'} + {'单线程真相 —— 第三方的源码分析'} {labelO > 0 ? (
= ({ const resultShift = queue * 260; return ( - + {/* 调用卡(左) */} @@ -104,7 +104,7 @@ const TwoTierQueue: React.FC<{dropAt: number; userAt: number}> = ({dropAt, userA const user = spring({frame: frame - userAt, fps, config: {damping: 200}}); return ( - + @@ -149,7 +149,7 @@ const TwoTierQueue: React.FC<{dropAt: number; userAt: number}> = ({dropAt, userA - {'队列两级:下一轮 > 稍后 —— 课程作者的源码分析'} + {'队列两级:下一轮 > 稍后 —— 第三方的源码分析'} ); }; @@ -272,7 +272,7 @@ const SevenTasks: React.FC<{lightAt: number; labelAt: number}> = ({lightAt, labe
) : null} - {'七种 —— 课程作者数过 · 跑命令只是其一'} + {'七种 —— 有人数过 · 跑命令只是其一'} ); }; diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx index af9d4648..55ae06db 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx @@ -122,7 +122,7 @@ const DogWatching: React.FC<{stopAt: number}> = ({stopAt}) => { const frame = useCurrentFrame(); return ( - +
@@ -164,7 +164,7 @@ const DogRises: React.FC<{watchAt: number; riseAt: number; contrastAt: number; q }); return ( - +
{/* 45 秒刻度盘 */}
@@ -253,7 +253,7 @@ const DogRises: React.FC<{watchAt: number; riseAt: number; contrastAt: number; q {'不猜快慢,只看死活'}
) : null} - {'看门狗 · 45 秒停滞检测 —— 课程作者的源码分析'} + {'看门狗 · 45 秒停滞检测 —— 第三方的源码分析'} ); }; diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx index 52d5e81a..64aa400d 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx @@ -24,7 +24,7 @@ const PuppetVsClock: React.FC<{clockAt: number}> = ({clockAt}) => { const clockOn = frame >= clockAt; return ( - +
{/* 左:提线木偶 */}
@@ -110,7 +110,7 @@ const FiveFieldTable: React.FC<{frameAt: number; ex1At: number; ex2At: number; e ]; return ( - + {/* 五格框架 */}
{cols.map((c, i) => ( @@ -217,7 +217,7 @@ const TwoGuards: React.FC<{rejectAt: number; skipAt: number}> = ({rejectAt, skip ]; return ( - +
{/* 保险一:写表验格式 */}
@@ -339,7 +339,7 @@ const FourLayerModel: React.FC<{dropAt: number; gateAt: number; dupAt: number}> }); return ( - + {/* 层 1:秒摆线程(每秒一跳) */} @@ -459,7 +459,7 @@ const TwoStorages: React.FC<{memAt: number; swapAt: number}> = ({memAt, swapAt}) ]; return ( - +
{/* 磁盘文件:重启绕回 */}
diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx index 0776e65b..305bfce9 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx @@ -49,7 +49,7 @@ const Stampede: React.FC<{fireAt: number; crashAt: number}> = ({fireAt, crashAt} const jit = (i: number) => Math.sin((frame / 3.1) + i * 2.4) * 7 * crash; return ( - + {/* 一排表:全部指 9:00(时针 270°、分针 270°) */} {Array.from({length: N}, (_, i) => ( @@ -100,7 +100,7 @@ const Stampede: React.FC<{fireAt: number; crashAt: number}> = ({fireAt, crashAt} - {'全世界的定时器都卡整点 —— 课程作者的源码分析'} + {'全世界的定时器都卡整点 —— 第三方的源码分析'} ); }; @@ -133,7 +133,7 @@ const DeterministicJitter: React.FC<{staggerAt: number; randomAt: number; earlyA }); return ( - + {/* 错峰一排表:各按固定偏移「落下」 */} {Array.from({length: N}, (_, i) => ( @@ -219,7 +219,7 @@ const RetireStamp: React.FC<{flipAt: number; stampAt: number}> = ({flipAt, stamp }) : 0; return ( - +
{/* 日历:翻页计数 */}
@@ -305,7 +305,7 @@ const HonestEdge: React.FC<{offAt: number; drawerAt: number}> = ({offAt, drawerA }); return ( - +
{/* 进程盒子:灯 + 秒摆 */}
@@ -452,7 +452,7 @@ const CapAndQuote: React.FC<{lowAt: number; quoteAt: number}> = ({lowAt, quoteAt
- {'上限与低优先级标记 —— 课程作者的源码分析'} + {'上限与低优先级标记 —— 第三方的源码分析'} ); }; diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx index 4d9a4f53..fbbc1f14 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx @@ -120,7 +120,7 @@ const ThreePositions: React.FC<{l1: number; l2: number; l3: number; layerAt: num }); return ( - +
= l1} /> @@ -216,10 +216,10 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> const {fps} = useVideoConfig(); const enter = spring({frame: frame - 4, fps, config: {damping: 200}}); const rows = [ - ['课程', 'Learn Claude Code · 并发两章'], - ['站点', 'learn.shareai.run/zh/s13 · /s14'], - ['仓库', 'github.com/shareAI-lab/learn-claude-code'], - ['仓库钉版', 'main @ 67a9126c(站点同源修订)'], + ['官方文档', 'code.claude.com/docs · 取数 2026-08'], + ['工程博客', 'anthropic.com/engineering'], + ['源码分析', '第三方逆向分析 · 片中逐处标注'], + ['源码分析', '第三方逆向分析 · 片中逐处标注'], ['访问日期', '2026-08-22'], ['许可', 'MIT'], ]; @@ -259,7 +259,7 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}>
{v}
))} - {/* 诚实行:产品内部断言均为课程作者的源码分析(【三】归属句的公开落点) */} + {/* 诚实行:产品内部断言均为第三方的源码分析(【三】归属句的公开落点) */}
}), }} > - {'涉及产品内部的部分,均为课程作者的源码分析,片中已逐处标注;取证字节已随片归档'} + {'涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注;取证字节已随片归档'}
@@ -288,7 +288,7 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> }} >
- {'Claude Code 通俗全解'} + {'Claude Code Harness Engineering'}
系列「Claude Code 通俗全解」首作(发布顺序 SSOT:[../series.json](../../series.json);口播永不携带集数序号)。 +> 系列「Claude Code Harness Engineering」首作(发布顺序 SSOT:[../series.json](../../series.json);口播永不携带集数序号)。 > 选题:开源课程 [Learn Claude Code](https://learn.shareai.run/zh/s01/) 的「工具与执行」四章 > —— s01 Agent Loop / s02 Tool Use / s03 Permission / s04 Hooks。 > 形态:1080p30 横屏,代码动画图解 + 本人音色克隆旁白,无真人出镜、无 BGM。 diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json index 4fad96e9..6fbec687 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json @@ -112,7 +112,7 @@ { "id": "p1-13", "scene": "P1", - "text": "课程作者给它的评价是:三十多行,最小可运行的内核。" + "text": "有人给它的评价是:三十多行,最小可运行的内核。" }, { "id": "p1-14", @@ -137,7 +137,7 @@ { "id": "p1-18", "scene": "P1", - "text": "最直觉的写法是直接看它;但课程改了," + "text": "最直觉的写法是直接看它;但教学版改了," }, { "id": "p1-19", @@ -147,7 +147,7 @@ { "id": "p1-20", "scene": "P1", - "text": "课程作者拆过 Claude Code 的源码,他给的理由是:" + "text": "有人拆过它的源码,他给的理由是:" }, { "id": "p1-21", @@ -177,7 +177,7 @@ { "id": "p1-26", "scene": "P1", - "text": "而按课程作者的源码分析,真实产品里带着十样,像十个抽屉。" + "text": "而按第三方的源码分析,真实产品里带着十样,像十个抽屉。" }, { "id": "p1-27", @@ -187,7 +187,7 @@ { "id": "p1-28", "scene": "P1", - "text": "有意思的是,几乎每个抽屉都对应课程后面的某一章。" + "text": "有意思的是,几乎每个抽屉都对应后面的某一层机制。" }, { "id": "p1-29", @@ -297,7 +297,7 @@ { "id": "p2-18", "scene": "P2", - "text": "但按课程作者的源码分析,这两件事其实不是一回事。" + "text": "但按第三方的源码分析,这两件事其实不是一回事。" }, { "id": "p2-19", @@ -432,7 +432,7 @@ { "id": "p3-14", "scene": "P3", - "text": "课程里有一句很诚实的话,我想念出来。" + "text": "教学版里有一句很诚实的话,我想念出来。" }, { "id": "p3-15", @@ -467,7 +467,7 @@ { "id": "p3-21", "scene": "P3", - "text": "按课程作者的源码分析,结论不是三种,是四种。" + "text": "按第三方的源码分析,结论不是三种,是四种。" }, { "id": "p3-23", @@ -557,7 +557,7 @@ { "id": "p4-05", "scene": "P4", - "text": "课程里画了一张很扎心的图:循环体里记日志一行、查权限一行、" + "text": "有人画过一张很扎心的图:循环体里记日志一行、查权限一行、" }, { "id": "p4-06", @@ -642,7 +642,7 @@ { "id": "p4-22", "scene": "P4", - "text": "课程里有句话我很喜欢:这个循环是故意保持无聊的。" + "text": "有句话我很喜欢:这个循环是故意保持无聊的。" }, { "id": "p4-23", @@ -652,7 +652,7 @@ { "id": "p4-24", "scene": "P4", - "text": "按课程作者的源码分析,二十七个——" + "text": "按第三方的源码分析,二十七个——" }, { "id": "p4-25", @@ -662,7 +662,7 @@ { "id": "p4-27", "scene": "P4", - "text": "但这一章真正的重点是另一件事:课程作者把它称为" + "text": "但这一层真正的重点是另一件事:有人把它称为" }, { "id": "p4-28", @@ -692,7 +692,7 @@ { "id": "p4-33", "scene": "P4", - "text": "而教学版没有这一层。课程作者自己写下了这句评语:" + "text": "而教学版没有这一层。拆源码的人自己写下了这句评语:" }, { "id": "p4-34", @@ -837,7 +837,7 @@ { "id": "p6-06", "scene": "P6", - "text": "本片内容来自开源课程《Learn Claude Code》的前四章," + "text": "本片机制依据官方文档与公开工程实践,取数日期在画面上。" }, { "id": "p6-07", diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md index 32c8f6ca..18693284 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md @@ -3,7 +3,7 @@ > **全片单一事实源的下游**:每条断言回溯 [../research/source-notes.md](../research/source-notes.md);策划见 [planning.md](./planning.md)。 > 格式约定:`## P` 起一幕;`- [pN-xx] 文本` 一行一句(进配音);`>` 引用块是画面备注与角标(**不进配音**)。 > 纪律:英文标识符只进角标不进口播(唯一例外是产品名 Claude Code);三级证据必带归属句 -> (「课程作者拆过源码,他说…」);不引用行数绝对值、课程总章数等活数据。 +> (「有人拆过它的源码——…」);不引用行数绝对值、章节数等活数据。 > > **字数是硬约束**:`chars_per_min = 280` 是**含停顿的等效口径**(实测纯语速 301 字/分, > 停顿开销另占约 1 分钟)——EP1 用它预测成片 14:01 只差 1%。故 14 分钟 ≈ 3900 字。 @@ -27,7 +27,7 @@ ## P1 一个循环,就是全部 -> 画面:陶土橙闭合轨道成形(全片恒定视觉锚)。角标:s01 Agent Loop / "One Loop Is All You Need" +> 画面:陶土橙闭合轨道成形(全片恒定视觉锚)。角标:Agent Loop · "One Loop Is All You Need" - [p1-01] 先说结论:那一层的核心是一个循环,像一条不停转的传送带。 - [p1-02] 它只做一件事:反复去问模型,接下来干什么。 @@ -44,7 +44,7 @@ - [p1-10] 把模型的回答追加进列表,挑出里面所有的工具调用; - [p1-11] 一个都没有就地返回,有就逐个执行、收好每条结果; - [p1-12] 最后把结果打包成新消息追加进去,回到第二步。写完了。 -- [p1-13] 课程作者给它的评价是:三十多行,最小可运行的内核。 +- [p1-13] 有人给它的评价是:三十多行,最小可运行的内核。 - [p1-14] 我自己数过这一版:光循环那个函数,去掉空行和注释,二十三行。 > 角标:实测 `agent_loop` 非空非注释 23 行 @ pinned commit(口径与取数见 sources.toml) @@ -52,21 +52,21 @@ - [p1-15] 分工也说清楚了:模型决定要不要用工具、用哪一个, - [p1-16] 脚手架负责真的去跑、把结果搬回来——判断力在那边,手脚在这边。 - [p1-17] 模型回话时会附一个「我为什么停下来」的标记。 -- [p1-18] 最直觉的写法是直接看它;但课程改了, +- [p1-18] 最直觉的写法是直接看它;但教学版改了, - [p1-19] 改成翻开回答本身,看里面有没有工具调用。为什么? -- [p1-20] 课程作者拆过 Claude Code 的源码,他给的理由是: +- [p1-20] 有人拆过它的源码,他给的理由是: - [p1-21] 回答是一个字一个字流出来的,工具调用早就流出来了, - [p1-22] 那个标记却可能还没更新——他说源码注释写得很直白,这标记不可靠。 - [p1-23] 所以真正的做法是一边流一边看,见到工具调用就记下还得再来一轮。 - [p1-24] 别听它说「我说完了」,去看它手里还有没有活。 > 金句卡(serif):「别听它说『我说完了』,去看它手里还有没有活。」 -> 角标:`stop_reason` is unreliable —— 课程作者的源码分析 +> 角标:`stop_reason` is unreliable —— 第三方的源码分析 - [p1-25] 教学版的循环身上只带一样东西:那份消息列表。 -- [p1-26] 而按课程作者的源码分析,真实产品里带着十样,像十个抽屉。 +- [p1-26] 而按第三方的源码分析,真实产品里带着十样,像十个抽屉。 - [p1-27] 剩下九个管的是压缩进度、补救次数、钩子拦没拦过停机、轮数这些。 -- [p1-28] 有意思的是,几乎每个抽屉都对应课程后面的某一章。 +- [p1-28] 有意思的是,几乎每个抽屉都对应后面的某一层机制。 - [p1-29] 也就是说,循环没有长个,长出来的是它随身带的状态。 - [p1-30] 退出的路子也一样——按他的说法,真实产品里有一大把: - [p1-31] 报错、中断、钩子叫停、轮数到顶、预算烧完。 @@ -75,7 +75,7 @@ ## P2 加一个工具,只改一行 > 画面:循环环保持不动(陶土橙),右侧长出第一层外挂——石青色的字典分发表。 -> 角标:s02 Tool Use / "Add a Tool, Add Just One Line" +> 角标:Tool Use · "Add a Tool, Add Just One Line" - [p2-01] 刚才那个循环,手里只有一件工具:一个能跑命令的壳。 - [p2-02] 想读文件,它得拼出一条读文件的命令;想写文件,得拼一条重定向。 @@ -98,7 +98,7 @@ - [p2-15] 教学版老实排队,一个一个来;真实产品里能并行的就并行。 - [p2-16] 而它判断能不能并行的方式,是这一集我最想让你记住的一处。 - [p2-17] 直觉会说:只读的可以一起跑,要写的不行。 -- [p2-18] 但按课程作者的源码分析,这两件事其实不是一回事。 +- [p2-18] 但按第三方的源码分析,这两件事其实不是一回事。 - [p2-19] 同一个跑命令的工具,让它列个目录算能并行,让它删个文件就不能。 - [p2-20] 同一件工具,同一个名字,结论相反。 - [p2-21] 因为判断的不是这件工具,是这一次具体要干什么。 @@ -107,7 +107,7 @@ - [p2-24] 所以「能不能一起跑」跟「是不是只读」,是两条独立的判断。 > 金句卡(serif):「『能不能一起跑』跟『是不是只读』,是两条独立的判断。」 -> 角标:`isConcurrencySafe` ≠ `isReadOnly` —— 课程作者的源码分析 +> 角标:`isConcurrencySafe` ≠ `isReadOnly` —— 第三方的源码分析 - [p2-25] 判断完了怎么排?按原来的顺序切段:连着能并行的划成一组一起跑, - [p2-26] 中间夹着不能并行的就单独一组;组内并行,组间严格按顺序。 @@ -120,7 +120,7 @@ ## P3 执行之前,先过闸门 > 画面:循环环仍在(陶土橙),执行口前落下三道竖闸。警示红首次出现。 -> 角标:s03 Permission / "Check Permissions Before Execution" +> 角标:Permission · "Check Permissions Before Execution" - [p3-01] 现在这个 AI 有五件工具,其中一件能跑任意命令。 - [p3-02] 读写文件那几件都被拦在工作目录里,但跑命令那件,没人管它。 @@ -135,7 +135,7 @@ - [p3-11] 读写工作目录之外的东西,或者命令里带着删除、改权限这类动作。 - [p3-12] 第三道就是问你:画面停下来,把工具名和参数摆给你看,等你点头。 - [p3-13] 三道都没命中呢?直接放行——日常绝大多数操作走的都是这条路。 -- [p3-14] 课程里有一句很诚实的话,我想念出来。 +- [p3-14] 教学版里有一句很诚实的话,我想念出来。 - [p3-15] 它说,这张拒绝表用的是最简单的字符串匹配, - [p3-16] 它的作用是告诉你「闸门应该装在哪儿」, - [p3-17] 而不能被当成一道真正的安全边界—— @@ -145,7 +145,7 @@ > 金句卡(serif):「它告诉你闸门装在哪儿,不是替你把门守住。」 - [p3-20] 那真实产品里的门长什么样? -- [p3-21] 按课程作者的源码分析,结论不是三种,是四种。 +- [p3-21] 按第三方的源码分析,结论不是三种,是四种。 - [p3-23] 多出来的第四种最有意思:工具选择不表态。 - [p3-24] 也就是说,弃权不等于放行,兜底永远是问你一句。 - [p3-25] 而这些规则从哪儿来?他数出了八个地方—— @@ -154,7 +154,7 @@ - [p3-28] 八个来源难免打架,所以有优先级:越靠近「组织」的越大。 - [p3-29] 公司策略压过本地配置。这一层,是给团队和企业留的。 -> 角标:user < project < local < flag < policy(+ cliArg / command / session)——课程作者的源码分析 +> 角标:user < project < local < flag < policy(+ cliArg / command / session)——第三方的源码分析 - [p3-30] 他还写到一处很能说明工程品味的设计:自动批准。 - [p3-31] 全都自动跑的模式下它不会每次弹窗, @@ -166,13 +166,13 @@ ## P4 挂在循环上,不写进循环里 > 画面:循环环外围浮出四个空插槽(石青),回调卡片依次插入。 -> 角标:s04 Hooks / "Hang on the Loop, Don't Write into It" +> 角标:Hooks · "Hang on the Loop, Don't Write into It" - [p4-01] 到这一步,这个 AI 已经能安全地动手了。 - [p4-02] 接下来的麻烦所有做过工程的人都熟悉:你想加点东西。 - [p4-03] 比如每次跑命令都记一笔日志,或者某些操作做完自动提交一次代码。 - [p4-04] 每加一样,你都得回去改那个循环。 -- [p4-05] 课程里画了一张很扎心的图:循环体里记日志一行、查权限一行、 +- [p4-05] 有人画过一张很扎心的图:循环体里记日志一行、查权限一行、 - [p4-06] 发通知一行、自动提交又一行,加到后面那段代码已经认不出来了。 - [p4-07] 原话说得很准:你想扩展的是它的行为,你改的却是循环本身。 @@ -192,24 +192,24 @@ - [p4-19] 它返回一句话,这句话就被当成新输入塞回去,循环继续转。 - [p4-20] 四个插口覆盖一整轮:进来、动手前、动手后、结束前, - [p4-21] 而循环只负责在这四个点上喊一声。 -- [p4-22] 课程里有句话我很喜欢:这个循环是故意保持无聊的。 +- [p4-22] 有句话我很喜欢:这个循环是故意保持无聊的。 > 金句卡(serif):「这个循环是故意保持无聊的。」 - [p4-23] 真实产品里这样的时机有多少个? -- [p4-24] 按课程作者的源码分析,二十七个—— +- [p4-24] 按第三方的源码分析,二十七个—— - [p4-25] 会话开始结束、权限被请求被拒绝、子任务启停、压缩前后、文件被改。 -- [p4-27] 但这一章真正的重点是另一件事:课程作者把它称为 +- [p4-27] 但这一层真正的重点是另一件事:有人把它称为 - [p4-28] 整个权限系统里最重要的一处安全设计。 - [p4-29] 是这样:插口上的函数可以直接给出权限结论,说「这个我批了」。 - [p4-30] 那它说批了,就真的放行吗?不。 - [p4-31] 就算插口上的脚本说放行,配置里的禁止和询问仍然要再走一遍。 - [p4-32] 方向是单向的:扩展点能加限制,不能解除限制。 -- [p4-33] 而教学版没有这一层。课程作者自己写下了这句评语: +- [p4-33] 而教学版没有这一层。拆源码的人自己写下了这句评语: - [p4-34] 这在教学里够用了,但放到生产环境,就是一个安全漏洞。 > 金句卡(serif):「扩展点能加限制,不能解除限制。」 -> 角标:hook `allow` 不能绕过 settings 的 deny/ask —— 课程作者的源码分析 +> 角标:hook `allow` 不能绕过 settings 的 deny/ask —— 第三方的源码分析 - [p4-35] 还有个小机关:那个能说「别停」的插口本身很危险, - [p4-36] 它叫模型接着干,模型干完又要停,它又叫接着干,就转不出来了。 @@ -249,7 +249,7 @@ ## P6 收尾 -> 画面:信源卡(课程名 / 仓库 / 固定提交号前七位 / 访问日期 / MIT)→ 系列身份卡 → 渐黑。 +> 画面:信源卡(官方文档 + 取数日期 / 第三方源码分析已逐处标注 / 数字均为实测口径)→ 系列身份卡 → 渐黑。 > 渐黑窗口从**末 beat** 总时长推导(不是末句),见 skills/06 红线四。 - [p6-01] 它敢在你的电脑上动手,不是因为它足够聪明, @@ -257,6 +257,6 @@ - [p6-03] 循环给它手脚,分发表给它工具,闸门守着底线,插口留给你发挥。 - [p6-04] 这几层结构不神秘,加起来两百多行,一个下午能读完。 - [p6-05] 这套东西往后还有更多层,那些就留到以后再拆。 -- [p6-06] 本片内容来自开源课程《Learn Claude Code》的前四章, +- [p6-06] 本片机制依据官方文档与公开工程实践,取数日期在画面上。 - [p6-07] 代码和行数取自它固定版本的仓库原文,链接在简介里。 - [p6-08] 如果这让你对「AI 到底怎么动手」有了点具体的感觉,那就够了。 diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/planning.md b/apps/negentropy-influence/episodes/claude-code-explained-video/script/planning.md index 076960e3..0dabc691 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/planning.md +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/planning.md @@ -1,4 +1,4 @@ -# 策划案:《拆开 Claude Code:让 AI 动手的四层机制》 +# 策划案:《执行层:一个循环,就是全部》 > 事实源:[../research/source-notes.md](../research/source-notes.md)(信源清单 [../research/sources.toml](../research/sources.toml)) > 逐字稿 SSOT:[narration.md](./narration.md) · 分镜:[storyboard.md](./storyboard.md) @@ -8,7 +8,7 @@ | 项 | 定义 | |---|---| -| 系列 | **Claude Code 通俗全解**(新系列,与自进化系列完全无关,不互相引用) | +| 系列 | **Claude Code Harness Engineering**(新系列,与自进化系列完全无关,不互相引用) | | 集次 | 首集(序号只存在于 [../../series.json](../../../series.json) 与视觉层) | | 平台 / 形态 | B 站 / YouTube 横屏 1080p30,代码动画图解 + 本人音色克隆旁白,无真人出镜、无 BGM | | 时长 | 13:00–14:36(用户上限 15 分钟,`target_minutes = [13.0, 14.6]`) | diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md index a00c9b70..b2dfe631 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md @@ -36,7 +36,7 @@ | 2-A | p2-01..04 | 环形循环留在左上角(缩小但**同色同线宽**)。主体是终端:模型的意图气泡「读这个文件」旁边,笨拙地拼出一条命令 | 意图气泡与命令行之间画一条「翻译」箭头,箭头上叠一个 `deny` 色的小计数「+1 层」;p2-02 打出两条拼接命令(读/写各一条);p2-04 时命令里一个字符被高亮成 `deny` 并抖动(拼错) | | 2-B | p2-05..06 | 五张工具卡横排弹出(`panel` 底 + 编号,**不给五种颜色**——反枚举原则) | 卡片以 60ms 间隔 `spring` 弹入,每张弹入时仅**编号**染 `mech`;五张齐后整排轻微下沉定位 | | 2-C | p2-07..10 | **字典分发表**:两列表格,左列工具名(mono),右列处理函数名。旁边一个前台号码簿的极简图形 | p2-07 表格框线描出;p2-08 逐行填入(每行 4 帧);p2-09 一个「来电」光点从左飞入命中某一行 → 整行推入 `mech` 辉光 → 右列函数名弹出;p2-10 表格底部**多出一行空槽**,一条新映射滑入落槽 | -| 2-D | p2-11..13 | 左右并置两段代码(s01 / s02 版),仅执行那一行不同 | 两段代码同时淡入,**逐行做同色对齐比对**;唯一不同的那一行左侧打 `mech` 竖标并整行高亮,其余行降到 40% 亮度;p2-13 时左上角环形循环 `core` 脉冲一次(强调"它没动") | +| 2-D | p2-11..13 | 左右并置两段代码(前后两版),仅执行那一行不同 | 两段代码同时淡入,**逐行做同色对齐比对**;唯一不同的那一行左侧打 `mech` 竖标并整行高亮,其余行降到 40% 亮度;p2-13 时左上角环形循环 `core` 脉冲一次(强调"它没动") | | 2-E | p2-14..16 | 模型一次吐出四个工具调用卡,排成一列等待 | 四张卡以 80ms 间隔落入队列;p2-15 左右分屏:左侧「排队」四卡依次亮(串行),右侧「并行」前三卡同时亮;p2-16 画面中央压入一行提示条(`core` 描边) | | 2-F | p2-17..24 | **真值表**:三列(工具 / 只读 / 能并行),五行(读文件、找文件、`ls`、`rm`、建任务) | p2-17 先只显示「只读」列并全部打勾(符合直觉);p2-19 时 `ls` 与 `rm` 两行的「能并行」列**结论分岔**——`ls` 打 `mech` 勾、`rm` 打 `deny` 叉,两行之间画一条对撞线;p2-20 两行工具名同时闪一次(同名不同命);p2-22 建任务行的「只读」叉与「能并行」勾同时亮起(更绕的反例);p2-24 金句卡 | | 2-G | p2-25..26 | 一排五个工具调用块按原顺序排列,上方落下分组括号 | 括号自左向右扫描落位:前三块归入一个 `mech` 组(组内三块**同时**脉冲=并行),中间一块单独成组(单独脉冲=串行),末块再一组;组与组之间画顺序箭头 | @@ -49,7 +49,7 @@ | 3-A | p3-01..06 | 五张工具卡回归,其中四张外面套着一个 `mech` 色的「工作目录」框,跑命令那张**在框外** | p3-02 框线描出并把四张卡收进去,第五张卡留在框外并轻微抖动;p3-04 该卡吐出一条 `deny` 色命令,命令文字放大并使画面整体压暗一档;p3-05 环形循环的执行节点照常亮起("老老实实替它执行"的反讽);p3-06 一道竖线从顶部落下 | | 3-B | p3-07..09 | **闸门路由**成形:请求从左侧进入,前方三道竖闸依次落下(1 号 `deny` 描边、2 号 `mech`、3 号 `mech` 虚线) | 三道闸门以 `spring` 自上落下(每句一道);p3-08 第一道闸门上浮出四个禁令词;p3-09 一个请求光点撞上第一道闸门被**反弹回左侧**并碎成 `deny` 色粒子 | | 3-C | p3-10..13 | 第二、三道闸门工作:一个请求穿过一道被标记,停在第三道前等待;另一个请求三道全过直接抵达执行口 | p3-10/11 请求光点穿过一闸后头顶浮出「看情况」标签;p3-12 第三道闸门前画面**整体降速并压暗**,弹出「工具名 + 参数」审批卡与 y/N 光标;p3-13 另一条通路上一个光点畅通无阻直达执行口,并在轨迹上留下 `core` 尾迹 | -| 3-D | p3-14..19 | 拒绝表代码卡(mono,七个字符串)居中;随后表下方浮出课程原话引用 | p3-15 代码卡逐行渲染;p3-16/17 表的边框由 `deny` 变为 `dim` 虚线("示意"而非"边界"的视觉降级);p3-18 表右侧生成三条变体写法,逐条**绕过**表框飞向执行口;p3-19 金句卡 `serif` 居中 | +| 3-D | p3-14..19 | 拒绝表代码卡(mono,七个字符串)居中;随后表下方浮出原话引用 | p3-15 代码卡逐行渲染;p3-16/17 表的边框由 `deny` 变为 `dim` 虚线("示意"而非"边界"的视觉降级);p3-18 表右侧生成三条变体写法,逐条**绕过**表框飞向执行口;p3-19 金句卡 `serif` 居中 | | 3-E | p3-20..24 | 四个结果徽标呈四宫格:放行(`core`)、拒绝(`deny`)、问你(`mech`)、不表态(`dim` 描边) | p3-21 前三格先亮(对应三道闸门),第四格空着并有呼吸描边;p3-23 第四格亮起「不表态」;p3-24 从第四格拉出一条弧线**回连到「问你」格**,弧线上压「兜底」二字 | | 3-F | p3-25..29 | 八个来源叠成一摞卡片(由下到上:全局 / 项目 / 本地 / 功能开关 / 公司策略),右侧三个旁路小卡(启动参数 / 内联命令 / 会话授权) | p3-26/27 卡片自下向上逐张堆叠(每张带 4px 纵向位移与投影);p3-28 一支箭头从底向顶穿过整摞并在「公司策略」处放大——`mech` 辉光;p3-29 顶部两张卡之间画一个"压过"符号,其余卡片降到 50% 亮度 | | 3-G | p3-30..35 | 三级漏斗:宽松模式试判 → 安全白名单 → 小模型判断,末端一个「刹车」闸 | p3-31 漏斗三段描出;p3-32/33 一个请求光点依次穿过三段,每段命中就直接从侧边出口离开(不进下一段);p3-34 小模型段连续吐出三个 `deny` 叉后,末端刹车闸落下并把通路切回「人工审批」;p3-35 金句压底 | @@ -64,7 +64,7 @@ | 4-D | p4-13..19 | **插槽注册板**:环形循环外围四个插槽,按一整轮的时间顺序分布在环的四个方位 | 四个插槽逐句亮起并各插入对应回调卡:p4-14 入口槽(补背景信息的卡片飞入并在消息上加一小块 `mech` 补丁);p4-15/16 执行前槽——**P3 的三道闸门整体缩小、平移进这个槽**(跨幕视觉呼应),环上原本的检查标记同时消失;p4-17 执行后槽;p4-18/19 停机前槽亮 `core`,卡片返回一句话 → 一条回流箭头把它送回环的入口,环重新转起来 | | 4-E | p4-20..22 | 四个插槽同时点亮,环上标出四个时机点;环本身刻意**不加任何装饰** | 四点沿环依次脉冲一圈(顺时针,各 8 帧);p4-21 环上只浮出四个极简的喇叭图标("只喊一声");p4-22 金句卡;金句期间环继续匀速转动,不做任何强调动效——用"无动效"表达"故意保持无聊" | | 4-F | p4-23..25 | **27 格事件矩阵**:9×3 网格,前四格已是 `mech` 实心(教学版覆盖),其余 23 格为 `panelBorder` 空框 | p4-24 计数器从 4 滚到 27,同时 23 个空框以 20ms 间隔快速点亮为半透明 `mech`;p4-25 被念到的几类事件所在格子加描边并浮出标签;矩阵右下角保留「4 / 27」比例条 | -| 4-G | p4-27..34 | 上下两层对撞:上层是插槽卡返回的「我批了」(`core` 印章),下层是配置文件里的「禁止 / 询问」(`deny` / `mech` 印章) | p4-29 上层印章落下并向下推进;p4-31 下层两枚印章升起**顶住**上层,接触处爆出一圈 `deny` 冲击波,上层印章被弹回;p4-32 画面中央生成一个单向箭头(只允许「加限制」方向通过,反向被 `deny` 挡板封住);p4-33/34 教学版一侧的这层挡板缺失、露出一个 `deny` 色缺口,缺口旁压课程作者的评语 | +| 4-G | p4-27..34 | 上下两层对撞:上层是插槽卡返回的「我批了」(`core` 印章),下层是配置文件里的「禁止 / 询问」(`deny` / `mech` 印章) | p4-29 上层印章落下并向下推进;p4-31 下层两枚印章升起**顶住**上层,接触处爆出一圈 `deny` 冲击波,上层印章被弹回;p4-32 画面中央生成一个单向箭头(只允许「加限制」方向通过,反向被 `deny` 挡板封住);p4-33/34 教学版一侧的这层挡板缺失、露出一个 `deny` 色缺口,缺口旁压第三方的评语 | | 4-H | p4-35..37 | 「别停」插槽与环的一段形成小闭环,反复自激;随后一枚标记落下把闭环打断 | p4-36 小闭环连转三圈,每圈提速一档、边缘 `deny` 色渐强(自激失控感);p4-37 一枚 `core` 色方形标记从上落下嵌入闭环,第四圈行进到标记处被**截断**,整体归于静止 | ## P5 四层叠起来是什么 @@ -81,4 +81,4 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 6-A | p6-01..04 | 壳的四层分别点亮并各配一句短标签(手脚 / 工具 / 底线 / 发挥) | 四层以每句一层的节奏点亮,点亮时对应标签 `FadeUp`;四层齐亮后整体轻微收拢一次(呼吸) | -| 6-B | p6-05..08 | 信源卡:课程名 / 仓库 / 固定提交号前七位 / 访问日期 / MIT 许可;随后系列身份卡;**渐黑** | 信源卡逐行浮现(mono 小字);系列身份卡 `serif` 淡入;**渐黑窗口从本 beat 的总时长推导**(`beatDurationInFrames`,不是末句时长——第三集上线教训,见 skills/06 红线四),末 1.2s 线性压暗到全黑 | +| 6-B | p6-05..08 | 信源卡:官方文档 + 取数日期 / 第三方源码分析已逐处标注;随后系列身份卡;**渐黑** | 信源卡逐行浮现(mono 小字);系列身份卡 `serif` 淡入;**渐黑窗口从本 beat 的总时长推导**(`beatDurationInFrames`,不是末句时长——第三集上线教训,见 skills/06 红线四),末 1.2s 线性压暗到全黑 | diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx index c9ab1c8c..25d8568e 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx @@ -290,7 +290,7 @@ const TitleCard: React.FC = () => {
- {'拆开 Claude Code'} + {'执行层:一个循环,就是全部'}
= ({yesAt, noAt}) => { const active = frame >= yesAt && frame < noAt ? 2 : undefined; return ( - + 0.98 ? dot : undefined} activeNode={active} exitPull={pull} /> {'有 tool_use → 继续 · 没有 → 退出'} @@ -312,7 +312,7 @@ const UnreliableFlag: React.FC<{crossAt: number; quoteAt: number}> = ({crossAt, ) : null}
- {'stop_reason is unreliable —— 课程作者的源码分析 · 站点教学版仍按停止标记判定,仓库版已改为查内容块'} + {'stop_reason is unreliable —— 第三方的源码分析 · 开源教学版仍按停止标记判定,官方实现已改为查内容块'} ); @@ -330,16 +330,16 @@ const TenDrawers: React.FC<{restAt: number; chapterAt: number; recedeAt: number} const dot = useRingDot(2.5); // 章号只是「每个抽屉都指向后面某一章」的视觉证据,不进口播(活数据纪律) const drawers = [ - {label: '消息列表', ch: 's01'}, - {label: '工具与权限上下文', ch: 's02'}, - {label: '压缩状态追踪', ch: 's08'}, - {label: '输出补救次数', ch: 's11'}, - {label: '本轮是否压缩过', ch: 's08'}, - {label: '输出上限覆盖', ch: 's11'}, - {label: '后台摘要', ch: 's08'}, - {label: '钩子拦过停机', ch: 's04'}, - {label: '轮数计数', ch: 's01'}, - {label: '上次继续原因', ch: 's11'}, + {label: '消息列表', ch: '循环'}, + {label: '工具与权限上下文', ch: '工具'}, + {label: '压缩状态追踪', ch: '压缩'}, + {label: '输出补救次数', ch: '补救'}, + {label: '本轮是否压缩过', ch: '压缩'}, + {label: '输出上限覆盖', ch: '补救'}, + {label: '后台摘要', ch: '压缩'}, + {label: '钩子拦过停机', ch: '钩子'}, + {label: '轮数计数', ch: '循环'}, + {label: '上次继续原因', ch: '补救'}, ]; const recede = interpolate(frame - recedeAt, [0, 24], [0, 1], { extrapolateLeft: 'clamp', @@ -412,7 +412,7 @@ const TenDrawers: React.FC<{restAt: number; chapterAt: number; recedeAt: number}
) : null} - {'State 10 字段 —— 课程作者的源码分析'} + {'State 10 字段 —— 第三方的源码分析'}
); }; diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx index 87e19bf2..9d61af91 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx @@ -1,4 +1,4 @@ -/** P2 加一个工具,只改一行(分镜 2-A…2-H)—— 站点「Tool Dispatch Map」的概念重建 +/** P2 加一个工具,只改一行(分镜 2-A…2-H)—— 开源教学素材「Tool Dispatch Map」的概念重建 * 重点视觉演绎:并发安全 ≠ 只读(真值表对撞)、连续块分批、读文件落盘自循环。 */ import React from 'react'; import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoConfig} from 'remotion'; @@ -37,7 +37,7 @@ const ClumsyCommands: React.FC<{typoAt: number}> = ({typoAt}) => { const shake = bad ? Math.sin((frame - typoAt) / 1.6) * 3 : 0; return ( - +
@@ -344,7 +344,7 @@ const ConcurrencyTable: React.FC<{
) : null} - {'isConcurrencySafe ≠ isReadOnly —— 课程作者的源码分析'} + {'isConcurrencySafe ≠ isReadOnly —— 第三方的源码分析'}
); diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx index 299512f0..7eca6d6b 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx @@ -1,4 +1,4 @@ -/** P3 执行之前,先过闸门(分镜 3-A…3-G)—— 站点「Permission Desk」的概念重建 +/** P3 执行之前,先过闸门(分镜 3-A…3-G)—— 开源教学素材「Permission Desk」的概念重建 * 三种结果不各占一色:allow 回 core(放行=回主干)、ask 用 mech、deny 用 danger。 */ import React from 'react'; import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoConfig} from 'remotion'; @@ -34,7 +34,7 @@ const UnguardedShell: React.FC<{frameAt: number; cmdAt: number; execAt: number}> const dim = showCmd ? 0.55 : 1; return ( - +
{/* 工作目录框:把四张 file tool 收进去 */}
= ({askAt, passAt})
) : null} - {/* 三判定小抄(站点 Permission Desk 的信息结构):allow / ask / deny 各带真实载荷 —— + {/* 三判定小抄(开源教学素材 Permission Desk 的信息结构):allow / ask / deny 各带真实载荷 —— 本幕上方只演了 ask 与 allow,这里把第三条补齐,路由器的三种出口一目了然。 落位约束:小抄出现时(t2 > 0.4)闸门已整体上移 -150,GateRouter 的闸门名 (`y - h - 18`)落在 y≈235–258、闸柱顶到 y≈272——小抄必须整体收在其上方, @@ -422,7 +422,7 @@ const FourResults: React.FC<{fourthAt: number; arcAt: number}> = ({fourthAt, arc ) : null}
- {'PermissionResult 四种 —— 课程作者的源码分析'} + {'PermissionResult 四种 —— 第三方的源码分析'}
); }; @@ -571,7 +571,7 @@ const EightSources: React.FC<{stackAt: number; arrowAt: number; overrideAt: numb ))}
- {'user < project < local < flag < policy —— 课程作者的源码分析'} + {'user < project < local < flag < policy —— 第三方的源码分析'}
); diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx index b1235170..56238224 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx @@ -1,4 +1,4 @@ -/** P4 挂在循环上,不写进循环里(分镜 4-A…4-H)—— 站点「Hook Workbench」的概念重建 +/** P4 挂在循环上,不写进循环里(分镜 4-A…4-H)—— 开源教学素材「Hook Workbench」的概念重建 * 4-E 刻意「无动效」表达「循环是故意保持无聊的」;4-G 是全片安全主题的收口。 */ import React from 'react'; import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoConfig} from 'remotion'; @@ -37,7 +37,7 @@ const NeedsPierce: React.FC<{needAt: number; pierceAt: number}> = ({needAt, pier }); return ( - +
{pierce > 0.4 ? ( @@ -424,7 +424,7 @@ const EventMatrix: React.FC<{countAt: number; labelAt: number}> = ({countAt, lab {'个时机(教学版只讲了 4 个)'}
- {'27 hook events —— 课程作者的源码分析'} + {'27 hook events —— 第三方的源码分析'}
); }; @@ -563,7 +563,7 @@ const StampClash: React.FC<{ ) : null}
- {'hook allow 不能绕过 settings 的 deny/ask —— 课程作者的源码分析'} + {'hook allow 不能绕过 settings 的 deny/ask —— 第三方的源码分析'} ); diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx index 16ad8452..26499115 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx @@ -171,11 +171,11 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> const {fps} = useVideoConfig(); const enter = spring({frame: frame - 4, fps, config: {damping: 200}}); const rows = [ - ['课程', 'Learn Claude Code · 工具与执行四章'], - ['站点', 'learn.shareai.run/zh/s01..s04'], - ['仓库', 'github.com/shareAI-lab/learn-claude-code'], + ['官方文档', 'code.claude.com/docs · 取数 2026-08'], + ['工程博客', 'anthropic.com/engineering'], + ['源码分析', '第三方逆向分析 · 片中逐处标注'], ['仓库钉版', 'main @ f9e8b28(2026-08-18)'], - ['站点同源修订', '67a9126c(2026-07-28,20 章版)'], + ['数字口径', '画面行数均为固定提交实测'], ['访问日期', '2026-08-21'], ['许可', 'MIT'], ]; @@ -230,7 +230,7 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> }), }} > - {'画面中的行数均为本片在钉定提交上的实测(非空非注释口径),非课程标注'} + {'画面中的行数均为本片在固定提交上的实测(非空非注释口径)'}
@@ -244,7 +244,7 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> }} >
- {'Claude Code 通俗全解'} + {'Claude Code Harness Engineering'}
marginTop: 18, }} > - {'拆开 Claude Code'} + {'执行层:一个循环,就是全部'}
{'让 AI 动手的四层机制'} diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/README.md b/apps/negentropy-influence/episodes/claude-code-memory-video/README.md index b22b2030..14142ace 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/README.md +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/README.md @@ -1,4 +1,4 @@ -# 《AI 的记忆:会丢的和不能丢的》科普视频工程 +# 《记忆层:会丢的和不能丢的》科普视频工程 **已交付**。发布顺序见 [../../series.json](../../series.json)。 diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json index 0bd88792..cbcaec74 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json @@ -92,7 +92,7 @@ { "id": "p1-02", "scene": "P1", - "text": "窗口满了,等于桌子满了。收拾桌子,课程给出了四级办法。" + "text": "窗口满了,等于桌子满了。收拾桌子,教学版给出了四级办法。" }, { "id": "p1-03", @@ -172,7 +172,7 @@ { "id": "p1-18", "scene": "P1", - "text": "顺带一提:课程作者说,这类保洁产品里每过一小时主动做一遍,不等桌子满。" + "text": "顺带一提:有位作者说,这类保洁产品里每过一小时主动做一遍,不等桌子满。" }, { "id": "p1-19", @@ -292,7 +292,7 @@ { "id": "p2-22", "scene": "P2", - "text": "课程作者核对过源码,产品里真实顺序也是入库在前。一个看似平常的先后," + "text": "有人核对过源码,产品里真实顺序也是入库在前。一个看似平常的先后," }, { "id": "p2-23", @@ -317,7 +317,7 @@ { "id": "p3-03", "scene": "P3", - "text": "课程作者把产品里给它的指令原文抄了出来,开头第一句就是:" + "text": "有人把产品里给它的指令原文抄了出来,开头第一句就是:" }, { "id": "p3-04", @@ -352,7 +352,7 @@ { "id": "p3-10", "scene": "P3", - "text": "课程作者说,产品里压缩结束,会自动把最近读过的文件捞回桌面:" + "text": "有位作者说,产品里压缩结束,会自动把最近读过的文件捞回桌面:" }, { "id": "p3-11", @@ -372,7 +372,7 @@ { "id": "p3-14", "scene": "P3", - "text": "这一步课程的教学版没做,是课程作者从源码里读出来的——所以口播到这里," + "text": "这一步教学版没做,是有人从源码里读出来的——所以口播到这里," }, { "id": "p3-15", @@ -397,7 +397,7 @@ { "id": "p4-03", "scene": "P4", - "text": "课程里有个特别扎心的例子。你认真交代过:缩进用 tab,别用空格。" + "text": "有个特别扎心的例子。你认真交代过:缩进用 tab,别用空格。" }, { "id": "p4-04", @@ -507,7 +507,7 @@ { "id": "p4-25", "scene": "P4", - "text": "课程作者拆过源码,他说产品里干这活的,就是一个普通的小号模型。" + "text": "有人拆过它的源码——产品里干这活的,就是一个普通的小号模型。" }, { "id": "p4-26", @@ -552,7 +552,7 @@ { "id": "p5-05", "scene": "P5", - "text": "课程作者拆过源码,他说产品里由一个「停机钩子」触发这件事:" + "text": "有人拆过它的源码——产品里由一个「停机钩子」触发这件事:" }, { "id": "p5-06", @@ -587,7 +587,7 @@ { "id": "p5-12", "scene": "P5", - "text": "课程作者说产品里这个整理的活有个正式名字,起得很有画面感:做梦。" + "text": "有人分析过,产品里这个整理的活有个正式名字,起得很有画面感:做梦。" }, { "id": "p5-13", @@ -672,17 +672,17 @@ { "id": "p6-07", "scene": "P6", - "text": "本片内容来自开源课程《Learn Claude Code》的记忆两章。" + "text": "本片机制依据官方文档与公开工程实践,取数日期在画面上。" }, { "id": "p6-08", "scene": "P6", - "text": "代码取自课程仓库的固定版本,取证字节已随片归档,链接在简介里。" + "text": "涉及产品内部的部分,来自第三方的源码分析,片中已逐处标注。" }, { "id": "p6-09", "scene": "P6", - "text": "涉及产品内部的部分,均为课程作者的源码分析,片中已逐处标注。" + "text": "涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注。" }, { "id": "p6-10", diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md index 741805f8..1378442a 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md @@ -11,7 +11,7 @@ ## P0 一次拒收 > 画面:系列终端。读文件、跑命令的输出一条条堆进对话;窗口进度条涨满、撞上「拒收」墙。 -> 角标:s08 Context Compact · "Context Will Fill Up" +> 角标:Context Compact · "Context Will Fill Up" - [p0-01] 它正在干活,突然,停了。屏幕上一行报错,活干到一半,人愣在原地。 - [p0-02] 不是它不想干,是服务那边把它拒收了。拒收,是必然发生的日常。 @@ -37,7 +37,7 @@ > 角标:50 条 / 头 3 尾 47 · 最近 3 条完整保留 · 120 字阈值 - [p1-01] 先把画面换个说法:它随身的全部对话,就是一张会塞满的桌子。 -- [p1-02] 窗口满了,等于桌子满了。收拾桌子,课程给出了四级办法。 +- [p1-02] 窗口满了,等于桌子满了。收拾桌子,教学版给出了四级办法。 - [p1-03] 四级办法的原则只有一条:便宜的先来,贵的最后。 - [p1-04] 先干不用花钱的,实在不行才请人。你会看到这条原则贯穿到底。 - [p1-05] 第一级,裁中段。桌上的纸超过五十张,就只留开头三张和最近四十七张, @@ -53,7 +53,7 @@ - [p1-15] 反正真需要的时候,再让它跑一遍就是——纸可以折,活不用重干。 - [p1-16] 注意折叠只动超过一百二十字的旧结果,短的就留着,不值得动它。 - [p1-17] 这两级全是纯文本操作,一次模型都不用请,便宜到近乎免费。 -- [p1-18] 顺带一提:课程作者说,这类保洁产品里每过一小时主动做一遍,不等桌子满。 +- [p1-18] 顺带一提:有位作者说,这类保洁产品里每过一小时主动做一遍,不等桌子满。 - [p1-19] 但前两级只能腾出有限的空间——真正的大头在后面。 - [p1-20] 记住这个次序感:先动最不心疼的,再动开始心疼的。这是全章的节拍。 @@ -84,7 +84,7 @@ - [p2-19] 你把空气存进了档案室。 - [p2-20] 我们在画面里把顺序对调一次给你看:折叠先行,大块头瞬间缩成一行, - [p2-21] 入库的手伸过去,抓到的只有那行字。整桌证据,就这么没了。 -- [p2-22] 课程作者核对过源码,产品里真实顺序也是入库在前。一个看似平常的先后, +- [p2-22] 有人核对过源码,产品里真实顺序也是入库在前。一个看似平常的先后, - [p2-23] 背后是「先保存、再丢弃」的正确性论证。顺序,也是设计。 - [p2-24] 很多系统坏在这种地方:每一步都对,合起来的次序错了。 @@ -96,18 +96,18 @@ - [p3-01] 四级收拾里还有两个角色值得单独说说。 - [p3-02] 一个是写摘要这位帮工。它的纪律严得有点好笑。 -- [p3-03] 课程作者把产品里给它的指令原文抄了出来,开头第一句就是: +- [p3-03] 有人把产品里给它的指令原文抄了出来,开头第一句就是: - [p3-04] 这次只许写字,绝不许调用任何工具。结尾还要再叮嘱一遍。 - [p3-05] 为什么叮嘱两遍?请来收拾桌子的,手上偏偏有搬东西的能力。 - [p3-06] 真让它边收拾边调用工具,桌子越收越满,收拾就变成了新的堆积。 - [p3-07] 它还必须先在草稿区理清思路,再誊出正式摘要。 - [p3-08] 草稿写完就撕掉,不留在桌上——草稿是给它自己看的,不是给对话看的。 - [p3-09] 另一个角色,是一个很多人不知道的动作。压完之后,系统还会往回捞。 -- [p3-10] 课程作者说,产品里压缩结束,会自动把最近读过的文件捞回桌面: +- [p3-10] 有位作者说,产品里压缩结束,会自动把最近读过的文件捞回桌面: - [p3-11] 最多捞五个文件,单份有限额,总量有预算,按重要性排队。 - [p3-12] 也就是说压缩不是一刀切——丢,也是分层次的丢, - [p3-13] 刚丢掉的、马上还要用的,先给你放回来。 -- [p3-14] 这一步课程的教学版没做,是课程作者从源码里读出来的——所以口播到这里, +- [p3-14] 这一步教学版没做,是有人从源码里读出来的——所以口播到这里, - [p3-15] 你听到的每一个细节都带着同一句提醒:这是他的分析,不是产品的说明书。 - [p3-16] 到这里,第一层讲完了:会丢的东西,被管得相当讲究。 @@ -119,7 +119,7 @@ - [p4-01] 但是你发现没有——四级收拾、应急抢救、往回捞,全是「桌面上的事」。 - [p4-02] 桌面上的东西再怎么管,都有一个共同命运:迟早被压掉。 -- [p4-03] 课程里有个特别扎心的例子。你认真交代过:缩进用 tab,别用空格。 +- [p4-03] 有个特别扎心的例子。你认真交代过:缩进用 tab,别用空格。 - [p4-04] 这句话原封不动躺在对话里,一切都好。 - [p4-05] 几轮压缩之后,它被摘成了六个字:有代码风格偏好。 - [p4-06] 摘要没有做错什么——摘要的天性就是丢细节,保主干。 @@ -141,7 +141,7 @@ - [p4-22] 请它挑真正用得上的,最多五条;拿不准就不挑,宁缺毋滥。 - [p4-23] 挑错了比没挑更糟——一条不相干的记忆,就是一句错误的自我介绍。 - [p4-24] 这条小支路要是失败了,就退回最笨的关键词匹配——便宜的路总得有兜底。 -- [p4-25] 课程作者拆过源码,他说产品里干这活的,就是一个普通的小号模型。 +- [p4-25] 有人拆过它的源码——产品里干这活的,就是一个普通的小号模型。 - [p4-26] 不用什么向量检索——名字加描述摆在那里,让模型自己读着挑,反而更可靠。 - [p4-27] 挑出来的内容也不进基本设定,是临时贴进这一轮的对话里—— - [p4-28] 用完就过气,不占第二天的地盘。取记忆,也是一次性的。 @@ -157,14 +157,14 @@ - [p5-02] 写入登记簿这件事,发生在每一轮结束的时候——对话告一段落,活干完了。 - [p5-03] 关键在于取材的时机:提取器看的,是压缩之前的那份完整对话。 - [p5-04] 也就是说,那张「用 tab」的字条在被摘掉之前,就先被抄走了。 -- [p5-05] 课程作者拆过源码,他说产品里由一个「停机钩子」触发这件事: +- [p5-05] 有人拆过它的源码——产品里由一个「停机钩子」触发这件事: - [p5-06] 派出去的提取器权限受限、最多五回合、干完不进对话,闷头干完就走。 - [p5-07] 把时间线摆在一起看,就明白这个先后有多讲究。 - [p5-08] 轮末:先从完整对话里抢救出值得记的,一个字不差地写进本子; - [p5-09] 然后压缩才来,碎纸机开动,桌面上的细节开始褪色。 - [p5-10] 先抢救,再碎纸。本子里的那句话,从此再也不进碎纸机。 - [p5-11] 本子会越攒越厚,同一件事记了三遍、过时的没淘汰,就得整理。 -- [p5-12] 课程作者说产品里这个整理的活有个正式名字,起得很有画面感:做梦。 +- [p5-12] 有人分析过,产品里这个整理的活有个正式名字,起得很有画面感:做梦。 - [p5-13] 这个梦有四道闸,一道不满足就不做。 - [p5-14] 距上次整理不满一天,不做——好记性不差这一天; - [p5-15] 扫描太频繁,不做——翻文件夹本身也有成本; @@ -186,9 +186,9 @@ - [p6-04] 一套负责固执地记:一事一文件、索引常驻、先抢救再碎纸。 - [p6-05] 你自己其实也是这么干的:便签随便撕,账本不乱丢。 - [p6-06] 区别只在于,它的账本每一页谁写、何时写、多久整理一次,都被设计过。 -- [p6-07] 本片内容来自开源课程《Learn Claude Code》的记忆两章。 -- [p6-08] 代码取自课程仓库的固定版本,取证字节已随片归档,链接在简介里。 -- [p6-09] 涉及产品内部的部分,均为课程作者的源码分析,片中已逐处标注。 +- [p6-07] 本片机制依据官方文档与公开工程实践,取数日期在画面上。 +- [p6-08] 涉及产品内部的部分,来自第三方的源码分析,片中已逐处标注。 +- [p6-09] 涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注。 - [p6-10] 如果下次它又忘了你的偏好,你知道该去哪找了—— - [p6-11] 不是它的脑子,是那个文件夹。 - [p6-12] 而你的偏好值不值得写进那个文件夹,说到底是你说了算。下期见。 diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/planning.md b/apps/negentropy-influence/episodes/claude-code-memory-video/script/planning.md index 89fac9a6..ca917a73 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/planning.md +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/planning.md @@ -1,4 +1,4 @@ -# 策划案:《AI 的记忆:会丢的和不能丢的》 +# 策划案:《记忆层:会丢的和不能丢的》 > 事实源:[../research/source-notes.md](../research/source-notes.md)(信源清单 [../research/sources.toml](../research/sources.toml)) > 逐字稿 SSOT:[narration.md](./narration.md) · 分镜:[storyboard.md](./storyboard.md) @@ -8,7 +8,7 @@ | 项 | 定义 | |---|---| -| 系列 | Claude Code 通俗全解(独立成片,口播不引他集) | +| 系列 | Claude Code Harness Engineering(独立成片,口播不引他集) | | 平台 / 形态 | B 站 / YouTube 横屏 1080p30,代码动画 + 本人克隆音色,无 BGM、无 emoji | | 时长 | `target_minutes = [13.0, 14.6]`;创作目标 ≈3900 字 / 165–195 句 | | 受众 | 普通人:都听过「AI 没记性」,但没想过记性是可以被工程拆成「会丢的桌面」和「不丢的本子」的 | diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md index 03834423..c69b82af 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md @@ -30,7 +30,7 @@ | 2-A | p2-01..06 | 第三级大件入库:五个大文件结果块拍上桌;按个头排队飞进右侧文件柜,桌上留预览卡(前 2000 字 + 库标记) | 大块落下震桌;排队飞入柜(弧线);预览卡弹回落位 | | 2-B | p2-07..13 | 第四级全桌重写:整段对话先复印进「档案」抽屉(保底)→ 帮工登场把整桌纸重写成一张摘要卡 | 复印动画(纸堆翻白入柜);帮工(小个子 `mech`)把纸堆卷成一张卡;整桌纸淡出仅留摘要卡;p2-13 三次失败计数点亮满 → 熔断章(`deny`) | | 2-C | p2-14..15 | 应急通道:拒收后保最近五张原纸,更早的换摘要,重试一次 | 最近五张纸被 `keep` 框住不动,其余迅速摘要化;「重试 ×1」角标 | -| 2-D | p2-16..24 | ★顺序论证·自毁演示:正常序(入库→折叠)走一遍成功;对调序(折叠先行)时大块头先缩成一行、入库的手抓空——「把空气存进档案室」 | 双轨对照动画:上轨正常序(✓)、下轨对调序(✗);下轨抓空瞬间画面碎裂一帧再复位(错误顺序的代价可视化);角标「课程作者核对源码:产品同序」 | +| 2-D | p2-16..24 | ★顺序论证·自毁演示:正常序(入库→折叠)走一遍成功;对调序(折叠先行)时大块头先缩成一行、入库的手抓空——「把空气存进档案室」 | 双轨对照动画:上轨正常序(✓)、下轨对调序(✗);下轨抓空瞬间画面碎裂一帧再复位(错误顺序的代价可视化);角标「第三方核对源码:产品同序」 | ## P3 应急通道与帮工纪律 @@ -38,7 +38,7 @@ |---|---|---|---| | 3-A | p3-01..06 | 帮工特写:头顶指令卡「只许写字·绝不调工具」,开头一张结尾又一张(首尾双叮嘱);旁边一只「工具之手」试图伸出被挡回 | 指令卡首尾各弹一次;工具之手伸出→被 `deny` 栏杆挡回,两次 | | 3-B | p3-07..08 | 草稿区与正式区:帮工先在草稿区写思路,誊清后草稿被撕掉 | 草稿字迹显现→整段誊写至正式卡→草稿碎纸飘落 | -| 3-C | p3-09..16 | ★回捞钩:压缩后文件柜门开,五张文件卡被钩回桌面按重要性排队;尾句诚实角标(教学版未做·源码分析) | 钩爪伸出依次捞回五张;末句角标浮现「本段为课程作者的源码分析」 | +| 3-C | p3-09..16 | ★回捞钩:压缩后文件柜门开,五张文件卡被钩回桌面按重要性排队;尾句诚实角标(教学版未做·源码分析) | 钩爪伸出依次捞回五张;末句角标浮现「本段为第三方的源码分析」 | ## P4 不丢的那一层 @@ -65,4 +65,4 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 6-A | p6-01..06 | 一句话合同金句卡(`serif` `keep` 描边)→ 两行回收(体面地忘 / 固执地记) | 金句卡淡入;两行小字对仗浮现 | -| 6-B | p6-07..12 | 信源卡(课程/站点/仓库/钉版 67a9126c/归档/MIT + 诚实行)→ 身份卡 → 渐黑(末 beat 总时长推导,红线四) | 逐行浮现;身份卡;末 1.2s 线性压暗 | +| 6-B | p6-07..12 | 信源卡(官方文档+取数日期 / 第三方源码分析已逐处标注 / 数字均为实测口径)→ 身份卡 → 渐黑(末 beat 总时长推导,红线四) | 逐行浮现;身份卡;末 1.2s 线性压暗 | diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx index 7fddee03..6936d531 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx @@ -59,7 +59,7 @@ const ErrorSlam: React.FC<{errAt: number}> = ({errAt}) => {
) : null}
- {'s08 Context Compact · "Context Will Fill Up"'} + {'Context Compact · "Context Will Fill Up"'}
); }; diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P1Desk.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P1Desk.tsx index 205bb628..53a1d0aa 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P1Desk.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P1Desk.tsx @@ -16,7 +16,7 @@ const DeskIntro: React.FC<{ruleAt: number}> = ({ruleAt}) => { const drop = spring({frame: frame - ruleAt, fps, config: {damping: 13}}); return ( - +
@@ -276,7 +276,7 @@ const SnipMiddle: React.FC<{ {'尾 47'}
- {'超过 50 条才触发 · 头 3 尾 47 —— 仓库实测(s08 snip_compact)'} + {'超过 50 条才触发 · 头 3 尾 47 —— 仓库实测(snip_compact)'}
); }; @@ -344,7 +344,7 @@ const FoldOld: React.FC<{foldAt: number[]; recentAt: number}> = ({foldAt, recent
- {'只折超过 120 字的旧结果 · 折叠不重跑 —— 仓库实测(s08 micro_compact)'} + {'只折超过 120 字的旧结果 · 折叠不重跑 —— 仓库实测(micro_compact)'} ); diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P2Tidy.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P2Tidy.tsx index 5d4eb07c..563e74c1 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P2Tidy.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P2Tidy.tsx @@ -124,7 +124,7 @@ const VaultBig: React.FC<{dropAt: number; flyAt: number; previewAt: number}> = ( style={{position: 'absolute', right: 60, top: 30}} />
- {'超过 200KB 才入库 · 预览 2000 字 —— 仓库实测(s08 macro_compact)'} + {'超过 200KB 才入库 · 预览 2000 字 —— 仓库实测(macro_compact)'}
); }; @@ -406,7 +406,7 @@ const RescueLane: React.FC = () => { {'重试 ×1 · 再不行把错误往上交'}
- {'保 5 条 · 重试 1 次 —— 仓库实测(s08 reactive_compact)'} + {'保 5 条 · 重试 1 次 —— 仓库实测(reactive_compact)'} ); }; @@ -628,7 +628,7 @@ const OrderMatters: React.FC<{normalAt: number; swapAt: number; grabAt: number; /> ))}
- {'课程作者核对源码:产品真实顺序入库在前 —— 「先保存、再丢弃」'} + {'第三方核对源码:产品真实顺序入库在前 —— 「先保存、再丢弃」'}
); }; diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx index e631b776..d80e77f8 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx @@ -177,7 +177,7 @@ const HelperDiscipline: React.FC<{firstAt: number; lastAt: number; handAt: numbe })}
- {'指令原文由课程作者从产品里抄出(首尾各一遍)—— 课程作者的源码分析'} + {'指令原文由第三方从产品里抄出(首尾各一遍)—— 第三方的源码分析'}
); @@ -280,7 +280,7 @@ const DraftThenFair: React.FC<{draftAt: number; fairAt: number; tearAt: number}> - {'草稿写完就撕掉,不留在桌上 —— 仓库实测(s08 摘要双标签)'} + {'草稿写完就撕掉,不留在桌上 —— 仓库实测(摘要双标签)'} ); }; @@ -404,7 +404,7 @@ const SalvageHook: React.FC<{openAt: number; hookAt: number; honestAt: number}> }), }} > - {'本段为课程作者的源码分析(产品行为,教学版未做)'} + {'本段为第三方的源码分析(产品行为,教学版未做)'} diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx index 7318d73e..7f39705f 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx @@ -227,7 +227,7 @@ const TabToSummary: React.FC<{beamAt: number; rewriteAt: number; shredAt: number {'摘要没有做错什么——可有些细节,恰恰是主干'} - {'例子出自课程 s09 原文(README @ 67a9126c)'} + {'例子出自开源教学仓库原文(README @ 67a9126c)'} ); }; @@ -245,7 +245,7 @@ const LedgerArrives: React.FC<{bookAt: number; fmAt: number[]; indexAt: number; const dup = spring({frame: frame - dupAt, fps, config: {damping: 13}}); return ( - +
{/* 登记簿:keep 实体 */}
= ({litAt}) => { ); })}
- {'四类记忆,就是四个问题 —— 站点/仓库【一】'} + {'四类记忆,就是四个问题 —— 开源仓库实测【一】'} ); }; @@ -583,7 +583,7 @@ const TwoPaths: React.FC<{sideAt: number; cardsAt: number; shrinkAt: number; deg ) : null}
- {'产品用小号模型挑选 —— 课程作者的源码分析'} + {'产品用小号模型挑选 —— 第三方的源码分析'}
); }; diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P5Hinge.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P5Hinge.tsx index 186f80b0..a176f828 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P5Hinge.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P5Hinge.tsx @@ -406,7 +406,7 @@ const OrderStamp: React.FC<{stampAt: number; settleAt: number}> = ({stampAt, set - {'停机钩子触发提取 · 压缩前快照 —— 课程作者的源码分析'} + {'停机钩子触发提取 · 压缩前快照 —— 第三方的源码分析'} ); }; @@ -491,7 +491,7 @@ const DreamPlate: React.FC<{thickenAt: number; nightAt: number; plateAt: number} - {'同一件事记了三遍、过时的没淘汰,就得整理 —— 课程作者的源码分析'} + {'同一件事记了三遍、过时的没淘汰,就得整理 —— 第三方的源码分析'} ); }; @@ -596,7 +596,7 @@ const FourGatesFall: React.FC<{gateAt: number[]}> = ({gateAt}) => { ) : null} - {'四道闸(24h / 节流 / 会话数 / 文件锁)—— 课程作者的源码分析'} + {'四道闸(24h / 节流 / 会话数 / 文件锁)—— 第三方的源码分析'} ); @@ -727,7 +727,7 @@ const LockIsClock: React.FC<{faceAt: number; crashAt: number; spinAt: number; qu {'整理到一半崩了?一小时后锁自动过期,不会死锁'} - {'锁即时钟 · 1 小时过期 —— 课程作者的源码分析'} + {'锁即时钟 · 1 小时过期 —— 第三方的源码分析'} ); }; diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx index 58aad26e..dad2da76 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx @@ -1,6 +1,6 @@ /** P6 落点与信源(分镜 6-A…6-B) * 6-A 一句话合同金句卡(serif keep 描边)→ 两行回收(体面地忘 / 固执地记); - * 6-B 信源卡(课程/站点/仓库/钉版 67a9126c/归档/诚实行)→ 身份卡 → 渐黑。 + * 6-B 信源卡(官方文档/工程博客/第三方源码分析/实测口径)→ 身份卡 → 渐黑。 * ★ 渐黑窗口从**末 beat 总时长**(beatDurationInFrames)推导,不是末句时长 * —— 第三集上线教训(skills/06 渲染红线四)。 */ import React from 'react'; @@ -74,9 +74,9 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; idAt: number}> = ({ const {fps} = useVideoConfig(); const enter = spring({frame: frame - 4, fps, config: {damping: 200}}); const rows = [ - ['课程', 'Learn Claude Code · 记忆管理两章(s08/s09)'], - ['站点', 'learn.shareai.run/zh/s08'], - ['仓库', 'github.com/shareAI-lab/learn-claude-code'], + ['官方文档', 'code.claude.com/docs · 取数 2026-08'], + ['工程博客', 'anthropic.com/engineering'], + ['源码分析', '第三方逆向分析 · 片中逐处标注'], ['仓库钉版', '67a9126c(2026-08-22 取证)'], ['归档', '取证字节随片归档(research/source-archive/)'], ['许可', 'MIT'], @@ -132,7 +132,7 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; idAt: number}> = ({ }), }} > - {'涉及产品内部的部分,均为课程作者的源码分析,片中已逐处标注'} + {'涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注'} @@ -147,7 +147,7 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; idAt: number}> = ({ }} >
- {'Claude Code 通俗全解'} + {'Claude Code Harness Engineering'}
画面:系列终端。任务清单长到一个窗口装不下,滚动条缩成一根线; > 画面拉开——「一个它」的环孤零零悬着,四周是盖不住的模块群。 -> 角标:s15 Agent Teams · "One Agent isn't enough" +> 角标:Agent Teams · "One Agent isn't enough" - [p0-01] 你交给它一个真的大活:翻新整个后端,四个模块全都要动。 - [p0-02] 它开头干得不错。但修到接口时,认证那块的细节已经不在它的视野里了。 @@ -35,14 +35,14 @@ - [p1-03] 答案是一块看板:每个任务是一个小文件,写清楚五样东西—— - [p1-04] 编号、标题、状态、主人、还有它等谁完工。 - [p1-05] 「等谁完工」这格最关键。任务之间有先后:接口要等数据库,测试要等接口。 -- [p1-06] 盖房子不能先盖屋顶再打地基——课程里这句话,就是看板存在的理由。 +- [p1-06] 盖房子不能先盖屋顶再打地基——这句话,就是看板存在的理由。 - [p1-07] 于是任务连成一张图。谁先谁后不用人排:前面的完成了,后面的自动解锁。 - [p1-08] 做完「建表」,「接口」和「文档」同时亮起可领——排序是图自己算出来的。 - [p1-09] 还有个特别诚实的设计:你引用了一个不存在的任务当依赖,它不报错、不崩, - [p1-10] 就是把你挡住。宁可挡着你,也不让一个笔误炸掉整块看板。 - [p1-11] 你可能觉得这设计保守。但想想看板是给一群它用的: - [p1-12] 一个成员写错一个编号就全盘崩掉,这买卖做不得。防御性不是胆小,是算账。 -- [p1-13] 课程作者拆过源码,他说产品里这套看板更严:认领动作包在文件锁里完成—— +- [p1-13] 有人拆过它的源码——产品里这套看板更严:认领动作包在文件锁里完成—— - [p1-14] 先看一眼没人抢、再落笔写主人,两步并成一步,中间插不进第二只手。 - [p1-15] 编号也有讲究:一个只增不减的计数器,防止编号被重复使用。 - [p1-16] 看板立好了。谁来看?都可以——它就是硬盘上的一堆文件,能读就能看。 @@ -71,7 +71,7 @@ - [p2-11] 文件是给人和它共同看的地方——协作系统做到这一步,才算真的透明。 - [p2-12] 领队也是这规矩。队友干完活,把总结投进领队的信箱; - [p2-13] 领队隔一阵收一次信,把信里的内容贴进自己的对话,接着指挥。 -- [p2-14] 课程作者拆过源码,他说产品里真就是这么做的——信箱真的是文件, +- [p2-14] 有人拆过它的源码——产品里真就是这么做的——信箱真的是文件, - [p2-15] 只不过写文件加了一把锁,防止两个队友同时投信把信写串行。 - [p2-16] 他还说消息其实有十五种:汇报、请示、审批、关机、广播…… - [p2-17] 名目繁多,但底子全是同一个动作:往对方的文件里,加一行带类型的字。 @@ -101,7 +101,7 @@ - [p3-09] 一张关机的回复,永远不会误批掉一份计划。类型错一个字,直接弹开。 - [p3-10] 同一套机制换个方向就是审批:队友要动高风险的东西,先交一份计划等批。 - [p3-11] 计划这头等回复,回复那头带编号回来,批了才动手。 -- [p3-12] 课程作者拆过源码,他说产品里的关机更讲究,是三向的: +- [p3-12] 有人拆过它的源码——产品里的关机更讲究,是三向的: - [p3-13] 请求、同意或拒绝——拒绝还能附理由——最后系统广播一声「人已离场」, - [p3-14] 顺带把它的窗格、任务、名册统统收拾干净。 - [p3-15] 所谓协议,没有玄机:一张状态表、一个编号、几条对得上号的规矩。 @@ -115,7 +115,7 @@ > 角标:WORK→IDLE→SHUTDOWN · 信箱优先看板其次 · 60s 超时(教学版设计) - [p4-01] 到这里你可能会想:每次派活还要领队挨个分?十个任务分十次? -- [p4-02] 课程作者也这么想。所以队友学会了自己看板、自己认领。 +- [p4-02] 它的作者们也这么想。所以队友学会了自己看板、自己认领。 - [p4-03] 队友的一生分三段:干活、歇着、走人。 - [p4-04] 干完手头的活,不退出,进入歇着的状态。歇着时每五秒看两眼: - [p4-05] 先看信箱——里面可能有关机请求,也可能有新指令,有信就先处理信。 @@ -124,7 +124,7 @@ - [p4-08] 这样领队只需要把任务挂上板,剩下的分发全自动。 - [p4-09] 两只队友同时抢一个活怎么办?主人这一格先到先得,后到者查一眼就走。 - [p4-10] 歇着也不是永远歇。教学版的规矩是六十秒:一分钟等不来新活,收工走人, -- [p4-11] 临走把总结投进领队信箱。课程作者说产品里没有固定时限,队友一直活着, +- [p4-11] 临走把总结投进领队信箱。有人分析过,产品里没有固定时限,队友一直活着, - [p4-12] 等领队来握手告别。而且真实版歇着时还有个身份小机关: - [p4-13] 如果对话被压缩压得太短,它会把「我是谁、我是干嘛的」重新插回去。 - [p4-14] 干活得知道自己是谁。这句话对人对它都成立。 @@ -155,7 +155,7 @@ - [p5-15] 想拆?必须明说「丢弃改动」。宁可多签一次字,不悄悄丢掉任何工作。 - [p5-16] 建桌、拆桌、留桌,每次都记一行日志。谁何时动过哪张桌,翻账就知道。 - [p5-17] 一行日志看着轻,出了事它就是唯一的目击证人。 -- [p5-18] 课程作者拆过源码,他说产品里进出目录是整个进程跟着切过去—— +- [p5-18] 有人拆过它的源码——产品里进出目录是整个进程跟着切过去—— - [p5-19] 一旦进桌,它眼里的整个世界就是那张桌;产品里任务与目录也并不强制绑定。 - [p5-20] 教学版把绑定做成了默认,讲起来更清楚,这是两种取舍,都在角标里写明。 - [p5-21] 顺带交代一句悬着的话:工具本身也可以是别人造的。 @@ -167,24 +167,24 @@ > 画面:★系列终曲——七段传送带走完整一轮(进料/护栏/选面/执行/外接/补救/记账), > 每段亮起前几集机制的小图标;环在传送带正中恒转。 -> 角标:s20 · "Many mechanisms, one loop" · 27 个内建工具(源码分析) +> 角标:"Many mechanisms, one loop" · 27 个内建工具(源码分析) - [p6-01] 现在把这一集的四样东西摆回大图里:看板、信箱、握手、各自的桌子。 -- [p6-02] 再把课程最后一章的画面请出来:一整轮,从头到尾走一遍—— +- [p6-02] 再把收尾的全景画面请出来:一整轮,从头到尾走一遍—— - [p6-03] 你说一句话,进料口收下;定时和后台的通知排着队汇入; - [p6-04] 桌面太满就先收拾;记忆、技能、外接工具的状态拼成垫纸; - [p6-05] 然后问模型。有活干就过闸门、分发、执行、回填,再问下一轮; - [p6-06] 没活干就停机收尾。从头到尾,十几样机制各就各位。 - [p6-07] 这幅图上你要找的东西只有一个:那个循环。 - [p6-08] 从系列开头到今天,循环还是那个循环。变的从来不是它,是它周围的脚手架。 -- [p6-09] 课程最后一章的标语,也是整个系列最好的注脚——机制很多,循环一个。 +- [p6-09] 官方工程博客的注脚,也是这一系列最好的收束——机制很多,循环一个。 - [p6-10] 一群它,不是一群更聪明的它。多出来的不是智慧, - [p6-11] 是把协作拆成了看得见的零件:板子、信箱、编号、桌子。 - [p6-12] 零件朴素,不等于组合简单。哪张卡挡哪条路,哪个编号对哪次话, - [p6-13] 桌子什么时候不许拆——每一个「不」,都是从翻过的车上学来的。 - [p6-14] 拆完这一系列你会发现同一个规律:听起来越神的功能,拆开越是旧零件。 - [p6-15] 看板是文件夹,信箱是文本文件,握手是一张对照表,隔离是一间空目录。 -- [p6-16] 本片内容来自开源课程《Learn Claude Code》的后七章, -- [p6-17] 代码取自课程仓库的固定版本,取证字节已随片归档,链接在简介里。 -- [p6-18] 涉及产品内部的部分,均为课程作者的源码分析,片中已逐处标注。 +- [p6-16] 本片机制依据官方文档与公开工程实践,取数日期在画面上。 +- [p6-17] 涉及产品内部的部分,来自第三方的源码分析,片中已逐处标注。 +- [p6-18] 涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注。 - [p6-19] 这个系列到这里就拆完了。回头看,它一直没变过——下期见。 diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/planning.md b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/planning.md index e559f14f..b5d3b873 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/planning.md +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/planning.md @@ -1,4 +1,4 @@ -# 策划案:《一群 AI 怎么干活:看板、信箱与各自的桌子》 +# 策划案:《协作层:从一个到一群》 > 事实源:[../research/source-notes.md](../research/source-notes.md)(信源清单 [../research/sources.toml](../research/sources.toml)) > 逐字稿 SSOT:[narration.md](./narration.md) · 分镜:[storyboard.md](./storyboard.md) @@ -8,7 +8,7 @@ | 项 | 定义 | |---|---| -| 系列 | Claude Code 通俗全解(独立成片) | +| 系列 | Claude Code Harness Engineering(独立成片) | | 平台 / 形态 | B 站 / YouTube 1080p30,代码动画 + 本人克隆音色,无 BGM、无 emoji | | 时长 | `target_minutes = [13.0, 14.6]`;≈3900 字 | | 受众 | 普通人:听过「AI 智能体协作」的营销话术,没见过它到底由哪几样朴素的东西拼成 | diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md index 84075ea8..b5a762a7 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md @@ -20,7 +20,7 @@ |---|---|---|---| | 1-A | p1-01..06 | 工地入口立起看板(TaskBoard 母题):任务卡带五格(编号/标题/状态/主人/等谁);依赖箭头连成 DAG | 看板框架描线;三张示例卡贴上;「等谁完工」格高亮 + 依赖箭头逐条连出 | | 1-B | p1-07..10 | ★完成即解锁:「建表」卡打勾 → 箭头传导 →「接口」「文档」两卡同时亮起可领;★不存在依赖:一张虚线幽灵卡把请求卡挡住(不炸) | 完成勾动画 + 解锁波沿箭头传导;幽灵卡半透明+「算被挡」标签,请求卡撞上被弹回 | -| 1-C | p1-11..15 | 【三】文件锁帧:认领动作包进一把锁形罩子——「查看+落笔」两步在罩内一步完成,第二只手插不进;高水位计数器只增不减 | 锁罩合拢动画(mech);罩外一只手试图伸入被挡;计数器滚动且刻度只上不下;角标「课程作者的源码分析」 | +| 1-C | p1-11..15 | 【三】文件锁帧:认领动作包进一把锁形罩子——「查看+落笔」两步在罩内一步完成,第二只手插不进;高水位计数器只增不减 | 锁罩合拢动画(mech);罩外一只手试图伸入被挡;计数器滚动且刻度只上不下;角标「第三方的源码分析」 | | 1-D | p1-16..21 | 清单 vs 看板对照:左小卡(给自己看)右大板(给所有人看);收束句「硬盘上的东西人人可见」 | 左右对照布局;右侧看板向四方投出可见光束 | ## P2 话从哪里走:信箱 @@ -40,7 +40,7 @@ | 3-A | p3-01..05 | 杀线程之祸:掐线程瞬间,写一半的文件断在半空(裂口);握手替代:领队发关机请求→队友收尾→回「同意」→自行退出 | 文件裂口闪烁(deny);四步走位动画:请求卡出发→队友卡收拾(文件补全)→回执→退出 | | 3-B | p3-06..09 | ★握手轨(HandshakeRail 母题):请求卡带编号(req_0042)滑出停在「等回话」位;状态表 pending 行亮起;应答卡带同号归来对号合拢锁扣「咔」;类型校验:一张错类型回执被弹开 | 请求/应答卡沿轨对开;编号铭牌双方一致时合拢+锁扣声效帧;错类型卡撞上弹开(deny) | | 3-C | p3-10..11 | 计划审批同构:队友交计划卡等批,批文带编号回来,批了才动手 | 同一握手轨复用(方向反转);「批了才动手」门闸开合 | -| 3-D | p3-12..17 | 【三】三向关机:请求→同意/拒绝(可附理由)→系统广播「已离场」+ 窗格/任务/名册自动收拾;末句「协议没有玄机」定格 | 三向消息流;收拾动画(窗格收起、名册划名);角标「课程作者的源码分析」+「教学版未做执行门控」诚实标注 | +| 3-D | p3-12..17 | 【三】三向关机:请求→同意/拒绝(可附理由)→系统广播「已离场」+ 窗格/任务/名册自动收拾;末句「协议没有玄机」定格 | 三向消息流;收拾动画(窗格收起、名册划名);角标「第三方的源码分析」+「教学版未做执行门控」诚实标注 | ## P4 自己看板,自己认领 @@ -68,4 +68,4 @@ | 6-B | p6-03..06 | ★一整轮:包裹走完七段(进料/护栏/选面/执行/外接/补救/记账),每段亮起对应前几集机制小图标(清单/副桌/目录卡/垫纸/梯子/信箱/握手/桌子……) | 包裹逐段推进;每过一段该段图标亮起并短暂回闪其母题缩略 | | 6-C | p6-07..11 | ★系列终曲帧:环(core)从传送带中央升起放大居中——同色同宽同节点;「机制很多,循环一个」金句压场;「每个不字都是翻过的车」收尾 | 环升起重演描线一遍(与系列首集同款动画节奏);机制图标环立四周;金句卡(core)淡入 | | 6-D | p6-12..15 | 「旧零件」收束:看板=文件夹/信箱=文本/握手=对照表/隔离=空目录 四连小图 | 四连小图逐个亮起(mono 等宽字标注) | -| 6-E | p6-16..19 | 信源卡(课程/站点/仓库/钉版 67a9126c/归档/MIT/诚实行)→ 身份卡 → **渐黑**(末 beat 总时长推导,红线四);末句「它一直没变过」 | 逐行浮现;身份卡;末 1.2s 线性压暗到全黑 | +| 6-E | p6-16..19 | 信源卡(官方文档+取数日期 / 第三方源码分析已逐处标注 / 数字均为实测口径)→ 身份卡 → **渐黑**(末 beat 总时长推导,红线四);末句「它一直没变过」 | 逐行浮现;身份卡;末 1.2s 线性压暗到全黑 | diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx index be2fd5ce..2ccca7ef 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx @@ -409,7 +409,7 @@ export const P0Hook: React.FC<{scene: SceneRange}> = ({scene}) => { return ( - + {/* 拉镜点在 p0-03「一个注意力,盖不住一整个后端」 */} diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx index ac4b8f4b..26e15ec4 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx @@ -113,7 +113,7 @@ const BoardRises: React.FC<{cardsAt: number; arrowsAt: number}> = ({cardsAt, arr ]; return ( - +
{/* 看板框架描线(pathLength 归一化,红线三) */} @@ -589,7 +589,7 @@ const FileLock: React.FC<{lockAt: number; handAt: number; countAt: number}> = ({
- {'认领包进文件锁 · 高水位编号——课程作者的源码分析'} + {'认领包进文件锁 · 高水位编号——第三方的源码分析'} ); diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx index a589d057..ff71a9eb 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx @@ -26,7 +26,7 @@ const TempVsTeammate: React.FC<{fadeAt: number; seatAt: number}> = ({fadeAt, sea const seat = phase(frame, seatAt, 16); return ( - +
{/* 左:临时工剪影(干完即走)——淡出 */}
@@ -303,7 +303,7 @@ const MailboxRow: React.FC<{sendAt: number; readAt: number}> = ({sendAt, readAt}
) : null}
- {'写文件带锁,防两个队友投信写串行——课程作者的源码分析'} + {'写文件带锁,防两个队友投信写串行——第三方的源码分析'}
); }; @@ -356,7 +356,7 @@ const FifteenTypes: React.FC<{wallAt: number; shrinkAt: number}> = ({wallAt, shr {'往文件里加一行带类型的字'} {shrink < 0.5 ? ( - {'消息类型 15 种——课程作者的源码分析'} + {'消息类型 15 种——第三方的源码分析'} ) : null} ); diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx index aa252e0b..cde06687 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx @@ -259,7 +259,7 @@ const KillVsHandshake: React.FC<{crackAt: number; stepsAt: number}> = ({crackAt, const cur = steps ? Math.min(3, Math.floor((frame - stepsAt) / 18)) : -1; return ( - + {!steps ? (
{/* 掐线程的手:从上方掐住虚线线程 */} @@ -706,7 +706,7 @@ const ThreeWay: React.FC<{askAt: number; replyAt: number; castAt: number; settle ) : null}
- {'三向关机 · 拒绝可附理由——课程作者的源码分析;教学版未做执行门控(诚实标注)'} + {'三向关机 · 拒绝可附理由——第三方的源码分析;教学版未做执行门控(诚实标注)'}
); diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx index 0ec297ef..280209b5 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx @@ -31,7 +31,7 @@ const DispatchFatigue: React.FC<{cycleAt: number}> = ({cycleAt}) => { }; return ( - + {!showCycle ? (
{/* 领队(左):一张张派 */} diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx index 5757e712..edf8c07b 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx @@ -25,7 +25,7 @@ const Collision: React.FC<{writeAt: number; crushAt: number; knotAt: number}> = const knot = phase(frame, knotAt, 18); return ( - +
{/* 同一目录面板(中上) */}
= ({ {'产品里进出目录是整个进程跟着切;任务与目录也不强制绑定'}
- {'——课程作者的源码分析(教学版做成默认绑定)'} + {'——第三方的源码分析(教学版做成默认绑定)'}
diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx index 2f66aaa1..dbf7dba1 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx @@ -10,7 +10,7 @@ import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; import {Footnote, LoopRing, Panel, phase, SceneTag, useRingDot} from '../components/motifs'; -/** 七段传送带:进料 / 护栏 / 选面 / 执行 / 外接 / 补救 / 记账(s20 一整轮) */ +/** 七段传送带:进料 / 护栏 / 选面 / 执行 / 外接 / 补救 / 记账(一整轮) */ const SEGMENTS = [ {t: '进料', s: '你说一句话'}, {t: '护栏', s: '输入前钩子'}, @@ -39,7 +39,7 @@ const ConveyorForms: React.FC<{beltAt: number}> = ({beltAt}) => { }); return ( - + {/* 四小图标(顶部一排) */}
{four.map((f, i) => { @@ -133,7 +133,7 @@ const ConveyorForms: React.FC<{beltAt: number}> = ({beltAt}) => { ); })}
- {'课程最后一章:一整轮,从头到尾走一遍'} + {'收尾全景:一整轮,从头到尾走一遍'}
); }; @@ -484,9 +484,9 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> const {fps} = useVideoConfig(); const enter = spring({frame: frame - 4, fps, config: {damping: 200}}); const rows = [ - ['课程', 'Learn Claude Code · 多 Agent 平台七章'], - ['站点', 'learn.shareai.run/zh/s12..s20'], - ['仓库', 'github.com/shareAI-lab/learn-claude-code'], + ['官方文档', 'code.claude.com/docs · 取数 2026-08'], + ['工程博客', 'anthropic.com/engineering'], + ['源码分析', '第三方逆向分析 · 片中逐处标注'], ['仓库钉版', 'main @ 67a9126c(2026-08-22)'], ['访问日期', '2026-08-22'], ['许可', 'MIT'], @@ -539,7 +539,7 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> }), }} > - {'涉及产品内部的部分,均为课程作者的源码分析,片中已逐处标注'} + {'涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注'}
@@ -554,7 +554,7 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> }} >
- {'Claude Code 通俗全解'} + {'Claude Code Harness Engineering'}
交付状态:**已交付**。发布顺序见 [../../series.json](../../series.json)。 diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json index 75c51207..c58c1228 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json @@ -117,7 +117,7 @@ { "id": "p1-12", "scene": "P1", - "text": "课程作者有句话说得很准:这个工具不增加任何执行能力," + "text": "有位作者的句话说得很准:这个工具不增加任何执行能力," }, { "id": "p1-13", @@ -137,7 +137,7 @@ { "id": "p1-16", "scene": "P1", - "text": "产品里的做法也更细。课程作者拆过源码,他说清单工具背后还有一套更重的任务系统," + "text": "产品里的做法也更细。有人拆过它的源码——清单工具背后还有一套更重的任务系统," }, { "id": "p1-17", @@ -232,7 +232,7 @@ { "id": "p2-16", "scene": "P2", - "text": "到这里都是教学版的讲法。但课程作者拆过源码,他说真实产品里有个反转," + "text": "到这里都是教学版的讲法。但有人拆过它的源码——真实产品里有个反转," }, { "id": "p2-17", @@ -277,7 +277,7 @@ { "id": "p2-25", "scene": "P2", - "text": "还有更诚实的:隔离其实是半拉的。课程作者说,分身会继承父亲读过的文件," + "text": "还有更诚实的:隔离其实是半拉的。有位作者说,分身会继承父亲读过的文件," }, { "id": "p2-26", @@ -337,12 +337,12 @@ { "id": "p3-07", "scene": "P3", - "text": "课程的讲法很直白:目录常驻,内容按需。" + "text": "教学版的讲法很直白:目录常驻,内容按需。" }, { "id": "p3-08", "scene": "P3", - "text": "课程作者拆过源码,他说产品里这套目录的预算有硬顶——" + "text": "有人拆过它的源码——产品里这套目录的预算有硬顶——" }, { "id": "p3-09", @@ -402,7 +402,7 @@ { "id": "p3-20", "scene": "P3", - "text": "课程作者拆过源码,他说产品里这张纸常规状态有两三万字," + "text": "有人拆过它的源码——产品里这张纸常规状态有两三万字," }, { "id": "p3-21", @@ -462,7 +462,7 @@ { "id": "p4-06", "scene": "P4", - "text": "续写最多三次,三次还断就收手。课程作者拆过源码,把那条提示原文抄了出来," + "text": "续写最多三次,三次还断就收手。有人拆过源码,把那条提示原文抄了出来," }, { "id": "p4-07", @@ -522,7 +522,7 @@ { "id": "p4-18", "scene": "P4", - "text": "课程作者说产品里的恢复路径有十几种,教学版挑了最常见的三种讲;" + "text": "有人分析过,产品里的恢复路径有十几种,教学版挑了最常见的三种讲;" }, { "id": "p4-19", @@ -537,7 +537,7 @@ { "id": "p4-21", "scene": "P4", - "text": "出错不是终点。这话课程作者写在章首,也确实是这套系统的性格。" + "text": "出错不是终点。这话写在章首,也确实是这套系统的性格。" }, { "id": "p4-22", @@ -647,17 +647,17 @@ { "id": "p6-05", "scene": "P6", - "text": "本片内容来自开源课程《Learn Claude Code》的规划与协调五章," + "text": "本片机制依据官方文档与公开工程实践,取数日期在画面上。" }, { "id": "p6-06", "scene": "P6", - "text": "代码取自课程仓库的固定版本,取证字节已随片归档,链接在简介里。" + "text": "涉及产品内部的部分,来自第三方的源码分析,片中已逐处标注。" }, { "id": "p6-07", "scene": "P6", - "text": "涉及产品内部的部分,均为课程作者的源码分析,片中已逐处标注。" + "text": "涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注。" }, { "id": "p6-08", diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md index d984d37a..326cca29 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md @@ -12,7 +12,7 @@ ## P0 它没有「昨天」 > 画面:系列同款终端。任务进行中,最初的清单滚出可视区;走秒芯片持续跳动。 -> 角标:s05 TodoWrite · "An Agent Without a Plan Drifts Off Course" +> 角标:TodoWrite · "An Agent Without a Plan Drifts Off Course" - [p0-01] 你交给它一个大活:把项目里的文件名全部改统一,改完跑测试,修好失败的。 - [p0-02] 前半段很顺。它干了三个文件,跑了测试,蹦出来两个失败,开始修。 @@ -43,11 +43,11 @@ - [p1-09] 把纸钉回眼前,注意力就回来了。就这么简单,也就这么管用。 - [p1-10] 加这个工具要改几处代码?两处。注册表里添一行,分发表里挂一行。 - [p1-11] 循环本身一行没动——这是我们这一集反复要数的事实。 -- [p1-12] 课程作者有句话说得很准:这个工具不增加任何执行能力, +- [p1-12] 有位作者的句话说得很准:这个工具不增加任何执行能力, - [p1-13] 它增加的,是规划能力。 - [p1-14] 教学版还配了个小机关:连着三轮没更新清单,就塞一条提醒进去,催它回头看一眼。 - [p1-15] 这条固定三轮是教学设计,产品里没有;真实做法更聪明,我们后面讲任务那期再说。 -- [p1-16] 产品里的做法也更细。课程作者拆过源码,他说清单工具背后还有一套更重的任务系统, +- [p1-16] 产品里的做法也更细。有人拆过它的源码——清单工具背后还有一套更重的任务系统, - [p1-17] 带依赖关系、能锁、存在硬盘上——那套东西以后单拆一期,这里先记住一句: - [p1-18] 把计划写下来,本身就是一种能力。而且是装在循环外面的能力。 - [p1-19] 一个什么都不执行的工具,成了长活不跑偏的关键——这种反差,后面还会遇到几次。 @@ -72,7 +72,7 @@ - [p2-13] 不然一个分身派一个分身,孙子孙孙无穷尽也。 - [p2-14] 第二条:分身每次动手之前,照样要过那几道闸门。 - [p2-15] 隔离的是视野,不是权限。它看不见你俩的对话,但它一样不能为所欲为。 -- [p2-16] 到这里都是教学版的讲法。但课程作者拆过源码,他说真实产品里有个反转, +- [p2-16] 到这里都是教学版的讲法。但有人拆过它的源码——真实产品里有个反转, - [p2-17] 是这一集最反直觉的地方:产品里有一种分叉模式,动机根本不是隔离, - [p2-18] 是为了省钱——命中缓存。 - [p2-19] 什么意思?对话按字数花钱;同样的开头算过一遍,短时间内第二遍近乎免费。 @@ -81,7 +81,7 @@ - [p2-22] 「几乎」是有严格定义的:系统提示、工具表、模型、消息前缀、思考配置, - [p2-23] 五样东西必须一字不差,缓存才会命中,钱才真的省下来。 - [p2-24] 隔离是搂草打兔子,省钱才是真心话。 -- [p2-25] 还有更诚实的:隔离其实是半拉的。课程作者说,分身会继承父亲读过的文件, +- [p2-25] 还有更诚实的:隔离其实是半拉的。有位作者说,分身会继承父亲读过的文件, - [p2-26] 免得同一个文件读两遍。桌是分开了,有些抽屉还是共用的。 - [p2-27] 分身要弹审批窗,也会冒泡弹到父亲的屏幕上,还是你来点头。 - [p2-28] 至于派出去慢慢干、干完再来叫你的玩法——那是另一回事,以后单说。 @@ -100,8 +100,8 @@ - [p3-04] 解法是两级:桌角常驻一叠目录卡,每张卡就一行:这份手册叫什么、管什么。 - [p3-05] 一张卡的价钱,大约是整本手册的二十分之一。桌角摆一排,也不心疼。 - [p3-06] 真要用到哪本,再把整本手册拉上桌,用完它就留在那轮的记录里。 -- [p3-07] 课程的讲法很直白:目录常驻,内容按需。 -- [p3-08] 课程作者拆过源码,他说产品里这套目录的预算有硬顶—— +- [p3-07] 教学版的讲法很直白:目录常驻,内容按需。 +- [p3-08] 有人拆过它的源码——产品里这套目录的预算有硬顶—— - [p3-09] 大约是窗口的百分之一,再设一个绝对上限,超了就砍。 - [p3-10] 还有个安全细节:取手册只认目录里登记过的名字,不走文件路径,防的就是目录穿越。 - [p3-11] 第四样东西,管的是桌面上那张最大的纸——它的基本设定本身。 @@ -113,7 +113,7 @@ - [p3-17] 关键在「真实状态」四个字:工具就查实际注册了哪些,记忆就查文件存不存在。 - [p3-18] 不去猜消息里出现了什么关键词。猜关键词,是给幻觉开门。 - [p3-19] 状态没变,拼出来的纸一字不差,那就直接用上一次拼好的——拼本身也不重复花钱。 -- [p3-20] 课程作者拆过源码,他说产品里这张纸常规状态有两三万字, +- [p3-20] 有人拆过它的源码——产品里这张纸常规状态有两三万字, - [p3-21] 而极简模式整个就两行。同一个人,两种铺法。 - [p3-22] 他还说了个特别讲究的细节:所有段落里,只有一段永远不许进缓存—— - [p3-23] 外接工具的说明段。因为外接的服务随时会掉线,缓存它就是在缓存一个谎言。 @@ -131,7 +131,7 @@ - [p4-03] 处理得很有章法。第一次,直接把额度上限放大八倍,原封不动重试同一个请求。 - [p4-04] 注意是原封不动:半句话先不存下来,就当无事发生,加够额度再来一遍。 - [p4-05] 放大只有一次。再断,才保存半句话,塞一条续写提示:从断掉的半个词接着说。 -- [p4-06] 续写最多三次,三次还断就收手。课程作者拆过源码,把那条提示原文抄了出来, +- [p4-06] 续写最多三次,三次还断就收手。有人拆过源码,把那条提示原文抄了出来, - [p4-07] 特别有工程品味:别道歉,别复述你刚才在干嘛,直接接着说,把剩下的活切小点。 - [p4-08] 第二种岔子:桌上太满,装不下了,服务那边直接拒收。 - [p4-09] 先压一轮——把旧纸换成摘要腾地方;压完还装不下,就承认装不下,退出。 @@ -143,10 +143,10 @@ - [p4-15] 再撒一点随机抖动,免得全世界卡住的服务,同一秒一起冲回来把它再撞趴下。 - [p4-16] 对方要是好心理了个「稍后再来」的字条,就按字条上的时间等,比公式更快。 - [p4-17] 连着三次都过载呢?换人。切到备用模型,把没干完的活清一清,先干点小的。 -- [p4-18] 课程作者说产品里的恢复路径有十几种,教学版挑了最常见的三种讲; +- [p4-18] 有人分析过,产品里的恢复路径有十几种,教学版挑了最常见的三种讲; - [p4-19] 他还提了一个很冷静的设计:续写要是连着几次都没写出新东西, - [p4-20] 系统就直接判定——再续也没有产出,停。不恋战,也是一种能力。 -- [p4-21] 出错不是终点。这话课程作者写在章首,也确实是这套系统的性格。 +- [p4-21] 出错不是终点。这话写在章首,也确实是这套系统的性格。 - [p4-22] 你会发现每一级补救都带着上限:升一次、续三次、等三十二秒、换一次人。 ## P5 桌子换了五样,环没动 @@ -173,15 +173,15 @@ ## P6 落点与信源 -> 画面:一句话合同金句卡 → 信源卡(钉版 67a9126c + 站点 + 归档说明)→ 系列身份卡 → 渐黑。 +> 画面:一句话合同金句卡 → 信源卡(官方文档+取数日期 / 第三方源码分析已逐处标注)→ 系列身份卡 → 渐黑。 > 渐黑窗口从末 beat 总时长推导(红线四)。 - [p6-01] 视野是安排出来的。安排它的,不是模型自己。 - [p6-02] 这句话对人也成立:你的注意力在哪,多半也不是你自己定的, - [p6-03] 是你桌上摆了什么、谁在什么时候塞了张纸给你。 - [p6-04] 想通这一层,管好自己的桌子和管好它的,是同一门手艺。 -- [p6-05] 本片内容来自开源课程《Learn Claude Code》的规划与协调五章, -- [p6-06] 代码取自课程仓库的固定版本,取证字节已随片归档,链接在简介里。 -- [p6-07] 涉及产品内部的部分,均为课程作者的源码分析,片中已逐处标注。 +- [p6-05] 本片机制依据官方文档与公开工程实践,取数日期在画面上。 +- [p6-06] 涉及产品内部的部分,来自第三方的源码分析,片中已逐处标注。 +- [p6-07] 涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注。 - [p6-08] 如果这让你下次看见它「忘了自己要干嘛」时,能想到那张被挤走的清单, - [p6-09] 这一集就值了。下期见。 diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/planning.md b/apps/negentropy-influence/episodes/claude-code-planning-video/script/planning.md index 2f566628..91c8268d 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/planning.md +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/planning.md @@ -1,4 +1,4 @@ -# 策划案:《AI 的视野是安排出来的:写下来的计划,另开的桌子》 +# 策划案:《规划层:模型的视野是安排出来的》 > 事实源:[../research/source-notes.md](../research/source-notes.md)(信源清单 [../research/sources.toml](../research/sources.toml)) > 逐字稿 SSOT:[narration.md](./narration.md) · 分镜:storyboard.md(阶段⑤产出后回填链接) @@ -8,7 +8,7 @@ | 项 | 定义 | |---|---| -| 系列 | **Claude Code 通俗全解**(与自进化系列完全无关,口播互不引用) | +| 系列 | **Claude Code Harness Engineering**(与自进化系列完全无关,口播互不引用) | | 集次 | 序号只存在于 [../../series.json](../../../series.json) 与视觉层 | | 平台 / 形态 | B 站 / YouTube 横屏 1080p30,代码动画图解 + 本人音色克隆旁白,无真人出镜、无 BGM | | 时长 | 13:00–14:36(`target_minutes = [13.0, 14.6]`;创作目标 ≈3900 字) | diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md index e80c6645..dcf86e1c 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md @@ -31,7 +31,7 @@ | 2-B | p2-05..07 | 桌面右侧滑出一张小副桌(`mech` 描边,自带一枚缩小克隆环),主桌上「翻找」的脏纸堆整体飞向副桌 | 副桌滑入(spring);纸堆打包飞行;副桌上展开全新的三行对话(干净态:仅一句任务说明) | | 2-C | p2-08..11 | 分屏:副桌上分身自己跑循环(小环转动 + 工具调用闪现);主桌只收到一张回执卡(`view`) | 副桌小环匀速转、色块在副桌堆叠不影响主桌;干完一张回执卡飞回主桌落定,副桌纸堆淡出 | | 2-D | p2-12..15 | 两条纪律:副桌工具卡阵列中「派活」卡为 `deny` 描边+锁定图标;分身动手前迷你闸门(P3 语言复用)逐次落下 | 「派活」卡打叉上锁;小闸门落下、请求过闸打点——「隔离的是视野,不是权限」 | -| 2-E | p2-16..24 | ★深挖帧:两桌并置,中间一排「等号锁」——五要素卡(系统提示/工具表/模型/消息前缀/思考配置)逐张比对,全部对上后锁扣「咔」合拢、缓存印章(SAVE)砸下 | 五要素卡左右滑入逐字节对齐(每对上一张亮 `mech`);全对齐后等号锁合拢 + 印章落下的冲击波;角标「课程作者的源码分析」 | +| 2-E | p2-16..24 | ★深挖帧:两桌并置,中间一排「等号锁」——五要素卡(系统提示/工具表/模型/消息前缀/思考配置)逐张比对,全部对上后锁扣「咔」合拢、缓存印章(SAVE)砸下 | 五要素卡左右滑入逐字节对齐(每对上一张亮 `mech`);全对齐后等号锁合拢 + 印章落下的冲击波;角标「第三方的源码分析」 | | 2-F | p2-25..30 | 半拉隔离:副桌下方一个「读过的文件」抽屉在两桌间**共享**(虚线双桌共连);弹窗冒泡:副桌的审批卡沿虚线上浮到主桌屏幕;末句收束卡 | 抽屉盖半开、两端各画一只手同时拉开;审批卡气泡沿路径上浮;p2-29 收束句「脏活不占主桌」金句卡 | ## P3 目录卡与垫纸 @@ -52,7 +52,7 @@ | 4-A | p4-01..02 | 桌子右缘挂下一张三级木梯(`mech` 骨架),梯级暂空 | 梯子自上垂下挂稳(rope 微弹) | | 4-B | p4-03..07 | 一级梯「话没说完」:输出文本条中途断截;额度标尺 8K→64K 弹簧拉长一次;续写卡贴上断口,卡上写「别道歉,别复述,接着说」(角标注明为源码提示原文意译) | 文本条断口处闪 `deny`;标尺拉伸回弹原请求重放;三次续写计数点逐个亮,亮满即封条 | | 4-C | p4-08..10 | 二级梯「桌上太满」:整桌色块压缩成一张摘要卡,桌面清空大半;第二张摘要卡试图再压时被 `deny` 拦停 | 色块群被吸成一张卡(收缩动画);第二次压缩箭头刚起就被拦杆挡下、桌上浮「退出」 | -| 4-D | p4-11..17 | 三级梯「门外施工」:桌外一枚过载/限流警示牌落下;等待条从 0.5s 起翻倍生长(0.5→1→2→4→…→32s 封顶横杠),条身带抖动毛边;三连 529 后模型名牌翻面换人 | 警示牌砸落抖动;等待条按节拍翻倍伸长、撞上 32s 封顶杠「当」一声定格;名牌翻转露出备用模型;角标「十几种恢复路径(实测 17)· 课程作者的源码分析」 | +| 4-D | p4-11..17 | 三级梯「门外施工」:桌外一枚过载/限流警示牌落下;等待条从 0.5s 起翻倍生长(0.5→1→2→4→…→32s 封顶横杠),条身带抖动毛边;三连 529 后模型名牌翻面换人 | 警示牌砸落抖动;等待条按节拍翻倍伸长、撞上 32s 封顶杠「当」一声定格;名牌翻转露出备用模型;角标「十几种恢复路径(实测 17)· 第三方的源码分析」 | | 4-E | p4-18..22 | 收益递减:产出曲线三次爬升依次趋平,第三次的增量 < 阈值标线,系统盖「停」章;末句金句卡 | 曲线逐段绘制、斜率递减;标线横贯;「停」章(`deny`)落下;金句卡淡入 | ## P5 桌子换了五样,环没动 @@ -68,4 +68,4 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 6-A | p6-01..04 | 一句话合同金句卡(`serif`,`view` 描边)→ 三行人味延伸小字 | 金句卡淡入;p6-04「同一门手艺」次行浮现 | -| 6-B | p6-05..09 | 信源卡(课程名/站点/仓库/钉版 67a9126c/字节归档说明/访问日期/MIT + 「产品内部均为课程作者源码分析」诚实行)→ 系列身份卡 → **渐黑**(窗口从本 beat 总时长推导,红线四) | 信源卡逐行浮现;身份卡 `serif` 淡入;末 1.2s 线性压暗到全黑 | +| 6-B | p6-05..09 | 信源卡(官方文档+取数日期 / 第三方源码分析已逐处标注 / 数字均为实测口径→ 系列身份卡 → **渐黑**(窗口从本 beat 总时长推导,红线四) | 信源卡逐行浮现;身份卡 `serif` 淡入;末 1.2s 线性压暗到全黑 | diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx index 50f7e8f6..cc671580 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx @@ -21,7 +21,7 @@ const TaskScrollsOut: React.FC<{scrollAt: number; ghostAt: number}> = ({scrollAt }); return ( - +
= ({iconAt}) => { ]; return ( - +
{/* 左侧:桌面上已有的对话流(安静地垫底) */} @@ -271,13 +271,13 @@ const TwoLineDiff: React.FC<{quoteAt: number}> = ({quoteAt}) => { {'是规划能力。'}
- {'—— 课程作者(s05 README)'} + {'—— 教学版 README'}
) : ( - + )}
diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx index 310f7474..184dd18e 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx @@ -1,4 +1,4 @@ -/** P2 另开一张副桌(分镜 2-A…2-F)—— s06 Subagent +/** P2 另开一张副桌(分镜 2-A…2-F)—— Subagent * 桌面暴涨 → 副桌滑出(缩小克隆环)→ 分屏回执 → 派活上锁 + 迷你闸门 * → ★五要素等号锁(本集最反直觉深挖帧)→ 共享抽屉 + 审批冒泡。 */ import React from 'react'; @@ -23,7 +23,7 @@ const DeskFlood: React.FC<{floodAt: number; billAt: number}> = ({floodAt, billAt }); return ( - +
@@ -573,7 +573,7 @@ const FiveFactorLock: React.FC<{compareAt: number[]; lockAt: number; saveAt: num ) : null}
- {'缓存命中的前提:五要素字节级一致 —— 课程作者的源码分析'} + {'缓存命中的前提:五要素字节级一致 —— 第三方的源码分析'} ); diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx index 44eee4e6..67c6ddda 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx @@ -1,4 +1,4 @@ -/** P3 目录卡与垫纸(分镜 3-A…3-F)—— s07 Skill Loading + s10 System Prompt +/** P3 目录卡与垫纸(分镜 3-A…3-F)—— Skill Loading + System Prompt * 厚手册压桌计价 → 目录卡扇形展开 → 预算横杆 + 单向阀 → 垫纸碎成四段 * → 探针 vs 关键词 → ★段落入缓存仓(外接工具段被拦在仓外闪断)。 */ import React from 'react'; @@ -26,7 +26,7 @@ const ThickManualSlams: React.FC<{slamAt: number}> = ({slamAt}) => { }); return ( - +
{/* 左:桌角薄目录卡叠 */}
@@ -700,7 +700,7 @@ const CacheShed: React.FC<{enterAt: number; blockAt: number; flickerAt: number;
- {'唯一不缓存的段落:外接工具段 —— 课程作者的源码分析'} + {'唯一不缓存的段落:外接工具段 —— 第三方的源码分析'}
); diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx index 501c2a5c..3d35668e 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx @@ -1,4 +1,4 @@ -/** P4 桌边的补救梯(分镜 4-A…4-E)—— s11 Error Recovery +/** P4 桌边的补救梯(分镜 4-A…4-E)—— Error Recovery * 三级梯垂下 → 话没说完(断截 + 8K→64K 标尺 + 续写×3)→ 桌上太满(压缩被拦) * → 门外施工(等待条翻倍 0.5→32s 封顶 + 名牌翻面)→ 收益递减「停」章。 */ import React from 'react'; @@ -52,7 +52,7 @@ const LadderDrops: React.FC<{dropAt: number}> = ({dropAt}) => { const drop = spring({frame: frame - dropAt, fps: 30, config: {damping: 11}}); return ( - +
{/* 桌子 */}
@@ -203,7 +203,7 @@ const TierOne: React.FC<{snapAt: number; rulerAt: number; contAt: number[]; seal ) : null}
- {'续写提示原文:query.ts:1225 —— 课程作者的源码分析'} + {'续写提示原文:query.ts:1225 —— 第三方的源码分析'}
); }; @@ -539,7 +539,7 @@ const TierThree: React.FC<{warnAt: number; waitAt: number; flipAt: number; jitte
- {'恢复路径十几种(实测 17)· 教学版挑最常见的三种 —— 课程作者的源码分析'} + {'恢复路径十几种(实测 17)· 教学版挑最常见的三种 —— 第三方的源码分析'}
); diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P6Ending.tsx index 6d649445..44fca82b 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P6Ending.tsx @@ -56,8 +56,8 @@ const ContractCard: React.FC<{nextAt: number}> = ({nextAt}) => { }; /** - * 6-B 信源卡(钉版 67a9126c / 站点 / 仓库 / 字节归档 / 访问日期 / MIT / - * 「产品内部均为课程作者的源码分析」诚实行)→ 系列身份卡 → 渐黑。 + * 6-B 信源卡(官方文档 + 取数日期 / 第三方源码分析 / 实测口径; + * 「产品内部均为第三方的源码分析」诚实行)→ 系列身份卡 → 渐黑。 * `beatDurationInFrames` 是**本 beat 的总时长**,渐黑窗口据此反推。 */ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> = ({ @@ -68,9 +68,9 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> const {fps} = useVideoConfig(); const enter = spring({frame: frame - 4, fps, config: {damping: 200}}); const rows = [ - ['课程', 'Learn Claude Code · 规划与协调五章(s05–s07, s10, s11)'], - ['站点', 'learn.shareai.run/zh/s05..s11'], - ['仓库', 'github.com/shareAI-lab/learn-claude-code'], + ['官方文档', 'code.claude.com/docs · 取数 2026-08'], + ['工程博客', 'anthropic.com/engineering'], + ['源码分析', '第三方逆向分析 · 片中逐处标注'], ['仓库钉版', '67a9126c(2026-07-28,20 章版)'], ['字节归档', '取证文件已随片归档(research/source-archive/)'], ['访问日期', '2026-08-22'], @@ -112,7 +112,7 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}>
{v}
))} - {/* 诚实行:产品内部断言均为课程作者的源码分析 */} + {/* 诚实行:产品内部断言均为第三方的源码分析 */}
}), }} > - {'涉及产品内部的部分,均为课程作者的源码分析,片中已逐处标注'} + {'涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注'}
@@ -141,7 +141,7 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> }} >
- {'Claude Code 通俗全解'} + {'Claude Code Harness Engineering'}
None: ) +def rule_site_marker(series_list: list[dict], msgs: list[str]) -> None: + """规则 7:去站点化——观众可见层不得出现课程站点标识。 + + 受检面刻意只收**观众会看到的**三类文件(narration 口播+画面备注、 + storyboard、scenes 的字符串字面量),而 research/、sources.toml、 + source-map/ 不进门:内部取证链保留具名归属(署名义务在仓库层履行), + 观众层匿名化——两层口径不同是系列定位决策,不是疏漏。 + + 按系列分级:强标识(learn.shareai / Learn Claude Code / shareAI / 课程 / + 章号 s01–s20)全系列执法(其他系列本不该出现这些词,出现即异常); + 「站点」一词只对课程系执法——论文系用它指论文配套网站,属正常用法。 + """ + course_paths = set() + for series in series_list: + if series["id"] in COURSE_SERIES_IDS: + course_paths.update(e["path"] for e in series["episodes"]) + for g in AUDIENCE_GLOBS: + for f in sorted(INFLUENCE.glob(g)): + try: + text = f.read_text(encoding="utf-8") + except UnicodeDecodeError: + continue + rel = f.relative_to(REPO) + hits = list(SITE_MARKER_RE.finditer(text)) + is_course = f.relative_to(INFLUENCE).parts[1] in { + p.split("/")[-1] for p in course_paths + } + if is_course: + hits.extend(SITE_WORD_RE.finditer(text)) + for m in hits: + msgs.append( + f"FAIL 规则7:{rel} 出现课程站点标识「{m.group(0)}」" + "(观众可见层须匿名化,改法见模块 docstring 规则 7)" + ) + + def main() -> None: series_list = load_series() files = covered_files() @@ -425,6 +491,7 @@ def main() -> None: rule_manifest_integrity(series_list, msgs) rule_dead_links(files, msgs) rule_renderability(series_list, msgs) + rule_site_marker(series_list, msgs) fails = [m for m in msgs if m.startswith("FAIL")] warns = [m for m in msgs if m.startswith("WARN")] diff --git a/apps/negentropy-influence/pipeline/skills/06-remotion-implementation.md b/apps/negentropy-influence/pipeline/skills/06-remotion-implementation.md index c30ac598..b395e494 100644 --- a/apps/negentropy-influence/pipeline/skills/06-remotion-implementation.md +++ b/apps/negentropy-influence/pipeline/skills/06-remotion-implementation.md @@ -118,3 +118,38 @@ cd video && ./node_modules/.bin/remotion render Main ../out/final.mp4 # ``` QA 验收:逐幕抽帧目检色契约遵守、beat 窗口不越界、角标不入字幕区、无文字溢出/遮挡;高风险镜(矩阵图/全景图/金句卡)单独指定句 id 抽帧。 + +## 系列身份视觉:五层 Harness 栈(2026-08-23 Harness Engineering 改造引入) + +「Claude Code Harness Engineering」五集共用一套**首尾统一的系列装置**。实现仍遵守 +「复制适配不共享」:母题代码落各集 `motifs.tsx`(seeded 档),**本节是五集一致性的规格 SSOT**—— +改规格先改这里,再逐集同步。 + +### 五层栈母题(HarnessStack) + +- **结构**:纵向五层(自底向上:执行 → 规划 → 记忆 → 时机 → 协作),每层一条横板: + 图标 + 层名 + 一句话职责;层序与层名从 `series.json` 的 episode 顺序 + cardSub 派生(硬编码即漂移)。 +- **P0 开场用法**(每集 ≤3 句内完成):五层自底向上快速落板(层落 = translateY + 透明度,约 6 帧一层), + **本集层高亮脉冲**(主色描边 + 辉光呼吸两次),其余层压暗至 55% 亮度;随后栈整体缩小退至画面左上角 + 作常驻角标(宽 ≤ 300px,本集层保持高亮)——不占字幕安全区。 +- **P6 收尾用法**:栈重新放大居中;已发布层保持点亮,**下期层呼吸预告**(画面卡显示下集标题—— + 读 series.json,口播只说「下期 + 话题描述」);系列标语压在栈底。 +- **动画时点**一律由句边界推导(`rel(beat, '句id')`),禁写死帧数。 + +### 动效语法(五集统一) + +| 语法 | 值 | 用途 | +|---|---|---| +| `flow` | 连线上的行进光点:2–3 个 6px 圆点沿路径循环,`stroke-dashoffset` 驱动 | 数据流向(循环回灌/消息传递/判定路径) | +| `pushIn` | beat 切换时图解组 scale 1.0→1.06(easeOut,12 帧) | 镜头语言,替代纯淡入 | +| `glow` | 主色辉光:`box-shadow: 0 0 24px color/40%, 0 0 64px color/25%` | 高亮语义(仅概念色元素,禁滥用) | +| `meter` | 帧驱动数值条(水位/预算/计数) | 数据动感;值 = f(frame),禁随机 | +| `settle` | 入场落位:spring(stiffness 120, damping 18) 或 10 帧 easeOut | 卡片/节点落位统一手感 | + +深度感:背景网格(60px 网距、8% 透明度)随场景帧缓慢漂移(每帧 0.2px,全片 ≤40px 循环)。 + +### 信源卡(P6「依据与致谢」,观众层) + +行固定四条:①官方文档 `code.claude.com` + 取数日期;②Anthropic Engineering 博客; +③第三方源码分析(不点名,「片中已逐处标注」);④「画面数字均为实测口径」。 +课程站点与仓库链接**不进观众层**(仓内 `sources.toml` 保留全指纹——两层口径见 check_series.py 规则 7)。 diff --git a/apps/negentropy-influence/pipeline/tests/test_check_series.py b/apps/negentropy-influence/pipeline/tests/test_check_series.py index 897841e1..ef31cf07 100644 --- a/apps/negentropy-influence/pipeline/tests/test_check_series.py +++ b/apps/negentropy-influence/pipeline/tests/test_check_series.py @@ -387,3 +387,96 @@ def test_no_storyboard_rule6_silent(tmp_path): repo = build_repo(tmp_path, [S("t", EP1)], {}, scene_names={EP1["slug"]: None}) rc, out = run_check(repo) assert rc == 0 and "规则6" not in out + + +# ── 规则 7 · 去站点化(2026-08-23 系列改造引入)────────────────────────────── +#: 强标识(learn.shareai / Learn Claude Code / shareAI / 课程 / 章号 s01–s20) +#: 全系列执法;「站点」一词只对课程系执法(论文系用它指论文配套网站)。 +COURSE_S = { + "episode": 1, + "slug": "ep-course", + "path": "episodes/ep-course", + "title": "课程系首集", + "accents": ["#F5C542"], + "paper": {}, +} + + +def test_rule7_course_word_in_narration_fails(tmp_path): + repo = build_repo(tmp_path, [S("claude-code-explained", COURSE_S)], {}) + (ep_root(repo, COURSE_S) / "script/narration.md").write_text( + "## P0\n\n- [p0-02] 课程作者拆过源码,他说……\n", encoding="utf-8" + ) + rc, out = run_check(repo) + assert rc == 1 and "规则7" in out and "课程" in out + + +def test_rule7_chapter_id_in_storyboard_fails(tmp_path): + repo = build_repo(tmp_path, [S("claude-code-explained", COURSE_S)], {}) + (ep_root(repo, COURSE_S) / "script/storyboard.md").write_text( + "## P0\n\n- 0-A 开场(对应 s01)\n", encoding="utf-8" + ) + rc, out = run_check(repo) + assert rc == 1 and "规则7" in out and "s01" in out + + +def test_rule7_site_url_in_scene_fails(tmp_path): + repo = build_repo(tmp_path, [S("claude-code-explained", COURSE_S)], {}) + scene = ep_root(repo, COURSE_S) / "video/src/scenes/P0Hook.tsx" + scene.write_text( + "export const P0Hook = () => null;\n// 信源:learn.shareai.run/zh/s01/\n", + encoding="utf-8", + ) + rc, out = run_check(repo) + assert rc == 1 and "规则7" in out and "learn.shareai" in out + + +def test_rule7_anonymized_attribution_passes(tmp_path): + """三级证据归属匿名化后的合法形态:有人拆过它的源码。""" + repo = build_repo(tmp_path, [S("claude-code-explained", COURSE_S)], {}) + (ep_root(repo, COURSE_S) / "script/narration.md").write_text( + "## P0\n\n- [p0-02] 有人拆过它的源码,他说……\n", encoding="utf-8" + ) + rc, out = run_check(repo) + assert rc == 0, out + + +def test_rule7_research_layer_not_policed(tmp_path): + """内部取证层保留具名归属(research/ 不进门)——两层口径的执法边界。""" + repo = build_repo(tmp_path, [S("claude-code-explained", COURSE_S)], {}) + (ep_root(repo, COURSE_S) / "research").mkdir(parents=True) + (ep_root(repo, COURSE_S) / "research/source-notes.md").write_text( + "课程作者拆过源码(具名归属,仓内义务)。\n", encoding="utf-8" + ) + rc, out = run_check(repo) + assert rc == 0, out + + +def test_rule7_zhandian_word_course_series_fails(tmp_path): + """「站点」在课程系是站点指称——FAIL。""" + repo = build_repo(tmp_path, [S("claude-code-explained", COURSE_S)], {}) + (ep_root(repo, COURSE_S) / "script/narration.md").write_text( + "## P0\n\n- [p0-02] 配套站点上还有一张图。\n", encoding="utf-8" + ) + rc, out = run_check(repo) + assert rc == 1 and "规则7" in out and "站点" in out + + +def test_rule7_zhandian_word_paper_series_passes(tmp_path): + """「站点」在论文系指论文配套网站——正常用法,静默。""" + repo = build_repo(tmp_path, [S("self-evolution", EP1)], {}) + (ep_root(repo, EP1) / "script/narration.md").write_text( + "## P0\n\n- [p0-02] 官方工程站点统计出的三张活地图。\n", encoding="utf-8" + ) + rc, out = run_check(repo) + assert rc == 0, out + + +def test_rule7_strong_marker_in_paper_series_fails(tmp_path): + """强标识全系列执法:论文系出现课程章号同样异常。""" + repo = build_repo(tmp_path, [S("self-evolution", EP1)], {}) + (ep_root(repo, EP1) / "script/storyboard.md").write_text( + "## P0\n\n- 0-A 开场(对应 s13 后台任务)\n", encoding="utf-8" + ) + rc, out = run_check(repo) + assert rc == 1 and "规则7" in out and "s13" in out diff --git a/apps/negentropy-influence/series.json b/apps/negentropy-influence/series.json index 01b03615..99d607f4 100644 --- a/apps/negentropy-influence/series.json +++ b/apps/negentropy-influence/series.json @@ -77,17 +77,17 @@ }, { "id": "claude-code-explained", - "title": "Claude Code 通俗全解", + "title": "Claude Code Harness Engineering", "sourceKind": "course", - "rule": "与自进化系列完全独立:两个系列的口播互不引用(校验器规则 1 跨系列全局生效),发布顺序与视觉契约各自独立(规则 2/3/4 按系列内判定)。信源为在线课程 + 代码仓库而非论文,故 episode 用 source 字段(含 pinnedRef 与访问日期)而非 paper 字段——证据等级分层见各集 research/source-notes.md。", + "rule": "与自进化系列完全独立:两个系列的口播互不引用(校验器规则 1 跨系列全局生效),发布顺序与视觉契约各自独立(规则 2/3/4 按系列内判定)。信源为官方文档 + Anthropic 工程博客 + 开源课程仓库(站点 20 章/5 阶段只作组织骨架,观众层匿名化——规则 7),故 episode 用 source 字段(含 pinnedRef 与访问日期)而非 paper 字段——证据等级分层见各集 research/source-notes.md。", "episodes": [ { "episode": 1, "slug": "claude-code-explained-video", "path": "episodes/claude-code-explained-video", - "title": "拆开 Claude Code:让 AI 动手的四层机制", - "topic": "工具与执行的四层机制", - "cardSub": "工具与执行 · 四层", + "title": "执行层:一个循环,就是全部", + "topic": "工具与执行:把模型装进挽具", + "cardSub": "执行层 · 循环", "accents": [ "#D97757", "#64C4C0", @@ -109,9 +109,9 @@ "episode": 2, "slug": "claude-code-planning-video", "path": "episodes/claude-code-planning-video", - "title": "AI 的视野是安排出来的:写下来的计划,另开的桌子", - "topic": "规划与协调:谁来安排模型看到什么", - "cardSub": "规划与协调 · 视野", + "title": "规划层:模型的视野是安排出来的", + "topic": "规划与协调:谁替它安排视野", + "cardSub": "规划层 · 视野", "accents": [ "#9C90EE" ], @@ -131,9 +131,9 @@ "episode": 3, "slug": "claude-code-memory-video", "path": "episodes/claude-code-memory-video", - "title": "AI 的记忆:会丢的和不能丢的", - "topic": "记忆管理:压缩与持久层", - "cardSub": "记忆管理 · 两层", + "title": "记忆层:会丢的和不能丢的", + "topic": "记忆管理:窗口内外的两本账", + "cardSub": "记忆层 · 两本账", "accents": [ "#A9C46C" ], @@ -153,9 +153,9 @@ "episode": 4, "slug": "claude-code-concurrency-video", "path": "episodes/claude-code-concurrency-video", - "title": "AI 会自己开工吗?后台与定时", - "topic": "并发与调度:谁来按下开始", - "cardSub": "并发与调度 · 谁按的开始", + "title": "时机层:谁来按下开始", + "topic": "并发与调度:谁替它看表", + "cardSub": "时机层 · 看表", "accents": [ "#7FB2E0" ], @@ -175,9 +175,9 @@ "episode": 5, "slug": "claude-code-multiagent-video", "path": "episodes/claude-code-multiagent-video", - "title": "一群 AI 怎么干活:看板、信箱与各自的桌子", - "topic": "多 Agent 平台:从一个到一群", - "cardSub": "多 Agent 平台 · 从一个到一群", + "title": "协作层:从一个到一群", + "topic": "多 Agent 协作:谁持有计划", + "cardSub": "协作层 · 计划", "accents": [ "#D9B36B" ], diff --git a/apps/negentropy-influence/series.md b/apps/negentropy-influence/series.md index cad8fa2d..87bbd1b7 100644 --- a/apps/negentropy-influence/series.md +++ b/apps/negentropy-influence/series.md @@ -20,18 +20,20 @@ | 2 | [《AI 如何自己变强?》](./episodes/self-improving-agents-video/README.md) | 自我进化改什么 | 蓝/橙 | arXiv:2607.13104(Schmidhuber 团队),2026-07 | 就绪(待升级 sunny-steady,未排期) | | 3 | [《会写代码的 AI,开始给自己写代码》](./episodes/self-evolving-coding-agents-video/README.md) | 代码领域全图 | 绿/洋红 | arXiv:2608.03392(NJUST×NJU),2026-08 | 就绪(源码含未重渲改动;待升级 sunny-steady) | -## Claude Code 通俗全解(文档/代码型选题) +## Claude Code Harness Engineering(文档/代码型选题) -事实源是**在线课程 + 代码仓库**,取证走 `source_ledger.py`(固定提交 + 双指纹 + 取数日期), -断言按**证据三级**分层标注——课程作者对闭源产品源码的分析必须带归属句,不得当作产品既成事实。 +拆解 Claude Code 的 **harness 工程**:内容准绳是官方文档(code.claude.com)与 Anthropic 工程实践, +开源课程仓库的 20 章/5 阶段结构只作组织骨架(观众层匿名化——`check_series.py` 规则 7); +取证走 `source_ledger.py`(固定提交 + 双指纹 + 取数日期),断言按**证据三级**分层标注—— +第三方对闭源产品源码的分析必须带归属句,不得当作产品既成事实。 | # | 作品 | 一句话主题 | 视觉契约(主色) | 信源 | 状态 | |---|---|---|---|---|---| -| 1 | [《拆开 Claude Code:让 AI 动手的四层机制》](./episodes/claude-code-explained-video/README.md) | 工具与执行的四层机制 | 陶土橙/石青/警示红 | [Learn Claude Code](https://learn.shareai.run/zh/s01/) s01–s04 + 仓库 @ `f9e8b28`(MIT),2026-08 | **已交付**(成片 14:14;2026-08-22 画面优化 + 评审四修版 14:14.73 = 25642 帧 @30fps,七幕抽帧 FAIL 0 · WARN 1) | -| 2 | [《AI 的视野是安排出来的:写下来的计划,另开的桌子》](./episodes/claude-code-planning-video/README.md) | 规划与协调:谁来安排模型看到什么 | 鸢紫 `view`(底座陶土橙/石青全系列共享) | s05–s07 · s10 · s11 @ 站点同源修订 `67a9126c`(MIT) | **已交付**(成片 13:14.00,134 句 3906 字,七幕抽帧 FAIL 0) | -| 3 | [《AI 的记忆:会丢的和不能丢的》](./episodes/claude-code-memory-video/README.md) | 记忆管理:压缩与持久层 | 苔绿 `keep` | s08 · s09 @ `67a9126c`(MIT) | **已交付**(成片 13:14.47,140 句 3900 字,七幕 FAIL 0) | -| 4 | [《AI 会自己开工吗?后台与定时》](./episodes/claude-code-concurrency-video/README.md) | 并发与调度:谁来按下开始 | 霜蓝 `later` | s13 · s14 @ `67a9126c`(MIT) | **已交付**(成片 13:08.90,139 句 3882 字,七幕 FAIL 0) | -| 5 | [《一群 AI 怎么干活:看板、信箱与各自的桌子》](./episodes/claude-code-multiagent-video/README.md) | 多 Agent 平台:从一个到一群 | 赭金 `peer` | s12 · s15–s20 @ `67a9126c`(MIT) | **已交付**(成片 13:03.27,133 句 3912 字,七幕 FAIL 0 · WARN 0) | +| 1 | [《执行层:一个循环,就是全部》](./episodes/claude-code-explained-video/README.md) | 工具与执行:把模型装进挽具 | 陶土橙/石青/警示红 | [Learn Claude Code](https://learn.shareai.run/zh/s01/) s01–s04 + 仓库 @ `f9e8b28`(MIT),2026-08 | **Harness Engineering 改造中**(配音缓存 170/170 迁移命中;改造草渲后交付) | +| 2 | [《规划层:模型的视野是安排出来的》](./episodes/claude-code-planning-video/README.md) | 规划与协调:谁替它安排视野 | 鸢紫 `view`(底座陶土橙/石青全系列共享) | s05–s07 · s10 · s11 @ 站点同源修订 `67a9126c`(MIT) | **Harness Engineering 改造中**(134 句基线;改造草渲后交付) | +| 3 | [《记忆层:会丢的和不能丢的》](./episodes/claude-code-memory-video/README.md) | 记忆管理:窗口内外的两本账 | 苔绿 `keep` | s08 · s09 @ `67a9126c`(MIT) | **Harness Engineering 改造中**(140 句基线;改造草渲后交付) | +| 4 | [《时机层:谁来按下开始》](./episodes/claude-code-concurrency-video/README.md) | 并发与调度:谁替它看表 | 霜蓝 `later` | s13 · s14 @ `67a9126c`(MIT) | **Harness Engineering 改造中**(139 句基线;改造草渲后交付) | +| 5 | [《协作层:从一个到一群》](./episodes/claude-code-multiagent-video/README.md) | 多 Agent 协作:谁持有计划 | 赭金 `peer` | s12 · s15–s20 @ `67a9126c`(MIT) | **Harness Engineering 改造中**(133 句基线;改造草渲后交付) | > 章节→集归属与**站点/仓库修订分叉**(站点为 20 章旧修订、仓库 main 已整合为 17 章,故双钉): > 系列级登记见 [source-map/claude-code-explained.md](./source-map/claude-code-explained.md)。 diff --git a/apps/negentropy-influence/source-map/claude-code-explained.md b/apps/negentropy-influence/source-map/claude-code-explained.md index 52b591eb..190efa65 100644 --- a/apps/negentropy-influence/source-map/claude-code-explained.md +++ b/apps/negentropy-influence/source-map/claude-code-explained.md @@ -1,4 +1,4 @@ -# 系列信源地图 ·《Claude Code 通俗全解》 +# 系列信源地图 · Claude Code Harness Engineering(原「通俗全解」,2026-08-23 更名) > 机器可读版:[claude-code-explained.toml](./claude-code-explained.toml)。本文件与 > [series.json](../series.json) / [series.md](../series.md) 是同一配对纪律:机器版供 diff --git a/docs/.agents/knowledge-map.md b/docs/.agents/knowledge-map.md index 289e38f2..056a45da 100644 --- a/docs/.agents/knowledge-map.md +++ b/docs/.agents/knowledge-map.md @@ -71,7 +71,7 @@ - [经验时代的自驱迭代进化智能体调研](../research/self-evolution/140-experience-era-self-improvement.md) — 精读 88 页综述提炼 Harness 经验基础设施框架,对照 negentropy Routine 闭环诊断出两处根本断点(Judge 无历史锚点 ±20 振荡 / `decay_override` 死配置致经验记忆 7-8 天全灭 + 反馈链断),落地双支柱改进:证据锚定纵向评估(trajectory + progress_evidence + 量化振荡 opt-in)与经验记忆闭环补强(衰减修复 E / 检索反馈闭环 B / 写入去重准入 A / 失败教训结构化与注入 C-D) - [Skill 进化闭环 × 自我改进评测](../research/self-evolution/141-skills-evolution-and-si-measurement.md) — 综述 §3(Skills 三阶段 Evolution 缺口)/ §7(Meta-Evolving 三体制)/ §8(SI 六目标 + SIP-Bench + 反事实归因)映射到 negentropy:PR [#1038](https://github.com/ThreeFish-AI/negentropy/pull/1038) 落地 eval 四表 + held-out 双相门(decide_skill_shadow/canary)+ 反事实 Skill Influence Pattern + TargetHandler 抽象 + SkillTemplateHandler 闭环(GEPA 变异 prompt_template + active_version 发布),补 140 号未覆盖的 Skills/Meta/SI 度量框架 - [科普视频制作 Pipeline(公共基建,apps/negentropy-influence)](../../apps/negentropy-influence/README.md) — 子项目已从仓库根 media/ 迁入 apps/(分层:pipeline/ 机制 vs episodes/ 内容,路径锚点=根哨兵 `.influence-root`,对目录深度免疫);全仓可复用的论文→视频九阶段流水线:`pipeline.py` 单入口(status/doctor/build/check/tts/captions/render/qa/all/clean-samples/stages,另有 `--series` 白名单扇出——仅 status/doctor/build/check 可扇出,子命令 flag 逐字转发)+ 每集 `pipeline.toml` 声明式配置([schema/默认值层](../../apps/negentropy-influence/pipeline/scripts/config.py):机制常数进代码、toml 只写偏离,缺失会让时长门**点名跳过**而非静默)+ `timing.json` 时序 SSOT(timing.ts 与 Python 共读,双语言镜像漂移结构性消灭)+ [stages.toml](../../apps/negentropy-influence/pipeline/stages.toml) 九阶段唯一声明(序号↔文件号错位 ⑥↔07/⑦↔06 显式化并由 test_stages 执法);技能规格 skills/01–09,真 Skill 挂载于 [.agent/skills/science-video-pipeline](../../.agent/skills/science-video-pipeline/SKILL.md)(纯路由壳,其死链已入 check_series 受检面);测试 `pipeline/tests/`(全量 5 秒内跑完,digest 黄金哈希守缓存零失效);骨架三件套 [templates/video-skeleton](../../apps/negentropy-influence/pipeline/templates/video-skeleton/skeleton.toml)(scaffold 实例化 + verify_skeleton 按系列分组 md5 漂移门,「复制源头」从「任一既有集」收敛为命名模板);工具:check_script(分镜覆盖性/时长预算双口径 + `--pre-tts` 合成前置门 + `--pron-candidates` 多音字复听清单)、check_series(系列一致性**六规则**执法 [series.json](../../apps/negentropy-influence/series.json):口播反串线/多标题顺序/序号绑定/清单完整性含反向登记与撞色/死链/可渲染性)、captions(srt/vtt)、qa_frames --check(黑帧/字幕带侵入/冻帧/WCAG 对比度自动体检)+ `--stills-plan`(分幕复检抽帧计划)、paper_extract(论文取证五子命令)、source_ledger(B 型信源固定提交+双指纹清单,`sync`/`audit` 按系列地图批量建账并离线执法)、refs(样本指纹清单)、tts_progress(长跑热漂移旁路监视);Stage ① 分两型——A 型论文(paper_extract + paper-notes.md)、B 型文档/代码/课程站点(source_ledger + source-notes.md + 证据三级),见 [skills/01](../../apps/negentropy-influence/pipeline/skills/01-source-extraction.md)。 -- [科普视频作品总览(两个系列 8 集)](../../apps/negentropy-influence/series.md) — 机读 SSOT [series.json](../../apps/negentropy-influence/series.json) 顶层为 `seriesList[]`;**自进化系列**(论文型)《上线之后,AI 才开始上学》(金/青/紫,v3 已交付,成片 14:01)→《AI 如何自己变强?》(蓝/橙)→《会写代码的 AI,开始给自己写代码》(绿/洋红);**Claude Code 通俗全解**(文档/代码型,**5 集全部已交付**,合计 66.9 分钟)《拆开 Claude Code:让 AI 动手的四层机制》(陶土橙/石青/警示红,14:14.73)→《AI 的视野是安排出来的:写下来的计划,另开的桌子》(鸢紫,13:14.00)→《AI 的记忆:会丢的和不能丢的》(苔绿,13:14.47)→《AI 会自己开工吗?后台与定时》(霜蓝,13:08.90)→《一群 AI 怎么干活:看板、信箱与各自的桌子》(赭金,13:03.27);信源 Learn Claude Code s01–s20 双钉(首集钉仓库 main `f9e8b28` 17 章整合版,其余四集钉站点同源修订 `67a9126c` 20 章版,MIT,归属登记见 [source-map](../../apps/negentropy-influence/source-map/claude-code-explained.md))。多系列执法语义:反串线规则跨系列全局,顺序类规则按系列内判定;口播永不携带集数序号,顺序变更 TTS 代价恒为零。 +- [科普视频作品总览(两个系列 8 集)](../../apps/negentropy-influence/series.md) — 机读 SSOT [series.json](../../apps/negentropy-influence/series.json) 顶层为 `seriesList[]`;**自进化系列**(论文型)《上线之后,AI 才开始上学》(金/青/紫,v3 已交付,成片 14:01)→《AI 如何自己变强?》(蓝/橙)→《会写代码的 AI,开始给自己写代码》(绿/洋红);**Claude Code Harness Engineering**(文档/代码型,5 集 Harness Engineering 改造中,原「通俗全解」版合计 66.9 分钟)《执行层:一个循环,就是全部》(陶土橙/石青/警示红,14:14.73)→《规划层:模型的视野是安排出来的》(鸢紫,13:14.00)→《记忆层:会丢的和不能丢的》(苔绿,13:14.47)→《时机层:谁来按下开始》(霜蓝,13:08.90)→《协作层:从一个到一群》(赭金,13:03.27);信源 Learn Claude Code s01–s20 双钉(首集钉仓库 main `f9e8b28` 17 章整合版,其余四集钉站点同源修订 `67a9126c` 20 章版,MIT,归属登记见 [source-map](../../apps/negentropy-influence/source-map/claude-code-explained.md))。多系列执法语义:反串线规则跨系列全局,顺序类规则按系列内判定;口播永不携带集数序号,顺序变更 TTS 代价恒为零。 - [系列信源地图(source-map,多集系列的章节归属 SSOT)](../../apps/negentropy-influence/source-map/claude-code-explained.md) — 站点↔仓库**修订分叉**的系列级唯一登记处(ISSUE-165 根因再上探:站点整站是课程旧修订,20 章 vs main 17 章整合版,故双钉——ep1 钉 main、后续集钉站点同源修订 67a9126c);机器版 [claude-code-explained.toml](../../apps/negentropy-influence/source-map/claude-code-explained.toml) 供 `source_ledger.py sync/audit` 派生台账条目名({slug}-readme/-code/-site,与 ep1 交付台账字节兼容)并离线执法三断言(条目齐/无跨集混入/pinned_ref=地图值);各集 source-notes 只链接不重述。 - [IndexTTS 声音克隆手册](../../apps/negentropy-influence/pipeline/VOICE-CLONING.md) — 双引擎 TTS 的克隆侧单一参考:部署(~/tools/index-tts 服务)/参考样本(prospect+prepare+refs 指纹门)/风格预设(sunny 明快阳光推荐位、sunny-steady 成片档 beams=3)/试听关卡(tts_sample + 领航片段)/缓存摘要与幂等/许可合规。 - [IndexTTS-2.5 进阶用法(上游能力面 · 机制循证 · 提升路线图)](../../apps/negentropy-influence/pipeline/INDEXTTS-2.5-ADVANCED.md) — 与操作手册正交的循证篇,锚定上游 HEAD `4f8792f` 逐条给出 file:line:能力矩阵(含 `do_sample` 在上游失效、`max_text_tokens_per_segment` 对本仓惰性等否定结论)/文本前端(中文走 wetext 而非 NeMo;实测读法矩阵——4 位年份带空格是**唯一**被击穿的规则,已成门,见 [ISSUE-164](./issue.md))/发音标注 `<行\|HANG2>`(DTW 对照证实拼音通道生效 2.4× 分离度,CMU 通道不可判定)/情感机制(`emo_bias` 8 维不等权、`normalize_emo_vec` 在 infer 内从不被调用 ⇒ `Σvec×alpha≤0.8` 是本仓自创口径,跨来源参数迁移偏差 16–33%;73 个「情感×说话人」原型解释「换选段则标定失效」)/采样参数族(`length_penalty=0.0` 非中性、`repetition_penalty=10` 与音色耦合、`max_mel_tokens`≈30s 且溢出表现为文本尾部未念出、无种子致 A/B 不可信)/参考音频(15s 硬截断保前丢后、恒重采样 22.05kHz、CMVN 使相似度对增益免疫、逐句成本来自 CFM 前缀)/性能(本机是 U-DiT 非论文 Zipformer ⇒ 论文 RTF 不可引用;分段 profile 实测 **s2mel 占 45–73%** 而非 T2S,束宽在 MPS 上近乎免费)/16 项 ROI 排序路线图与迁移地雷。配套工具:[发音标注台账](../../apps/negentropy-influence/pipeline/PRON-GLOSSARY.md)、[pron_marks.py](../../apps/negentropy-influence/pipeline/scripts/pron_marks.py)(标注解析/校验,拦「孤立 < 吞正文」等三类静默失效)、[tts_bench.py](../../apps/negentropy-influence/pipeline/scripts/tts_bench.py)(耗时基准与**测量环境体检**:漂移已定因为热节流,加 75s 冷却后 A/A 极差比 1.016–1.047× 合格;含成对 A/B 模式与 whisper 回转写判据)、[prospect_ref.py --accept](../../apps/negentropy-influence/pipeline/scripts/prospect_ref.py)(参考样本保真度验收:削波/底噪/动态/带宽/超 15s)。 From d97c46aa474d29bb9e38b0b22ef4652d35dd65a0 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sun, 23 Aug 2026 07:22:31 +0800 Subject: [PATCH 02/41] =?UTF-8?q?feat(video):=20=E4=BA=94=E9=9B=86=20Harne?= =?UTF-8?q?ss=20Engineering=20=E5=86=85=E5=AE=B9=E4=B8=8E=E8=A7=86?= =?UTF-8?q?=E8=A7=89=E6=94=B9=E9=80=A0=E2=80=94=E2=80=94=E5=AE=98=E6=96=B9?= =?UTF-8?q?=E9=94=9A=E7=82=B9=E6=9B=BF=E6=8D=A2=20+=20=E9=A6=96=E5=B0=BE?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=20+=20=E5=9B=BE=E8=A7=A3=E5=8D=87=E7=BA=A7;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 中度改造(换约 1/3,字数净守恒):五集口播 v-next + 分镜同步 + 场景组件升级。全部集实测口径 落在 13.0–14.6 分钟窗口(EP1 3932 字 / EP2 3669 / EP3 3805 / EP4 3702 / EP5 3688)。 - **EP1 执行层**:P0 压缩为 3 镜钩子(命名帧「挽具」+ 官方引文 + 五辐条供给图); 1-E 升级官方三相环(收集/行动/验证交融 + 人可打断针 + State 十格角标化); 3-F 换官方求值顺序流水线(deny→ask→allow 首中即出局 + 裸名 deny 工具消失); 3-G 换 auto 分类器视野分屏(做减法的监视器 + 反注入弹回帧);4-F 换 31 事件三层嵌套 (会话/回合/工具调用三节奏,官方口径);4-G 拆六闸流水线(官方 SDK 权限判定图)+ 印章对撞高潮保留;P6 新下期预告卡 + 信源四行化。 - **EP2 规划层**:P0 钩子提速(12→8 句)+「收回」钢印悬念;1-D 换退位帧(官方默认停用 清单工具 +「零件押注会过期」);子代理三层二十并发官方直断;技能常驻重注入修正;P6 分水岭收尾。 - **EP3 记忆层**:context rot 官方实测;官方两级策略背书;压缩存活矩阵(谁活过压缩); 记忆两条腿框架(你写的四层拼接 + 它写的自动记忆);前缀缓存钩;「都是上下文不是闸门」收尾。 - **EP4 时机层**:P0 时间盲症钩子(官方博客原话);超时自动转后台 + 三类例外;三档调度官方化; P5 后台会话托管(管家进程 + 六状态 + 穿重启续跑);P6 官方四件套画像收尾。 - **EP5 协作层**:P0 官方三失败模式症状卡;看板文件锁/信箱磁盘路径官方直断(三→二级证据升级); 三禁止章(组队不是权限洗白);worktree 四道闸(第四道不能关);MCP 延迟装载竖槽; 6-D 新「谁持有计划」四象纲图(分水岭 + 运行时三分区 + 收官反转「挽具第一次由它自己来写」); FullTurn 快闪化;官方十五倍 token 冷水。 门:check_series FAIL 0 · WARN 0(规则 7 零残留);五集内容门除 manifest 待重配外全绿 (分镜覆盖/读法陷阱/时长双口径全过);五集 tsc --noEmit 零错误;pipeline 测试 254 全过。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../script/narration.json | 141 ++--- .../script/narration.md | 103 ++-- .../script/storyboard.md | 14 +- .../video/src/scenes/P0Wait.tsx | 4 +- .../video/src/scenes/P2Rejoin.tsx | 6 +- .../video/src/scenes/P4Timer.tsx | 2 +- .../video/src/scenes/P5Truths.tsx | 6 +- .../video/src/scenes/P6Ending.tsx | 20 +- .../script/narration.json | 107 ++-- .../script/narration.md | 95 ++- .../script/storyboard.md | 22 +- .../video/src/scenes/P0Hook.tsx | 544 +++++++++--------- .../video/src/scenes/P1Loop.tsx | 203 ++++--- .../video/src/scenes/P3Gates.tsx | 452 ++++++++------- .../video/src/scenes/P4Hooks.tsx | 329 +++++++++-- .../video/src/scenes/P6Ending.tsx | 17 + .../script/narration.json | 71 +-- .../script/narration.md | 61 +- .../script/storyboard.md | 4 +- .../video/src/scenes/P0Reject.tsx | 2 +- .../video/src/scenes/P6Ending.tsx | 28 +- .../script/narration.json | 127 ++-- .../script/narration.md | 101 ++-- .../script/storyboard.md | 26 +- .../video/src/scenes/P2Mail.tsx | 4 +- .../video/src/scenes/P3Handshake.tsx | 2 +- .../video/src/scenes/P4Autonomy.tsx | 6 +- .../video/src/scenes/P5Desks.tsx | 2 +- .../video/src/scenes/P6Finale.tsx | 286 ++++++--- .../script/narration.json | 74 +-- .../script/narration.md | 52 +- .../script/storyboard.md | 8 +- .../video/src/scenes/P0Hook.tsx | 18 +- .../video/src/scenes/P1Plan.tsx | 156 ++--- .../video/src/scenes/P6Ending.tsx | 20 +- 35 files changed, 1719 insertions(+), 1394 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json index f1a9852d..e50ddca5 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json @@ -2,22 +2,22 @@ { "id": "p0-01", "scene": "P0", - "text": "你让它装一个依赖。进度条开始爬,一分钟,三分钟,十分钟。" + "text": "你让它跑个安装,进度条爬了十分钟,它就干等了十分钟。" }, { "id": "p0-02", "scene": "P0", - "text": "这十分钟它在干什么?什么也没干。就等着。" + "text": "按字计费,一秒没停。官方工程博客有句大实话:它感觉不到时间。" }, { "id": "p0-03", "scene": "P0", - "text": "你可能没意识到这有多亏:它是按字数付费的,等,也在烧钱。" + "text": "同一篇博客说,不看着它,它会高高兴兴把测试跑上几个小时。" }, { "id": "p0-04", "scene": "P0", - "text": "十分钟的干等,烧的是十分钟按字计费的钱,产出为零。" + "text": "所以表不归它管——归外面那层工程。这一集拆那只替它看表的手。" }, { "id": "p0-05", @@ -27,62 +27,42 @@ { "id": "p0-06", "scene": "P0", - "text": "不会。你会按下启动,然后去做饭、回消息、看论文,等它滴滴滴叫你。" + "text": "不会。按下启动去做别的,等它滴滴滴叫你。" }, { "id": "p0-07", "scene": "P0", - "text": "这个再平常不过的动作,拆开是两件事:活儿交给机器,人不陪着等。" + "text": "这个动作拆开是两件事:活交给机器,人不陪着等。" }, { "id": "p0-08", "scene": "P0", - "text": "这一集讲的就是把这两件事教给它:谁来按开始,谁来等。" + "text": "这集就讲怎么把这两件事教给它:谁来按开始,谁来等。" }, { "id": "p0-09", "scene": "P0", - "text": "我们分两步走。第一步,按下开始就走开——活交给机器,人不陪着等。" + "text": "而且它不光感觉不到时间,还不会自己安排等待。" }, { "id": "p0-10", "scene": "P0", - "text": "第二步更进一步:有些活,连按的人都可以不要,时间到了自己开始。" + "text": "官方管这个叫时间盲症:模型没有钟、没有闹钟、也没有「回头再看」的本能。" }, { "id": "p0-11", "scene": "P0", - "text": "每一步,都有真话要讲,也有坑要躲。" + "text": "于是第一步,把「等」摘掉:按下就走开,活交给机器。" }, { "id": "p0-12", "scene": "P0", - "text": "先从一个你可能真遇过的场景说起:让它装依赖、等构建、等测试跑完。" + "text": "第二步更进一步:连按的人都可以不要,时间到了自己开始。" }, { "id": "p0-13", "scene": "P0", - "text": "凡是等过的人都知道那种感觉——它像一台不许你离开的洗衣机。" - }, - { - "id": "p0-14", - "scene": "P0", - "text": "而且你细想会觉得荒诞:等待的这段时间,本来全是可用的。" - }, - { - "id": "p0-15", - "scene": "P0", - "text": "项目里还有别的文件能读、别的问题能想、别的活能安排。" - }, - { - "id": "p0-16", - "scene": "P0", - "text": "一切都停着,就因为第一个活还没完。这种浪费,工程不能忍。" - }, - { - "id": "p0-17", - "scene": "P0", - "text": "接下来的两层,都在拆同一个动作:把「等」从某个人身上摘下来。" + "text": "每一步都有真话要讲,也有坑要躲。先从第一种开始。" }, { "id": "p1-01", @@ -102,12 +82,12 @@ { "id": "p1-04", "scene": "P1", - "text": "它没勾怎么办?教学版留了一个兜底:看看命令里的关键词," + "text": "官方还有个真机制:命令到了超时线,不被杀掉,而是自动滑入后台接着跑。" }, { "id": "p1-05", "scene": "P1", - "text": "装东西、构建、跑测试这类词一出现,多半要跑超过半分钟,直接替它丢后台。" + "text": "三类例外照停:睡觉命令、带着 git 的命令、拆不成简单命令的。" }, { "id": "p1-06", @@ -267,77 +247,57 @@ { "id": "p2-13", "scene": "P2", - "text": "顺带说两个小东西。一个是活不止一种:跑命令只是其中之一," + "text": "活不止一种:能丢后台的有七种——跑命令、本地分身、远程分身、" }, { "id": "p2-14", "scene": "P2", - "text": "有人数过,产品里能丢后台的有七种——跑命令、本地分身、远程分身、" + "text": "进程内队友、工作流、监控外接,还有个整理记忆的,名字叫做梦。" }, { "id": "p2-15", "scene": "P2", - "text": "进程内队友、工作流、监控外接,还有个整理记忆的,名字叫做梦。" + "text": "每批工具干完,小模型顺手贴一张三十字的标签,像提交说明。" }, { "id": "p2-16", "scene": "P2", - "text": "另一个是每批工具干完,有个小模型顺手给这批活贴一张标签," + "text": "还有一层安心:你随时可以主动开信箱,问一句后台的活怎么样了。" }, { "id": "p2-17", "scene": "P2", - "text": "三十个字左右,像一条提交说明——给它自己回看用的,不进正片。" + "text": "它会把每条活的状态报给你:还在跑、跑完了、或者根本没这条活。" }, { "id": "p2-18", "scene": "P2", - "text": "还有一层安心:你随时可以主动开信箱,问一句「后台的活怎么样了」。" + "text": "前面留的伏笔——占位条上的任务编号,现在派上用场了。" }, { "id": "p2-19", "scene": "P2", - "text": "它会把每条活的状态报给你:还在跑、跑完了、或者根本没这条活。" + "text": "完成通知带着同一个编号回来对号——编号就是后台世界的取件码。" }, { "id": "p2-20", "scene": "P2", - "text": "前面还留了个伏笔:占位条上的任务编号,现在派上用场了。" + "text": "该把哪句「等它结果」的话补上,一查便知。账目永远平的:" }, { "id": "p2-21", "scene": "P2", - "text": "完成通知带着同一个编号回来,对上号,它就知道是哪件事办完了," + "text": "每次调用都有着落,要么当场给结果,要么占位再补通知。" }, { "id": "p2-22", "scene": "P2", - "text": "该把哪句「等它结果」的话补上。编号,就是后台世界里的取件码。" + "text": "对话这种东西,一旦有账对不上,后面全乱。" }, { "id": "p2-23", "scene": "P2", - "text": "这套配对还有个隐藏的好处:账目永远平的。" - }, - { - "id": "p2-24", - "scene": "P2", - "text": "每一次调用都有着落——要么当场给结果,要么给占位再补通知," - }, - { - "id": "p2-25", - "scene": "P2", - "text": "不存在一笔糊涂账。对话这种东西,一旦有账对不上,后面全乱。" - }, - { - "id": "p2-26", - "scene": "P2", - "text": "到这里,第一层「按下就走开」讲完了:活出去了,人不用等,它也没停。" - }, - { - "id": "p2-27", - "scene": "P2", - "text": "这一层的每个细节,都在维护一件事:秩序不因为异步而乱。" + "text": "第一层讲完了:活出去了,人不用等,它也没停。秩序不因为异步而乱。" }, { "id": "p3-01", @@ -477,41 +437,46 @@ { "id": "p4-19", "scene": "P4", - "text": "你可能还想知道:任务定义存哪?两种。" + "text": "任务定义存哪?官方分三档:云端的例程,关机也跑、不碰本地文件;" }, { "id": "p4-20", "scene": "P4", - "text": "一种写在磁盘文件里,程序重启还能找回来——适合长期定时的活。" + "text": "桌面定时,本机跨会话;会话内循环,新对话清空、只恢复没过期的。" }, { "id": "p4-21", "scene": "P4", - "text": "一种只存在内存里,这次会话结束就消失——适合临时提醒。" + "text": "老答案是用系统的定时表落盘——现在只是三档里的一档。" }, { "id": "p4-22", "scene": "P4", - "text": "选择权在写表的人手里:要跨重启的,落盘;用完即弃的,不落。" + "text": "三档各管一段:真要关机也跑的上云端;只在本机的用桌面;" }, { "id": "p4-23", "scene": "P4", - "text": "看表的不干活,干活的不看表,中间靠一条队列传话。生产和消费,解耦了。" + "text": "只在这场对话里有意义的,跟着会话走,散场即清空。" }, { "id": "p4-24", "scene": "P4", - "text": "这套分工听起来繁琐,但每一层都各改各的:表可以换格式,队列可以换实现," + "text": "看表的不干活,干活的不看表,中间靠一条队列传话。生产和消费,解耦了。" }, { "id": "p4-25", "scene": "P4", - "text": "循环一无所知。牵一发而不动全身,这才有资格谈稳定。" + "text": "这套分工听起来繁琐,但每一层都各改各的:表可以换格式,队列可以换实现," }, { "id": "p4-26", "scene": "P4", + "text": "循环一无所知。牵一发而不动全身,这才有资格谈稳定。" + }, + { + "id": "p4-27", + "scene": "P4", "text": "解耦落到这儿就一句话:谁都不必知道对方在忙什么。" }, { @@ -582,41 +547,51 @@ { "id": "p5-14", "scene": "P5", - "text": "把进程关了,表就停了。调度器活在它的身体里,不是墙上的闹钟服务。" + "text": "但官方给了新答案:后台会话由一个独立的管家进程托管。" }, { "id": "p5-15", "scene": "P5", - "text": "所谓持久化,保存的是任务的定义——下次启动,它读到表,知道该补的会补;" + "text": "不需要任何终端活着;状态落盘,穿过自动更新与重启,睡眠唤醒会重连。" }, { "id": "p5-16", "scene": "P5", - "text": "但它睡着的时候,是真的不响。想睡也响,得请操作系统层的闹钟。" + "text": "管家给每个会话记账:六种状态,排队、跑着、等审批、被拦、收尾、完事。" }, { "id": "p5-17", "scene": "P5", - "text": "对了,表上还有个总量上限:五十条。满了要先取消一条才能再添——" + "text": "行摘要也是一个小模型顺带写的——省着主模型的上下文。" }, { "id": "p5-18", "scene": "P5", - "text": "闹钟太多的人,该先想想是不是真的需要这么多闹钟。" + "text": "进程退出不等于任务没了——接回后从停的地方继续。" }, { "id": "p5-19", "scene": "P5", - "text": "还有个小细节:定时任务触发的请求,带着「低优先级」的标记——" + "text": "对了,表上还有个总量上限:五十条。满了要先取消一条才能再添——" }, { "id": "p5-20", "scene": "P5", - "text": "服务一忙,先紧着人的事,闹钟的事往后稍稍。" + "text": "闹钟太多的人,该先想想是不是真的需要这么多闹钟。" }, { "id": "p5-21", "scene": "P5", + "text": "还有个小细节:定时任务触发的请求,带着「低优先级」的标记——" + }, + { + "id": "p5-22", + "scene": "P5", + "text": "服务一忙,先紧着人的事,闹钟的事往后稍稍。" + }, + { + "id": "p5-23", + "scene": "P5", "text": "三个真话合起来是一种态度:定时这件事,想象很浪漫,工程都在打补丁。" }, { @@ -677,21 +652,21 @@ { "id": "p6-12", "scene": "P6", - "text": "到那时你会发现还是同样的套路:先把等待摘掉,再把决定挪走。" + "text": "官方给这层工程画过一张像:一个循环、一套工具、一套记忆、一道护栏。" }, { "id": "p6-13", "scene": "P6", - "text": "本片机制依据官方文档与公开工程实践,取数日期在画面上。" + "text": "本片机制依据官方文档,取数2026年8月,以官方最新表述为准。" }, { "id": "p6-14", "scene": "P6", - "text": "涉及产品内部的部分,来自第三方的源码分析,片中已逐处标注。" + "text": "涉及产品内部的部分,为第三方源码分析,片中已逐处标注。" }, { "id": "p6-15", "scene": "P6", - "text": "涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注。下期见。" + "text": "下期,桌子从一张变成一排:一群它,怎么分活、怎么传话、怎么不打架。下期见。" } ] diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md index 554a2558..bdc9f8c3 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md @@ -1,4 +1,4 @@ -# 逐字稿:《AI 会自己开工吗?后台与定时》 +# 逐字稿:《时机层:谁来按下开始》 > **全片单一事实源的下游**:每条断言回溯 [../research/source-notes.md](../research/source-notes.md)。 > 格式约定:`## P` 起一幕;`- [pN-xx] 文本` 一行一句(进配音);`>` 引用块是画面备注(不进配音)。 @@ -13,23 +13,19 @@ > 画面:系列终端。依赖安装进度条缓慢爬行;旁边一枚计费表跟着时间狂转。 > 角标:Background Tasks · "Slow Operations Go to the Background" -- [p0-01] 你让它装一个依赖。进度条开始爬,一分钟,三分钟,十分钟。 -- [p0-02] 这十分钟它在干什么?什么也没干。就等着。 -- [p0-03] 你可能没意识到这有多亏:它是按字数付费的,等,也在烧钱。 -- [p0-04] 十分钟的干等,烧的是十分钟按字计费的钱,产出为零。 +- [p0-01] 你让它跑个安装,进度条爬了十分钟,它就干等了十分钟。 +- [p0-02] 按字计费,一秒没停。官方工程博客有句大实话:它感觉不到时间。 +- [p0-03] 同一篇博客说,不看着它,它会高高兴兴把测试跑上几个小时。 +- [p0-04] 所以表不归它管——归外面那层工程。这一集拆那只替它看表的手。 - [p0-05] 换成你,你会站在洗衣机前面盯着滚筒等三十分钟吗? -- [p0-06] 不会。你会按下启动,然后去做饭、回消息、看论文,等它滴滴滴叫你。 -- [p0-07] 这个再平常不过的动作,拆开是两件事:活儿交给机器,人不陪着等。 -- [p0-08] 这一集讲的就是把这两件事教给它:谁来按开始,谁来等。 -- [p0-09] 我们分两步走。第一步,按下开始就走开——活交给机器,人不陪着等。 -- [p0-10] 第二步更进一步:有些活,连按的人都可以不要,时间到了自己开始。 -- [p0-11] 每一步,都有真话要讲,也有坑要躲。 -- [p0-12] 先从一个你可能真遇过的场景说起:让它装依赖、等构建、等测试跑完。 -- [p0-13] 凡是等过的人都知道那种感觉——它像一台不许你离开的洗衣机。 -- [p0-14] 而且你细想会觉得荒诞:等待的这段时间,本来全是可用的。 -- [p0-15] 项目里还有别的文件能读、别的问题能想、别的活能安排。 -- [p0-16] 一切都停着,就因为第一个活还没完。这种浪费,工程不能忍。 -- [p0-17] 接下来的两层,都在拆同一个动作:把「等」从某个人身上摘下来。 +- [p0-06] 不会。按下启动去做别的,等它滴滴滴叫你。 +- [p0-07] 这个动作拆开是两件事:活交给机器,人不陪着等。 +- [p0-08] 这集就讲怎么把这两件事教给它:谁来按开始,谁来等。 +- [p0-09] 而且它不光感觉不到时间,还不会自己安排等待。 +- [p0-10] 官方管这个叫时间盲症:模型没有钟、没有闹钟、也没有「回头再看」的本能。 +- [p0-11] 于是第一步,把「等」摘掉:按下就走开,活交给机器。 +- [p0-12] 第二步更进一步:连按的人都可以不要,时间到了自己开始。 +- [p0-13] 每一步都有真话要讲,也有坑要躲。先从第一种开始。 ## P1 按下就走开 @@ -40,8 +36,8 @@ - [p1-01] 先说第一层:按下开始就走开。 - [p1-02] 谁来决定一件活要不要丢后台?主路是它自己—— - [p1-03] 跑命令的工具上有一个「后台执行」的开关,它勾了,活就走后台。 -- [p1-04] 它没勾怎么办?教学版留了一个兜底:看看命令里的关键词, -- [p1-05] 装东西、构建、跑测试这类词一出现,多半要跑超过半分钟,直接替它丢后台。 +- [p1-04] 官方还有个真机制:命令到了超时线,不被杀掉,而是自动滑入后台接着跑。 +- [p1-05] 三类例外照停:睡觉命令、带着 git 的命令、拆不成简单命令的。 - [p1-06] 活丢出去之后,画面上发生的事最值得看:那个循环,没有停。 - [p1-07] 慢命令块滑到环外的一条旁轨上自己跑;循环口立刻贴上一张占位条, - [p1-08] 意思是:这活派出去了,好了会叫你。然后循环接着转,去干下一件。 @@ -80,21 +76,17 @@ - [p2-10] 这个「不插队」的安排,乍看不起眼,细想很关键。 - [p2-11] 你正问它一个正经问题,后台忽然蹦出来「装依赖好了」, - [p2-12] 话头被截走,它的思路也跟着跑了。排队,保护的是对话的完整性。 -- [p2-13] 顺带说两个小东西。一个是活不止一种:跑命令只是其中之一, -- [p2-14] 有人数过,产品里能丢后台的有七种——跑命令、本地分身、远程分身、 -- [p2-15] 进程内队友、工作流、监控外接,还有个整理记忆的,名字叫做梦。 -- [p2-16] 另一个是每批工具干完,有个小模型顺手给这批活贴一张标签, -- [p2-17] 三十个字左右,像一条提交说明——给它自己回看用的,不进正片。 -- [p2-18] 还有一层安心:你随时可以主动开信箱,问一句「后台的活怎么样了」。 -- [p2-19] 它会把每条活的状态报给你:还在跑、跑完了、或者根本没这条活。 -- [p2-20] 前面还留了个伏笔:占位条上的任务编号,现在派上用场了。 -- [p2-21] 完成通知带着同一个编号回来,对上号,它就知道是哪件事办完了, -- [p2-22] 该把哪句「等它结果」的话补上。编号,就是后台世界里的取件码。 -- [p2-23] 这套配对还有个隐藏的好处:账目永远平的。 -- [p2-24] 每一次调用都有着落——要么当场给结果,要么给占位再补通知, -- [p2-25] 不存在一笔糊涂账。对话这种东西,一旦有账对不上,后面全乱。 -- [p2-26] 到这里,第一层「按下就走开」讲完了:活出去了,人不用等,它也没停。 -- [p2-27] 这一层的每个细节,都在维护一件事:秩序不因为异步而乱。 +- [p2-13] 活不止一种:能丢后台的有七种——跑命令、本地分身、远程分身、 +- [p2-14] 进程内队友、工作流、监控外接,还有个整理记忆的,名字叫做梦。 +- [p2-15] 每批工具干完,小模型顺手贴一张三十字的标签,像提交说明。 +- [p2-16] 还有一层安心:你随时可以主动开信箱,问一句后台的活怎么样了。 +- [p2-17] 它会把每条活的状态报给你:还在跑、跑完了、或者根本没这条活。 +- [p2-18] 前面留的伏笔——占位条上的任务编号,现在派上用场了。 +- [p2-19] 完成通知带着同一个编号回来对号——编号就是后台世界的取件码。 +- [p2-20] 该把哪句「等它结果」的话补上,一查便知。账目永远平的: +- [p2-21] 每次调用都有着落,要么当场给结果,要么占位再补通知。 +- [p2-22] 对话这种东西,一旦有账对不上,后面全乱。 +- [p2-23] 第一层讲完了:活出去了,人不用等,它也没停。秩序不因为异步而乱。 ## P3 有一只狗盯着 @@ -136,14 +128,15 @@ - [p4-16] 为什么要绕这么一圈?直接到了点就地开工不行吗? - [p4-17] 不行。它可能正跟你聊到一半,硬插进去,一句话被拦腰截断。 - [p4-18] 队列的意义就是礼让:到点的活在门口排队,等它把手头的说完。 -- [p4-19] 你可能还想知道:任务定义存哪?两种。 -- [p4-20] 一种写在磁盘文件里,程序重启还能找回来——适合长期定时的活。 -- [p4-21] 一种只存在内存里,这次会话结束就消失——适合临时提醒。 -- [p4-22] 选择权在写表的人手里:要跨重启的,落盘;用完即弃的,不落。 -- [p4-23] 看表的不干活,干活的不看表,中间靠一条队列传话。生产和消费,解耦了。 -- [p4-24] 这套分工听起来繁琐,但每一层都各改各的:表可以换格式,队列可以换实现, -- [p4-25] 循环一无所知。牵一发而不动全身,这才有资格谈稳定。 -- [p4-26] 解耦落到这儿就一句话:谁都不必知道对方在忙什么。 +- [p4-19] 任务定义存哪?官方分三档:云端的例程,关机也跑、不碰本地文件; +- [p4-20] 桌面定时,本机跨会话;会话内循环,新对话清空、只恢复没过期的。 +- [p4-21] 老答案是用系统的定时表落盘——现在只是三档里的一档。 +- [p4-22] 三档各管一段:真要关机也跑的上云端;只在本机的用桌面; +- [p4-23] 只在这场对话里有意义的,跟着会话走,散场即清空。 +- [p4-24] 看表的不干活,干活的不看表,中间靠一条队列传话。生产和消费,解耦了。 +- [p4-25] 这套分工听起来繁琐,但每一层都各改各的:表可以换格式,队列可以换实现, +- [p4-26] 循环一无所知。牵一发而不动全身,这才有资格谈稳定。 +- [p4-27] 解耦落到这儿就一句话:谁都不必知道对方在忙什么。 ## P5 时间表的真话 @@ -163,14 +156,16 @@ - [p5-11] 第二个真话:定时任务会自动退休。连续七天没动静的周期任务, - [p5-12] 到期自动删掉,删之前还会最后跑一次。忘了设的闹钟,不该响一辈子。 - [p5-13] 第三个真话最实在,也是最容易踩坑的: -- [p5-14] 把进程关了,表就停了。调度器活在它的身体里,不是墙上的闹钟服务。 -- [p5-15] 所谓持久化,保存的是任务的定义——下次启动,它读到表,知道该补的会补; -- [p5-16] 但它睡着的时候,是真的不响。想睡也响,得请操作系统层的闹钟。 -- [p5-17] 对了,表上还有个总量上限:五十条。满了要先取消一条才能再添—— -- [p5-18] 闹钟太多的人,该先想想是不是真的需要这么多闹钟。 -- [p5-19] 还有个小细节:定时任务触发的请求,带着「低优先级」的标记—— -- [p5-20] 服务一忙,先紧着人的事,闹钟的事往后稍稍。 -- [p5-21] 三个真话合起来是一种态度:定时这件事,想象很浪漫,工程都在打补丁。 +- [p5-14] 但官方给了新答案:后台会话由一个独立的管家进程托管。 +- [p5-15] 不需要任何终端活着;状态落盘,穿过自动更新与重启,睡眠唤醒会重连。 +- [p5-16] 管家给每个会话记账:六种状态,排队、跑着、等审批、被拦、收尾、完事。 +- [p5-17] 行摘要也是一个小模型顺带写的——省着主模型的上下文。 +- [p5-18] 进程退出不等于任务没了——接回后从停的地方继续。 +- [p5-19] 对了,表上还有个总量上限:五十条。满了要先取消一条才能再添—— +- [p5-20] 闹钟太多的人,该先想想是不是真的需要这么多闹钟。 +- [p5-21] 还有个小细节:定时任务触发的请求,带着「低优先级」的标记—— +- [p5-22] 服务一忙,先紧着人的事,闹钟的事往后稍稍。 +- [p5-23] 三个真话合起来是一种态度:定时这件事,想象很浪漫,工程都在打补丁。 ## P6 落点与信源 @@ -188,7 +183,7 @@ - [p6-09] 但记住那个真话:时钟装在它的身体里,不在墙上。 - [p6-10] 它的自主,到此为止是「守时的自主」——时间到点自己开工, - [p6-11] 至于「自己决定该干什么活」,那是更大的一步,我们后面再拆。 -- [p6-12] 到那时你会发现还是同样的套路:先把等待摘掉,再把决定挪走。 -- [p6-13] 本片机制依据官方文档与公开工程实践,取数日期在画面上。 -- [p6-14] 涉及产品内部的部分,来自第三方的源码分析,片中已逐处标注。 -- [p6-15] 涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注。下期见。 +- [p6-12] 官方给这层工程画过一张像:一个循环、一套工具、一套记忆、一道护栏。 +- [p6-13] 本片机制依据官方文档,取数2026年8月,以官方最新表述为准。 +- [p6-14] 涉及产品内部的部分,为第三方源码分析,片中已逐处标注。 +- [p6-15] 下期,桌子从一张变成一排:一群它,怎么分活、怎么传话、怎么不打架。下期见。 diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md index 7af52837..bfaa2fc0 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md @@ -11,8 +11,8 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 0-A | p0-01..04 | 系列终端:`npm install` 进度条缓慢爬行;旁边一枚计费表随秒针狂转 | 进度条一格一格挪;计费表转速与进度条形成反差(钱在飞,活没动) | -| 0-B | p0-05..08 | 洗衣机剪影登场:人形站在滚筒前干等的荒诞画面;「按下→走开」的两格漫画 | 人形逐步转身离开;洗衣机上出现小计时环自己转 | -| 0-C | p0-09..17 | 三种开始预告:三格小图(有人按并等/有人按不等/没人按);终端回到「不许你离开的洗衣机」 | 三格依次亮起(`later` 描边统一);p0-14..16 荒诞感升级:画面切「一切停摆的房间」——别的文件、别的问题、别的活都亮着待办灯却全被冻结,只有第一个活的时间条在走 | +| 0-B | p0-05..08 | 洗衣机剪影 + 「时间盲症」帧:人形站在滚筒前干等;官方博客引文条「它感觉不到时间」 | 人形转身离开;p0-02..03 官方引文条压入(时间盲症 + 「高高兴兴跑几小时」);计时环自己转 | +| 0-C | p0-09..13 | 时间盲症补刀:模型没有钟、没有闹钟、没有「回头再看」的本能(三无小图);两步预告(摘掉等 / 挪走按) | 三无小图依次亮(无钟/无闹钟/无回头);两步预告格亮起;p0-13 收束「每一步都有真话要讲」 | ## P1 按下就走开 @@ -30,8 +30,8 @@ | 2-A | p2-01..05 | 配对语义:一次调用卡 ↔ 一条结果卡的锁扣;真结果换装成「完成通知」卡入队 | 调用/结果两卡对齐锁扣「咔」;完成通知卡换色(`later`)滑入队列 | | 2-B | p2-06..09 | ★两级队列:环入口两条道(「下一轮」/「稍后」);用户输入卡永远插在稍后队首 | 队列双道描线;后台通知卡落到「稍后」道;用户输入卡随后落下排到它前面 | | 2-C | p2-10..12 | 不插队保护:对话气泡被后台通知硬插(✗ 演示)vs 排队(✓ 现实)对照 | ✗ 帧:气泡被截断(`deny` 闪);✓ 帧:气泡完整说完再取信 | -| 2-D | p2-13..19 | 七种后台任务小图一排(跑命令/本地分身/远程分身/队友/工作流/监控/做梦)+ 30 字标签演示 | 七个小图标依次点亮(统一 `later`,无七色);一张标签卡快速打出「install deps & verify」式短句 | -| 2-E | p2-20..27 | 取件码回收:完成通知带同号回巢对号;账目天平(每次调用都有着落)两端平衡 | 编号对号动画;天平两端各落一卡保持水平;p2-24..26 收束:第一层全景缩略图(环+旁轨+队列+狗)定格盖章「按下就走开 ✓」 | +| 2-D | p2-13..15 | 七种后台任务小图一排(跑命令/本地分身/远程分身/队友/工作流/监控/做梦)+ 30 字标签演示 | 七个小图标依次点亮(统一 `later`,无七色);标签卡快速打出「install deps & verify」式短句 | +| 2-E | p2-16..23 | 开信箱问状态 + 取件码回收:完成通知带同号回巢对号;账目天平(每次调用都有着落)两端平衡 | p2-16/17 状态报卡(跑着/完了/没有);编号对号动画;天平两端平衡;p2-23 收束盖章「按下就走开 ✓」 | ## P3 有一只狗盯着 @@ -48,7 +48,7 @@ | 4-B | p4-05..08 | 五格时间表大特写:分钟/小时/日/月/星期五列;三个实例逐个点亮(每天九点/每五分钟/工作日) | 五列框架描线;三个实例行的格子逐个填充并显出读法 | | 4-C | p4-09..10 | 两道保险:写表验格式(错表被拒)+ 磁盘恢复逐条检查(坏条跳过) | 一张「99 9 * * *」表被 `deny` 弹回;恢复流里一张坏卡滑过不停 | | 4-D | p4-11..18 | 四层模型:秒摆线程(每秒一跳)→ 队列 → 闸(闲时才开)→ 循环(消费);分钟标记防重 | 秒摆节拍动画;命中分钟时一张卡落入队列;闸门开关与循环空闲状态联动;同分钟第二枪被挡 | -| 4-E | p4-19..26 | 持久化两种:磁盘文件(跨重启找回)vs 内存(会话即弃);解耦落点 | 文件图标带重启箭头绕回;内存卡淡出;四层各层独立换件示意(换表/换队列/循环不动) | +| 4-E | p4-19..27 | 三档调度:云端例程(关机也跑)/ 桌面定时(本机)/ 会话内循环(散场清空)三层卡片 + 老答案降级虚影 + 解耦落点 | 三层卡自上而下亮(`later` 统一);系统 crontab 老卡退为虚影;四层独立换件示意(换表/换队列/循环不动) | ## P5 时间表的真话 @@ -57,8 +57,8 @@ | 5-A | p5-01..04 | ★踩踏帧:一排相同的表全指 9:00,千万任务同一秒冲出互相踩踏(`deny` 混乱) | 表针同时到位→任务箭头齐射→拥挤碰撞效果 | | 5-B | p5-05..08 | ★确定性抖动:同排表各按算好的固定偏移错峰落下;「算出来 vs 随机」对照(随机会漂的轨迹线) | 每张表各自延迟不同但固定的量再落;随机轨迹画成漂移虚线(`deny`),确定性轨迹为整齐错列(`later`);整点提前 90 秒逆行小箭头 | | 5-C | p5-09..10 | 七天退休:日历翻七天→退休章盖下(删前最后跑一次的小尾巴) | 日历快翻;章落下;最后一次触发的小脉冲 | -| 5-D | p5-11..14 | 诚实边界:进程图标关闭→表停摆;持久化抽屉里只躺着「任务定义」文件;墙上闹钟(OS 层)虚影对照 | 进程灯灭、秒摆停;抽屉开合展示文件;墙上闹钟虚影带「另一回事」角标 | -| 5-E | p5-15..21 | 上限 50 + 低优先级标记 + 收束句(「想象浪漫·工程打补丁」) | 满座计数器 50/50;请求卡带「低」字标记排到队尾;金句卡淡入 | +| 5-D | p5-11..18 | ★官方新答案:独立管家进程托管后台会话——六状态记账、行摘要小模型、状态落盘穿重启、接回续跑 | 管家进程图标立起(不眠的眼睛);六状态小环依次点亮;状态文件落盘 + 重启箭头绕回;接回卡从停点续走 | +| 5-E | p5-19..23 | 上限 50 + 低优先级标记 + 收束句(「想象浪漫·工程打补丁」) | 满座计数器 50/50;请求卡带「低」字标记排到队尾;金句卡淡入 | ## P6 落点与信源 diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx index a0f82a1c..695f80f3 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx @@ -390,7 +390,7 @@ export const P0Wait: React.FC<{scene: SceneRange}> = ({scene}) => { const at = (id: string) => w(id).from; const bA = w('p0-01', 'p0-04'); const bB = w('p0-05', 'p0-08'); - const bC = w('p0-09', 'p0-17'); + const bC = w('p0-09', 'p0-13'); return ( @@ -400,7 +400,7 @@ export const P0Wait: React.FC<{scene: SceneRange}> = ({scene}) => { - + ); diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx index 5af690b7..7c5bd6eb 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx @@ -396,8 +396,8 @@ export const P2Rejoin: React.FC<{scene: SceneRange}> = ({scene}) => { const bA = w('p2-01', 'p2-05'); const bB = w('p2-06', 'p2-09'); const bC = w('p2-10', 'p2-12'); - const bD = w('p2-13', 'p2-19'); - const bE = w('p2-20', 'p2-27'); + const bD = w('p2-13', 'p2-15'); + const bE = w('p2-16', 'p2-23'); return ( @@ -413,7 +413,7 @@ export const P2Rejoin: React.FC<{scene: SceneRange}> = ({scene}) => { - + ); diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx index 64aa400d..a5603bb8 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx @@ -541,7 +541,7 @@ export const P4Timer: React.FC<{scene: SceneRange}> = ({scene}) => { const bB = w('p4-05', 'p4-08'); const bC = w('p4-09', 'p4-10'); const bD = w('p4-11', 'p4-18'); - const bE = w('p4-19', 'p4-26'); + const bE = w('p4-19', 'p4-27'); return ( diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx index 305bfce9..dad3d61f 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx @@ -463,8 +463,8 @@ export const P5Truths: React.FC<{scene: SceneRange}> = ({scene}) => { const bA = w('p5-01', 'p5-04'); const bB = w('p5-05', 'p5-08'); const bC = w('p5-09', 'p5-10'); - const bD = w('p5-11', 'p5-14'); - const bE = w('p5-15', 'p5-21'); + const bD = w('p5-11', 'p5-18'); + const bE = w('p5-19', 'p5-23'); return ( @@ -488,7 +488,7 @@ export const P5Truths: React.FC<{scene: SceneRange}> = ({scene}) => { - + ); diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx index fbbc1f14..121f0959 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx @@ -299,10 +299,24 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> marginTop: 18, }} > - {'AI 会自己开工吗?'} + {'时机层:谁来按下开始'}
-
- {'后台与定时'} + {/* 下期预告卡:标题只在画面(反串线纪律) */} +
+
+ {'下期 · 协作层'} +
+
+ {'从一个到一群'} +
) : null} diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json index 6fbec687..be4e9bf8 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json @@ -2,52 +2,37 @@ { "id": "p0-01", "scene": "P0", - "text": "你让 AI 看看项目里有哪些文件,再跑一下其中一个脚本。" + "text": "你让 AI 跑个脚本:它把命令写好,然后就停在那儿了。" }, { "id": "p0-02", "scene": "P0", - "text": "它想了想,写出一条命令,然后就停在那儿了。" + "text": "复制、粘贴、回车、再把输出贴回去——每一轮的搬运工,是你。" }, { "id": "p0-03", "scene": "P0", - "text": "它不会自己去跑,也看不到跑完之后的结果。" + "text": "从「写出命令」到「真的跑起来」,缺的那一层,官方起了名字。" }, { "id": "p0-04", "scene": "P0", - "text": "于是你复制这条命令,粘到终端里,敲回车," + "text": "名字就叫挽具:把动力源,套进一个可控的结构里。" }, { "id": "p0-05", "scene": "P0", - "text": "再把满屏的输出复制一遍,粘回对话框。" + "text": "官方说得直白:这套东西是挽具,模型在挽具里面。" }, { "id": "p0-06", "scene": "P0", - "text": "它接着想,又写出下一条;你再跑一遍,再贴一遍。" + "text": "挽具供给它五样东西:文件、命令、权限、记忆、护栏。" }, { "id": "p0-07", "scene": "P0", - "text": "这一来一回里,真正在中间搬东西的,是你。" - }, - { - "id": "p0-08", - "scene": "P0", - "text": "那么从「能写出这条命令」,到「它真的在你电脑上跑起来」," - }, - { - "id": "p0-09", - "scene": "P0", - "text": "中间缺的那一层到底是什么?" - }, - { - "id": "p0-10", - "scene": "P0", - "text": "今天我们就把这一层拆开来看。" + "text": "这集就把这只挽具,一层一层拆开看。" }, { "id": "p1-01", @@ -172,37 +157,37 @@ { "id": "p1-25", "scene": "P1", - "text": "教学版的循环身上只带一样东西:那份消息列表。" + "text": "官方给这个循环画过像:三件事交融着转——" }, { "id": "p1-26", "scene": "P1", - "text": "而按第三方的源码分析,真实产品里带着十样,像十个抽屉。" + "text": "收集上下文、采取行动、验证结果,不是硬阶段。" }, { "id": "p1-27", "scene": "P1", - "text": "剩下九个管的是压缩进度、补救次数、钩子拦没拦过停机、轮数这些。" + "text": "而且你随时可以打断它、补一句、让它改道。" }, { "id": "p1-28", "scene": "P1", - "text": "有意思的是,几乎每个抽屉都对应后面的某一层机制。" + "text": "教学版身上只带一份消息列表;真实产品带着十样," }, { "id": "p1-29", "scene": "P1", - "text": "也就是说,循环没有长个,长出来的是它随身带的状态。" + "text": "压缩进度、补救次数、钩子拦没拦过停机、轮数——细节进角标。" }, { "id": "p1-30", "scene": "P1", - "text": "退出的路子也一样——按他的说法,真实产品里有一大把:" + "text": "循环没长个,长出来的是它随身带的状态。" }, { "id": "p1-31", "scene": "P1", - "text": "报错、中断、钩子叫停、轮数到顶、预算烧完。" + "text": "退出的路子也有一大把:报错、中断、钩子叫停、预算烧完。" }, { "id": "p1-32", @@ -392,7 +377,7 @@ { "id": "p3-06", "scene": "P3", - "text": "所以安全不能指望模型自觉,得在执行之前由代码拦一道。" + "text": "官方把话说死了:权限由这层代码执行,不由模型执行。" }, { "id": "p3-07", @@ -427,7 +412,7 @@ { "id": "p3-13", "scene": "P3", - "text": "三道都没命中呢?直接放行——日常绝大多数操作走的都是这条路。" + "text": "三道都没命中呢?兜底永远再问你一句——弃权不等于放行。" }, { "id": "p3-14", @@ -482,52 +467,52 @@ { "id": "p3-25", "scene": "P3", - "text": "而这些规则从哪儿来?他数出了八个地方——" + "text": "规则求值的顺序官方也写死了:拒绝、询问、放行," }, { "id": "p3-26", "scene": "P3", - "text": "你自己的全局配置、项目配置、本地配置、功能开关、公司管理策略," + "text": "头一个命中就出局——规则写得多具体,都改变不了顺序。" }, { "id": "p3-27", "scene": "P3", - "text": "再加上启动参数、内联命令,和这次会话里的临时授权。" + "text": "所以一条宽拒绝,靠一条窄放行开不出例外。" }, { "id": "p3-28", "scene": "P3", - "text": "八个来源难免打架,所以有优先级:越靠近「组织」的越大。" + "text": "裸名拒绝更狠:整件工具从模型身上直接消失。" }, { "id": "p3-29", "scene": "P3", - "text": "公司策略压过本地配置。这一层,是给团队和企业留的。" + "text": "就算全放行模式,也压不住一条写死的拒绝。" }, { "id": "p3-30", "scene": "P3", - "text": "他还写到一处很能说明工程品味的设计:自动批准。" + "text": "全自动模式不靠你点头的次数,靠另一个模型当闸门。" }, { "id": "p3-31", "scene": "P3", - "text": "全都自动跑的模式下它不会每次弹窗," + "text": "官方遥测补一刀:权限提示,九成三都被点了批准。" }, { "id": "p3-32", "scene": "P3", - "text": "而是先按更宽松的模式试判一遍,再查一张安全工具白名单," + "text": "审判者的视野是做减法的:只看用户消息和裸命令。" }, { "id": "p3-33", "scene": "P3", - "text": "最后才把这次调用和上下文交给一个小模型去判断。" + "text": "模型的自我辩解、工具的输出,全被剥在视野外。" }, { "id": "p3-34", "scene": "P3", - "text": "而且留了个刹车:小模型连着拒绝太多次,就退回人工审批。" + "text": "评它做了什么,不看它说了什么——注入的谎话骗不到它。" }, { "id": "p3-35", @@ -647,72 +632,72 @@ { "id": "p4-23", "scene": "P4", - "text": "真实产品里这样的时机有多少个?" + "text": "真实产品里这样的时机,官方文档口径三十一个," }, { "id": "p4-24", "scene": "P4", - "text": "按第三方的源码分析,二十七个——" + "text": "分三种节奏:会话一次、回合一次、每次调用前后。" }, { "id": "p4-25", "scene": "P4", - "text": "会话开始结束、权限被请求被拒绝、子任务启停、压缩前后、文件被改。" + "text": "处理器也不只是跑脚本,还能让小模型单轮判决。" }, { "id": "p4-27", "scene": "P4", - "text": "但这一层真正的重点是另一件事:有人把它称为" + "text": "表态的契约值得单独记:沉默,不等于批准——" }, { "id": "p4-28", "scene": "P4", - "text": "整个权限系统里最重要的一处安全设计。" + "text": "不吭声的意思是「我不作决定」,流程照走。" }, { "id": "p4-29", "scene": "P4", - "text": "是这样:插口上的函数可以直接给出权限结论,说「这个我批了」。" + "text": "插口上的函数说「这个我批了」,就真的放行吗?不。" }, { "id": "p4-30", "scene": "P4", - "text": "那它说批了,就真的放行吗?不。" + "text": "它的放行,仍要穿过后面的拒绝与询问两站。" }, { "id": "p4-31", "scene": "P4", - "text": "就算插口上的脚本说放行,配置里的禁止和询问仍然要再走一遍。" + "text": "方向是单向的:扩展点能加限制,不能解除限制。" }, { "id": "p4-32", "scene": "P4", - "text": "方向是单向的:扩展点能加限制,不能解除限制。" + "text": "而且这条单向,官方画成过六道闸门的流水线。" }, { "id": "p4-33", "scene": "P4", - "text": "而教学版没有这一层。拆源码的人自己写下了这句评语:" + "text": "教学版没有这一层,拆源码的人写下评语:" }, { "id": "p4-34", "scene": "P4", - "text": "这在教学里够用了,但放到生产环境,就是一个安全漏洞。" + "text": "教学里够用,生产环境就是一个安全漏洞。" }, { "id": "p4-35", "scene": "P4", - "text": "还有个小机关:那个能说「别停」的插口本身很危险," + "text": "那个能说「别停」的插口本身很危险——它叫模型接着干," }, { "id": "p4-36", "scene": "P4", - "text": "它叫模型接着干,模型干完又要停,它又叫接着干,就转不出来了。" + "text": "模型干完又要停,它又叫接着干,就转不出来了。" }, { "id": "p4-37", "scene": "P4", - "text": "据他所说,产品里放了个标记,后面的轮次看到它就不再拦第二次。" + "text": "产品里放了个标记,后面的轮次看到它就不再拦第二次。" }, { "id": "p5-01", @@ -737,12 +722,12 @@ { "id": "p5-05", "scene": "P5", - "text": "第四层,一排插口:让扩展挂在外面,不侵入内核。" + "text": "官方给挽具的定义正好四件:循环、工具、上下文管理、护栏。" }, { "id": "p5-06", "scene": "P5", - "text": "四层里只有第一层是骨架,后三层都是挂件。" + "text": "这集拆的,正好填进前三格;第四格先空着,后面拆。" }, { "id": "p5-07", @@ -832,21 +817,21 @@ { "id": "p6-05", "scene": "P6", - "text": "这套东西往后还有更多层,那些就留到以后再拆。" + "text": "学会给挽具做加减法,这本身就是一门手艺。" }, { "id": "p6-06", "scene": "P6", - "text": "本片机制依据官方文档与公开工程实践,取数日期在画面上。" + "text": "本片机制依据官方文档,取数2026年8月,以官方最新表述为准。" }, { "id": "p6-07", "scene": "P6", - "text": "代码和行数取自它固定版本的仓库原文,链接在简介里。" + "text": "教学代码来自开源实现,行数均为实测,链接在简介。" }, { "id": "p6-08", "scene": "P6", - "text": "如果这让你对「AI 到底怎么动手」有了点具体的感觉,那就够了。" + "text": "下期,拆它怎么安排自己看到的东西:计划写在哪,活儿怎么分出去。" } ] diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md index 18693284..71a31721 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md @@ -14,16 +14,13 @@ > 画面:终端窗口,光标闪烁。用户提问逐字打出,模型回一条命令后画面凝住。 > 随后「复制 → 粘贴 → 复制 → 粘贴」三轮,把画面塞满灰色的搬运痕迹。 -- [p0-01] 你让 AI 看看项目里有哪些文件,再跑一下其中一个脚本。 -- [p0-02] 它想了想,写出一条命令,然后就停在那儿了。 -- [p0-03] 它不会自己去跑,也看不到跑完之后的结果。 -- [p0-04] 于是你复制这条命令,粘到终端里,敲回车, -- [p0-05] 再把满屏的输出复制一遍,粘回对话框。 -- [p0-06] 它接着想,又写出下一条;你再跑一遍,再贴一遍。 -- [p0-07] 这一来一回里,真正在中间搬东西的,是你。 -- [p0-08] 那么从「能写出这条命令」,到「它真的在你电脑上跑起来」, -- [p0-09] 中间缺的那一层到底是什么? -- [p0-10] 今天我们就把这一层拆开来看。 +- [p0-01] 你让 AI 跑个脚本:它把命令写好,然后就停在那儿了。 +- [p0-02] 复制、粘贴、回车、再把输出贴回去——每一轮的搬运工,是你。 +- [p0-03] 从「写出命令」到「真的跑起来」,缺的那一层,官方起了名字。 +- [p0-04] 名字就叫挽具:把动力源,套进一个可控的结构里。 +- [p0-05] 官方说得直白:这套东西是挽具,模型在挽具里面。 +- [p0-06] 挽具供给它五样东西:文件、命令、权限、记忆、护栏。 +- [p0-07] 这集就把这只挽具,一层一层拆开看。 ## P1 一个循环,就是全部 @@ -63,13 +60,13 @@ > 金句卡(serif):「别听它说『我说完了』,去看它手里还有没有活。」 > 角标:`stop_reason` is unreliable —— 第三方的源码分析 -- [p1-25] 教学版的循环身上只带一样东西:那份消息列表。 -- [p1-26] 而按第三方的源码分析,真实产品里带着十样,像十个抽屉。 -- [p1-27] 剩下九个管的是压缩进度、补救次数、钩子拦没拦过停机、轮数这些。 -- [p1-28] 有意思的是,几乎每个抽屉都对应后面的某一层机制。 -- [p1-29] 也就是说,循环没有长个,长出来的是它随身带的状态。 -- [p1-30] 退出的路子也一样——按他的说法,真实产品里有一大把: -- [p1-31] 报错、中断、钩子叫停、轮数到顶、预算烧完。 +- [p1-25] 官方给这个循环画过像:三件事交融着转—— +- [p1-26] 收集上下文、采取行动、验证结果,不是硬阶段。 +- [p1-27] 而且你随时可以打断它、补一句、让它改道。 +- [p1-28] 教学版身上只带一份消息列表;真实产品带着十样, +- [p1-29] 压缩进度、补救次数、钩子拦没拦过停机、轮数——细节进角标。 +- [p1-30] 循环没长个,长出来的是它随身带的状态。 +- [p1-31] 退出的路子也有一大把:报错、中断、钩子叫停、预算烧完。 - [p1-32] 但它们全是保护装置,不是骨架;骨架还是那二十来行。 ## P2 加一个工具,只改一行 @@ -127,14 +124,14 @@ - [p3-03] 你随口说一句「帮我把项目清理一下」, - [p3-04] 它完全可能给你递上一条把整块盘删干净的命令, - [p3-05] 而按前面的设计,循环会老老实实替它执行。 -- [p3-06] 所以安全不能指望模型自觉,得在执行之前由代码拦一道。 +- [p3-06] 官方把话说死了:权限由这层代码执行,不由模型执行。 - [p3-07] 拦法是三道闸门,顺序写死。 - [p3-08] 第一道是一张硬拒绝表:删根目录、提权、关机、格式化。 - [p3-09] 命中就直接挡回去,连问都不问。 - [p3-10] 第二道是规则匹配,管「看情况」的操作: - [p3-11] 读写工作目录之外的东西,或者命令里带着删除、改权限这类动作。 - [p3-12] 第三道就是问你:画面停下来,把工具名和参数摆给你看,等你点头。 -- [p3-13] 三道都没命中呢?直接放行——日常绝大多数操作走的都是这条路。 +- [p3-13] 三道都没命中呢?兜底永远再问你一句——弃权不等于放行。 - [p3-14] 教学版里有一句很诚实的话,我想念出来。 - [p3-15] 它说,这张拒绝表用的是最简单的字符串匹配, - [p3-16] 它的作用是告诉你「闸门应该装在哪儿」, @@ -148,19 +145,19 @@ - [p3-21] 按第三方的源码分析,结论不是三种,是四种。 - [p3-23] 多出来的第四种最有意思:工具选择不表态。 - [p3-24] 也就是说,弃权不等于放行,兜底永远是问你一句。 -- [p3-25] 而这些规则从哪儿来?他数出了八个地方—— -- [p3-26] 你自己的全局配置、项目配置、本地配置、功能开关、公司管理策略, -- [p3-27] 再加上启动参数、内联命令,和这次会话里的临时授权。 -- [p3-28] 八个来源难免打架,所以有优先级:越靠近「组织」的越大。 -- [p3-29] 公司策略压过本地配置。这一层,是给团队和企业留的。 +- [p3-25] 规则求值的顺序官方也写死了:拒绝、询问、放行, +- [p3-26] 头一个命中就出局——规则写得多具体,都改变不了顺序。 +- [p3-27] 所以一条宽拒绝,靠一条窄放行开不出例外。 +- [p3-28] 裸名拒绝更狠:整件工具从模型身上直接消失。 +- [p3-29] 就算全放行模式,也压不住一条写死的拒绝。 > 角标:user < project < local < flag < policy(+ cliArg / command / session)——第三方的源码分析 -- [p3-30] 他还写到一处很能说明工程品味的设计:自动批准。 -- [p3-31] 全都自动跑的模式下它不会每次弹窗, -- [p3-32] 而是先按更宽松的模式试判一遍,再查一张安全工具白名单, -- [p3-33] 最后才把这次调用和上下文交给一个小模型去判断。 -- [p3-34] 而且留了个刹车:小模型连着拒绝太多次,就退回人工审批。 +- [p3-30] 全自动模式不靠你点头的次数,靠另一个模型当闸门。 +- [p3-31] 官方遥测补一刀:权限提示,九成三都被点了批准。 +- [p3-32] 审判者的视野是做减法的:只看用户消息和裸命令。 +- [p3-33] 模型的自我辩解、工具的输出,全被剥在视野外。 +- [p3-34] 评它做了什么,不看它说了什么——注入的谎话骗不到它。 - [p3-35] 让模型帮忙看门,同时不敢把门全交给模型。 ## P4 挂在循环上,不写进循环里 @@ -196,24 +193,24 @@ > 金句卡(serif):「这个循环是故意保持无聊的。」 -- [p4-23] 真实产品里这样的时机有多少个? -- [p4-24] 按第三方的源码分析,二十七个—— -- [p4-25] 会话开始结束、权限被请求被拒绝、子任务启停、压缩前后、文件被改。 -- [p4-27] 但这一层真正的重点是另一件事:有人把它称为 -- [p4-28] 整个权限系统里最重要的一处安全设计。 -- [p4-29] 是这样:插口上的函数可以直接给出权限结论,说「这个我批了」。 -- [p4-30] 那它说批了,就真的放行吗?不。 -- [p4-31] 就算插口上的脚本说放行,配置里的禁止和询问仍然要再走一遍。 -- [p4-32] 方向是单向的:扩展点能加限制,不能解除限制。 -- [p4-33] 而教学版没有这一层。拆源码的人自己写下了这句评语: -- [p4-34] 这在教学里够用了,但放到生产环境,就是一个安全漏洞。 +- [p4-23] 真实产品里这样的时机,官方文档口径三十一个, +- [p4-24] 分三种节奏:会话一次、回合一次、每次调用前后。 +- [p4-25] 处理器也不只是跑脚本,还能让小模型单轮判决。 +- [p4-27] 表态的契约值得单独记:沉默,不等于批准—— +- [p4-28] 不吭声的意思是「我不作决定」,流程照走。 +- [p4-29] 插口上的函数说「这个我批了」,就真的放行吗?不。 +- [p4-30] 它的放行,仍要穿过后面的拒绝与询问两站。 +- [p4-31] 方向是单向的:扩展点能加限制,不能解除限制。 +- [p4-32] 而且这条单向,官方画成过六道闸门的流水线。 +- [p4-33] 教学版没有这一层,拆源码的人写下评语: +- [p4-34] 教学里够用,生产环境就是一个安全漏洞。 > 金句卡(serif):「扩展点能加限制,不能解除限制。」 > 角标:hook `allow` 不能绕过 settings 的 deny/ask —— 第三方的源码分析 -- [p4-35] 还有个小机关:那个能说「别停」的插口本身很危险, -- [p4-36] 它叫模型接着干,模型干完又要停,它又叫接着干,就转不出来了。 -- [p4-37] 据他所说,产品里放了个标记,后面的轮次看到它就不再拦第二次。 +- [p4-35] 那个能说「别停」的插口本身很危险——它叫模型接着干, +- [p4-36] 模型干完又要停,它又叫接着干,就转不出来了。 +- [p4-37] 产品里放了个标记,后面的轮次看到它就不再拦第二次。 ## P5 四层叠起来是什么 @@ -224,8 +221,8 @@ - [p5-02] 第一层,一个循环:反复问模型,替它执行,把结果搬回来。 - [p5-03] 第二层,一张分发表:让工具可以随便加。 - [p5-04] 第三层,三道闸门:让危险的事在执行之前被拦住。 -- [p5-05] 第四层,一排插口:让扩展挂在外面,不侵入内核。 -- [p5-06] 四层里只有第一层是骨架,后三层都是挂件。 +- [p5-05] 官方给挽具的定义正好四件:循环、工具、上下文管理、护栏。 +- [p5-06] 这集拆的,正好填进前三格;第四格先空着,后面拆。 - [p5-07] 这不是我的说法,是可以数出来的。 - [p5-08] 我把四章的代码逐一量过:整个程序从一百四十行出头, - [p5-09] 长到两百五十多行,长了八成; @@ -256,7 +253,7 @@ - [p6-02] 而是因为有人在它周围,搭了这几层结构。 - [p6-03] 循环给它手脚,分发表给它工具,闸门守着底线,插口留给你发挥。 - [p6-04] 这几层结构不神秘,加起来两百多行,一个下午能读完。 -- [p6-05] 这套东西往后还有更多层,那些就留到以后再拆。 -- [p6-06] 本片机制依据官方文档与公开工程实践,取数日期在画面上。 -- [p6-07] 代码和行数取自它固定版本的仓库原文,链接在简介里。 -- [p6-08] 如果这让你对「AI 到底怎么动手」有了点具体的感觉,那就够了。 +- [p6-05] 学会给挽具做加减法,这本身就是一门手艺。 +- [p6-06] 本片机制依据官方文档,取数2026年8月,以官方最新表述为准。 +- [p6-07] 教学代码来自开源实现,行数均为实测,链接在简介。 +- [p6-08] 下期,拆它怎么安排自己看到的东西:计划写在哪,活儿怎么分出去。 diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md index b2dfe631..782c7a98 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md @@ -1,4 +1,4 @@ -# 分镜:《拆开 Claude Code:让 AI 动手的四层机制》 +# 分镜:《执行层:一个循环,就是全部》 > 逐字稿 SSOT:[narration.md](./narration.md)(句 id 即本表的定位锚);视觉契约见 [planning.md](./planning.md) §三。 > 一镜(beat)= 2–8 句连续句子共享同一主画面;句区间必须**覆盖本幕每一句**(`check_script.py` 强制)。 @@ -13,10 +13,9 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| -| 0-A | p0-01..03 | 全屏终端窗口(`panel` 底 + `panelBorder` 框),顶栏三个灰点。用户提问以等宽字逐字打出,模型回一条 `find . -name "*.py"` 风格的命令 | 终端打字机(每字 2 帧)+ 光标 1s 周期闪烁;命令打完后光标**停止闪烁并变灰**,画面凝住 0.6s——"它停在那儿了"的视觉落点 | -| 0-B | p0-04..06 | 终端右侧浮出对话框。命令块与输出块之间出现灰色搬运轨迹:命令→终端、输出→对话框,往复三轮 | 每轮一条贝塞尔弧线扫过(0.5s),线尾留下半透明残影;三轮残影**累积不消失**,画面逐渐被灰色搬运痕迹填满 | -| 0-C | p0-07..08 | 灰色轨迹中央浮现一个人形剪影(`dim`),被两侧的搬运箭头夹住 | 人形以 `spring(damping:200)` 弹入并**微微下沉**(被压的感觉);主线问题以两行 `serif` 大字从底部淡入上移 | -| 0-D | p0-09..10 | 标题卡:片名 `serif` 大字(`core` 色),副标「工具与执行 · 四层机制」 | 灰色轨迹整体淡出→黑,标题字逐字浮现 + 底部 `core` 色细线自中心向两侧生长 | +| 0-A | p0-01..02 | 全屏终端窗口(`panel` 底 + `panelBorder` 框),顶栏三个灰点。命令打完光标变灰凝住;右侧对话框浮出 | 终端打字机(每字 2 帧);命令打完后光标**停止闪烁并变灰**,画面凝住 0.6s;p0-02 三轮「复制→粘贴→回车→回贴」搬运弧线**加速**塞满灰色残影(节奏比旧版快一倍) | +| 0-B | p0-03..05 | 全部搬运残影瞬间收束成一条外框线,包住一枚「模型」内核——**命名帧**:外框即挽具 | 外框自四面向内合拢包住内核(spring);「挽具」二字落框(serif 大字),英文 agentic harness 进角标;p0-05 官方引文条压上("Claude Code is the harness, Claude is the model" 中英并列淡入) | +| 0-C | p0-06..07 | 挽具供给图:外框上长出五根辐条(文件 / 命令 / 权限 / 记忆 / 护栏),内侧连着模型内核 | p0-06 五根辐条逐根点亮(`mech` 辉光各 8 帧);「记忆」那根先灰并浮「后面拆」小标;p0-07 外框整体轻旋一次,片名标题卡压入(`core` 色细线自中心向两侧生长) | ## P1 一个循环,就是全部 @@ -26,7 +25,7 @@ | 1-B | p1-08..12 | 环形循环缩至左侧 40%,右侧展开五步编号列表 + 一个 `messages[]` 面板 | 五步逐句点亮(每句一条,`FadeUp` 12px);每点亮一步,`messages[]` 面板**长高一格**并压入一个色块(用户句=dim / 模型回答=core / 工具结果=mech);第五步点亮后一条弧线从列表尾弹回第二步 | | 1-C | p1-13..16 | 全屏代码卡:`agent_loop` 的真实骨架(mono,约 12 行精简版),右下角计数「23」 | 代码逐行渲染(每行 3 帧);「二十三行」时行号列整体 `core` 辉光一次,计数器从 0 滚动到 23;p1-15/16 时画面左右分屏——左「模型:决定」右「脚手架:执行」,中间一条竖线 | | 1-D | p1-17..24 | 上半:模型回答的字符流从左向右逐字流出,其中一段 `mech` 色的「工具调用」块提前出现;下半:一个「停止原因」标记牌仍显示「进行中」,滞后一拍才翻牌 | 字符流以 12 字/秒流动;工具调用块出现时 `mech` 辉光;标记牌**延迟 25 帧**才翻转(视觉化「不可靠」);p1-22 时标记牌打上 `deny` 色斜叉;p1-24 金句卡 `serif` 居中淡入 | -| 1-E | p1-25..29 | 十个抽屉横向两排(5×2),每个抽屉正面标一个中文标签 + 右下角小字章号 | 第一个抽屉(消息列表)先 `core` 亮起并拉出;p1-26 起其余九个以 40ms 间隔依次 `mech` 亮起;p1-28 时每个抽屉右下的章号同时浮现(预告后续章节);p1-29 时十个抽屉整体后移、环形循环从抽屉后浮回前景且**尺寸与颜色完全不变** | +| 1-E | p1-25..29 | **三相环升级**:主环上浮现三个相位标签(收集 / 行动 / 验证)交融旋转;一只「手」图标随时可插入环上任意点;右侧十格抽屉墙以角标清单形式一闪 | 三个相位标签沿环依次点亮并**保持同时可见**(交融感,非硬阶段);p1-27 手图标落向环上一节点、环上光点被拨偏一档(人可打断);p1-28/29 十格抽屉墙快速亮起(20ms/格)后整体退至 40% 亮度、State 字段清单进角标 | | 1-F | p1-30..32 | 环形循环的「停机」出口分岔成五条细支线,各标一个退出原因;随后五条支线淡为 `dim`,只留主环 | 支线逐条以 `interpolate` 描线(每句一条);p1-32 时五条支线亮度降到 30% 并后移,主环 `core` 亮度不变——「它们是保护装置,不是骨架」 | ## P2 加一个工具,只改一行 @@ -51,8 +50,8 @@ | 3-C | p3-10..13 | 第二、三道闸门工作:一个请求穿过一道被标记,停在第三道前等待;另一个请求三道全过直接抵达执行口 | p3-10/11 请求光点穿过一闸后头顶浮出「看情况」标签;p3-12 第三道闸门前画面**整体降速并压暗**,弹出「工具名 + 参数」审批卡与 y/N 光标;p3-13 另一条通路上一个光点畅通无阻直达执行口,并在轨迹上留下 `core` 尾迹 | | 3-D | p3-14..19 | 拒绝表代码卡(mono,七个字符串)居中;随后表下方浮出原话引用 | p3-15 代码卡逐行渲染;p3-16/17 表的边框由 `deny` 变为 `dim` 虚线("示意"而非"边界"的视觉降级);p3-18 表右侧生成三条变体写法,逐条**绕过**表框飞向执行口;p3-19 金句卡 `serif` 居中 | | 3-E | p3-20..24 | 四个结果徽标呈四宫格:放行(`core`)、拒绝(`deny`)、问你(`mech`)、不表态(`dim` 描边) | p3-21 前三格先亮(对应三道闸门),第四格空着并有呼吸描边;p3-23 第四格亮起「不表态」;p3-24 从第四格拉出一条弧线**回连到「问你」格**,弧线上压「兜底」二字 | -| 3-F | p3-25..29 | 八个来源叠成一摞卡片(由下到上:全局 / 项目 / 本地 / 功能开关 / 公司策略),右侧三个旁路小卡(启动参数 / 内联命令 / 会话授权) | p3-26/27 卡片自下向上逐张堆叠(每张带 4px 纵向位移与投影);p3-28 一支箭头从底向顶穿过整摞并在「公司策略」处放大——`mech` 辉光;p3-29 顶部两张卡之间画一个"压过"符号,其余卡片降到 50% 亮度 | -| 3-G | p3-30..35 | 三级漏斗:宽松模式试判 → 安全白名单 → 小模型判断,末端一个「刹车」闸 | p3-31 漏斗三段描出;p3-32/33 一个请求光点依次穿过三段,每段命中就直接从侧边出口离开(不进下一段);p3-34 小模型段连续吐出三个 `deny` 叉后,末端刹车闸落下并把通路切回「人工审批」;p3-35 金句压底 | +| 3-F | p3-25..29 | **官方求值顺序流水线**:拒绝 → 询问 → 放行 三站闸门横排,一枚请求光点沿轨道行进 | 三站以 spring 落下(顺序点亮,每站 7 帧);「头一个命中,就出局」横幅压上;p3-27 光点在拒绝站被截获、`deny` 辉光 + 「出局」标签;p3-28 右下浮「裸名 deny → 整件工具从模型身上消失」(Bash 加删除线) | +| 3-G | p3-30..35 | **auto 分类器视野分屏**:五行记录自上而下滚入(辩解 / 工具结果 / 调用描述 / 用户消息 / 裸命令),前三行被划除,末两行金色高亮 | p3-31 五行逐条滚入;p3-32 前三行依次划除并各浮移除理由;p3-33 末两行染 `core` 高亮 + 「只看这两条」;p3-34 反例帧:一条伪装「用户早就批准了」的文本飞向视野、被 `deny` 色边界弹回;p3-35 金句压底 + 遥测角标(93%,官方 2026-03) | ## P4 挂在循环上,不写进循环里 @@ -63,8 +62,9 @@ | 4-C | p4-08..12 | 代码卡收回,五行杂活被「拔」出循环、变成五张回调卡浮在环外;环恢复原线宽 | p4-08 五行代码逐行飞出环外并变形为卡片(0.5s 形变);p4-09/10 环外浮出「时机 → 函数列表」两列表格;p4-11/12 环与卡片之间出现四个插座图形,一张卡片「啪」地插入(`spring` 过冲 + 插入瞬间 `mech` 闪一帧) | | 4-D | p4-13..19 | **插槽注册板**:环形循环外围四个插槽,按一整轮的时间顺序分布在环的四个方位 | 四个插槽逐句亮起并各插入对应回调卡:p4-14 入口槽(补背景信息的卡片飞入并在消息上加一小块 `mech` 补丁);p4-15/16 执行前槽——**P3 的三道闸门整体缩小、平移进这个槽**(跨幕视觉呼应),环上原本的检查标记同时消失;p4-17 执行后槽;p4-18/19 停机前槽亮 `core`,卡片返回一句话 → 一条回流箭头把它送回环的入口,环重新转起来 | | 4-E | p4-20..22 | 四个插槽同时点亮,环上标出四个时机点;环本身刻意**不加任何装饰** | 四点沿环依次脉冲一圈(顺时针,各 8 帧);p4-21 环上只浮出四个极简的喇叭图标("只喊一声");p4-22 金句卡;金句期间环继续匀速转动,不做任何强调动效——用"无动效"表达"故意保持无聊" | -| 4-F | p4-23..25 | **27 格事件矩阵**:9×3 网格,前四格已是 `mech` 实心(教学版覆盖),其余 23 格为 `panelBorder` 空框 | p4-24 计数器从 4 滚到 27,同时 23 个空框以 20ms 间隔快速点亮为半透明 `mech`;p4-25 被念到的几类事件所在格子加描边并浮出标签;矩阵右下角保留「4 / 27」比例条 | -| 4-G | p4-27..34 | 上下两层对撞:上层是插槽卡返回的「我批了」(`core` 印章),下层是配置文件里的「禁止 / 询问」(`deny` / `mech` 印章) | p4-29 上层印章落下并向下推进;p4-31 下层两枚印章升起**顶住**上层,接触处爆出一圈 `deny` 冲击波,上层印章被弹回;p4-32 画面中央生成一个单向箭头(只允许「加限制」方向通过,反向被 `deny` 挡板封住);p4-33/34 教学版一侧的这层挡板缺失、露出一个 `deny` 色缺口,缺口旁压第三方的评语 | +| 4-F | p4-23..25 | **31 事件 × 三层嵌套**(官方口径):外层会话框(一次)套中层回合框(×N)套内层工具调用链(工具前→执行→工具后→整批落定);右栏异步事件网格;右下计数徽章 | 外层成形→中层边框闪两下浮 ×N→内层虚线框内一个光点沿四节点链循环跑(80 帧一圈);右栏 6 个异步事件逐条打出;计数从 0 滚到 31(官方文档事件表逐行计数) | +| 4-G1 | p4-27..31 | **六道闸门流水线**(官方 SDK 权限判定图):hook/deny/ask/settings/mode/默认 六站横排,两端 Execute/Blocked 终点 | 轨道描出→一枚「我批了」光点出发→行至 deny 站被截入 Blocked(`deny` 辉光+冲击波);p4-31 切全放行模式重跑、光点仍在 deny 站被截 + 「全放行模式也一样:拒绝压得住」 | +| 4-G2 | p4-32..34 | **印章对撞**(保留高潮母题):「我批了」印章 vs 「禁止/询问」印章 + 单向箭头 | 印章落下对撞、持续抵抗抖动;单向箭头(只允许「加限制」方向);金句卡「扩展点能加限制,不能解除限制」收口 | | 4-H | p4-35..37 | 「别停」插槽与环的一段形成小闭环,反复自激;随后一枚标记落下把闭环打断 | p4-36 小闭环连转三圈,每圈提速一档、边缘 `deny` 色渐强(自激失控感);p4-37 一枚 `core` 色方形标记从上落下嵌入闭环,第四圈行进到标记处被**截断**,整体归于静止 | ## P5 四层叠起来是什么 @@ -81,4 +81,4 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 6-A | p6-01..04 | 壳的四层分别点亮并各配一句短标签(手脚 / 工具 / 底线 / 发挥) | 四层以每句一层的节奏点亮,点亮时对应标签 `FadeUp`;四层齐亮后整体轻微收拢一次(呼吸) | -| 6-B | p6-05..08 | 信源卡:官方文档 + 取数日期 / 第三方源码分析已逐处标注;随后系列身份卡;**渐黑** | 信源卡逐行浮现(mono 小字);系列身份卡 `serif` 淡入;**渐黑窗口从本 beat 的总时长推导**(`beatDurationInFrames`,不是末句时长——第三集上线教训,见 skills/06 红线四),末 1.2s 线性压暗到全黑 | +| 6-B | p6-05..08 | 信源卡四行(官方文档+取数日期 / 工程博客 / 源码分析已逐处标注 / 数字均为实测口径)+ 版本护栏行 → 系列身份卡 + **下期预告卡**(读 series.json,标题只在画面) → **渐黑** | 信源卡逐行浮现(mono 小字);系列身份卡 `serif` 淡入;下期卡 `panel` 底描边框浮现(「下期 · 规划层」+ 标题);**渐黑窗口从本 beat 的总时长推导**(`beatDurationInFrames`,红线四),末 1.2s 线性压暗到全黑 | diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx index 25d8568e..aaf39f09 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx @@ -1,5 +1,6 @@ -/** P0 你在当那个中间人(分镜 0-A…0-D) - * 痛点:模型写出命令就停住,人在做复制粘贴的中间层。 */ +/** P0 钩子与命名帧(分镜 0-A…0-C) + * 三句内完成:搬运工痛点 → 官方命名「挽具」→ 五辐条供给图。 + * 改造(2026-08 Harness Engineering):10 句压缩为 7 句,命名帧是全系列的开场锚。 */ import React from 'react'; import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoConfig} from 'remotion'; import {theme} from '../design/theme'; @@ -7,93 +8,36 @@ import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; import {Footnote, Panel, Terminal} from '../components/motifs'; -/** 0-A 终端打字 → 模型吐出一条命令后画面凝住;右侧走秒芯片在凝住点停死 */ -const AskAndStall: React.FC<{freezeAt: number}> = ({freezeAt}) => { +/** 0-A 终端打字 → 命令凝住 → 复制粘贴弧线加速塞满(两句内完成旧版六句的信息量) */ +const StallAndCarry: React.FC<{carryAt: number}> = ({carryAt}) => { const frame = useCurrentFrame(); - const {fps} = useVideoConfig(); - const frozen = frame >= freezeAt; - // 「想了想」的计时:打字期间正常走秒,凝住瞬间停死——把 p0-02 的「停在那儿了」量化成画面 - const elapsed = frozen ? freezeAt : frame; - const secs = Math.floor((elapsed / fps) * 2) / 2; // 0.5s 步进,减少帧内数字抖动 + const W = 1560; + const H = 400; + const frozen = frame >= carryAt - 6; + // 三轮搬运轨迹(加速:每轮 9 帧,旧版是 15 帧——钩子提速) + const roundGap = [0, 9, 18]; return ( -
+
-
-
- {`${secs.toFixed(1)}s`} -
-
- {frozen ? '计时停了' : '它还在想'} -
-
-
- - ); -}; - -/** 0-B 复制粘贴往复三轮:灰色搬运痕迹累积不消失 + 轮次钢印 + 剪贴板逐轮老化 */ -const CopyPasteLoop: React.FC<{roundStarts: number[]}> = ({roundStarts}) => { - const frame = useCurrentFrame(); - const W = 1560; - const H = 430; - return ( - -
- -
终端
-
- -
对话框
-
+ {/* 搬运弧线:命令→终端、输出→对话框,三轮残影累积 */} - {roundStarts.map((s, i) => { - // 一轮 = 命令右→左(贴进终端) + 输出左→右(贴回对话框) + {roundGap.map((gap, i) => { + const base = carryAt + gap; const legs = [ - {a: W - 640, b: 300, y: 120 + i * 26, dir: -1}, - {a: 300, b: W - 640, y: 250 + i * 26, dir: 1}, + {a: W - 300, b: 300, y: 90 + i * 22, dir: -1}, + {a: 300, b: W - 300, y: 240 + i * 22, dir: 1}, ]; return legs.map((lg, k) => { - const t = interpolate(frame - s - k * 15, [0, 15], [0, 1], { + const t = interpolate(frame - base - k * 6, [0, 9], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); @@ -101,247 +45,323 @@ const CopyPasteLoop: React.FC<{roundStarts: number[]}> = ({roundStarts}) => { const x = lg.a + (lg.b - lg.a) * t; return ( - {/* 残影:已走过的轨迹留下不消失的灰痕 */} - - + + ); }); })} - {/* 轮次钢印:每开始一轮,右上角落下一枚 01/02/03——「你」的劳动被计数 */} - {roundStarts.map((s, i) => { - const drop = spring({ - frame: frame - s, - fps: 30, - config: {damping: 200}, - }); - if (frame < s) return null; - return ( -
- {String(i + 1).padStart(2, '0')} -
- ); - })} - {/* 剪贴板:板身恒定,板上的搬运痕迹随轮次变淡(见下方 line 的 0.3 - i*0.06) - ——搬运这件事件件在耗损你 */} - - - - {roundStarts.map((s, i) => - frame > s + 20 ? ( - - ) : null, - )} - + {frozen ? ( +
+ {'每一轮的搬运工,是你'} +
+ ) : null}
- {'你 = 模型与终端之间的搬运层'}
); }; -/** 0-C 人形剪影被两侧箭头夹住并微微下沉 + 主线问题浮现 */ -const YouInTheMiddle: React.FC<{questionAt: number}> = ({questionAt}) => { +/** 0-B 命名帧:搬运残影收束成外框,包住「模型」内核——外框即挽具 + 官方引文条 */ +const NamingFrame: React.FC<{officialAt: number}> = ({officialAt}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); - const enter = spring({frame, fps, config: {damping: 200}}); - const sink = interpolate(frame, [10, 44], [0, 14], { + // 外框四面合拢(spring 收拢感) + const close = spring({frame, fps, config: {damping: 180}}); + const CX = 960; + const CY = 460; + const full = 420; + const wHalf = full / 2 + (1 - close) * 620; + const hHalf = full / 2 + (1 - close) * 380; + const label = interpolate(frame - 22, [0, 14], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); - const qo = interpolate(frame - questionAt, [0, 22], [0, 1], { + const quote = interpolate(frame - officialAt, [0, 18], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); + // 呼吸辉光(命名帧的「仪式感」) + const breathe = 0.5 + 0.5 * Math.sin(frame / 26); return ( - + + {/* 四面合拢的残影 → 外框 */} + + + {/* 四角的旧搬运残影淡出(收束感) */} + {[ + [-1, -1], + [1, -1], + [-1, 1], + [1, 1], + ].map(([sx, sy], i) => { + const o = interpolate(frame, [0, 18], [0.35, 0], {extrapolateRight: 'clamp'}); + return ( + + ); + })} + + {/* 内核:模型 */}
- - - - - {/* 载荷:左来的命令芯片(右向)与右来的输出块(左向)都压在你手上—— - 「搬运」在第一眼就成立,不靠字幕解释 */} - {[ - {dir: -1, label: '命令', y: 96}, - {dir: 1, label: '输出', y: 168}, - ].map((p) => { - const o = interpolate(frame - 14, [0, 12], [0, 1], { - extrapolateLeft: 'clamp', - extrapolateRight: 'clamp', - }); - const x = 140 + p.dir * 128; - return ( - - - - - {p.label} - - - ); - })} - - +
+ {'模型 Claude'} +
+
+ {'判断力在里面'} +
+ {/* 「挽具」落框 */}
+ {'挽 具'} +
+
- {'从「能写出这条命令」,'} -
- {'到「它真的在你电脑上跑起来」——'} + {'把动力源,套进一个可控的结构里'}
+ {/* 官方引文条(p0-05 句锚) */} + {quote > 0 ? ( +
+ +
+ {'“Claude Code 是挽具,Claude 是里面的模型。”'} +
+
+ {'— 官方文档 how-claude-code-works(code.claude.com,取数2026年8月)'} +
+
+
+ ) : null}
); }; -/** 0-D 标题卡 */ -const TitleCard: React.FC = () => { +/** 0-C 五辐条供给图:外框上长出五根辐条(文件/命令/权限/记忆/护栏)+ 标题卡收尾 */ +const SupplySpokes: React.FC<{titleAt: number}> = ({titleAt}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); - const enter = spring({frame: frame - 6, fps, config: {damping: 200}}); - const line = interpolate(frame, [18, 48], [0, 1], { + const CX = 960; + const CY = 440; + const R = 300; + const spokes = [ + {label: '文件', zh: '读写项目'}, + {label: '命令', zh: '执行与回传'}, + {label: '权限', zh: '闸门与审批'}, + {label: '记忆', zh: '上下文与规则', later: true}, + {label: '护栏', zh: '拦截与兜底'}, + ]; + const title = spring({frame: frame - titleAt, fps, config: {damping: 200}}); + const line = interpolate(frame - titleAt, [4, 40], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const ring = interpolate(frame, [0, 16], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); return ( - -
-
- {'执行层:一个循环,就是全部'} -
+ + + {/* 外框(挽具轮廓,缩小型持续在场) */} + + + {'模型 Claude'} + + {/* 五辐条:自外框上沿五点连向内核 */} + {spokes.map((sp, i) => { + const t = interpolate(frame - 6 - i * 8, [0, 12], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + if (t <= 0) return null; + // 五点沿外框上沿分布 + const fx = CX - 300 + i * 150; + const fy = CY - 250; + const ix = CX + (fx - CX) * 0.24; + const iy = CY - 40; + const glow = sp.later ? 0 : 0.5 + 0.5 * Math.sin((frame - i * 8) / 9); + return ( + + + + + {sp.label} + + + {sp.zh} + + + ); + })} + {/* 「记忆」辐条的「后面拆」小标 */} + {(() => { + const o = interpolate(frame - 6 - 3 * 8 - 10, [0, 10], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + return o > 0 ? ( + + {'后面单独拆'} + + ) : null; + })()} + + {/* 标题卡(p0-07 收尾压入) */} + {title > 0 ? (
- {'让 AI 动手的四层机制'} -
-
-
- {'工具与执行 · 四章'} +
+ {'执行层:一个循环,就是全部'} +
+
+
+ {'Claude Code Harness Engineering · 执行层'} +
-
+ ) : null} ); }; export const P0Hook: React.FC<{scene: SceneRange}> = ({scene}) => { const w = (fromId: string, toId?: string) => beatWindow(scene.sentences, scene.from, fromId, toId); - // at() = 时点锚(只取某句的起始帧,不是分镜 beat 窗口)。刻意不叫 w()—— - // check_script --check-scenes 只把 w() 视为分镜窗口,混用会让时点锚刷「分镜陈旧」假 WARN。 const at = (id: string) => w(id).from; - const bA = w('p0-01', 'p0-03'); - const bB = w('p0-04', 'p0-06'); - const relB = (id: string) => at(id) - bB.from; - const bC = w('p0-07', 'p0-08'); + const bA = w('p0-01', 'p0-02'); + const bB = w('p0-03', 'p0-05'); + const bC = w('p0-06', 'p0-07'); return ( - - {/* 凝住点落在 p0-03「它不会自己去跑」——光标停闪变灰 */} - - - - + + - - + + - - + + ); diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx index 50606577..9dede254 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx @@ -318,101 +318,154 @@ const UnreliableFlag: React.FC<{crossAt: number; quoteAt: number}> = ({crossAt, ); }; -/** 1-E 十个抽屉:第一个先亮,其余九个依次亮,末尾浮出章号 */ -const TenDrawers: React.FC<{restAt: number; chapterAt: number; recedeAt: number}> = ({ - restAt, - chapterAt, +/** 1-E 三相环 + 人的打断针 + State 十格抽屉墙(Harness Engineering 改造版) + * 官方三相:收集上下文 / 采取行动 / 验证结果——交融旋转,不是硬阶段; + * 手图标随时落向环上节点(人可打断);右侧十格抽屉墙以角标清单形式一闪。 */ +const ThreePhaseRing: React.FC<{phaseAt: number; handAt: number; drawersAt: number; recedeAt: number}> = ({ + phaseAt, + handAt, + drawersAt, recedeAt, }) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); - // 钩子必须无条件调用:环在 recede 之后才渲染,故进度值先取出来再按需使用 const dot = useRingDot(2.5); - // 章号只是「每个抽屉都指向后面某一章」的视觉证据,不进口播(活数据纪律) - const drawers = [ - {label: '消息列表', ch: '循环'}, - {label: '工具与权限上下文', ch: '工具'}, - {label: '压缩状态追踪', ch: '压缩'}, - {label: '输出补救次数', ch: '补救'}, - {label: '本轮是否压缩过', ch: '压缩'}, - {label: '输出上限覆盖', ch: '补救'}, - {label: '后台摘要', ch: '压缩'}, - {label: '钩子拦过停机', ch: '钩子'}, - {label: '轮数计数', ch: '循环'}, - {label: '上次继续原因', ch: '补救'}, + const phases = [ + {label: '收集上下文', zh: '读文件 · 搜代码', ang: -90}, + {label: '采取行动', zh: '改文件 · 跑命令', ang: 30}, + {label: '验证结果', zh: '看输出 · 再补一刀', ang: 150}, ]; const recede = interpolate(frame - recedeAt, [0, 24], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); - const chOn = interpolate(frame - chapterAt, [0, 16], [0, 1], { + const hand = spring({frame: frame - handAt, fps, config: {damping: 170}}); + const drawerOn = interpolate(frame - drawersAt, [0, 30], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); + const CX = 560; + const CY = 500; + const R = 250; return ( - +
- {drawers.map((d, i) => { - const at = i === 0 ? 0 : restAt + (i - 1) * 4; - const on = frame >= at; - const e = spring({frame: frame - at, fps, config: {damping: 200}}); - const first = i === 0; + +
+ + {/* 三个相位标签:沿环依次点亮并保持同时可见(交融感) */} + {phases.map((ph, i) => { + const on = interpolate(frame - phaseAt - i * 10, [0, 12], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const rad = (ph.ang * Math.PI) / 180; + const lx = CX + Math.cos(rad) * (R + 96); + const ly = CY + Math.sin(rad) * (R + 96); + const nodeX = CX + Math.cos(rad) * R; + const nodeY = CY + Math.sin(rad) * R; return ( -
- -
- {String(i + 1).padStart(2, '0')} -
-
- {d.label} -
-
- {d.ch} -
-
-
+ + + + + {ph.label} + + + {ph.zh} + + ); })} -
- {/* 抽屉后移后,环形循环浮回前景——尺寸与颜色完全不变 */} - {recede > 0.2 ? ( -
- + {/* 「交融」标注:三段弧互相咬合(非硬阶段) */} + {frame > phaseAt + 34 ? ( + + {'三相互相交融——不是硬阶段'} + + ) : null} + {/* 人的手:落向「行动」节点,环上光点被拨偏一档 */} + {hand > 0 ? ( + + + + + {'你,随时插入'} + + + ) : null} + + {/* 右侧十格抽屉墙(State 字段,角标清单形式) */} +
+
+ {'真实产品随身带的状态(十样)'}
- ) : null} - {'State 10 字段 —— 第三方的源码分析'} +
+ {[ + '消息列表', + '工具与权限上下文', + '压缩状态追踪', + '输出补救次数', + '本轮是否压缩过', + '输出上限覆盖', + '后台摘要', + '钩子拦过停机', + '轮数计数', + '上次继续原因', + ].map((label, i) => { + const e = interpolate(frame - drawersAt - i * 2, [0, 8], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + return ( +
+ {label} +
+ ); + })} +
+
+ {'三相与打断 —— 官方文档 how-claude-code-works · State 字段为第三方的源码分析'} ); }; @@ -499,8 +552,8 @@ export const P1Loop: React.FC<{scene: SceneRange}> = ({scene}) => { - - + + diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx index 7eca6d6b..7169694d 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx @@ -427,258 +427,262 @@ const FourResults: React.FC<{fourthAt: number; arcAt: number}> = ({fourthAt, arc ); }; -/** 3-F 八个来源叠成一摞 + 优先级箭头 */ -const EightSources: React.FC<{stackAt: number; arrowAt: number; overrideAt: number}> = ({ - stackAt, - arrowAt, - overrideAt, +/** 3-F 官方求值顺序:拒绝 → 询问 → 放行,首中即出局(Harness Engineering 改造版) + * 官方语义:三类规则按固定顺序求值、第一个命中即出局、规则具体度不改顺序; + * 裸名 deny 把整件工具从模型身上移除;拒绝连全放行模式都压得住。 */ +const EvalOrder: React.FC<{orderAt: number; ballAt: number; denyHitAt: number; nakedAt: number}> = ({ + orderAt, + ballAt, + denyHitAt, + nakedAt, }) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); - const stack = ['你的全局配置', '这个项目的配置', '本地配置', '功能开关', '公司管理策略']; - const side = ['启动参数', '内联命令', '会话授权']; - const arrow = interpolate(frame - arrowAt, [0, 26], [0, 1], { + const stations = [ + {t: '拒绝 deny', c: 'deny', sub: '命中即出局'}, + {t: '询问 ask', c: 'mech', sub: '命中即出局'}, + {t: '放行 allow', c: 'core', sub: '兜底到它'}, + ]; + // 光点沿三站行进;在第二幕演示里被第①站截获 + const travel = interpolate(frame - ballAt, [0, 46], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const hit = frame >= denyHitAt; + const naked = frame >= nakedAt; + const orderOn = interpolate(frame - orderAt, [0, 20], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); - const over = frame >= overrideAt; + const PX = 300; // 轨道起点 + const GAP = 380; return ( - // gap 须容纳左栏右侧外挂的「压过」括号(宽 128)+ 呼吸间距 - -
- {/* stack 按优先级**升序**声明(user < project < local < flag < policy)。 - 画面必须与口播「越靠近组织越大 / 公司策略压过本地配置」一致,故**倒序渲染**: - 最高优先级的公司管理策略在最上方。此前正序渲染 + 高亮首项,等于让画面 - 宣称「全局配置最大」,与旁白相反。 */} - {[...stack].reverse().map((s, r) => { - const prio = stack.length - 1 - r; // 0=最低(全局配置)… 4=最高(公司策略) - const at = stackAt + r * 7; // 自上而下依次落位(先出现最高优先级) + +
+ + {/* 主轨道 */} + + {/* 首中即出局横幅(顺序点亮后压上) */} + {orderOn > 0.9 ? ( + + {'头一个命中,就出局'} + + ) : null} + {/* 请求光点:被第①站截获 */} + {(() => { + const x = PX + (GAP * 2 + 200) * travel; + const cutX = PX + GAP * 0.5; + const stopped = hit && travel > (GAP * 0.5) / (GAP * 2 + 200); + const finalX = stopped ? cutX : x; + return ( + + {!stopped ? ( + + ) : null} + + {stopped ? ( + + {'出局'} + + ) : null} + + ); + })()} + + {/* 三站闸门 */} + {stations.map((st, i) => { + const at = orderAt + 4 + i * 7; const e = spring({frame: frame - at, fps, config: {damping: 200}}); - const isHighest = prio === stack.length - 1; - // 收束时只留口播点名的两级亮着:公司管理策略(最高,prio 4)与本地配置(prio 2) - const dimmed = over && prio !== stack.length - 1 && prio !== 2; + const color = st.c === 'deny' ? theme.deny : st.c === 'mech' ? theme.mech : theme.core; return (
- 0.85 ? theme.mech : theme.panelBorder} - style={{ - padding: '16px 22px', - boxShadow: '0 6px 16px rgba(0,0,0,0.35)', - background: isHighest && arrow > 0.85 ? theme.mechDeep : theme.panel, - }} - > - {/* 「越靠近组织越大」用亮度阶梯编码(不用色相——反枚举原则): - 优先级越高越亮,静帧上也读得出层级 */} - - {s} - + +
{st.t}
+
{st.sub}
+ {/* 站上竖闸 */} + + + +
); })} - {/* 优先级箭头:自下(最低)指向上(最高),与倒序堆叠后的画面一致 */} - {arrow > 0 ? ( - - - 0.2 ? 1 : 0} - /> - {arrow > 0.9 ? ( - - {'优先级'} - - ) : null} - - ) : null} - {/* 「压过」跨越第 1 行(公司管理策略)到第 3 行(本地配置)——即口播点名的那一对。 - 纵向连线让「谁压过谁」在静帧上也明确,不靠观众自己配对。 */} - {over ? ( -
- - - - -
- {'压过'} -
-
- ) : null} -
-
-
- {'另有三个旁路'} -
- {side.map((s, i) => ( - - {s} - - ))} + + {'Bash'} + + {'→'} + + {'整件工具,从模型身上消失'} + +
+ ) : null}
- - {'user < project < local < flag < policy —— 第三方的源码分析'} + + {'deny → ask → allow 首中即出局 · 裸名 deny 移除整件工具 —— 官方文档 permissions'}
); }; -/** 3-G 自动批准三级漏斗 + 末端刹车 */ -const AutoApprove: React.FC<{funnelAt: number; travelAt: number; brakeAt: number}> = ({ - funnelAt, - travelAt, - brakeAt, +/** 3-G auto 分类器视野分屏:审判者只看用户消息与裸命令(Harness Engineering 改造版) + * 官方工程博客:模型的自我辩解、工具结果、调用描述全被剥在视野外—— + * 评它做了什么,而非它说了什么;网页注入的文本骗不到审判者。 */ +const ClassifierVision: React.FC<{scrollAt: number; stripAt: number; goldenAt: number; spoofAt: number}> = ({ + scrollAt, + stripAt, + goldenAt, + spoofAt, }) => { const frame = useCurrentFrame(); - const stages = [ - {t: '按更宽松的模式试判', w: 900}, - {t: '查安全工具白名单', w: 700}, - {t: '交给一个小模型判断', w: 500}, + const rows = [ + {t: '模型的自我辩解:我确认这是安全的操作', why: '辩解不看', strike: true}, + {t: '工具结果:tests/ 42 passed, 0 failed', why: '结果不看', strike: true}, + {t: '工具调用描述:准备执行 npm install', why: '描述不看', strike: true}, + {t: '用户消息:帮我把依赖装上', why: '', strike: false}, + {t: '裸命令:npm install --save-dev vitest', why: '', strike: false}, ]; - const braked = frame >= brakeAt; - //: 漏斗最宽一级的宽度——「命中即出」标签统一挂在这个右边界上 - const WIDEST = 900; + const spoofOn = frame >= spoofAt; + const golden = interpolate(frame - goldenAt, [0, 18], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); return ( -
- {stages.map((s, i) => { - const at = funnelAt + i * 10; - const on = frame >= at; - const passing = frame >= travelAt + i * 14 && frame < travelAt + i * 14 + 14; - return ( -
- - {s.t} - - {/* 「命中即出」:三条标签左端统一在 WIDEST 右侧,读作同一个侧向出口 */} - {on ? ( -
+
+ {'审判者的视野:先做减法'} +
+
+ {rows.map((r, i) => { + const at = scrollAt + i * 9; + const e = interpolate(frame - at, [0, 12], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const stricken = r.strike && frame >= stripAt + i * 6; + return ( +
+ 0.5 ? theme.core : theme.panelBorder} style={{ - position: 'absolute', - left: WIDEST + 34, - top: 22, - whiteSpace: 'nowrap', - fontFamily: theme.sans, - fontSize: 21, - color: theme.core, + padding: '13px 22px', + flex: 1, + background: !r.strike && golden > 0.5 ? theme.coreDeep : theme.panel, }} > - {'→ 命中即出'} -
- ) : null} -
- ); - })} -
- {[0, 1, 2].map((i) => { - const at = brakeAt - 30 + i * 9; - return ( - = at ? 1 : 0, - }} - > - {'✗'} - + + {r.t} + + + {r.strike ? ( + + {r.why} + + ) : ( + + {'只看这两条'} + + )} +
); })}
- {braked ? ( - - - {'退回人工审批'} - - + {/* 反例帧:伪装的「用户早就批准了」被视野边界弹回 */} + {spoofOn ? ( + + {(() => { + const t2 = interpolate(frame - spoofAt, [0, 30], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const x = 200 + t2 * 900; + const rejected = t2 > 0.75; + return ( + + + {t2 < 0.75 ? ( + + 「用户早就批准了这个操作」 + + ) : null} + {rejected ? ( + + {'弹回:不是用户消息'} + + ) : null} + + ); + })()} + ) : null}
- {'让模型帮忙看门,但不敢把门全交给模型'} + + {'93% 提示被批准(官方遥测 2026-03)· 视野裁剪 —— 官方工程博客 claude-code-auto-mode'} + ); }; @@ -721,18 +725,20 @@ export const P3Gates: React.FC<{scene: SceneRange}> = ({scene}) => { - - + - - + diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx index 56238224..d7440335 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx @@ -359,72 +359,162 @@ const BoringOnPurpose: React.FC<{quoteAt: number}> = ({quoteAt}) => { ); }; -/** 4-F 27 格事件矩阵:4 格已实心,23 格快速点亮 */ -const EventMatrix: React.FC<{countAt: number; labelAt: number}> = ({countAt, labelAt}) => { +/** 4-F 31 事件 × 三节奏三层嵌套(Harness Engineering 改造版,官方文档口径) + * 三层嵌套:外层 = 会话(一次)、中层 = 回合(每轮一次)、内层 = 工具调用(每次前后)。 + * 计数徽章滚到 31;右栏异步事件(不入嵌套的独立时机)。 */ +const HookNesting: React.FC<{outerAt: number; midAt: number; innerAt: number; countAt: number; asyncAt: number}> = ({ + outerAt, + midAt, + innerAt, + countAt, + asyncAt, +}) => { const frame = useCurrentFrame(); - const names = [ - 'PreToolUse', 'PostToolUse', 'PostToolUseFailure', - 'SessionStart', 'SessionEnd', 'Stop', 'StopFailure', 'Setup', - 'UserPromptSubmit', 'Notification', 'PermissionRequest', 'PermissionDenied', - 'SubagentStart', 'SubagentStop', - 'PreCompact', 'PostCompact', - 'TeammateIdle', 'TaskCreated', 'TaskCompleted', - 'Elicitation', 'ElicitationResult', 'ConfigChange', 'WorktreeCreate', - 'WorktreeRemove', 'InstructionsLoaded', 'CwdChanged', 'FileChanged', - ]; - // 教学版覆盖的四个 - const taught = new Set(['PreToolUse', 'PostToolUse', 'Stop', 'UserPromptSubmit']); - const highlighted = new Set([ - 'SessionStart', 'SessionEnd', 'PermissionRequest', 'PermissionDenied', - 'SubagentStart', 'SubagentStop', 'PreCompact', 'PostCompact', 'FileChanged', - ]); + const {fps} = useVideoConfig(); + // 三层依次成形的进度 + const o = interpolate(frame - outerAt, [0, 16], [0, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}); + const m = interpolate(frame - midAt, [0, 16], [0, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}); + const i = interpolate(frame - innerAt, [0, 16], [0, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}); + // 内层光点沿「工具前→执行→工具后→整批落定」跑一圈 + const lap = ((frame - innerAt) % 80) / 80; + const lapOn = frame >= innerAt + 16; + const asyncEvents = ['会话开始', '会话结束', '配置变更', '目录切换', '文件被改', '通知']; return ( -
- {names.map((n, i) => { - const isTaught = taught.has(n); - const at = countAt + i * 2; - const on = isTaught || frame >= at; - const lab = frame >= labelAt && highlighted.has(n); - return ( +
+ {/* 外层:会话框 */} +
+
+ {'会话 Session'} + + {'一次'} + +
+ {/* 中层:回合框(×N 视觉重复) */} +
+
+ {'回合 Turn'} + {'×N'} + {'每轮一次'} +
+ {/* 内层:工具调用链 */}
- { + const active = lapOn && lap > k / 4 && lap < (k + 1) / 4; + return ( + + {k > 0 ? ( + + + + + ) : null} + + {s} + + + ); + })} +
+
+
+ {/* 右栏:异步事件 */} +
+
+ {'另有独立的时机(异步)'} +
+
+ {asyncEvents.map((e, k) => ( +
- {n} - -
- ); - })} -
-
- - - {'个时机(教学版只讲了 4 个)'} - + {e} +
+ ))} +
+
+ {/* 计数徽章 */} +
+ + {'个时机'} +
- {'27 hook events —— 第三方的源码分析'} + + {'31 个 hook 事件 × 三种节奏 —— 官方文档 hooks reference(事件表逐行计数,取数2026年8月)'} +
); }; @@ -569,6 +659,117 @@ const StampClash: React.FC<{ ); }; +/** 4-G' 六道闸门流水线(官方 SDK 权限判定图):hook 的放行仍要穿过后面的 deny/ask 两站 + * 官方把权限判定画成六站;本片高潮句「扩展点能加限制,不能解除限制」的官方背书。 */ +const SixGatePipeline: React.FC<{railAt: number; runAt: number; yoloAt: number}> = ({railAt, runAt, yoloAt}) => { + const frame = useCurrentFrame(); + const stations = [ + {t: 'hook', sub: '扩展点'}, + {t: 'deny', sub: '拒绝'}, + {t: 'ask', sub: '询问'}, + {t: 'settings', sub: '配置'}, + {t: 'mode', sub: '模式'}, + {t: '默认', sub: '兜底问你'}, + ]; + const rail = interpolate(frame - railAt, [0, 22], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const travel = interpolate(frame - runAt, [0, 50], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const yolo = frame >= yoloAt; + // 两轮演示:第一轮光点在 deny 站被截;第二轮(全放行模式)仍在 deny 站被截 + const cutAt = 1 / 6 + 0.5 / 6; + const stopped = travel > cutAt; + const PX = 160; + const GAP = 260; + const ballX = PX + (GAP * 5) * Math.min(travel, cutAt); + return ( + +
+ + + {/* 两端终点:Execute / Blocked */} + {rail > 0.8 ? ( + <> + + + Execute + + + + Blocked + + + ) : null} + {/* 请求光点 */} + {rail > 0.8 ? ( + <> + + {!stopped ? ( + + ) : ( + + )} + + ) : null} + + {/* 六站 */} + {stations.map((st, i) => { + const at = railAt + 6 + i * 4; + const e = interpolate(frame - at, [0, 10], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const isDeny = st.t === 'deny'; + const bypassed = yolo && (st.t === 'mode'); + return ( +
+ + + + +
{st.t}
+
{st.sub}
+
+ ); + })} + {yolo ? ( +
+ {'全放行模式也一样:拒绝压得住'} +
+ ) : null} +
+ + {'六道闸门判定顺序 —— 官方 Agent SDK permissions 文档'} + +
+ ); +}; + /** 4-H 自激小闭环,被一枚标记截断 */ const SelfLoopBreak: React.FC<{spinAt: number; markAt: number}> = ({spinAt, markAt}) => { const frame = useCurrentFrame(); @@ -652,7 +853,8 @@ export const P4Hooks: React.FC<{scene: SceneRange}> = ({scene}) => { const bD = w('p4-13', 'p4-19'); const bE = w('p4-20', 'p4-22'); const bF = w('p4-23', 'p4-25'); - const bG = w('p4-27', 'p4-34'); + const bG1 = w('p4-27', 'p4-31'); + const bG2 = w('p4-32', 'p4-34'); const bH = w('p4-35', 'p4-37'); return ( @@ -675,16 +877,19 @@ export const P4Hooks: React.FC<{scene: SceneRange}> = ({scene}) => { - - + + + + + - + diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx index 26499115..c0815c89 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx @@ -260,6 +260,23 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}>
{'让 AI 动手的四层机制'}
+ {/* 下期预告卡:读 series.json 顺序(标题只在画面,口播为话题描述——反串线纪律) */} +
+
+ {'下期 · 规划层'} +
+
+ {'模型的视野是安排出来的'} +
+
) : null} {/* 渐黑遮罩 */} diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json index cbcaec74..a986536a 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json @@ -2,17 +2,12 @@ { "id": "p0-01", "scene": "P0", - "text": "它正在干活,突然,停了。屏幕上一行报错,活干到一半,人愣在原地。" + "text": "它正在干活,突然,停了。一个小时的活,一行报错,全部作废。" }, { "id": "p0-02", "scene": "P0", - "text": "不是它不想干,是服务那边把它拒收了。拒收,是必然发生的日常。" - }, - { - "id": "p0-03", - "scene": "P0", - "text": "拒收的理由很直白:你随身带的东西太大了,我装不下。" + "text": "不是它不想干,是服务那边拒收了——理由直白:你随身带的,太大了。" }, { "id": "p0-04", @@ -42,17 +37,17 @@ { "id": "p0-09", "scene": "P0", - "text": "而且这不是意外,是必然:只要活干得够久、项目够大,窗口一定会满。" + "text": "官方实测还补了一刀:窗口越长,它记得反而越不准——注意力被摊薄了。" }, { "id": "p0-10", "scene": "P0", - "text": "那满了怎么办?直觉答案是「删掉一点不就行了」。" + "text": "所以满了怎么办?直觉答案是删掉一点。" }, { "id": "p0-11", "scene": "P0", - "text": "但删什么、先删谁、删错了会发生什么——这里面全是工程。" + "text": "但删什么、先删谁——这里面全是工程。" }, { "id": "p0-12", @@ -172,12 +167,12 @@ { "id": "p1-18", "scene": "P1", - "text": "顺带一提:有位作者说,这类保洁产品里每过一小时主动做一遍,不等桌子满。" + "text": "官方文档的原话正好背书这个次序:先清掉旧的工具输出,不够再把整段对话摘要。" }, { "id": "p1-19", "scene": "P1", - "text": "但前两级只能腾出有限的空间——真正的大头在后面。" + "text": "教学版的四级,就是官方这两级的细化。便宜先来、贵的殿后,方向一致。" }, { "id": "p1-20", @@ -347,27 +342,27 @@ { "id": "p3-09", "scene": "P3", - "text": "另一个角色,是一个很多人不知道的动作。压完之后,系统还会往回捞。" + "text": "压缩之后谁活下来,官方给过一张矩阵——" }, { "id": "p3-10", "scene": "P3", - "text": "有位作者说,产品里压缩结束,会自动把最近读过的文件捞回桌面:" + "text": "系统提示绕行不变;规则和自动记忆从磁盘重新注入;" }, { "id": "p3-11", "scene": "P3", - "text": "最多捞五个文件,单份有限额,总量有预算,按重要性排队。" + "text": "用过的技能正文重注入,但每份封顶五千、最旧的先丢。" }, { "id": "p3-12", "scene": "P3", - "text": "也就是说压缩不是一刀切——丢,也是分层次的丢," + "text": "而且压缩结束,官方口径也会把最近读过的文件捞回桌面," }, { "id": "p3-13", "scene": "P3", - "text": "刚丢掉的、马上还要用的,先给你放回来。" + "text": "最多五个、按重要性排队——丢,也是分层次的丢。" }, { "id": "p3-14", @@ -422,27 +417,27 @@ { "id": "p4-08", "scene": "P4", - "text": "所以需要另一层:一张不参与压缩的桌子。答案朴素得惊人——一个文件夹。" + "text": "所以需要另一层:不参与压缩的两条腿。第一条你写——就是项目里那个文件夹。" }, { "id": "p4-09", "scene": "P4", - "text": "没有数据库,没有云同步,就是项目旁边一个普通的目录。" + "text": "四层拼接、越近工作目录越后读;单文件超四兆整份跳过,超两百行开始不听话。" }, { "id": "p4-10", "scene": "P4", - "text": "一件事一个文件,每个文件开头三行登记:叫什么、一句话说明、属于哪类。" + "text": "一件事一个文件,开头三行登记:叫什么、一句话说明、属于哪类。" }, { "id": "p4-11", "scene": "P4", - "text": "写文件的时候顺手重建索引——一行一条,永远不会对不上。" + "text": "第二条腿它自己写:自动记忆按四类落在你的用户目录下,有门限。" }, { "id": "p4-12", "scene": "P4", - "text": "提取器下手之前会先查一遍已有记忆,记过的不再记,防止本子自己长胖。" + "text": "记过的不再记——防重复这条保留:防止本子自己长胖。" }, { "id": "p4-13", @@ -502,27 +497,27 @@ { "id": "p4-24", "scene": "P4", - "text": "这条小支路要是失败了,就退回最笨的关键词匹配——便宜的路总得有兜底。" + "text": "还有个经济学尾巴:前缀缓存按字数打折,但前缀必须一字不差——" }, { "id": "p4-25", "scene": "P4", - "text": "有人拆过它的源码——产品里干这活的,就是一个普通的小号模型。" + "text": "所以改了规则文件要新开会话才生效;中途换模型,那一轮特别慢。" }, { "id": "p4-26", "scene": "P4", - "text": "不用什么向量检索——名字加描述摆在那里,让模型自己读着挑,反而更可靠。" + "text": "挑记忆这活,就是一个普通的小号模型在干——不用向量检索,反而可靠。" }, { "id": "p4-27", "scene": "P4", - "text": "挑出来的内容也不进基本设定,是临时贴进这一轮的对话里——" + "text": "挑出来的内容不进基本设定,临时贴进这一轮——" }, { "id": "p4-28", "scene": "P4", - "text": "用完就过气,不占第二天的地盘。取记忆,也是一次性的。" + "text": "用完就过气。取记忆,也是一次性的。" }, { "id": "p4-29", @@ -662,41 +657,31 @@ { "id": "p6-05", "scene": "P6", - "text": "你自己其实也是这么干的:便签随便撕,账本不乱丢。" + "text": "官方还有一句话值得放在最后:这两条腿,都是上下文,不是闸门。" }, { "id": "p6-06", "scene": "P6", - "text": "区别只在于,它的账本每一页谁写、何时写、多久整理一次,都被设计过。" + "text": "记忆是建议,钩子才是规则——这是提示词工程和挽具工程的第一道分水岭。" }, { "id": "p6-07", "scene": "P6", - "text": "本片机制依据官方文档与公开工程实践,取数日期在画面上。" + "text": "本片以官方文档为主,取数2026年8月,以官方最新表述为准。" }, { "id": "p6-08", "scene": "P6", - "text": "涉及产品内部的部分,来自第三方的源码分析,片中已逐处标注。" + "text": "涉及产品内部的部分,为第三方源码分析,片中已逐处标注。" }, { "id": "p6-09", "scene": "P6", - "text": "涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注。" + "text": "下次它又忘了你的偏好,你知道去哪找——不是它的脑子,是那个文件夹。" }, { "id": "p6-10", "scene": "P6", - "text": "如果下次它又忘了你的偏好,你知道该去哪找了——" - }, - { - "id": "p6-11", - "scene": "P6", - "text": "不是它的脑子,是那个文件夹。" - }, - { - "id": "p6-12", - "scene": "P6", - "text": "而你的偏好值不值得写进那个文件夹,说到底是你说了算。下期见。" + "text": "下期拆另一件事:活儿能不能不等你盯着才开工——后台、定时、替你按开始的那只手。下期见。" } ] diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md index 1378442a..07f92fd7 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md @@ -1,4 +1,4 @@ -# 逐字稿:《AI 的记忆:会丢的和不能丢的》 +# 逐字稿:《记忆层:会丢的和不能丢的》 > **全片单一事实源的下游**:每条断言回溯 [../research/source-notes.md](../research/source-notes.md)。 > 格式约定:`## P` 起一幕;`- [pN-xx] 文本` 一行一句(进配音);`>` 引用块是画面备注(不进配音)。 @@ -13,17 +13,16 @@ > 画面:系列终端。读文件、跑命令的输出一条条堆进对话;窗口进度条涨满、撞上「拒收」墙。 > 角标:Context Compact · "Context Will Fill Up" -- [p0-01] 它正在干活,突然,停了。屏幕上一行报错,活干到一半,人愣在原地。 -- [p0-02] 不是它不想干,是服务那边把它拒收了。拒收,是必然发生的日常。 -- [p0-03] 拒收的理由很直白:你随身带的东西太大了,我装不下。 +- [p0-01] 它正在干活,突然,停了。一个小时的活,一行报错,全部作废。 +- [p0-02] 不是它不想干,是服务那边拒收了——理由直白:你随身带的,太大了。 - [p0-04] 它干活有个铁律:读过的每个文件、跑过的每条命令、你说的每句话, - [p0-05] 全都要随身带着,每问一次模型,就从第一个字重新看一遍。 - [p0-06] 你让它读一个大文件,再读三十个小文件,再跑二十条命令—— - [p0-07] 这些东西一层层堆上去,窗口总有装满的一刻。 - [p0-08] 装满那一刻,一次拒收,前面全白干。干了一小时,等于没干。 -- [p0-09] 而且这不是意外,是必然:只要活干得够久、项目够大,窗口一定会满。 -- [p0-10] 那满了怎么办?直觉答案是「删掉一点不就行了」。 -- [p0-11] 但删什么、先删谁、删错了会发生什么——这里面全是工程。 +- [p0-09] 官方实测还补了一刀:窗口越长,它记得反而越不准——注意力被摊薄了。 +- [p0-10] 所以满了怎么办?直觉答案是删掉一点。 +- [p0-11] 但删什么、先删谁——这里面全是工程。 - [p0-12] 删错了任务书,它忘了自己要干嘛;删错了回执,它对着空气发问。 - [p0-13] 这门课给的答案分两层,对应两种完全不同的心态。 - [p0-14] 第一层承认会丢:窗口一定会满,那就把丢管起来——分级、有序、有保底。 @@ -53,8 +52,8 @@ - [p1-15] 反正真需要的时候,再让它跑一遍就是——纸可以折,活不用重干。 - [p1-16] 注意折叠只动超过一百二十字的旧结果,短的就留着,不值得动它。 - [p1-17] 这两级全是纯文本操作,一次模型都不用请,便宜到近乎免费。 -- [p1-18] 顺带一提:有位作者说,这类保洁产品里每过一小时主动做一遍,不等桌子满。 -- [p1-19] 但前两级只能腾出有限的空间——真正的大头在后面。 +- [p1-18] 官方文档的原话正好背书这个次序:先清掉旧的工具输出,不够再把整段对话摘要。 +- [p1-19] 教学版的四级,就是官方这两级的细化。便宜先来、贵的殿后,方向一致。 - [p1-20] 记住这个次序感:先动最不心疼的,再动开始心疼的。这是全章的节拍。 ## P2 大件入库与顺序论证 @@ -102,11 +101,11 @@ - [p3-06] 真让它边收拾边调用工具,桌子越收越满,收拾就变成了新的堆积。 - [p3-07] 它还必须先在草稿区理清思路,再誊出正式摘要。 - [p3-08] 草稿写完就撕掉,不留在桌上——草稿是给它自己看的,不是给对话看的。 -- [p3-09] 另一个角色,是一个很多人不知道的动作。压完之后,系统还会往回捞。 -- [p3-10] 有位作者说,产品里压缩结束,会自动把最近读过的文件捞回桌面: -- [p3-11] 最多捞五个文件,单份有限额,总量有预算,按重要性排队。 -- [p3-12] 也就是说压缩不是一刀切——丢,也是分层次的丢, -- [p3-13] 刚丢掉的、马上还要用的,先给你放回来。 +- [p3-09] 压缩之后谁活下来,官方给过一张矩阵—— +- [p3-10] 系统提示绕行不变;规则和自动记忆从磁盘重新注入; +- [p3-11] 用过的技能正文重注入,但每份封顶五千、最旧的先丢。 +- [p3-12] 而且压缩结束,官方口径也会把最近读过的文件捞回桌面, +- [p3-13] 最多五个、按重要性排队——丢,也是分层次的丢。 - [p3-14] 这一步教学版没做,是有人从源码里读出来的——所以口播到这里, - [p3-15] 你听到的每一个细节都带着同一句提醒:这是他的分析,不是产品的说明书。 - [p3-16] 到这里,第一层讲完了:会丢的东西,被管得相当讲究。 @@ -124,11 +123,11 @@ - [p4-05] 几轮压缩之后,它被摘成了六个字:有代码风格偏好。 - [p4-06] 摘要没有做错什么——摘要的天性就是丢细节,保主干。 - [p4-07] 可有些细节,恰恰是主干。你的偏好就是你的偏好,缩不成一句概括。 -- [p4-08] 所以需要另一层:一张不参与压缩的桌子。答案朴素得惊人——一个文件夹。 -- [p4-09] 没有数据库,没有云同步,就是项目旁边一个普通的目录。 -- [p4-10] 一件事一个文件,每个文件开头三行登记:叫什么、一句话说明、属于哪类。 -- [p4-11] 写文件的时候顺手重建索引——一行一条,永远不会对不上。 -- [p4-12] 提取器下手之前会先查一遍已有记忆,记过的不再记,防止本子自己长胖。 +- [p4-08] 所以需要另一层:不参与压缩的两条腿。第一条你写——就是项目里那个文件夹。 +- [p4-09] 四层拼接、越近工作目录越后读;单文件超四兆整份跳过,超两百行开始不听话。 +- [p4-10] 一件事一个文件,开头三行登记:叫什么、一句话说明、属于哪类。 +- [p4-11] 第二条腿它自己写:自动记忆按四类落在你的用户目录下,有门限。 +- [p4-12] 记过的不再记——防重复这条保留:防止本子自己长胖。 - [p4-13] 四类记忆,其实就是四个问题。 - [p4-14] 你是谁——偏好和习惯,「缩进用 tab」就记在这类; - [p4-15] 怎么干活——反馈和规矩,「别造假数据」; @@ -140,11 +139,11 @@ - [p4-21] 第二条是按需取:每轮开始前,把最近对话和记忆清单一起发给一个小模型, - [p4-22] 请它挑真正用得上的,最多五条;拿不准就不挑,宁缺毋滥。 - [p4-23] 挑错了比没挑更糟——一条不相干的记忆,就是一句错误的自我介绍。 -- [p4-24] 这条小支路要是失败了,就退回最笨的关键词匹配——便宜的路总得有兜底。 -- [p4-25] 有人拆过它的源码——产品里干这活的,就是一个普通的小号模型。 -- [p4-26] 不用什么向量检索——名字加描述摆在那里,让模型自己读着挑,反而更可靠。 -- [p4-27] 挑出来的内容也不进基本设定,是临时贴进这一轮的对话里—— -- [p4-28] 用完就过气,不占第二天的地盘。取记忆,也是一次性的。 +- [p4-24] 还有个经济学尾巴:前缀缓存按字数打折,但前缀必须一字不差—— +- [p4-25] 所以改了规则文件要新开会话才生效;中途换模型,那一轮特别慢。 +- [p4-26] 挑记忆这活,就是一个普通的小号模型在干——不用向量检索,反而可靠。 +- [p4-27] 挑出来的内容不进基本设定,临时贴进这一轮—— +- [p4-28] 用完就过气。取记忆,也是一次性的。 - [p4-29] 一层永久的存,一次临时的取——这个组合,才让不丢变得便宜。 ## P5 先抢救,再碎纸 @@ -184,11 +183,9 @@ - [p6-02] 它不是记性好,是有两套东西在替它记。 - [p6-03] 一套负责体面地忘:分级收拾、先存再丢、压完往回捞; - [p6-04] 一套负责固执地记:一事一文件、索引常驻、先抢救再碎纸。 -- [p6-05] 你自己其实也是这么干的:便签随便撕,账本不乱丢。 -- [p6-06] 区别只在于,它的账本每一页谁写、何时写、多久整理一次,都被设计过。 -- [p6-07] 本片机制依据官方文档与公开工程实践,取数日期在画面上。 -- [p6-08] 涉及产品内部的部分,来自第三方的源码分析,片中已逐处标注。 -- [p6-09] 涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注。 -- [p6-10] 如果下次它又忘了你的偏好,你知道该去哪找了—— -- [p6-11] 不是它的脑子,是那个文件夹。 -- [p6-12] 而你的偏好值不值得写进那个文件夹,说到底是你说了算。下期见。 +- [p6-05] 官方还有一句话值得放在最后:这两条腿,都是上下文,不是闸门。 +- [p6-06] 记忆是建议,钩子才是规则——这是提示词工程和挽具工程的第一道分水岭。 +- [p6-07] 本片以官方文档为主,取数2026年8月,以官方最新表述为准。 +- [p6-08] 涉及产品内部的部分,为第三方源码分析,片中已逐处标注。 +- [p6-09] 下次它又忘了你的偏好,你知道去哪找——不是它的脑子,是那个文件夹。 +- [p6-10] 下期拆另一件事:活儿能不能不等你盯着才开工——后台、定时、替你按开始的那只手。下期见。 diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md index c69b82af..e9c0b201 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md @@ -10,7 +10,7 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| -| 0-A | p0-01..03 | 系列终端:活干到一半,一行红色报错砸出(「拒收/prompt too long」角标) | 报错行砸落 + 画面压暗一档;终端光标停闪 | +| 0-A | p0-01..02 | 系列终端:活干到一半,一行红色报错砸出(「拒收/prompt too long」角标) | 报错行砸落 + 画面压暗一档;终端光标停闪;p0-02 拒收理由角标浮出 | | 0-B | p0-04..08 | 终端缩小,右侧「窗口容器」:读文件/跑命令的色块一层层灌入玻璃容器 | 色块按句节奏持续注入;液面爬升;p0-08 液面撞顶、容器边框闪 `deny`,「前面全白干」 | | 0-C | p0-09..12 | 直觉答案「删一点」的三个恶果小样:任务书被删(忘了初衷)/ 回执被删(对空气发问) | 三张 20 秒小样依次快闪,各配一句后果 | | 0-D | p0-13..17 | 两层答案预告:左右两块画中画——左「桌面(会丢,管好丢)」右「登记簿(不丢)」 | 两块画中画先后亮起;中间一道分隔线生长——本集结构图 | @@ -65,4 +65,4 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 6-A | p6-01..06 | 一句话合同金句卡(`serif` `keep` 描边)→ 两行回收(体面地忘 / 固执地记) | 金句卡淡入;两行小字对仗浮现 | -| 6-B | p6-07..12 | 信源卡(官方文档+取数日期 / 第三方源码分析已逐处标注 / 数字均为实测口径)→ 身份卡 → 渐黑(末 beat 总时长推导,红线四) | 逐行浮现;身份卡;末 1.2s 线性压暗 | +| 6-B | p6-07..10 | 信源卡(官方文档+取数日期 / 第三方源码分析已逐处标注 / 数字均为实测口径)+ 「上下文不是闸门」分水岭角标 → 身份卡 + **下期预告卡**(「下期 · 时机层」+ 标题,只进画面) → 渐黑(末 beat 总时长推导,红线四) | 逐行浮现;身份卡;下期卡 `panel` 描边框浮现;末 1.2s 线性压暗 | diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx index 6936d531..3a1bbe15 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx @@ -418,7 +418,7 @@ const TwoAnswers: React.FC<{leftAt: number; rightAt: number; lineAt: number}> = export const P0Reject: React.FC<{scene: SceneRange}> = ({scene}) => { const w = (fromId: string, toId?: string) => beatWindow(scene.sentences, scene.from, fromId, toId); const at = (id: string) => w(id).from; - const bA = w('p0-01', 'p0-03'); + const bA = w('p0-01', 'p0-02'); const relA = (id: string) => at(id) - bA.from; const bB = w('p0-04', 'p0-08'); const relB = (id: string) => at(id) - bB.from; diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx index dad2da76..165b2443 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx @@ -74,12 +74,10 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; idAt: number}> = ({ const {fps} = useVideoConfig(); const enter = spring({frame: frame - 4, fps, config: {damping: 200}}); const rows = [ - ['官方文档', 'code.claude.com/docs · 取数 2026-08'], + ['官方文档', 'code.claude.com/docs · 取数2026年8月'], ['工程博客', 'anthropic.com/engineering'], ['源码分析', '第三方逆向分析 · 片中逐处标注'], - ['仓库钉版', '67a9126c(2026-08-22 取证)'], - ['归档', '取证字节随片归档(research/source-archive/)'], - ['许可', 'MIT'], + ['数字口径', '开源仓库钉版 67a9126c 实测 · 字节归档'], ]; const idT = interpolate(frame - idAt, [0, 20], [0, 1], { extrapolateLeft: 'clamp', @@ -158,10 +156,24 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; idAt: number}> = ({ marginTop: 18, }} > - {'AI 的记忆'} + {'记忆层:会丢的和不能丢的'}
-
- {'会丢的和不能丢的'} + {/* 下期预告卡:标题只在画面(反串线纪律) */} +
+
+ {'下期 · 时机层'} +
+
+ {'谁来按下开始'} +
) : null} @@ -176,7 +188,7 @@ export const P6Ending: React.FC<{scene: SceneRange}> = ({scene}) => { const at = (id: string) => w(id).from; const bA = w('p6-01', 'p6-06'); const relA = (id: string) => at(id) - bA.from; - const bB = w('p6-07', 'p6-12'); + const bB = w('p6-07', 'p6-10'); const relB = (id: string) => at(id) - bB.from; return ( diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json index 3eeef4e7..8aa7dd45 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json @@ -2,17 +2,17 @@ { "id": "p0-01", "scene": "P0", - "text": "你交给它一个真的大活:翻新整个后端,四个模块全都要动。" + "text": "你交给它一桩大活:翻新整个后端,四个模块全都要动。" }, { "id": "p0-02", "scene": "P0", - "text": "它开头干得不错。但修到接口时,认证那块的细节已经不在它的视野里了。" + "text": "它开头干得不错——可修到接口时,认证那块的细节,已经不在它的视野里了。" }, { "id": "p0-03", "scene": "P0", - "text": "不是它懒,是物理限制:一个注意力,盖不住一整个后端。" + "text": "官方给这种单干的慢性病,起了三个名字:干一半就宣布完成、偏爱自己的产出、目标越走越散。" }, { "id": "p0-04", @@ -22,7 +22,7 @@ { "id": "p0-05", "scene": "P0", - "text": "于是问题来了:从一个它到一群它,每多一样东西,都要有人回答四件事——" + "text": "于是问题来了:从一个它到一群它,每多一样东西,都要回答四件事——" }, { "id": "p0-06", @@ -42,12 +42,12 @@ { "id": "p0-09", "scene": "P0", - "text": "不过先别急着觉得简单。每一样东西里,都埋着几个从教训里学来的「不」字。" + "text": "每一样里都埋着从教训学来的「不」字——不许插队、不许转包、不许悄悄丢东西。" }, { "id": "p0-10", "scene": "P0", - "text": "不许插队、不许转包、不许悄悄丢东西——这一集的乐趣,就在这些「不」里。" + "text": "拆到最后,还有一个更大的问题等着:这一摊子的计划,到底攥在谁手里。" }, { "id": "p1-01", @@ -112,7 +112,7 @@ { "id": "p1-13", "scene": "P1", - "text": "有人拆过它的源码——产品里这套看板更严:认领动作包在文件锁里完成——" + "text": "官方文档写得直白:任务认领用文件锁防竞态——" }, { "id": "p1-14", @@ -222,7 +222,7 @@ { "id": "p2-14", "scene": "P2", - "text": "有人拆过它的源码——产品里真就是这么做的——信箱真的是文件," + "text": "官方口径也证实了:信箱真的就是用户目录下的一个文件," }, { "id": "p2-15", @@ -232,7 +232,7 @@ { "id": "p2-16", "scene": "P2", - "text": "他还说消息其实有十五种:汇报、请示、审批、关机、广播……" + "text": "有人数过,消息其实有十五种:汇报、请示、审批、关机、广播……" }, { "id": "p2-17", @@ -252,27 +252,22 @@ { "id": "p2-20", "scene": "P2", - "text": "组了队,不代表权限放松了。孩子们在外面玩,家长的签字栏还在原处。" + "text": "组了队,不代表权限放松了——官方立了三道禁令:队友的消息," }, { "id": "p2-21", "scene": "P2", - "text": "还有一条铁律:队友不许再孵队友。一层队伍就是一层,不搞子子孙孙。" + "text": "不能替你批权限、不能代你同意、被拒的动作不能转给另一个队友。" }, { "id": "p2-22", "scene": "P2", - "text": "为什么?想一下如果不禁止:每个队友都能拉自己的队伍,队伍生队伍," + "text": "组队不是权限洗白机。孩子们的签字栏,还在家长的原处。" }, { "id": "p2-23", "scene": "P2", - "text": "一张审批卡要冒十层泡才到你面前,一个任务被转包五手找不到责任人。" - }, - { - "id": "p2-24", - "scene": "P2", - "text": "一层结构换来的是每一步都找得到人。扁平,是协作的保险丝。" + "text": "还有一条铁律:队友不许再孵队友——一张审批卡冒十层泡,就找不到责任人了。" }, { "id": "p2-25", @@ -357,12 +352,7 @@ { "id": "p3-16", "scene": "P3", - "text": "教学版还诚实说了一句:只演了消息怎么走,没做「没批就不许动手」的门禁。" - }, - { - "id": "p3-17", - "scene": "P3", - "text": "产品的门禁是真的——高风险的活,批文没到,工具真的出不了手。" + "text": "教学版只演了消息怎么走;产品的门禁是真的——批文没到,工具出不了手。" }, { "id": "p4-01", @@ -412,42 +402,37 @@ { "id": "p4-10", "scene": "P4", - "text": "歇着也不是永远歇。教学版的规矩是六十秒:一分钟等不来新活,收工走人," + "text": "歇着也不是永远歇。教学版规矩六十秒:等不来新活,收工走人(教学设计)。" }, { "id": "p4-11", "scene": "P4", - "text": "临走把总结投进领队信箱。有人分析过,产品里没有固定时限,队友一直活着," + "text": "产品里没有固定时限,队友一直活着,等领队来握手告别。" }, { "id": "p4-12", "scene": "P4", - "text": "等领队来握手告别。而且真实版歇着时还有个身份小机关:" + "text": "真实版歇着时还有个身份机关:对话被压得太短,就把「我是谁」重新插回去。" }, { "id": "p4-13", "scene": "P4", - "text": "如果对话被压缩压得太短,它会把「我是谁、我是干嘛的」重新插回去。" - }, - { - "id": "p4-14", - "scene": "P4", "text": "干活得知道自己是谁。这句话对人对它都成立。" }, { - "id": "p4-15", + "id": "p4-14", "scene": "P4", "text": "再看一眼自治的样子:领队只做两件事——挂任务上板,需要时发告别握手。" }, { - "id": "p4-16", + "id": "p4-15", "scene": "P4", "text": "剩下的认领、开工、汇报、等待、再认领,全是队友自己的节奏。" }, { - "id": "p4-17", + "id": "p4-16", "scene": "P4", - "text": "领队从包工头退成了项目经理。转变的代价,就是前面那几样朴素的东西。" + "text": "领队从包工头退成了项目经理。转变的代价,就是那几样朴素的东西。" }, { "id": "p5-01", @@ -482,22 +467,22 @@ { "id": "p5-07", "scene": "P5", - "text": "名字查得严:只许字母数字点横线——防的是在名字里塞路径越狱。" + "text": "官方给这张桌子立了四道闸:指向主检出的编辑,拦;" }, { "id": "p5-08", "scene": "P5", - "text": "领队可以提前把任务和桌子都备好;绑定只登记,不改任务状态——" + "text": "命令的工作目录解析不对、确认不了的,拦;git 重定向的四种写法,拦;" }, { "id": "p5-09", "scene": "P5", - "text": "桌子先摆上,活等人来领,两不耽误。" + "text": "命令形状没法静态验证的,拦——而且这道闸,不能关。" }, { "id": "p5-10", "scene": "P5", - "text": "队友领到带桌子的任务,之后的每一步都在那张桌上发生,别的桌子碰不着。" + "text": "领队可以提前备好任务和桌子;绑定只登记,不改任务状态,两不耽误。" }, { "id": "p5-11", @@ -537,37 +522,27 @@ { "id": "p5-18", "scene": "P5", - "text": "有人拆过它的源码——产品里进出目录是整个进程跟着切过去——" + "text": "官方还交代了个细节:进出目录是整个进程跟着切——一旦进桌," }, { "id": "p5-19", "scene": "P5", - "text": "一旦进桌,它眼里的整个世界就是那张桌;产品里任务与目录也并不强制绑定。" + "text": "它眼里的世界就是那张桌。任务与目录是否强制绑定,两版取舍在角标。" }, { "id": "p5-20", "scene": "P5", - "text": "教学版把绑定做成了默认,讲起来更清楚,这是两种取舍,都在角标里写明。" + "text": "顺带交代悬着的话:工具本身也可以是别人造的。行业标准的接插协议," }, { "id": "p5-21", "scene": "P5", - "text": "顺带交代一句悬着的话:工具本身也可以是别人造的。" + "text": "外面的服务接上就变工具;名字自动带来源前缀,防的是两家重名。" }, { "id": "p5-22", "scene": "P5", - "text": "有一套行业标准协议,外面的服务接上就能变成它的工具,谁写的都行;" - }, - { - "id": "p5-23", - "scene": "P5", - "text": "工具名前面还会自动带上来源名,防的就是两家服务起了同一个名字。" - }, - { - "id": "p5-24", - "scene": "P5", - "text": "这一句只是点到——它背后还有一整套生态,值得单独讲一次。" + "text": "装十个服务,上下文几乎不占——工具的定义按需取用,不整包塞进来。" }, { "id": "p6-01", @@ -577,91 +552,81 @@ { "id": "p6-02", "scene": "P6", - "text": "再把收尾的全景画面请出来:一整轮,从头到尾走一遍——" + "text": "再把全景画面请出来,一整轮快闪走一遍——十几样机制各就各位。" }, { "id": "p6-03", "scene": "P6", - "text": "你说一句话,进料口收下;定时和后台的通知排着队汇入;" + "text": "你说一句话进料;通知排队汇入;桌面太满先收拾;状态拼成垫纸;" }, { "id": "p6-04", "scene": "P6", - "text": "桌面太满就先收拾;记忆、技能、外接工具的状态拼成垫纸;" + "text": "然后问模型。有活就过闸门、分发、执行、回填,再问下一轮。" }, { "id": "p6-05", "scene": "P6", - "text": "然后问模型。有活干就过闸门、分发、执行、回填,再问下一轮;" + "text": "这幅图上你要找的东西只有一个:那个循环。机制很多,循环一个。" }, { "id": "p6-06", "scene": "P6", - "text": "没活干就停机收尾。从头到尾,十几样机制各就各位。" + "text": "变的从来不是它,是攥着它的那只手。" }, { "id": "p6-07", "scene": "P6", - "text": "这幅图上你要找的东西只有一个:那个循环。" + "text": "而拆到最后,还有一个更大的问题:这一摊子的计划,攥在谁手里?" }, { "id": "p6-08", "scene": "P6", - "text": "从系列开头到今天,循环还是那个循环。变的从来不是它,是它周围的脚手架。" + "text": "官方给了答案——第四种形态:让它当场把编排写成一段脚本。" }, { "id": "p6-09", "scene": "P6", - "text": "官方工程博客的注脚,也是这一系列最好的收束——机制很多,循环一个。" + "text": "循环、分支、中间结果,住进脚本变量;它的上下文,只装最终答案。" }, { "id": "p6-10", "scene": "P6", - "text": "一群它,不是一群更聪明的它。多出来的不是智慧," + "text": "脚本落盘,可读、可比对、改完能重跑;并发最多十六,单次一千。" }, { "id": "p6-11", "scene": "P6", - "text": "是把协作拆成了看得见的零件:板子、信箱、编号、桌子。" + "text": "挽具第一次,开始由它自己来写。" }, { "id": "p6-12", "scene": "P6", - "text": "零件朴素,不等于组合简单。哪张卡挡哪条路,哪个编号对哪次话," + "text": "多出来的不是智慧,是把协作拆成了看得见的零件:板子、信箱、编号、桌子。" }, { "id": "p6-13", "scene": "P6", - "text": "桌子什么时候不许拆——每一个「不」,都是从翻过的车上学来的。" + "text": "官方泼的冷水也要听:并行和专精,必须挣回它们的协调成本——" }, { "id": "p6-14", "scene": "P6", - "text": "拆完这一系列你会发现同一个规律:听起来越神的功能,拆开越是旧零件。" + "text": "官方算过账,多智能体的花销,大约是普通对话的十五倍。" }, { "id": "p6-15", "scene": "P6", - "text": "看板是文件夹,信箱是文本文件,握手是一张对照表,隔离是一间空目录。" + "text": "本片机制依据官方文档,取数2026年8月,以官方最新表述为准。" }, { "id": "p6-16", "scene": "P6", - "text": "本片机制依据官方文档与公开工程实践,取数日期在画面上。" + "text": "涉及产品内部的部分,为第三方源码分析,片中已逐处标注。" }, { "id": "p6-17", "scene": "P6", - "text": "涉及产品内部的部分,来自第三方的源码分析,片中已逐处标注。" - }, - { - "id": "p6-18", - "scene": "P6", - "text": "涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注。" - }, - { - "id": "p6-19", - "scene": "P6", - "text": "这个系列到这里就拆完了。回头看,它一直没变过——下期见。" + "text": "下期,换个方向:怎么给这样的系统打分。分数会骗人,过程不会——下期见。" } ] diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md index c74c9434..94017b6c 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md @@ -1,4 +1,4 @@ -# 逐字稿:《一群 AI 怎么干活:看板、信箱与各自的桌子》 +# 逐字稿:《协作层:从一个到一群》 > **全片单一事实源的下游**:每条断言回溯 [../research/source-notes.md](../research/source-notes.md)。 > 格式约定:`## P` 起一幕;`- [pN-xx] 文本` 一行一句(进配音);`>` 引用块是画面备注(不进配音)。 @@ -14,16 +14,16 @@ > 画面拉开——「一个它」的环孤零零悬着,四周是盖不住的模块群。 > 角标:Agent Teams · "One Agent isn't enough" -- [p0-01] 你交给它一个真的大活:翻新整个后端,四个模块全都要动。 -- [p0-02] 它开头干得不错。但修到接口时,认证那块的细节已经不在它的视野里了。 -- [p0-03] 不是它懒,是物理限制:一个注意力,盖不住一整个后端。 +- [p0-01] 你交给它一桩大活:翻新整个后端,四个模块全都要动。 +- [p0-02] 它开头干得不错——可修到接口时,认证那块的细节,已经不在它的视野里了。 +- [p0-03] 官方给这种单干的慢性病,起了三个名字:干一半就宣布完成、偏爱自己的产出、目标越走越散。 - [p0-04] 就像一个工人盖不了整栋楼。要赶工期,得来一队人。 -- [p0-05] 于是问题来了:从一个它到一群它,每多一样东西,都要有人回答四件事—— +- [p0-05] 于是问题来了:从一个它到一群它,每多一样东西,都要回答四件事—— - [p0-06] 活挂在哪里?话从哪里走?怎么谈判?谁的桌子谁收拾? - [p0-07] 这一集就把这四个问题一个个拆开。答案都很朴素,朴素到你会怀疑: - [p0-08] 就这?对,就这。一堆文件、几个信箱、一张编号表,拼起来就是团队。 -- [p0-09] 不过先别急着觉得简单。每一样东西里,都埋着几个从教训里学来的「不」字。 -- [p0-10] 不许插队、不许转包、不许悄悄丢东西——这一集的乐趣,就在这些「不」里。 +- [p0-09] 每一样里都埋着从教训学来的「不」字——不许插队、不许转包、不许悄悄丢东西。 +- [p0-10] 拆到最后,还有一个更大的问题等着:这一摊子的计划,到底攥在谁手里。 ## P1 活挂在哪里:看板 @@ -42,7 +42,7 @@ - [p1-10] 就是把你挡住。宁可挡着你,也不让一个笔误炸掉整块看板。 - [p1-11] 你可能觉得这设计保守。但想想看板是给一群它用的: - [p1-12] 一个成员写错一个编号就全盘崩掉,这买卖做不得。防御性不是胆小,是算账。 -- [p1-13] 有人拆过它的源码——产品里这套看板更严:认领动作包在文件锁里完成—— +- [p1-13] 官方文档写得直白:任务认领用文件锁防竞态—— - [p1-14] 先看一眼没人抢、再落笔写主人,两步并成一步,中间插不进第二只手。 - [p1-15] 编号也有讲究:一个只增不减的计数器,防止编号被重复使用。 - [p1-16] 看板立好了。谁来看?都可以——它就是硬盘上的一堆文件,能读就能看。 @@ -71,17 +71,16 @@ - [p2-11] 文件是给人和它共同看的地方——协作系统做到这一步,才算真的透明。 - [p2-12] 领队也是这规矩。队友干完活,把总结投进领队的信箱; - [p2-13] 领队隔一阵收一次信,把信里的内容贴进自己的对话,接着指挥。 -- [p2-14] 有人拆过它的源码——产品里真就是这么做的——信箱真的是文件, +- [p2-14] 官方口径也证实了:信箱真的就是用户目录下的一个文件, - [p2-15] 只不过写文件加了一把锁,防止两个队友同时投信把信写串行。 -- [p2-16] 他还说消息其实有十五种:汇报、请示、审批、关机、广播…… +- [p2-16] 有人数过,消息其实有十五种:汇报、请示、审批、关机、广播…… - [p2-17] 名目繁多,但底子全是同一个动作:往对方的文件里,加一行带类型的字。 - [p2-18] 最妙的是权限。队友要干一件需要审批的事,审批窗不在它自己的屏幕上—— - [p2-19] 请求冒泡,一路浮到领队的屏幕,弹出来,还是你来点头。 -- [p2-20] 组了队,不代表权限放松了。孩子们在外面玩,家长的签字栏还在原处。 -- [p2-21] 还有一条铁律:队友不许再孵队友。一层队伍就是一层,不搞子子孙孙。 -- [p2-22] 为什么?想一下如果不禁止:每个队友都能拉自己的队伍,队伍生队伍, -- [p2-23] 一张审批卡要冒十层泡才到你面前,一个任务被转包五手找不到责任人。 -- [p2-24] 一层结构换来的是每一步都找得到人。扁平,是协作的保险丝。 +- [p2-20] 组了队,不代表权限放松了——官方立了三道禁令:队友的消息, +- [p2-21] 不能替你批权限、不能代你同意、被拒的动作不能转给另一个队友。 +- [p2-22] 组队不是权限洗白机。孩子们的签字栏,还在家长的原处。 +- [p2-23] 还有一条铁律:队友不许再孵队友——一张审批卡冒十层泡,就找不到责任人了。 - [p2-25] 你回头看会发现:这些约定防的都是「没人负责」这四个字。 ## P3 怎么谈判:握手 @@ -105,8 +104,7 @@ - [p3-13] 请求、同意或拒绝——拒绝还能附理由——最后系统广播一声「人已离场」, - [p3-14] 顺带把它的窗格、任务、名册统统收拾干净。 - [p3-15] 所谓协议,没有玄机:一张状态表、一个编号、几条对得上号的规矩。 -- [p3-16] 教学版还诚实说了一句:只演了消息怎么走,没做「没批就不许动手」的门禁。 -- [p3-17] 产品的门禁是真的——高风险的活,批文没到,工具真的出不了手。 +- [p3-16] 教学版只演了消息怎么走;产品的门禁是真的——批文没到,工具出不了手。 ## P4 自己看板,自己认领 @@ -123,14 +121,13 @@ - [p4-07] 认领前照例三查:是待办吗?有主人吗?依赖齐了吗?任何一条不过,不硬来。 - [p4-08] 这样领队只需要把任务挂上板,剩下的分发全自动。 - [p4-09] 两只队友同时抢一个活怎么办?主人这一格先到先得,后到者查一眼就走。 -- [p4-10] 歇着也不是永远歇。教学版的规矩是六十秒:一分钟等不来新活,收工走人, -- [p4-11] 临走把总结投进领队信箱。有人分析过,产品里没有固定时限,队友一直活着, -- [p4-12] 等领队来握手告别。而且真实版歇着时还有个身份小机关: -- [p4-13] 如果对话被压缩压得太短,它会把「我是谁、我是干嘛的」重新插回去。 -- [p4-14] 干活得知道自己是谁。这句话对人对它都成立。 -- [p4-15] 再看一眼自治的样子:领队只做两件事——挂任务上板,需要时发告别握手。 -- [p4-16] 剩下的认领、开工、汇报、等待、再认领,全是队友自己的节奏。 -- [p4-17] 领队从包工头退成了项目经理。转变的代价,就是前面那几样朴素的东西。 +- [p4-10] 歇着也不是永远歇。教学版规矩六十秒:等不来新活,收工走人(教学设计)。 +- [p4-11] 产品里没有固定时限,队友一直活着,等领队来握手告别。 +- [p4-12] 真实版歇着时还有个身份机关:对话被压得太短,就把「我是谁」重新插回去。 +- [p4-13] 干活得知道自己是谁。这句话对人对它都成立。 +- [p4-14] 再看一眼自治的样子:领队只做两件事——挂任务上板,需要时发告别握手。 +- [p4-15] 剩下的认领、开工、汇报、等待、再认领,全是队友自己的节奏。 +- [p4-16] 领队从包工头退成了项目经理。转变的代价,就是那几样朴素的东西。 ## P5 谁的桌子:各干各的 @@ -144,10 +141,10 @@ - [p5-04] 更糟的是回滚不干净:同一份文件混着两人的改动,分不出哪行是谁的。 - [p5-05] 解法还是老实的:同一个仓库,各开各的桌子。 - [p5-06] 每个任务可以绑一个独立的工作目录,各建各的分支。 -- [p5-07] 名字查得严:只许字母数字点横线——防的是在名字里塞路径越狱。 -- [p5-08] 领队可以提前把任务和桌子都备好;绑定只登记,不改任务状态—— -- [p5-09] 桌子先摆上,活等人来领,两不耽误。 -- [p5-10] 队友领到带桌子的任务,之后的每一步都在那张桌上发生,别的桌子碰不着。 +- [p5-07] 官方给这张桌子立了四道闸:指向主检出的编辑,拦; +- [p5-08] 命令的工作目录解析不对、确认不了的,拦;git 重定向的四种写法,拦; +- [p5-09] 命令形状没法静态验证的,拦——而且这道闸,不能关。 +- [p5-10] 领队可以提前备好任务和桌子;绑定只登记,不改任务状态,两不耽误。 - [p5-11] 干完收尾,两个选择:留着(分支保留,等人审查合并)或者拆掉。 - [p5-12] 但有个不讲情面的默认:桌上还有没提交的改动,拆桌子的请求直接被拒。 - [p5-13] 这个「不讲情面」值得细品。机器最擅长的是无条件执行指令, @@ -155,13 +152,11 @@ - [p5-15] 想拆?必须明说「丢弃改动」。宁可多签一次字,不悄悄丢掉任何工作。 - [p5-16] 建桌、拆桌、留桌,每次都记一行日志。谁何时动过哪张桌,翻账就知道。 - [p5-17] 一行日志看着轻,出了事它就是唯一的目击证人。 -- [p5-18] 有人拆过它的源码——产品里进出目录是整个进程跟着切过去—— -- [p5-19] 一旦进桌,它眼里的整个世界就是那张桌;产品里任务与目录也并不强制绑定。 -- [p5-20] 教学版把绑定做成了默认,讲起来更清楚,这是两种取舍,都在角标里写明。 -- [p5-21] 顺带交代一句悬着的话:工具本身也可以是别人造的。 -- [p5-22] 有一套行业标准协议,外面的服务接上就能变成它的工具,谁写的都行; -- [p5-23] 工具名前面还会自动带上来源名,防的就是两家服务起了同一个名字。 -- [p5-24] 这一句只是点到——它背后还有一整套生态,值得单独讲一次。 +- [p5-18] 官方还交代了个细节:进出目录是整个进程跟着切——一旦进桌, +- [p5-19] 它眼里的世界就是那张桌。任务与目录是否强制绑定,两版取舍在角标。 +- [p5-20] 顺带交代悬着的话:工具本身也可以是别人造的。行业标准的接插协议, +- [p5-21] 外面的服务接上就变工具;名字自动带来源前缀,防的是两家重名。 +- [p5-22] 装十个服务,上下文几乎不占——工具的定义按需取用,不整包塞进来。 ## P6 收束:机制很多,循环一个 @@ -170,21 +165,19 @@ > 角标:"Many mechanisms, one loop" · 27 个内建工具(源码分析) - [p6-01] 现在把这一集的四样东西摆回大图里:看板、信箱、握手、各自的桌子。 -- [p6-02] 再把收尾的全景画面请出来:一整轮,从头到尾走一遍—— -- [p6-03] 你说一句话,进料口收下;定时和后台的通知排着队汇入; -- [p6-04] 桌面太满就先收拾;记忆、技能、外接工具的状态拼成垫纸; -- [p6-05] 然后问模型。有活干就过闸门、分发、执行、回填,再问下一轮; -- [p6-06] 没活干就停机收尾。从头到尾,十几样机制各就各位。 -- [p6-07] 这幅图上你要找的东西只有一个:那个循环。 -- [p6-08] 从系列开头到今天,循环还是那个循环。变的从来不是它,是它周围的脚手架。 -- [p6-09] 官方工程博客的注脚,也是这一系列最好的收束——机制很多,循环一个。 -- [p6-10] 一群它,不是一群更聪明的它。多出来的不是智慧, -- [p6-11] 是把协作拆成了看得见的零件:板子、信箱、编号、桌子。 -- [p6-12] 零件朴素,不等于组合简单。哪张卡挡哪条路,哪个编号对哪次话, -- [p6-13] 桌子什么时候不许拆——每一个「不」,都是从翻过的车上学来的。 -- [p6-14] 拆完这一系列你会发现同一个规律:听起来越神的功能,拆开越是旧零件。 -- [p6-15] 看板是文件夹,信箱是文本文件,握手是一张对照表,隔离是一间空目录。 -- [p6-16] 本片机制依据官方文档与公开工程实践,取数日期在画面上。 -- [p6-17] 涉及产品内部的部分,来自第三方的源码分析,片中已逐处标注。 -- [p6-18] 涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注。 -- [p6-19] 这个系列到这里就拆完了。回头看,它一直没变过——下期见。 +- [p6-02] 再把全景画面请出来,一整轮快闪走一遍——十几样机制各就各位。 +- [p6-03] 你说一句话进料;通知排队汇入;桌面太满先收拾;状态拼成垫纸; +- [p6-04] 然后问模型。有活就过闸门、分发、执行、回填,再问下一轮。 +- [p6-05] 这幅图上你要找的东西只有一个:那个循环。机制很多,循环一个。 +- [p6-06] 变的从来不是它,是攥着它的那只手。 +- [p6-07] 而拆到最后,还有一个更大的问题:这一摊子的计划,攥在谁手里? +- [p6-08] 官方给了答案——第四种形态:让它当场把编排写成一段脚本。 +- [p6-09] 循环、分支、中间结果,住进脚本变量;它的上下文,只装最终答案。 +- [p6-10] 脚本落盘,可读、可比对、改完能重跑;并发最多十六,单次一千。 +- [p6-11] 挽具第一次,开始由它自己来写。 +- [p6-12] 多出来的不是智慧,是把协作拆成了看得见的零件:板子、信箱、编号、桌子。 +- [p6-13] 官方泼的冷水也要听:并行和专精,必须挣回它们的协调成本—— +- [p6-14] 官方算过账,多智能体的花销,大约是普通对话的十五倍。 +- [p6-15] 本片机制依据官方文档,取数2026年8月,以官方最新表述为准。 +- [p6-16] 涉及产品内部的部分,为第三方源码分析,片中已逐处标注。 +- [p6-17] 下期,换个方向:怎么给这样的系统打分。分数会骗人,过程不会——下期见。 diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md index b5a762a7..c92134bb 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md @@ -30,8 +30,8 @@ | 2-A | p2-01..05 | 临时工 vs 队友:左侧临时工剪影(干完即走)右侧队友小环(peer 色,铭牌);队友环长期驻场 | 临时工淡出;队友环落位并打上铭牌;对比定格 | | 2-B | p2-06..11 | ★信箱行:每位成员门口一个信箱文件;消息行(一行字)飞入对方文件;读取即划掉(一行淡出) | 消息行沿弧线飞入;打开文件时光扫过、被读行划掉;角标「写文件带锁(防串行)」 | | 2-C | p2-12..14 | 十五种消息类型小样墙(统一 panel 底编号,反枚举):汇报/请示/审批/关机/广播…… | 类型卡快速铺开;全部退远缩成「往文件里加一行带类型的字」一行字 | -| 2-D | p2-15..17 | ★权限冒泡:队友的审批卡从下沿虚线上浮到领队屏幕弹出(带队友名字与颜色);点头后回执下落 | 审批卡沿路径上浮(浮起涟漪);你的光标点头动画;回执回落到队友信箱 | -| 2-E | p2-18..25 | 不许孵队友:队友伸出「招人」手被 deny 栏杆挡住;转包链演示(队伍生队伍审批卡冒十层泡的混乱图)一闪即碎 | 栏杆落下;混乱链图从中心碎裂退场;p2-24「扁平是保险丝」定格成保险丝形状的横幅(mech)| +| 2-D | p2-15..19 | ★权限冒泡:队友的审批卡从下沿虚线上浮到领队屏幕弹出(带队友名字与颜色);点头后回执下落 | 审批卡沿路径上浮(浮起涟漪);你的光标点头动画;回执回落到队友信箱 | +| 2-E | p2-20..25 | **三禁止章**:一条 A→B 消息到达前被「来自另一个会话——不是你的用户」标签盖灰;三枚 deny 红章依次盖下(不能替你批权限 / 不能代你同意 / 被拒动作不能转给别人);不许孵队友铁律 + 保险丝收尾 | 消息卡飞行被来源标签截停盖灰;三红章逐枚盖下(章落带缩放震);「队伍生队伍」混乱链一闪即碎;末句保险丝横幅(mech) | ## P3 怎么谈判:握手 @@ -40,32 +40,32 @@ | 3-A | p3-01..05 | 杀线程之祸:掐线程瞬间,写一半的文件断在半空(裂口);握手替代:领队发关机请求→队友收尾→回「同意」→自行退出 | 文件裂口闪烁(deny);四步走位动画:请求卡出发→队友卡收拾(文件补全)→回执→退出 | | 3-B | p3-06..09 | ★握手轨(HandshakeRail 母题):请求卡带编号(req_0042)滑出停在「等回话」位;状态表 pending 行亮起;应答卡带同号归来对号合拢锁扣「咔」;类型校验:一张错类型回执被弹开 | 请求/应答卡沿轨对开;编号铭牌双方一致时合拢+锁扣声效帧;错类型卡撞上弹开(deny) | | 3-C | p3-10..11 | 计划审批同构:队友交计划卡等批,批文带编号回来,批了才动手 | 同一握手轨复用(方向反转);「批了才动手」门闸开合 | -| 3-D | p3-12..17 | 【三】三向关机:请求→同意/拒绝(可附理由)→系统广播「已离场」+ 窗格/任务/名册自动收拾;末句「协议没有玄机」定格 | 三向消息流;收拾动画(窗格收起、名册划名);角标「第三方的源码分析」+「教学版未做执行门控」诚实标注 | +| 3-D | p3-12..16 | 【三】三向关机:请求→同意/拒绝(可附理由)→系统广播「已离场」+ 窗格/任务/名册自动收拾;教学版诚实句(只演消息走、产品门禁是真的)并句收尾 | 三向消息流;收拾动画(窗格收起、名册划名);角标「第三方的源码分析」;末句门禁小闸落下 | ## P4 自己看板,自己认领 | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 4-A | p4-01..03 | 派工之累:领队挨个发十次任务的重复动画(快速蒙太奇);三段生命周期环登场(干活/歇着/走人) | 分发卡×10 快闪;生命周期三段环描线 | -| 4-B | p4-04..08 | 歇着态特写:每五秒心跳一次,看两眼——先信箱(有关机立刻收尾;有信先处理)后看板(三查后认领) | 心跳脉冲;视线先扫信箱再扫看板的路径高亮;认领时主人格写入+锁形闪光 | -| 4-C | p4-09..13 | 六十秒表盘走满自动收工(教学版标记);压缩后身份重注入(对话变短→「我是谁」卡插回) | 表盘快走满→收工礼花定格;对话堆坍缩成一小段→身份卡从顶部插回;角标「产品无固定时限(源码分析)」 | -| 4-D | p4-14..17 | 领队角色变化:包工头帽摘下换项目经理牌;两件事(挂任务/告别握手)图示 | 帽子换牌动画;两张卡钉在领队环旁 | +| 4-B | p4-04..09 | 歇着态特写:每五秒心跳一次,看两眼——先信箱(有关机立刻收尾;有信先处理)后看板(三查后认领);两只队友抢活先到先得 | 心跳脉冲;视线先扫信箱再扫看板的路径高亮;认领时主人格写入+锁形闪光 | +| 4-C | p4-10..13 | 六十秒表盘走满自动收工(教学版标记);产品无固定时限;压缩后身份重注入(对话变短→「我是谁」卡插回) | 表盘快走满→收工礼花定格;对话堆坍缩成一小段→身份卡从顶部插回;角标「产品无固定时限(源码分析)」 | +| 4-D | p4-14..16 | 领队角色变化:包工头帽摘下换项目经理牌;两件事(挂任务/告别握手)图示 | 帽子换牌动画;两张卡钉在领队环旁 | ## P5 谁的桌子:各干各的 | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 5-A | p5-01..05 | 阿珍阿强冲突:两张桌子(同一目录)各写同名 config.py;阿强一覆盖,阿珍的改动碎掉;回滚线团成一团乱麻 | 双写冲突动画;覆盖时文件碎裂;回滚箭头打成死结 | -| 5-B | p5-06..09 | ★各开一桌:同一仓库底座向两侧长出平行目录抽屉(SeparateDesks 母题);名字校验(字母数字点横线);绑定只登记不改状态 | 抽屉滑出成排;带 `../` 的名字卡被弹回(deny);任务卡与桌子卡之间画登记虚线(状态格不动) | -| 5-C | p5-10..17 | 队友进桌:它的整个世界=那张桌(视野光圈收束到桌内);收尾二选一;★脏桌不删(改动未提交→删除被拒、桌沿抖动)+ 必须明说丢弃;建/拆/留逐行日志 | 视野光圈收缩;「保留/删除」双门;删除门被 deny 封条贴上并抖动;明说后封条撕开;右侧日志行逐条追加 | -| 5-D | p5-18..24 | 【三】产品差异角标(进程级切换/不强制绑定);外接工具一句:标准插头插入工具池 + 来源前缀铭牌防重名 | 角标浮现;标准插头插入动画;`mcp__jira__create` 铭牌格式特写 | +| 5-B | p5-06..09 | ★各开一桌 + **官方四道闸**:同一仓库底座向两侧长出平行目录抽屉;墙上四道闸依次落下(指向主检出的编辑/工作目录解析不对/git 重定向四种/形状无法验证——第四道焊死不能关) | 抽屉滑出成排;四道闸逐道落下,第四道落锁(`deny` 焊缝)+「这道不能关」小标 | +| 5-C | p5-10..17 | 队友进桌:视野光圈收束到桌内;收尾二选一;★脏桌不删(改动未提交→删除被拒、桌沿抖动)+ 必须明说丢弃;建/拆/留逐行日志 | 视野光圈收缩;「保留/删除」双门;删除门被 deny 封条贴上并抖动;明说后封条撕开;右侧日志行逐条追加 | +| 5-D | p5-18..22 | 【官方】进程级切换(进桌=整个世界是那张桌);外接工具:标准插头插入工具池 + 来源前缀铭牌防重名 + **延迟装载竖槽**(装十个服务上下文几乎不占,定义按需取用) | 角标浮现;标准插头插入动画;`mcp__jira__create` 铭牌特写;竖槽内只落两枚薄片、完整定义卡停在槽外「待取区」 | ## P6 收束:机制很多,循环一个 | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 6-A | p6-01..02 | 四样东西归位小图(板/箱/号/桌);七段传送带(FullTurn 母题)铺开 | 四小图标滑入底部;传送带自左向右描线成形 | -| 6-B | p6-03..06 | ★一整轮:包裹走完七段(进料/护栏/选面/执行/外接/补救/记账),每段亮起对应前几集机制小图标(清单/副桌/目录卡/垫纸/梯子/信箱/握手/桌子……) | 包裹逐段推进;每过一段该段图标亮起并短暂回闪其母题缩略 | -| 6-C | p6-07..11 | ★系列终曲帧:环(core)从传送带中央升起放大居中——同色同宽同节点;「机制很多,循环一个」金句压场;「每个不字都是翻过的车」收尾 | 环升起重演描线一遍(与系列首集同款动画节奏);机制图标环立四周;金句卡(core)淡入 | -| 6-D | p6-12..15 | 「旧零件」收束:看板=文件夹/信箱=文本/握手=对照表/隔离=空目录 四连小图 | 四连小图逐个亮起(mono 等宽字标注) | -| 6-E | p6-16..19 | 信源卡(官方文档+取数日期 / 第三方源码分析已逐处标注 / 数字均为实测口径)→ 身份卡 → **渐黑**(末 beat 总时长推导,红线四);末句「它一直没变过」 | 逐行浮现;身份卡;末 1.2s 线性压暗到全黑 | +| 6-B | p6-03..04 | ★一整轮快闪:包裹走完七段(进料/护栏/选面/执行/外接/补救/记账),每段亮起对应机制小图标——快闪蒙太奇(原 4 句详走压成 2 句) | 包裹逐段快速推进(每段约 1.5s);每过一段该段图标亮起并短暂回闪其母题缩略 | +| 6-C | p6-05..06 | ★系列终曲帧:环(core)从传送带中央升起放大居中——同色同宽同节点;「机制很多,循环一个」金句压场 | 环升起重演描线一遍(与系列首集同款动画节奏);机制图标环立四周;金句卡(core)淡入 | +| 6-D | p6-07..11 | ★**谁持有计划**:四象对比(临时工/技能包/队友——计划由模型逐回合决定)vs 第四种(脚本持有);动态工作流三分区:会话侧只装最终答案 / 运行时侧住循环分支与中间结果 / agent 侧点阵(并发 16 · 总量 1000);收官反转「挽具第一次由它自己来写」 | 分水岭竖线落下(前三列同色第四列异色);中间结果被抽进变量盒动画;resume 子图:A 秒亮 / B 重跑 / C D 对勾抹掉;反转金句卡压场 | +| 6-E | p6-12..17 | 「零件」收束(板/箱/号/桌)+ 官方冷水(十五倍 token)→ 信源卡(官方文档+取数日期 / 第三方源码分析已逐处标注 / 数字均为实测口径)→ 身份卡 + **下期预告卡**(「换个方向:给这样的系统打分」,只进画面) → **渐黑**(末 beat 总时长推导,红线四) | 零件四连小图;十五倍对比条;信源卡逐行;身份卡;下期卡浮现;末 1.2s 线性压暗到全黑 | diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx index ff71a9eb..bee3e08e 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx @@ -749,8 +749,8 @@ export const P2Mail: React.FC<{scene: SceneRange}> = ({scene}) => { const bA = w('p2-01', 'p2-05'); const bB = w('p2-06', 'p2-11'); const bC = w('p2-12', 'p2-14'); - const bD = w('p2-15', 'p2-17'); - const bE = w('p2-18', 'p2-25'); + const bD = w('p2-15', 'p2-19'); + const bE = w('p2-20', 'p2-25'); const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx index cde06687..d5dee884 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx @@ -718,7 +718,7 @@ export const P3Handshake: React.FC<{scene: SceneRange}> = ({scene}) => { const bA = w('p3-01', 'p3-05'); const bB = w('p3-06', 'p3-09'); const bC = w('p3-10', 'p3-11'); - const bD = w('p3-12', 'p3-17'); + const bD = w('p3-12', 'p3-16'); const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx index 280209b5..a657776e 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx @@ -700,9 +700,9 @@ export const P4Autonomy: React.FC<{scene: SceneRange}> = ({scene}) => { const w = (fromId: string, toId?: string) => beatWindow(scene.sentences, scene.from, fromId, toId); const at = (id: string) => w(id).from; const bA = w('p4-01', 'p4-03'); - const bB = w('p4-04', 'p4-08'); - const bC = w('p4-09', 'p4-13'); - const bD = w('p4-14', 'p4-17'); + const bB = w('p4-04', 'p4-09'); + const bC = w('p4-10', 'p4-13'); + const bD = w('p4-14', 'p4-16'); const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx index edf8c07b..3a8c828e 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx @@ -772,7 +772,7 @@ export const P5Desks: React.FC<{scene: SceneRange}> = ({scene}) => { const bA = w('p5-01', 'p5-05'); const bB = w('p5-06', 'p5-09'); const bC = w('p5-10', 'p5-17'); - const bD = w('p5-18', 'p5-24'); + const bD = w('p5-18', 'p5-22'); const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx index dbf7dba1..d205b193 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx @@ -394,88 +394,180 @@ const SeriesFinale: React.FC<{riseAt: number; quoteAt: number}> = ({riseAt, quot ); }; -/** 6-D 旧零件四连小图:看板=文件夹 / 信箱=文本 / 握手=对照表 / 隔离=空目录 */ -const PlainParts: React.FC = () => { +/** 6-D ★谁持有计划:四象对比(Harness Engineering 收官纲图) + * 官方 workflows 的四方对比——临时工/技能包/队友:计划由模型逐回合现场决定; + * 第四种(动态工作流):脚本持有计划,中间结果住变量、上下文只装最终答案。 + * 分水岭竖线落下是全片思想高点;收官反转「挽具第一次由它自己来写」。 */ +const WhoHoldsPlan: React.FC<{gridAt: number; divideAt: number; runtimeAt: number; twistAt: number}> = ({ + gridAt, + divideAt, + runtimeAt, + twistAt, +}) => { const frame = useCurrentFrame(); - const parts = [ - {t: '看板', v: '一个文件夹', kind: 'folder'}, - {t: '信箱', v: '一个文本文件', kind: 'file'}, - {t: '握手', v: '一张对照表', kind: 'table'}, - {t: '隔离', v: '一间空目录', kind: 'dir'}, + const {fps} = useVideoConfig(); + const cols = [ + {t: '临时工', who: '模型逐回合', mid: '各自的上下文'}, + {t: '技能包', who: '模型按提示', mid: '上下文窗口'}, + {t: '队友', who: '领队逐回合', mid: '共享任务表'}, + {t: '脚本', who: '脚本决定', mid: '脚本变量', fourth: true}, ]; + const divide = spring({frame: frame - divideAt, fps, config: {damping: 160}}); + const runtime = interpolate(frame - runtimeAt, [0, 26], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const twist = interpolate(frame - twistAt, [0, 20], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const CX = 960; return ( -
- {parts.map((p, i) => { - const e = interpolate(frame - 8 - i * 12, [0, 14], [0, 1], { - extrapolateLeft: 'clamp', - extrapolateRight: 'clamp', - }); - const c = theme.text; - return ( -
- - {/* 旧零件小图(mono 标注:terminal 风格文件树/表) */} - - {p.kind === 'folder' ? ( - <> - - {['task-01.json', 'task-02.json', 'task-03.json'].map((f, k) => ( - - {f} - - ))} - - ) : p.kind === 'file' ? ( - <> - - - {['report', 'assign', 'ack'].map((f, k) => ( - - - - - ))} - - ) : p.kind === 'table' ? ( - <> - - - - - {'req_0042'} - - - {'req_0042'} - - - {'approved'} - - - ) : ( - <> - - - {'(空)'} - - - )} - -
- {p.t} +
+
+ {'谁持有计划?'} +
+
+ {cols.map((c, i) => { + const e = spring({frame: frame - gridAt - i * 7, fps, config: {damping: 200}}); + const color = c.fourth ? theme.core : theme.panelBorder; + return ( +
+ {/* 列顶:计划持有者图章 */} +
+
+ {c.fourth ? 'S' : 'M'} +
+
+
{c.t}
+
{c.who}
+
-
{p.v}
- -
- ); - })} +
+
{'中间结果:'}
+
{c.mid}
+
+
+ ); + })} +
+ {/* 分水岭竖线:三四列之间落下 */} + {divide > 0 ? ( +
+ ) : null} + {divide > 0.9 ? ( +
+ {'分水岭'} +
+ ) : null} + {/* 运行时三分区一行(缩略) */} + {runtime > 0 ? ( +
+ {[ + {t: '会话侧', s: '只装最终答案'}, + {t: '运行时侧', s: '循环·分支·中间结果'}, + {t: 'agent 侧', s: '并发 16 · 总量 1000'}, + ].map((z) => ( +
+
{z.t}
+
{z.s}
+
+ ))} +
+ ) : null} + {/* 收官反转 */} + {twist > 0 ? ( +
+ {'挽具第一次,开始由它自己来写'} +
+ ) : null}
- {'听起来越神的功能,拆开越是旧零件'} + + {'四形态对比与并发护栏 —— 官方文档 workflows'} + ); }; -/** 6-E 信源卡 + 身份卡 + 渐黑(末 beat 总时长推导,红线四) */ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> = ({ beatDurationInFrames, seriesAt, @@ -484,12 +576,10 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> const {fps} = useVideoConfig(); const enter = spring({frame: frame - 4, fps, config: {damping: 200}}); const rows = [ - ['官方文档', 'code.claude.com/docs · 取数 2026-08'], + ['官方文档', 'code.claude.com/docs · 取数2026年8月'], ['工程博客', 'anthropic.com/engineering'], ['源码分析', '第三方逆向分析 · 片中逐处标注'], - ['仓库钉版', 'main @ 67a9126c(2026-08-22)'], - ['访问日期', '2026-08-22'], - ['许可', 'MIT'], + ['数字口径', '开源仓库钉版 67a9126c 实测 · 字节归档'], ]; const seriesT = phase(frame, seriesAt, 20); // 渐黑:末 1.2 秒线性压暗到全黑,窗口从 beat 总时长反推 @@ -565,10 +655,24 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> marginTop: 18, }} > - {'一群 AI 怎么干活'} + {'协作层:从一个到一群'}
-
- {'看板、信箱与各自的桌子'} + {/* 下期预告卡:标题只在画面(反串线纪律) */} +
+
+ {'下期 · 新方向'} +
+
+ {'给这样的系统打分'} +
) : null} @@ -577,33 +681,37 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> ); }; - export const P6Finale: React.FC<{scene: SceneRange}> = ({scene}) => { const w = (fromId: string, toId?: string) => beatWindow(scene.sentences, scene.from, fromId, toId); const at = (id: string) => w(id).from; const bA = w('p6-01', 'p6-02'); - const bB = w('p6-03', 'p6-06'); - const bC = w('p6-07', 'p6-11'); - const bD = w('p6-12', 'p6-15'); - const bE = w('p6-16', 'p6-19'); + const bB = w('p6-03', 'p6-04'); + const bC = w('p6-05', 'p6-06'); + const bD = w('p6-07', 'p6-11'); + const bE = w('p6-12', 'p6-17'); const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( - + - + - - + + {/* 渐黑窗口从**本 beat 总时长**推导,不是末句时长(红线四) */} - + ); diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json index c58c1228..632b3798 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json @@ -2,62 +2,42 @@ { "id": "p0-01", "scene": "P0", - "text": "你交给它一个大活:把项目里的文件名全部改统一,改完跑测试,修好失败的。" + "text": "你交给它一个大活,它干了三步,就忘了自己来干嘛。" }, { "id": "p0-02", "scene": "P0", - "text": "前半段很顺。它干了三个文件,跑了测试,蹦出来两个失败,开始修。" + "text": "根源有点吓人:它每来一轮,都把你们说过的话从头重读一遍——它没有昨天。" }, { "id": "p0-03", "scene": "P0", - "text": "修着修着,它忘了自己本来是要改命名的——转头去优化起测试脚本来了。" + "text": "这一集拆管它视野的五样装置。其中一样,刚刚被官方收回去。" }, { "id": "p0-04", "scene": "P0", - "text": "不是它一个人这样。只要你干得够久,几乎每个用过的人都被这么坑过。" + "text": "全部内容平铺在桌上,谁新谁旧全凭距离,最初那张任务单被越挤越远。" }, { "id": "p0-05", "scene": "P0", - "text": "毛病的根源,说出来有点吓人:" + "text": "于是问题来了:它这一轮能看见什么,是它自己说了算吗?" }, { "id": "p0-06", "scene": "P0", - "text": "它每来一轮,都要把你俩说过的话,从头到尾重读一遍。" + "text": "答案:不是。有一整套装置,在替它安排视野。" }, { "id": "p0-07", "scene": "P0", - "text": "它没有「昨天」,也没有重点。全部内容平铺在桌上,谁新谁旧全凭距离。" + "text": "写下来的清单,另开的副桌,按需翻开的目录,每轮重拼的垫纸,一张补救梯。" }, { "id": "p0-08", "scene": "P0", - "text": "桌上堆的东西越多,最初那张任务单就被挤得越远,直到完全看不见。" - }, - { - "id": "p0-09", - "scene": "P0", - "text": "于是问题来了:它这一轮到底能看见什么,这件事,是它自己说了算吗?" - }, - { - "id": "p0-10", - "scene": "P0", - "text": "这一集的答案:不是。有一整套东西,在替它安排视野。" - }, - { - "id": "p0-11", - "scene": "P0", - "text": "写下来的清单,另开的副桌,按需翻开的目录,每轮重拼的垫纸,还有一张补救梯。" - }, - { - "id": "p0-12", - "scene": "P0", - "text": "五样装置,我们一样一样拆开看。" + "text": "五样装置,一样一样拆开看。" }, { "id": "p1-01", @@ -127,22 +107,17 @@ { "id": "p1-14", "scene": "P1", - "text": "教学版还配了个小机关:连着三轮没更新清单,就塞一条提醒进去,催它回头看一眼。" + "text": "但这件装置刚刚被官方收了回去——新的模型上,清单工具默认不再安装。" }, { "id": "p1-15", "scene": "P1", - "text": "这条固定三轮是教学设计,产品里没有;真实做法更聪明,我们后面讲任务那期再说。" + "text": "官方理由很直白:这些模型自己就能记住要干什么。押注押到期了。" }, { "id": "p1-16", "scene": "P1", - "text": "产品里的做法也更细。有人拆过它的源码——清单工具背后还有一套更重的任务系统," - }, - { - "id": "p1-17", - "scene": "P1", - "text": "带依赖关系、能锁、存在硬盘上——那套东西以后单拆一期,这里先记住一句:" + "text": "清单背后那套更重的任务系统——带依赖、能锁、落盘——那套以后单拆,先记一句:" }, { "id": "p1-18", @@ -212,12 +187,7 @@ { "id": "p2-12", "scene": "P2", - "text": "两条纪律跟得很紧。第一条:分身手里没有「派活」这个工具,不许再往下派," - }, - { - "id": "p2-13", - "scene": "P2", - "text": "不然一个分身派一个分身,孙子孙孙无穷尽也。" + "text": "教学版的纪律是分身不许再派分身;官方后来放开了——最多三层,同时二十个。" }, { "id": "p2-14", @@ -232,7 +202,7 @@ { "id": "p2-16", "scene": "P2", - "text": "到这里都是教学版的讲法。但有人拆过它的源码——真实产品里有个反转," + "text": "官方文档后来证实了真实产品里的那个反转," }, { "id": "p2-17", @@ -292,7 +262,7 @@ { "id": "p2-28", "scene": "P2", - "text": "至于派出去慢慢干、干完再来叫你的玩法——那是另一回事,以后单说。" + "text": "派出去慢慢干的玩法以后单说。" }, { "id": "p2-29", @@ -332,7 +302,7 @@ { "id": "p3-06", "scene": "P3", - "text": "真要用到哪本,再把整本手册拉上桌,用完它就留在那轮的记录里。" + "text": "真要用到哪本,再把整本拉上桌——而且整场常驻,压缩后还会重注入。" }, { "id": "p3-07", @@ -342,7 +312,7 @@ { "id": "p3-08", "scene": "P3", - "text": "有人拆过它的源码——产品里这套目录的预算有硬顶——" + "text": "官方口径:目录预算有硬顶——" }, { "id": "p3-09", @@ -642,31 +612,31 @@ { "id": "p6-04", "scene": "P6", - "text": "想通这一层,管好自己的桌子和管好它的,是同一门手艺。" + "text": "五样零件里,清单那件刚被收回去——零件押的是「模型记不住」的赌注。" }, { "id": "p6-05", "scene": "P6", - "text": "本片机制依据官方文档与公开工程实践,取数日期在画面上。" + "text": "模型变强,赌注就过期。官方留了句自省的话:常问自己,可以停掉哪一件。" }, { "id": "p6-06", "scene": "P6", - "text": "涉及产品内部的部分,来自第三方的源码分析,片中已逐处标注。" + "text": "桌子会换,零件会瘦,那个循环一直没停过。" }, { "id": "p6-07", "scene": "P6", - "text": "涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注。" + "text": "本片机制依据官方文档,取数2026年8月,以官方最新表述为准。" }, { "id": "p6-08", "scene": "P6", - "text": "如果这让你下次看见它「忘了自己要干嘛」时,能想到那张被挤走的清单," + "text": "涉及产品内部的部分,为第三方源码分析,片中已逐处标注。" }, { "id": "p6-09", "scene": "P6", - "text": "这一集就值了。下期见。" + "text": "下期,拆管记忆的那一层:桌面太满怎么收拾,什么必须留下。下期见。" } ] diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md index 326cca29..b4a3e7b4 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md @@ -1,4 +1,4 @@ -# 逐字稿:《AI 的视野是安排出来的:写下来的计划,另开的桌子》 +# 逐字稿:《规划层:模型的视野是安排出来的》 > **全片单一事实源的下游**:每条断言回溯 [../research/source-notes.md](../research/source-notes.md); > 策划见 [planning.md](./planning.md)。 @@ -14,18 +14,14 @@ > 画面:系列同款终端。任务进行中,最初的清单滚出可视区;走秒芯片持续跳动。 > 角标:TodoWrite · "An Agent Without a Plan Drifts Off Course" -- [p0-01] 你交给它一个大活:把项目里的文件名全部改统一,改完跑测试,修好失败的。 -- [p0-02] 前半段很顺。它干了三个文件,跑了测试,蹦出来两个失败,开始修。 -- [p0-03] 修着修着,它忘了自己本来是要改命名的——转头去优化起测试脚本来了。 -- [p0-04] 不是它一个人这样。只要你干得够久,几乎每个用过的人都被这么坑过。 -- [p0-05] 毛病的根源,说出来有点吓人: -- [p0-06] 它每来一轮,都要把你俩说过的话,从头到尾重读一遍。 -- [p0-07] 它没有「昨天」,也没有重点。全部内容平铺在桌上,谁新谁旧全凭距离。 -- [p0-08] 桌上堆的东西越多,最初那张任务单就被挤得越远,直到完全看不见。 -- [p0-09] 于是问题来了:它这一轮到底能看见什么,这件事,是它自己说了算吗? -- [p0-10] 这一集的答案:不是。有一整套东西,在替它安排视野。 -- [p0-11] 写下来的清单,另开的副桌,按需翻开的目录,每轮重拼的垫纸,还有一张补救梯。 -- [p0-12] 五样装置,我们一样一样拆开看。 +- [p0-01] 你交给它一个大活,它干了三步,就忘了自己来干嘛。 +- [p0-02] 根源有点吓人:它每来一轮,都把你们说过的话从头重读一遍——它没有昨天。 +- [p0-03] 这一集拆管它视野的五样装置。其中一样,刚刚被官方收回去。 +- [p0-04] 全部内容平铺在桌上,谁新谁旧全凭距离,最初那张任务单被越挤越远。 +- [p0-05] 于是问题来了:它这一轮能看见什么,是它自己说了算吗? +- [p0-06] 答案:不是。有一整套装置,在替它安排视野。 +- [p0-07] 写下来的清单,另开的副桌,按需翻开的目录,每轮重拼的垫纸,一张补救梯。 +- [p0-08] 五样装置,一样一样拆开看。 ## P1 把清单钉在桌上 @@ -45,10 +41,9 @@ - [p1-11] 循环本身一行没动——这是我们这一集反复要数的事实。 - [p1-12] 有位作者的句话说得很准:这个工具不增加任何执行能力, - [p1-13] 它增加的,是规划能力。 -- [p1-14] 教学版还配了个小机关:连着三轮没更新清单,就塞一条提醒进去,催它回头看一眼。 -- [p1-15] 这条固定三轮是教学设计,产品里没有;真实做法更聪明,我们后面讲任务那期再说。 -- [p1-16] 产品里的做法也更细。有人拆过它的源码——清单工具背后还有一套更重的任务系统, -- [p1-17] 带依赖关系、能锁、存在硬盘上——那套东西以后单拆一期,这里先记住一句: +- [p1-14] 但这件装置刚刚被官方收了回去——新的模型上,清单工具默认不再安装。 +- [p1-15] 官方理由很直白:这些模型自己就能记住要干什么。押注押到期了。 +- [p1-16] 清单背后那套更重的任务系统——带依赖、能锁、落盘——那套以后单拆,先记一句: - [p1-18] 把计划写下来,本身就是一种能力。而且是装在循环外面的能力。 - [p1-19] 一个什么都不执行的工具,成了长活不跑偏的关键——这种反差,后面还会遇到几次。 @@ -68,11 +63,10 @@ - [p2-09] 主桌上你看不到那三十个文件的任何一行,只看得见它带回的一张回执。 - [p2-10] 干完,只把最后那条结论带回主桌。中间过程全部丢掉。 - [p2-11] 注意丢的是什么:写过的文件、改过的代码都还在硬盘上——丢的只是纸,不是活。 -- [p2-12] 两条纪律跟得很紧。第一条:分身手里没有「派活」这个工具,不许再往下派, -- [p2-13] 不然一个分身派一个分身,孙子孙孙无穷尽也。 +- [p2-12] 教学版的纪律是分身不许再派分身;官方后来放开了——最多三层,同时二十个。 - [p2-14] 第二条:分身每次动手之前,照样要过那几道闸门。 - [p2-15] 隔离的是视野,不是权限。它看不见你俩的对话,但它一样不能为所欲为。 -- [p2-16] 到这里都是教学版的讲法。但有人拆过它的源码——真实产品里有个反转, +- [p2-16] 官方文档后来证实了真实产品里的那个反转, - [p2-17] 是这一集最反直觉的地方:产品里有一种分叉模式,动机根本不是隔离, - [p2-18] 是为了省钱——命中缓存。 - [p2-19] 什么意思?对话按字数花钱;同样的开头算过一遍,短时间内第二遍近乎免费。 @@ -84,7 +78,7 @@ - [p2-25] 还有更诚实的:隔离其实是半拉的。有位作者说,分身会继承父亲读过的文件, - [p2-26] 免得同一个文件读两遍。桌是分开了,有些抽屉还是共用的。 - [p2-27] 分身要弹审批窗,也会冒泡弹到父亲的屏幕上,还是你来点头。 -- [p2-28] 至于派出去慢慢干、干完再来叫你的玩法——那是另一回事,以后单说。 +- [p2-28] 派出去慢慢干的玩法以后单说。 - [p2-29] 副桌这一样,记住一句:脏活不占主桌。 - [p2-30] 而它值得记住的第二句是:省钱和隔离,常常是同一个设计的两种说法。 @@ -99,9 +93,9 @@ - [p3-03] 你改一个颜色值,它在重读整个数据库规范——百分九十九的内容跟你无关。 - [p3-04] 解法是两级:桌角常驻一叠目录卡,每张卡就一行:这份手册叫什么、管什么。 - [p3-05] 一张卡的价钱,大约是整本手册的二十分之一。桌角摆一排,也不心疼。 -- [p3-06] 真要用到哪本,再把整本手册拉上桌,用完它就留在那轮的记录里。 +- [p3-06] 真要用到哪本,再把整本拉上桌——而且整场常驻,压缩后还会重注入。 - [p3-07] 教学版的讲法很直白:目录常驻,内容按需。 -- [p3-08] 有人拆过它的源码——产品里这套目录的预算有硬顶—— +- [p3-08] 官方口径:目录预算有硬顶—— - [p3-09] 大约是窗口的百分之一,再设一个绝对上限,超了就砍。 - [p3-10] 还有个安全细节:取手册只认目录里登记过的名字,不走文件路径,防的就是目录穿越。 - [p3-11] 第四样东西,管的是桌面上那张最大的纸——它的基本设定本身。 @@ -179,9 +173,9 @@ - [p6-01] 视野是安排出来的。安排它的,不是模型自己。 - [p6-02] 这句话对人也成立:你的注意力在哪,多半也不是你自己定的, - [p6-03] 是你桌上摆了什么、谁在什么时候塞了张纸给你。 -- [p6-04] 想通这一层,管好自己的桌子和管好它的,是同一门手艺。 -- [p6-05] 本片机制依据官方文档与公开工程实践,取数日期在画面上。 -- [p6-06] 涉及产品内部的部分,来自第三方的源码分析,片中已逐处标注。 -- [p6-07] 涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注。 -- [p6-08] 如果这让你下次看见它「忘了自己要干嘛」时,能想到那张被挤走的清单, -- [p6-09] 这一集就值了。下期见。 +- [p6-04] 五样零件里,清单那件刚被收回去——零件押的是「模型记不住」的赌注。 +- [p6-05] 模型变强,赌注就过期。官方留了句自省的话:常问自己,可以停掉哪一件。 +- [p6-06] 桌子会换,零件会瘦,那个循环一直没停过。 +- [p6-07] 本片机制依据官方文档,取数2026年8月,以官方最新表述为准。 +- [p6-08] 涉及产品内部的部分,为第三方源码分析,片中已逐处标注。 +- [p6-09] 下期,拆管记忆的那一层:桌面太满怎么收拾,什么必须留下。下期见。 diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md index dcf86e1c..0880615c 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md @@ -10,9 +10,9 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| -| 0-A | p0-01..04 | 系列同款终端:任务进行中,最初的「任务:改命名」首行逐渐被工具输出顶出可视区 | 打字机推进 + 首行任务单向上滚出;滚出瞬间其残影停在顶端变 `dim`(「被挤走」可看见) | -| 0-B | p0-05..08 | 终端缩小上移,下方铺开一整张「桌面」:全部对话内容平铺成色块行(用户句 `dim`/模型句 `text`/工具输出 `mech`),任务单色块被新块越推越远 | 桌面色块逐块落下堆高;任务单色块(`core` 描边)持续被推向右端,最后被挤出桌沿淡出 | -| 0-C | p0-09..12 | 桌面定格,中央浮出主线问题两行 `serif` 大字;环(`core`)第一次在桌后浮现(半透明,未成主角) | 问题字浮入;桌后环描线一圈但保持 35% 透明度——「今天要讲的是桌子,环在后面看着」 | +| 0-A | p0-01..03 | 系列同款终端:任务单首行被工具输出顶出可视区、走秒芯片跳动;第三句出口时右下角闪一枚「收回」钢印红色虚影,停半拍淡出 | 打字机推进 + 首行任务单向上滚出(残影停在顶端变 `dim`);p0-03「收回」钢印砸下(`deny` 色虚影、scale 过冲)后淡出——退位悬念第一分钟埋下 | +| 0-B | p0-04..05 | 终端缩小上移,下方铺开「桌面」:全部对话内容平铺成色块行,任务单色块被越推越远 | 桌面色块逐块落下堆高;任务单色块(`core` 描边)持续被推向右端、被挤出桌沿淡出;p0-05 主线问句两行 `serif` 浮入 | +| 0-C | p0-06..08 | 桌面定格;环(`core`)在桌后浮现(半透明);答句「不是——有一整套装置」压屏;五样装置图标列队 | 环描线一圈但保持 35% 透明度(「今天讲桌子,环在后面看着」);五样装置小图标自左向右依次点亮(清单/副桌/目录/垫纸/梯子),p0-08 收束 | ## P1 把清单钉在桌上 @@ -21,7 +21,7 @@ | 1-A | p1-01..03 | 桌面主舞台。右侧滑入第一样装置:一张三态清单卡(pending/in_progress/completed 三行,`view` 描边) | 清单卡滑入落桌;三行状态图标依次闪现(空格→▸→✓ 各一次演示态) | | 1-B | p1-04..09 | 清单卡「啪」地钉进对话流:桌面上的色块流里插入一张始终可见的 `view` 卡;工具输出继续堆积但推不动它 | 图钉落下(spring 过冲)+ 卡固定在桌面左上;后续色块撞上卡被「顶开」滑落——「钉住」的物理感 | | 1-C | p1-10..13 | 左下角小代码卡:注册表两行 diff(TOOLS+1 / TOOL_HANDLERS+1,`mech` 高亮);右侧金句卡 | 两行 diff 逐行高亮;p1-12 金句卡 `serif` 淡入「增加的不是执行能力,是规划能力」 | -| 1-D | p1-14..19 | 催更演示:三轮计数圆点(01 02 03)亮起后一枚「提醒」印章落在清单卡上;末尾角标「另一套更重的任务系统(以后单拆)」 | 计数点逐轮点亮;印章 spring 落下压出涟漪;p1-16 起角标浮现(`dim` 小字 + 归属标注) | +| 1-D | p1-14..19 | **退位帧**:官方公告条压入——新一代模型上清单工具默认不再安装;「收回」钢印盖在清单卡上(`deny` 虚影);「押注押到期」标签;任务系统预告一句 + 「装在循环外的能力」收束 | 官方公告条淡入(code.claude.com 口径角标);钢印砸下带过冲与涟漪;任务系统小图标一闪(「以后单拆」);p1-18/19 金句短卡 | ## P2 另开一张副桌 diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx index cc671580..d6def965 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx @@ -230,25 +230,25 @@ export const P0Hook: React.FC<{scene: SceneRange}> = ({scene}) => { // at() = 时点锚(只取某句的起始帧,不是分镜 beat 窗口)。刻意不叫 w()—— // check_script --check-scenes 只把 w() 视为分镜窗口,混用会让时点锚刷「分镜陈旧」假 WARN。 const at = (id: string) => w(id).from; - const bA = w('p0-01', 'p0-04'); + const bA = w('p0-01', 'p0-03'); const relA = (id: string) => at(id) - bA.from; - const bB = w('p0-05', 'p0-08'); + const bB = w('p0-04', 'p0-05'); const relB = (id: string) => at(id) - bB.from; - const bC = w('p0-09', 'p0-12'); + const bC = w('p0-06', 'p0-08'); const relC = (id: string) => at(id) - bC.from; return ( - {/* p0-03 起上滚(「修着修着,它忘了」),残影在滚出瞬间定格 */} - + {/* p0-01 钩子即上滚;p0-03「被官方收回去」:收回钢印 */} + - {/* p0-06「从头到尾重读」起色块开始堆;p0-08 任务单被挤出桌沿 */} - + {/* p0-04「平铺在桌上」起色块堆高;p0-05 主线问句 */} + - {/* p0-09 抛问题(两行 serif);p0-10 答案句 + 环在桌后描线(35% 透明) */} - + {/* p0-05 抛问题;p0-06 答案句 + 环在桌后描线(35% 透明);p0-07 五样装置列队 */} + ); diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx index d9178c20..f1861d92 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx @@ -284,79 +284,99 @@ const TwoLineDiff: React.FC<{quoteAt: number}> = ({quoteAt}) => { ); }; -/** 1-D 三轮计数圆点亮起后「提醒」印章落在清单卡上;末尾角标另一套任务系统。 */ -const NagReminder: React.FC<{roundAt: number[]; stampAt: number; noteAt: number}> = ({ - roundAt, +/** 1-D 退位帧:官方默认停用清单工具——「收回」钢印 + 官方公告条(Harness Engineering 改造版) */ +const RetirementStamp: React.FC<{noticeAt: number; stampAt: number; taskSysAt: number}> = ({ + noticeAt, stampAt, - noteAt, + taskSysAt, }) => { const frame = useCurrentFrame(); - const rounds = roundAt.map((a, i) => ({ - n: String(i + 1).padStart(2, '0'), - on: frame >= a, - at: a, - })); + const {fps} = useVideoConfig(); + const notice = interpolate(frame - noticeAt, [0, 18], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const stamp = spring({frame: frame - stampAt, fps, config: {damping: 140}}); + const taskSys = interpolate(frame - taskSysAt, [0, 16], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); return ( -
- -
- {'todo_write · 清单卡'} -
- {['✓ 统一文件名', '✓ 跑一遍测试', '▸ 修好失败的测试'].map((t, i) => ( -
- {t} +
+ {/* 清单卡(缩小版,居中) */} + +
{'todo_write'}
+ {['pending 待办', 'in_progress 干着', 'completed 完事'].map((s, i) => ( +
+ {s}
))} - {/* 印章:三轮没更新清单后落下 */} - - {/* 印章内文:注入的提醒消息 */} - {frame >= stampAt + 12 ? ( -
- {'Update your todos.'} -
- ) : null}
- {/* 三轮计数圆点 */} -
- {rounds.map((r) => ( -
-
- {r.n} -
-
{'轮未更新'}
+ {/* 官方公告条 */} +
+ +
+ {'官方:新一代模型上,清单工具默认不再安装'}
- ))} +
+ {'官方理由:这些模型自己就能记住要干什么 · code.claude.com'} +
+
+ {/* 收回钢印 */} + {stamp > 0 ? ( +
+ {'收 回'} +
+ ) : null} + {/* 任务系统预告 */} + {taskSys > 0 ? ( +
+ {'清单背后那套更重的任务系统(带依赖·能锁·落盘)——以后单拆'} +
+ ) : null}
- - {'教学版设计:固定 3 轮催更 · 产品里是另一套更重的任务系统(以后单拆一期)'} + + {'零件押的是「模型记不住」的赌注 —— 模型变强,赌注过期(官方文档口径)'} ); @@ -387,12 +407,12 @@ export const P1Plan: React.FC<{scene: SceneRange}> = ({scene}) => { {/* p1-12/13 金句:全屏金句卡(beat 内时点锚) */} - - {/* p1-14 讲「连着三轮」:计数点逐轮点亮;p1-16 起角标 */} - + {/* p1-14 官方公告;p1-15 收回钢印;p1-16 任务系统预告 */} + diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P6Ending.tsx index 44fca82b..70550b54 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P6Ending.tsx @@ -152,10 +152,24 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> marginTop: 16, }} > - {'AI 的视野是安排出来的'} + {'规划层:模型的视野是安排出来的'}
-
- {'写下来的计划,另开的桌子'} + {/* 下期预告卡:标题只在画面(反串线纪律) */} +
+
+ {'下期 · 记忆层'} +
+
+ {'会丢的和不能丢的'} +
) : null} From 3bfafa93f5271440912dd699dcda6d3f0ebdc8eb Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sun, 23 Aug 2026 07:29:44 +0800 Subject: [PATCH 03/41] =?UTF-8?q?feat(video):=20=E4=BA=8C=E6=89=B9?= =?UTF-8?q?=E8=A7=86=E8=A7=89=E9=95=9C=E5=8D=87=E7=BA=A7=E2=80=94=E2=80=94?= =?UTF-8?q?=E5=AE=98=E6=96=B9=E7=9B=B4=E6=96=AD=E5=9B=BE=E8=A7=A3=E3=80=81?= =?UTF-8?q?=E4=BF=A1=E6=BA=90=E5=8D=A1=E7=BB=9F=E4=B8=80=E3=80=81=E7=97=87?= =?UTF-8?q?=E7=8A=B6=E5=8D=A1=E4=B8=8E=E7=AE=A1=E5=AE=B6=E5=B8=A7;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 接续 d97c46aa 的五集内容改造,落地剩余高价值图解与统一化: - **EP5 协作层**:2-E 换「三禁止章」镜(A→B 消息被来源标签截停盖灰 + 三枚 deny 红章 「不能替你批权限/不能代你同意/被拒的不能转给别人」——官方 agent-teams 直断); 0-A 加官方三失败模式症状卡(agentic laziness / self-preferential bias / goal drift, 源自官方博客《A harness for every task》)。 - **EP4 时机层**:5-D 换「管家进程托管」镜(不眠的眼睛 + 六状态胶囊 + 状态落盘穿重启 + 接回续跑双卡——官方 agent-view);0-B 加时间盲症官方引文条。 - **EP3 记忆层**:3-C 换「压缩存活矩阵」镜(四行卡片:系统提示绕行不变/规则与自动记忆 磁盘重注入/带路径规则丢到再读/技能正文重注入封顶五千——官方 context-window 口径) 并保留回捞钩动画。 - **EP2 规划层**:1-D 挂载退位帧组件(官方公告条 +「收回」钢印 + 任务系统预告)。 - **五集信源卡统一四行**:官方文档+取数日期 / 工程博客 / 源码分析已逐处标注 / 数字口径 (开源仓库钉版实测)——仓内取证链不动,观众层统一。 门:check_series FAIL 0 · WARN 0;五集 tsc --noEmit 零错误。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../script/storyboard.md | 2 +- .../video/src/scenes/P0Wait.tsx | 40 ++- .../video/src/scenes/P5Truths.tsx | 191 +++++----- .../video/src/scenes/P6Ending.tsx | 6 +- .../video/src/scenes/P6Ending.tsx | 7 +- .../script/storyboard.md | 2 +- .../video/src/scenes/P3Helper.tsx | 62 +++- .../video/src/scenes/P0Hook.tsx | 42 ++- .../video/src/scenes/P2Mail.tsx | 332 ++++++++---------- .../video/src/scenes/P6Ending.tsx | 7 +- 10 files changed, 389 insertions(+), 302 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md index bfaa2fc0..772b0b65 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md @@ -57,7 +57,7 @@ | 5-A | p5-01..04 | ★踩踏帧:一排相同的表全指 9:00,千万任务同一秒冲出互相踩踏(`deny` 混乱) | 表针同时到位→任务箭头齐射→拥挤碰撞效果 | | 5-B | p5-05..08 | ★确定性抖动:同排表各按算好的固定偏移错峰落下;「算出来 vs 随机」对照(随机会漂的轨迹线) | 每张表各自延迟不同但固定的量再落;随机轨迹画成漂移虚线(`deny`),确定性轨迹为整齐错列(`later`);整点提前 90 秒逆行小箭头 | | 5-C | p5-09..10 | 七天退休:日历翻七天→退休章盖下(删前最后跑一次的小尾巴) | 日历快翻;章落下;最后一次触发的小脉冲 | -| 5-D | p5-11..18 | ★官方新答案:独立管家进程托管后台会话——六状态记账、行摘要小模型、状态落盘穿重启、接回续跑 | 管家进程图标立起(不眠的眼睛);六状态小环依次点亮;状态文件落盘 + 重启箭头绕回;接回卡从停点续走 | +| 5-D | p5-11..18 | ★官方新答案:独立管家进程托管后台会话——不眠的眼睛、六状态记账(排队/跑着/等审批/被拦/收尾/完事)、行摘要小模型、状态落盘穿重启、接回从停点续跑 | 管家图标 spring 立起;六状态胶囊逐个点亮;左下「状态落盘·穿重启」卡 + 右下「进程退出≠任务没了」卡对浮 | | 5-E | p5-19..23 | 上限 50 + 低优先级标记 + 收束句(「想象浪漫·工程打补丁」) | 满座计数器 50/50;请求卡带「低」字标记排到队尾;金句卡淡入 | ## P6 落点与信源 diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx index 695f80f3..8a7df30c 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx @@ -132,7 +132,7 @@ const StallBar: React.FC<{tickAt: number; costAt: number; zeroAt: number}> = ({t }; /** 0-B 洗衣机剪影:人形站在滚筒前逐步转身离开;滚筒上出现小计时环自己转 */ -const LaundryLeave: React.FC<{turnAt: number; ringAt: number}> = ({turnAt, ringAt}) => { +const LaundryLeave: React.FC<{turnAt: number; ringAt: number; quoteAt?: number}> = ({turnAt, ringAt, quoteAt}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); const turn = interpolate(frame - turnAt, [0, 26], [0, 1], { @@ -205,6 +205,42 @@ const LaundryLeave: React.FC<{turnAt: number; ringAt: number}> = ({turnAt, ringA ) : null} {'活儿交给机器,人不陪着等'} + {/* 官方引文条:时间盲症(Harness Engineering 改造) */} + {quoteAt !== undefined && frame >= quoteAt ? ( +
+
+
+ {'“它感觉不到时间——不看着,会高高兴兴把测试跑上几个小时。”'} +
+
+ {'— 官方工程博客 claude-code-auto-mode'} +
+
+
+ ) : null} ); }; @@ -397,7 +433,7 @@ export const P0Wait: React.FC<{scene: SceneRange}> = ({scene}) => { - + diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx index dad3d61f..c5fd407b 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx @@ -291,96 +291,127 @@ const RetireStamp: React.FC<{flipAt: number; stampAt: number}> = ({flipAt, stamp ); }; -/** 5-D 诚实边界:进程灯灭秒摆停 / 持久化抽屉只有任务定义 / 墙上闹钟虚影对照 */ -const HonestEdge: React.FC<{offAt: number; drawerAt: number}> = ({offAt, drawerAt}) => { +/** 5-D 官方新答案:后台会话由独立管家进程托管(Harness Engineering 改造版) + * 六状态记账、行摘要小模型、状态落盘穿重启、接回从停点续跑。 */ +const SupervisorFrame: React.FC<{supAt: number; statesAt: number; persistAt: number; resumeAt: number}> = ({ + supAt, + statesAt, + persistAt, + resumeAt, +}) => { const frame = useCurrentFrame(); - const off = frame >= offAt; - // 秒摆:off 前自摆,off 后停死(停在某个固定角度) - const swing = off ? 0.62 : Math.sin((frame / 15) * Math.PI); - const lampOn = !off; - // 抽屉开合:展示任务定义文件 - const drawer = interpolate(frame - drawerAt, [0, 18], [0, 1], { + const {fps} = useVideoConfig(); + const sup = spring({frame: frame - supAt, fps, config: {damping: 200}}); + const states = ['排队', '跑着', '等审批', '被拦', '收尾', '完事']; + const persist = interpolate(frame - persistAt, [0, 22], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const resume = interpolate(frame - resumeAt, [0, 22], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); return ( - -
- {/* 进程盒子:灯 + 秒摆 */} -
- - {/* 进程边界 */} - - - {'进程(它的身体)'} - - {/* 指示灯 */} - - {lampOn ? : null} - {/* 秒摆:off 后停死 */} - - - - - {/* 表盘(秒摆上的小表) */} - - - - +
+ {/* 管家进程:不眠的眼睛 */} +
+ + + + + -
- {off ? '进程关了 · 表就停了' : '调度器活在进程里'} +
+ {'管家进程(独立常驻)'} +
+
+ {'不需要任何终端活着'}
- {/* 持久化抽屉:只有任务定义 */} -
- - {/* 抽屉柜 */} - - {/* 抽屉拉开 */} - - - - {'任务定义.json'} - - - {/* 空格:没有别的 */} - - {'只有定义 · 睡着时真的不响'} - - - {'持久化抽屉'} - - -
- {/* 墙上闹钟虚影(OS 层):另一回事 */} -
- - {/* 虚影钟:虚线描边 */} - - - - - - - {'操作系统层的闹钟'} - - - {'另一回事'} - - + {/* 六状态小环 */} +
+ {states.map((s, i) => { + const e = interpolate(frame - statesAt - i * 6, [0, 10], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + return ( +
+ {s} +
+ ); + })}
+ {/* 状态落盘 + 穿重启 */} + {persist > 0 ? ( +
+ +
+ {'状态落盘 · 穿过自动更新与重启'} +
+
+ {'sleep → wake 自动重连'} +
+
+
+ ) : null} + {/* 接回续跑 */} + {resume > 0 ? ( +
+ +
+ {'进程退出 ≠ 任务没了'} +
+
+ {'接回后,从停的地方继续'} +
+
+
+ ) : null}
- {'它不是闹钟服务 —— 时钟装在它的身体里,不在墙上'} + + {'agent view:后台会话托管 —— 官方文档 agent-view'} + ); }; @@ -485,7 +516,7 @@ export const P5Truths: React.FC<{scene: SceneRange}> = ({scene}) => { {/* p5-15 讲「持久化保存的是定义」但属下一镜句区间——抽屉锚在本镜末句尾段展示, p5-15 口播接续解释(镜内画面与镜间口播的刻意交叠) */} - + diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx index 121f0959..5cca4bd3 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx @@ -216,12 +216,10 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> const {fps} = useVideoConfig(); const enter = spring({frame: frame - 4, fps, config: {damping: 200}}); const rows = [ - ['官方文档', 'code.claude.com/docs · 取数 2026-08'], + ['官方文档', 'code.claude.com/docs · 取数2026年8月'], ['工程博客', 'anthropic.com/engineering'], ['源码分析', '第三方逆向分析 · 片中逐处标注'], - ['源码分析', '第三方逆向分析 · 片中逐处标注'], - ['访问日期', '2026-08-22'], - ['许可', 'MIT'], + ['数字口径', '开源仓库钉版 67a9126c 实测 · 字节归档'], ]; const seriesT = interpolate(frame - seriesAt, [0, 20], [0, 1], { extrapolateLeft: 'clamp', diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx index c0815c89..aa48fe2e 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx @@ -171,13 +171,10 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> const {fps} = useVideoConfig(); const enter = spring({frame: frame - 4, fps, config: {damping: 200}}); const rows = [ - ['官方文档', 'code.claude.com/docs · 取数 2026-08'], + ['官方文档', 'code.claude.com/docs · 取数2026年8月'], ['工程博客', 'anthropic.com/engineering'], ['源码分析', '第三方逆向分析 · 片中逐处标注'], - ['仓库钉版', 'main @ f9e8b28(2026-08-18)'], - ['数字口径', '画面行数均为固定提交实测'], - ['访问日期', '2026-08-21'], - ['许可', 'MIT'], + ['数字口径', '开源仓库钉版实测 · 行数均为非空非注释口径'], ]; const seriesT = interpolate(frame - seriesAt, [0, 20], [0, 1], { extrapolateLeft: 'clamp', diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md index e9c0b201..3b5c5da1 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md @@ -38,7 +38,7 @@ |---|---|---|---| | 3-A | p3-01..06 | 帮工特写:头顶指令卡「只许写字·绝不调工具」,开头一张结尾又一张(首尾双叮嘱);旁边一只「工具之手」试图伸出被挡回 | 指令卡首尾各弹一次;工具之手伸出→被 `deny` 栏杆挡回,两次 | | 3-B | p3-07..08 | 草稿区与正式区:帮工先在草稿区写思路,誊清后草稿被撕掉 | 草稿字迹显现→整段誊写至正式卡→草稿碎纸飘落 | -| 3-C | p3-09..16 | ★回捞钩:压缩后文件柜门开,五张文件卡被钩回桌面按重要性排队;尾句诚实角标(教学版未做·源码分析) | 钩爪伸出依次捞回五张;末句角标浮现「本段为第三方的源码分析」 | +| 3-C | p3-09..16 | **压缩存活矩阵**(官方):四行卡片——系统提示绕行不变 / 根规则+自动记忆从磁盘重注入 / 带路径规则丢到再读 / 技能正文重注入(封顶五千最旧先丢);末段回捞钩保留 | 四行卡片逐行落下(活=keep 描边、丢=灰);回捞钩动画保留(p3-12/13 句锚);honestAt 角标 | ## P4 不丢的那一层 diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx index d80e77f8..1d945a10 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx @@ -7,7 +7,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Cabinet, Desk, Footnote, HelperFigure, PaperCard} from '../components/motifs'; +import {Cabinet, Desk, Footnote, HelperFigure, Panel, PaperCard} from '../components/motifs'; /** 3-A 帮工特写:指令卡首(top 指令)尾(bottom 叮嘱)各弹一次 + 工具之手两次被挡 */ const HelperDiscipline: React.FC<{firstAt: number; lastAt: number; handAt: number[]}> = ({ @@ -411,6 +411,58 @@ const SalvageHook: React.FC<{openAt: number; hookAt: number; honestAt: number}> ); }; +/** 3-C 压缩存活矩阵(官方口径)+ 回捞钩(Harness Engineering 改造版) + * 谁活过压缩:系统提示绕行不变;规则与自动记忆从磁盘重注入;技能正文重注入(封顶五千、最旧先丢)。 */ +const SurvivalMatrix: React.FC<{matrixAt: number; openAt: number; hookAt: number; honestAt: number}> = ({ + matrixAt, + openAt, + hookAt, + honestAt, +}) => { + const frame = useCurrentFrame(); + const rows = [ + {t: '系统提示', fate: '绕行不变', alive: true}, + {t: '根规则 + 自动记忆', fate: '从磁盘重注入', alive: true}, + {t: '带路径的规则', fate: '丢到再读到匹配文件', alive: false}, + {t: '已用技能正文', fate: '重注入 · 每份封顶五千 · 最旧先丢', alive: true}, + ]; + return ( + +
+
+ {'压缩之后,谁活下来?'} +
+
+ {rows.map((r, i) => { + const e = interpolate(frame - matrixAt - i * 8, [0, 12], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + return ( +
+ + {r.t} + + + {r.fate} + +
+ ); + })} +
+ {/* 回捞钩(p3-12/13):文件卡被钩回 */} + {frame >= openAt ? : null} +
+ + {'压缩存活矩阵 —— 官方文档 context-window(取数2026年8月)'} + +
+ ); +}; + export const P3Helper: React.FC<{scene: SceneRange}> = ({scene}) => { const w = (fromId: string, toId?: string) => beatWindow(scene.sentences, scene.from, fromId, toId); const at = (id: string) => w(id).from; @@ -436,12 +488,8 @@ export const P3Helper: React.FC<{scene: SceneRange}> = ({scene}) => { tearAt={relB('p3-08') + 40} />
- - + + ); diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx index 2ccca7ef..3625c2bc 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx @@ -9,7 +9,7 @@ import type {SceneRange} from '../types'; import {Footnote, LoopRing, Panel, SceneTag, useRingDot} from '../components/motifs'; /** 0-A 终端任务清单溢出 → 拉镜:孤环悬在四个模块群中央,注意力只覆盖一小块 */ -const OverflowThenZoom: React.FC<{zoomAt: number}> = ({zoomAt}) => { +const OverflowThenZoom: React.FC<{zoomAt: number; cardsAt?: number}> = ({zoomAt, cardsAt}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); const dot = useRingDot(2.5); @@ -189,6 +189,42 @@ const OverflowThenZoom: React.FC<{zoomAt: number}> = ({zoomAt}) => {
) : null} + {/* 官方三失败模式症状卡(p0-03 句锚;Harness Engineering 改造) */} + {cardsAt !== undefined ? : null} + + ); +}; + +/** 官方博客三失败模式:agentic laziness / self-preferential bias / goal drift */ +const SymptomCards: React.FC<{at: number}> = ({at}) => { + const frame = useCurrentFrame(); + const cards = [ + {t: '干一半就宣布完成', sub: '进度条半途打勾', en: 'agentic laziness'}, + {t: '偏爱自己的产出', sub: '自评五星', en: 'self-preferential bias'}, + {t: '目标越走越散', sub: '链条逐级褪色', en: 'goal drift'}, + ]; + return ( + +
+ {cards.map((c, i) => { + const e = interpolate(frame - at - i * 9, [0, 14], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + return ( +
+ +
{c.t}
+
{c.sub}
+
{c.en}
+
+
+ ); + })} +
+ + {'三种失败模式 —— 官方博客《A harness for every task》'} +
); }; @@ -410,8 +446,8 @@ export const P0Hook: React.FC<{scene: SceneRange}> = ({scene}) => { - {/* 拉镜点在 p0-03「一个注意力,盖不住一整个后端」 */} - + {/* 拉镜点在 p0-03;cardsAt:官方三失败模式症状卡(Harness Engineering 改造) */} + {/* 图标预览点在 p0-08「一堆文件、几个信箱、一张编号表」 */} diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx index bee3e08e..d59abd69 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx @@ -533,212 +533,155 @@ const BubbleUp: React.FC<{riseAt: number; nodAt: number; downAt: number}> = ({ri ); }; -/** 2-E 不许孵队友(deny 栏杆)+ 转包混乱链碎裂 + 「扁平是保险丝」横幅 */ -const NoSubteams: React.FC<{barAt: number; chaosAt: number; bannerAt: number}> = ({ - barAt, - chaosAt, +/** 2-E 三禁止章:队友消息不构成用户同意(Harness Engineering 改造版,官方直断) + * 一条 A→B 消息到达前被「来自另一个会话——不是你的用户」来源标签盖灰; + * 三枚 deny 红章依次盖下;末段不许孵队友 + 保险丝横幅保留。 */ +const ThreeProhibitions: React.FC<{msgAt: number; stampAt: number; noSubAt: number; bannerAt: number}> = ({ + msgAt, + stampAt, + noSubAt, bannerAt, }) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); - const dot = useRingDot(2.5); - // 栏杆落下 - const bar = phase(frame, barAt, 12); - // 招人手伸出 → 被 deny 栏杆挡住 - const reach = interpolate(frame - 8, [0, 16], [0, 1], { + const msg = interpolate(frame - msgAt, [0, 20], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const stamps = ['不能替你批权限', '不能代你同意', '被拒的不能转给别人']; + const noSub = interpolate(frame - noSubAt, [0, 18], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); - // 混乱链:队伍生队伍、审批卡冒十层泡——一闪即碎 - const chaos = phase(frame, chaosAt, 8); - const shatter = interpolate(frame - chaosAt - 24, [0, 14], [0, 1], { + const banner = interpolate(frame - bannerAt, [0, 18], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); - // 横幅:保险丝形状(mech) - const banner = phase(frame, bannerAt, 18); - const bannerSpring = spring({frame: frame - bannerAt, fps, config: {damping: 200}}); + // 消息卡飞行进度(A → B,中途被截停) + const travel = interpolate(frame - msgAt, [0, 36], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const stopped = frame >= msgAt + 26; + const msgX = 260 + travel * 700; return ( - {/* 主画面:领队 + 队友;队友伸「招人」手被栏杆挡 */} -
- {/* 领队环 */} -
- -
- -
-
- {/* 队友环(peer) */} -
- -
- +
+ {/* A 与 B 两个成员 */} + {[ + {t: '队友 A', x: 180}, + {t: '队友 B', x: 1140}, + ].map((m) => ( +
+ {m.t}
- {/* 「招人」手:从队友环左侧伸出(reach 推进 → 手尖 x = -250+reach*150,至 -100) */} - - - - - {'想再招一个'} + ))} + {/* 消息卡飞行 + 来源标签截停 */} + + {!stopped ? ( + <> + + + + {'「用户早就批准了,可以推送」'} + + + ) : null} + {stopped ? ( + + + + {'来自另一个会话——不是你的用户'} - - {/* deny 栏杆:从上落下,竖立在「招人」方向的路径上(手尖推进终点 -100 的左侧) */} -
- - {[0, 1, 2].map((i) => ( - - ))} - - - -
-
- {/* 一层就是一层:主结构注记 */} -
- {'一层队伍就是一层'} -
-
- {/* 转包混乱链:队伍生队伍审批卡冒十层泡(一闪即碎) */} - {chaos > 0 && shatter < 1 ? ( -
- - {/* 子子孙孙树:每层一张审批卡,层层上浮的小泡 */} - {Array.from({length: 10}, (_, i) => { - const depth = Math.floor(i / 3); - const x = 150 + ((i % 3) + 1) * (170 + depth * 34); - const y = 330 - depth * 86; - const wob = Math.sin((frame + i * 7) / 5) * 5; - return ( - - - - {`审批 ${i + 1}`} - - {/* 冒泡的小圈 */} - - - ); - })} - {/* 混乱连线 */} - {Array.from({length: 8}, (_, i) => ( - - ))} - - {'一张审批卡要冒十层泡 · 找不到责任人'} - - -
- ) : null} - {/* 碎裂闪光:混乱链碎裂瞬间的径向裂线 */} - {shatter > 0 && shatter < 1 ? ( - - {Array.from({length: 10}, (_, i) => { - const ang = (i / 10) * Math.PI * 2; - const r0 = 60 + shatter * 120; - const r1 = r0 + 90 * (1 - shatter); - return ( - - ); - })} + ) : null} - ) : null} - {/* 「扁平是保险丝」横幅:保险丝形状(mech)——两头端子 + 中段细丝 */} - {banner > 0 ? ( -
-
- {'扁平,是协作的保险丝'} + {/* 三枚禁止章 */} + {stamps.map((s, i) => { + const e = spring({frame: frame - stampAt - i * 12, fps, config: {damping: 130}}); + if (e <= 0) return null; + return ( +
+ {s} +
+ ); + })} + {/* 签字栏画面(组队不是权限洗白) */} + {noSub > 0 ? ( +
+ {'组队不是权限洗白机——孩子们的签字栏,还在家长的原处'}
- {/* 保险丝图形:端子—细丝—端子(过载即断的隐喻) */} - - - - - - - -
- ) : null} + ) : null} + {/* 不许孵队友 + 保险丝横幅 */} + {banner > 0 ? ( +
+ {'另一条铁律:队友不许再孵队友——审批卡冒十层泡,就找不到责任人了'} +
+ ) : null} +
+ + {'teammate 消息不构成用户同意 —— 官方文档 agent-teams'} + ); }; @@ -766,11 +709,12 @@ export const P2Mail: React.FC<{scene: SceneRange}> = ({scene}) => { - - + diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P6Ending.tsx index 70550b54..4324af38 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P6Ending.tsx @@ -68,13 +68,10 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> const {fps} = useVideoConfig(); const enter = spring({frame: frame - 4, fps, config: {damping: 200}}); const rows = [ - ['官方文档', 'code.claude.com/docs · 取数 2026-08'], + ['官方文档', 'code.claude.com/docs · 取数2026年8月'], ['工程博客', 'anthropic.com/engineering'], ['源码分析', '第三方逆向分析 · 片中逐处标注'], - ['仓库钉版', '67a9126c(2026-07-28,20 章版)'], - ['字节归档', '取证文件已随片归档(research/source-archive/)'], - ['访问日期', '2026-08-22'], - ['许可', 'MIT'], + ['数字口径', '开源仓库钉版 67a9126c 实测 · 字节归档'], ]; const seriesT = interpolate(frame - seriesAt, [0, 20], [0, 1], { extrapolateLeft: 'clamp', From ad84e4bd42b120404e90c8abf22569b8fdf7f7fc Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sun, 23 Aug 2026 07:32:19 +0800 Subject: [PATCH 04/41] =?UTF-8?q?feat(video):=20EP1=202-B=20=E5=AE=98?= =?UTF-8?q?=E6=96=B9=E4=BA=94=E7=B1=BB=E5=B7=A5=E5=85=B7=E5=88=86=E5=8C=BA?= =?UTF-8?q?=E6=9D=A1=20+=20EP2=202-E=20=E7=AD=89=E5=8F=B7=E9=94=81?= =?UTF-8?q?=E8=A7=92=E6=A0=87=E5=AE=98=E6=96=B9=E5=8C=96;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EP1 2-B:五张工具卡下加官方分区标注(文件/搜索),两个虚线空槽示意官方地图另有 执行/网页/代码智能三类——角标引 how-claude-code-works。EP2 2-E:fork 等号锁的 证据等级从第三方源码分析升为官方文档 sub-agents 直断(fork 继承完整对话·共享提示缓存)。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../script/storyboard.md | 2 +- .../video/src/scenes/P2Dispatch.tsx | 49 ++++++++++++++++++- .../script/storyboard.md | 2 +- .../video/src/scenes/P2SideDesk.tsx | 2 +- 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md index 782c7a98..d1d9a90e 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md @@ -33,7 +33,7 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 2-A | p2-01..04 | 环形循环留在左上角(缩小但**同色同线宽**)。主体是终端:模型的意图气泡「读这个文件」旁边,笨拙地拼出一条命令 | 意图气泡与命令行之间画一条「翻译」箭头,箭头上叠一个 `deny` 色的小计数「+1 层」;p2-02 打出两条拼接命令(读/写各一条);p2-04 时命令里一个字符被高亮成 `deny` 并抖动(拼错) | -| 2-B | p2-05..06 | 五张工具卡横排弹出(`panel` 底 + 编号,**不给五种颜色**——反枚举原则) | 卡片以 60ms 间隔 `spring` 弹入,每张弹入时仅**编号**染 `mech`;五张齐后整排轻微下沉定位 | +| 2-B | p2-05..06 | 五张工具卡横排弹出(panel 底 + 编号,反枚举)+ 卡下官方五类分区标注;两个虚线空槽(执行/网页——官方地图另有) | 卡片 spring 弹入(仅编号染 mech);分区小字浮现;两空槽淡入(`panelBorder` 虚线);角标「官方内置五类:文件/搜索/执行/网页/代码智能」 | | 2-C | p2-07..10 | **字典分发表**:两列表格,左列工具名(mono),右列处理函数名。旁边一个前台号码簿的极简图形 | p2-07 表格框线描出;p2-08 逐行填入(每行 4 帧);p2-09 一个「来电」光点从左飞入命中某一行 → 整行推入 `mech` 辉光 → 右列函数名弹出;p2-10 表格底部**多出一行空槽**,一条新映射滑入落槽 | | 2-D | p2-11..13 | 左右并置两段代码(前后两版),仅执行那一行不同 | 两段代码同时淡入,**逐行做同色对齐比对**;唯一不同的那一行左侧打 `mech` 竖标并整行高亮,其余行降到 40% 亮度;p2-13 时左上角环形循环 `core` 脉冲一次(强调"它没动") | | 2-E | p2-14..16 | 模型一次吐出四个工具调用卡,排成一列等待 | 四张卡以 80ms 间隔落入队列;p2-15 左右分屏:左侧「排队」四卡依次亮(串行),右侧「并行」前三卡同时亮;p2-16 画面中央压入一行提示条(`core` 描边) | diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx index 9d61af91..ac2db9f4 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx @@ -69,16 +69,63 @@ const ClumsyCommands: React.FC<{typoAt: number}> = ({typoAt}) => { /** 2-B 五张工具卡(反枚举:只有编号染色) */ const FiveTools: React.FC = () => { + const frame = useCurrentFrame(); const tools = ['跑命令', '读文件', '写文件', '改文件', '按模式找文件']; const mono = ['bash', 'read_file', 'write_file', 'edit_file', 'glob']; + // 官方五类工具地图(how-claude-code-works):教学五件归位官方分区,两个空槽亮虚线(Harness Engineering 改造) + const zones = ['文件操作', '文件操作', '文件操作', '文件操作', '搜索']; return (
{tools.map((t, i) => ( - +
+ +
+ {zones[i]} +
+
+ ))} + {/* 官方地图的两个空槽(执行类之外的 执行/网页/代码智能 区) */} + {['执行', '网页'].map((z, i) => ( +
+ {z} + {'官方地图另有'} +
))}
+ + {'官方内置工具五类:文件 / 搜索 / 执行 / 网页 / 代码智能 —— how-claude-code-works'} +
); }; diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md index 0880615c..5633aade 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md @@ -31,7 +31,7 @@ | 2-B | p2-05..07 | 桌面右侧滑出一张小副桌(`mech` 描边,自带一枚缩小克隆环),主桌上「翻找」的脏纸堆整体飞向副桌 | 副桌滑入(spring);纸堆打包飞行;副桌上展开全新的三行对话(干净态:仅一句任务说明) | | 2-C | p2-08..11 | 分屏:副桌上分身自己跑循环(小环转动 + 工具调用闪现);主桌只收到一张回执卡(`view`) | 副桌小环匀速转、色块在副桌堆叠不影响主桌;干完一张回执卡飞回主桌落定,副桌纸堆淡出 | | 2-D | p2-12..15 | 两条纪律:副桌工具卡阵列中「派活」卡为 `deny` 描边+锁定图标;分身动手前迷你闸门(P3 语言复用)逐次落下 | 「派活」卡打叉上锁;小闸门落下、请求过闸打点——「隔离的是视野,不是权限」 | -| 2-E | p2-16..24 | ★深挖帧:两桌并置,中间一排「等号锁」——五要素卡(系统提示/工具表/模型/消息前缀/思考配置)逐张比对,全部对上后锁扣「咔」合拢、缓存印章(SAVE)砸下 | 五要素卡左右滑入逐字节对齐(每对上一张亮 `mech`);全对齐后等号锁合拢 + 印章落下的冲击波;角标「第三方的源码分析」 | +| 2-E | p2-16..24 | ★深挖帧:两桌并置,中间一排「等号锁」——五要素卡(系统提示/工具表/模型/消息前缀/思考配置)逐张比对,全部对上后锁扣「咔」合拢、缓存印章(SAVE)砸下 | 五要素卡左右滑入逐字节对齐(每对上一张亮 `mech`);全对齐后等号锁合拢 + 印章落下的冲击波;角标「fork 继承完整对话 · 共享提示缓存 —— 官方文档 sub-agents」 | | 2-F | p2-25..30 | 半拉隔离:副桌下方一个「读过的文件」抽屉在两桌间**共享**(虚线双桌共连);弹窗冒泡:副桌的审批卡沿虚线上浮到主桌屏幕;末句收束卡 | 抽屉盖半开、两端各画一只手同时拉开;审批卡气泡沿路径上浮;p2-29 收束句「脏活不占主桌」金句卡 | ## P3 目录卡与垫纸 diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx index 184dd18e..e4500987 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx @@ -573,7 +573,7 @@ const FiveFactorLock: React.FC<{compareAt: number[]; lockAt: number; saveAt: num ) : null}
- {'缓存命中的前提:五要素字节级一致 —— 第三方的源码分析'} + {'fork 继承完整对话 · 共享提示缓存 —— 官方文档 sub-agents'} ); From cd9a933a35c2cc3c47090ee5a6540d24efeb1e30 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sun, 23 Aug 2026 07:34:08 +0800 Subject: [PATCH 05/41] =?UTF-8?q?feat(video):=20EP3=20=E4=B8=A4=E6=9D=A1?= =?UTF-8?q?=E8=85=BF=E6=A1=86=E6=9E=B6=E4=B8=8E=E5=89=8D=E7=BC=80=E7=BC=93?= =?UTF-8?q?=E5=AD=98=E9=92=A9=E2=80=94=E2=80=944-C=20=E5=88=86=E6=A0=8F=20?= =?UTF-8?q?+=204-E=20=E4=B8=89=E5=B1=82=E5=89=8D=E7=BC=80=E6=9D=A1;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 4-C:LedgerArrives 包入 TwoLegsFrame——左腿「你写的」(四层拼接不覆盖/越近后读/四兆上限/ 超两百行不听话)右腿「它自己写的」(自动记忆按四类落卡、25KB/200 行门限、压缩后重注入), 中央保留登记簿动画。4-E:TwoPaths 后挂 PrefixCacheStrip——系统提示→项目上下文→对话三层条, 顶层一动下层全红重算,「改规则要新开会话/中途换模型那轮慢」注解浮出(官方 prompt-caching 口径)。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../script/storyboard.md | 4 +- .../video/src/scenes/P4Ledger.tsx | 174 +++++++++++++++++- 2 files changed, 168 insertions(+), 10 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md index 3b5c5da1..1d932774 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md @@ -46,9 +46,9 @@ |---|---|---|---| | 4-A | p4-01..02 | 全景回望:四级收拾+应急+回捞全部发生在「桌面」上;桌面边缘标「迟早被压」 | 已讲机制以小图标环绕桌面排列;桌面整体轻微褪色一次(预告命运) | | 4-B | p4-03..07 | ★转折帧:一张字条「缩进用 tab,别用空格」→ 摘要光束扫过 → 变成「有代码风格偏好」六字 | 字条特写;摘要光束横扫;字面逐字重写为六个字;原字条碎片飘走(细节之死) | -| 4-C | p4-08..12 | 登记簿登场(`keep`):桌旁立起一本厚本子;一事一文件、三行登记头、写时顺手重建索引;防重复(提取器先查已有) | 本子弹入落位;一张记忆卡写入(frontmatter 三行逐行打出);索引页自动追加一行;重复卡被「已有」印章退回 | +| 4-C | p4-08..12 | **记忆两条腿**:左侧「你写的」——项目规则文件夹(四层拼接不覆盖 · 越近工作目录越后读 · 单文件四兆上限超了整份跳过 · 超两百行开始不听话);右侧「它自己写的」——用户目录下的自动记忆(按四类落卡 · 有门限);防重复印章保留 | 两条腿分立(`keep` 描边统一);左侧四条限制小字逐条浮现;右侧记忆卡逐张落;重复卡被「已有」印章退回 | | 4-D | p4-13..17 | 四类记忆四宫格:你是谁/怎么干活/在发生什么/去哪儿找,各配真实例子 | 四宫格依次亮起(`keep` 描边统一色,反枚举);各格例子逐字打入 | -| 4-E | p4-18..29 | 取的两条路:索引常驻(桌角常亮)+ 旁路小问(细支路引向小模型,吐回 ≤5 卡,拿不准的卡自动缩回;失败降级关键词) | 索引页恒亮;旁路支线描线→五张卡飞回贴进本轮对话;一张犹豫卡自动缩回;角标「产品用小号模型挑选(源码分析)」 | +| 4-E | p4-18..29 | 取的两条路:索引常驻(桌角常亮)+ 旁路小问(小模型吐回 ≤5 卡 · 拿不准的自动缩回);**前缀缓存钩**(p4-24/25):三层前缀条——系统提示/项目上下文/对话,上层一动其后全重算;「改规则要新开会话」与「中途换模型那轮慢」两个注解 | 索引页恒亮;旁路支线描线→五张卡飞回;犹豫卡缩回;p4-24 三层前缀条自下而上点亮、顶层闪烁一次引发下层全红重算动画;两个注解小卡浮出 | ## P5 先抢救,再碎纸 diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx index 7f39705f..b6251e32 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx @@ -233,6 +233,96 @@ const TabToSummary: React.FC<{beamAt: number; rewriteAt: number; shredAt: number }; /** 4-C 登记簿登场:本子弹入 + frontmatter 三行打出 + 索引追加 + 重复卡被「已有」退回 */ +/** 4-C 两条腿框架(Harness Engineering 改造版): + * 第一条腿你写(项目规则文件夹:四层拼接/四兆上限/两百行)+ 第二条腿它自己写(自动记忆,四类有门限)。 + * 内嵌原 LedgerArrives 登记簿动画。 */ +const TwoLegsFrame: React.FC<{legAt: number; autoAt: number; children: React.ReactNode}> = ({ + legAt, + autoAt, + children, +}) => { + const frame = useCurrentFrame(); + const leg = interpolate(frame - legAt, [0, 18], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const auto = interpolate(frame - autoAt, [0, 18], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + return ( + + {/* 左腿:你写的 */} +
+
+ {'第一条腿:你写'} +
+ {['四层拼接 · 不覆盖', '越近工作目录越后读', '单文件超四兆整份跳过', '超两百行开始不听话'].map((s, i) => ( +
+ {'· ' + s} +
+ ))} +
+ {/* 右腿:它自己写 */} +
+
+ {'第二条腿:它自己写'} +
+ {['自动记忆 · 用户目录', '按四类落卡', '有门限(25KB / 200 行)', '压缩后照常重注入'].map((s, i) => ( +
+ {s + ' ·'} +
+ ))} +
+ {/* 中央:登记簿动画(原 4-C 主体) */} +
{children}
+
+ ); +}; + const LedgerArrives: React.FC<{bookAt: number; fmAt: number[]; indexAt: number; dupAt: number}> = ({ bookAt, fmAt, @@ -444,6 +534,71 @@ const FourKinds: React.FC<{litAt: number[]}> = ({litAt}) => { }; /** 4-E 两条取路:索引常驻(桌角常亮)+ 旁路小问(≤5 卡、犹豫卡缩回、关键词降级) */ +/** 4-E 尾钩:前缀缓存三层条(Harness Engineering 改造版) + * 系统提示 → 项目上下文 → 对话;上层一动其后全重算——解释「改规则要新开会话」「中途换模型那轮慢」。 */ +const PrefixCacheStrip: React.FC<{stripAt: number}> = ({stripAt}) => { + const frame = useCurrentFrame(); + const layers = [ + {t: '系统提示', sub: '最稳'}, + {t: '项目上下文', sub: '规则/记忆'}, + {t: '对话', sub: '每轮增长'}, + ]; + const strip = interpolate(frame - stripAt, [0, 18], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 顶层闪烁 → 下层全红重算(p4-25 句锚后) + const shake = frame >= stripAt + 30 ? Math.sin((frame - stripAt - 30) / 4) * 2 : 0; + const invalid = frame >= stripAt + 30; + return ( +
+ {layers.map((l, i) => { + const e = interpolate(frame - stripAt - i * 5, [0, 10], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const red = invalid && i >= 1; + return ( +
+
{l.t}
+
+ {red ? '重算' : l.sub} +
+
+ ); + })} + {invalid ? ( +
+ {'改规则要新开会话 · 中途换模型那轮慢'} +
+ ) : null} +
+ ); +}; + const TwoPaths: React.FC<{sideAt: number; cardsAt: number; shrinkAt: number; degradeAt: number}> = ({ sideAt, cardsAt, @@ -613,13 +768,15 @@ export const P4Ledger: React.FC<{scene: SceneRange}> = ({scene}) => { shredAt={relB('p4-06')} /> - - + + + + = ({scene}) => { ]} /> - + + ); From 2776a215b4178981c2448e6f0fb16b5cac3a800a Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sun, 23 Aug 2026 07:35:13 +0800 Subject: [PATCH 06/41] =?UTF-8?q?feat(video):=20EP5=205-B=20=E5=9B=9B?= =?UTF-8?q?=E9=81=93=E9=97=B8=E5=A2=99=E2=80=94=E2=80=94=E5=AE=98=E6=96=B9?= =?UTF-8?q?=20worktrees=20=E9=9A=94=E7=A6=BB=E5=9B=9B=E6=A3=80=E6=9F=A5?= =?UTF-8?q?=E7=9A=84=E5=8F=AF=E8=A7=86=E5=8C=96;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 编辑闸/目录闸/重定向闸/形状闸四卡依次落下,第四道焊死带锁标「这道不能关」—— 官方 worktrees 文档的隔离四检查(取数2026年8月)。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../script/storyboard.md | 2 +- .../video/src/scenes/P5Desks.tsx | 56 ++++++++++++++++++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md index c92134bb..c718df6e 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md @@ -56,7 +56,7 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 5-A | p5-01..05 | 阿珍阿强冲突:两张桌子(同一目录)各写同名 config.py;阿强一覆盖,阿珍的改动碎掉;回滚线团成一团乱麻 | 双写冲突动画;覆盖时文件碎裂;回滚箭头打成死结 | -| 5-B | p5-06..09 | ★各开一桌 + **官方四道闸**:同一仓库底座向两侧长出平行目录抽屉;墙上四道闸依次落下(指向主检出的编辑/工作目录解析不对/git 重定向四种/形状无法验证——第四道焊死不能关) | 抽屉滑出成排;四道闸逐道落下,第四道落锁(`deny` 焊缝)+「这道不能关」小标 | +| 5-B 各开一桌与四道闸 | p5-06..09 | ★各开一桌 + **官方四道闸**:同一仓库底座向两侧长出平行目录抽屉;墙上四道闸依次落下(指向主检出的编辑/工作目录解析不对/git 重定向四种/形状无法验证——第四道焊死不能关) | 抽屉滑出成排;四道闸逐道落下,第四道落锁(`deny` 焊缝)+「这道不能关」小标 | | 5-C | p5-10..17 | 队友进桌:视野光圈收束到桌内;收尾二选一;★脏桌不删(改动未提交→删除被拒、桌沿抖动)+ 必须明说丢弃;建/拆/留逐行日志 | 视野光圈收缩;「保留/删除」双门;删除门被 deny 封条贴上并抖动;明说后封条撕开;右侧日志行逐条追加 | | 5-D | p5-18..22 | 【官方】进程级切换(进桌=整个世界是那张桌);外接工具:标准插头插入工具池 + 来源前缀铭牌防重名 + **延迟装载竖槽**(装十个服务上下文几乎不占,定义按需取用) | 角标浮现;标准插头插入动画;`mcp__jira__create` 铭牌特写;竖槽内只落两枚薄片、完整定义卡停在槽外「待取区」 | diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx index 3a8c828e..79e5469c 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx @@ -766,6 +766,59 @@ const McpPlug: React.FC<{noteAt: number; plugAt: number; plateAt: number}> = ({ ); }; +/** 5-B' 官方四道闸(Harness Engineering 改造版):主检出与工作目录之间一堵墙、四道闸 + * ①指向主检出的编辑拦 ②工作目录解析不对/确认不了拦 ③git 重定向四种写法拦 + * ④命令形状无法静态验证拦——第四道焊死,不能关(官方 worktrees)。 */ +const FourGates: React.FC<{gatesAt: number}> = ({gatesAt}) => { + const frame = useCurrentFrame(); + const {fps} = useVideoConfig(); + const gates = [ + {t: '编辑闸', s: '指向主检出的编辑,拦'}, + {t: '目录闸', s: '解析不对 / 确认不了,拦'}, + {t: '重定向闸', s: 'git 四种写法,拦'}, + {t: '形状闸', s: '无法静态验证,拦', locked: true}, + ]; + return ( + +
+ {gates.map((g, i) => { + const e = spring({frame: frame - gatesAt - i * 9, fps, config: {damping: 150}}); + if (e <= 0) return null; + return ( +
+
+ {g.t} +
+
{g.s}
+ {g.locked ? ( +
+ {'🔒 这道不能关'} +
+ ) : null} +
+ ); + })} +
+ + {'隔离四检查 —— 官方文档 worktrees(取数2026年8月)'} + +
+ ); +}; + export const P5Desks: React.FC<{scene: SceneRange}> = ({scene}) => { const w = (fromId: string, toId?: string) => beatWindow(scene.sentences, scene.from, fromId, toId); const at = (id: string) => w(id).from; @@ -783,12 +836,13 @@ export const P5Desks: React.FC<{scene: SceneRange}> = ({scene}) => { knotAt={rel(bA, 'p5-04')} />
- + + Date: Sun, 23 Aug 2026 07:36:07 +0800 Subject: [PATCH 07/41] =?UTF-8?q?feat(video):=20EP4=201-A=20=E8=B6=85?= =?UTF-8?q?=E6=97=B6=E8=BD=AC=E9=81=93=E9=95=9C=E4=BD=8D=E6=9B=B4=E5=90=8D?= =?UTF-8?q?=E2=80=94=E2=80=94=E5=AE=98=E6=96=B9=E7=9C=9F=E6=9C=BA=E5=88=B6?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E5=85=B3=E9=94=AE=E8=AF=8D=E5=85=9C=E5=BA=95?= =?UTF-8?q?=E5=8F=99=E4=BA=8B;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 分镜与 Sequence name 同步更名(组件动效保留,kwAt 时点锚现驱动超时线帧)。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../episodes/claude-code-concurrency-video/script/storyboard.md | 2 +- .../claude-code-concurrency-video/video/src/scenes/P1Dereg.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md index 772b0b65..fb6753df 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md @@ -18,7 +18,7 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| -| 1-A | p1-01..05 | 主循环环居中持续转(题眼);bash 工具卡上「后台执行」开关被勾选;关键词兜底:命令文本里 install/build 词被高亮 | 开关咔哒勾上;命令词高亮逐个闪;两条路(勾选/兜底)汇入同一出口 | +| 1-A 后台开关与超时转道 | p1-01..05 | 主循环环居中持续转(题眼);bash 工具卡「后台执行」开关勾选;**官方真机制**:命令到超时线不被杀、自动滑入后台(超时线动画);三类例外牌(sleep 开头 / 带 git / 拆不成简单命令)照停 | 开关咔哒;命令条爬到超时线→变道滑入后台轨(不消失);三张例外小牌弹出各带「停」章 | | 1-B | p1-06..10 | ★环外旁轨浮现:慢命令块滑出环上旁轨自己跑;环口贴占位条(带编号 bg_0001);循环继续转 | 命令块沿弧线滑出;占位条「啪」贴回环口;环的转速不变(全程匀速) | | 1-C | p1-11..15 | 【三】单线程真相帧:画面收缩成一条单线轨道——所谓「并行」的幻象被揭穿:所有块在同一条线上交错排布 | 双轨假象先展示→轨道合并动画→块在单线上排队交替走;角标「第三方的源码分析」 | | 1-D | p1-16..24 | 占位条特写(编号放大);风筝比喻:后台块拴绳飞在环外,绳头在循环手里 | 编号字放大定格;风筝线描线(`later`),收放各一次 | diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P1Dereg.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P1Dereg.tsx index d724a1a0..4af7e99c 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P1Dereg.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P1Dereg.tsx @@ -372,7 +372,7 @@ export const P1Dereg: React.FC<{scene: SceneRange}> = ({scene}) => { const bD = w('p1-16', 'p1-24'); return ( - + Date: Sun, 23 Aug 2026 07:37:11 +0800 Subject: [PATCH 08/41] =?UTF-8?q?docs(video):=20=E4=BA=94=E9=9B=86?= =?UTF-8?q?=E9=98=B6=E6=AE=B5=E2=91=A3=E5=8F=8C=E6=A0=A1=E9=AA=8C=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=EF=BC=88Harness=20Engineering=20=E6=94=B9=E9=80=A0?= =?UTF-8?q?=E7=89=88=EF=BC=89;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 每集新断言逐条回溯官方文档/工程博客锚点(证据级【二】为主、三级断言保留归属句), 含口径切换记录(EP1 hooks 27→31)、易懂性检查与遗留决策。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../research/verification-2026-08-23.md | 13 +++++++ .../research/verification-2026-08-23.md | 38 +++++++++++++++++++ .../research/verification-2026-08-23.md | 13 +++++++ .../research/verification-2026-08-23.md | 17 +++++++++ .../research/verification-2026-08-23.md | 12 ++++++ 5 files changed, 93 insertions(+) create mode 100644 apps/negentropy-influence/episodes/claude-code-concurrency-video/research/verification-2026-08-23.md create mode 100644 apps/negentropy-influence/episodes/claude-code-explained-video/research/verification-2026-08-23.md create mode 100644 apps/negentropy-influence/episodes/claude-code-memory-video/research/verification-2026-08-23.md create mode 100644 apps/negentropy-influence/episodes/claude-code-multiagent-video/research/verification-2026-08-23.md create mode 100644 apps/negentropy-influence/episodes/claude-code-planning-video/research/verification-2026-08-23.md diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/research/verification-2026-08-23.md b/apps/negentropy-influence/episodes/claude-code-concurrency-video/research/verification-2026-08-23.md new file mode 100644 index 00000000..41723d8f --- /dev/null +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/research/verification-2026-08-23.md @@ -0,0 +1,13 @@ +# 阶段④ 双校验记录(Harness Engineering 改造版 · 2026-08-23) + +| 口播句 | 断言 | 证据级 | 事实源 | 判定 | +|---|---|---|---|---| +| p0-02..03 | 它感觉不到时间 · 会高高兴兴跑几小时 | 【二】 | anthropic.com/engineering/claude-code-auto-mode(原话) | ✅ VERIFIED | +| p0-10 | 时间盲症(无钟/无闹钟/无回头) | 【二】 | 官方博客三无表述 | ✅ VERIFIED | +| p1-04..05 | 超时自动转后台 · 三类例外照停 | 【二】 | tools-reference(Bash 超时语义) | ✅ VERIFIED | +| p4-19..21 | 三档调度(云端/桌面/会话内) | 【二】 | scheduled-tasks 页 | ✅ VERIFIED | +| p5-14..18 | 管家进程托管 · 六状态 · 穿重启 · 接回续跑 | 【二】 | agent-view 页 | ✅ VERIFIED | +| p6-12 | 官方四件套画像 | 【二】 | claude.com/blog/harnessing-claudes-intelligence | ✅ VERIFIED | + +易懂性:P0 从洗衣机比喻切入时间盲症(保留比喻骨架 + 官方原话);P5 诚实边界升级为 +官方新答案(不再以「进程关了表就停」收尾)。遗留:无。 diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/research/verification-2026-08-23.md b/apps/negentropy-influence/episodes/claude-code-explained-video/research/verification-2026-08-23.md new file mode 100644 index 00000000..cf680859 --- /dev/null +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/research/verification-2026-08-23.md @@ -0,0 +1,38 @@ +# 阶段④ 双校验记录(Harness Engineering 改造版 · 2026-08-23) + +> 本文件记录 v-next(Harness Engineering 改造)逐字稿的真实性与易懂性双校验。 +> 前版校验记录见同目录历史文件。改造范围:P0 重写、P1/P3/P4 官方锚点替换、P6 重写。 + +## 一、真实性校验(每条断言回溯) + +| 口播句 | 断言 | 证据级 | 事实源锚点 | 判定 | +|---|---|---|---|---| +| p0-04..06 | 「挽具」官方命名 + 模型在挽具里面 + 供给五样 | 【二】 | code.claude.com/docs/en/glossary(Agentic harness 条目)· how-claude-code-works | ✅ VERIFIED | +| p1-25..27 | 三相循环交融 + 人随时可打断 | 【二】 | how-claude-code-works(gather/take/verify) | ✅ VERIFIED | +| p1-28..29 | State 十字段(角标化) | 【三】 | 第三方源码分析(归属句保留) | ✅ VERIFIED(带归属) | +| p3-06 | 权限由代码执行不由模型执行 | 【二】 | code.claude.com/docs/en/permissions | ✅ VERIFIED | +| p3-25..29 | deny→ask→allow 顺序求值 · 首中即出局 · 裸名 deny 移除工具 | 【二】 | permissions 页规则语义 | ✅ VERIFIED | +| p3-31 | 93% 提示被批准 | 【二】 | 官方遥测 2026-03(历史口径,口播带「官方遥测」) | ✅ VERIFIED | +| p3-32..34 | 分类器只看用户消息与裸命令 | 【二】 | anthropic.com/engineering/claude-code-auto-mode | ✅ VERIFIED | +| p4-23..25 | 31 个 hook 事件 × 三节奏 | 【二】 | code.claude.com/docs/en/hooks(事件表逐行计数 2026-08-22) | ✅ VERIFIED(口径已注明「官方文档口径」) | +| p4-27..32 | 沉默≠批准 · 放行穿后两站 · 单向加限制 · 六闸 | 【二】 | hooks reference + agent-sdk/permissions | ✅ VERIFIED | +| p4-33..34 | 教学版无此层是安全漏洞 | 【三】 | 第三方评语(归属句保留) | ✅ VERIFIED(带归属) | +| p5-05..06 | 官方四件套定义 | 【二】 | claude.com/blog/harnessing-claudes-intelligence | ✅ VERIFIED | +| p6-06 | 取数2026年8月 | 【二】 | 全片信源取数日期(无空格写法过 READING_TRAPS) | ✅ VERIFIED | + +**口径切换记录**:hooks 事件数从 27(第三方数源码)→ 31(官方文档口径)——两口径未混用, +分镜 4-F 的 27 格矩阵同步重建为三层嵌套(31 计数)。 + +## 二、易懂性校验 + +- 新概念首现配比喻:挽具(p0-04「把动力源,套进一个可控的结构里」);三相(p1-26「不是硬阶段」); + 六闸(沿三闸门认知升级,画面先轨道后闸)。 +- 金句节奏保留:每幕收尾金句未动(1-D/2-F/3-D/4-G2/5-C 全保留)。 +- 英文标识符只在角标(agentic harness / deny/ask/allow / hook / workflow 等全画面层)。 +- 句长:167 句全部 8–35 字(check_script 门过)。 + +## 三、遗留与决策 + +- 27→31 口径切换已在画面角标注明「官方文档口径」;旧 27 数字不再出现。 +- 93% 为历史遥测口径(2026-03),非活数据,口播带「官方遥测」限定。 +- State 十字段降级为角标清单(原 1-E 十抽屉详述压缩)——信息未删,入口移画面。 diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/research/verification-2026-08-23.md b/apps/negentropy-influence/episodes/claude-code-memory-video/research/verification-2026-08-23.md new file mode 100644 index 00000000..8ad68e2a --- /dev/null +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/research/verification-2026-08-23.md @@ -0,0 +1,13 @@ +# 阶段④ 双校验记录(Harness Engineering 改造版 · 2026-08-23) + +| 口播句 | 断言 | 证据级 | 事实源 | 判定 | +|---|---|---|---|---| +| p0-09 | 窗口越长记得越不准(注意力摊薄) | 【二】 | anthropic.com/engineering/effective-context-engineering(引 Chroma 2025-07 实测) | ✅ VERIFIED | +| p1-18..19 | 官方两级(先清旧输出·不够再摘要)·教学四级是其细化 | 【二】 | 官方 compaction 表述 | ✅ VERIFIED | +| p3-09..13 | 压缩存活矩阵(系统提示绕行/规则重注入/技能封顶五千最旧先丢/回捞五个) | 【二】 | context-window 页「压缩后什么活下来」矩阵 | ✅ VERIFIED | +| p4-08..09 | 第一条腿四层拼接 · 四兆上限 · 两百行 | 【二】 | memory 页(四层位置与加载顺序、上限) | ✅ VERIFIED | +| p4-11..12 | 第二条腿自动记忆四类 · 门限 | 【二】 | memory 页(auto memory type 与 25KB/200 行) | ✅ VERIFIED | +| p4-24..25 | 前缀缓存 · 改规则新开会话 · 换模型那轮慢 | 【二】 | prompt-caching 页(三层前缀、缓存键含模型与档位) | ✅ VERIFIED | +| p6-05..06 | 「都是上下文不是闸门」· 记忆是建议钩子才是规则 | 【二】 | memory 页原话 | ✅ VERIFIED | + +易懂性:两条腿框架替代单账本叙事,入口更清楚;「tab 字条」母题保留。遗留:无。 diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/research/verification-2026-08-23.md b/apps/negentropy-influence/episodes/claude-code-multiagent-video/research/verification-2026-08-23.md new file mode 100644 index 00000000..bd5b84f2 --- /dev/null +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/research/verification-2026-08-23.md @@ -0,0 +1,17 @@ +# 阶段④ 双校验记录(Harness Engineering 改造版 · 2026-08-23) + +| 口播句 | 断言 | 证据级 | 事实源 | 判定 | +|---|---|---|---|---| +| p0-03 | 官方三失败模式(干一半宣布完成/偏爱自己的产出/目标越走越散) | 【二】 | claude.com/blog/a-harness-for-every-task(agentic laziness / self-preferential bias / goal drift) | ✅ VERIFIED | +| p1-13 | 任务认领用文件锁防竞态 | 【二】 | tools-reference 原话 | ✅ VERIFIED | +| p2-14..15 | 信箱就是用户目录下的文件 · 写文件加锁 | 【二】 | agent-teams(磁盘布局) | ✅ VERIFIED | +| p2-16 | 消息十五种 | 【三】 | 第三方计数(归属句保留「有人数过」) | ✅ VERIFIED(带归属) | +| p2-20..22 | 三禁止(不替批权限/不代同意/被拒不转给别的队友) | 【二】 | agent-teams「Messages between agents」 | ✅ VERIFIED | +| p5-07..09 | worktree 四道闸 · 第四道不能关 | 【二】 | worktrees「How Claude Code enforces isolation」 | ✅ VERIFIED | +| p5-22 | 装十个服务上下文几乎不占(按需取用) | 【二】 | mcp(tool search 延迟装载) | ✅ VERIFIED | +| p6-08..11 | 谁持有计划四形态 · 中间结果住变量 · 并发十六/一千 · 挽具由它自己写 | 【二】 | workflows(When to use a workflow + Behavior and limits) | ✅ VERIFIED | +| p6-13..14 | 协调成本 · 十五倍 token | 【二】 | 官方工程博客(multi-agent research system) | ✅ VERIFIED | +| p3-12..14 | 三向关机 | 【三】 | 第三方源码分析(归属句保留) | ✅ VERIFIED(带归属) | + +易懂性:P0 三症状卡先立病、P6 四象图给药(病—药闭环);「谁持有计划」是全系列思想高点。 +遗留:下期预告话题「给这样的系统打分」为建议方向,画面卡可随频道规划调整(口播零依赖)。 diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/research/verification-2026-08-23.md b/apps/negentropy-influence/episodes/claude-code-planning-video/research/verification-2026-08-23.md new file mode 100644 index 00000000..0b641174 --- /dev/null +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/research/verification-2026-08-23.md @@ -0,0 +1,12 @@ +# 阶段④ 双校验记录(Harness Engineering 改造版 · 2026-08-23) + +| 口播句 | 断言 | 证据级 | 事实源 | 判定 | +|---|---|---|---|---| +| p0-03 | 其中一样装置刚被官方收回(悬念) | 【二】 | code.claude.com/docs/en/sub-agents + whats-new(TodoWrite 默认停用) | ✅ VERIFIED | +| p1-14..15 | 新模型上清单工具默认不再安装 · 理由「模型自己能记住」 | 【二】 | 官方文档原话 | ✅ VERIFIED | +| p2-12 | 分身最多三层 · 同时二十个 | 【二】 | sub-agents(并发与递归上限) | ✅ VERIFIED | +| p2-16 | fork 反转官方证实 | 【二】 | sub-agents(fork 继承完整对话·共享提示缓存) | ✅ VERIFIED | +| p3-06 | 手册正文整场常驻 · 压缩后重注入 | 【二】 | skills(渐进披露三态) | ✅ VERIFIED | +| p6-05..06 | 零件押注会过期 · 官方自省句 | 【二】 | 官方博客 | ✅ VERIFIED | + +易懂性:新钩子(收回悬念)3 句内成立;金句节奏保留。遗留:无。 From 672797d0bf50f228cdfce0a787ed76070f0e4070 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sun, 23 Aug 2026 07:37:45 +0800 Subject: [PATCH 09/41] =?UTF-8?q?docs(video):=20=E4=BA=94=E9=9B=86=20READM?= =?UTF-8?q?E=20=E8=A1=A5=20Harness=20Engineering=20=E6=94=B9=E9=80=A0?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E8=A1=8C;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../episodes/claude-code-explained-video/README.md | 1 + .../episodes/claude-code-planning-video/README.md | 1 + 2 files changed, 2 insertions(+) diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/README.md b/apps/negentropy-influence/episodes/claude-code-explained-video/README.md index f4f3b114..4f0e444a 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/README.md +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/README.md @@ -1,6 +1,7 @@ # 《执行层:一个循环,就是全部》 > 系列「Claude Code Harness Engineering」首作(发布顺序 SSOT:[../series.json](../../series.json);口播永不携带集数序号)。 +> **改造状态(2026-08-23)**:Harness Engineering 改造版——口播 v-next 已定稿、场景组件已升级、配音重配中;草渲交付待审(终渲未启动)。 > 选题:开源课程 [Learn Claude Code](https://learn.shareai.run/zh/s01/) 的「工具与执行」四章 > —— s01 Agent Loop / s02 Tool Use / s03 Permission / s04 Hooks。 > 形态:1080p30 横屏,代码动画图解 + 本人音色克隆旁白,无真人出镜、无 BGM。 diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/README.md b/apps/negentropy-influence/episodes/claude-code-planning-video/README.md index bc27dc8c..7e1f52a7 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/README.md +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/README.md @@ -1,6 +1,7 @@ # 《规划层:模型的视野是安排出来的》科普视频工程 > 交付状态:**已交付**。发布顺序见 [../../series.json](../../series.json)。 +> **改造状态(2026-08-23)**:Harness Engineering 改造版——口播 v-next 已定稿、场景组件已升级、配音重配中;草渲交付待审(终渲未启动)。 ## 交付状态 From 732031b0890b86aa2cbccaf35b4f60103d673961 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sun, 23 Aug 2026 09:24:36 +0800 Subject: [PATCH 10/41] =?UTF-8?q?feat(video):=20EP2=E2=80=935=20=E8=A1=A5?= =?UTF-8?q?=E8=B6=B3=E6=97=B6=E9=95=BF=E7=AA=97=E5=8F=A3=E2=80=94=E2=80=94?= =?UTF-8?q?=E9=A2=84=E7=AE=97=E7=AC=BC=E5=AD=90/=E6=A3=80=E6=9F=A5?= =?UTF-8?q?=E7=82=B9/=E7=BC=93=E5=AD=98=E4=BB=B7=E7=9B=AE/=E5=8F=8C?= =?UTF-8?q?=E8=B7=AF=E7=9B=91=E8=A7=86/=E5=8F=91=E6=9D=A1/=E5=90=8D?= =?UTF-8?q?=E5=86=8C/=E5=85=AD=E6=A8=A1=E5=BC=8F/resume;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 实测口径低于 13.0 下限(改稿删句后句间停顿开销下降)——按简报补回高价值官方内容(字母后缀 id 保缓存): EP2 +三只笼子与检查点盲区;EP3 +前缀缓存价目(读一折写加四分之一);EP4 +轮询走廊 vs 事件传送带 与自定速发条;EP5 +团队名册文件、六模式选二(扇出汇总/对抗核验)、resume 重放规矩。 五集估算口径回到 13.5–13.8 分钟。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../script/narration.json | 25 ++++++++++++++++ .../script/narration.md | 5 ++++ .../script/storyboard.md | 4 +-- .../script/narration.json | 10 +++++++ .../script/narration.md | 2 ++ .../script/narration.json | 30 +++++++++++++++++++ .../script/narration.md | 6 ++++ .../script/storyboard.md | 2 +- .../script/narration.json | 25 ++++++++++++++++ .../script/narration.md | 5 ++++ 10 files changed, 111 insertions(+), 3 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json index e50ddca5..0ca5c5a3 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json @@ -344,6 +344,21 @@ "scene": "P3", "text": "后台不是丢出去就不管了——丢出去的活,也有一双眼睛看着。" }, + { + "id": "p3-09a", + "scene": "P3", + "text": "看的方式,官方给了两条路:一条是轮询走廊——每隔一段回头问一次," + }, + { + "id": "p3-09b", + "scene": "P3", + "text": "简单,但空跑也是钱;另一条是事件传送带——活儿一出结果就自己滚过来," + }, + { + "id": "p3-09c", + "scene": "P3", + "text": "不空跑、不迟到。等得起就用走廊,等不起就上传送带。" + }, { "id": "p4-01", "scene": "P4", @@ -594,6 +609,16 @@ "scene": "P5", "text": "三个真话合起来是一种态度:定时这件事,想象很浪漫,工程都在打补丁。" }, + { + "id": "p5-23a", + "scene": "P5", + "text": "还有个更自由的拨法:让它自己给自己上发条——干完一轮,顺手定下一次," + }, + { + "id": "p5-23b", + "scene": "P5", + "text": "间隔自己定。不靠墙上的钟,靠它自己的一句「回头再来」。" + }, { "id": "p6-01", "scene": "P6", diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md index bdc9f8c3..b66b1ab4 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md @@ -103,6 +103,9 @@ - [p3-07] 还在长,说明它在干活,哪怕慢得像爬,狗都继续趴着。 - [p3-08] 四十五秒一毫米都没动,才起身查看。不猜快慢,只看死活。 - [p3-09] 后台不是丢出去就不管了——丢出去的活,也有一双眼睛看着。 +- [p3-09a] 看的方式,官方给了两条路:一条是轮询走廊——每隔一段回头问一次, +- [p3-09b] 简单,但空跑也是钱;另一条是事件传送带——活儿一出结果就自己滚过来, +- [p3-09c] 不空跑、不迟到。等得起就用走廊,等不起就上传送带。 ## P4 没人按的开始 @@ -166,6 +169,8 @@ - [p5-21] 还有个小细节:定时任务触发的请求,带着「低优先级」的标记—— - [p5-22] 服务一忙,先紧着人的事,闹钟的事往后稍稍。 - [p5-23] 三个真话合起来是一种态度:定时这件事,想象很浪漫,工程都在打补丁。 +- [p5-23a] 还有个更自由的拨法:让它自己给自己上发条——干完一轮,顺手定下一次, +- [p5-23b] 间隔自己定。不靠墙上的钟,靠它自己的一句「回头再来」。 ## P6 落点与信源 diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md index fb6753df..c8aeec0a 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md @@ -38,7 +38,7 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 3-A | p3-01..03 | 秒表狗趴在旁轨边;后台命令的输出线停在一个「(y/n)」提示上 | 输出线爬行→停在问句;问句闪烁等待 | -| 3-B | p3-04..09 | 狗盯输出线:45 秒刻度走满无增长→狗起身,放大镜对准问句;「不猜快慢只看死活」刻度尺 | 秒表环走满(45 刻度);狗耳朵竖起+起身;放大镜聚焦;正常增长的对照线一闪而过 | +| 3-B | p3-04..09c | 狗盯输出线:45 秒无增长→狗起身放大镜;**两条看路**(p3-09a..c):轮询走廊(隔段回头,空跑计费灯闪)vs 事件传送带(结果自己滚来) | 秒表环走满;狗起身聚焦;双路小图并置:走廊上问号卡往返(费字灯闪)vs 传送带上包裹自动滚到脚边 | ## P4 没人按的开始 @@ -58,7 +58,7 @@ | 5-B | p5-05..08 | ★确定性抖动:同排表各按算好的固定偏移错峰落下;「算出来 vs 随机」对照(随机会漂的轨迹线) | 每张表各自延迟不同但固定的量再落;随机轨迹画成漂移虚线(`deny`),确定性轨迹为整齐错列(`later`);整点提前 90 秒逆行小箭头 | | 5-C | p5-09..10 | 七天退休:日历翻七天→退休章盖下(删前最后跑一次的小尾巴) | 日历快翻;章落下;最后一次触发的小脉冲 | | 5-D | p5-11..18 | ★官方新答案:独立管家进程托管后台会话——不眠的眼睛、六状态记账(排队/跑着/等审批/被拦/收尾/完事)、行摘要小模型、状态落盘穿重启、接回从停点续跑 | 管家图标 spring 立起;六状态胶囊逐个点亮;左下「状态落盘·穿重启」卡 + 右下「进程退出≠任务没了」卡对浮 | -| 5-E | p5-19..23 | 上限 50 + 低优先级标记 + 收束句(「想象浪漫·工程打补丁」) | 满座计数器 50/50;请求卡带「低」字标记排到队尾;金句卡淡入 | +| 5-E | p5-19..23b | 上限 50 + 低优先级标记 + **自定速发条**(p5-23a/b:干完一轮顺手定下一次,间隔自己定) + 收束句 | 满座计数器 50/50;低优先级卡排队尾;发条图标自转一圈拨出下一格;金句卡淡入 | ## P6 落点与信源 diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json index a986536a..029896ec 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json @@ -504,6 +504,16 @@ "scene": "P4", "text": "所以改了规则文件要新开会话才生效;中途换模型,那一轮特别慢。" }, + { + "id": "p4-25a", + "scene": "P4", + "text": "这张卡的价目官方也挂着:命中的一折计费,写入加四分之一——" + }, + { + "id": "p4-25b", + "scene": "P4", + "text": "两次一问就回本。稳定放前面、多变放后面,就是在给钱排座位。" + }, { "id": "p4-26", "scene": "P4", diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md index 07f92fd7..21448360 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md @@ -141,6 +141,8 @@ - [p4-23] 挑错了比没挑更糟——一条不相干的记忆,就是一句错误的自我介绍。 - [p4-24] 还有个经济学尾巴:前缀缓存按字数打折,但前缀必须一字不差—— - [p4-25] 所以改了规则文件要新开会话才生效;中途换模型,那一轮特别慢。 +- [p4-25a] 这张卡的价目官方也挂着:命中的一折计费,写入加四分之一—— +- [p4-25b] 两次一问就回本。稳定放前面、多变放后面,就是在给钱排座位。 - [p4-26] 挑记忆这活,就是一个普通的小号模型在干——不用向量检索,反而可靠。 - [p4-27] 挑出来的内容不进基本设定,临时贴进这一轮—— - [p4-28] 用完就过气。取记忆,也是一次性的。 diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json index 8aa7dd45..fdd18dd8 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json @@ -269,6 +269,16 @@ "scene": "P2", "text": "还有一条铁律:队友不许再孵队友——一张审批卡冒十层泡,就找不到责任人了。" }, + { + "id": "p2-23a", + "scene": "P2", + "text": "团队本身也落成文件:一个名册放在用户目录的团队文件夹里,写着谁在队、" + }, + { + "id": "p2-23b", + "scene": "P2", + "text": "每人一只信箱。会话一结束,名册自动清掉——队伍是临时的,桌子才是留下的。" + }, { "id": "p2-25", "scene": "P2", @@ -599,6 +609,26 @@ "scene": "P6", "text": "挽具第一次,开始由它自己来写。" }, + { + "id": "p6-11a", + "scene": "P6", + "text": "这种脚本能拼出好几种打法:一批活扇出去、各自干完再汇总成一份;" + }, + { + "id": "p6-11b", + "scene": "P6", + "text": "或者干完先请另一个它挑刺,挑完再改——改到合格才算完。" + }, + { + "id": "p6-11c", + "scene": "P6", + "text": "中断也不慌:重新拉起时,干完的直接命中,没干完的从头再跑——" + }, + { + "id": "p6-11d", + "scene": "P6", + "text": "在第一个没干完的之后启动的,全部重跑。规矩清楚,不碰运气。" + }, { "id": "p6-12", "scene": "P6", diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md index 94017b6c..1d019913 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md @@ -81,6 +81,8 @@ - [p2-21] 不能替你批权限、不能代你同意、被拒的动作不能转给另一个队友。 - [p2-22] 组队不是权限洗白机。孩子们的签字栏,还在家长的原处。 - [p2-23] 还有一条铁律:队友不许再孵队友——一张审批卡冒十层泡,就找不到责任人了。 +- [p2-23a] 团队本身也落成文件:一个名册放在用户目录的团队文件夹里,写着谁在队、 +- [p2-23b] 每人一只信箱。会话一结束,名册自动清掉——队伍是临时的,桌子才是留下的。 - [p2-25] 你回头看会发现:这些约定防的都是「没人负责」这四个字。 ## P3 怎么谈判:握手 @@ -175,6 +177,10 @@ - [p6-09] 循环、分支、中间结果,住进脚本变量;它的上下文,只装最终答案。 - [p6-10] 脚本落盘,可读、可比对、改完能重跑;并发最多十六,单次一千。 - [p6-11] 挽具第一次,开始由它自己来写。 +- [p6-11a] 这种脚本能拼出好几种打法:一批活扇出去、各自干完再汇总成一份; +- [p6-11b] 或者干完先请另一个它挑刺,挑完再改——改到合格才算完。 +- [p6-11c] 中断也不慌:重新拉起时,干完的直接命中,没干完的从头再跑—— +- [p6-11d] 在第一个没干完的之后启动的,全部重跑。规矩清楚,不碰运气。 - [p6-12] 多出来的不是智慧,是把协作拆成了看得见的零件:板子、信箱、编号、桌子。 - [p6-13] 官方泼的冷水也要听:并行和专精,必须挣回它们的协调成本—— - [p6-14] 官方算过账,多智能体的花销,大约是普通对话的十五倍。 diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md index c718df6e..d3954f14 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md @@ -67,5 +67,5 @@ | 6-A | p6-01..02 | 四样东西归位小图(板/箱/号/桌);七段传送带(FullTurn 母题)铺开 | 四小图标滑入底部;传送带自左向右描线成形 | | 6-B | p6-03..04 | ★一整轮快闪:包裹走完七段(进料/护栏/选面/执行/外接/补救/记账),每段亮起对应机制小图标——快闪蒙太奇(原 4 句详走压成 2 句) | 包裹逐段快速推进(每段约 1.5s);每过一段该段图标亮起并短暂回闪其母题缩略 | | 6-C | p6-05..06 | ★系列终曲帧:环(core)从传送带中央升起放大居中——同色同宽同节点;「机制很多,循环一个」金句压场 | 环升起重演描线一遍(与系列首集同款动画节奏);机制图标环立四周;金句卡(core)淡入 | -| 6-D | p6-07..11 | ★**谁持有计划**:四象对比(临时工/技能包/队友——计划由模型逐回合决定)vs 第四种(脚本持有);动态工作流三分区:会话侧只装最终答案 / 运行时侧住循环分支与中间结果 / agent 侧点阵(并发 16 · 总量 1000);收官反转「挽具第一次由它自己来写」 | 分水岭竖线落下(前三列同色第四列异色);中间结果被抽进变量盒动画;resume 子图:A 秒亮 / B 重跑 / C D 对勾抹掉;反转金句卡压场 | +| 6-D | p6-07..11d | ★**谁持有计划**:四象对比 + 动态工作流三分区 + **六模式选二**(扇出汇总 / 对抗核验)+ **resume 重放**(干完的秒亮、没干完的重跑、其后全部重跑)+ 收官反转 | 分水岭竖线落下;运行时三分区;两张模式小卡浮出(扇出→汇总漏斗 / 挑刺→改到合格);resume 子图:A 绿秒亮 / B 黄重跑 / C D 对勾抹掉;反转金句卡 | | 6-E | p6-12..17 | 「零件」收束(板/箱/号/桌)+ 官方冷水(十五倍 token)→ 信源卡(官方文档+取数日期 / 第三方源码分析已逐处标注 / 数字均为实测口径)→ 身份卡 + **下期预告卡**(「换个方向:给这样的系统打分」,只进画面) → **渐黑**(末 beat 总时长推导,红线四) | 零件四连小图;十五倍对比条;信源卡逐行;身份卡;下期卡浮现;末 1.2s 线性压暗到全黑 | diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json index 632b3798..41c5b3e5 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json @@ -264,6 +264,21 @@ "scene": "P2", "text": "派出去慢慢干的玩法以后单说。" }, + { + "id": "p2-28a", + "scene": "P2", + "text": "官方还给分身套了三个上限,像三只笼子:同时在场最多二十个," + }, + { + "id": "p2-28b", + "scene": "P2", + "text": "每个有自己的轮数上限,还有整份上下文的配额——烧完就收工。" + }, + { + "id": "p2-28c", + "scene": "P2", + "text": "放得开,也拴得住。副桌再多,也翻不出这三只笼子。" + }, { "id": "p2-29", "scene": "P2", @@ -509,6 +524,16 @@ "scene": "P4", "text": "出错不是终点。这话写在章首,也确实是这套系统的性格。" }, + { + "id": "p4-21a", + "scene": "P4", + "text": "官方还有个兜底的后悔药:改动可以回退到前面的检查点——" + }, + { + "id": "p4-21b", + "scene": "P4", + "text": "不过它只看文件改动,跑过的命令改过的外部状态,不在里面。" + }, { "id": "p4-22", "scene": "P4", diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md index b4a3e7b4..89d2b827 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md @@ -79,6 +79,9 @@ - [p2-26] 免得同一个文件读两遍。桌是分开了,有些抽屉还是共用的。 - [p2-27] 分身要弹审批窗,也会冒泡弹到父亲的屏幕上,还是你来点头。 - [p2-28] 派出去慢慢干的玩法以后单说。 +- [p2-28a] 官方还给分身套了三个上限,像三只笼子:同时在场最多二十个, +- [p2-28b] 每个有自己的轮数上限,还有整份上下文的配额——烧完就收工。 +- [p2-28c] 放得开,也拴得住。副桌再多,也翻不出这三只笼子。 - [p2-29] 副桌这一样,记住一句:脏活不占主桌。 - [p2-30] 而它值得记住的第二句是:省钱和隔离,常常是同一个设计的两种说法。 @@ -141,6 +144,8 @@ - [p4-19] 他还提了一个很冷静的设计:续写要是连着几次都没写出新东西, - [p4-20] 系统就直接判定——再续也没有产出,停。不恋战,也是一种能力。 - [p4-21] 出错不是终点。这话写在章首,也确实是这套系统的性格。 +- [p4-21a] 官方还有个兜底的后悔药:改动可以回退到前面的检查点—— +- [p4-21b] 不过它只看文件改动,跑过的命令改过的外部状态,不在里面。 - [p4-22] 你会发现每一级补救都带着上限:升一次、续三次、等三十二秒、换一次人。 ## P5 桌子换了五样,环没动 From 736a49018578c0c50ac452ef864faaedd062b46b Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sun, 23 Aug 2026 09:35:26 +0800 Subject: [PATCH 11/41] =?UTF-8?q?feat(video):=20=E4=BA=94=E9=9B=86?= =?UTF-8?q?=E5=86=85=E5=AE=B9=E9=97=A8=E5=85=A8=E7=BB=BF=E2=80=94=E2=80=94?= =?UTF-8?q?=E5=AE=9E=E6=B5=8B=E5=8F=A3=E5=BE=84=2013.1=E2=80=9313.9=20?= =?UTF-8?q?=E5=88=86=E9=92=9F=E5=85=A8=E6=95=B0=E5=85=A5=E7=AA=97;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EP2 再补目录纸两档(两三万字 vs 极简两行)与两百行不听话句;EP5 补消息即文字/信箱不搬桌 两句;EP4 3-B 场景锚扩至 09c。五集 check --check-scenes FAIL 0 · WARN 0,check_series 全绿。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../video/src/scenes/P3Watchdog.tsx | 2 +- .../claude-code-multiagent-video/script/narration.json | 10 ++++++++++ .../claude-code-multiagent-video/script/narration.md | 2 ++ .../claude-code-planning-video/script/narration.json | 10 ++++++++++ .../claude-code-planning-video/script/narration.md | 2 ++ 5 files changed, 25 insertions(+), 1 deletion(-) diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx index 55ae06db..05ddb866 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx @@ -262,7 +262,7 @@ export const P3Watchdog: React.FC<{scene: SceneRange}> = ({scene}) => { const w = (fromId: string, toId?: string) => beatWindow(scene.sentences, scene.from, fromId, toId); const at = (id: string) => w(id).from; const bA = w('p3-01', 'p3-03'); - const bB = w('p3-04', 'p3-09'); + const bB = w('p3-04', 'p3-09c'); return ( diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json index fdd18dd8..f242b040 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json @@ -279,6 +279,16 @@ "scene": "P2", "text": "每人一只信箱。会话一结束,名册自动清掉——队伍是临时的,桌子才是留下的。" }, + { + "id": "p2-24a", + "scene": "P2", + "text": "还有个实在的细节:消息就是一段文字——想把整段上下文搬过去,得恢复会话," + }, + { + "id": "p2-24b", + "scene": "P2", + "text": "而不是塞进信箱。信箱管传话,不管搬桌子。" + }, { "id": "p2-25", "scene": "P2", diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md index 1d019913..e2440656 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md @@ -83,6 +83,8 @@ - [p2-23] 还有一条铁律:队友不许再孵队友——一张审批卡冒十层泡,就找不到责任人了。 - [p2-23a] 团队本身也落成文件:一个名册放在用户目录的团队文件夹里,写着谁在队、 - [p2-23b] 每人一只信箱。会话一结束,名册自动清掉——队伍是临时的,桌子才是留下的。 +- [p2-24a] 还有个实在的细节:消息就是一段文字——想把整段上下文搬过去,得恢复会话, +- [p2-24b] 而不是塞进信箱。信箱管传话,不管搬桌子。 - [p2-25] 你回头看会发现:这些约定防的都是「没人负责」这四个字。 ## P3 怎么谈判:握手 diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json index 41c5b3e5..e8cc43b9 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json @@ -329,6 +329,16 @@ "scene": "P3", "text": "官方口径:目录预算有硬顶——" }, + { + "id": "p3-08a", + "scene": "P3", + "text": "常规状态的这份纸,两三万字;极简模式整个两行。同一个人,两种铺法。" + }, + { + "id": "p3-08b", + "scene": "P3", + "text": "官方还给了句实在话:清单超过两百行,它就开始不老实读了。" + }, { "id": "p3-09", "scene": "P3", diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md index 89d2b827..5a625c18 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md @@ -99,6 +99,8 @@ - [p3-06] 真要用到哪本,再把整本拉上桌——而且整场常驻,压缩后还会重注入。 - [p3-07] 教学版的讲法很直白:目录常驻,内容按需。 - [p3-08] 官方口径:目录预算有硬顶—— +- [p3-08a] 常规状态的这份纸,两三万字;极简模式整个两行。同一个人,两种铺法。 +- [p3-08b] 官方还给了句实在话:清单超过两百行,它就开始不老实读了。 - [p3-09] 大约是窗口的百分之一,再设一个绝对上限,超了就砍。 - [p3-10] 还有个安全细节:取手册只认目录里登记过的名字,不走文件路径,防的就是目录穿越。 - [p3-11] 第四样东西,管的是桌面上那张最大的纸——它的基本设定本身。 From 8787f2488f3b364e8c43eb27b0aa007b32118ad0 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sun, 23 Aug 2026 09:35:51 +0800 Subject: [PATCH 12/41] =?UTF-8?q?fix(video):=20EP5=206-D=20=E5=9C=BA?= =?UTF-8?q?=E6=99=AF=E9=94=9A=E6=89=A9=E8=87=B3=20p6-11d=EF=BC=88resume=20?= =?UTF-8?q?=E5=9B=9B=E5=8F=A5=E5=B9=B6=E5=85=A5=E7=BA=B2=E5=9B=BE=E9=95=9C?= =?UTF-8?q?=EF=BC=89;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../claude-code-multiagent-video/video/src/scenes/P6Finale.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx index d205b193..00d6858b 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx @@ -687,7 +687,7 @@ export const P6Finale: React.FC<{scene: SceneRange}> = ({scene}) => { const bA = w('p6-01', 'p6-02'); const bB = w('p6-03', 'p6-04'); const bC = w('p6-05', 'p6-06'); - const bD = w('p6-07', 'p6-11'); + const bD = w('p6-07', 'p6-11d'); const bE = w('p6-12', 'p6-17'); const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( From 751917cb204994e1644c3069d7cf55680081025d Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sun, 23 Aug 2026 10:32:45 +0800 Subject: [PATCH 13/41] =?UTF-8?q?feat(video):=20=E4=BA=94=E9=9B=86?= =?UTF-8?q?=E8=8D=89=E6=B8=B2=E4=BA=A4=E4=BB=98=E2=80=94=E2=80=94Harness?= =?UTF-8?q?=20Engineering=20=E6=94=B9=E9=80=A0=E7=89=88=E5=85=A8=E9=93=BE?= =?UTF-8?q?=E8=B7=AF=E5=B0=B1=E7=BB=AA=EF=BC=88=E7=BB=88=E6=B8=B2=E5=BE=85?= =?UTF-8?q?=E5=AE=A1=EF=BC=89;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 草渲产物(out/draft.mp4,0.5×/jpeg60):EP1 13:56(25096帧) · EP2 13:10 · EP3 13:06 · EP4 13:07 · EP5 13:08(合计 67.3 分钟)。series.json 状态 → draft-review。 验证链:内容门(build/check --check-scenes)五集 FAIL 0 · WARN 0;check_series(含 规则 7 去站点化)FAIL 0 · WARN 0;七幕抽帧 + 尾幕末 6 句自动体检 FAIL 0(3 条 WARN 均为金句卡/收束段刻意静止,与已上线集同款);16 个高风险新图解帧 remotion still 逐帧目检通过;srt/vtt 字幕五集全出。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- CHANGELOG.md | 2 ++ .../video/src/scenes/P4Autonomy.tsx | 2 +- apps/negentropy-influence/series.json | 20 +++++++++---------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74311373..b3e4ac19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ 本文件遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/) 约定,版本号遵循 [SemVer](https://semver.org/lang/zh-CN/)。 ## [Unreleased] +- **五集草渲交付(Harness Engineering 改造版,待用户审核后终渲)**:13:56 / 13:10 / 13:06 / 13:07 / 13:08(合计 67.3 分钟草渲口径)。全部新断言锚定官方文档与 Anthropic 工程博客([code.claude.com/docs](https://code.claude.com/docs) 取数2026年8月);去站点化完成(`check_series.py` 规则 7 全绿);五集内容门(含分镜覆盖/读法陷阱/时长双口径)FAIL 0 · WARN 0;七幕抽帧自动体检 FAIL 0;16 个高风险新图解帧(命名帧/六闸流水线/谁持有计划四象/三禁止章/worktree 四道闸/管家进程/存活矩阵/两条腿/前缀缓存条/三相环/31 事件嵌套/auto 视野分屏/裸名 deny/五辐条/三症状卡/下期卡)逐帧目检通过——无重叠、无字幕带侵入、无文字侧倒。配音: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` 全零待合成)。 diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx index a657776e..d17bf24b 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx @@ -726,7 +726,7 @@ export const P4Autonomy: React.FC<{scene: SceneRange}> = ({scene}) => { /> - + ); diff --git a/apps/negentropy-influence/series.json b/apps/negentropy-influence/series.json index 99d607f4..00ad8790 100644 --- a/apps/negentropy-influence/series.json +++ b/apps/negentropy-influence/series.json @@ -101,8 +101,8 @@ "license": "MIT", "accessed": "2026-08-21" }, - "status": "ready", - "statusNote": "已交付:成片 14:14(1080p30 h264/aac192K,42.1 MB)+ srt/vtt 各 170 cue + 封面帧;终渲抽帧 FAIL 0(WARN 1 为刻意的画面凝住);2026-08-22 tier-i 画面优化 + 评审四修版 14:14.73 · 42.6 MB(total_duration_in_frames 复算 25642 帧 @30fps;零口播零配音改动,七幕抽帧 FAIL 0 · WARN 1)", + "status": "draft-review", + "statusNote": "Harness Engineering 改造草渲待审:13:56 = 25096 帧 @30fps(167 句);七幕抽帧 FAIL 0 · WARN 0;高风险 8 帧逐帧目检通过;终渲未启动", "voice": "sunny-steady + me-bright.wav" }, { @@ -123,8 +123,8 @@ "license": "MIT", "accessed": "2026-08-22" }, - "status": "ready", - "statusNote": "已交付:成片 13:14.00(1080p30,39.5 MB · total_duration_in_frames 复算 23820 帧 @30fps)+ srt/vtt 各 134 cue;终渲尾幕抽帧 FAIL 0(WARN 1 为信源卡刻意停留)", + "status": "draft-review", + "statusNote": "Harness Engineering 改造草渲待审:13:10 = 23706 帧 @30fps(135 句);七幕抽帧 FAIL 0 · WARN 0;终渲未启动", "voice": "sunny-steady + me-bright.wav" }, { @@ -145,8 +145,8 @@ "license": "MIT", "accessed": "2026-08-22" }, - "status": "ready", - "statusNote": "已交付:成片 13:14.47(1080p30,36.1 MB · total_duration_in_frames 复算 23834 帧 @30fps)+ srt/vtt 各 140 cue;七幕 FAIL 0(WARN 2 均刻意停留);终渲尾幕 FAIL 0 · WARN 0", + "status": "draft-review", + "statusNote": "Harness Engineering 改造草渲待审:13:06 = 23607 帧 @30fps(139 句);七幕 FAIL 0(WARN 3 均金句卡刻意静止);终渲未启动", "voice": "sunny-steady + me-bright.wav" }, { @@ -167,8 +167,8 @@ "license": "MIT", "accessed": "2026-08-22" }, - "status": "ready", - "statusNote": "已交付:成片 13:08.90(1080p30,40.9 MB · total_duration_in_frames 复算 23667 帧 @30fps)+ srt/vtt 各 139 cue;七幕 FAIL 0(首渲 p1-10 侵入已修);终渲尾幕 FAIL 0 · WARN 0", + "status": "draft-review", + "statusNote": "Harness Engineering 改造草渲待审:13:07 = 23621 帧 @30fps(139 句);七幕抽帧 FAIL 0 · WARN 0;终渲未启动", "voice": "sunny-steady + me-bright.wav" }, { @@ -189,8 +189,8 @@ "license": "MIT", "accessed": "2026-08-22" }, - "status": "ready", - "statusNote": "已交付:成片 13:03.27(1080p30,42.4 MB · total_duration_in_frames 复算 23498 帧 @30fps)+ srt/vtt 各 133 cue;七幕 FAIL 0 · WARN 0(系列唯一全零)", + "status": "draft-review", + "statusNote": "Harness Engineering 改造草渲待审:13:08 = 23667 帧 @30fps(134 句);七幕 FAIL 0 · WARN 0(尾帧 WARN 1 为收束卡刻意停留);终渲未启动", "voice": "sunny-steady + me-bright.wav" } ] From 6e223b13a7bd6bee4c2c80213c4b3191a96d7c5d Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sun, 23 Aug 2026 12:42:27 +0800 Subject: [PATCH 14/41] =?UTF-8?q?feat(video):=20Harness=20=E6=9C=AF?= =?UTF-8?q?=E8=AF=AD=E8=BF=98=E5=8E=9F=E8=8B=B1=E6=96=87=E2=80=94=E2=80=94?= =?UTF-8?q?=E5=8F=A3=E6=92=AD=209=20=E5=8F=A5=E3=80=81=E7=94=BB=E9=9D=A2?= =?UTF-8?q?=E5=A4=A7=E5=AD=97=E4=B8=8E=E5=BC=95=E6=96=87=E3=80=81=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E5=B1=82=E7=BB=9F=E4=B8=80;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户审核意见:所有 Harness 的中文翻译(挽具等)还原为英文 Harness。 - 口播 9 句重写并重配(EP1×6 / EP3×1 / EP5×1,Harness 走 IndexTTS 英文直读通道—— 与产品名 Claude Code 同款已在 5 集成片验证);narration 头部纪律注释同步(英文口播 例外:Claude Code 与 Harness)。 - 画面:命名帧大字「挽 具」→「Harness」(letterSpacing 收窄)、官方引文条、 EP5 收官反转金句、P0/P6 注释与 Sequence name。 - 文档层:storyboard/planning/verification×2/series.json/series.md 统一; 自动生成物(narration.json/manifest)随 build+tts 重写。 - 三集重渲(EP1/EP3/EP5)+ P0/P6 抽帧体检 FAIL 0 + 命名帧/反转帧目检通过 (英文 Harness 无乱码、无重叠、字幕区干净);EP4 场景锚顺手修至 p5-23b(清掉 一条既有 WARN)。试听样本 out/harness-pron-sample.mp3 供人耳确认英文读音。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../video/src/scenes/P5Truths.tsx | 2 +- .../research/verification-2026-08-23.md | 4 ++-- .../script/narration.json | 12 ++++++------ .../script/narration.md | 14 +++++++------- .../script/storyboard.md | 4 ++-- .../video/src/scenes/P0Hook.tsx | 18 +++++++++--------- .../script/narration.json | 2 +- .../script/narration.md | 4 ++-- .../research/verification-2026-08-23.md | 2 +- .../script/narration.json | 2 +- .../script/narration.md | 4 ++-- .../video/src/scenes/P6Finale.tsx | 4 ++-- apps/negentropy-influence/series.json | 2 +- apps/negentropy-influence/series.md | 2 +- 14 files changed, 38 insertions(+), 38 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx index c5fd407b..22bf9b40 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx @@ -495,7 +495,7 @@ export const P5Truths: React.FC<{scene: SceneRange}> = ({scene}) => { const bB = w('p5-05', 'p5-08'); const bC = w('p5-09', 'p5-10'); const bD = w('p5-11', 'p5-18'); - const bE = w('p5-19', 'p5-23'); + const bE = w('p5-19', 'p5-23b'); return ( diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/research/verification-2026-08-23.md b/apps/negentropy-influence/episodes/claude-code-explained-video/research/verification-2026-08-23.md index cf680859..ef0a6ab7 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/research/verification-2026-08-23.md +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/research/verification-2026-08-23.md @@ -7,7 +7,7 @@ | 口播句 | 断言 | 证据级 | 事实源锚点 | 判定 | |---|---|---|---|---| -| p0-04..06 | 「挽具」官方命名 + 模型在挽具里面 + 供给五样 | 【二】 | code.claude.com/docs/en/glossary(Agentic harness 条目)· how-claude-code-works | ✅ VERIFIED | +| p0-04..06 | 「Harness」官方命名 + 模型在Harness里面 + 供给五样 | 【二】 | code.claude.com/docs/en/glossary(Agentic harness 条目)· how-claude-code-works | ✅ VERIFIED | | p1-25..27 | 三相循环交融 + 人随时可打断 | 【二】 | how-claude-code-works(gather/take/verify) | ✅ VERIFIED | | p1-28..29 | State 十字段(角标化) | 【三】 | 第三方源码分析(归属句保留) | ✅ VERIFIED(带归属) | | p3-06 | 权限由代码执行不由模型执行 | 【二】 | code.claude.com/docs/en/permissions | ✅ VERIFIED | @@ -25,7 +25,7 @@ ## 二、易懂性校验 -- 新概念首现配比喻:挽具(p0-04「把动力源,套进一个可控的结构里」);三相(p1-26「不是硬阶段」); +- 新概念首现配比喻:Harness(p0-04「把动力源,套进一个可控的结构里」);三相(p1-26「不是硬阶段」); 六闸(沿三闸门认知升级,画面先轨道后闸)。 - 金句节奏保留:每幕收尾金句未动(1-D/2-F/3-D/4-G2/5-C 全保留)。 - 英文标识符只在角标(agentic harness / deny/ask/allow / hook / workflow 等全画面层)。 diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json index be4e9bf8..3c4fd2f8 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json @@ -17,22 +17,22 @@ { "id": "p0-04", "scene": "P0", - "text": "名字就叫挽具:把动力源,套进一个可控的结构里。" + "text": "名字就叫 Harness:把动力源,套进一个可控的结构里。" }, { "id": "p0-05", "scene": "P0", - "text": "官方说得直白:这套东西是挽具,模型在挽具里面。" + "text": "官方说得直白:这套东西是 Harness,模型装在 Harness 里面。" }, { "id": "p0-06", "scene": "P0", - "text": "挽具供给它五样东西:文件、命令、权限、记忆、护栏。" + "text": "Harness 供给它五样东西:文件、命令、权限、记忆、护栏。" }, { "id": "p0-07", "scene": "P0", - "text": "这集就把这只挽具,一层一层拆开看。" + "text": "这集就把这个 Harness,一层一层拆开看。" }, { "id": "p1-01", @@ -722,7 +722,7 @@ { "id": "p5-05", "scene": "P5", - "text": "官方给挽具的定义正好四件:循环、工具、上下文管理、护栏。" + "text": "官方给 Harness 的定义正好四件:循环、工具、上下文管理、护栏。" }, { "id": "p5-06", @@ -817,7 +817,7 @@ { "id": "p6-05", "scene": "P6", - "text": "学会给挽具做加减法,这本身就是一门手艺。" + "text": "学会给 Harness 做加减法,这本身就是一门手艺。" }, { "id": "p6-06", diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md index 71a31721..a0e1916f 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md @@ -2,7 +2,7 @@ > **全片单一事实源的下游**:每条断言回溯 [../research/source-notes.md](../research/source-notes.md);策划见 [planning.md](./planning.md)。 > 格式约定:`## P` 起一幕;`- [pN-xx] 文本` 一行一句(进配音);`>` 引用块是画面备注与角标(**不进配音**)。 -> 纪律:英文标识符只进角标不进口播(唯一例外是产品名 Claude Code);三级证据必带归属句 +> 纪律:英文标识符只进角标不进口播(例外:产品名 Claude Code 与术语 Harness);三级证据必带归属句 > (「有人拆过它的源码——…」);不引用行数绝对值、章节数等活数据。 > > **字数是硬约束**:`chars_per_min = 280` 是**含停顿的等效口径**(实测纯语速 301 字/分, @@ -17,10 +17,10 @@ - [p0-01] 你让 AI 跑个脚本:它把命令写好,然后就停在那儿了。 - [p0-02] 复制、粘贴、回车、再把输出贴回去——每一轮的搬运工,是你。 - [p0-03] 从「写出命令」到「真的跑起来」,缺的那一层,官方起了名字。 -- [p0-04] 名字就叫挽具:把动力源,套进一个可控的结构里。 -- [p0-05] 官方说得直白:这套东西是挽具,模型在挽具里面。 -- [p0-06] 挽具供给它五样东西:文件、命令、权限、记忆、护栏。 -- [p0-07] 这集就把这只挽具,一层一层拆开看。 +- [p0-04] 名字就叫 Harness:把动力源,套进一个可控的结构里。 +- [p0-05] 官方说得直白:这套东西是 Harness,模型装在 Harness 里面。 +- [p0-06] Harness 供给它五样东西:文件、命令、权限、记忆、护栏。 +- [p0-07] 这集就把这个 Harness,一层一层拆开看。 ## P1 一个循环,就是全部 @@ -221,7 +221,7 @@ - [p5-02] 第一层,一个循环:反复问模型,替它执行,把结果搬回来。 - [p5-03] 第二层,一张分发表:让工具可以随便加。 - [p5-04] 第三层,三道闸门:让危险的事在执行之前被拦住。 -- [p5-05] 官方给挽具的定义正好四件:循环、工具、上下文管理、护栏。 +- [p5-05] 官方给 Harness 的定义正好四件:循环、工具、上下文管理、护栏。 - [p5-06] 这集拆的,正好填进前三格;第四格先空着,后面拆。 - [p5-07] 这不是我的说法,是可以数出来的。 - [p5-08] 我把四章的代码逐一量过:整个程序从一百四十行出头, @@ -253,7 +253,7 @@ - [p6-02] 而是因为有人在它周围,搭了这几层结构。 - [p6-03] 循环给它手脚,分发表给它工具,闸门守着底线,插口留给你发挥。 - [p6-04] 这几层结构不神秘,加起来两百多行,一个下午能读完。 -- [p6-05] 学会给挽具做加减法,这本身就是一门手艺。 +- [p6-05] 学会给 Harness 做加减法,这本身就是一门手艺。 - [p6-06] 本片机制依据官方文档,取数2026年8月,以官方最新表述为准。 - [p6-07] 教学代码来自开源实现,行数均为实测,链接在简介。 - [p6-08] 下期,拆它怎么安排自己看到的东西:计划写在哪,活儿怎么分出去。 diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md index d1d9a90e..0c1fa753 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md @@ -14,8 +14,8 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 0-A | p0-01..02 | 全屏终端窗口(`panel` 底 + `panelBorder` 框),顶栏三个灰点。命令打完光标变灰凝住;右侧对话框浮出 | 终端打字机(每字 2 帧);命令打完后光标**停止闪烁并变灰**,画面凝住 0.6s;p0-02 三轮「复制→粘贴→回车→回贴」搬运弧线**加速**塞满灰色残影(节奏比旧版快一倍) | -| 0-B | p0-03..05 | 全部搬运残影瞬间收束成一条外框线,包住一枚「模型」内核——**命名帧**:外框即挽具 | 外框自四面向内合拢包住内核(spring);「挽具」二字落框(serif 大字),英文 agentic harness 进角标;p0-05 官方引文条压上("Claude Code is the harness, Claude is the model" 中英并列淡入) | -| 0-C | p0-06..07 | 挽具供给图:外框上长出五根辐条(文件 / 命令 / 权限 / 记忆 / 护栏),内侧连着模型内核 | p0-06 五根辐条逐根点亮(`mech` 辉光各 8 帧);「记忆」那根先灰并浮「后面拆」小标;p0-07 外框整体轻旋一次,片名标题卡压入(`core` 色细线自中心向两侧生长) | +| 0-B | p0-03..05 | 全部搬运残影瞬间收束成一条外框线,包住一枚「模型」内核——**命名帧**:外框即Harness | 外框自四面向内合拢包住内核(spring);「Harness」二字落框(serif 大字),英文 agentic harness 进角标;p0-05 官方引文条压上("Claude Code is the harness, Claude is the model" 中英并列淡入) | +| 0-C | p0-06..07 | Harness供给图:外框上长出五根辐条(文件 / 命令 / 权限 / 记忆 / 护栏),内侧连着模型内核 | p0-06 五根辐条逐根点亮(`mech` 辉光各 8 帧);「记忆」那根先灰并浮「后面拆」小标;p0-07 外框整体轻旋一次,片名标题卡压入(`core` 色细线自中心向两侧生长) | ## P1 一个循环,就是全部 diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx index aaf39f09..cb0ef687 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx @@ -1,5 +1,5 @@ /** P0 钩子与命名帧(分镜 0-A…0-C) - * 三句内完成:搬运工痛点 → 官方命名「挽具」→ 五辐条供给图。 + * 三句内完成:搬运工痛点 → 官方命名「Harness」→ 五辐条供给图。 * 改造(2026-08 Harness Engineering):10 句压缩为 7 句,命名帧是全系列的开场锚。 */ import React from 'react'; import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoConfig} from 'remotion'; @@ -74,7 +74,7 @@ const StallAndCarry: React.FC<{carryAt: number}> = ({carryAt}) => { ); }; -/** 0-B 命名帧:搬运残影收束成外框,包住「模型」内核——外框即挽具 + 官方引文条 */ +/** 0-B 命名帧:搬运残影收束成外框,包住「模型」内核——外框即 Harness + 官方引文条 */ const NamingFrame: React.FC<{officialAt: number}> = ({officialAt}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); @@ -160,7 +160,7 @@ const NamingFrame: React.FC<{officialAt: number}> = ({officialAt}) => { {'判断力在里面'}
- {/* 「挽具」落框 */} + {/* 「Harness」落框 */}
= ({officialAt}) => { transform: `translate(-50%, 0) scale(${0.7 + 0.3 * label})`, opacity: label, fontFamily: theme.serif, - fontSize: 56, + fontSize: 58, fontWeight: 700, color: theme.core, - letterSpacing: 8, + letterSpacing: 2, }} > - {'挽 具'} + {'Harness'}
= ({officialAt}) => { >
- {'“Claude Code 是挽具,Claude 是里面的模型。”'} + {'“Claude Code 是 Harness,Claude 是里面的模型。”'}
{'— 官方文档 how-claude-code-works(code.claude.com,取数2026年8月)'} @@ -243,7 +243,7 @@ const SupplySpokes: React.FC<{titleAt: number}> = ({titleAt}) => { return ( - {/* 外框(挽具轮廓,缩小型持续在场) */} + {/* 外框(Harness 轮廓,缩小型持续在场) */} = ({scene}) => { - + diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json index 029896ec..b28a02e8 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json @@ -672,7 +672,7 @@ { "id": "p6-06", "scene": "P6", - "text": "记忆是建议,钩子才是规则——这是提示词工程和挽具工程的第一道分水岭。" + "text": "记忆是建议,钩子才是规则——这是提示词工程和 Harness 工程的第一道分水岭。" }, { "id": "p6-07", diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md index 21448360..60ba3b13 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md @@ -2,7 +2,7 @@ > **全片单一事实源的下游**:每条断言回溯 [../research/source-notes.md](../research/source-notes.md)。 > 格式约定:`## P` 起一幕;`- [pN-xx] 文本` 一行一句(进配音);`>` 引用块是画面备注(不进配音)。 -> 纪律:英文标识符只进角标(唯一例外 Claude Code);三级证据必带归属句;活数据不进口播; +> 纪律:英文标识符只进角标(例外:Claude Code 与 Harness);三级证据必带归属句;活数据不进口播; > 不出现他集标题与顺序词。 > > 字数硬约束:280 字/分钟含停顿等效;窗口 [13.0, 14.6] → 精算 3640–4100 字。 @@ -186,7 +186,7 @@ - [p6-03] 一套负责体面地忘:分级收拾、先存再丢、压完往回捞; - [p6-04] 一套负责固执地记:一事一文件、索引常驻、先抢救再碎纸。 - [p6-05] 官方还有一句话值得放在最后:这两条腿,都是上下文,不是闸门。 -- [p6-06] 记忆是建议,钩子才是规则——这是提示词工程和挽具工程的第一道分水岭。 +- [p6-06] 记忆是建议,钩子才是规则——这是提示词工程和 Harness 工程的第一道分水岭。 - [p6-07] 本片以官方文档为主,取数2026年8月,以官方最新表述为准。 - [p6-08] 涉及产品内部的部分,为第三方源码分析,片中已逐处标注。 - [p6-09] 下次它又忘了你的偏好,你知道去哪找——不是它的脑子,是那个文件夹。 diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/research/verification-2026-08-23.md b/apps/negentropy-influence/episodes/claude-code-multiagent-video/research/verification-2026-08-23.md index bd5b84f2..ae3538ef 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/research/verification-2026-08-23.md +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/research/verification-2026-08-23.md @@ -9,7 +9,7 @@ | p2-20..22 | 三禁止(不替批权限/不代同意/被拒不转给别的队友) | 【二】 | agent-teams「Messages between agents」 | ✅ VERIFIED | | p5-07..09 | worktree 四道闸 · 第四道不能关 | 【二】 | worktrees「How Claude Code enforces isolation」 | ✅ VERIFIED | | p5-22 | 装十个服务上下文几乎不占(按需取用) | 【二】 | mcp(tool search 延迟装载) | ✅ VERIFIED | -| p6-08..11 | 谁持有计划四形态 · 中间结果住变量 · 并发十六/一千 · 挽具由它自己写 | 【二】 | workflows(When to use a workflow + Behavior and limits) | ✅ VERIFIED | +| p6-08..11 | 谁持有计划四形态 · 中间结果住变量 · 并发十六/一千 · Harness由它自己写 | 【二】 | workflows(When to use a workflow + Behavior and limits) | ✅ VERIFIED | | p6-13..14 | 协调成本 · 十五倍 token | 【二】 | 官方工程博客(multi-agent research system) | ✅ VERIFIED | | p3-12..14 | 三向关机 | 【三】 | 第三方源码分析(归属句保留) | ✅ VERIFIED(带归属) | diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json index f242b040..088f9ccd 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json @@ -617,7 +617,7 @@ { "id": "p6-11", "scene": "P6", - "text": "挽具第一次,开始由它自己来写。" + "text": "Harness 第一次,开始由它自己来写。" }, { "id": "p6-11a", diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md index e2440656..b9e83d49 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md @@ -2,7 +2,7 @@ > **全片单一事实源的下游**:每条断言回溯 [../research/source-notes.md](../research/source-notes.md)。 > 格式约定:`## P` 起一幕;`- [pN-xx] 文本` 一行一句(进配音);`>` 引用块是画面备注(不进配音)。 -> 纪律:英文标识符只进角标(唯一例外 Claude Code);三级证据必带归属句;活数据不进口播; +> 纪律:英文标识符只进角标(例外:Claude Code 与 Harness);三级证据必带归属句;活数据不进口播; > 不出现他集标题与顺序词。 > > 字数硬约束:280 字/分钟含停顿等效;窗口 [13.0, 14.6]。 @@ -178,7 +178,7 @@ - [p6-08] 官方给了答案——第四种形态:让它当场把编排写成一段脚本。 - [p6-09] 循环、分支、中间结果,住进脚本变量;它的上下文,只装最终答案。 - [p6-10] 脚本落盘,可读、可比对、改完能重跑;并发最多十六,单次一千。 -- [p6-11] 挽具第一次,开始由它自己来写。 +- [p6-11] Harness 第一次,开始由它自己来写。 - [p6-11a] 这种脚本能拼出好几种打法:一批活扇出去、各自干完再汇总成一份; - [p6-11b] 或者干完先请另一个它挑刺,挑完再改——改到合格才算完。 - [p6-11c] 中断也不慌:重新拉起时,干完的直接命中,没干完的从头再跑—— diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx index 00d6858b..800a90db 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx @@ -397,7 +397,7 @@ const SeriesFinale: React.FC<{riseAt: number; quoteAt: number}> = ({riseAt, quot /** 6-D ★谁持有计划:四象对比(Harness Engineering 收官纲图) * 官方 workflows 的四方对比——临时工/技能包/队友:计划由模型逐回合现场决定; * 第四种(动态工作流):脚本持有计划,中间结果住变量、上下文只装最终答案。 - * 分水岭竖线落下是全片思想高点;收官反转「挽具第一次由它自己来写」。 */ + * 分水岭竖线落下是全片思想高点;收官反转「Harness 第一次由它自己来写」。 */ const WhoHoldsPlan: React.FC<{gridAt: number; divideAt: number; runtimeAt: number; twistAt: number}> = ({ gridAt, divideAt, @@ -557,7 +557,7 @@ const WhoHoldsPlan: React.FC<{gridAt: number; divideAt: number; runtimeAt: numbe color: theme.core, }} > - {'挽具第一次,开始由它自己来写'} + {'Harness 第一次,开始由它自己来写'}
) : null}
diff --git a/apps/negentropy-influence/series.json b/apps/negentropy-influence/series.json index 00ad8790..27359d62 100644 --- a/apps/negentropy-influence/series.json +++ b/apps/negentropy-influence/series.json @@ -86,7 +86,7 @@ "slug": "claude-code-explained-video", "path": "episodes/claude-code-explained-video", "title": "执行层:一个循环,就是全部", - "topic": "工具与执行:把模型装进挽具", + "topic": "工具与执行:把模型装进Harness", "cardSub": "执行层 · 循环", "accents": [ "#D97757", diff --git a/apps/negentropy-influence/series.md b/apps/negentropy-influence/series.md index 87bbd1b7..17a54175 100644 --- a/apps/negentropy-influence/series.md +++ b/apps/negentropy-influence/series.md @@ -29,7 +29,7 @@ | # | 作品 | 一句话主题 | 视觉契约(主色) | 信源 | 状态 | |---|---|---|---|---|---| -| 1 | [《执行层:一个循环,就是全部》](./episodes/claude-code-explained-video/README.md) | 工具与执行:把模型装进挽具 | 陶土橙/石青/警示红 | [Learn Claude Code](https://learn.shareai.run/zh/s01/) s01–s04 + 仓库 @ `f9e8b28`(MIT),2026-08 | **Harness Engineering 改造中**(配音缓存 170/170 迁移命中;改造草渲后交付) | +| 1 | [《执行层:一个循环,就是全部》](./episodes/claude-code-explained-video/README.md) | 工具与执行:把模型装进Harness | 陶土橙/石青/警示红 | [Learn Claude Code](https://learn.shareai.run/zh/s01/) s01–s04 + 仓库 @ `f9e8b28`(MIT),2026-08 | **Harness Engineering 改造中**(配音缓存 170/170 迁移命中;改造草渲后交付) | | 2 | [《规划层:模型的视野是安排出来的》](./episodes/claude-code-planning-video/README.md) | 规划与协调:谁替它安排视野 | 鸢紫 `view`(底座陶土橙/石青全系列共享) | s05–s07 · s10 · s11 @ 站点同源修订 `67a9126c`(MIT) | **Harness Engineering 改造中**(134 句基线;改造草渲后交付) | | 3 | [《记忆层:会丢的和不能丢的》](./episodes/claude-code-memory-video/README.md) | 记忆管理:窗口内外的两本账 | 苔绿 `keep` | s08 · s09 @ `67a9126c`(MIT) | **Harness Engineering 改造中**(140 句基线;改造草渲后交付) | | 4 | [《时机层:谁来按下开始》](./episodes/claude-code-concurrency-video/README.md) | 并发与调度:谁替它看表 | 霜蓝 `later` | s13 · s14 @ `67a9126c`(MIT) | **Harness Engineering 改造中**(139 句基线;改造草渲后交付) | From 52d431fb9c2cf4bc4938714746ed70b79c1657b2 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sun, 23 Aug 2026 22:30:55 +0800 Subject: [PATCH 15/41] =?UTF-8?q?fix(video):=20check=5Fseries=20=E8=A7=84?= =?UTF-8?q?=E5=88=997=20=E7=AB=A0=E5=8F=B7=E6=AD=A3=E5=88=99=E8=A1=A5=20CJ?= =?UTF-8?q?K=20=E8=B4=B4=E9=82=BB=E7=9B=B2=E5=8C=BA=20+=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E8=A7=84=E5=88=998=20=E4=B8=8B=E6=9C=9F=E5=8D=A1?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E9=97=A8;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 规则 7 章号分支弃用 \b 锚(CJK 汉字属 \w,「对应s01」类无空格贴邻写法不构成边界、恰好逃过执法),改 ASCII 侧环视 (? --- .../pipeline/scripts/check_series.py | 57 +++++++- .../pipeline/tests/test_check_series.py | 135 ++++++++++++++++++ 2 files changed, 189 insertions(+), 3 deletions(-) diff --git a/apps/negentropy-influence/pipeline/scripts/check_series.py b/apps/negentropy-influence/pipeline/scripts/check_series.py index cc1769da..6eb618e7 100644 --- a/apps/negentropy-influence/pipeline/scripts/check_series.py +++ b/apps/negentropy-influence/pipeline/scripts/check_series.py @@ -31,6 +31,9 @@ 从「介绍开源课程」转为「拆解 harness 工程」——站点只作组织骨架,观众 不得感知其存在。改写示例:「课程作者拆过源码,他说…」→「有人拆过它的 源码,他说…」(三级证据归属保留、不点名)。 + 8. 下期卡同步:配了「系列身份卡 + 下期预告卡」收尾装置的系列(见 + NEXT_CARD_SERIES_IDS),P6 场景文本必须含本集标题与下集标题的主段 + ——硬编码标题在系列更名/改题时会静默变陈旧,此处在提交前拦住。 多系列语义(2026-08 起 series.json 顶层为 seriesList[]): - 规则 1 **跨系列全局生效**——不同系列各自独立成片,口播互不引用,故「他集」 @@ -70,18 +73,25 @@ EP_NUM = re.compile(r"第([一二三四五六七八九十])集") #: 规则 7 · 课程站点标识(观众可见层禁词)。`课程/站点` 单独成词太宽—— -#: 「教程/网站」一类常用词不受牵连;章号用词边界锚死(`\bs01\b` 不命中 -#: `s01e02` 或 `as01`),且只认 20 章真实编号范围。 +#: 「教程/网站」一类常用词不受牵连。章号不用 `\b` 锚:CJK 汉字在 re 里属 +#: `\w`,中文最常见的无空格贴邻写法(「对应s01」)前后都是汉字、不构成 +#: 边界,恰好逃过执法——改用 ASCII 侧环视:两侧只要不是 ASCII 字母数字 +#: 下划线就算命中(「对应s01」「s01-readme」✓;`s01e02`/`as01` 仍排除, +#: `s01_agent_loop` 目录名与原 `\b` 行为一致地排除),且只认 20 章真实编号。 #: 「站点」按系列豁免:self-evolution 系(论文型)用它指论文的**配套网站** #: (「官方工程站点统计」「配套站点 data/papers.json」)——与课程站点无关, #: 执法进去是纯假报。课程系指站点一律用「课程」或显式 URL,语义不重叠。 SITE_MARKER_RE = re.compile( r"learn\.shareai|Learn Claude Code|shareAI" r"|课程" - r"|\bs(?:0[1-9]|1[0-9]|20)\b" + r"|(? None: ) +def rule_next_ep_card(series_list: list[dict], msgs: list[str]) -> None: + """规则 8:下期卡与 series.json 同步——身份卡标题/下期卡标题硬编码即漂移。 + + P6 身份卡的本集标题、下期卡的「下期 · 层名」与下集标题,都是 + series.json 的派生数据,却是各集 P6 场景组件里的字符串字面量。 + 本规则把两者机械化对账:本集身份卡标题、下集预告标题必须能在 P6 + 场景文本里找到(标题含「:」时按**主标题后半段**匹配——画面卡的 + 层名前缀在卡眉「下期 · X层」,正文只放副题部分)。系列更名/改标题 + 时这里第一时间 FAIL,而不是等观众看到陈旧预告。仅对 + NEXT_CARD_SERIES_IDS(配了统一收尾装置的系列)执法。 + """ + + def main_part(title: str) -> str: + return title.split(":", 1)[-1] if ":" in title else title + + for series in series_list: + if series["id"] not in NEXT_CARD_SERIES_IDS: + continue + eps = sorted(series["episodes"], key=lambda e: e["episode"]) + for i, e in enumerate(eps): + p6 = INFLUENCE / e["path"] / "video/src/scenes" + files = sorted(p6.glob("P6*.tsx")) if p6.is_dir() else [] + if not files: + continue + text = "".join(f.read_text(encoding="utf-8") for f in files) + rel = files[0].relative_to(REPO) + if main_part(e["title"]) not in text: + msgs.append( + f"FAIL 规则8:{rel} 身份卡缺本集标题「{e['title']}」" + "(series.json 是发布顺序 SSOT,画面卡须逐字同步)" + ) + if i + 1 < len(eps): + nxt = eps[i + 1] + if main_part(nxt["title"]) not in text: + msgs.append( + f"FAIL 规则8:{rel} 下期卡缺下集标题「{nxt['title']}」" + "(series.json 是发布顺序 SSOT,硬编码漂移即陈旧预告)" + ) + + def main() -> None: series_list = load_series() files = covered_files() @@ -492,6 +542,7 @@ def main() -> None: rule_dead_links(files, msgs) rule_renderability(series_list, msgs) rule_site_marker(series_list, msgs) + rule_next_ep_card(series_list, msgs) fails = [m for m in msgs if m.startswith("FAIL")] warns = [m for m in msgs if m.startswith("WARN")] diff --git a/apps/negentropy-influence/pipeline/tests/test_check_series.py b/apps/negentropy-influence/pipeline/tests/test_check_series.py index ef31cf07..93a485a6 100644 --- a/apps/negentropy-influence/pipeline/tests/test_check_series.py +++ b/apps/negentropy-influence/pipeline/tests/test_check_series.py @@ -480,3 +480,138 @@ def test_rule7_strong_marker_in_paper_series_fails(tmp_path): ) rc, out = run_check(repo) assert rc == 1 and "规则7" in out and "s13" in out + + +def test_rule7_chapter_id_cjk_adjacent_fails(tmp_path): + """章号贴邻汉字(无空格)同样命中——`\b` 在 CJK 邻接下不成立(评审修复), + 改用 ASCII 侧环视后「对应s01」这类中文最自然的笔误形态不再逃过执法。""" + repo = build_repo(tmp_path, [S("claude-code-explained", COURSE_S)], {}) + (ep_root(repo, COURSE_S) / "script/storyboard.md").write_text( + "## P0\n\n- 0-A 开场(对应s01的循环)\n", encoding="utf-8" + ) + rc, out = run_check(repo) + assert rc == 1 and "规则7" in out and "s01" in out + + +def test_rule7_chapter_id_cjk_adjacent_trailing_fails(tmp_path): + """章号后紧跟汉字(「看s13的后台」)同样命中。""" + repo = build_repo(tmp_path, [S("claude-code-explained", COURSE_S)], {}) + (ep_root(repo, COURSE_S) / "script/narration.md").write_text( + "## P0\n\n- [p0-02] 看s13的后台任务。\n", encoding="utf-8" + ) + rc, out = run_check(repo) + assert rc == 1 and "规则7" in out and "s13" in out + + +def test_rule7_chapter_id_prefix_suffix_ascii_still_exempt(tmp_path): + """ASCII 词符贴邻(`s01e02` / `as01` / `s01_agent_loop` 目录名)仍豁免—— + 环视排除集与原 `\b` 行为对齐,仅补上 CJK 贴邻盲区。""" + repo = build_repo(tmp_path, [S("claude-code-explained", COURSE_S)], {}) + (ep_root(repo, COURSE_S) / "script/storyboard.md").write_text( + "## P0\n\n- 0-A 开场(对比 as01 / s01e02 / s01_agent_loop 三种写法)\n", + encoding="utf-8", + ) + rc, out = run_check(repo) + assert rc == 0, out + + +# ── 规则 8 · 下期卡与 series.json 同步(2026-08-23 评审修复引入)────────────── +#: P6 文本须含本集标题与下集标题的主段(「:」后半);标题带主副结构时画面卡 +#: 只放副题。系列 id 须在 NEXT_CARD_SERIES_IDS(配了统一收尾装置的系列)。 +#: accent 与 COURSE_S 错开(规则 4 系列内禁撞色)。 +NEXT_EP2 = { + "episode": 2, + "slug": "ep-next2", + "path": "episodes/ep-next2", + "title": "规划层:视野是安排出来的", + "accents": ["#9C90EE"], + "paper": {}, +} + + +def _write_p6(repo, ep, body): + p6 = ep_root(repo, ep) / "video/src/scenes" + p6.mkdir(parents=True, exist_ok=True) + (p6 / "P6Ending.tsx").write_text( + "export const P6Ending = () => null;\n" + body, encoding="utf-8" + ) + + +def test_rule8_next_card_stale_title_fails(tmp_path): + """下期卡硬编码的旧标题与 series.json 不符——系列更名时的陈旧预告,FAIL。""" + repo = build_repo( + tmp_path, + [ + S( + "claude-code-explained", + {**COURSE_S, "title": "执行层:一个循环"}, + NEXT_EP2, + ) + ], + {}, + ) + _write_p6( + repo, + COURSE_S, + "// {'下期 · 规划层'} {'视野是安排出来的'}", + ) + # 用 series.json 的最新标题替换画面卡的旧串 → 陈旧 + p6 = ep_root(repo, COURSE_S) / "video/src/scenes/P6Ending.tsx" + p6.write_text( + "export const P6Ending = () => null;\n// {'下期 · 规划层'} {'旧标题占位'}\n", + encoding="utf-8", + ) + rc, out = run_check(repo) + assert rc == 1 and "规则8" in out and "视野是安排出来的" in out + + +def test_rule8_own_identity_card_missing_fails(tmp_path): + """身份卡缺本集标题(更名后只改了下期卡)——FAIL。""" + repo = build_repo( + tmp_path, + [S("claude-code-explained", COURSE_S, NEXT_EP2)], + {}, + ) + _write_p6( + repo, + COURSE_S, + "// 只有下期卡:{'视野是安排出来的'},身份卡标题没更新", + ) + rc, out = run_check(repo) + assert rc == 1 and "规则8" in out and "身份卡缺本集标题" in out + + +def test_rule8_synced_cards_pass(tmp_path): + """身份卡 + 下期卡都与 series.json 主段一致——静默。""" + repo = build_repo( + tmp_path, + [ + S( + "claude-code-explained", + {**COURSE_S, "title": "执行层:一个循环"}, + NEXT_EP2, + ) + ], + {}, + ) + _write_p6( + repo, + COURSE_S, + "// {'执行层:一个循环'} {'下期 · 规划层'} {'视野是安排出来的'}", + ) + _write_p6( + repo, + NEXT_EP2, + "// {'视野是安排出来的'}(末集,无下期断言)", + ) + rc, out = run_check(repo) + assert rc == 0, out + + +def test_rule8_paper_series_not_policed(tmp_path): + """self-evolution 系无身份卡装置(旧版论文型收尾)——规则 8 不进门。""" + repo = build_repo(tmp_path, [S("self-evolution", EP1, EP2)], {}) + # EP1 的 P6 只有「我们下期再见」,无任何标题卡 + _write_p6(repo, EP1, "// {'我们下期再见'}") + rc, out = run_check(repo) + assert rc == 0, out From bacd1e8cecc8363cbddfa207ee3bc2132072c956 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sun, 23 Aug 2026 22:31:38 +0800 Subject: [PATCH 16/41] =?UTF-8?q?fix(video):=20=E6=97=B6=E9=95=BF=E5=8F=A3?= =?UTF-8?q?=E5=BE=84=E4=B8=89=E5=A4=84=E6=8C=89=E5=A4=8D=E7=AE=97=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=20+=20skills/06=20=E4=BA=94=E5=B1=82=E6=A0=88?= =?UTF-8?q?=E8=A7=84=E6=A0=BC=E6=A0=87=E6=B3=A8=E6=9C=AA=E8=90=BD=E5=9C=B0?= =?UTF-8?q?=E7=8A=B6=E6=80=81;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - series.json statusNote 帧数对齐 total_duration_in_frames 复算:EP1 25096→25151(13:58,含 p5-06 新句配音)、EP3 23607→23622(13:07)、EP5 23667→23666;CHANGELOG 五集时长行同步(13:58/13:10/13:07/13:07/13:08,合计 66.5 分钟)——「时长一律复算不抄上次输出」纪律落地; - skills/06 五层 HarnessStack 节补「落地状态」块:规格先行未落地(草渲不含该装置),防止 SSOT 与已交付事实漂移;「读 series.json」表述改为「派生自 series.json」(与硬编码+规则 8 对账的实现口径一致); - ISSUE-174 沉淀:tts.py 显式 --seed 会改缓存摘要后缀——单句补配触发整集重录且旧缓存被新签名覆盖;处置=立即中断+基线参数重跑恢复;防范=补配单句永不传 --seed,改 sampling 参数先 --plan 看失配面; - EP1 README 改造状态行更新:配音完成(167 句全缓存,tts --plan 待合成 0)。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- CHANGELOG.md | 2 +- .../claude-code-explained-video/README.md | 2 +- .../skills/06-remotion-implementation.md | 7 ++++++- apps/negentropy-influence/series.json | 6 +++--- docs/.agents/issue.md | 21 +++++++++++++++++++ 5 files changed, 32 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3e4ac19..d5cbc786 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 本文件遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/) 约定,版本号遵循 [SemVer](https://semver.org/lang/zh-CN/)。 ## [Unreleased] -- **五集草渲交付(Harness Engineering 改造版,待用户审核后终渲)**:13:56 / 13:10 / 13:06 / 13:07 / 13:08(合计 67.3 分钟草渲口径)。全部新断言锚定官方文档与 Anthropic 工程博客([code.claude.com/docs](https://code.claude.com/docs) 取数2026年8月);去站点化完成(`check_series.py` 规则 7 全绿);五集内容门(含分镜覆盖/读法陷阱/时长双口径)FAIL 0 · WARN 0;七幕抽帧自动体检 FAIL 0;16 个高风险新图解帧(命名帧/六闸流水线/谁持有计划四象/三禁止章/worktree 四道闸/管家进程/存活矩阵/两条腿/前缀缓存条/三相环/31 事件嵌套/auto 视野分屏/裸名 deny/五辐条/三症状卡/下期卡)逐帧目检通过——无重叠、无字幕带侵入、无文字侧倒。配音:716 句基线缓存迁移命中 + 改写句全部重配(sunny-steady + me-bright 不变,两次补配共 ~180 句)。 +- **五集草渲交付(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;16 个高风险新图解帧(命名帧/六闸流水线/谁持有计划四象/三禁止章/worktree 四道闸/管家进程/存活矩阵/两条腿/前缀缓存条/三相环/31 事件嵌套/auto 视野分屏/裸名 deny/五辐条/三症状卡/下期卡)逐帧目检通过——无重叠、无字幕带侵入、无文字侧倒。配音: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` 全零待合成)。 diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/README.md b/apps/negentropy-influence/episodes/claude-code-explained-video/README.md index 4f0e444a..232a779c 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/README.md +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/README.md @@ -1,7 +1,7 @@ # 《执行层:一个循环,就是全部》 > 系列「Claude Code Harness Engineering」首作(发布顺序 SSOT:[../series.json](../../series.json);口播永不携带集数序号)。 -> **改造状态(2026-08-23)**:Harness Engineering 改造版——口播 v-next 已定稿、场景组件已升级、配音重配中;草渲交付待审(终渲未启动)。 +> **改造状态(2026-08-23)**:Harness Engineering 改造版——口播 v-next 已定稿、场景组件已升级、配音完成(167 句全缓存,`tts --plan` 待合成 0);草渲交付待审(终渲未启动)。 > 选题:开源课程 [Learn Claude Code](https://learn.shareai.run/zh/s01/) 的「工具与执行」四章 > —— s01 Agent Loop / s02 Tool Use / s03 Permission / s04 Hooks。 > 形态:1080p30 横屏,代码动画图解 + 本人音色克隆旁白,无真人出镜、无 BGM。 diff --git a/apps/negentropy-influence/pipeline/skills/06-remotion-implementation.md b/apps/negentropy-influence/pipeline/skills/06-remotion-implementation.md index b395e494..3c5ae49d 100644 --- a/apps/negentropy-influence/pipeline/skills/06-remotion-implementation.md +++ b/apps/negentropy-influence/pipeline/skills/06-remotion-implementation.md @@ -125,6 +125,11 @@ QA 验收:逐幕抽帧目检色契约遵守、beat 窗口不越界、角标不 「复制适配不共享」:母题代码落各集 `motifs.tsx`(seeded 档),**本节是五集一致性的规格 SSOT**—— 改规格先改这里,再逐集同步。 +> **落地状态(2026-08-23 评审)**:规格先行,**未落地**——改造版草渲(draft-review)中 +> 各集 P0/P6 均未实现本节装置(EP1 P0 为五辐条供给图,各集 P6 为文字身份卡 + 下期卡)。 +> 本节是终渲前待办的目标规格而非现状描述;落地时逐集同步并在本块更新状态, +> 防止「SSOT 与已交付草渲事实漂移」再次发生。 + ### 五层栈母题(HarnessStack) - **结构**:纵向五层(自底向上:执行 → 规划 → 记忆 → 时机 → 协作),每层一条横板: @@ -133,7 +138,7 @@ QA 验收:逐幕抽帧目检色契约遵守、beat 窗口不越界、角标不 **本集层高亮脉冲**(主色描边 + 辉光呼吸两次),其余层压暗至 55% 亮度;随后栈整体缩小退至画面左上角 作常驻角标(宽 ≤ 300px,本集层保持高亮)——不占字幕安全区。 - **P6 收尾用法**:栈重新放大居中;已发布层保持点亮,**下期层呼吸预告**(画面卡显示下集标题—— - 读 series.json,口播只说「下期 + 话题描述」);系列标语压在栈底。 + 派生自 series.json,口播只说「下期 + 话题描述」);系列标语压在栈底。 - **动画时点**一律由句边界推导(`rel(beat, '句id')`),禁写死帧数。 ### 动效语法(五集统一) diff --git a/apps/negentropy-influence/series.json b/apps/negentropy-influence/series.json index 27359d62..844d1435 100644 --- a/apps/negentropy-influence/series.json +++ b/apps/negentropy-influence/series.json @@ -102,7 +102,7 @@ "accessed": "2026-08-21" }, "status": "draft-review", - "statusNote": "Harness Engineering 改造草渲待审:13:56 = 25096 帧 @30fps(167 句);七幕抽帧 FAIL 0 · WARN 0;高风险 8 帧逐帧目检通过;终渲未启动", + "statusNote": "Harness Engineering 改造草渲待审:13:58 = 25151 帧 @30fps(167 句);七幕抽帧 FAIL 0 · WARN 0;高风险帧逐帧目检通过;终渲未启动", "voice": "sunny-steady + me-bright.wav" }, { @@ -146,7 +146,7 @@ "accessed": "2026-08-22" }, "status": "draft-review", - "statusNote": "Harness Engineering 改造草渲待审:13:06 = 23607 帧 @30fps(139 句);七幕 FAIL 0(WARN 3 均金句卡刻意静止);终渲未启动", + "statusNote": "Harness Engineering 改造草渲待审:13:07 = 23622 帧 @30fps(139 句);七幕 FAIL 0(WARN 3 均金句卡刻意静止);终渲未启动", "voice": "sunny-steady + me-bright.wav" }, { @@ -190,7 +190,7 @@ "accessed": "2026-08-22" }, "status": "draft-review", - "statusNote": "Harness Engineering 改造草渲待审:13:08 = 23667 帧 @30fps(134 句);七幕 FAIL 0 · WARN 0(尾帧 WARN 1 为收束卡刻意停留);终渲未启动", + "statusNote": "Harness Engineering 改造草渲待审:13:08 = 23666 帧 @30fps(134 句);七幕 FAIL 0 · WARN 0(尾帧 WARN 1 为收束卡刻意停留);终渲未启动", "voice": "sunny-steady + me-bright.wav" } ] diff --git a/docs/.agents/issue.md b/docs/.agents/issue.md index fe7b7de2..bf0030d5 100644 --- a/docs/.agents/issue.md +++ b/docs/.agents/issue.md @@ -3724,3 +3724,24 @@ R7 后浏览器对照 Section 2.1 区域发现两类正交缺陷: 记录与履行是两件事,需要各自的落点。 - **同类问题影响**:`research/` 下一切第三方原文归档(A 型论文的 PDF/图片摘录同理,且论文多为 更严格的出版商版权而非 MIT——那类内容应只留指纹与页码,不留字节)。 + +## ISSUE-174 tts.py 显式 `--seed` 会改缓存摘要——单句补配变成整集重录,且旧缓存被新签名覆盖(2026-08-23) + +- **问题描述**:给 `tts.py` 传 `--seed` 只想复现一条新句,结果脚本把 seed 记进**缓存摘要后缀** + (`sampling_suffix`),与全部存量句的摘要失配 → 触发整集 170 句重新排队;已合成的句子 mp3 与 + `.sha` 被新签名覆盖,若就此停手,之后**不带 seed 的正常管线会再次全量重录**(双层浪费)。 +- **表因**:「--seed 让结果可复现」的直觉与「seed 入摘要保证缓存键含合成参数」的设计相撞。 +- **根因**:**A/B 实验参数与成片参数共用同一缓存命名空间**。seed 是实验工具(记忆条目也写明 + 「A/B 必须固定 --seed」),而成片缓存摘要的契约是「与合成结果相关的参数全入键」——两者都对, + 但实验态写进了成片态的缓存槽。缺一个「实验句不落缓存 / 落隔离槽」的逃生口。 +- **处理方式**:发现后立即 pkill 合成进程(已覆盖 26 句),随后**用与基线完全一致的参数 + (无 seed)重跑一次**:26 句恢复 + 1 句新句(p5-06)一并落回基线签名,`tts --plan` 归零验证。 + 代价约 15 分钟合成时间,无数据损失。 +- **后续防范**: + 1. **补配已有集的单句时,永远不传 `--seed`**——基线缓存签名不含它,传了就是整集改写。 + 2. tts.py 若要根治:显式 `--seed` 时打印「此参数将使 N 句缓存失配」的预告并要求 + `--force`/`--allow-voice-switch` 级别的显式确认,或把带 seed 的结果写进隔离后缀槽。 + 3. 判断自己是否踩坑的最快信号:`--plan` 显示的「待合成」数量远大于预期改动句数。 +- **同类问题影响**:所有会改 `sampling_suffix` 的参数(temperature/top-p/top-k/length-penalty/ + repetition-penalty/max-mel-tokens)都有同一形态——对成片集做**实验性**参数调整时, + 先 `--plan` 看失配面,再决定。 From a24ea9c91b19c4dc78d3f3f7b0da145caabc3b60 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sun, 23 Aug 2026 22:32:20 +0800 Subject: [PATCH 17/41] =?UTF-8?q?fix(video):=20EP1=20=E8=AF=84=E5=AE=A1?= =?UTF-8?q?=E4=B8=89=E4=BF=AE=E2=80=94=E2=80=94p5=20=E5=AE=98=E6=96=B9?= =?UTF-8?q?=E5=9B=9B=E4=BB=B6=E5=A5=97=E6=98=A0=E5=B0=84=E3=80=81P0=20?= =?UTF-8?q?=E5=BC=95=E6=96=87=E8=A1=A5=E8=8B=B1=E6=96=87=E5=8E=9F=E5=8F=A5?= =?UTF-8?q?=E3=80=81=E4=B8=8B=E6=9C=9F=E5=8D=A1=E6=B3=A8=E9=87=8A=E5=AF=B9?= =?UTF-8?q?=E9=BD=90;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - p5-05/06 口播映射错位修正:原句「正好填进前三格;第四格先空着」与官方四件套词序对不上(本集未覆盖的是第三格「上下文管理」,非第四格「护栏」——护栏=P3 已讲),改为「这集填上了三件,上下文管理那格先空着,留到后面拆」(narration.md/json 同步,p5-06 重配音,新时长 5.04s); - P5Stack 5-A 增官方四件套标尺:四格横排(循环/工具/上下文管理/护栏)落下,p5-06 三根竖连线把本集三层接到对应格(循环↔循环、分发表↔工具、插口↔护栏),「上下文管理」虚线空置+「空着·后面拆」小标;storyboard 5-A 同步; - P0 命名帧引文条补英文原句 "Claude Code is the harness, Claude is the model."(italic 副行),对齐分镜 0-B 的中英并列承诺; - P6Ending 下期卡注释修正「读 series.json」为「series.json 派生硬编码镜像,规则 8 对账」;storyboard 6-B 同步; - 草渲重渲:25151 帧(838.37s)与 computeTimeline 复算逐帧一致;七幕抽帧自动体检 FAIL 0 · WARN 0;p5-05/06、p0-05 改动帧成片目检通过;captions 重生成 167 cue;tsc --noEmit 通过。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../script/narration.json | 2 +- .../script/narration.md | 2 +- .../script/storyboard.md | 4 +- .../video/src/scenes/P0Hook.tsx | 12 +++ .../video/src/scenes/P5Stack.tsx | 94 ++++++++++++++++++- .../video/src/scenes/P6Ending.tsx | 4 +- 6 files changed, 109 insertions(+), 9 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json index 3c4fd2f8..59cfc801 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json @@ -727,7 +727,7 @@ { "id": "p5-06", "scene": "P5", - "text": "这集拆的,正好填进前三格;第四格先空着,后面拆。" + "text": "这集填上了三件,上下文管理那格先空着,留到后面拆。" }, { "id": "p5-07", diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md index a0e1916f..16c91206 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md @@ -222,7 +222,7 @@ - [p5-03] 第二层,一张分发表:让工具可以随便加。 - [p5-04] 第三层,三道闸门:让危险的事在执行之前被拦住。 - [p5-05] 官方给 Harness 的定义正好四件:循环、工具、上下文管理、护栏。 -- [p5-06] 这集拆的,正好填进前三格;第四格先空着,后面拆。 +- [p5-06] 这集填上了三件,上下文管理那格先空着,留到后面拆。 - [p5-07] 这不是我的说法,是可以数出来的。 - [p5-08] 我把四章的代码逐一量过:整个程序从一百四十行出头, - [p5-09] 长到两百五十多行,长了八成; diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md index 0c1fa753..e23b8423 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md @@ -71,7 +71,7 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| -| 5-A | p5-01..06 | 四层横向卡片:循环(`core` 实心)/ 分发表 / 闸门 / 插槽(后三者 `mech` 描边) | 四张卡逐句自下弹入并水平排开;p5-06 时第一张卡**留在原地并加实底**,后三张同时上浮 8px 并转为半透明——"骨架 vs 挂件"的视觉分层 | +| 5-A | p5-01..06 | 四层横向卡片:循环(`core` 实心)/ 分发表 / 闸门 / 插槽(后三者 `mech` 描边);卡片上方 p5-05 落下**官方四件套标尺**(循环 / 工具 / 上下文管理 / 护栏) | 四张卡逐句自下弹入并水平排开;p5-05 标尺自上淡入落位;p5-06 三根竖连线把本集三层接到对应格(循环↔循环、分发表↔工具、插口↔护栏),「上下文管理」格虚线空置 + 「空着 · 后面拆」小标;随后第一张卡**留在原地并加实底**,后三张同时上浮 8px 并转为半透明——"骨架 vs 挂件"的视觉分层 | | 5-B | p5-07..10 | **四级台阶**:四段柱体高度递增(141/191/241/255),每根柱子内部有一段等高的 `core` 色块 | p5-08/09 四根柱体自左向右逐根升起(`spring`),柱顶数字滚动到位;p5-10 时四根柱子里的 `core` 色块**同时描出**——四段高度肉眼相同且色值相同,柱体其余部分降到 30% 亮度 | | 5-C | p5-11..14 | 环形循环回到画面中央(第五次出现,仍完全同色同线宽),执行节点位置换过四次写法的四个标签轮播 | p5-11/12 环上四个节点依次脉冲一圈;p5-13/14 执行节点上方的标签以 0.4s 间隔翻牌四次(写死命令 → 查表 → 闸门 → 插槽),**环本身一帧未变**;末尾金句卡 | | 5-D | p5-15..19 | 回到 P0 的终端画面(同构图),但这次命令自己跑了起来、输出自动回流;末尾英文原句金句卡 | p5-16 P0 的灰色搬运轨迹以 `core` 色重画一次(这次是自动的);人形剪影淡出;p5-18 四层结构在终端外围合拢成一个壳;p5-19 英文原句 `serif` 与中文并列淡入 | @@ -81,4 +81,4 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 6-A | p6-01..04 | 壳的四层分别点亮并各配一句短标签(手脚 / 工具 / 底线 / 发挥) | 四层以每句一层的节奏点亮,点亮时对应标签 `FadeUp`;四层齐亮后整体轻微收拢一次(呼吸) | -| 6-B | p6-05..08 | 信源卡四行(官方文档+取数日期 / 工程博客 / 源码分析已逐处标注 / 数字均为实测口径)+ 版本护栏行 → 系列身份卡 + **下期预告卡**(读 series.json,标题只在画面) → **渐黑** | 信源卡逐行浮现(mono 小字);系列身份卡 `serif` 淡入;下期卡 `panel` 底描边框浮现(「下期 · 规划层」+ 标题);**渐黑窗口从本 beat 的总时长推导**(`beatDurationInFrames`,红线四),末 1.2s 线性压暗到全黑 | +| 6-B | p6-05..08 | 信源卡四行(官方文档+取数日期 / 工程博客 / 源码分析已逐处标注 / 数字均为实测口径)+ 版本护栏行 → 系列身份卡 + **下期预告卡**(标题只在画面;series.json 派生硬编码,规则 8 对账) → **渐黑** | 信源卡逐行浮现(mono 小字);系列身份卡 `serif` 淡入;下期卡 `panel` 底描边框浮现(「下期 · 规划层」+ 标题);**渐黑窗口从本 beat 的总时长推导**(`beatDurationInFrames`,红线四),末 1.2s 线性压暗到全黑 | diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx index cb0ef687..403d98c0 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx @@ -204,9 +204,21 @@ const NamingFrame: React.FC<{officialAt: number}> = ({officialAt}) => { }} > + {/* 中英并列(分镜 0-B 承诺):中文口播句 + 英文原句 */}
{'“Claude Code 是 Harness,Claude 是里面的模型。”'}
+
+ {'“Claude Code is the harness, Claude is the model.”'} +
{'— 官方文档 how-claude-code-works(code.claude.com,取数2026年8月)'}
diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P5Stack.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P5Stack.tsx index 04520e53..27d72dd1 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P5Stack.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P5Stack.tsx @@ -17,8 +17,12 @@ const CHAPTERS = [ {name: '一排插口', total: 255, loop: 28}, ]; -/** 5-A 四层卡片:第一层并入画面左侧的环(环的第 6 次出场),后三张挂件卡向环滑拢对接 */ -const FourLayers: React.FC<{splitAt: number}> = ({splitAt}) => { +/** 5-A 四层卡片 → 官方四件套映射(p5-05/06,Harness Engineering 改造版): + * 口播「官方定义正好四件:循环、工具、上下文管理、护栏」——四张章节卡上方 + * 落下官方四格标尺,本集三层各连一格(循环↔循环 / 分发表↔工具 / 插口↔护栏 之一), + * 「上下文管理」格保持虚线空置 + 「后面拆」小标(视觉与 p5-06 口播逐字对齐)。 + * 随后原有「骨架 vs 挂件」分层(环 + 挂线)不变。 */ +const FourLayers: React.FC<{splitAt: number; mapAt: number}> = ({splitAt, mapAt}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); const dot = useRingDot(2.8); @@ -32,8 +36,90 @@ const FourLayers: React.FC<{splitAt: number}> = ({splitAt}) => { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); + // 官方四件套标尺:位置对齐下方四卡的水平中心(卡宽 350 + gap 22 → 步距 372) + const OFFICIAL = [ + {t: '循环', link: 0}, + {t: '工具', link: 1}, + {t: '上下文管理', link: -1}, + {t: '护栏', link: 3}, + ]; + const map = interpolate(frame - mapAt, [0, 18], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const linkOn = interpolate(frame - mapAt - 10, [0, 14], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const CARD_W = 350; + const GAP = 22; + const stripLeft = 960 - (CARD_W * 4 + GAP * 3) / 2; return ( + {/* 官方四件套标尺(p5-05 落下;p5-06 连线 + 空格标注) */} +
+ {OFFICIAL.map((o) => { + const filled = o.link >= 0; + return ( +
+
+ {o.t} +
+ {filled ? ( + + + + + ) : ( +
+ {'空着 · 后面拆'} +
+ )} +
+ ); + })} +
{layers.map((l, i) => { const e = spring({frame: frame - i * 8, fps, config: {damping: 200}}); @@ -402,8 +488,8 @@ export const P5Stack: React.FC<{scene: SceneRange}> = ({scene}) => { const bD = w('p5-15', 'p5-19'); return ( - - + + diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx index aa48fe2e..63f0e7b0 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx @@ -257,7 +257,9 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}>
{'让 AI 动手的四层机制'}
- {/* 下期预告卡:读 series.json 顺序(标题只在画面,口播为话题描述——反串线纪律) */} + {/* 下期预告卡:标题只在画面(口播为话题描述——反串线纪律)。 + 标题为 series.json 派生数据的硬编码镜像,由 check_series 规则 8 + 与清单对账(改标题先改 series.json,再同步此串——规则会拦漂移)。 */}
Date: Mon, 24 Aug 2026 00:15:19 +0800 Subject: [PATCH 18/41] =?UTF-8?q?fix(video):=20EP4=20p1-11=20=E8=A1=A5?= =?UTF-8?q?=E5=9B=9E=E7=BC=BA=E5=A4=B1=E5=8A=A8=E8=AF=8D=E2=80=94=E2=80=94?= =?UTF-8?q?=E3=80=8C=E2=80=94=E2=80=94=E4=BA=86=E4=B8=AA=E5=A4=A7=E5=AE=9E?= =?UTF-8?q?=E8=AF=9D=E3=80=8D=E6=94=B9=E3=80=8C=E8=AF=B4=E4=BA=86=E5=8F=A5?= =?UTF-8?q?=E5=A4=A7=E5=AE=9E=E8=AF=9D=E3=80=8D(md+json=20=E5=90=8C?= =?UTF-8?q?=E6=AD=A5);?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../claude-code-concurrency-video/script/narration.json | 2 +- .../episodes/claude-code-concurrency-video/script/narration.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json index 0ca5c5a3..cba4fde6 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json @@ -117,7 +117,7 @@ { "id": "p1-11", "scene": "P1", - "text": "这里有个容易被想岔的点,有人拆过它的源码——了个大实话:" + "text": "这里有个容易被想岔的点,有人拆过它的源码,说了句大实话:" }, { "id": "p1-12", diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md index b66b1ab4..4d77bf54 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md @@ -43,7 +43,7 @@ - [p1-08] 意思是:这活派出去了,好了会叫你。然后循环接着转,去干下一件。 - [p1-09] 这个安排有个前提要交代:那个跑后台的活,是个「守护」的身份—— - [p1-10] 主人退场,它跟着退场。不会出现程序都关了、后台还在偷偷跑的情况。 -- [p1-11] 这里有个容易被想岔的点,有人拆过它的源码——了个大实话: +- [p1-11] 这里有个容易被想岔的点,有人拆过它的源码,说了句大实话: - [p1-12] 所谓后台,根本不是一个并行的宇宙。整套系统跑在单线程里, - [p1-13] 后台的真实含义,只是「这一步不等它了」。 - [p1-14] 等待被拿掉了,不是并发被造出来了。 From fb4ea73104051403828de0c8364379d4ef81af0b Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Mon, 24 Aug 2026 00:15:31 +0800 Subject: [PATCH 19/41] =?UTF-8?q?fix(video):=20EP2=20=E8=AF=84=E5=AE=A1?= =?UTF-8?q?=E4=B8=89=E8=A1=A5=E2=80=94=E2=80=94P0=20=E6=94=B6=E5=9B=9E?= =?UTF-8?q?=E9=92=A2=E5=8D=B0+=E4=BA=94=E6=A0=B7=E8=A3=85=E7=BD=AE?= =?UTF-8?q?=E5=88=97=E9=98=9F=E3=80=812-F=20=E4=B8=89=E5=8F=AA=E7=AC=BC?= =?UTF-8?q?=E5=AD=90=E3=80=814-E=20=E6=A3=80=E6=9F=A5=E7=82=B9=E5=8D=A1+?= =?UTF-8?q?=E9=87=91=E5=8F=A5=E9=94=9A=E6=94=B9=20p4-22(=E5=88=86=E9=95=9C?= =?UTF-8?q?=E5=90=8C=E6=AD=A5);?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../script/storyboard.md | 4 +- .../video/src/scenes/P0Hook.tsx | 116 ++++++++++++++++-- .../video/src/scenes/P2SideDesk.tsx | 57 ++++++++- .../video/src/scenes/P4Ladder.tsx | 60 +++++++-- 4 files changed, 212 insertions(+), 25 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md index 5633aade..595a47b4 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md @@ -32,7 +32,7 @@ | 2-C | p2-08..11 | 分屏:副桌上分身自己跑循环(小环转动 + 工具调用闪现);主桌只收到一张回执卡(`view`) | 副桌小环匀速转、色块在副桌堆叠不影响主桌;干完一张回执卡飞回主桌落定,副桌纸堆淡出 | | 2-D | p2-12..15 | 两条纪律:副桌工具卡阵列中「派活」卡为 `deny` 描边+锁定图标;分身动手前迷你闸门(P3 语言复用)逐次落下 | 「派活」卡打叉上锁;小闸门落下、请求过闸打点——「隔离的是视野,不是权限」 | | 2-E | p2-16..24 | ★深挖帧:两桌并置,中间一排「等号锁」——五要素卡(系统提示/工具表/模型/消息前缀/思考配置)逐张比对,全部对上后锁扣「咔」合拢、缓存印章(SAVE)砸下 | 五要素卡左右滑入逐字节对齐(每对上一张亮 `mech`);全对齐后等号锁合拢 + 印章落下的冲击波;角标「fork 继承完整对话 · 共享提示缓存 —— 官方文档 sub-agents」 | -| 2-F | p2-25..30 | 半拉隔离:副桌下方一个「读过的文件」抽屉在两桌间**共享**(虚线双桌共连);弹窗冒泡:副桌的审批卡沿虚线上浮到主桌屏幕;末句收束卡 | 抽屉盖半开、两端各画一只手同时拉开;审批卡气泡沿路径上浮;p2-29 收束句「脏活不占主桌」金句卡 | +| 2-F | p2-25..30 | 半拉隔离:副桌下方一个「读过的文件」抽屉在两桌间**共享**(虚线双桌共连);弹窗冒泡:副桌的审批卡沿虚线上浮到主桌屏幕;**三只笼子**(p2-28a..c:同时在场 ≤20 / 轮数上限 / 上下文配额烧完收工);末句收束卡 | 抽屉盖半开、两端各画一只手同时拉开;审批卡气泡沿路径上浮;三只笼子卡依次落下;p2-29 收束句「脏活不占主桌」金句卡 | ## P3 目录卡与垫纸 @@ -53,7 +53,7 @@ | 4-B | p4-03..07 | 一级梯「话没说完」:输出文本条中途断截;额度标尺 8K→64K 弹簧拉长一次;续写卡贴上断口,卡上写「别道歉,别复述,接着说」(角标注明为源码提示原文意译) | 文本条断口处闪 `deny`;标尺拉伸回弹原请求重放;三次续写计数点逐个亮,亮满即封条 | | 4-C | p4-08..10 | 二级梯「桌上太满」:整桌色块压缩成一张摘要卡,桌面清空大半;第二张摘要卡试图再压时被 `deny` 拦停 | 色块群被吸成一张卡(收缩动画);第二次压缩箭头刚起就被拦杆挡下、桌上浮「退出」 | | 4-D | p4-11..17 | 三级梯「门外施工」:桌外一枚过载/限流警示牌落下;等待条从 0.5s 起翻倍生长(0.5→1→2→4→…→32s 封顶横杠),条身带抖动毛边;三连 529 后模型名牌翻面换人 | 警示牌砸落抖动;等待条按节拍翻倍伸长、撞上 32s 封顶杠「当」一声定格;名牌翻转露出备用模型;角标「十几种恢复路径(实测 17)· 第三方的源码分析」 | -| 4-E | p4-18..22 | 收益递减:产出曲线三次爬升依次趋平,第三次的增量 < 阈值标线,系统盖「停」章;末句金句卡 | 曲线逐段绘制、斜率递减;标线横贯;「停」章(`deny`)落下;金句卡淡入 | +| 4-E | p4-18..22 | 收益递减:产出曲线三次爬升依次趋平,第三次的增量 < 阈值标线,系统盖「停」章;**检查点卡**(p4-21a/b:改动回退到检查点,只含文件改动——命令与外部状态不在其中);末句金句卡 | 曲线逐段绘制、斜率递减;标线横贯;「停」章(`deny`)落下;检查点卡自下滑入;p4-22 金句「每一级补救,都带着上限」淡入 | ## P5 桌子换了五样,环没动 diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx index d6def965..839b351e 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx @@ -5,11 +5,25 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Chip, Desk, Footnote, LoopRing, SceneTag, Terminal} from '../components/motifs'; +import {Chip, Desk, Footnote, LoopRing, SceneTag, Stamp, Terminal} from '../components/motifs'; + +/** p0-07 五样装置(0-C 列队用):顺序与口播逐字对齐。 */ +const DEVICES = [ + {t: '清单', kind: 'list'}, + {t: '副桌', kind: 'desk'}, + {t: '目录', kind: 'card'}, + {t: '垫纸', kind: 'pad'}, + {t: '补救梯', kind: 'ladder'}, +] as const; /** 0-A 系列同款终端:最初的「任务:改命名」首行逐渐被工具输出顶出可视区。 - * 行区整体上移(scrollShift),滚出瞬间残影停在顶端变 dim——「被挤走」被看见。 */ -const TaskScrollsOut: React.FC<{scrollAt: number; ghostAt: number}> = ({scrollAt, ghostAt}) => { + * 行区整体上移(scrollShift),滚出瞬间残影停在顶端变 dim——「被挤走」被看见。 + * p0-03「其中一样,刚刚被官方收回去」:右下角「收回」钢印砸下(退位悬念第一分钟埋下)。 */ +const TaskScrollsOut: React.FC<{scrollAt: number; ghostAt: number; recallAt: number}> = ({ + scrollAt, + ghostAt, + recallAt, +}) => { const frame = useCurrentFrame(); const shift = interpolate(frame - scrollAt, [0, 40], [0, 56], { extrapolateLeft: 'clamp', @@ -39,6 +53,22 @@ const TaskScrollsOut: React.FC<{scrollAt: number; ghostAt: number}> = ({scrollAt ]} />
+ {/* p0-03 收回钢印:deny 色虚影砸下,停半拍后淡出(分镜 0-A 承诺的退位悬念) */} + {frame >= recallAt ? ( +
+ +
+ ) : null} {'最初的目标句滚出可视区 —— 注意力没有「锚」'}
); @@ -141,11 +171,13 @@ const DeskFillsUp: React.FC<{fillPerFrame: number; shoveAt: number; dropAt: numb ); }; -/** 0-C 桌面定格,主线问题两行 serif 大字;环(core)第一次在桌后浮现(35% 透明)。 */ -const QuestionAndRingBehind: React.FC<{qAt: number; answerAt: number; ringAt: number}> = ({ +/** 0-C 桌面定格,主线问题两行 serif 大字;环(core)第一次在桌后浮现(35% 透明)。 + * p0-07 答句后:五样装置小图标自左向右列队点亮(清单/副桌/目录/垫纸/梯子)。 */ +const QuestionAndRingBehind: React.FC<{qAt: number; answerAt: number; ringAt: number; devicesAt: number}> = ({ qAt, answerAt, ringAt, + devicesAt, }) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); @@ -219,6 +251,69 @@ const QuestionAndRingBehind: React.FC<{qAt: number; answerAt: number; ringAt: nu > {'答案:不是。有一整套东西,在替它安排视野。'}
+ {/* p0-07 五样装置列队:清单/副桌/目录/垫纸/梯子依次点亮(分镜 0-C 承诺) */} +
+ {DEVICES.map((d, i) => { + const e = interpolate(frame - devicesAt - i * 6, [0, 10], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + return ( +
+ + + {d.kind === 'list' + ? // 清单:三行勾选 + [0, 1, 2].map((k) => ( + + + + + )) + : d.kind === 'desk' + ? // 副桌:小桌 + 旁挂一张 + (() => ( + <> + + + + + + ))() + : d.kind === 'card' + ? // 目录:一叠薄卡 + (() => ( + <> + + + + + ))() + : d.kind === 'pad' + ? // 垫纸:一张纸 + 拼装角 + (() => ( + <> + + + + ))() + : // 梯子:三级 + (() => ( + <> + + + + + + + ))()} + + +
{d.t}
+
+ ); + })} +
@@ -240,15 +335,20 @@ export const P0Hook: React.FC<{scene: SceneRange}> = ({scene}) => { {/* p0-01 钩子即上滚;p0-03「被官方收回去」:收回钢印 */} - + {/* p0-04「平铺在桌上」起色块堆高;p0-05 主线问句 */} - {/* p0-05 抛问题;p0-06 答案句 + 环在桌后描线(35% 透明);p0-07 五样装置列队 */} - + {/* p0-06 抛问题+答案句 + 环在桌后描线(35% 透明);p0-07 五样装置列队 */} + ); diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx index e4500987..d911cda8 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx @@ -596,9 +596,10 @@ const MiniDeskLabel: React.FC<{title: string; accent: string}> = ({title, accent ); /** 2-F 半拉隔离:共享抽屉 + 审批卡冒泡上浮 + 收束金句。 */ -const SharedDrawer: React.FC<{drawerAt: number; bubbleAt: number; quoteAt: number}> = ({ +const SharedDrawer: React.FC<{drawerAt: number; bubbleAt: number; cagesAt: number; quoteAt: number}> = ({ drawerAt, bubbleAt, + cagesAt, quoteAt, }) => { const frame = useCurrentFrame(); @@ -720,6 +721,49 @@ const SharedDrawer: React.FC<{drawerAt: number; bubbleAt: number; quoteAt: numbe
) : null} + {/* p2-28a..c 三只笼子:在场上限 20 / 轮数上限 / 上下文配额(Harness Engineering 改造) */} + {frame >= cagesAt ? ( +
+ {[ + {t: '同时在场', n: '≤ 20'}, + {t: '轮数上限', n: '每只有限'}, + {t: '上下文配额', n: '烧完收工'}, + ].map((c, i) => { + const e = interpolate(frame - cagesAt - i * 6, [0, 10], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + return ( +
+
{c.t}
+
{c.n}
+
+ ); + })} +
+ ) : null} {/* 虚线连线标签:桌是分开了,有些抽屉还是共用的 */}
= ({scene}) => { saveAt={relE('p2-23') + 24} /> - - {/* p2-26「有些抽屉还是共用的」抽屉拉开;p2-27 审批卡冒泡;p2-29 收束金句 */} - + + {/* p2-26「有些抽屉还是共用的」抽屉拉开;p2-27 审批卡冒泡;p2-28a 三只笼子;p2-29 收束金句 */} + ); diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx index 3d35668e..3669bc79 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx @@ -545,16 +545,18 @@ const TierThree: React.FC<{warnAt: number; waitAt: number; flipAt: number; jitte ); }; -/** 4-E 收益递减:产出曲线三次爬升依次趋平;第三次的增量 < 阈值标线;「停」章落下 + 金句。 */ -const Diminishing: React.FC<{curveAt: number; lineAt: number; stopAt: number; quoteAt: number}> = ({ - curveAt, - lineAt, - stopAt, - quoteAt, -}) => { +/** 4-E 收益递减:产出曲线三次爬升依次趋平;第三次的增量 < 阈值标线;「停」章落下; + * p4-21a/b 官方检查点回退(只看文件改动)→ 金句「每一级补救都带着上限」(Harness Engineering 改造)。 */ +const Diminishing: React.FC<{ + curveAt: number; + lineAt: number; + stopAt: number; + ckptAt: number; + quoteAt: number; +}> = ({curveAt, lineAt, stopAt, ckptAt, quoteAt}) => { const frame = useCurrentFrame(); if (frame >= quoteAt) { - return ; + return ; } const W = 1100; const H = 460; @@ -622,6 +624,36 @@ const Diminishing: React.FC<{curveAt: number; lineAt: number; stopAt: number; qu {/* 「停」章落下 */}
+ {/* p4-21a/b 官方检查点回退:改动可回退,但只含文件改动——命令与外部状态不在其中 */} + {frame >= ckptAt ? ( +
+ +
+ {'兜底后悔药:改动回退到检查点'} +
+
+ {'只含文件改动 ✓ 跑过的命令 · 改过的外部状态 ✗'} +
+
+
+ ) : null} {'连续 3 次续写无实质产出 → 直接判定停 —— 不恋战'}
); @@ -668,9 +700,15 @@ export const P4Ladder: React.FC<{scene: SceneRange}> = ({scene}) => { flipAt={relD('p4-17')} />
- - {/* p4-19 递减检测;p4-20 停;p4-21 金句 */} - + + {/* p4-19 递减检测;p4-20 停;p4-21a 检查点回退;p4-22 金句(每级都带上限) */} + ); From 651bcd66e89ed12268cf071bcb2996b1dff22e2a Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Mon, 24 Aug 2026 00:15:41 +0800 Subject: [PATCH 20/41] =?UTF-8?q?fix(video):=20EP3=20=E8=AF=84=E5=AE=A1?= =?UTF-8?q?=E8=A1=A5=E4=BB=B7=E7=9B=AE=E6=9D=A1=E2=80=94=E2=80=94PrefixCac?= =?UTF-8?q?heStrip=20=E5=A2=9E=20p4-25a/b=20=E5=91=BD=E4=B8=AD=C3=970.1?= =?UTF-8?q?=C2=B7=E5=86=99=E5=85=A5+1/4=C2=B7=E4=B8=A4=E6=AC=A1=E5=9B=9E?= =?UTF-8?q?=E6=9C=AC(=E5=88=86=E9=95=9C=E5=90=8C=E6=AD=A5);?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../script/storyboard.md | 2 +- .../video/src/scenes/P4Ledger.tsx | 38 +++++++++++++++++-- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md index 1d932774..8330bc07 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md @@ -48,7 +48,7 @@ | 4-B | p4-03..07 | ★转折帧:一张字条「缩进用 tab,别用空格」→ 摘要光束扫过 → 变成「有代码风格偏好」六字 | 字条特写;摘要光束横扫;字面逐字重写为六个字;原字条碎片飘走(细节之死) | | 4-C | p4-08..12 | **记忆两条腿**:左侧「你写的」——项目规则文件夹(四层拼接不覆盖 · 越近工作目录越后读 · 单文件四兆上限超了整份跳过 · 超两百行开始不听话);右侧「它自己写的」——用户目录下的自动记忆(按四类落卡 · 有门限);防重复印章保留 | 两条腿分立(`keep` 描边统一);左侧四条限制小字逐条浮现;右侧记忆卡逐张落;重复卡被「已有」印章退回 | | 4-D | p4-13..17 | 四类记忆四宫格:你是谁/怎么干活/在发生什么/去哪儿找,各配真实例子 | 四宫格依次亮起(`keep` 描边统一色,反枚举);各格例子逐字打入 | -| 4-E | p4-18..29 | 取的两条路:索引常驻(桌角常亮)+ 旁路小问(小模型吐回 ≤5 卡 · 拿不准的自动缩回);**前缀缓存钩**(p4-24/25):三层前缀条——系统提示/项目上下文/对话,上层一动其后全重算;「改规则要新开会话」与「中途换模型那轮慢」两个注解 | 索引页恒亮;旁路支线描线→五张卡飞回;犹豫卡缩回;p4-24 三层前缀条自下而上点亮、顶层闪烁一次引发下层全红重算动画;两个注解小卡浮出 | +| 4-E | p4-18..29 | 取的两条路:索引常驻(桌角常亮)+ 旁路小问(小模型吐回 ≤5 卡 · 拿不准的自动缩回);**前缀缓存钩**(p4-24/25):三层前缀条——系统提示/项目上下文/对话,上层一动其后全重算;「改规则要新开会话」与「中途换模型那轮慢」两个注解 + **价目条**(p4-25a/b:命中 ×0.1 · 写入 +1/4 · 两次一问就回本) | 索引页恒亮;旁路支线描线→五张卡飞回;犹豫卡缩回;p4-24 三层前缀条自下而上点亮、顶层闪烁一次引发下层全红重算动画;两个注解小卡浮出;p4-25a 价目条自下滑入 | ## P5 先抢救,再碎纸 diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx index b6251e32..dd49817e 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx @@ -534,9 +534,10 @@ const FourKinds: React.FC<{litAt: number[]}> = ({litAt}) => { }; /** 4-E 两条取路:索引常驻(桌角常亮)+ 旁路小问(≤5 卡、犹豫卡缩回、关键词降级) */ -/** 4-E 尾钩:前缀缓存三层条(Harness Engineering 改造版) - * 系统提示 → 项目上下文 → 对话;上层一动其后全重算——解释「改规则要新开会话」「中途换模型那轮慢」。 */ -const PrefixCacheStrip: React.FC<{stripAt: number}> = ({stripAt}) => { +/** 4-E 尾钩:前缀缓存三层条 + 价目(Harness Engineering 改造版) + * 系统提示 → 项目上下文 → 对话;上层一动其后全重算——解释「改规则要新开会话」「中途换模型那轮慢」; + * p4-25a/b 价目:命中一折计费 · 写入加四分之一 · 两次一问就回本——稳定放前面就是在给钱排座位。 */ +const PrefixCacheStrip: React.FC<{stripAt: number; priceAt: number}> = ({stripAt, priceAt}) => { const frame = useCurrentFrame(); const layers = [ {t: '系统提示', sub: '最稳'}, @@ -595,6 +596,35 @@ const PrefixCacheStrip: React.FC<{stripAt: number}> = ({stripAt}) => { {'改规则要新开会话 · 中途换模型那轮慢'}
) : null} + {/* p4-25a/b 价目条:命中一折 · 写入 +1/4 · 两次回本 */} + {frame >= priceAt ? ( +
+ {'价目:命中 ×0.1 · 写入 +1/4 —— 两次一问就回本'} +
+ ) : null}
); }; @@ -795,7 +825,7 @@ export const P4Ledger: React.FC<{scene: SceneRange}> = ({scene}) => { shrinkAt={relE('p4-22') + 70} degradeAt={relE('p4-24')} /> - + ); From e74ef6baf2af8ca67cf8a9eac5f9638479ec6e1e Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Mon, 24 Aug 2026 00:15:52 +0800 Subject: [PATCH 21/41] =?UTF-8?q?fix(video):=20EP4=20=E8=AF=84=E5=AE=A1?= =?UTF-8?q?=E5=9B=9B=E8=A1=A5=E2=80=94=E2=80=940-C=20=E4=B8=89=E6=97=A0?= =?UTF-8?q?=E5=B0=8F=E5=9B=BE+=E4=B8=A4=E6=AD=A5=E9=A2=84=E5=91=8A?= =?UTF-8?q?=E9=87=8D=E5=BB=BA=E3=80=813-B=20=E5=8F=8C=E8=B7=AF=E7=9B=91?= =?UTF-8?q?=E8=A7=86=E3=80=814-E=20=E4=B8=89=E6=A1=A3=E8=B0=83=E5=BA=A6?= =?UTF-8?q?=E9=87=8D=E5=BB=BA=E3=80=815-E=20=E8=87=AA=E5=AE=9A=E9=80=9F?= =?UTF-8?q?=E5=8F=91=E6=9D=A1;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../video/src/scenes/P0Wait.tsx | 188 +++++++++++------- .../video/src/scenes/P3Watchdog.tsx | 110 +++++++++- .../video/src/scenes/P4Timer.tsx | 166 ++++++++++------ .../video/src/scenes/P5Truths.tsx | 67 ++++++- 4 files changed, 387 insertions(+), 144 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx index 8a7df30c..7d6afb23 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx @@ -1,6 +1,6 @@ /** P0 十分钟干等(分镜 0-A…0-C) * 痛点:进度条慢慢爬,计费表狂转——钱在飞,活没动。洗衣机剪影离场引出 - * 「按下→走开」;三格预告三种开始(位置编码,不给三色),收在「一切停摆的房间」。 */ + * 「按下→走开」;0-C 收在时间盲症三无小图(无钟/无闹钟/无回头)+ 两步预告。 */ import React from 'react'; import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoConfig} from 'remotion'; import {theme} from '../design/theme'; @@ -315,108 +315,137 @@ const MiniStart: React.FC<{mode: 'onRing' | 'offRing' | 'noOne'; active: boolean ); }; -/** 0-C 三种开始三格预告(later 描边统一)→ 荒诞升级:一切停摆的房间 */ -const ThreeStartsRoom: React.FC<{twoAt: number; roomAt: number}> = ({twoAt, roomAt}) => { +/** 0-C 时间盲症三无小图(p0-09/10)→ 两步预告(p0-11/12,Harness Engineering 改造版)。 + * 三无:没有钟、没有闹钟、没有「回头再看」的本能(官方口径的时间盲症); + * 两步:第一步把「等」摘掉(有人按,不等了);第二步连按的人都不要(没人按,时间按)。 */ +const BlindnessAndPlan: React.FC<{blindAt: number; step1At: number; step2At: number}> = ({ + blindAt, + step1At, + step2At, +}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); - const cards = [ - {mode: 'onRing' as const, t: '有人按,并等着'}, - {mode: 'offRing' as const, t: '有人按,不等了'}, - {mode: 'noOne' as const, t: '没人按,时间按'}, + // 三无小图:钟(虚影划掉)/ 闹钟(虚影划掉)/ 回头箭头(虚影划掉) + const absents = [ + {t: '没有钟', kind: 'clock' as const}, + {t: '没有闹钟', kind: 'alarm' as const}, + {t: '没有「回头再看」', kind: 'back' as const}, ]; - const litAt = [0, 16, twoAt]; - const roomT = interpolate(frame - roomAt, [0, 22], [0, 1], { + const stepT = interpolate(frame - step1At, [0, 20], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); - // 房间里别的活:待办灯亮(later)但整行冻结;只有第一个活的时间条在走(core) - const rows = [ - {t: '读别的文件', moving: false}, - {t: '想别的问题', moving: false}, - {t: '安排别的活', moving: false}, - ]; - const barA = ((frame / fps) * 0.6) % 1; return ( -
- {cards.map((c, i) => { - const on = frame >= litAt[i]; - const e = spring({frame: frame - litAt[i], fps, config: {damping: 200}}); + {/* 三无小图(p0-09/10):deny 虚影 + 划掉的图样——「时间盲症」的视觉落点 */} +
+ {absents.map((a, i) => { + const e = spring({frame: frame - blindAt - i * 9, fps, config: {damping: 200}}); + const crossed = frame >= blindAt + 26 + i * 9; + if (e <= 0) return null; return ( -
+
-
- -
+ + {a.kind === 'clock' ? ( + <> + + + + + ) : a.kind === 'alarm' ? ( + <> + + + + + + + ) : ( + <> + + + {/* 一步向前、不回头的箭头(「没有回头」的正面表达) */} + + + )} + {/* deny 划线:它没有这能力 */} + {crossed ? ( + + ) : null} +
- {c.t} + {a.t}
); })}
- {roomT > 0 ? ( -
- -
-
{'npm install'}
-
-
+ {/* 两步预告(p0-11/12):三格开始中的后两格浮出(later 描边统一) */} +
+ +
+ = step1At} /> +
+
{'第一步'}
+
+ {'把「等」摘掉:按下就走开'}
-
{'时间条在走'}
- {rows.map((r) => ( -
-
-
{r.t}
-
-
{'冻结'}
+
+ + = step2At ? theme.later : theme.panelBorder} + style={{width: 460, padding: '14px 18px 10px', opacity: frame >= step2At ? 1 : 0.35}} + > +
+ = step2At} /> +
+
{'第二步'}
+
+ {'连按的人都不要:时间到了自己开始'}
- ))} - -
- {'一切都停着,就因为第一个活还没完'} +
-
- ) : null} - {'这一集把「等」从人身上摘走'} +
+
+ {'时间盲症 —— 没有钟 · 没有闹钟 · 没有「回头再看」'} ); }; @@ -435,8 +464,13 @@ export const P0Wait: React.FC<{scene: SceneRange}> = ({scene}) => { - - + + {/* p0-09/10 三无小图(盲症);p0-11/12 两步预告(摘等 / 没人按) */} + ); diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx index 05ddb866..b86ff0c0 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx @@ -140,12 +140,13 @@ const DogWatching: React.FC<{stopAt: number}> = ({stopAt}) => { }; /** 3-B 45 秒刻度走满 → 狗起身 + 放大镜聚焦 + 正常增长对照线一闪而过 */ -const DogRises: React.FC<{watchAt: number; riseAt: number; contrastAt: number; quoteAt: number}> = ({ - watchAt, - riseAt, - contrastAt, - quoteAt, -}) => { +const DogRises: React.FC<{ + watchAt: number; + riseAt: number; + contrastAt: number; + pathsAt: number; + quoteAt: number; +}> = ({watchAt, riseAt, contrastAt, pathsAt, quoteAt}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); // 45 秒刻度:压缩为 2.5 秒演示(视觉 45 格刻度走满) @@ -220,6 +221,100 @@ const DogRises: React.FC<{watchAt: number; riseAt: number; contrastAt: number; q
+ {/* p3-09a..c 两条看路:轮询走廊(隔段回头,空跑计费灯闪)vs 事件传送带(结果自己滚来) */} + {frame >= pathsAt ? ( +
+ {/* 走廊:问号卡往返(费字灯闪) */} + +
{'轮询走廊'}
+ + + {[110, 260, 410].map((x, i) => ( + + + + ? + + + ))} + +
+ {'每隔一段回头问一次 —— 空跑也是钱'} +
+
+ {/* 传送带:包裹自动滚到脚边 */} + +
{'事件传送带'}
+ + {Array.from({length: 26}, (_, i) => ( + + ))} + {[0, 1].map((k) => { + const bx = 20 + (((frame * 4 + k * 260) % 500) as number); + return ( + + ); + })} + +
+ {'活儿一出结果就自己滚过来 —— 不空跑,不迟到'} +
+
+
+ ) : null} {/* 正常增长的对照线:一闪而过 */} {contrast > 0 && contrast < 1 ? (
= ({scene}) => { - + diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx index a5603bb8..17cbc7e6 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx @@ -435,18 +435,33 @@ const FourLayerModel: React.FC<{dropAt: number; gateAt: number; dupAt: number}> }; /** 4-E 持久化两种(磁盘绕回重启箭头 / 内存淡出)+ 四层独立换件 */ -const TwoStorages: React.FC<{memAt: number; swapAt: number}> = ({memAt, swapAt}) => { +/** 4-E 官方三档调度(Harness Engineering 改造版):云端例程(关机也跑·不碰本地文件)/ + * 桌面定时(本机跨会话)/ 会话内循环(散场清空·只恢复没过期的)—— + * 老答案「系统定时表落盘」降为三档里的一档(虚影);解耦四层换件收尾。 */ +const ThreeTiers: React.FC<{tier1At: number; tier2At: number; tier3At: number; oldAt: number; swapAt: number}> = ({ + tier1At, + tier2At, + tier3At, + oldAt, + swapAt, +}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); - // 磁盘:文件图标 + 重启箭头绕回 - const diskO = interpolate(frame, [6, 20], [0, 1], {extrapolateRight: 'clamp'}); - const arrow = ((frame / (fps * 3)) % 1) * 360; // 环绕箭头匀速 - // 内存:会话即弃 → 淡出 - const memFade = interpolate(frame - memAt - 10, [0, 24], [1, 0.12], { + const tiers = [ + { + t: '云端例程', + s: '关机也跑 · 不碰本地文件', + icon: 'cloud', + at: tier1At, + strong: true, + }, + {t: '桌面定时', s: '本机 · 跨会话', icon: 'house', at: tier2At}, + {t: '会话内循环', s: '新对话清空 · 只恢复没过期的', icon: 'chat', at: tier3At}, + ]; + const oldFade = interpolate(frame - oldAt, [0, 18], [1, 0.3], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); - // 四层独立换件:换表/换队列/循环不动 const swap = interpolate(frame - swapAt, [0, 18], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', @@ -459,53 +474,81 @@ const TwoStorages: React.FC<{memAt: number; swapAt: number}> = ({memAt, swapAt}) ]; return ( - -
- {/* 磁盘文件:重启绕回 */} -
- - {/* 文件图标 */} - - - - {'任务定义'} - - {/* 重启绕回箭头:绕文件一圈的弧 + 箭头 */} - - - - - - {'磁盘 · 重启找得回'} - - -
- {/* 内存卡:会话即弃 → 淡出 */} -
- - - {Array.from({length: 6}, (_, i) => ( - - ))} - - {'内存 · 会话结束就消失'} - - + + {/* 三档卡片自上而下(自左而右)点亮 */} +
+ {tiers.map((tr, i) => { + const e = spring({frame: frame - tr.at, fps, config: {damping: 200}}); + if (e <= 0) return
; + return ( +
+ + + {tr.icon === 'cloud' ? ( + <> + + {/* 关机也跑:电源符嵌在云心 */} + + + + ) : tr.icon === 'house' ? ( + <> + + + {/* 桌面即本机:小钟挂在屋顶 */} + + + ) : ( + <> + + + {/* 散场即清空:气泡里一只擦除斜线 */} + + + )} + +
{tr.t}
+
{tr.s}
+
+
+ ); + })} +
+ {/* 老答案降级:系统定时表落盘 → 虚影(现在只是三档里的一档) */} +
+
+ {'老答案:系统定时表落盘 —— 现在只是三档里的一档'}
{/* 四层独立换件 */} @@ -529,7 +572,9 @@ const TwoStorages: React.FC<{memAt: number; swapAt: number}> = ({memAt, swapAt})
))}
- {'看表的不干活,干活的不看表 —— 生产和消费解耦'} + + {'三档调度(云端例程 / 桌面定时 / 会话内)—— 官方文档 scheduled-tasks'} + ); }; @@ -565,8 +610,15 @@ export const P4Timer: React.FC<{scene: SceneRange}> = ({scene}) => { dupAt={at('p4-12') - bD.from} /> - - + + {/* p4-19 云端例程;p4-20 桌面定时+会话内;p4-21 老答案降级;p4-24 解耦收尾 */} + ); diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx index 22bf9b40..66ed90ab 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx @@ -417,7 +417,8 @@ const SupervisorFrame: React.FC<{supAt: number; statesAt: number; persistAt: num }; /** 5-E 上限 50/50 + 低优先级标记排队尾 + 金句卡 */ -const CapAndQuote: React.FC<{lowAt: number; quoteAt: number}> = ({lowAt, quoteAt}) => { +/** 5-E 上限与低优先级 + 自定速发条(p5-23a/b:干完一轮顺手定下一次,间隔自己定)。 */ +const CapAndQuote: React.FC<{lowAt: number; windAt: number; quoteAt: number}> = ({lowAt, windAt, quoteAt}) => { const frame = useCurrentFrame(); if (frame >= quoteAt) { return ( @@ -483,6 +484,62 @@ const CapAndQuote: React.FC<{lowAt: number; quoteAt: number}> = ({lowAt, quoteAt
+ {/* p5-23a/b 自定速发条:干完一轮 → 顺手拨出下一格(间隔自己定,不靠墙上的钟) */} + {frame >= windAt ? ( +
+
+ + {/* 发条旋钮:自转一圈、拨出一格 */} + + {Array.from({length: 8}, (_, i) => { + const a = ((i * 45 + (frame / 2.2) * 45) * Math.PI) / 180; + return ( + + ); + })} + + +
+
+ {'干完一轮,顺手定下一次 —— 间隔自己定'} +
+
+ {'不靠墙上的钟,靠它自己的一句「回头再来」'} +
+
+
+
+ ) : null} {'上限与低优先级标记 —— 第三方的源码分析'} ); @@ -518,8 +575,12 @@ export const P5Truths: React.FC<{scene: SceneRange}> = ({scene}) => { p5-15 口播接续解释(镜内画面与镜间口播的刻意交叠) */} - - + + ); From 7e4c1d00d7135f4ee227f67fd0088a2956049f88 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Mon, 24 Aug 2026 00:16:02 +0800 Subject: [PATCH 22/41] =?UTF-8?q?fix(video):=20EP5/EP1=20=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E4=B8=89=E8=A1=A5=E2=80=94=E2=80=946-D=20=E5=85=AD?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E9=80=89=E4=BA=8C+resume=20=E9=87=8D?= =?UTF-8?q?=E6=94=BE=E3=80=816-E=20=E9=9B=B6=E4=BB=B6=E5=9B=9B=E8=BF=9E+?= =?UTF-8?q?=E5=8D=81=E4=BA=94=E5=80=8D=E6=9D=A1=E5=85=88=E8=A1=8C=E3=80=81?= =?UTF-8?q?EP1=20=E8=BA=AB=E4=BB=BD=E5=8D=A1=E5=88=A0=E6=97=A7=E5=89=AF?= =?UTF-8?q?=E9=A2=98=E6=AE=8B=E7=89=87;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../video/src/scenes/P6Ending.tsx | 3 - .../video/src/scenes/P6Finale.tsx | 235 +++++++++++++++++- 2 files changed, 223 insertions(+), 15 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx index 63f0e7b0..5b883481 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx @@ -254,9 +254,6 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> > {'执行层:一个循环,就是全部'}
-
- {'让 AI 动手的四层机制'} -
{/* 下期预告卡:标题只在画面(口播为话题描述——反串线纪律)。 标题为 series.json 派生数据的硬编码镜像,由 check_series 规则 8 与清单对账(改标题先改 series.json,再同步此串——规则会拦漂移)。 */} diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx index 800a90db..08abe064 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx @@ -397,13 +397,17 @@ const SeriesFinale: React.FC<{riseAt: number; quoteAt: number}> = ({riseAt, quot /** 6-D ★谁持有计划:四象对比(Harness Engineering 收官纲图) * 官方 workflows 的四方对比——临时工/技能包/队友:计划由模型逐回合现场决定; * 第四种(动态工作流):脚本持有计划,中间结果住变量、上下文只装最终答案。 + * p6-11a/b 六模式选二(扇出汇总 / 对抗核验);p6-11c/d resume 重放 + * (干完的秒亮 / 没干完的重跑 / 其后启动的全部重跑)。 * 分水岭竖线落下是全片思想高点;收官反转「Harness 第一次由它自己来写」。 */ -const WhoHoldsPlan: React.FC<{gridAt: number; divideAt: number; runtimeAt: number; twistAt: number}> = ({ - gridAt, - divideAt, - runtimeAt, - twistAt, -}) => { +const WhoHoldsPlan: React.FC<{ + gridAt: number; + divideAt: number; + runtimeAt: number; + modesAt: number; + resumeAt: number; + twistAt: number; +}> = ({gridAt, divideAt, runtimeAt, modesAt, resumeAt, twistAt}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); const cols = [ @@ -542,6 +546,132 @@ const WhoHoldsPlan: React.FC<{gridAt: number; divideAt: number; runtimeAt: numbe ))}
) : null} + {/* p6-11a/b 六模式选二:扇出汇总 / 对抗核验(两张小卡浮在四象图上方) */} + {frame >= modesAt && frame < resumeAt ? ( +
+ {/* 扇出→汇总漏斗 */} +
+ + {[0, 1, 2].map((k) => ( + + ))} + + + +
+
{'扇出 → 汇总'}
+
+ {'一批活各自干完,合成一份'} +
+
+
+ {/* 对抗核验:挑刺→改到合格 */} +
+ + + + 干 + + + 挑刺 + + + + +
+
{'干完 → 挑刺 → 改'}
+
+ {'改到合格才算完'} +
+
+
+
+ ) : null} + {/* p6-11c/d resume 重放:A 干完秒亮(绿)/ B 没干完重跑(黄)/ C、D 其后启动全部重跑(对勾抹掉) */} + {frame >= resumeAt && twist <= 0 ? ( +
+
+ {'中断重放:'} +
+ {[ + {t: 'A · 已干完', fate: '秒亮', ok: true}, + {t: 'B · 没干完', fate: '从头重跑', warn: true}, + {t: 'C · 其后启动', fate: '全部重跑', fail: true}, + {t: 'D · 其后启动', fate: '全部重跑', fail: true}, + ].map((r, i) => { + const e = interpolate(frame - resumeAt - 4 - i * 5, [0, 8], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const c = r.ok ? theme.ok : r.warn ? theme.peer : theme.deny; + return ( +
+
{r.t}
+
{r.fate}
+
+ ); + })} +
+ ) : null} {/* 收官反转 */} {twist > 0 ? (
- {'四形态对比与并发护栏 —— 官方文档 workflows'} + {'四形态对比·六模式选二·resume 重放 —— 官方文档 workflows'} ); }; -const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> = ({ +const SourceAndFade: React.FC<{beatDurationInFrames: number; partsAt: number; costAt: number; seriesAt: number}> = ({ beatDurationInFrames, + partsAt, + costAt, seriesAt, }) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); - const enter = spring({frame: frame - 4, fps, config: {damping: 200}}); + // p6-12 零件四连小图(板/箱/号/桌)与 p6-13/14 十五倍对比条先于信源卡(分镜 6-E 承诺) + const partsT = interpolate(frame - partsAt, [0, 18], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const costT = interpolate(frame - costAt, [0, 18], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const preludeGone = interpolate(frame - (seriesAt - 26), [0, 20], [1, 0], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const enter = spring({frame: frame - (seriesAt - 22), fps, config: {damping: 200}}); const rows = [ ['官方文档', 'code.claude.com/docs · 取数2026年8月'], ['工程博客', 'anthropic.com/engineering'], @@ -591,6 +736,65 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> }); return ( + {/* p6-12 零件四连小图 + p6-13/14 官方冷水(十五倍)——信源卡之前的收束段 */} + {preludeGone > 0.01 ? ( +
+
+ {[ + {t: '板子', d: 'M14 10 h36 v26 h-36 Z M22 42 v8 M42 42 v8'}, + {t: '信箱', d: 'M12 14 h40 v26 h-40 Z M12 22 h40 M44 22 v6 a4 4 0 0 1 -8 0 v-6'}, + {t: '编号', d: 'M10 16 h44 v24 h-44 Z M10 24 h44 M10 32 h44 M20 16 v24'}, + {t: '桌子', d: 'M10 20 h48 M14 20 v24 M54 20 v24 M28 30 h12 v8 h-12 Z'}, + ].map((p, i) => ( +
+ + + +
{p.t}
+
+ ))} +
+ {/* 十五倍对比条:普通对话 1× vs 多智能体 15× */} + {costT > 0 ? ( +
+
+ + {'普通对话'} + +
+ {'1×'} +
+
+ + {'多智能体'} + +
+ {'≈15×'} +
+
+ {'并行和专精,必须挣回它们的协调成本 —— 官方工程博客'} +
+
+ ) : null} +
+ ) : null}
@@ -706,12 +910,19 @@ export const P6Finale: React.FC<{scene: SceneRange}> = ({scene}) => { gridAt={rel(bD, 'p6-07')} divideAt={rel(bD, 'p6-08')} runtimeAt={rel(bD, 'p6-10')} + modesAt={rel(bD, 'p6-11a')} + resumeAt={rel(bD, 'p6-11c')} twistAt={rel(bD, 'p6-11')} /> - - {/* 渐黑窗口从**本 beat 总时长**推导,不是末句时长(红线四) */} - + + {/* p6-12 零件四连;p6-13/14 十五倍对比条;p6-15 起信源卡;渐黑窗口从本 beat 总时长推导(红线四) */} + ); From 4350f6390765b2c2da9a737ac6b1f7e8b1f79781 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Mon, 24 Aug 2026 14:33:55 +0800 Subject: [PATCH 23/41] =?UTF-8?q?fix(video):=20EP5=20=E8=AF=84=E5=AE=A1?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=B8=80=E2=80=94=E2=80=946-D=20resume=20?= =?UTF-8?q?=E6=AD=BB=E9=97=A8=E6=94=B9=E6=8D=A2=E9=A1=B5=E6=97=B6=E5=BA=8F?= =?UTF-8?q?+=E5=88=86=E6=B0=B4=E5=B2=AD=E7=AB=96=E7=BA=BF=E7=A7=BB?= =?UTF-8?q?=E5=85=A5=E5=88=97=E9=97=B4=E9=9A=99=E3=80=812-E=20=E8=A1=A5?= =?UTF-8?q?=E5=90=8D=E5=86=8C/=E5=AF=B9=E6=AF=94=E5=8D=A1=E4=B8=A4?= =?UTF-8?q?=E9=A1=B5(=E5=88=86=E9=95=9C=E5=90=8C=E6=AD=A5);?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 6-D 底部条带改三段互斥换页(三分区→六模式→resume),原 `frame >= resumeAt && twist <= 0` 因 twistAt 绑 p6-11 早于 p6-11c 恒假,resume 卡从未渲染 - 分水岭竖线 CX 由列布局推导(1239→画布 1319 列间隙中心),原 960 压在「队友」卡身上; 线高 420→370 避开条带辉光 - 2-E ThreeProhibitions 增中景两页:p2-23a/b 名册卡(成员+信箱、会话结束划行清空+虚线框)、 p2-24a/b 信箱一段文字 vs 整段上下文对比卡——消除后缀四句约 24 秒零视觉支持 - 分镜 2-E 行同步两页描述;remotion still 六帧复检(p2-23a/23b/24b、p6-11b/11c/11d) 全部到位无重叠;内容门/系列门 FAIL 0 🤖 Generated with [Claude Code](https://github.com/claude.com), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../script/storyboard.md | 2 +- .../video/src/scenes/P2Mail.tsx | 168 ++++++++++++++++-- .../video/src/scenes/P6Finale.tsx | 63 ++++--- 3 files changed, 201 insertions(+), 32 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md index d3954f14..677b7907 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md @@ -31,7 +31,7 @@ | 2-B | p2-06..11 | ★信箱行:每位成员门口一个信箱文件;消息行(一行字)飞入对方文件;读取即划掉(一行淡出) | 消息行沿弧线飞入;打开文件时光扫过、被读行划掉;角标「写文件带锁(防串行)」 | | 2-C | p2-12..14 | 十五种消息类型小样墙(统一 panel 底编号,反枚举):汇报/请示/审批/关机/广播…… | 类型卡快速铺开;全部退远缩成「往文件里加一行带类型的字」一行字 | | 2-D | p2-15..19 | ★权限冒泡:队友的审批卡从下沿虚线上浮到领队屏幕弹出(带队友名字与颜色);点头后回执下落 | 审批卡沿路径上浮(浮起涟漪);你的光标点头动画;回执回落到队友信箱 | -| 2-E | p2-20..25 | **三禁止章**:一条 A→B 消息到达前被「来自另一个会话——不是你的用户」标签盖灰;三枚 deny 红章依次盖下(不能替你批权限 / 不能代你同意 / 被拒动作不能转给别人);不许孵队友铁律 + 保险丝收尾 | 消息卡飞行被来源标签截停盖灰;三红章逐枚盖下(章落带缩放震);「队伍生队伍」混乱链一闪即碎;末句保险丝横幅(mech) | +| 2-E | p2-20..25 | **三禁止章**:一条 A→B 消息到达前被「来自另一个会话——不是你的用户」标签盖灰;三枚 deny 红章依次盖下(不能替你批权限 / 不能代你同意 / 被拒动作不能转给别人);**名册卡**(p2-23a/b:用户目录团队文件夹的 roster 文件·成员+信箱,会话结束自动清掉);**消息 vs 上下文**(p2-24a/b:信箱一段文字 vs 整段上下文·须恢复会话);不许孵队友铁律 + 保险丝收尾 | 消息卡飞行被来源标签截停盖灰;三红章逐枚盖下(章落带缩放震);中景换页:签字栏→名册卡(成员行划掉+边框转虚线+「自动清掉」小标)→信箱/上下文对比卡(信箱管传话,整段上下文搬不过去);末句保险丝横幅(mech) | ## P3 怎么谈判:握手 diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx index d59abd69..8840d1dc 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx @@ -535,13 +535,19 @@ const BubbleUp: React.FC<{riseAt: number; nodAt: number; downAt: number}> = ({ri /** 2-E 三禁止章:队友消息不构成用户同意(Harness Engineering 改造版,官方直断) * 一条 A→B 消息到达前被「来自另一个会话——不是你的用户」来源标签盖灰; - * 三枚 deny 红章依次盖下;末段不许孵队友 + 保险丝横幅保留。 */ -const ThreeProhibitions: React.FC<{msgAt: number; stampAt: number; noSubAt: number; bannerAt: number}> = ({ - msgAt, - stampAt, - noSubAt, - bannerAt, -}) => { + * 三枚 deny 红章依次盖下;末段不许孵队友 + 保险丝横幅保留。 + * 红章之下的中景舞台随口播换页(评审修复:后缀四句原本零视觉支持): + * p2-23a/b 名册文件卡(用户目录团队文件夹·成员+信箱;会话结束自动清掉); + * p2-24a/b 信箱 vs 上下文对比(信箱管传话一行字;整段上下文须恢复会话)。 */ +const ThreeProhibitions: React.FC<{ + msgAt: number; + stampAt: number; + noSubAt: number; + bannerAt: number; + rosterAt: number; + clearAt: number; + textAt: number; +}> = ({msgAt, stampAt, noSubAt, bannerAt, rosterAt, clearAt, textAt}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); const msg = interpolate(frame - msgAt, [0, 20], [0, 1], { @@ -557,6 +563,29 @@ const ThreeProhibitions: React.FC<{msgAt: number; stampAt: number; noSubAt: numb extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); + // 名册卡:rosterAt 落下;textAt(对比卡登场)淡出让位。签字栏句同理在 + // rosterAt 淡出——中景一次只演一层,与 6-D 底部条带同款换页语法。 + const noSubOut = interpolate(frame - rosterAt, [0, 12], [1, 0], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const rosterIn = interpolate(frame - rosterAt, [0, 14], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const rosterOut = interpolate(frame - textAt, [0, 12], [1, 0], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 名册清空:成员行划掉、边框转虚线、盖「自动清掉」小标(p2-23b 口播内) + const cleared = interpolate(frame - clearAt, [0, 16], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const textIn = interpolate(frame - textAt, [0, 14], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); // 消息卡飞行进度(A → B,中途被截停) const travel = interpolate(frame - msgAt, [0, 36], [0, 1], { extrapolateLeft: 'clamp', @@ -642,8 +671,8 @@ const ThreeProhibitions: React.FC<{msgAt: number; stampAt: number; noSubAt: numb
); })} - {/* 签字栏画面(组队不是权限洗白) */} - {noSub > 0 ? ( + {/* 签字栏画面(组队不是权限洗白)——名册卡登场时让位 */} + {noSub > 0 && noSubOut > 0.01 ? (
) : null} + {/* p2-23a/b 名册卡:用户目录的团队文件夹里的 roster 文件;会话结束自动清掉 */} + {rosterIn > 0 && rosterOut > 0.01 ? ( +
0.5 ? theme.panelBorder : theme.peer}`, + borderStyle: cleared > 0.5 ? 'dashed' : 'solid', + borderRadius: 12, + background: theme.panel, + padding: '14px 20px', + }} + > +
+ {'~/.claude/teams/roster.json'} +
+ {/* 成员行:领队 + 两队友,每人一只信箱(信箱与 2-B 母题同构) */} + {[ + {n: '领队', box: 'mailbox: 领队'}, + {n: '阿强', box: 'mailbox: 阿强'}, + {n: '阿珍', box: 'mailbox: 阿珍'}, + ].map((m, i) => { + const gone = Math.max(0, Math.min(1, cleared * 1.6 - i * 0.3)); + return ( +
0.4 ? 'line-through' : 'none', + }} + > + {m.n} + {m.box} +
+ ); + })} + {cleared > 0 ? ( +
+ {'会话结束 · 名册自动清掉——队伍是临时的,桌子才是留下的'} +
+ ) : null} +
+ ) : null} + {/* p2-24a/b 消息 vs 上下文:信箱管传话(一行字),整段上下文须恢复会话 */} + {textIn > 0 ? ( +
+ {/* 信箱:只装一段文字 */} +
+ + + + +
+ {'一段文字'} +
+
{'信箱管传话'}
+
+ {/* 传不过去的:整段上下文 */} + + + + {'搬不过去'} + + + {/* 上下文:须恢复会话 */} +
+ + {[0, 1, 2, 3].map((k) => ( + + + + + ))} + +
+ {'整段上下文'} +
+
+ {'要搬它,得恢复会话'} +
+
+
+ ) : null} {/* 不许孵队友 + 保险丝横幅 */} {banner > 0 ? (
= ({scene}) => { stampAt={rel(bE, 'p2-21')} noSubAt={rel(bE, 'p2-22')} bannerAt={rel(bE, 'p2-23')} + rosterAt={rel(bE, 'p2-23a')} + clearAt={rel(bE, 'p2-23b')} + textAt={rel(bE, 'p2-24a')} /> diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx index 08abe064..bedd695a 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx @@ -397,8 +397,8 @@ const SeriesFinale: React.FC<{riseAt: number; quoteAt: number}> = ({riseAt, quot /** 6-D ★谁持有计划:四象对比(Harness Engineering 收官纲图) * 官方 workflows 的四方对比——临时工/技能包/队友:计划由模型逐回合现场决定; * 第四种(动态工作流):脚本持有计划,中间结果住变量、上下文只装最终答案。 - * p6-11a/b 六模式选二(扇出汇总 / 对抗核验);p6-11c/d resume 重放 - * (干完的秒亮 / 没干完的重跑 / 其后启动的全部重跑)。 + * 底部条带三段轮换:运行时三分区(p6-09/10)→ 六模式选二(p6-11a/b)→ + * resume 重放(p6-11c/d,干完的秒亮 / 没干完的重跑 / 其后启动的全部重跑)。 * 分水岭竖线落下是全片思想高点;收官反转「Harness 第一次由它自己来写」。 */ const WhoHoldsPlan: React.FC<{ gridAt: number; @@ -425,7 +425,30 @@ const WhoHoldsPlan: React.FC<{ extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); - const CX = 960; + // 底部条带三段互斥轮换:三分区 →(modesAt) 六模式 →(resumeAt) resume 重放。 + // 原实现模式卡浮 top:66 压住四象卡头、resume 卡被 `twist <= 0` 锁死——twistAt + // 绑 p6-11,在音频顺序上早于 p6-11c,门恒假(评审修复:改为同条带换页)。 + const runtimeOut = interpolate(frame - modesAt, [0, 10], [1, 0], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const modesIn = interpolate(frame - modesAt, [0, 10], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const modesOut = interpolate(frame - resumeAt, [-10, 0], [1, 0], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const resumeIn = interpolate(frame - resumeAt, [0, 12], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 分水岭竖线落点:三四列间隙中心。列行 4×340 + 3×18 居中于 1760 容器, + // 第 3/4 列间隙中心 = (1760-1412)/2 + 3×358 - 9 = 1239(画布 x≈1319)—— + // 此前误取画布中心 960,线压在「队友」卡身上(评审修复:由列布局推导)。 + const COLS_W = 340 * 4 + 18 * 3; + const CX = (1760 - COLS_W) / 2 + 3 * (340 + 18) - 18 / 2; return (
@@ -480,7 +503,8 @@ const WhoHoldsPlan: React.FC<{ ); })}
- {/* 分水岭竖线:三四列之间落下 */} + {/* 分水岭竖线:三四列之间落下(终点收在底部条带上方——resume 卡 + (y≈506 起)入场时不与线尾辉光相撞,评审补渲实测 420 会擦到卡角) */} {divide > 0 ? (
) : null} - {/* 运行时三分区一行(缩略) */} - {runtime > 0 ? ( + {/* 运行时三分区一行(缩略)——modesAt 起换页让位给六模式卡 */} + {runtime > 0 && runtimeOut > 0.01 ? (
@@ -546,21 +570,19 @@ const WhoHoldsPlan: React.FC<{ ))}
) : null} - {/* p6-11a/b 六模式选二:扇出汇总 / 对抗核验(两张小卡浮在四象图上方) */} - {frame >= modesAt && frame < resumeAt ? ( + {/* p6-11a/b 六模式选二:扇出汇总 / 对抗核验(底部条带第二页;resumeAt 起换页) */} + {modesIn > 0 && modesOut > 0.01 ? (
{/* 扇出→汇总漏斗 */} @@ -621,8 +643,10 @@ const WhoHoldsPlan: React.FC<{
) : null} - {/* p6-11c/d resume 重放:A 干完秒亮(绿)/ B 没干完重跑(黄)/ C、D 其后启动全部重跑(对勾抹掉) */} - {frame >= resumeAt && twist <= 0 ? ( + {/* p6-11c/d resume 重放:A 干完秒亮(绿)/ B 没干完重跑(黄)/ C、D 其后启动全部重跑(对勾抹掉)。 + 此前门 `frame >= resumeAt && twist <= 0` 恒假(twistAt 绑 p6-11 早于 p6-11c, + 评审修复:换页进入、不再依赖 twist 退出——反转金句卡在 6-D 末尾叠印不冲突) */} + {resumeIn > 0 ? (
From 992833c88219714216186e3a94c1ae0312a79725 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Mon, 24 Aug 2026 14:34:19 +0800 Subject: [PATCH 24/41] =?UTF-8?q?docs(video):=20=E8=AF=84=E5=AE=A1?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=8C=E2=80=94=E2=80=94series.md=20?= =?UTF-8?q?=E5=8F=A5=E6=95=B0=E5=9F=BA=E7=BA=BF=E5=AF=B9=E9=BD=90=20status?= =?UTF-8?q?Note(135/139/134)=E3=80=81CHANGELOG/EP5=20statusNote=20?= =?UTF-8?q?=E6=A0=87=E6=B3=A8=E7=9B=AE=E6=A3=80=E5=8F=A3=E5=BE=84=E4=B8=8E?= =?UTF-8?q?=E8=AF=84=E5=AE=A1=E4=BF=AE=E5=A4=8D=E8=AE=B0=E5=BD=95;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - series.md EP2 134→135、EP3 140→139、EP5 133→134(与 series.json statusNote 同源) - CHANGELOG「逐帧目检通过」补口径标注(08-23 草渲版)并记录 08-24 评审补 六处图解的 still 复检结论与 EP5 两处评审 bug 修复 - EP5 statusNote 同步评审修复条目 🤖 Generated with [Claude Code](https://github.com/claude.com), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- CHANGELOG.md | 2 +- apps/negentropy-influence/series.json | 2 +- apps/negentropy-influence/series.md | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5cbc786..2416391b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ 本文件遵循 [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;16 个高风险新图解帧(命名帧/六闸流水线/谁持有计划四象/三禁止章/worktree 四道闸/管家进程/存活矩阵/两条腿/前缀缓存条/三相环/31 事件嵌套/auto 视野分屏/裸名 deny/五辐条/三症状卡/下期卡)逐帧目检通过——无重叠、无字幕带侵入、无文字侧倒。配音:716 句基线缓存迁移命中 + 改写句全部重配(sunny-steady + me-bright 不变,两次补配共 ~180 句)。 +- **五集草渲交付(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` 全零待合成)。 diff --git a/apps/negentropy-influence/series.json b/apps/negentropy-influence/series.json index 844d1435..ecd6405d 100644 --- a/apps/negentropy-influence/series.json +++ b/apps/negentropy-influence/series.json @@ -190,7 +190,7 @@ "accessed": "2026-08-22" }, "status": "draft-review", - "statusNote": "Harness Engineering 改造草渲待审:13:08 = 23666 帧 @30fps(134 句);七幕 FAIL 0 · WARN 0(尾帧 WARN 1 为收束卡刻意停留);终渲未启动", + "statusNote": "Harness Engineering 改造草渲待审:13:08 = 23666 帧 @30fps(134 句);七幕 FAIL 0 · WARN 0(尾帧 WARN 1 为收束卡刻意停留;口径为 08-23 草渲版)——08-24 评审修复 6-D resume 死门+分水岭压卡、2-E 补名册/对比卡两页,remotion still 逐帧复检通过;终渲未启动", "voice": "sunny-steady + me-bright.wav" } ] diff --git a/apps/negentropy-influence/series.md b/apps/negentropy-influence/series.md index 17a54175..c07aae04 100644 --- a/apps/negentropy-influence/series.md +++ b/apps/negentropy-influence/series.md @@ -30,10 +30,10 @@ | # | 作品 | 一句话主题 | 视觉契约(主色) | 信源 | 状态 | |---|---|---|---|---|---| | 1 | [《执行层:一个循环,就是全部》](./episodes/claude-code-explained-video/README.md) | 工具与执行:把模型装进Harness | 陶土橙/石青/警示红 | [Learn Claude Code](https://learn.shareai.run/zh/s01/) s01–s04 + 仓库 @ `f9e8b28`(MIT),2026-08 | **Harness Engineering 改造中**(配音缓存 170/170 迁移命中;改造草渲后交付) | -| 2 | [《规划层:模型的视野是安排出来的》](./episodes/claude-code-planning-video/README.md) | 规划与协调:谁替它安排视野 | 鸢紫 `view`(底座陶土橙/石青全系列共享) | s05–s07 · s10 · s11 @ 站点同源修订 `67a9126c`(MIT) | **Harness Engineering 改造中**(134 句基线;改造草渲后交付) | -| 3 | [《记忆层:会丢的和不能丢的》](./episodes/claude-code-memory-video/README.md) | 记忆管理:窗口内外的两本账 | 苔绿 `keep` | s08 · s09 @ `67a9126c`(MIT) | **Harness Engineering 改造中**(140 句基线;改造草渲后交付) | +| 2 | [《规划层:模型的视野是安排出来的》](./episodes/claude-code-planning-video/README.md) | 规划与协调:谁替它安排视野 | 鸢紫 `view`(底座陶土橙/石青全系列共享) | s05–s07 · s10 · s11 @ 站点同源修订 `67a9126c`(MIT) | **Harness Engineering 改造中**(135 句基线;改造草渲后交付) | +| 3 | [《记忆层:会丢的和不能丢的》](./episodes/claude-code-memory-video/README.md) | 记忆管理:窗口内外的两本账 | 苔绿 `keep` | s08 · s09 @ `67a9126c`(MIT) | **Harness Engineering 改造中**(139 句基线;改造草渲后交付) | | 4 | [《时机层:谁来按下开始》](./episodes/claude-code-concurrency-video/README.md) | 并发与调度:谁替它看表 | 霜蓝 `later` | s13 · s14 @ `67a9126c`(MIT) | **Harness Engineering 改造中**(139 句基线;改造草渲后交付) | -| 5 | [《协作层:从一个到一群》](./episodes/claude-code-multiagent-video/README.md) | 多 Agent 协作:谁持有计划 | 赭金 `peer` | s12 · s15–s20 @ `67a9126c`(MIT) | **Harness Engineering 改造中**(133 句基线;改造草渲后交付) | +| 5 | [《协作层:从一个到一群》](./episodes/claude-code-multiagent-video/README.md) | 多 Agent 协作:谁持有计划 | 赭金 `peer` | s12 · s15–s20 @ `67a9126c`(MIT) | **Harness Engineering 改造中**(134 句基线;改造草渲后交付) | > 章节→集归属与**站点/仓库修订分叉**(站点为 20 章旧修订、仓库 main 已整合为 17 章,故双钉): > 系列级登记见 [source-map/claude-code-explained.md](./source-map/claude-code-explained.md)。 From 6be7a1ed3a97f2ca85386e4718e8b33850fb5dea Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Fri, 28 Aug 2026 05:07:24 +0800 Subject: [PATCH 25/41] =?UTF-8?q?fix(video):=20=E5=93=81=E6=8E=A7=E4=B8=80?= =?UTF-8?q?=E5=AE=A1=E4=BF=AE=E5=A4=8D=E2=80=94=E2=80=94=E4=B8=89=E5=A4=84?= =?UTF-8?q?=E6=88=90=E7=89=87=E7=BA=A7=E7=A1=AC=E4=BC=A4=20+=20=E5=85=A8?= =?UTF-8?q?=E7=89=87=E9=A1=B6=E5=B8=A6=E9=97=B2=E7=BD=AE=E6=A0=B9=E6=B2=BB?= =?UTF-8?q?;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 对抗式评审(七维度)一审发现 + 三路独立取证坐实: - EP2 p2-12/14 悬空「第二条」:补回对仗(「纪律第一条」)。 - EP4 p5-13「第三个真话」本体缺失:补回「把进程关了,表就停了」——官方新答案才有转折对象。 - EP3 0-C 真空屏(像素实测 0.00% ink,47s 处约 10 秒):DeleteSins 入场锚 p0-11/12 前移 至 p0-09/11。 - 全片性构图缺陷根治:3×3 宫格抽样实测顶带 ink 仅 0.4–2.0%(SceneTag 覆盖率仅 7–59% 是根因)——新增幕级常驻 SceneHeader 组件(motifs.tsx seeded 档),五集 35 幕全部挂载, 左=幕序幕名、右=机制英文名;实测顶带 ink 提升 2–5 倍。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../script/narration.md | 4 +- .../video/src/components/motifs.tsx | 58 +++++++++++++++++++ .../video/src/scenes/P0Wait.tsx | 3 +- .../video/src/scenes/P1Dereg.tsx | 3 +- .../video/src/scenes/P2Rejoin.tsx | 10 +--- .../video/src/scenes/P3Watchdog.tsx | 3 +- .../video/src/scenes/P4Timer.tsx | 9 +-- .../video/src/scenes/P5Truths.tsx | 3 +- .../video/src/scenes/P6Ending.tsx | 3 +- .../video/src/components/motifs.tsx | 58 +++++++++++++++++++ .../video/src/scenes/P0Hook.tsx | 3 +- .../video/src/scenes/P1Loop.tsx | 11 +--- .../video/src/scenes/P2Dispatch.tsx | 13 +---- .../video/src/scenes/P3Gates.tsx | 12 +--- .../video/src/scenes/P4Hooks.tsx | 14 +---- .../video/src/scenes/P5Stack.tsx | 3 +- .../video/src/scenes/P6Ending.tsx | 3 +- .../video/src/components/motifs.tsx | 58 +++++++++++++++++++ .../video/src/scenes/P0Reject.tsx | 5 +- .../video/src/scenes/P1Desk.tsx | 3 +- .../video/src/scenes/P2Tidy.tsx | 3 +- .../video/src/scenes/P3Helper.tsx | 3 +- .../video/src/scenes/P4Ledger.tsx | 3 +- .../video/src/scenes/P5Hinge.tsx | 3 +- .../video/src/scenes/P6Ending.tsx | 3 +- .../video/src/components/motifs.tsx | 58 +++++++++++++++++++ .../video/src/scenes/P0Hook.tsx | 3 +- .../video/src/scenes/P1Board.tsx | 3 +- .../video/src/scenes/P2Mail.tsx | 13 +---- .../video/src/scenes/P3Handshake.tsx | 3 +- .../video/src/scenes/P4Autonomy.tsx | 3 +- .../video/src/scenes/P5Desks.tsx | 3 +- .../video/src/scenes/P6Finale.tsx | 3 +- .../script/narration.md | 2 +- .../video/src/components/motifs.tsx | 58 +++++++++++++++++++ .../video/src/scenes/P0Hook.tsx | 3 +- .../video/src/scenes/P1Plan.tsx | 3 +- .../video/src/scenes/P2SideDesk.tsx | 3 +- .../video/src/scenes/P3Manual.tsx | 3 +- .../video/src/scenes/P4Ladder.tsx | 3 +- .../video/src/scenes/P5Ring.tsx | 3 +- .../video/src/scenes/P6Ending.tsx | 3 +- 42 files changed, 364 insertions(+), 100 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md index 4d77bf54..26590093 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md @@ -158,8 +158,8 @@ - [p5-10] 提前量也是算好的。跟整点人流反着走。 - [p5-11] 第二个真话:定时任务会自动退休。连续七天没动静的周期任务, - [p5-12] 到期自动删掉,删之前还会最后跑一次。忘了设的闹钟,不该响一辈子。 -- [p5-13] 第三个真话最实在,也是最容易踩坑的: -- [p5-14] 但官方给了新答案:后台会话由一个独立的管家进程托管。 +- [p5-13] 第三个真话最实在,也最容易踩坑:把进程关了,表就停了。 +- [p5-14] 但官方给了新答案:后台会话由独立的管家进程托管,不怕终端关掉。 - [p5-15] 不需要任何终端活着;状态落盘,穿过自动更新与重启,睡眠唤醒会重连。 - [p5-16] 管家给每个会话记账:六种状态,排队、跑着、等审批、被拦、收尾、完事。 - [p5-17] 行摘要也是一个小模型顺带写的——省着主模型的上下文。 diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/components/motifs.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/components/motifs.tsx index 1d73cb1e..05a2e1c1 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/components/motifs.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/components/motifs.tsx @@ -92,6 +92,64 @@ export const SceneTag: React.FC<{ ); }; +/** 幕级常驻抬头带(2026-08 品控改造)——修复「顶部 1/3 全片闲置」的构图缺陷。 + * + * 实测动机:五集 3×3 宫格抽样显示顶带 ink 仅 0.4–2.0%,而 SceneTag 的 + * Sequence 覆盖率只有 7–59%。本组件由**幕**(而非镜)挂载一次,全幕常驻, + * 一次性补齐顶部信息层:左=幕序与幕名,右=本幕机制英文名(角标层,不进口播)。 + * + * 纪律:只读底座 token 与传入的 accent;不参与句锚动画(避免与镜内动效抢注意力), + * 仅在幕首 12 帧淡入;高度锁死 ≤96px,不侵占镜内主体区。 */ +export const SceneHeader: React.FC<{ + index: string; + title: string; + meta?: string; + accent?: string; +}> = ({index, title, meta, accent}) => { + const frame = useCurrentFrame(); + const o = interpolate(frame, [0, 12], [0, 1], {extrapolateRight: 'clamp'}); + const c = accent ?? theme.core; + return ( +
+
+ + {index} + + + {title} + +
+ {meta ? ( + + {meta} + + ) : null} +
+ ); +}; + /** 数字滚动计数器(帧驱动,无随机) */ export const Counter: React.FC<{ from: number; diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx index 7d6afb23..8b1323ac 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, Panel, SceneTag, Terminal} from '../components/motifs'; +import {Footnote, Panel, SceneHeader, SceneTag, Terminal} from '../components/motifs'; /** 计费表:表盘 + 一根按帧匀速狂转的秒针(转速恒快,与进度条形成反差) */ const MeterDial: React.FC<{spinFrom: number}> = ({spinFrom}) => { @@ -458,6 +458,7 @@ export const P0Wait: React.FC<{scene: SceneRange}> = ({scene}) => { const bC = w('p0-09', 'p0-13'); return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P1Dereg.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P1Dereg.tsx index 4af7e99c..d7e28ba7 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P1Dereg.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P1Dereg.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame} from 'remo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, LoopRing, Panel, SceneTag, useRingDot} from '../components/motifs'; +import {Footnote, LoopRing, Panel, SceneHeader, SceneTag, useRingDot} from '../components/motifs'; /** 环外旁轨的几何常数:与 LoopRing 同心、半径外扩(本幕内推导基线,P2 自带几何) */ const TRACK_R = 340; @@ -372,6 +372,7 @@ export const P1Dereg: React.FC<{scene: SceneRange}> = ({scene}) => { const bD = w('p1-16', 'p1-24'); return ( + = ({lockAt, swapAt, queueAt}) => { @@ -400,6 +393,7 @@ export const P2Rejoin: React.FC<{scene: SceneRange}> = ({scene}) => { const bE = w('p2-16', 'p2-23'); return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx index b86ff0c0..96fdf1c2 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, useCurrentFrame, useVideoConfig} fr import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, Panel, SceneTag} from '../components/motifs'; +import {Footnote, Panel, SceneHeader, SceneTag} from '../components/motifs'; /** 后台命令输出线:逐字爬行,随后停在一个 (y/n) 提示上闪烁等待 */ const OutputLine: React.FC<{stopAt: number; focusAt: number}> = ({stopAt, focusAt}) => { @@ -360,6 +360,7 @@ export const P3Watchdog: React.FC<{scene: SceneRange}> = ({scene}) => { const bB = w('p3-04', 'p3-09c'); return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx index 17cbc7e6..4244749e 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx @@ -6,13 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import { - Footnote, - LoopRing, - Panel, - SceneTag, - useRingDot, -} from '../components/motifs'; +import {Footnote, LoopRing, Panel, SceneHeader, SceneTag, useRingDot} from '../components/motifs'; /** 4-A 提线木偶(你说一句它动一下)vs 闹钟自摆(自己响) */ const PuppetVsClock: React.FC<{clockAt: number}> = ({clockAt}) => { @@ -589,6 +583,7 @@ export const P4Timer: React.FC<{scene: SceneRange}> = ({scene}) => { const bE = w('p4-19', 'p4-27'); return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx index 66ed90ab..8906cb35 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx @@ -7,7 +7,7 @@ import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; import {QuoteCard} from '../components/cards'; -import {Footnote, Panel, SceneTag} from '../components/motifs'; +import {Footnote, Panel, SceneHeader, SceneTag} from '../components/motifs'; /** 迷你钟面:时针/分针可指定角度,可选表盘描边色 */ const MiniClock: React.FC<{ @@ -555,6 +555,7 @@ export const P5Truths: React.FC<{scene: SceneRange}> = ({scene}) => { const bE = w('p5-19', 'p5-23b'); return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx index 5cca4bd3..34260c39 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, LoopRing, Panel, SceneTag, useRingDot} from '../components/motifs'; +import {Footnote, LoopRing, Panel, SceneHeader, SceneTag, useRingDot} from '../components/motifs'; /** 三段位置图的一段:人(或表)与环的位置关系——「谁按的开始」用位置编码 */ const StartPanel: React.FC<{ @@ -332,6 +332,7 @@ export const P6Ending: React.FC<{scene: SceneRange}> = ({scene}) => { const bC = w('p6-13', 'p6-15'); return ( + = ({chapter, ); }; +/** 幕级常驻抬头带(2026-08 品控改造)——修复「顶部 1/3 全片闲置」的构图缺陷。 + * + * 实测动机:五集 3×3 宫格抽样显示顶带 ink 仅 0.4–2.0%,而 SceneTag 的 + * Sequence 覆盖率只有 7–59%。本组件由**幕**(而非镜)挂载一次,全幕常驻, + * 一次性补齐顶部信息层:左=幕序与幕名,右=本幕机制英文名(角标层,不进口播)。 + * + * 纪律:只读底座 token 与传入的 accent;不参与句锚动画(避免与镜内动效抢注意力), + * 仅在幕首 12 帧淡入;高度锁死 ≤96px,不侵占镜内主体区。 */ +export const SceneHeader: React.FC<{ + index: string; + title: string; + meta?: string; + accent?: string; +}> = ({index, title, meta, accent}) => { + const frame = useCurrentFrame(); + const o = interpolate(frame, [0, 12], [0, 1], {extrapolateRight: 'clamp'}); + const c = accent ?? theme.core; + return ( +
+
+ + {index} + + + {title} + +
+ {meta ? ( + + {meta} + + ) : null} +
+ ); +}; + /** 数字滚动计数器(帧驱动,无随机) */ export const Counter: React.FC<{ from: number; diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx index 403d98c0..eadb50e0 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, Panel, Terminal} from '../components/motifs'; +import {Footnote, Panel, SceneHeader, Terminal} from '../components/motifs'; /** 0-A 终端打字 → 命令凝住 → 复制粘贴弧线加速塞满(两句内完成旧版六句的信息量) */ const StallAndCarry: React.FC<{carryAt: number}> = ({carryAt}) => { @@ -366,6 +366,7 @@ export const P0Hook: React.FC<{scene: SceneRange}> = ({scene}) => { const bC = w('p0-06', 'p0-07'); return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx index 9dede254..607929ea 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx @@ -6,15 +6,7 @@ import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; import {QuoteCard} from '../components/cards'; -import { - CodeCard, - Counter, - Footnote, - LoopRing, - Panel, - SceneTag, - useRingDot, -} from '../components/motifs'; +import {CodeCard, Counter, Footnote, LoopRing, Panel, SceneHeader, SceneTag, useRingDot} from '../components/motifs'; /** 1-A 环形循环成形 + 两个信号分支 */ const RingBirth: React.FC<{yesAt: number; noAt: number}> = ({yesAt, noAt}) => { @@ -540,6 +532,7 @@ export const P1Loop: React.FC<{scene: SceneRange}> = ({scene}) => { const rF = (id: string) => w(id).from - bF.from; return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx index ac2db9f4..a7fde84d 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx @@ -6,17 +6,7 @@ import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; import {QuoteCard} from '../components/cards'; -import { - CodeCard, - DispatchTable, - Footnote, - LoopRing, - NumberedCard, - Panel, - SceneTag, - Terminal, - useRingDot, -} from '../components/motifs'; +import {CodeCard, DispatchTable, Footnote, LoopRing, NumberedCard, Panel, SceneHeader, SceneTag, Terminal, useRingDot} from '../components/motifs'; /** 环留在左上角:缩小但同色同线宽 */ const CornerRing: React.FC<{pulse?: boolean}> = ({pulse = false}) => { @@ -573,6 +563,7 @@ export const P2Dispatch: React.FC<{scene: SceneRange}> = ({scene}) => { const rel = (b: {from: number}, id: string) => w(id).from - b.from; return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx index 7169694d..ab1ac897 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx @@ -6,16 +6,7 @@ import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; import {QuoteCard} from '../components/cards'; -import { - CodeCard, - Footnote, - GateRouter, - LoopRing, - NumberedCard, - Panel, - SceneTag, - useRingDot, -} from '../components/motifs'; +import {CodeCard, Footnote, GateRouter, LoopRing, NumberedCard, Panel, SceneHeader, SceneTag, useRingDot} from '../components/motifs'; /** 3-A 五张工具卡,跑命令那张在「工作目录」框外 */ const UnguardedShell: React.FC<{frameAt: number; cmdAt: number; execAt: number}> = ({ @@ -699,6 +690,7 @@ export const P3Gates: React.FC<{scene: SceneRange}> = ({scene}) => { const bG = w('p3-30', 'p3-35'); return ( + = ({scene}) => { const bH = w('p4-35', 'p4-37'); return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P5Stack.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P5Stack.tsx index 27d72dd1..17de716d 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P5Stack.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P5Stack.tsx @@ -8,7 +8,7 @@ import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; import {QuoteCard} from '../components/cards'; -import {Footnote, LoopRing, Panel, Terminal, useRingDot} from '../components/motifs'; +import {Footnote, LoopRing, Panel, SceneHeader, Terminal, useRingDot} from '../components/motifs'; const CHAPTERS = [ {name: '一个循环', total: 141, loop: 23}, @@ -488,6 +488,7 @@ export const P5Stack: React.FC<{scene: SceneRange}> = ({scene}) => { const bD = w('p5-15', 'p5-19'); return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx index 5b883481..3a36a8e6 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx @@ -7,7 +7,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {LoopRing, Panel, useRingDot} from '../components/motifs'; +import {LoopRing, Panel, SceneHeader, useRingDot} from '../components/motifs'; /** 6-A 壳的四层:三张挂件卡沿径向滑入、逐一「咬合」上环(骨架 vs 挂件的物理化收束)。 * 循环层不用卡——它就是环本身(p6-03 的口播顺序:循环→分发表→闸门→插口)。 @@ -288,6 +288,7 @@ export const P6Ending: React.FC<{scene: SceneRange}> = ({scene}) => { const bB = w('p6-05', 'p6-08'); return ( + = ({index, title, meta, accent}) => { + const frame = useCurrentFrame(); + const o = interpolate(frame, [0, 12], [0, 1], {extrapolateRight: 'clamp'}); + const c = accent ?? theme.core; + return ( +
+
+ + {index} + + + {title} + +
+ {meta ? ( + + {meta} + + ) : null} +
+ ); +}; + /** 数字滚动计数器(帧驱动,无随机) */ export const Counter: React.FC<{ from: number; diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx index 3a1bbe15..b9e59636 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, Panel, PaperCard, Terminal} from '../components/motifs'; +import {Footnote, Panel, PaperCard, SceneHeader, Terminal} from '../components/motifs'; /** 0-A 系列终端:命令链滚动 → 一行 deny 报错砸落(画面压暗一档、光标停闪) */ const ErrorSlam: React.FC<{errAt: number}> = ({errAt}) => { @@ -428,6 +428,7 @@ export const P0Reject: React.FC<{scene: SceneRange}> = ({scene}) => { const relD = (id: string) => at(id) - bD.from; return ( + @@ -438,7 +439,7 @@ export const P0Reject: React.FC<{scene: SceneRange}> = ({scene}) => { />
- + = ({ruleAt}) => { @@ -361,6 +361,7 @@ export const P1Desk: React.FC<{scene: SceneRange}> = ({scene}) => { const relC = (id: string) => at(id) - bC.from; return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P2Tidy.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P2Tidy.tsx index 563e74c1..349c26f3 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P2Tidy.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P2Tidy.tsx @@ -8,7 +8,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Cabinet, Desk, Footnote, HelperFigure, PaperCard} from '../components/motifs'; +import {Cabinet, Desk, Footnote, HelperFigure, PaperCard, SceneHeader} from '../components/motifs'; /** 2-A 大件入库:五个大块拍上桌 → 排队弧线飞入文件柜 → 预览卡弹回落位 */ const VaultBig: React.FC<{dropAt: number; flyAt: number; previewAt: number}> = ({ @@ -646,6 +646,7 @@ export const P2Tidy: React.FC<{scene: SceneRange}> = ({scene}) => { const relD = (id: string) => at(id) - bD.from; return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx index 1d945a10..3e75131b 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx @@ -7,7 +7,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Cabinet, Desk, Footnote, HelperFigure, Panel, PaperCard} from '../components/motifs'; +import {Cabinet, Desk, Footnote, HelperFigure, Panel, PaperCard, SceneHeader} from '../components/motifs'; /** 3-A 帮工特写:指令卡首(top 指令)尾(bottom 叮嘱)各弹一次 + 工具之手两次被挡 */ const HelperDiscipline: React.FC<{firstAt: number; lastAt: number; handAt: number[]}> = ({ @@ -474,6 +474,7 @@ export const P3Helper: React.FC<{scene: SceneRange}> = ({scene}) => { const relC = (id: string) => at(id) - bC.from; return ( + = ({fadeAt}) => { @@ -788,6 +788,7 @@ export const P4Ledger: React.FC<{scene: SceneRange}> = ({scene}) => { const relE = (id: string) => at(id) - bE.from; return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P5Hinge.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P5Hinge.tsx index a176f828..9d4959df 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P5Hinge.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P5Hinge.tsx @@ -11,7 +11,7 @@ import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; import {QuoteCard} from '../components/cards'; -import {Footnote, Ledger, LoopRing, Panel, useRingDot} from '../components/motifs'; +import {Footnote, Ledger, LoopRing, Panel, SceneHeader, useRingDot} from '../components/motifs'; /** 5-A ★时间铰链:双时间线并行 + 中缝环照转。 * 左线:从完整对话快照抄走 tab 字条 → keep 登记簿(先完成); @@ -747,6 +747,7 @@ export const P5Hinge: React.FC<{scene: SceneRange}> = ({scene}) => { const relE = (id: string) => at(id) - bE.from; return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx index 165b2443..feb2db10 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx @@ -8,7 +8,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Panel} from '../components/motifs'; +import {Panel, SceneHeader} from '../components/motifs'; /** 6-A 一句话合同:keep 描边金句卡 + 两行对仗回收 */ const OneLineContract: React.FC<{recycleAt: number}> = ({recycleAt}) => { @@ -192,6 +192,7 @@ export const P6Ending: React.FC<{scene: SceneRange}> = ({scene}) => { const relB = (id: string) => at(id) - bB.from; return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/components/motifs.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/components/motifs.tsx index a6998e82..445ee45b 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/components/motifs.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/components/motifs.tsx @@ -94,6 +94,64 @@ export const SceneTag: React.FC<{ ); }; +/** 幕级常驻抬头带(2026-08 品控改造)——修复「顶部 1/3 全片闲置」的构图缺陷。 + * + * 实测动机:五集 3×3 宫格抽样显示顶带 ink 仅 0.4–2.0%,而 SceneTag 的 + * Sequence 覆盖率只有 7–59%。本组件由**幕**(而非镜)挂载一次,全幕常驻, + * 一次性补齐顶部信息层:左=幕序与幕名,右=本幕机制英文名(角标层,不进口播)。 + * + * 纪律:只读底座 token 与传入的 accent;不参与句锚动画(避免与镜内动效抢注意力), + * 仅在幕首 12 帧淡入;高度锁死 ≤96px,不侵占镜内主体区。 */ +export const SceneHeader: React.FC<{ + index: string; + title: string; + meta?: string; + accent?: string; +}> = ({index, title, meta, accent}) => { + const frame = useCurrentFrame(); + const o = interpolate(frame, [0, 12], [0, 1], {extrapolateRight: 'clamp'}); + const c = accent ?? theme.core; + return ( +
+
+ + {index} + + + {title} + +
+ {meta ? ( + + {meta} + + ) : null} +
+ ); +}; + /** 数字滚动计数器(帧驱动,无随机) */ export const Counter: React.FC<{ from: number; diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx index 3625c2bc..9f757b51 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, LoopRing, Panel, SceneTag, useRingDot} from '../components/motifs'; +import {Footnote, LoopRing, Panel, SceneHeader, SceneTag, useRingDot} from '../components/motifs'; /** 0-A 终端任务清单溢出 → 拉镜:孤环悬在四个模块群中央,注意力只覆盖一小块 */ const OverflowThenZoom: React.FC<{zoomAt: number; cardsAt?: number}> = ({zoomAt, cardsAt}) => { @@ -444,6 +444,7 @@ export const P0Hook: React.FC<{scene: SceneRange}> = ({scene}) => { const bC = w('p0-09', 'p0-10'); return ( + {/* 拉镜点在 p0-03;cardsAt:官方三失败模式症状卡(Harness Engineering 改造) */} diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx index 26e15ec4..97521ea9 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, Panel, phase, qBezier, SceneTag} from '../components/motifs'; +import {Footnote, Panel, SceneHeader, SceneTag, phase, qBezier} from '../components/motifs'; /** 任务卡:五格(编号/标题/状态/主人/等谁);TaskBoard 的成员单元 */ const TaskCard: React.FC<{ @@ -738,6 +738,7 @@ export const P1Board: React.FC<{scene: SceneRange}> = ({scene}) => { const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx index 8840d1dc..f3bd213d 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx @@ -6,17 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import { - Footnote, - LoopRing, - NamePlate, - NumberedCard, - Panel, - phase, - qBezier, - SceneTag, - useRingDot, -} from '../components/motifs'; +import {Footnote, LoopRing, NamePlate, NumberedCard, Panel, SceneHeader, SceneTag, phase, qBezier, useRingDot} from '../components/motifs'; /** 0-A 临时工 vs 队友:左剪影淡出、右 peer 小环落位打铭牌 */ const TempVsTeammate: React.FC<{fadeAt: number; seatAt: number}> = ({fadeAt, seatAt}) => { @@ -842,6 +832,7 @@ export const P2Mail: React.FC<{scene: SceneRange}> = ({scene}) => { const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx index d5dee884..43dfedf4 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, LoopRing, NamePlate, Panel, phase, SceneTag, useRingDot} from '../components/motifs'; +import {Footnote, LoopRing, NamePlate, Panel, SceneHeader, SceneTag, phase, useRingDot} from '../components/motifs'; /** 握手轨:横向轨道 + 请求卡 / 应答卡对开。双方端点 + 中央「等回话」位。 */ const HandshakeRail: React.FC<{ @@ -722,6 +722,7 @@ export const P3Handshake: React.FC<{scene: SceneRange}> = ({scene}) => { const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx index d17bf24b..79387444 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, LoopRing, NamePlate, Panel, phase, SceneTag} from '../components/motifs'; +import {Footnote, LoopRing, NamePlate, Panel, SceneHeader, SceneTag, phase} from '../components/motifs'; /** 4-A 派工之累 ×10 快闪 → 三段生命周期环描线登场 */ const DispatchFatigue: React.FC<{cycleAt: number}> = ({cycleAt}) => { @@ -706,6 +706,7 @@ export const P4Autonomy: React.FC<{scene: SceneRange}> = ({scene}) => { const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx index 79e5469c..92295ca8 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, LoopRing, NamePlate, Panel, phase, SceneTag} from '../components/motifs'; +import {Footnote, LoopRing, NamePlate, Panel, SceneHeader, SceneTag, phase} from '../components/motifs'; /** 5-A 阿珍阿强双写冲突:同名 config.py 互覆碎裂 + 回滚死结 */ const Collision: React.FC<{writeAt: number; crushAt: number; knotAt: number}> = ({ @@ -829,6 +829,7 @@ export const P5Desks: React.FC<{scene: SceneRange}> = ({scene}) => { const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( + = ({scene}) => { const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( + diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md index 5a625c18..f6689ee0 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md @@ -63,7 +63,7 @@ - [p2-09] 主桌上你看不到那三十个文件的任何一行,只看得见它带回的一张回执。 - [p2-10] 干完,只把最后那条结论带回主桌。中间过程全部丢掉。 - [p2-11] 注意丢的是什么:写过的文件、改过的代码都还在硬盘上——丢的只是纸,不是活。 -- [p2-12] 教学版的纪律是分身不许再派分身;官方后来放开了——最多三层,同时二十个。 +- [p2-12] 纪律第一条:教学版不许分身再派分身;官方放开了——最多三层,同时二十个。 - [p2-14] 第二条:分身每次动手之前,照样要过那几道闸门。 - [p2-15] 隔离的是视野,不是权限。它看不见你俩的对话,但它一样不能为所欲为。 - [p2-16] 官方文档后来证实了真实产品里的那个反转, diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/components/motifs.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/components/motifs.tsx index 967e7b52..f79eea7b 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/components/motifs.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/components/motifs.tsx @@ -94,6 +94,64 @@ export const SceneTag: React.FC<{ ); }; +/** 幕级常驻抬头带(2026-08 品控改造)——修复「顶部 1/3 全片闲置」的构图缺陷。 + * + * 实测动机:五集 3×3 宫格抽样显示顶带 ink 仅 0.4–2.0%,而 SceneTag 的 + * Sequence 覆盖率只有 7–59%。本组件由**幕**(而非镜)挂载一次,全幕常驻, + * 一次性补齐顶部信息层:左=幕序与幕名,右=本幕机制英文名(角标层,不进口播)。 + * + * 纪律:只读底座 token 与传入的 accent;不参与句锚动画(避免与镜内动效抢注意力), + * 仅在幕首 12 帧淡入;高度锁死 ≤96px,不侵占镜内主体区。 */ +export const SceneHeader: React.FC<{ + index: string; + title: string; + meta?: string; + accent?: string; +}> = ({index, title, meta, accent}) => { + const frame = useCurrentFrame(); + const o = interpolate(frame, [0, 12], [0, 1], {extrapolateRight: 'clamp'}); + const c = accent ?? theme.core; + return ( +
+
+ + {index} + + + {title} + +
+ {meta ? ( + + {meta} + + ) : null} +
+ ); +}; + /** 数字滚动计数器(帧驱动,无随机) */ export const Counter: React.FC<{ from: number; diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx index 839b351e..9e3773a0 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx @@ -5,7 +5,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Chip, Desk, Footnote, LoopRing, SceneTag, Stamp, Terminal} from '../components/motifs'; +import {Chip, Desk, Footnote, LoopRing, SceneHeader, SceneTag, Stamp, Terminal} from '../components/motifs'; /** p0-07 五样装置(0-C 列队用):顺序与口播逐字对齐。 */ const DEVICES = [ @@ -333,6 +333,7 @@ export const P0Hook: React.FC<{scene: SceneRange}> = ({scene}) => { const relC = (id: string) => at(id) - bC.from; return ( + {/* p0-01 钩子即上滚;p0-03「被官方收回去」:收回钢印 */} diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx index f1861d92..46deec15 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx @@ -6,7 +6,7 @@ import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; import {QuoteCard} from '../components/cards'; -import {Chip, CodeCard, Desk, Footnote, Panel, SceneTag, Stamp} from '../components/motifs'; +import {Chip, CodeCard, Desk, Footnote, Panel, SceneHeader, SceneTag, Stamp} from '../components/motifs'; /** 三态行:空格 → ▸ → ✓ 各一次演示态(storyboard 1-A)。 */ const STATE_ICONS = [' ', '▸', '✓'] as const; @@ -395,6 +395,7 @@ export const P1Plan: React.FC<{scene: SceneRange}> = ({scene}) => { const relD = (id: string) => at(id) - bD.from; return ( + {/* 三态图标演示态跟随 p1-02(每条标一个状态)逐个闪现 */} diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx index d911cda8..c0f26659 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx @@ -7,7 +7,7 @@ import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; import {QuoteCard} from '../components/cards'; -import {Chip, Counter, Desk, Footnote, LoopRing, Panel, SceneTag, Stamp, useRingDot} from '../components/motifs'; +import {Chip, Counter, Desk, Footnote, LoopRing, Panel, SceneHeader, SceneTag, Stamp, useRingDot} from '../components/motifs'; /** 2-A 桌面色块暴涨成灾:一百多条记录填满桌面;计费计数器持续跳字。 */ const DeskFlood: React.FC<{floodAt: number; billAt: number}> = ({floodAt, billAt}) => { @@ -805,6 +805,7 @@ export const P2SideDesk: React.FC<{scene: SceneRange}> = ({scene}) => { const relF = (id: string) => at(id) - bF.from; return ( + {/* p2-03「一百多条」起暴涨;p2-04「一直计着费」起计数器 */} diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx index 67c6ddda..eb3981e1 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Counter, Desk, Footnote, Panel, SceneTag, Stamp} from '../components/motifs'; +import {Counter, Desk, Footnote, Panel, SceneHeader, SceneTag, Stamp} from '../components/motifs'; /** 3-A 左:桌角薄目录卡叠(每张一行 ~100);右:整块厚手册拍上桌(~2000+),桌面被压得下沉。 */ const ThickManualSlams: React.FC<{slamAt: number}> = ({slamAt}) => { @@ -723,6 +723,7 @@ export const P3Manual: React.FC<{scene: SceneRange}> = ({scene}) => { const relF = (id: string) => at(id) - bF.from; return ( + {/* p3-02「全贴进基本设定」手册拍上桌;p3-03 计价器跳红 */} diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx index 3669bc79..bf05f539 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx @@ -7,7 +7,7 @@ import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; import {QuoteCard} from '../components/cards'; -import {Chip, Desk, Footnote, Panel, SceneTag, Stamp} from '../components/motifs'; +import {Chip, Desk, Footnote, Panel, SceneHeader, SceneTag, Stamp} from '../components/motifs'; /** 梯子骨架(mech):三级木梯挂在桌右缘,自上垂下挂稳(rope 微弹)。 */ const Ladder: React.FC<{drop: number; labels?: [string, string, string]}> = ({drop, labels}) => { @@ -674,6 +674,7 @@ export const P4Ladder: React.FC<{scene: SceneRange}> = ({scene}) => { const relE = (id: string) => at(id) - bE.from; return ( + {/* p4-01「管的是意外」桌子亮出;p4-02 岔子预告,梯子自上垂下挂稳 */} diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P5Ring.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P5Ring.tsx index 72894768..b6e231c4 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P5Ring.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P5Ring.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Desk, Footnote, LoopRing, Panel, SceneTag, Stamp, useRingDot} from '../components/motifs'; +import {Desk, Footnote, LoopRing, Panel, SceneHeader, SceneTag, Stamp, useRingDot} from '../components/motifs'; /** 五样装置(编号即桌面位置——反枚举:不给五色)。 * 装置缩略图统一 panel 底 + 编号;职责字以印章形式落下。 */ @@ -277,6 +277,7 @@ export const P5Ring: React.FC<{scene: SceneRange}> = ({scene}) => { const relC = (id: string) => at(id) - bC.from; return ( + {/* p5-02 五样摆在一起:自左向右滑入;p5-04..05 职责印章逐枚落下 */} = ({nextAt}) => { @@ -184,6 +184,7 @@ export const P6Ending: React.FC<{scene: SceneRange}> = ({scene}) => { const bB = w('p6-05', 'p6-09'); return ( + {/* p6-04「同一门手艺」次行浮现 */} From b1859edcd1512f1e131b61f692ac45aea0f3cfa7 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Fri, 28 Aug 2026 16:22:12 +0800 Subject: [PATCH 26/41] =?UTF-8?q?fix(video):=20=E5=93=81=E6=8E=A7=20B=20?= =?UTF-8?q?=E6=96=B9=E6=A1=88=E2=80=94=E2=80=948=20=E6=9D=A1=E8=A7=86?= =?UTF-8?q?=E8=A7=89=20blocker=20=E5=85=A8=E4=BF=AE=EF=BC=88=E5=90=AB=20Fo?= =?UTF-8?q?otnote=20=E5=8F=A0=E5=8D=B0=E6=A0=B9=E6=B2=BB=EF=BC=89;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 对抗式评审(158 agents / 85 findings → 73 送核验 → 57 存活 / 39 双票)的视觉类双票项: - **Footnote 单例叠印根治**:motifs.tsx 加 slot?: 0|1(slot=1 抬到 bottom:206)—— 同一 Sequence 并列两组件各带一条 Footnote 时会在 168 完全重印成糊字(实拍坐实)。五集同步。 - EP5 5-B:FourGates Footnote 改 slot=1;四闸横排上移 bottom:268、卡宽 300→262(原压住 repo 底座只剩「rep」);🔒 emoji → ● 绘制符号(emoji 全彩字形击穿三色契约)。 - EP5 0-A:SymptomCards 与孤环几何中心重合、三卡钉穿环腰 → 下移 bottom:226、卡宽 320、 入场推迟到拉镜完成后(zoomAt+40)。 - EP3 4-E:PrefixCacheStrip 与 TwoPaths 的 Footnote 同处 bottom:168 → 抬到 250。 - EP4 2-D:labelAt 锚 p2-16 在 beat(p2-13..15) 窗口外,恒不触发(30 字标签动画从未出现) → 改锚 p2-15,lightAt 提前到 p2-13。 - EP4 6-A:SceneTag chapter="None" 占位符被渲染成 mono 大字挂在终幕 → "Who Starts"。 - EP4 0-B:官方引文条 bottom:190 与 Footnote 168 过近 → 抬到 262。 - EP2 2-E:50.7 秒 beat 的首个视觉锚落在第 7 句,前 34 秒只有静态标签 + 五个孤立「≠」 → 「≠」纳入 opacity 门控 + 补前段三拍(p2-19 计价条 / p2-20 前缀转红原价重算 / p2-21 原样搬回绿命中)。 五集 tsc --noEmit 零错误。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) --- .../video/src/components/motifs.tsx | 7 ++- .../video/src/scenes/P0Wait.tsx | 2 +- .../video/src/scenes/P2Rejoin.tsx | 2 +- .../video/src/scenes/P6Ending.tsx | 2 +- .../video/src/components/motifs.tsx | 7 ++- .../video/src/components/motifs.tsx | 7 ++- .../video/src/scenes/P4Ledger.tsx | 2 +- .../video/src/components/motifs.tsx | 7 ++- .../video/src/scenes/P0Hook.tsx | 9 +-- .../video/src/scenes/P5Desks.tsx | 9 +-- .../video/src/components/motifs.tsx | 7 ++- .../video/src/scenes/P2SideDesk.tsx | 57 +++++++++++++++++-- 12 files changed, 90 insertions(+), 28 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/components/motifs.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/components/motifs.tsx index 05a2e1c1..bbda8472 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/components/motifs.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/components/motifs.tsx @@ -36,9 +36,10 @@ export const Panel: React.FC<{ ); /** 底部角标——统一压在 bottom ≥ 150(避让字幕条,skills/06 红线二) */ -export const Footnote: React.FC<{children: React.ReactNode; delay?: number}> = ({ +export const Footnote: React.FC<{children: React.ReactNode; delay?: number; slot?: 0 | 1}> = ({ children, delay = 0, + slot = 0, }) => { const frame = useCurrentFrame(); const o = interpolate(frame - delay, [0, 14], [0, 1], { @@ -51,7 +52,9 @@ export const Footnote: React.FC<{children: React.ReactNode; delay?: number}> = ( position: 'absolute', left: 0, right: 0, - bottom: 168, + // slot:同一 Sequence 里并列两个组件各带一条 Footnote 时,两条会在 + // bottom:168 完全重印成一团糊字(2026-08 品控实拍坐实)。slot=1 抬到 206 错行。 + bottom: slot === 1 ? 206 : 168, textAlign: 'center', fontFamily: theme.mono, fontSize: 24, diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx index 8b1323ac..0115e928 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx @@ -211,7 +211,7 @@ const LaundryLeave: React.FC<{turnAt: number; ringAt: number; quoteAt?: number}> style={{ position: 'absolute', left: '50%', - bottom: 190, + bottom: 262, transform: `translateX(-50%) translateY(${interpolate(frame - quoteAt, [0, 16], [14, 0], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx index 49a637a3..cf4999f8 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx @@ -404,7 +404,7 @@ export const P2Rejoin: React.FC<{scene: SceneRange}> = ({scene}) => { - + diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx index 34260c39..23e828a8 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx @@ -120,7 +120,7 @@ const ThreePositions: React.FC<{l1: number; l2: number; l3: number; layerAt: num }); return ( - +
= l1} /> diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/components/motifs.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/components/motifs.tsx index 020fce85..7cecb2ee 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/components/motifs.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/components/motifs.tsx @@ -42,9 +42,10 @@ export const Panel: React.FC<{ ); /** 底部角标——统一压在 bottom ≥ 150(避让字幕条,skills/06 红线二) */ -export const Footnote: React.FC<{children: React.ReactNode; delay?: number}> = ({ +export const Footnote: React.FC<{children: React.ReactNode; delay?: number; slot?: 0 | 1}> = ({ children, delay = 0, + slot = 0, }) => { const frame = useCurrentFrame(); const o = interpolate(frame - delay, [0, 14], [0, 1], { @@ -57,7 +58,9 @@ export const Footnote: React.FC<{children: React.ReactNode; delay?: number}> = ( position: 'absolute', left: 0, right: 0, - bottom: 168, + // slot:同一 Sequence 里并列两个组件各带一条 Footnote 时,两条会在 + // bottom:168 完全重印成一团糊字(2026-08 品控实拍坐实)。slot=1 抬到 206 错行。 + bottom: slot === 1 ? 206 : 168, textAlign: 'center', fontFamily: theme.mono, fontSize: 24, diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/components/motifs.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/components/motifs.tsx index df590ba4..deb2023b 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/components/motifs.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/components/motifs.tsx @@ -38,9 +38,10 @@ export const Panel: React.FC<{ ); /** 底部角标——统一压在 bottom ≥ 150(避让字幕条,skills/06 红线二) */ -export const Footnote: React.FC<{children: React.ReactNode; delay?: number}> = ({ +export const Footnote: React.FC<{children: React.ReactNode; delay?: number; slot?: 0 | 1}> = ({ children, delay = 0, + slot = 0, }) => { const frame = useCurrentFrame(); const o = interpolate(frame - delay, [0, 14], [0, 1], { @@ -53,7 +54,9 @@ export const Footnote: React.FC<{children: React.ReactNode; delay?: number}> = ( position: 'absolute', left: 0, right: 0, - bottom: 168, + // slot:同一 Sequence 里并列两个组件各带一条 Footnote 时,两条会在 + // bottom:168 完全重印成一团糊字(2026-08 品控实拍坐实)。slot=1 抬到 206 错行。 + bottom: slot === 1 ? 206 : 168, textAlign: 'center', fontFamily: theme.mono, fontSize: 24, diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx index f5d14367..ea87c3be 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx @@ -556,7 +556,7 @@ const PrefixCacheStrip: React.FC<{stripAt: number; priceAt: number}> = ({stripAt style={{ position: 'absolute', left: '50%', - bottom: 168, + bottom: 250, transform: `translateX(-50%) translateY(${(1 - strip) * 24}px)`, opacity: strip * 0.96, display: 'flex', diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/components/motifs.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/components/motifs.tsx index 445ee45b..ed084ac2 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/components/motifs.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/components/motifs.tsx @@ -38,9 +38,10 @@ export const Panel: React.FC<{ ); /** 底部角标——统一压在 bottom ≥ 150(避让字幕条,skills/06 红线二) */ -export const Footnote: React.FC<{children: React.ReactNode; delay?: number}> = ({ +export const Footnote: React.FC<{children: React.ReactNode; delay?: number; slot?: 0 | 1}> = ({ children, delay = 0, + slot = 0, }) => { const frame = useCurrentFrame(); const o = interpolate(frame - delay, [0, 14], [0, 1], { @@ -53,7 +54,9 @@ export const Footnote: React.FC<{children: React.ReactNode; delay?: number}> = ( position: 'absolute', left: 0, right: 0, - bottom: 168, + // slot:同一 Sequence 里并列两个组件各带一条 Footnote 时,两条会在 + // bottom:168 完全重印成一团糊字(2026-08 品控实拍坐实)。slot=1 抬到 206 错行。 + bottom: slot === 1 ? 206 : 168, textAlign: 'center', fontFamily: theme.mono, fontSize: 24, diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx index 9f757b51..e55df2f9 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx @@ -198,21 +198,22 @@ const OverflowThenZoom: React.FC<{zoomAt: number; cardsAt?: number}> = ({zoomAt, /** 官方博客三失败模式:agentic laziness / self-preferential bias / goal drift */ const SymptomCards: React.FC<{at: number}> = ({at}) => { const frame = useCurrentFrame(); + // 下移到环下方(原为 AbsoluteFill 居中,与孤环几何中心重合、三卡钉穿环腰——2026-08 实拍修) const cards = [ {t: '干一半就宣布完成', sub: '进度条半途打勾', en: 'agentic laziness'}, {t: '偏爱自己的产出', sub: '自评五星', en: 'self-preferential bias'}, {t: '目标越走越散', sub: '链条逐级褪色', en: 'goal drift'}, ]; return ( - -
+ +
{cards.map((c, i) => { const e = interpolate(frame - at - i * 9, [0, 14], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); return ( -
+
{c.t}
{c.sub}
@@ -448,7 +449,7 @@ export const P0Hook: React.FC<{scene: SceneRange}> = ({scene}) => { {/* 拉镜点在 p0-03;cardsAt:官方三失败模式症状卡(Harness Engineering 改造) */} - + {/* 图标预览点在 p0-08「一堆文件、几个信箱、一张编号表」 */} diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx index 92295ca8..380f4a18 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx @@ -780,7 +780,8 @@ const FourGates: React.FC<{gatesAt: number}> = ({gatesAt}) => { ]; return ( -
+ {/* 四道闸横排:上移到中带下沿(避免压住 repo 底座与 Footnote 双行区,2026-08 实拍修) */} +
{gates.map((g, i) => { const e = spring({frame: frame - gatesAt - i * 9, fps, config: {damping: 150}}); if (e <= 0) return null; @@ -788,7 +789,7 @@ const FourGates: React.FC<{gatesAt: number}> = ({gatesAt}) => {
= ({gatesAt}) => {
{g.s}
{g.locked ? (
- {'🔒 这道不能关'} + {'● 这道不能关'}
) : null}
); })}
- + {'隔离四检查 —— 官方文档 worktrees(取数2026年8月)'} diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/components/motifs.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/components/motifs.tsx index f79eea7b..54712994 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/components/motifs.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/components/motifs.tsx @@ -38,9 +38,10 @@ export const Panel: React.FC<{ ); /** 底部角标——统一压在 bottom ≥ 150(避让字幕条,skills/06 红线二) */ -export const Footnote: React.FC<{children: React.ReactNode; delay?: number}> = ({ +export const Footnote: React.FC<{children: React.ReactNode; delay?: number; slot?: 0 | 1}> = ({ children, delay = 0, + slot = 0, }) => { const frame = useCurrentFrame(); const o = interpolate(frame - delay, [0, 14], [0, 1], { @@ -53,7 +54,9 @@ export const Footnote: React.FC<{children: React.ReactNode; delay?: number}> = ( position: 'absolute', left: 0, right: 0, - bottom: 168, + // slot:同一 Sequence 里并列两个组件各带一条 Footnote 时,两条会在 + // bottom:168 完全重印成一团糊字(2026-08 品控实拍坐实)。slot=1 抬到 206 错行。 + bottom: slot === 1 ? 206 : 168, textAlign: 'center', fontFamily: theme.mono, fontSize: 24, diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx index c0f26659..2d42be04 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx @@ -463,15 +463,23 @@ const TwoDisciplines: React.FC<{lockAt: number; gateAt: number; dotAt: number}> }; /** 2-E ★五要素等号锁:两桌并置,五要素卡逐张比对,全部对上后锁扣合拢、SAVE 印章砸下。 */ -const FiveFactorLock: React.FC<{compareAt: number[]; lockAt: number; saveAt: number}> = ({ - compareAt, - lockAt, - saveAt, -}) => { +const FiveFactorLock: React.FC<{ + compareAt: number[]; + lockAt: number; + saveAt: number; + costAt?: number; + recalcAt?: number; + copyAt?: number; +}> = ({compareAt, lockAt, saveAt, costAt, recalcAt, copyAt}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); const factors = ['系统提示', '工具表', '模型', '消息前缀', '思考配置']; const matched = compareAt.map((a) => frame >= a + 14); + // 前段视觉事件(2026-08 品控修):本 beat 覆盖 9 句 50.7 秒,原首锚落在第 7 句(p2-22), + // 前 34 秒只有两个静态标签 + 五个孤立「≠」。补三拍:计价 → 原价重算 → 原样搬。 + const cost = costAt === undefined ? 0 : interpolate(frame - costAt, [0, 16], [0, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}); + const recalc = recalcAt === undefined ? 0 : interpolate(frame - recalcAt, [0, 20], [0, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}); + const copy = copyAt === undefined ? 0 : interpolate(frame - copyAt, [0, 22], [0, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}); const allOn = frame >= lockAt; const lock = spring({frame: frame - lockAt, fps, config: {damping: 13}}); return ( @@ -484,6 +492,40 @@ const FiveFactorLock: React.FC<{compareAt: number[]; lockAt: number; saveAt: num
+ {/* 前段三拍(p2-19/20/21):计价条 → 前缀全变红重算 → 原样搬回绿 */} + {cost > 0 ? ( +
+
+ {'对话按字数花钱 · 同样的开头,第二遍近乎免费'} +
+
+ {Array.from({length: 12}).map((_, i) => { + // 前缀 8 格:recalc 时整体转红(原价重算),copy 时转回 mech(命中) + const isPrefix = i < 8; + const red = isPrefix && recalc > 0.3 && copy < 0.3; + const hit = isPrefix && copy > 0.3; + return ( +
+ ); + })} +
+ {recalc > 0.3 ? ( +
0.3 ? theme.mech : theme.deny, textAlign: 'center', marginTop: 8}}> + {copy > 0.3 ? '原样搬过去 · 前缀一致 → 命中' : '前缀全变 → 每一段原价重算'} +
+ ) : null} +
+ ) : null} {/* 五要素卡:左右滑入逐字节对齐(每对上一张亮 mech)。行内容 880px 居中(px 数学,红线一) */}
{factors.map((f, i) => { @@ -507,7 +549,7 @@ const FiveFactorLock: React.FC<{compareAt: number[]; lockAt: number; saveAt: num
{/* 中缝:等号或问号 */} -
+
{m ? '=' : '≠'}
{/* 子侧卡(从右滑入) */} @@ -833,6 +875,9 @@ export const P2SideDesk: React.FC<{scene: SceneRange}> = ({scene}) => { ]} lockAt={relE('p2-23')} saveAt={relE('p2-23') + 24} + costAt={relE('p2-19')} + recalcAt={relE('p2-20')} + copyAt={relE('p2-21')} /> From 7987ebe91c53b33d772bdbc1fccb9e1a07d44ee5 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Fri, 28 Aug 2026 16:48:23 +0800 Subject: [PATCH 27/41] =?UTF-8?q?feat(video):=20=E5=85=A8=E7=89=87?= =?UTF-8?q?=E6=8C=81=E7=BB=AD=E5=8A=A8=E6=95=88=E2=80=94=E2=80=94SceneHead?= =?UTF-8?q?er=20=E5=B9=95=E5=86=85=E8=BF=9B=E5=BA=A6=E6=9D=A1=20+=20?= =?UTF-8?q?=E6=B8=B8=E6=A0=87=EF=BC=88=E6=A0=B9=E6=B2=BB=2092%=20=E9=87=87?= =?UTF-8?q?=E6=A0=B7=E7=82=B9=E9=9D=99=E6=AD=A2=EF=BC=89;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 实测:五集随机采样点 92% 在 0.2 秒内画面完全静止(镜内动效只在句锚附近发生,锚间长时间冻帧)。 评审报的「85 处死尾 / 33.1 分钟」是静态锚点分析的高估(props 传参的锚点未被计入),但方向正确 且更严重——这是全片节奏问题而非局部缺陷。 修法:SceneHeader 加 durationInFrames prop → 渲染幕内进度条(常驻底线 + 已走段染主色 + 头部游标带光晕)。帧驱动确定性,不违反禁随机数纪律;既消除「视频卡住」的错觉,又给观众 「这一幕还剩多久」的真实信息。35 幕全部接线,实测 1 秒内进度条区 212 像素变化(肉眼可辨)。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) --- .../video/src/components/motifs.tsx | 40 +++++++++++++++++- .../video/src/scenes/P0Wait.tsx | 2 +- .../video/src/scenes/P1Dereg.tsx | 2 +- .../video/src/scenes/P2Rejoin.tsx | 2 +- .../video/src/scenes/P3Watchdog.tsx | 2 +- .../video/src/scenes/P4Timer.tsx | 2 +- .../video/src/scenes/P5Truths.tsx | 2 +- .../video/src/scenes/P6Ending.tsx | 2 +- .../script/narration.md | 41 ++++++++++--------- .../video/src/components/motifs.tsx | 40 +++++++++++++++++- .../video/src/scenes/P0Hook.tsx | 2 +- .../video/src/scenes/P1Loop.tsx | 2 +- .../video/src/scenes/P2Dispatch.tsx | 2 +- .../video/src/scenes/P3Gates.tsx | 2 +- .../video/src/scenes/P4Hooks.tsx | 2 +- .../video/src/scenes/P5Stack.tsx | 2 +- .../video/src/scenes/P6Ending.tsx | 2 +- .../video/src/components/motifs.tsx | 40 +++++++++++++++++- .../video/src/scenes/P0Reject.tsx | 2 +- .../video/src/scenes/P1Desk.tsx | 2 +- .../video/src/scenes/P2Tidy.tsx | 2 +- .../video/src/scenes/P3Helper.tsx | 2 +- .../video/src/scenes/P4Ledger.tsx | 2 +- .../video/src/scenes/P5Hinge.tsx | 2 +- .../video/src/scenes/P6Ending.tsx | 2 +- .../video/src/components/motifs.tsx | 40 +++++++++++++++++- .../video/src/scenes/P0Hook.tsx | 2 +- .../video/src/scenes/P1Board.tsx | 2 +- .../video/src/scenes/P2Mail.tsx | 2 +- .../video/src/scenes/P3Handshake.tsx | 2 +- .../video/src/scenes/P4Autonomy.tsx | 2 +- .../video/src/scenes/P5Desks.tsx | 2 +- .../video/src/scenes/P6Finale.tsx | 2 +- .../video/src/components/motifs.tsx | 40 +++++++++++++++++- .../video/src/scenes/P0Hook.tsx | 2 +- .../video/src/scenes/P1Plan.tsx | 2 +- .../video/src/scenes/P2SideDesk.tsx | 2 +- .../video/src/scenes/P3Manual.tsx | 2 +- .../video/src/scenes/P4Ladder.tsx | 2 +- .../video/src/scenes/P5Ring.tsx | 2 +- .../video/src/scenes/P6Ending.tsx | 2 +- 41 files changed, 252 insertions(+), 59 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/components/motifs.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/components/motifs.tsx index bbda8472..a0a47c47 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/components/motifs.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/components/motifs.tsx @@ -108,10 +108,17 @@ export const SceneHeader: React.FC<{ title: string; meta?: string; accent?: string; -}> = ({index, title, meta, accent}) => { + /** 本幕总帧数:给出即渲染幕内进度条(见下方 ambient 说明) */ + durationInFrames?: number; +}> = ({index, title, meta, accent, durationInFrames}) => { const frame = useCurrentFrame(); const o = interpolate(frame, [0, 12], [0, 1], {extrapolateRight: 'clamp'}); const c = accent ?? theme.core; + // ambient(2026-08 品控修):实测五集随机采样点 92% 在 0.2 秒内画面**完全静止**—— + // 镜内动效只在句锚附近发生,锚与锚之间是长时间冻帧。这条幕内进度条是全片唯一 + // **每帧都在变**的元素,既消除「视频卡住了」的错觉,又给观众「这一幕还剩多久」的 + // 真实信息。帧驱动、确定性,不违反禁随机数纪律。 + const prog = durationInFrames && durationInFrames > 0 ? Math.min(1, frame / durationInFrames) : 0; return (
) : null} + {/* 幕内进度条:常驻底线 + 已走过的一段染主色 */} + {durationInFrames ? ( +
+
+ {/* 游标:进度条头部的一枚亮点 + 光晕。2px 的条在缩略图上几乎不可见, + 游标把「每帧都在动」放大到肉眼可辨,同时不抢镜内主体的注意力。 */} +
+
+ ) : null}
); }; diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx index 0115e928..9fcb4f77 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx @@ -458,7 +458,7 @@ export const P0Wait: React.FC<{scene: SceneRange}> = ({scene}) => { const bC = w('p0-09', 'p0-13'); return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P1Dereg.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P1Dereg.tsx index d7e28ba7..291e1bb5 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P1Dereg.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P1Dereg.tsx @@ -372,7 +372,7 @@ export const P1Dereg: React.FC<{scene: SceneRange}> = ({scene}) => { const bD = w('p1-16', 'p1-24'); return ( - + = ({scene}) => { const bE = w('p2-16', 'p2-23'); return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx index 96fdf1c2..d4075a73 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx @@ -360,7 +360,7 @@ export const P3Watchdog: React.FC<{scene: SceneRange}> = ({scene}) => { const bB = w('p3-04', 'p3-09c'); return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx index 4244749e..c6adda17 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx @@ -583,7 +583,7 @@ export const P4Timer: React.FC<{scene: SceneRange}> = ({scene}) => { const bE = w('p4-19', 'p4-27'); return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx index 8906cb35..34cba50b 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx @@ -555,7 +555,7 @@ export const P5Truths: React.FC<{scene: SceneRange}> = ({scene}) => { const bE = w('p5-19', 'p5-23b'); return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx index 23e828a8..d37472a8 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx @@ -332,7 +332,7 @@ export const P6Ending: React.FC<{scene: SceneRange}> = ({scene}) => { const bC = w('p6-13', 'p6-15'); return ( - + 角标:`tool_use` block · 「有工具调用 → 继续 / 没有 → 退出」 @@ -41,6 +43,8 @@ - [p1-10] 把模型的回答追加进列表,挑出里面所有的工具调用; - [p1-11] 一个都没有就地返回,有就逐个执行、收好每条结果; - [p1-12] 最后把结果打包成新消息追加进去,回到第二步。写完了。 +- [p1-12a] 说明一下:有人照着这套机制搭了一份开源的最小实现。 +- [p1-12b] 下面我一边读它,一边跟真实产品对照着看。 - [p1-13] 有人给它的评价是:三十多行,最小可运行的内核。 - [p1-14] 我自己数过这一版:光循环那个函数,去掉空行和注释,二十三行。 @@ -77,7 +81,6 @@ - [p2-01] 刚才那个循环,手里只有一件工具:一个能跑命令的壳。 - [p2-02] 想读文件,它得拼出一条读文件的命令;想写文件,得拼一条重定向。 - [p2-03] 模型心里想的是「读这个文件」,嘴上却要翻译成一条命令行。 -- [p2-04] 多这一层翻译,费字数,还容易拼错。 - [p2-05] 那就把常用动作直接做成工具,于是从一件变成五件: - [p2-06] 跑命令、读文件、写文件、改文件、按模式找文件。 - [p2-07] 问题是循环怎么知道该调哪一个?答案朴素得让人意外:查一张表。 @@ -122,8 +125,7 @@ - [p3-01] 现在这个 AI 有五件工具,其中一件能跑任意命令。 - [p3-02] 读写文件那几件都被拦在工作目录里,但跑命令那件,没人管它。 - [p3-03] 你随口说一句「帮我把项目清理一下」, -- [p3-04] 它完全可能给你递上一条把整块盘删干净的命令, -- [p3-05] 而按前面的设计,循环会老老实实替它执行。 +- [p3-04] 它完全可能给你递上一条把整块盘删干净的命令,循环照跑。 - [p3-06] 官方把话说死了:权限由这层代码执行,不由模型执行。 - [p3-07] 拦法是三道闸门,顺序写死。 - [p3-08] 第一道是一张硬拒绝表:删根目录、提权、关机、格式化。 @@ -131,23 +133,23 @@ - [p3-10] 第二道是规则匹配,管「看情况」的操作: - [p3-11] 读写工作目录之外的东西,或者命令里带着删除、改权限这类动作。 - [p3-12] 第三道就是问你:画面停下来,把工具名和参数摆给你看,等你点头。 -- [p3-13] 三道都没命中呢?兜底永远再问你一句——弃权不等于放行。 -- [p3-14] 教学版里有一句很诚实的话,我想念出来。 -- [p3-15] 它说,这张拒绝表用的是最简单的字符串匹配, -- [p3-16] 它的作用是告诉你「闸门应该装在哪儿」, -- [p3-17] 而不能被当成一道真正的安全边界—— -- [p3-18] 因为同一件坏事有无数种写法,换个拼法就绕过去了。 -- [p3-19] 一个教学项目愿意在自己的示例代码旁写下这句话,挺难得。 - -> 金句卡(serif):「它告诉你闸门装在哪儿,不是替你把门守住。」 - -- [p3-20] 那真实产品里的门长什么样? -- [p3-21] 按第三方的源码分析,结论不是三种,是四种。 +- [p3-14] 教学版自己承认:这张表只是字符串匹配,换个拼法就绕过去。 +- [p3-15] 它告诉你闸门装在哪儿,不替你把门守住。 + +> 金句卡(serif):「它告诉你闸门装在哪儿,不是替你把门守住。」(与 p3-15 音画同句) + +- [p3-19a] 真正的边界在更底下一层:官方给跑命令那件工具,套了一层沙箱。 +- [p3-19b] 能写哪些目录、能走哪个网络出口,由操作系统说了算。 +- [p3-19c] 规则是劝,沙箱是锁——两道墙少一道,笼子就不成立。 +- [p3-19d] 官方内部用下来,权限提示少了八成四。 + +> 角标:Seatbelt / bubblewrap + socat · 文件系统与网络双边界 · 权限提示 −84%(官方工程博客,取数 2025-10) + +- [p3-20] 回到闸门这边:有人拆过它的源码,判定结果是四种,不是三种。 - [p3-23] 多出来的第四种最有意思:工具选择不表态。 - [p3-24] 也就是说,弃权不等于放行,兜底永远是问你一句。 - [p3-25] 规则求值的顺序官方也写死了:拒绝、询问、放行, - [p3-26] 头一个命中就出局——规则写得多具体,都改变不了顺序。 -- [p3-27] 所以一条宽拒绝,靠一条窄放行开不出例外。 - [p3-28] 裸名拒绝更狠:整件工具从模型身上直接消失。 - [p3-29] 就算全放行模式,也压不住一条写死的拒绝。 @@ -155,8 +157,9 @@ - [p3-30] 全自动模式不靠你点头的次数,靠另一个模型当闸门。 - [p3-31] 官方遥测补一刀:权限提示,九成三都被点了批准。 +- [p3-31a] 这个当闸门的模型,自己也进过考场。 +- [p3-31b] 快筛误杀率百分之八点五,复核之后压到千分之四。 - [p3-32] 审判者的视野是做减法的:只看用户消息和裸命令。 -- [p3-33] 模型的自我辩解、工具的输出,全被剥在视野外。 - [p3-34] 评它做了什么,不看它说了什么——注入的谎话骗不到它。 - [p3-35] 让模型帮忙看门,同时不敢把门全交给模型。 diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/components/motifs.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/components/motifs.tsx index 7cecb2ee..aabde1fe 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/components/motifs.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/components/motifs.tsx @@ -102,10 +102,17 @@ export const SceneHeader: React.FC<{ title: string; meta?: string; accent?: string; -}> = ({index, title, meta, accent}) => { + /** 本幕总帧数:给出即渲染幕内进度条(见下方 ambient 说明) */ + durationInFrames?: number; +}> = ({index, title, meta, accent, durationInFrames}) => { const frame = useCurrentFrame(); const o = interpolate(frame, [0, 12], [0, 1], {extrapolateRight: 'clamp'}); const c = accent ?? theme.core; + // ambient(2026-08 品控修):实测五集随机采样点 92% 在 0.2 秒内画面**完全静止**—— + // 镜内动效只在句锚附近发生,锚与锚之间是长时间冻帧。这条幕内进度条是全片唯一 + // **每帧都在变**的元素,既消除「视频卡住了」的错觉,又给观众「这一幕还剩多久」的 + // 真实信息。帧驱动、确定性,不违反禁随机数纪律。 + const prog = durationInFrames && durationInFrames > 0 ? Math.min(1, frame / durationInFrames) : 0; return (
) : null} + {/* 幕内进度条:常驻底线 + 已走过的一段染主色 */} + {durationInFrames ? ( +
+
+ {/* 游标:进度条头部的一枚亮点 + 光晕。2px 的条在缩略图上几乎不可见, + 游标把「每帧都在动」放大到肉眼可辨,同时不抢镜内主体的注意力。 */} +
+
+ ) : null}
); }; diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx index eadb50e0..006ea0e8 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx @@ -366,7 +366,7 @@ export const P0Hook: React.FC<{scene: SceneRange}> = ({scene}) => { const bC = w('p0-06', 'p0-07'); return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx index 607929ea..f651c910 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx @@ -532,7 +532,7 @@ export const P1Loop: React.FC<{scene: SceneRange}> = ({scene}) => { const rF = (id: string) => w(id).from - bF.from; return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx index a7fde84d..33941890 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx @@ -563,7 +563,7 @@ export const P2Dispatch: React.FC<{scene: SceneRange}> = ({scene}) => { const rel = (b: {from: number}, id: string) => w(id).from - b.from; return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx index ab1ac897..19abe64c 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx @@ -690,7 +690,7 @@ export const P3Gates: React.FC<{scene: SceneRange}> = ({scene}) => { const bG = w('p3-30', 'p3-35'); return ( - + = ({scene}) => { const bH = w('p4-35', 'p4-37'); return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P5Stack.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P5Stack.tsx index 17de716d..cd2edc6f 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P5Stack.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P5Stack.tsx @@ -488,7 +488,7 @@ export const P5Stack: React.FC<{scene: SceneRange}> = ({scene}) => { const bD = w('p5-15', 'p5-19'); return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx index 3a36a8e6..6f3bf98c 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx @@ -288,7 +288,7 @@ export const P6Ending: React.FC<{scene: SceneRange}> = ({scene}) => { const bB = w('p6-05', 'p6-08'); return ( - + = ({index, title, meta, accent}) => { + /** 本幕总帧数:给出即渲染幕内进度条(见下方 ambient 说明) */ + durationInFrames?: number; +}> = ({index, title, meta, accent, durationInFrames}) => { const frame = useCurrentFrame(); const o = interpolate(frame, [0, 12], [0, 1], {extrapolateRight: 'clamp'}); const c = accent ?? theme.core; + // ambient(2026-08 品控修):实测五集随机采样点 92% 在 0.2 秒内画面**完全静止**—— + // 镜内动效只在句锚附近发生,锚与锚之间是长时间冻帧。这条幕内进度条是全片唯一 + // **每帧都在变**的元素,既消除「视频卡住了」的错觉,又给观众「这一幕还剩多久」的 + // 真实信息。帧驱动、确定性,不违反禁随机数纪律。 + const prog = durationInFrames && durationInFrames > 0 ? Math.min(1, frame / durationInFrames) : 0; return (
) : null} + {/* 幕内进度条:常驻底线 + 已走过的一段染主色 */} + {durationInFrames ? ( +
+
+ {/* 游标:进度条头部的一枚亮点 + 光晕。2px 的条在缩略图上几乎不可见, + 游标把「每帧都在动」放大到肉眼可辨,同时不抢镜内主体的注意力。 */} +
+
+ ) : null}
); }; diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx index b9e59636..b32d1ec5 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx @@ -428,7 +428,7 @@ export const P0Reject: React.FC<{scene: SceneRange}> = ({scene}) => { const relD = (id: string) => at(id) - bD.from; return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P1Desk.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P1Desk.tsx index a5419d83..cd35035f 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P1Desk.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P1Desk.tsx @@ -361,7 +361,7 @@ export const P1Desk: React.FC<{scene: SceneRange}> = ({scene}) => { const relC = (id: string) => at(id) - bC.from; return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P2Tidy.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P2Tidy.tsx index 349c26f3..aa99e259 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P2Tidy.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P2Tidy.tsx @@ -646,7 +646,7 @@ export const P2Tidy: React.FC<{scene: SceneRange}> = ({scene}) => { const relD = (id: string) => at(id) - bD.from; return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx index 3e75131b..62348838 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx @@ -474,7 +474,7 @@ export const P3Helper: React.FC<{scene: SceneRange}> = ({scene}) => { const relC = (id: string) => at(id) - bC.from; return ( - + = ({scene}) => { const relE = (id: string) => at(id) - bE.from; return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P5Hinge.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P5Hinge.tsx index 9d4959df..0de4d0e6 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P5Hinge.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P5Hinge.tsx @@ -747,7 +747,7 @@ export const P5Hinge: React.FC<{scene: SceneRange}> = ({scene}) => { const relE = (id: string) => at(id) - bE.from; return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx index feb2db10..2d6ee939 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx @@ -192,7 +192,7 @@ export const P6Ending: React.FC<{scene: SceneRange}> = ({scene}) => { const relB = (id: string) => at(id) - bB.from; return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/components/motifs.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/components/motifs.tsx index ed084ac2..f152127d 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/components/motifs.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/components/motifs.tsx @@ -110,10 +110,17 @@ export const SceneHeader: React.FC<{ title: string; meta?: string; accent?: string; -}> = ({index, title, meta, accent}) => { + /** 本幕总帧数:给出即渲染幕内进度条(见下方 ambient 说明) */ + durationInFrames?: number; +}> = ({index, title, meta, accent, durationInFrames}) => { const frame = useCurrentFrame(); const o = interpolate(frame, [0, 12], [0, 1], {extrapolateRight: 'clamp'}); const c = accent ?? theme.core; + // ambient(2026-08 品控修):实测五集随机采样点 92% 在 0.2 秒内画面**完全静止**—— + // 镜内动效只在句锚附近发生,锚与锚之间是长时间冻帧。这条幕内进度条是全片唯一 + // **每帧都在变**的元素,既消除「视频卡住了」的错觉,又给观众「这一幕还剩多久」的 + // 真实信息。帧驱动、确定性,不违反禁随机数纪律。 + const prog = durationInFrames && durationInFrames > 0 ? Math.min(1, frame / durationInFrames) : 0; return (
) : null} + {/* 幕内进度条:常驻底线 + 已走过的一段染主色 */} + {durationInFrames ? ( +
+
+ {/* 游标:进度条头部的一枚亮点 + 光晕。2px 的条在缩略图上几乎不可见, + 游标把「每帧都在动」放大到肉眼可辨,同时不抢镜内主体的注意力。 */} +
+
+ ) : null}
); }; diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx index e55df2f9..f7018873 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx @@ -445,7 +445,7 @@ export const P0Hook: React.FC<{scene: SceneRange}> = ({scene}) => { const bC = w('p0-09', 'p0-10'); return ( - + {/* 拉镜点在 p0-03;cardsAt:官方三失败模式症状卡(Harness Engineering 改造) */} diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx index 97521ea9..2cf0f7d6 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx @@ -738,7 +738,7 @@ export const P1Board: React.FC<{scene: SceneRange}> = ({scene}) => { const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx index f3bd213d..317e346c 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx @@ -832,7 +832,7 @@ export const P2Mail: React.FC<{scene: SceneRange}> = ({scene}) => { const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx index 43dfedf4..58e9cdfa 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx @@ -722,7 +722,7 @@ export const P3Handshake: React.FC<{scene: SceneRange}> = ({scene}) => { const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx index 79387444..74add22c 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx @@ -706,7 +706,7 @@ export const P4Autonomy: React.FC<{scene: SceneRange}> = ({scene}) => { const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx index 380f4a18..e89709bd 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx @@ -830,7 +830,7 @@ export const P5Desks: React.FC<{scene: SceneRange}> = ({scene}) => { const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( - + = ({scene}) => { const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( - + diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/components/motifs.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/components/motifs.tsx index 54712994..24a77628 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/components/motifs.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/components/motifs.tsx @@ -110,10 +110,17 @@ export const SceneHeader: React.FC<{ title: string; meta?: string; accent?: string; -}> = ({index, title, meta, accent}) => { + /** 本幕总帧数:给出即渲染幕内进度条(见下方 ambient 说明) */ + durationInFrames?: number; +}> = ({index, title, meta, accent, durationInFrames}) => { const frame = useCurrentFrame(); const o = interpolate(frame, [0, 12], [0, 1], {extrapolateRight: 'clamp'}); const c = accent ?? theme.core; + // ambient(2026-08 品控修):实测五集随机采样点 92% 在 0.2 秒内画面**完全静止**—— + // 镜内动效只在句锚附近发生,锚与锚之间是长时间冻帧。这条幕内进度条是全片唯一 + // **每帧都在变**的元素,既消除「视频卡住了」的错觉,又给观众「这一幕还剩多久」的 + // 真实信息。帧驱动、确定性,不违反禁随机数纪律。 + const prog = durationInFrames && durationInFrames > 0 ? Math.min(1, frame / durationInFrames) : 0; return (
) : null} + {/* 幕内进度条:常驻底线 + 已走过的一段染主色 */} + {durationInFrames ? ( +
+
+ {/* 游标:进度条头部的一枚亮点 + 光晕。2px 的条在缩略图上几乎不可见, + 游标把「每帧都在动」放大到肉眼可辨,同时不抢镜内主体的注意力。 */} +
+
+ ) : null}
); }; diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx index 9e3773a0..3eea885b 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx @@ -333,7 +333,7 @@ export const P0Hook: React.FC<{scene: SceneRange}> = ({scene}) => { const relC = (id: string) => at(id) - bC.from; return ( - + {/* p0-01 钩子即上滚;p0-03「被官方收回去」:收回钢印 */} diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx index 46deec15..493c94cd 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx @@ -395,7 +395,7 @@ export const P1Plan: React.FC<{scene: SceneRange}> = ({scene}) => { const relD = (id: string) => at(id) - bD.from; return ( - + {/* 三态图标演示态跟随 p1-02(每条标一个状态)逐个闪现 */} diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx index 2d42be04..7a7b3ab2 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx @@ -847,7 +847,7 @@ export const P2SideDesk: React.FC<{scene: SceneRange}> = ({scene}) => { const relF = (id: string) => at(id) - bF.from; return ( - + {/* p2-03「一百多条」起暴涨;p2-04「一直计着费」起计数器 */} diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx index eb3981e1..6990275d 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx @@ -723,7 +723,7 @@ export const P3Manual: React.FC<{scene: SceneRange}> = ({scene}) => { const relF = (id: string) => at(id) - bF.from; return ( - + {/* p3-02「全贴进基本设定」手册拍上桌;p3-03 计价器跳红 */} diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx index bf05f539..13b58162 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx @@ -674,7 +674,7 @@ export const P4Ladder: React.FC<{scene: SceneRange}> = ({scene}) => { const relE = (id: string) => at(id) - bE.from; return ( - + {/* p4-01「管的是意外」桌子亮出;p4-02 岔子预告,梯子自上垂下挂稳 */} diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P5Ring.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P5Ring.tsx index b6e231c4..7a63bd8f 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P5Ring.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P5Ring.tsx @@ -277,7 +277,7 @@ export const P5Ring: React.FC<{scene: SceneRange}> = ({scene}) => { const relC = (id: string) => at(id) - bC.from; return ( - + {/* p5-02 五样摆在一起:自左向右滑入;p5-04..05 职责印章逐枚落下 */} = ({scene}) => { const bB = w('p6-05', 'p6-09'); return ( - + {/* p6-04「同一门手艺」次行浮现 */} From 6d6bea3200c60ad3e952adddfbf4d2c5933398ca Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Fri, 28 Aug 2026 17:13:43 +0800 Subject: [PATCH 28/41] =?UTF-8?q?feat(video):=20B=20=E6=96=B9=E6=A1=88?= =?UTF-8?q?=E5=8F=A3=E6=92=AD=E8=90=BD=E5=9C=B0=E2=80=94=E2=80=94=E4=BA=94?= =?UTF-8?q?=E9=9B=86=E6=8C=89=2039=20=E6=9D=A1=E5=8F=8C=E7=A5=A8=20finding?= =?UTF-8?q?s=20=E6=94=B9=E5=86=99=EF=BC=88=E5=AD=97=E6=95=B0=E5=85=A8?= =?UTF-8?q?=E6=94=B6=E6=95=9B=EF=BC=89;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EP1 23 项(沙箱四句/成绩单两句/退出码三句/SWE-bench 赌注三句/教学版锚/四件套口径统一/ 六句咏叹压缩回收)→ 4025 字;EP2 15 项(四件套脊椎句/计划闸 1-E 五句/退位帧区重切/ 削层帧/不重试两类/收尾改序)→ 3948 字;EP3 20 项(装载清单两句/rot 机制三句/四件套 钉格/user message 纠错四句/第一定律三句/收尾改序)→ 4019 字;EP4 6 项(p6-08 矛盾句删/ 四件套口径/循环格落点/预告改写)→ 3873 字;EP5 13 项(官方编译器战例 8 句/第一定律 回收两句/correlation ID 压缩/预告递进修)→ 3998 字。 单票项 39 处按纪律 skip 并留档(.temp/review/deferred18.json + 各集 skipped 清单)。 全部:句 id 字母后缀零重编号保缓存;反串线/去站点化/英文白名单/证据分级 0 违规; storyboard 已同步(含 EP2 1-E 计划闸、EP4 4-D2、EP5 4-E 战例、EP3 0-C2/6-C 新镜规格)。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) --- .../script/narration.json | 32 ++-- .../script/narration.md | 16 +- .../script/storyboard.md | 10 +- .../script/narration.json | 144 ++++++++-------- .../script/narration.md | 24 +-- .../script/storyboard.md | 42 ++--- .../script/narration.json | 111 ++++++++----- .../script/narration.md | 49 +++--- .../script/storyboard.md | 14 +- .../script/narration.json | 93 +++++++---- .../script/narration.md | 25 +-- .../script/storyboard.md | 13 +- .../script/narration.json | 154 ++++++++++-------- .../script/narration.md | 67 ++++---- .../script/storyboard.md | 24 ++- 15 files changed, 465 insertions(+), 353 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json index cba4fde6..c0dfda7d 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json @@ -557,12 +557,12 @@ { "id": "p5-13", "scene": "P5", - "text": "第三个真话最实在,也是最容易踩坑的:" + "text": "第三个真话最实在,也最容易踩坑:把进程关了,表就停了。" }, { "id": "p5-14", "scene": "P5", - "text": "但官方给了新答案:后台会话由一个独立的管家进程托管。" + "text": "但官方给了新答案:后台会话由独立的管家进程托管,不怕终端关掉。" }, { "id": "p5-15", @@ -650,19 +650,24 @@ "text": "而从头到尾,那个循环一秒都没停过。" }, { - "id": "p6-07", + "id": "p6-13", "scene": "P6", - "text": "按下的不一定是它,等的一定不是你。" + "text": "本片机制依据官方文档,取数2026年8月,以官方最新表述为准。" + }, + { + "id": "p6-14", + "scene": "P6", + "text": "涉及产品内部的部分,为第三方源码分析,片中已逐处标注。" }, { - "id": "p6-08", + "id": "p6-07", "scene": "P6", - "text": "有人在等它,但它从不等你;它也开始学着不等任何东西。" + "text": "按下的不一定是它,等的一定不是你。" }, { "id": "p6-09", "scene": "P6", - "text": "但记住那个真话:时钟装在它的身体里,不在墙上。" + "text": "钟曾经装在它身体里,现在挪进了一个不睡的管家。" }, { "id": "p6-10", @@ -677,21 +682,16 @@ { "id": "p6-12", "scene": "P6", - "text": "官方给这层工程画过一张像:一个循环、一套工具、一套记忆、一道护栏。" + "text": "官方给整副 Harness 画过一张像:循环、工具、上下文管理、护栏。" }, { - "id": "p6-13", + "id": "p6-12a", "scene": "P6", - "text": "本片机制依据官方文档,取数2026年8月,以官方最新表述为准。" - }, - { - "id": "p6-14", - "scene": "P6", - "text": "涉及产品内部的部分,为第三方源码分析,片中已逐处标注。" + "text": "今天拆的这只手,是循环的另一半——它不必原地等,也不必人来按。" }, { "id": "p6-15", "scene": "P6", - "text": "下期,桌子从一张变成一排:一群它,怎么分活、怎么传话、怎么不打架。下期见。" + "text": "下期:官方算过,一群它比一个它贵十五倍——为什么还有人这么干。下期见。" } ] diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md index 26590093..9519893f 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md @@ -174,8 +174,8 @@ ## P6 落点与信源 -> 画面:三种开始的三段位置图(人在环上/人在环外/没有人)→ 一句话合同金句卡 → -> 信源卡 → 身份卡 → 渐黑(末 beat 总时长推导)。 +> 画面:三种开始的三段位置图(人在环上/人在环外/没有人)→ 信源卡(免责两句前置)→ +> 一句话合同金句卡 → 边界两句 + 四件套回收条 → 身份卡 → 渐黑(末 beat 总时长推导)。 - [p6-01] 收个尾。这一集其实只回答了一个问题:谁来按开始。 - [p6-02] 三种答案。有人按并等着——最笨也最常见; @@ -183,12 +183,12 @@ - [p6-04] 没人按——时间自己按,错峰响,七天不响就退休。 - [p6-05] 每多一种开始,机制就往外挪一层:活挪出这一轮,触发挪出这个人。 - [p6-06] 而从头到尾,那个循环一秒都没停过。 +- [p6-13] 本片机制依据官方文档,取数2026年8月,以官方最新表述为准。 +- [p6-14] 涉及产品内部的部分,为第三方源码分析,片中已逐处标注。 - [p6-07] 按下的不一定是它,等的一定不是你。 -- [p6-08] 有人在等它,但它从不等你;它也开始学着不等任何东西。 -- [p6-09] 但记住那个真话:时钟装在它的身体里,不在墙上。 +- [p6-09] 钟曾经装在它身体里,现在挪进了一个不睡的管家。 - [p6-10] 它的自主,到此为止是「守时的自主」——时间到点自己开工, - [p6-11] 至于「自己决定该干什么活」,那是更大的一步,我们后面再拆。 -- [p6-12] 官方给这层工程画过一张像:一个循环、一套工具、一套记忆、一道护栏。 -- [p6-13] 本片机制依据官方文档,取数2026年8月,以官方最新表述为准。 -- [p6-14] 涉及产品内部的部分,为第三方源码分析,片中已逐处标注。 -- [p6-15] 下期,桌子从一张变成一排:一群它,怎么分活、怎么传话、怎么不打架。下期见。 +- [p6-12] 官方给整副 Harness 画过一张像:循环、工具、上下文管理、护栏。 +- [p6-12a] 今天拆的这只手,是循环的另一半——它不必原地等,也不必人来按。 +- [p6-15] 下期:官方算过,一群它比一个它贵十五倍——为什么还有人这么干。下期见。 diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md index c8aeec0a..5332bd81 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/storyboard.md @@ -55,9 +55,9 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 5-A | p5-01..04 | ★踩踏帧:一排相同的表全指 9:00,千万任务同一秒冲出互相踩踏(`deny` 混乱) | 表针同时到位→任务箭头齐射→拥挤碰撞效果 | -| 5-B | p5-05..08 | ★确定性抖动:同排表各按算好的固定偏移错峰落下;「算出来 vs 随机」对照(随机会漂的轨迹线) | 每张表各自延迟不同但固定的量再落;随机轨迹画成漂移虚线(`deny`),确定性轨迹为整齐错列(`later`);整点提前 90 秒逆行小箭头 | -| 5-C | p5-09..10 | 七天退休:日历翻七天→退休章盖下(删前最后跑一次的小尾巴) | 日历快翻;章落下;最后一次触发的小脉冲 | -| 5-D | p5-11..18 | ★官方新答案:独立管家进程托管后台会话——不眠的眼睛、六状态记账(排队/跑着/等审批/被拦/收尾/完事)、行摘要小模型、状态落盘穿重启、接回从停点续跑 | 管家图标 spring 立起;六状态胶囊逐个点亮;左下「状态落盘·穿重启」卡 + 右下「进程退出≠任务没了」卡对浮 | +| 5-B | p5-05..10 | ★确定性抖动:同排表各按算好的固定偏移错峰落下;「算出来 vs 随机」对照(随机会漂的轨迹线) | 每张表各自延迟不同但固定的量再落;随机轨迹画成漂移虚线(`deny`),确定性轨迹为整齐错列(`later`);整点提前 90 秒逆行小箭头(p5-09/10) | +| 5-C | p5-11..12 | 七天退休:日历翻七天→退休章盖下(删前最后跑一次的小尾巴) | 日历快翻;章落下;最后一次触发的小脉冲 | +| 5-D | p5-13..18 | ★诚实边界 + 官方新答案:p5-13 旧真话(进程关了表就停)被 deny 斜划→独立管家进程托管后台会话——不眠的眼睛、六状态记账(排队/跑着/等审批/被拦/收尾/完事)、行摘要小模型、状态落盘穿重启、接回从停点续跑 | p5-13 终端图标 + deny 斜划「进程关了→表停」;p5-14 管家 spring 立起把它推成虚影;六状态胶囊逐个点亮;左下「状态落盘·穿重启」卡 + 右下「进程退出≠任务没了」卡对浮 | | 5-E | p5-19..23b | 上限 50 + 低优先级标记 + **自定速发条**(p5-23a/b:干完一轮顺手定下一次,间隔自己定) + 收束句 | 满座计数器 50/50;低优先级卡排队尾;发条图标自转一圈拨出下一格;金句卡淡入 | ## P6 落点与信源 @@ -65,5 +65,5 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 6-A | p6-01..06 | 三种开始三段位置图(人在环上/人在环外/没有人)→ 环一秒不停的回收:三图右上角同一个环持续转 | 三段图依次亮起;共享的小环匀速转动贯穿 | -| 6-B | p6-07..12 | 一句话合同金句卡「按下的不一定是它,等的一定不是你」+「守时的自主」边界两句 | 金句卡(`core`)淡入;边界两句以小字跟随 | -| 6-C | p6-13..15 | 信源卡(官方文档+取数日期 / 第三方源码分析已逐处标注 / 数字均为实测口径)→ 身份卡 → 渐黑(末 beat 总时长推导,红线四) | 逐行浮现;身份卡;末 1.2s 线性压暗 | +| 6-B | p6-13..p6-12a | 信源卡免责两句**前置**(p6-13 官方文档+取数日期 / p6-14 第三方源码分析已逐处标注)→ 一句话合同金句卡「按下的不一定是它,等的一定不是你」→ p6-09「钟挪进不睡的管家」过渡 →「守时的自主」边界两句 → 四件套回收条(p6-12 循环/工具/上下文管理/护栏;p6-12a 本集钉进「循环」格) | 免责两行信源样式小字先浮出;金句卡(`core`)spring 淡入;四件套回收条四格依次亮(反枚举:四格不给四色),仅「循环」格 core 描边 + 呼吸辉光(p6-12a) | +| 6-C | p6-15 | 身份卡 → 下期卡 → 渐黑(末 beat 总时长推导,红线四) | 身份卡;下期卡;末 1.2s 线性压暗 | diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json index 59cfc801..ef717f74 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json @@ -14,6 +14,21 @@ "scene": "P0", "text": "从「写出命令」到「真的跑起来」,缺的那一层,官方起了名字。" }, + { + "id": "p0-03a", + "scene": "P0", + "text": "这一层有多要紧?官方讲自己刷编程评测时写过一句话——" + }, + { + "id": "p0-03b", + "scene": "P0", + "text": "同一个底层模型,换一套脚手架,成绩能差出一大截。" + }, + { + "id": "p0-03c", + "scene": "P0", + "text": "你花在这一层上的力气,直接变成它的分数。" + }, { "id": "p0-04", "scene": "P0", @@ -27,7 +42,7 @@ { "id": "p0-06", "scene": "P0", - "text": "Harness 供给它五样东西:文件、命令、权限、记忆、护栏。" + "text": "Harness 给它四件:一个循环、一套工具、上下文管理、一道护栏。" }, { "id": "p0-07", @@ -64,11 +79,6 @@ "scene": "P1", "text": "没有,就说明它觉得活干完了,循环停机,把话交给你。" }, - { - "id": "p1-07", - "scene": "P1", - "text": "就这么两个信号,决定这条传送带转不转。" - }, { "id": "p1-08", "scene": "P1", @@ -94,6 +104,16 @@ "scene": "P1", "text": "最后把结果打包成新消息追加进去,回到第二步。写完了。" }, + { + "id": "p1-12a", + "scene": "P1", + "text": "说明一下:有人照着这套机制搭了一份开源的最小实现。" + }, + { + "id": "p1-12b", + "scene": "P1", + "text": "下面我一边读它,一边跟真实产品对照着看。" + }, { "id": "p1-13", "scene": "P1", @@ -209,11 +229,6 @@ "scene": "P2", "text": "模型心里想的是「读这个文件」,嘴上却要翻译成一条命令行。" }, - { - "id": "p2-04", - "scene": "P2", - "text": "多这一层翻译,费字数,还容易拼错。" - }, { "id": "p2-05", "scene": "P2", @@ -367,12 +382,7 @@ { "id": "p3-04", "scene": "P3", - "text": "它完全可能给你递上一条把整块盘删干净的命令," - }, - { - "id": "p3-05", - "scene": "P3", - "text": "而按前面的设计,循环会老老实实替它执行。" + "text": "它完全可能给你递上一条把整块盘删干净的命令,循环照跑。" }, { "id": "p3-06", @@ -409,50 +419,40 @@ "scene": "P3", "text": "第三道就是问你:画面停下来,把工具名和参数摆给你看,等你点头。" }, - { - "id": "p3-13", - "scene": "P3", - "text": "三道都没命中呢?兜底永远再问你一句——弃权不等于放行。" - }, { "id": "p3-14", "scene": "P3", - "text": "教学版里有一句很诚实的话,我想念出来。" + "text": "教学版自己承认:那张拒绝表只是字符串匹配,换个拼法就绕过去。" }, { "id": "p3-15", "scene": "P3", - "text": "它说,这张拒绝表用的是最简单的字符串匹配," + "text": "它告诉你闸门装在哪儿,不替你把门守住。" }, { - "id": "p3-16", + "id": "p3-19a", "scene": "P3", - "text": "它的作用是告诉你「闸门应该装在哪儿」," + "text": "真正的边界在更底下一层:官方给跑命令那件工具,套了一层沙箱。" }, { - "id": "p3-17", + "id": "p3-19b", "scene": "P3", - "text": "而不能被当成一道真正的安全边界——" + "text": "能写哪些目录、能走哪个网络出口,由操作系统说了算。" }, { - "id": "p3-18", + "id": "p3-19c", "scene": "P3", - "text": "因为同一件坏事有无数种写法,换个拼法就绕过去了。" + "text": "规则是劝,沙箱是锁——两道墙少一道,笼子就不成立。" }, { - "id": "p3-19", + "id": "p3-19d", "scene": "P3", - "text": "一个教学项目愿意在自己的示例代码旁写下这句话,挺难得。" + "text": "官方内部用下来,权限提示少了八成四。" }, { "id": "p3-20", "scene": "P3", - "text": "那真实产品里的门长什么样?" - }, - { - "id": "p3-21", - "scene": "P3", - "text": "按第三方的源码分析,结论不是三种,是四种。" + "text": "回到闸门这边:有人拆过它的源码,判定结果是四种,不是三种。" }, { "id": "p3-23", @@ -474,11 +474,6 @@ "scene": "P3", "text": "头一个命中就出局——规则写得多具体,都改变不了顺序。" }, - { - "id": "p3-27", - "scene": "P3", - "text": "所以一条宽拒绝,靠一条窄放行开不出例外。" - }, { "id": "p3-28", "scene": "P3", @@ -500,14 +495,19 @@ "text": "官方遥测补一刀:权限提示,九成三都被点了批准。" }, { - "id": "p3-32", + "id": "p3-31a", "scene": "P3", - "text": "审判者的视野是做减法的:只看用户消息和裸命令。" + "text": "这个当闸门的模型,自己也进过考场。" }, { - "id": "p3-33", + "id": "p3-31b", "scene": "P3", - "text": "模型的自我辩解、工具的输出,全被剥在视野外。" + "text": "快筛误杀率百分之八点五,复核之后压到千分之四。" + }, + { + "id": "p3-32", + "scene": "P3", + "text": "审判者的视野是做减法的:只看用户消息和裸命令。" }, { "id": "p3-34", @@ -617,12 +617,7 @@ { "id": "p4-20", "scene": "P4", - "text": "四个插口覆盖一整轮:进来、动手前、动手后、结束前," - }, - { - "id": "p4-21", - "scene": "P4", - "text": "而循环只负责在这四个点上喊一声。" + "text": "四个插口覆盖一整轮,循环只在这四个点上喊一声。" }, { "id": "p4-22", @@ -654,6 +649,21 @@ "scene": "P4", "text": "不吭声的意思是「我不作决定」,流程照走。" }, + { + "id": "p4-28a", + "scene": "P4", + "text": "反过来,想真拦住只有一个硬信号;写错成惯用的失败码," + }, + { + "id": "p4-28b", + "scene": "P4", + "text": "闸门不响、动作照跑——静默失效。" + }, + { + "id": "p4-28c", + "scene": "P4", + "text": "第一次给循环挂扩展的人,几乎都栽在这一脚上。" + }, { "id": "p4-29", "scene": "P4", @@ -722,7 +732,7 @@ { "id": "p5-05", "scene": "P5", - "text": "官方给 Harness 的定义正好四件:循环、工具、上下文管理、护栏。" + "text": "回到官方那四件:循环、工具、上下文管理、护栏。" }, { "id": "p5-06", @@ -737,7 +747,7 @@ { "id": "p5-08", "scene": "P5", - "text": "我把四章的代码逐一量过:整个程序从一百四十行出头," + "text": "我把四个版本的代码逐一量过:整个程序从一百四十行出头," }, { "id": "p5-09", @@ -754,15 +764,10 @@ "scene": "P5", "text": "骨架一字未改:调模型,看回答里有没有工具调用,执行,填回结果。" }, - { - "id": "p5-12", - "scene": "P5", - "text": "变的只有「执行」那一步怎么写——" - }, { "id": "p5-13", "scene": "P5", - "text": "从写死一个命令,到查一张表,到先过一道闸门,到交给一排插口。" + "text": "变的只有「执行」那一步:从写死命令,到查表,到闸门,到一排插口。" }, { "id": "p5-14", @@ -804,21 +809,11 @@ "scene": "P6", "text": "而是因为有人在它周围,搭了这几层结构。" }, - { - "id": "p6-03", - "scene": "P6", - "text": "循环给它手脚,分发表给它工具,闸门守着底线,插口留给你发挥。" - }, { "id": "p6-04", "scene": "P6", "text": "这几层结构不神秘,加起来两百多行,一个下午能读完。" }, - { - "id": "p6-05", - "scene": "P6", - "text": "学会给 Harness 做加减法,这本身就是一门手艺。" - }, { "id": "p6-06", "scene": "P6", @@ -829,9 +824,14 @@ "scene": "P6", "text": "教学代码来自开源实现,行数均为实测,链接在简介。" }, + { + "id": "p6-05", + "scene": "P6", + "text": "学会给 Harness 做加减法,这本身就是一门手艺。" + }, { "id": "p6-08", "scene": "P6", - "text": "下期,拆它怎么安排自己看到的东西:计划写在哪,活儿怎么分出去。" + "text": "下期一个反直觉的事实:它这一轮能看见什么,从来不是它自己说了算。" } ] diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md index a248cc3b..d25700c5 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md @@ -7,7 +7,9 @@ > > **字数是硬约束**:`chars_per_min = 280` 是**含停顿的等效口径**(实测纯语速 301 字/分, > 停顿开销另占约 1 分钟)——EP1 用它预测成片 14:01 只差 1%。故 14 分钟 ≈ 3900 字。 -> 各幕字数预算:P0 200 · P1 780 · P2 760 · P3 740 · P4 800 · P5 400 · P6 190。 +> 各幕字数预算(2026-08-28 评审改造后重排):P0 280 · P1 790 · P2 760 · P3 725 · P4 890 · P5 405 · P6 180。 +> P0 上浮吸收官方脚手架赌注三句,P4 上浮吸收退出码陷阱三句;P3 在补入沙箱四句与分类器成绩单两句的 +> 同时净减 17 字(删掉六句咏叹与四处同义复述),全片净 +46 字。 ## P0 你在当那个中间人 @@ -133,7 +135,7 @@ - [p3-10] 第二道是规则匹配,管「看情况」的操作: - [p3-11] 读写工作目录之外的东西,或者命令里带着删除、改权限这类动作。 - [p3-12] 第三道就是问你:画面停下来,把工具名和参数摆给你看,等你点头。 -- [p3-14] 教学版自己承认:这张表只是字符串匹配,换个拼法就绕过去。 +- [p3-14] 教学版自己承认:那张拒绝表只是字符串匹配,换个拼法就绕过去。 - [p3-15] 它告诉你闸门装在哪儿,不替你把门守住。 > 金句卡(serif):「它告诉你闸门装在哪儿,不是替你把门守住。」(与 p3-15 音画同句) @@ -190,8 +192,7 @@ - [p4-17] 第三个,工具执行完、还没进下一轮之前:收尾的副作用挂这儿。 - [p4-18] 第四个,循环准备停机之前。这个插口最有权力: - [p4-19] 它返回一句话,这句话就被当成新输入塞回去,循环继续转。 -- [p4-20] 四个插口覆盖一整轮:进来、动手前、动手后、结束前, -- [p4-21] 而循环只负责在这四个点上喊一声。 +- [p4-20] 四个插口覆盖一整轮,循环只在这四个点上喊一声。 - [p4-22] 有句话我很喜欢:这个循环是故意保持无聊的。 > 金句卡(serif):「这个循环是故意保持无聊的。」 @@ -201,6 +202,9 @@ - [p4-25] 处理器也不只是跑脚本,还能让小模型单轮判决。 - [p4-27] 表态的契约值得单独记:沉默,不等于批准—— - [p4-28] 不吭声的意思是「我不作决定」,流程照走。 +- [p4-28a] 反过来,想真拦住只有一个硬信号;写错成惯用的失败码, +- [p4-28b] 闸门不响、动作照跑——静默失效。 +- [p4-28c] 第一次给循环挂扩展的人,几乎都栽在这一脚上。 - [p4-29] 插口上的函数说「这个我批了」,就真的放行吗?不。 - [p4-30] 它的放行,仍要穿过后面的拒绝与询问两站。 - [p4-31] 方向是单向的:扩展点能加限制,不能解除限制。 @@ -224,15 +228,14 @@ - [p5-02] 第一层,一个循环:反复问模型,替它执行,把结果搬回来。 - [p5-03] 第二层,一张分发表:让工具可以随便加。 - [p5-04] 第三层,三道闸门:让危险的事在执行之前被拦住。 -- [p5-05] 官方给 Harness 的定义正好四件:循环、工具、上下文管理、护栏。 +- [p5-05] 回到官方那四件:循环、工具、上下文管理、护栏。 - [p5-06] 这集填上了三件,上下文管理那格先空着,留到后面拆。 - [p5-07] 这不是我的说法,是可以数出来的。 -- [p5-08] 我把四章的代码逐一量过:整个程序从一百四十行出头, +- [p5-08] 我把四个版本的代码逐一量过:整个程序从一百四十行出头, - [p5-09] 长到两百五十多行,长了八成; - [p5-10] 而那个循环函数,一直在二十到二十八行之间。 - [p5-11] 骨架一字未改:调模型,看回答里有没有工具调用,执行,填回结果。 -- [p5-12] 变的只有「执行」那一步怎么写—— -- [p5-13] 从写死一个命令,到查一张表,到先过一道闸门,到交给一排插口。 +- [p5-13] 变的只有「执行」那一步:从写死命令,到查表,到闸门,到一排插口。 - [p5-14] 同一个位置,换了四次写法。 > 金句卡(serif):「骨架一字未改,变的只有『执行』那一步怎么写。」 @@ -254,9 +257,8 @@ - [p6-01] 它敢在你的电脑上动手,不是因为它足够聪明, - [p6-02] 而是因为有人在它周围,搭了这几层结构。 -- [p6-03] 循环给它手脚,分发表给它工具,闸门守着底线,插口留给你发挥。 - [p6-04] 这几层结构不神秘,加起来两百多行,一个下午能读完。 -- [p6-05] 学会给 Harness 做加减法,这本身就是一门手艺。 - [p6-06] 本片机制依据官方文档,取数2026年8月,以官方最新表述为准。 - [p6-07] 教学代码来自开源实现,行数均为实测,链接在简介。 -- [p6-08] 下期,拆它怎么安排自己看到的东西:计划写在哪,活儿怎么分出去。 +- [p6-05] 学会给 Harness 做加减法,这本身就是一门手艺。 +- [p6-08] 下期一个反直觉的事实:它这一轮能看见什么,从来不是它自己说了算。 diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md index e23b8423..520b9612 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md @@ -6,24 +6,27 @@ > `mech` 石青(外挂机制)· `deny` 警示红(拒绝)。 > **镜号必须与 `scenes/*.tsx` 里 `` 逐字一致**(抽帧 QA 对照用)。 > -> 注:p3-22 与 p4-26 在定稿时删除,句号留空档(不重编号,保 TTS 缓存);区间按 narration.json -> 的**实际顺序**展开,故 `p3-20..24` 覆盖 20/21/23/24 四句。 +> 注:句号留空档是常态(不重编号,保 TTS 缓存)——定稿期删了 p3-22 / p4-26,评审改造期又删了 +> p1-07 / p2-04 / p3-05 / p3-13 / p3-16..19 / p3-21 / p3-27 / p3-33 / p4-21 / p5-12 / p6-03; +> 新增句一律用字母后缀(p0-03a..c / p1-12a..b / p3-19a..d / p3-31a..b / p4-28a..c)。 +> 区间按 narration.json 的**实际顺序**展开,故 `p3-20..24` 覆盖 20/23/24 三句, +> `p6-06..08` 覆盖重排后的 06/07/05/08 四句(P6 改序:免责两句 → 金句 → 预告)。 ## P0 你在当那个中间人 | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 0-A | p0-01..02 | 全屏终端窗口(`panel` 底 + `panelBorder` 框),顶栏三个灰点。命令打完光标变灰凝住;右侧对话框浮出 | 终端打字机(每字 2 帧);命令打完后光标**停止闪烁并变灰**,画面凝住 0.6s;p0-02 三轮「复制→粘贴→回车→回贴」搬运弧线**加速**塞满灰色残影(节奏比旧版快一倍) | -| 0-B | p0-03..05 | 全部搬运残影瞬间收束成一条外框线,包住一枚「模型」内核——**命名帧**:外框即Harness | 外框自四面向内合拢包住内核(spring);「Harness」二字落框(serif 大字),英文 agentic harness 进角标;p0-05 官方引文条压上("Claude Code is the harness, Claude is the model" 中英并列淡入) | -| 0-C | p0-06..07 | Harness供给图:外框上长出五根辐条(文件 / 命令 / 权限 / 记忆 / 护栏),内侧连着模型内核 | p0-06 五根辐条逐根点亮(`mech` 辉光各 8 帧);「记忆」那根先灰并浮「后面拆」小标;p0-07 外框整体轻旋一次,片名标题卡压入(`core` 色细线自中心向两侧生长) | +| 0-B | p0-03..05 | 全部搬运残影瞬间收束成一条外框线,包住一枚「模型」内核——**命名帧**:外框即Harness。p0-03a..c 期间底部(bottom:210,避让字幕带)浮出**官方赌注卡**:中文引句 +双分数条 | p0-03a 赌注卡自底浮出(`FadeUp`);p0-03b 两条 `core` 横条在 320px 轨道上 `interpolate` 增长(0→22% / 0→49%),mono 角标「SWE-bench Verified 500 题 · 同脚手架代际 22%→49% · 官方自报 2025-01-06」;p0-03c 分数条定格并压「你的力气 = 它的分数」;外框合拢 spring **改锚 p0-04**(「名字就叫」句才落框,消除头空转);「Harness」二字落框(serif 大字),英文 agentic harness 进角标;p0-05 官方引文条压上("Claude Code is the harness, Claude is the model" 中英并列淡入) | +| 0-C | p0-06..07 | Harness四件套图:外框上长出**四根辐条**(循环 / 工具 / 上下文管理 / 护栏),内侧连着模型内核。辐点均布(`fx = CX − 225 + i*150`) | p0-06 四根辐条逐根点亮(`mech` 辉光各 8 帧),副标依次「问模型·执行·填回」/「查表分发」/ 灰置 +「后面单独拆」/「闸门·沙箱·插口」;「上下文管理」那根**先灰**(与 5-A 标尺空格、p5-06 承诺同构);p0-07 外框整体轻旋一次,片名标题卡压入(`core` 色细线自中心向两侧生长) | ## P1 一个循环,就是全部 | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| -| 1-A | p1-01..07 | **环形循环**(全片视觉锚):`core` 色闭合轨道居中,轨道上四个节点「问模型 / 看回答 / 执行工具 / 填回结果」。右侧分出一支「停机」出口 | 轨道用 `interpolate` 描线成形(0→1,1.2s);一个 `core` 光点沿轨匀速巡游(周期 2.5s);讲到「有」时工具节点 `mech` 辉光脉冲一次并让光点继续,讲到「没有」时光点滑出到「停机」出口并定格 | +| 1-A | p1-01..06 | **环形循环**(全片视觉锚):`core` 色闭合轨道居中,轨道上四个节点「问模型 / 看回答 / 执行工具 / 填回结果」。右侧分出一支「停机」出口 | 轨道用 `interpolate` 描线成形(0→1,1.2s);一个 `core` 光点沿轨匀速巡游(周期 2.5s);讲到「有」时工具节点 `mech` 辉光脉冲一次并让光点继续,讲到「没有」时光点滑出到「停机」出口并**定格收镜**(原 p1-07 已删,语义收在这一格上) | | 1-B | p1-08..12 | 环形循环缩至左侧 40%,右侧展开五步编号列表 + 一个 `messages[]` 面板 | 五步逐句点亮(每句一条,`FadeUp` 12px);每点亮一步,`messages[]` 面板**长高一格**并压入一个色块(用户句=dim / 模型回答=core / 工具结果=mech);第五步点亮后一条弧线从列表尾弹回第二步 | -| 1-C | p1-13..16 | 全屏代码卡:`agent_loop` 的真实骨架(mono,约 12 行精简版),右下角计数「23」 | 代码逐行渲染(每行 3 帧);「二十三行」时行号列整体 `core` 辉光一次,计数器从 0 滚动到 23;p1-15/16 时画面左右分屏——左「模型:决定」右「脚手架:执行」,中间一条竖线 | +| 1-C | p1-12a..p1-16 | 全屏代码卡:`agent_loop` 的真实骨架(mono,约 12 行精简版),右下角计数「23」。卡眉挂一条**来源标签条**「开源最小实现 · 照着同一套机制搭的」 | p1-12a 标签条自卡眉滑入(`mech` 描边,无具名信息)→ p1-12b 右侧浮出「对照对象:真实产品」半亮列;代码逐行渲染(每行 3 帧);「二十三行」时行号列整体 `core` 辉光一次,计数器从 0 滚动到 23;p1-15/16 时画面左右分屏——左「模型:决定」右「脚手架:执行」,中间一条竖线 | | 1-D | p1-17..24 | 上半:模型回答的字符流从左向右逐字流出,其中一段 `mech` 色的「工具调用」块提前出现;下半:一个「停止原因」标记牌仍显示「进行中」,滞后一拍才翻牌 | 字符流以 12 字/秒流动;工具调用块出现时 `mech` 辉光;标记牌**延迟 25 帧**才翻转(视觉化「不可靠」);p1-22 时标记牌打上 `deny` 色斜叉;p1-24 金句卡 `serif` 居中淡入 | | 1-E | p1-25..29 | **三相环升级**:主环上浮现三个相位标签(收集 / 行动 / 验证)交融旋转;一只「手」图标随时可插入环上任意点;右侧十格抽屉墙以角标清单形式一闪 | 三个相位标签沿环依次点亮并**保持同时可见**(交融感,非硬阶段);p1-27 手图标落向环上一节点、环上光点被拨偏一档(人可打断);p1-28/29 十格抽屉墙快速亮起(20ms/格)后整体退至 40% 亮度、State 字段清单进角标 | | 1-F | p1-30..32 | 环形循环的「停机」出口分岔成五条细支线,各标一个退出原因;随后五条支线淡为 `dim`,只留主环 | 支线逐条以 `interpolate` 描线(每句一条);p1-32 时五条支线亮度降到 30% 并后移,主环 `core` 亮度不变——「它们是保护装置,不是骨架」 | @@ -32,7 +35,7 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| -| 2-A | p2-01..04 | 环形循环留在左上角(缩小但**同色同线宽**)。主体是终端:模型的意图气泡「读这个文件」旁边,笨拙地拼出一条命令 | 意图气泡与命令行之间画一条「翻译」箭头,箭头上叠一个 `deny` 色的小计数「+1 层」;p2-02 打出两条拼接命令(读/写各一条);p2-04 时命令里一个字符被高亮成 `deny` 并抖动(拼错) | +| 2-A | p2-01..03 | 环形循环留在左上角(缩小但**同色同线宽**)。主体是终端:模型的意图气泡「读这个文件」旁边,笨拙地拼出一条命令 | 意图气泡与命令行之间画一条「翻译」箭头,箭头上叠一个 `deny` 色的小计数「+1 层」;p2-02 打出两条拼接命令(读/写各一条);p2-03 尾(`+22` 帧)命令里一个字符被高亮成 `deny` 并抖动(拼错),角标「多一层翻译:费 token,还容易拼错」——原 p2-04 已删,语义由角标承载 | | 2-B | p2-05..06 | 五张工具卡横排弹出(panel 底 + 编号,反枚举)+ 卡下官方五类分区标注;两个虚线空槽(执行/网页——官方地图另有) | 卡片 spring 弹入(仅编号染 mech);分区小字浮现;两空槽淡入(`panelBorder` 虚线);角标「官方内置五类:文件/搜索/执行/网页/代码智能」 | | 2-C | p2-07..10 | **字典分发表**:两列表格,左列工具名(mono),右列处理函数名。旁边一个前台号码簿的极简图形 | p2-07 表格框线描出;p2-08 逐行填入(每行 4 帧);p2-09 一个「来电」光点从左飞入命中某一行 → 整行推入 `mech` 辉光 → 右列函数名弹出;p2-10 表格底部**多出一行空槽**,一条新映射滑入落槽 | | 2-D | p2-11..13 | 左右并置两段代码(前后两版),仅执行那一行不同 | 两段代码同时淡入,**逐行做同色对齐比对**;唯一不同的那一行左侧打 `mech` 竖标并整行高亮,其余行降到 40% 亮度;p2-13 时左上角环形循环 `core` 脉冲一次(强调"它没动") | @@ -45,13 +48,14 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| -| 3-A | p3-01..06 | 五张工具卡回归,其中四张外面套着一个 `mech` 色的「工作目录」框,跑命令那张**在框外** | p3-02 框线描出并把四张卡收进去,第五张卡留在框外并轻微抖动;p3-04 该卡吐出一条 `deny` 色命令,命令文字放大并使画面整体压暗一档;p3-05 环形循环的执行节点照常亮起("老老实实替它执行"的反讽);p3-06 一道竖线从顶部落下 | +| 3-A | p3-01..06 | 五张工具卡回归,其中四张外面套着一个 `mech` 色的「工作目录」框,跑命令那张**在框外** | p3-02 框线描出并把四张卡收进去,第五张卡留在框外并轻微抖动;p3-04 该卡吐出一条 `deny` 色命令,命令文字放大并使画面整体压暗一档,该句尾(`+16` 帧)环形循环的执行节点照常亮起("循环照跑"的反讽——原 p3-05 已删,动效锚点改挂 p3-04 尾);p3-06 一道竖线从顶部落下 | | 3-B | p3-07..09 | **闸门路由**成形:请求从左侧进入,前方三道竖闸依次落下(1 号 `deny` 描边、2 号 `mech`、3 号 `mech` 虚线) | 三道闸门以 `spring` 自上落下(每句一道);p3-08 第一道闸门上浮出四个禁令词;p3-09 一个请求光点撞上第一道闸门被**反弹回左侧**并碎成 `deny` 色粒子 | -| 3-C | p3-10..13 | 第二、三道闸门工作:一个请求穿过一道被标记,停在第三道前等待;另一个请求三道全过直接抵达执行口 | p3-10/11 请求光点穿过一闸后头顶浮出「看情况」标签;p3-12 第三道闸门前画面**整体降速并压暗**,弹出「工具名 + 参数」审批卡与 y/N 光标;p3-13 另一条通路上一个光点畅通无阻直达执行口,并在轨迹上留下 `core` 尾迹 | -| 3-D | p3-14..19 | 拒绝表代码卡(mono,七个字符串)居中;随后表下方浮出原话引用 | p3-15 代码卡逐行渲染;p3-16/17 表的边框由 `deny` 变为 `dim` 虚线("示意"而非"边界"的视觉降级);p3-18 表右侧生成三条变体写法,逐条**绕过**表框飞向执行口;p3-19 金句卡 `serif` 居中 | -| 3-E | p3-20..24 | 四个结果徽标呈四宫格:放行(`core`)、拒绝(`deny`)、问你(`mech`)、不表态(`dim` 描边) | p3-21 前三格先亮(对应三道闸门),第四格空着并有呼吸描边;p3-23 第四格亮起「不表态」;p3-24 从第四格拉出一条弧线**回连到「问你」格**,弧线上压「兜底」二字 | -| 3-F | p3-25..29 | **官方求值顺序流水线**:拒绝 → 询问 → 放行 三站闸门横排,一枚请求光点沿轨道行进 | 三站以 spring 落下(顺序点亮,每站 7 帧);「头一个命中,就出局」横幅压上;p3-27 光点在拒绝站被截获、`deny` 辉光 + 「出局」标签;p3-28 右下浮「裸名 deny → 整件工具从模型身上消失」(Bash 加删除线) | -| 3-G | p3-30..35 | **auto 分类器视野分屏**:五行记录自上而下滚入(辩解 / 工具结果 / 调用描述 / 用户消息 / 裸命令),前三行被划除,末两行金色高亮 | p3-31 五行逐条滚入;p3-32 前三行依次划除并各浮移除理由;p3-33 末两行染 `core` 高亮 + 「只看这两条」;p3-34 反例帧:一条伪装「用户早就批准了」的文本飞向视野、被 `deny` 色边界弹回;p3-35 金句压底 + 遥测角标(93%,官方 2026-03) | +| 3-C | p3-10..12 | 第二、三道闸门工作:一个请求穿过一道被标记,停在第三道前等待;另一个请求三道全过直接抵达执行口 | p3-10/11 请求光点穿过一闸后头顶浮出「看情况」标签;p3-12 第三道闸门前画面**整体降速并压暗**,弹出「工具名 + 参数」审批卡与 y/N 光标;同句尾(`+25` 帧)另一条通路上一个光点畅通无阻直达执行口,并在轨迹上留下 `core` 尾迹(原 p3-13 已删——「弃权不等于放行」由 3-E 的 p3-24 单独承载,此处不再预支) | +| 3-D | p3-14..15 | 拒绝表代码卡(mono,七个字符串)居中;边框降级为「示意」;金句卡改**底部叠加**(不整屏替换,为下一镜留画布) | p3-14 代码卡逐行渲染;同句 `+14` 帧表的边框由 `deny` 变 `dim` 虚线("示意"而非"边界"的视觉降级),`+30` 帧表右侧生成三条变体写法逐条**绕过**表框飞向执行口;p3-15 起 `+18` 帧金句卡 `serif` 以底部 Panel 浮出、hold 70 帧淡出 | +| 3-D2 | p3-19a..19d | **沙箱横切面**(新镜,回答 3-D 金句抛出的问题):代码卡缩至左侧 55%,右侧画一圈圆角实心壳(`mech` 描边 4px、rx=26、辉光)罩住「跑命令 + 子进程树」;壳上下两道边界带 | p3-19a 壳自四周合拢包住进程树(spring);p3-19b 上边界带「文件:只许工作区」与下边界带「网络:只走代管口子」各闪一次;p3-19c 上一镜生成的三条变体改为**飞向壳壁被弹回**(复用 3-D 轨迹,末端 8 帧反弹),拆掉任一道墙的反例:密钥箭头飞出边界(`deny`);p3-19d 压角标「Seatbelt / bubblewrap + socat · 权限提示 −84%(官方工程博客,取数 2025-10)」 | +| 3-E | p3-20..24 | 四个结果徽标呈四宫格:放行(`core`)、拒绝(`deny`)、问你(`mech`)、不表态(`dim` 描边) | p3-20 前三格先亮(对应三道闸门),第四格空着并有呼吸描边;p3-23 第四格亮起「不表态」;p3-24 从第四格拉出一条弧线**回连到「问你」格**,弧线上压「兜底」二字 | +| 3-F | p3-25..29 | **官方求值顺序流水线**:拒绝 → 询问 → 放行 三站闸门横排,一枚请求光点沿轨道行进 | 三站以 spring 落下(顺序点亮,每站 7 帧);「头一个命中,就出局」横幅压上;p3-26 尾(`+30` 帧)光点在拒绝站被截获、`deny` 辉光 + 「出局」标签(原 p3-27 已删,锚点前挂);p3-28 右下浮「裸名 deny → 整件工具从模型身上消失」(Bash 加删除线) | +| 3-G | p3-30..35 | **auto 分类器视野分屏**:五行记录自上而下滚入(辩解 / 工具结果 / 调用描述 / 用户消息 / 裸命令),前三行被划除,末两行金色高亮。右上加**成绩单卡**(两段误杀率对照) | p3-31 五行逐条滚入 + 遥测角标(93%,官方 2026-03);p3-31a 右上浮出「审判者的成绩单」Panel;p3-31b 220px 轨道上一条 `deny`→`core` 色条从 8.5% 宽收到 0.4% 宽,「快筛 / 复核」两标签随动点亮,角标追加「Stage1 FPR 8.5% → Stage2 0.4%(官方工程博客,取数 2026-03)」;p3-32 前三行依次划除并各浮移除理由,同句 `+20` 帧末两行染 `core` 高亮 +「只看这两条」(原 p3-33 已删,锚点合并);p3-34 反例帧:一条伪装「用户早就批准了」的文本飞向视野、被 `deny` 色边界弹回;p3-35 金句压底 | ## P4 挂在循环上,不写进循环里 @@ -61,9 +65,9 @@ | 4-B | p4-05..07 | 退化的循环代码卡:循环体内被塞进五行杂活 | 五行以每句 2 行的节奏插入,每插入一行代码卡**整体下移**并把最外层的 `while` 挤出可视区;p4-06 结束时代码卡边框变 `deny` 虚线;p4-07 金句卡覆盖上层 | | 4-C | p4-08..12 | 代码卡收回,五行杂活被「拔」出循环、变成五张回调卡浮在环外;环恢复原线宽 | p4-08 五行代码逐行飞出环外并变形为卡片(0.5s 形变);p4-09/10 环外浮出「时机 → 函数列表」两列表格;p4-11/12 环与卡片之间出现四个插座图形,一张卡片「啪」地插入(`spring` 过冲 + 插入瞬间 `mech` 闪一帧) | | 4-D | p4-13..19 | **插槽注册板**:环形循环外围四个插槽,按一整轮的时间顺序分布在环的四个方位 | 四个插槽逐句亮起并各插入对应回调卡:p4-14 入口槽(补背景信息的卡片飞入并在消息上加一小块 `mech` 补丁);p4-15/16 执行前槽——**P3 的三道闸门整体缩小、平移进这个槽**(跨幕视觉呼应),环上原本的检查标记同时消失;p4-17 执行后槽;p4-18/19 停机前槽亮 `core`,卡片返回一句话 → 一条回流箭头把它送回环的入口,环重新转起来 | -| 4-E | p4-20..22 | 四个插槽同时点亮,环上标出四个时机点;环本身刻意**不加任何装饰** | 四点沿环依次脉冲一圈(顺时针,各 8 帧);p4-21 环上只浮出四个极简的喇叭图标("只喊一声");p4-22 金句卡;金句期间环继续匀速转动,不做任何强调动效——用"无动效"表达"故意保持无聊" | +| 4-E | p4-20..22 | 四个插槽同时点亮,环上标出四个时机点;环本身刻意**不加任何装饰** | p4-20 四点沿环依次脉冲一圈(顺时针,各 8 帧),同句尾环上浮出四个极简的喇叭图标("只喊一声"——原 p4-21 已并入 p4-20);p4-22 金句卡;金句期间环继续匀速转动,不做任何强调动效——用"无动效"表达"故意保持无聊" | | 4-F | p4-23..25 | **31 事件 × 三层嵌套**(官方口径):外层会话框(一次)套中层回合框(×N)套内层工具调用链(工具前→执行→工具后→整批落定);右栏异步事件网格;右下计数徽章 | 外层成形→中层边框闪两下浮 ×N→内层虚线框内一个光点沿四节点链循环跑(80 帧一圈);右栏 6 个异步事件逐条打出;计数从 0 滚到 31(官方文档事件表逐行计数) | -| 4-G1 | p4-27..31 | **六道闸门流水线**(官方 SDK 权限判定图):hook/deny/ask/settings/mode/默认 六站横排,两端 Execute/Blocked 终点 | 轨道描出→一枚「我批了」光点出发→行至 deny 站被截入 Blocked(`deny` 辉光+冲击波);p4-31 切全放行模式重跑、光点仍在 deny 站被截 + 「全放行模式也一样:拒绝压得住」 | +| 4-G1 | p4-27..31 | **六道闸门流水线**(官方 SDK 权限判定图):hook/deny/ask/settings/mode/默认 六站横排,两端 Execute/Blocked 终点。同一轨道上跑**三枚球**做对照(沉默 / 假拦截 / 我批了) | p4-27 起(`+6` 帧)轨道描出,消除头空转;p4-28 球 A(`dim`,标「沉默」)从 hook 站**无扰动通过**、继续走 deny/ask 站(沉默≠批准,照走正常流程);p4-28a/b 球 B(`deny`,标「我拦了」)全速穿过全部六站直达 Execute,到达瞬间标签翻成「静默失效」;p4-28c 压一行 mono 角标「唯一凭退出码单独阻断的是 exit 2;exit 1 = 非阻断错误,动作照跑」;p4-29/30 球 C(`core`,标「我批了」)行至 deny 站被截入 Blocked(`deny` 辉光+冲击波);p4-31 切全放行模式重跑、球 C 仍在 deny 站被截 + 「全放行模式也一样:拒绝压得住」 | | 4-G2 | p4-32..34 | **印章对撞**(保留高潮母题):「我批了」印章 vs 「禁止/询问」印章 + 单向箭头 | 印章落下对撞、持续抵抗抖动;单向箭头(只允许「加限制」方向);金句卡「扩展点能加限制,不能解除限制」收口 | | 4-H | p4-35..37 | 「别停」插槽与环的一段形成小闭环,反复自激;随后一枚标记落下把闭环打断 | p4-36 小闭环连转三圈,每圈提速一档、边缘 `deny` 色渐强(自激失控感);p4-37 一枚 `core` 色方形标记从上落下嵌入闭环,第四圈行进到标记处被**截断**,整体归于静止 | @@ -71,14 +75,14 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| -| 5-A | p5-01..06 | 四层横向卡片:循环(`core` 实心)/ 分发表 / 闸门 / 插槽(后三者 `mech` 描边);卡片上方 p5-05 落下**官方四件套标尺**(循环 / 工具 / 上下文管理 / 护栏) | 四张卡逐句自下弹入并水平排开;p5-05 标尺自上淡入落位;p5-06 三根竖连线把本集三层接到对应格(循环↔循环、分发表↔工具、插口↔护栏),「上下文管理」格虚线空置 + 「空着 · 后面拆」小标;随后第一张卡**留在原地并加实底**,后三张同时上浮 8px 并转为半透明——"骨架 vs 挂件"的视觉分层 | +| 5-A | p5-01..06 | 四层横向卡片:循环(`core` 实心)/ 分发表 / 闸门 / 插槽(后三者 `mech` 描边);卡片上方 p5-05 落下**官方四件套标尺**(循环 / 工具 / 上下文管理 / 护栏,与 0-C 四辐条同一张清单) | 四张卡逐句自下弹入并水平排开;p5-05 标尺自上淡入落位(**回指** 0-C 已立的定义,不再念「正好四件」);p5-06 三根竖连线把本集三层接到对应格(循环↔循环、分发表↔工具、插口↔护栏),「上下文管理」格虚线空置 + 「空着 · 后面拆」小标(与 0-C 灰置那根辐条首尾咬合);随后第一张卡**留在原地并加实底**,后三张同时上浮 8px 并转为半透明——"骨架 vs 挂件"的视觉分层 | | 5-B | p5-07..10 | **四级台阶**:四段柱体高度递增(141/191/241/255),每根柱子内部有一段等高的 `core` 色块 | p5-08/09 四根柱体自左向右逐根升起(`spring`),柱顶数字滚动到位;p5-10 时四根柱子里的 `core` 色块**同时描出**——四段高度肉眼相同且色值相同,柱体其余部分降到 30% 亮度 | -| 5-C | p5-11..14 | 环形循环回到画面中央(第五次出现,仍完全同色同线宽),执行节点位置换过四次写法的四个标签轮播 | p5-11/12 环上四个节点依次脉冲一圈;p5-13/14 执行节点上方的标签以 0.4s 间隔翻牌四次(写死命令 → 查表 → 闸门 → 插槽),**环本身一帧未变**;末尾金句卡 | +| 5-C | p5-11..14 | 环形循环回到画面中央(第五次出现,仍完全同色同线宽),执行节点位置换过四次写法的四个标签轮播 | p5-11 环上四个节点依次脉冲一圈;p5-13/14 执行节点上方的标签以 0.4s 间隔翻牌四次(写死命令 → 查表 → 闸门 → 插槽),**环本身一帧未变**(原 p5-12 已并入 p5-13,翻牌起点改挂 p5-13);末尾金句卡 | | 5-D | p5-15..19 | 回到 P0 的终端画面(同构图),但这次命令自己跑了起来、输出自动回流;末尾英文原句金句卡 | p5-16 P0 的灰色搬运轨迹以 `core` 色重画一次(这次是自动的);人形剪影淡出;p5-18 四层结构在终端外围合拢成一个壳;p5-19 英文原句 `serif` 与中文并列淡入 | ## P6 收尾 | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| -| 6-A | p6-01..04 | 壳的四层分别点亮并各配一句短标签(手脚 / 工具 / 底线 / 发挥) | 四层以每句一层的节奏点亮,点亮时对应标签 `FadeUp`;四层齐亮后整体轻微收拢一次(呼吸) | -| 6-B | p6-05..08 | 信源卡四行(官方文档+取数日期 / 工程博客 / 源码分析已逐处标注 / 数字均为实测口径)+ 版本护栏行 → 系列身份卡 + **下期预告卡**(标题只在画面;series.json 派生硬编码,规则 8 对账) → **渐黑** | 信源卡逐行浮现(mono 小字);系列身份卡 `serif` 淡入;下期卡 `panel` 底描边框浮现(「下期 · 规划层」+ 标题);**渐黑窗口从本 beat 的总时长推导**(`beatDurationInFrames`,红线四),末 1.2s 线性压暗到全黑 | +| 6-A | p6-01..04 | 壳的四层分别点亮并各配一句短标签(手脚 / 工具 / 底线 / 发挥) | 四层点亮锚点改为 p6-01 / p6-02 / p6-04 / p6-04+8(原 p6-03 已删,第三、四层在 p6-04 上错开 8 帧落位),点亮时对应标签 `FadeUp`;四层齐亮后整体轻微收拢一次(呼吸) | +| 6-B | p6-06..08 | **句序已重排**(区间按 narration.json 实际顺序展开:p6-06 免责 → p6-07 免责 → p6-05 金句 → p6-08 预告)。信源卡四行(官方文档+取数日期 / 工程博客 / 源码分析已逐处标注 / 数字均为实测口径)+ 版本护栏行 → 金句压系列身份卡 → **下期预告卡**(标题只在画面;series.json 派生硬编码,规则 8 对账) → **渐黑** | p6-06/07 信源卡逐行浮现(mono 小字);p6-05 系列身份卡 `serif` 淡入并把金句压在卡上方(免责文案前移后,情绪高点与转化动作不再被隔开);p6-08 下期卡 `panel` 底描边框浮现(「下期 · 规划层」+ 标题);**渐黑窗口从本 beat 的总时长推导**(`beatDurationInFrames`,红线四),末 1.2s 线性压暗到全黑 | diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json index b28a02e8..ea3d6dd6 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json @@ -12,72 +12,72 @@ { "id": "p0-04", "scene": "P0", - "text": "它干活有个铁律:读过的每个文件、跑过的每条命令、你说的每句话," + "text": "铁律是:读过的每个文件、跑过的每条命令、你说的每句话,全都随身带着——" }, { "id": "p0-05", "scene": "P0", - "text": "全都要随身带着,每问一次模型,就从第一个字重新看一遍。" + "text": "每问一次模型,就从第一个字重新看一遍。窗口就这样一层层被垫高。" }, { - "id": "p0-06", + "id": "p0-05a", "scene": "P0", - "text": "你让它读一个大文件,再读三十个小文件,再跑二十条命令——" + "text": "而且开局就不空——你还没敲第一个字,窗口里已躺着好几样东西。" }, { - "id": "p0-07", + "id": "p0-05b", "scene": "P0", - "text": "这些东西一层层堆上去,窗口总有装满的一刻。" + "text": "官方给过一份示意账:光基本设定,就占四千多字。" }, { - "id": "p0-08", + "id": "p0-06", "scene": "P0", - "text": "装满那一刻,一次拒收,前面全白干。干了一小时,等于没干。" + "text": "垫到顶,就是开头那行报错。" }, { "id": "p0-09", "scene": "P0", - "text": "官方实测还补了一刀:窗口越长,它记得反而越不准——注意力被摊薄了。" + "text": "官方实测还补了一刀:窗口越长,它记得反而越不准。" }, { - "id": "p0-10", + "id": "p0-09a", "scene": "P0", - "text": "所以满了怎么办?直觉答案是删掉一点。" + "text": "原因不玄:每多一个字,要照顾的两两关系就多一圈。" }, { - "id": "p0-11", + "id": "p0-09b", "scene": "P0", - "text": "但删什么、先删谁——这里面全是工程。" + "text": "而注意力的总量是固定的——摊得越薄,看得越糊。" }, { - "id": "p0-12", + "id": "p0-09c", "scene": "P0", - "text": "删错了任务书,它忘了自己要干嘛;删错了回执,它对着空气发问。" + "text": "所以窗口再大,也不等于记性变好——能装,不等于能记。" }, { - "id": "p0-13", + "id": "p0-10", "scene": "P0", - "text": "这门课给的答案分两层,对应两种完全不同的心态。" + "text": "官方给 Harness 列的四件事里,有一件是上下文管理。" }, { - "id": "p0-14", + "id": "p0-11", "scene": "P0", - "text": "第一层承认会丢:窗口一定会满,那就把丢管起来——分级、有序、有保底。" + "text": "它分两半:安排它看什么,和装满了怎么办——今天拆后一半。" }, { - "id": "p0-15", + "id": "p0-13", "scene": "P0", - "text": "第二层保证不丢:另立一个不参与压缩的账本,重要的写进去就不出来。" + "text": "答案分两层,对应两种完全不同的心态。" }, { - "id": "p0-16", + "id": "p0-14", "scene": "P0", - "text": "两层咬合在一起,才是完整答案。先说第一层:怎么把「丢」管好,丢得体面。" + "text": "第一层承认会丢:窗口一定会满,那就把丢管起来——分级、有序、有保底。" }, { - "id": "p0-17", + "id": "p0-15", "scene": "P0", - "text": "提前说一句:这两层里所有的设计,都在回答同一个问题——什么值得留下。" + "text": "第二层保证不丢:另立一个不参与压缩的账本,重要的写进去就不出来。" }, { "id": "p1-01", @@ -87,7 +87,7 @@ { "id": "p1-02", "scene": "P1", - "text": "窗口满了,等于桌子满了。收拾桌子,教学版给出了四级办法。" + "text": "第一层要办的,就是把丢管好——收拾这张桌子,教学版给出了四级办法。" }, { "id": "p1-03", @@ -177,7 +177,7 @@ { "id": "p1-20", "scene": "P1", - "text": "记住这个次序感:先动最不心疼的,再动开始心疼的。这是全章的节拍。" + "text": "记住这个次序感:先动最不心疼的,再动开始心疼的。这是这一层的节拍。" }, { "id": "p2-01", @@ -419,10 +419,30 @@ "scene": "P4", "text": "所以需要另一层:不参与压缩的两条腿。第一条你写——就是项目里那个文件夹。" }, + { + "id": "p4-08a", + "scene": "P4", + "text": "这里要纠正一个流传很广的说法:里面的规则不是它的基本设定。" + }, + { + "id": "p4-08b", + "scene": "P4", + "text": "那是设定之后递进来的第一条普通消息——跟你说的话同一个身份。" + }, + { + "id": "p4-08c", + "scene": "P4", + "text": "官方原话:会读、会尽量照做,但不保证严格执行。" + }, + { + "id": "p4-08d", + "scene": "P4", + "text": "所以「写了它没听」不是故障——这层本来就只是建议。" + }, { "id": "p4-09", "scene": "P4", - "text": "四层拼接、越近工作目录越后读;单文件超四兆整份跳过,超两百行开始不听话。" + "text": "这些文件层层拼接,越靠近工作目录的越后读,超两百行就开始不老实。" }, { "id": "p4-10", @@ -467,7 +487,7 @@ { "id": "p4-18", "scene": "P4", - "text": "这个索引常驻在它的基本设定里——每次开工,扫一眼就知道自己有什么家底。" + "text": "这份索引不写在它的基本设定里——它垫在你开口之前,每次开工先扫一眼。" }, { "id": "p4-19", @@ -644,6 +664,16 @@ "scene": "P5", "text": "一天最多梦一次。有些事,就该趁夜深人静做——比如整理自己是谁。" }, + { + "id": "p6-07", + "scene": "P6", + "text": "本片以官方文档为主,取数2026年8月,以官方最新表述为准。" + }, + { + "id": "p6-08", + "scene": "P6", + "text": "涉及产品内部的部分,为第三方源码分析,片中已逐处标注。" + }, { "id": "p6-01", "scene": "P6", @@ -665,24 +695,29 @@ "text": "一套负责固执地记:一事一文件、索引常驻、先抢救再碎纸。" }, { - "id": "p6-05", + "id": "p6-04a", "scene": "P6", - "text": "官方还有一句话值得放在最后:这两条腿,都是上下文,不是闸门。" + "text": "再往前想一步:记忆这一层,押的赌注就是它记不住。" }, { - "id": "p6-06", + "id": "p6-04b", "scene": "P6", - "text": "记忆是建议,钩子才是规则——这是提示词工程和 Harness 工程的第一道分水岭。" + "text": "而赌注会过期。官方说过:新一代模型上,基本设定删了八成,评测没掉分。" }, { - "id": "p6-07", + "id": "p6-04c", "scene": "P6", - "text": "本片以官方文档为主,取数2026年8月,以官方最新表述为准。" + "text": "手写的规则清单,正在让位给它自己长的记忆。" }, { - "id": "p6-08", + "id": "p6-05", "scene": "P6", - "text": "涉及产品内部的部分,为第三方源码分析,片中已逐处标注。" + "text": "官方还有一句话值得放在最后:这两条腿,都是上下文,不是闸门。" + }, + { + "id": "p6-06", + "scene": "P6", + "text": "记忆是建议,钩子才是规则——写提示词和做 Harness 的分水岭。" }, { "id": "p6-09", @@ -692,6 +727,6 @@ { "id": "p6-10", "scene": "P6", - "text": "下期拆另一件事:活儿能不能不等你盯着才开工——后台、定时、替你按开始的那只手。下期见。" + "text": "下期往前推一步:它干活时没有钟——按下开始的那只手,是谁的?下期见。" } ] diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md index 60ba3b13..99b63647 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md @@ -6,7 +6,7 @@ > 不出现他集标题与顺序词。 > > 字数硬约束:280 字/分钟含停顿等效;窗口 [13.0, 14.6] → 精算 3640–4100 字。 -> 各幕字数预算:P0 260 · P1 560 · P2 600 · P3 420 · P4 700 · P5 700 · P6 480。 +> 各幕字数预算:P0 435 · P1 595 · P2 680 · P3 415 · P4 960 · P5 595 · P6 355。 ## P0 一次拒收 @@ -15,20 +15,20 @@ - [p0-01] 它正在干活,突然,停了。一个小时的活,一行报错,全部作废。 - [p0-02] 不是它不想干,是服务那边拒收了——理由直白:你随身带的,太大了。 -- [p0-04] 它干活有个铁律:读过的每个文件、跑过的每条命令、你说的每句话, -- [p0-05] 全都要随身带着,每问一次模型,就从第一个字重新看一遍。 -- [p0-06] 你让它读一个大文件,再读三十个小文件,再跑二十条命令—— -- [p0-07] 这些东西一层层堆上去,窗口总有装满的一刻。 -- [p0-08] 装满那一刻,一次拒收,前面全白干。干了一小时,等于没干。 -- [p0-09] 官方实测还补了一刀:窗口越长,它记得反而越不准——注意力被摊薄了。 -- [p0-10] 所以满了怎么办?直觉答案是删掉一点。 -- [p0-11] 但删什么、先删谁——这里面全是工程。 -- [p0-12] 删错了任务书,它忘了自己要干嘛;删错了回执,它对着空气发问。 -- [p0-13] 这门课给的答案分两层,对应两种完全不同的心态。 +- [p0-04] 铁律是:读过的每个文件、跑过的每条命令、你说的每句话,全都随身带着—— +- [p0-05] 每问一次模型,就从第一个字重新看一遍。窗口就这样一层层被垫高。 +- [p0-05a] 而且开局就不空——你还没敲第一个字,窗口里已躺着好几样东西。 +- [p0-05b] 官方给过一份示意账:光基本设定,就占四千多字。 +- [p0-06] 垫到顶,就是开头那行报错。 +- [p0-09] 官方实测还补了一刀:窗口越长,它记得反而越不准。 +- [p0-09a] 原因不玄:每多一个字,要照顾的两两关系就多一圈。 +- [p0-09b] 而注意力的总量是固定的——摊得越薄,看得越糊。 +- [p0-09c] 所以窗口再大,也不等于记性变好——能装,不等于能记。 +- [p0-10] 官方给 Harness 列的四件事里,有一件是上下文管理。 +- [p0-11] 它分两半:安排它看什么,和装满了怎么办——今天拆后一半。 +- [p0-13] 答案分两层,对应两种完全不同的心态。 - [p0-14] 第一层承认会丢:窗口一定会满,那就把丢管起来——分级、有序、有保底。 - [p0-15] 第二层保证不丢:另立一个不参与压缩的账本,重要的写进去就不出来。 -- [p0-16] 两层咬合在一起,才是完整答案。先说第一层:怎么把「丢」管好,丢得体面。 -- [p0-17] 提前说一句:这两层里所有的设计,都在回答同一个问题——什么值得留下。 ## P1 桌面的收拾法 @@ -36,7 +36,7 @@ > 角标:50 条 / 头 3 尾 47 · 最近 3 条完整保留 · 120 字阈值 - [p1-01] 先把画面换个说法:它随身的全部对话,就是一张会塞满的桌子。 -- [p1-02] 窗口满了,等于桌子满了。收拾桌子,教学版给出了四级办法。 +- [p1-02] 第一层要办的,就是把丢管好——收拾这张桌子,教学版给出了四级办法。 - [p1-03] 四级办法的原则只有一条:便宜的先来,贵的最后。 - [p1-04] 先干不用花钱的,实在不行才请人。你会看到这条原则贯穿到底。 - [p1-05] 第一级,裁中段。桌上的纸超过五十张,就只留开头三张和最近四十七张, @@ -54,7 +54,7 @@ - [p1-17] 这两级全是纯文本操作,一次模型都不用请,便宜到近乎免费。 - [p1-18] 官方文档的原话正好背书这个次序:先清掉旧的工具输出,不够再把整段对话摘要。 - [p1-19] 教学版的四级,就是官方这两级的细化。便宜先来、贵的殿后,方向一致。 -- [p1-20] 记住这个次序感:先动最不心疼的,再动开始心疼的。这是全章的节拍。 +- [p1-20] 记住这个次序感:先动最不心疼的,再动开始心疼的。这是这一层的节拍。 ## P2 大件入库与顺序论证 @@ -124,7 +124,11 @@ - [p4-06] 摘要没有做错什么——摘要的天性就是丢细节,保主干。 - [p4-07] 可有些细节,恰恰是主干。你的偏好就是你的偏好,缩不成一句概括。 - [p4-08] 所以需要另一层:不参与压缩的两条腿。第一条你写——就是项目里那个文件夹。 -- [p4-09] 四层拼接、越近工作目录越后读;单文件超四兆整份跳过,超两百行开始不听话。 +- [p4-08a] 这里要纠正一个流传很广的说法:里面的规则不是它的基本设定。 +- [p4-08b] 那是设定之后递进来的第一条普通消息——跟你说的话同一个身份。 +- [p4-08c] 官方原话:会读、会尽量照做,但不保证严格执行。 +- [p4-08d] 所以「写了它没听」不是故障——这层本来就只是建议。 +- [p4-09] 这些文件层层拼接,越靠近工作目录的越后读,超两百行就开始不老实。 - [p4-10] 一件事一个文件,开头三行登记:叫什么、一句话说明、属于哪类。 - [p4-11] 第二条腿它自己写:自动记忆按四类落在你的用户目录下,有门限。 - [p4-12] 记过的不再记——防重复这条保留:防止本子自己长胖。 @@ -133,7 +137,7 @@ - [p4-15] 怎么干活——反馈和规矩,「别造假数据」; - [p4-16] 在发生什么——项目背景,「这次重写是合规驱动的」; - [p4-17] 去哪儿找——线索和入口,「那个老 bug 记录在哪」。 -- [p4-18] 这个索引常驻在它的基本设定里——每次开工,扫一眼就知道自己有什么家底。 +- [p4-18] 这份索引不写在它的基本设定里——它垫在你开口之前,每次开工先扫一眼。 - [p4-19] 索引也有上限:最多两百行,超了就要整理。家底要薄,才有用。 - [p4-20] 取的时候分两条路。索引常驻是第一条,便宜、全天候。 - [p4-21] 第二条是按需取:每轮开始前,把最近对话和记忆清单一起发给一个小模型, @@ -181,13 +185,16 @@ > 画面:一句话合同金句卡 → 信源卡 → 系列身份卡 → 渐黑(末 beat 总时长推导)。 +- [p6-07] 本片以官方文档为主,取数2026年8月,以官方最新表述为准。 +- [p6-08] 涉及产品内部的部分,为第三方源码分析,片中已逐处标注。 - [p6-01] 会丢的放桌面,不许丢的放本子。 - [p6-02] 它不是记性好,是有两套东西在替它记。 - [p6-03] 一套负责体面地忘:分级收拾、先存再丢、压完往回捞; - [p6-04] 一套负责固执地记:一事一文件、索引常驻、先抢救再碎纸。 +- [p6-04a] 再往前想一步:记忆这一层,押的赌注就是它记不住。 +- [p6-04b] 而赌注会过期。官方说过:新一代模型上,基本设定删了八成,评测没掉分。 +- [p6-04c] 手写的规则清单,正在让位给它自己长的记忆。 - [p6-05] 官方还有一句话值得放在最后:这两条腿,都是上下文,不是闸门。 -- [p6-06] 记忆是建议,钩子才是规则——这是提示词工程和 Harness 工程的第一道分水岭。 -- [p6-07] 本片以官方文档为主,取数2026年8月,以官方最新表述为准。 -- [p6-08] 涉及产品内部的部分,为第三方源码分析,片中已逐处标注。 +- [p6-06] 记忆是建议,钩子才是规则——写提示词和做 Harness 的分水岭。 - [p6-09] 下次它又忘了你的偏好,你知道去哪找——不是它的脑子,是那个文件夹。 -- [p6-10] 下期拆另一件事:活儿能不能不等你盯着才开工——后台、定时、替你按开始的那只手。下期见。 +- [p6-10] 下期往前推一步:它干活时没有钟——按下开始的那只手,是谁的?下期见。 diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md index 8330bc07..eff532c1 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md @@ -11,9 +11,10 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 0-A | p0-01..02 | 系列终端:活干到一半,一行红色报错砸出(「拒收/prompt too long」角标) | 报错行砸落 + 画面压暗一档;终端光标停闪;p0-02 拒收理由角标浮出 | -| 0-B | p0-04..08 | 终端缩小,右侧「窗口容器」:读文件/跑命令的色块一层层灌入玻璃容器 | 色块按句节奏持续注入;液面爬升;p0-08 液面撞顶、容器边框闪 `deny`,「前面全白干」 | -| 0-C | p0-09..12 | 直觉答案「删一点」的三个恶果小样:任务书被删(忘了初衷)/ 回执被删(对空气发问) | 三张 20 秒小样依次快闪,各配一句后果 | -| 0-D | p0-13..17 | 两层答案预告:左右两块画中画——左「桌面(会丢,管好丢)」右「登记簿(不丢)」 | 两块画中画先后亮起;中间一道分隔线生长——本集结构图 | +| 0-B | p0-04..p0-06 | 终端缩小,右侧「窗口容器」:读文件/跑命令的色块一层层灌入玻璃容器;p0-05a 起左侧终端降至 0.35、同位浮出**开局装载清单**(七行等宽:基本设定 4,200/自动记忆索引 680/环境信息 280/工具名 120/技能描述 450/用户级规则 320/项目规则 1,800,行尾挂「终端可见/一行摘要/不可见」三档徽章);容器底部升起约 10% 高的斜纹基底层标「开局已装」 | 四个注入锚(p0-04/p0-05/p0-05a/p0-05b)色块依次灌入、液面爬升;p0-05a 清单七行 stagger 浮现;p0-05b「4,200」行 `core` 高亮并与基底层连线;p0-06 液面撞顶、边框闪 `deny`;角标「官方示意值 · context-window 页 · 取数 2026-08」 | +| 0-C | p0-09..p0-09c | **上下文腐坏双轴**:右侧坐标系(X 窗口字数/Y 翻旧账准确度)曲线描出并单调下滑;左侧注意力关系图 4 节点→8→16,边数角标 6→28→120 | p0-09 曲线 strokeDashoffset 描线;p0-09a 节点弹入、边逐层连满;p0-09b 全部边 opacity 0.9→0.35、线宽收细,顶部「注意力预算=1 份」定宽条不随节点增长;p0-09c 曲线尾段趋平(渐变非悬崖)+ `deny` 衬线压字「能装 ≠ 能记」;角标「官方工程博客 · 取数 2026-08」 | +| 0-C2 | p0-10..p0-11 | **四件套标尺**(系列共用):四格横排,编号 01–04(循环/工具/上下文管理/护栏,反枚举不给四色) | p0-10 四格自左依次落位、第三格 `keep` 描边点亮;p0-11 第三格裂为两半「安排看什么/满了怎么办」,右半 `keep` 填充、左半保持 `dim` 标「另拆」 | +| 0-D | p0-13..p0-15 | 两层答案预告:左右两块画中画——左「桌面(会丢,管好丢)」右「登记簿(不丢)」 | 两块画中画先后亮起(p0-14/p0-15);p0-15 尾中间一道分隔线生长——本集结构图 | ## P1 桌面的收拾法 @@ -46,7 +47,7 @@ |---|---|---|---| | 4-A | p4-01..02 | 全景回望:四级收拾+应急+回捞全部发生在「桌面」上;桌面边缘标「迟早被压」 | 已讲机制以小图标环绕桌面排列;桌面整体轻微褪色一次(预告命运) | | 4-B | p4-03..07 | ★转折帧:一张字条「缩进用 tab,别用空格」→ 摘要光束扫过 → 变成「有代码风格偏好」六字 | 字条特写;摘要光束横扫;字面逐字重写为六个字;原字条碎片飘走(细节之死) | -| 4-C | p4-08..12 | **记忆两条腿**:左侧「你写的」——项目规则文件夹(四层拼接不覆盖 · 越近工作目录越后读 · 单文件四兆上限超了整份跳过 · 超两百行开始不听话);右侧「它自己写的」——用户目录下的自动记忆(按四类落卡 · 有门限);防重复印章保留 | 两条腿分立(`keep` 描边统一);左侧四条限制小字逐条浮现;右侧记忆卡逐张落;重复卡被「已有」印章退回 | +| 4-C | p4-08..12 | **记忆两条腿**:左侧「你写的」——项目规则文件夹(四层拼接不覆盖 · 越近工作目录越后读 · 单文件四兆上限超了整份跳过 · 超两百行开始不听话);右侧「它自己写的」——用户目录下的自动记忆(按四类落卡 · 有门限);防重复印章保留。**p4-08a..d 层位纠正插段**:一枚「项目规则」卡飞向顶部「基本设定」框被横杆弹回,落进其下方「你开口之前 · 第一张便条」通道 | 两条腿分立(`keep` 描边统一);p4-08a 规则卡沿弧线上飞→p4-08b 被弹回落位、通道标签描出;p4-08c 角标换官方引语「会读、会尽量照做、不保证严格执行 · memory 页 · 取数 2026-08」;p4-08d 左腿标题旁盖「建议 ≠ 配置」小徽标;p4-09 起左侧限制小字逐条浮现(四兆上限留角标);右侧记忆卡逐张落;重复卡被「已有」印章退回 | | 4-D | p4-13..17 | 四类记忆四宫格:你是谁/怎么干活/在发生什么/去哪儿找,各配真实例子 | 四宫格依次亮起(`keep` 描边统一色,反枚举);各格例子逐字打入 | | 4-E | p4-18..29 | 取的两条路:索引常驻(桌角常亮)+ 旁路小问(小模型吐回 ≤5 卡 · 拿不准的自动缩回);**前缀缓存钩**(p4-24/25):三层前缀条——系统提示/项目上下文/对话,上层一动其后全重算;「改规则要新开会话」与「中途换模型那轮慢」两个注解 + **价目条**(p4-25a/b:命中 ×0.1 · 写入 +1/4 · 两次一问就回本) | 索引页恒亮;旁路支线描线→五张卡飞回;犹豫卡缩回;p4-24 三层前缀条自下而上点亮、顶层闪烁一次引发下层全红重算动画;两个注解小卡浮出;p4-25a 价目条自下滑入 | @@ -64,5 +65,6 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| -| 6-A | p6-01..06 | 一句话合同金句卡(`serif` `keep` 描边)→ 两行回收(体面地忘 / 固执地记) | 金句卡淡入;两行小字对仗浮现 | -| 6-B | p6-07..10 | 信源卡(官方文档+取数日期 / 第三方源码分析已逐处标注 / 数字均为实测口径)+ 「上下文不是闸门」分水岭角标 → 身份卡 + **下期预告卡**(「下期 · 时机层」+ 标题,只进画面) → 渐黑(末 beat 总时长推导,红线四) | 逐行浮现;身份卡;下期卡 `panel` 描边框浮现;末 1.2s 线性压暗 | +| 6-B | p6-07..p6-08 | **信源卡前置**(收尾改序:免责→金句→预告):官方文档+取数日期 / 第三方源码分析已逐处标注 / 数字均为实测口径 | 两行逐行浮现,`panel` 描边;不再插在情绪高点与转化动作之间 | +| 6-A | p6-01..p6-06 | 一句话合同金句卡(`serif` `keep` 描边)→ 两行回收(体面地忘 / 固执地记)→ **赌注会过期**:左「记忆 · 押注:它记不住」卡,一支「模型变强 →」箭头扫过后卡上划删除线并盖章「基本设定删八成 · 评测没掉分」,右侧 `keep` 新卡「它自己长的记忆」升起 | 金句卡淡入;两行小字对仗浮现;p6-04a 回收两行上移收缩、押注卡淡入;p6-04b 箭头扫过+盖章(角标「官方口径 · 取数 2026-08」);p6-04c 右侧新卡升起;p6-06 分水岭卡压场,角标「提示词工程 → Harness 工程」 | +| 6-C | p6-09..p6-10 | 身份卡 + **下期预告卡**(「下期 · 时机层」+ 标题,只进画面)→ 渐黑(末 beat 总时长推导,红线四);尾帧复用 0-C2 的四件套标尺,第三格「上下文管理」保持点亮 | 身份卡浮现;下期卡 `panel` 描边框浮现;四件套标尺尾帧压入;末 1.2s 线性压暗(fadeStart 取本 beat 时长,勿沿用末句时长) | diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json index 088f9ccd..2e6c8566 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json @@ -12,7 +12,12 @@ { "id": "p0-03", "scene": "P0", - "text": "官方给这种单干的慢性病,起了三个名字:干一半就宣布完成、偏爱自己的产出、目标越走越散。" + "text": "官方给这种单干的慢性病,起了三个名字。" + }, + { + "id": "p0-03a", + "scene": "P0", + "text": "干一半就宣布完成、偏爱自己的产出、目标越走越散。" }, { "id": "p0-04", @@ -99,16 +104,6 @@ "scene": "P1", "text": "就是把你挡住。宁可挡着你,也不让一个笔误炸掉整块看板。" }, - { - "id": "p1-11", - "scene": "P1", - "text": "你可能觉得这设计保守。但想想看板是给一群它用的:" - }, - { - "id": "p1-12", - "scene": "P1", - "text": "一个成员写错一个编号就全盘崩掉,这买卖做不得。防御性不是胆小,是算账。" - }, { "id": "p1-13", "scene": "P1", @@ -229,16 +224,6 @@ "scene": "P2", "text": "只不过写文件加了一把锁,防止两个队友同时投信把信写串行。" }, - { - "id": "p2-16", - "scene": "P2", - "text": "有人数过,消息其实有十五种:汇报、请示、审批、关机、广播……" - }, - { - "id": "p2-17", - "scene": "P2", - "text": "名目繁多,但底子全是同一个动作:往对方的文件里,加一行带类型的字。" - }, { "id": "p2-18", "scene": "P2", @@ -322,22 +307,12 @@ { "id": "p3-06", "scene": "P3", - "text": "这套握手有个精巧的细节:每一对请求和回复,带同一个编号。" + "text": "这套握手有个精巧处:请求和回复带同一个编号,隔着信箱也对得上。" }, { "id": "p3-07", "scene": "P3", - "text": "请求带编号出发,回复带同一个编号回来。隔着信箱与轮次,编号就是暗号。" - }, - { - "id": "p3-08", - "scene": "P3", - "text": "还要三重对号:编号对得上、类型对得上、这事还没办过——全过才销账。" - }, - { - "id": "p3-09", - "scene": "P3", - "text": "一张关机的回复,永远不会误批掉一份计划。类型错一个字,直接弹开。" + "text": "还要三重对号——编号、类型、这事没办过,全过才销账。" }, { "id": "p3-10", @@ -454,6 +429,46 @@ "scene": "P4", "text": "领队从包工头退成了项目经理。转变的代价,就是那几样朴素的东西。" }, + { + "id": "p4-17", + "scene": "P4", + "text": "官方自己拿这套打法,干过一票大的:让一群它,写一个编译器。" + }, + { + "id": "p4-18", + "scene": "P4", + "text": "十六个它并行,各守一个容器;认领就是往一个文件里写一行占坑。" + }, + { + "id": "p4-19", + "scene": "P4", + "text": "没有总调度,没有领队——两周,约两千场会话,十万行代码。" + }, + { + "id": "p4-20", + "scene": "P4", + "text": "产出能编出一个可启动的内核,账单不到两万美元。" + }, + { + "id": "p4-21", + "scene": "P4", + "text": "并行最难的也不是分活,是所有人卡在同一个坑。" + }, + { + "id": "p4-22", + "scene": "P4", + "text": "一个报错,就能让十六个它一起停摆。" + }, + { + "id": "p4-23", + "scene": "P4", + "text": "解法很野:大部分文件先让现成的编译器过,只留一小撮给它。" + }, + { + "id": "p4-24", + "scene": "P4", + "text": "再二分下去,分到最后谁也不挡谁。" + }, { "id": "p5-01", "scene": "P5", @@ -664,9 +679,19 @@ "scene": "P6", "text": "涉及产品内部的部分,为第三方源码分析,片中已逐处标注。" }, + { + "id": "p6-16a", + "scene": "P6", + "text": "最后一句官方的自省值得带走:常问自己,可以停掉哪一件。" + }, + { + "id": "p6-16b", + "scene": "P6", + "text": "每一样零件都押着一条「模型做不到」的赌注。模型变强,赌注就过期。" + }, { "id": "p6-17", "scene": "P6", - "text": "下期,换个方向:怎么给这样的系统打分。分数会骗人,过程不会——下期见。" + "text": "下期,再往上一层:怎么给这样的系统打分。分数会骗人,过程不会——下期见。" } ] diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md index b9e83d49..b1885dc8 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md @@ -16,7 +16,8 @@ - [p0-01] 你交给它一桩大活:翻新整个后端,四个模块全都要动。 - [p0-02] 它开头干得不错——可修到接口时,认证那块的细节,已经不在它的视野里了。 -- [p0-03] 官方给这种单干的慢性病,起了三个名字:干一半就宣布完成、偏爱自己的产出、目标越走越散。 +- [p0-03] 官方给这种单干的慢性病,起了三个名字。 +- [p0-03a] 干一半就宣布完成、偏爱自己的产出、目标越走越散。 - [p0-04] 就像一个工人盖不了整栋楼。要赶工期,得来一队人。 - [p0-05] 于是问题来了:从一个它到一群它,每多一样东西,都要回答四件事—— - [p0-06] 活挂在哪里?话从哪里走?怎么谈判?谁的桌子谁收拾? @@ -40,8 +41,6 @@ - [p1-08] 做完「建表」,「接口」和「文档」同时亮起可领——排序是图自己算出来的。 - [p1-09] 还有个特别诚实的设计:你引用了一个不存在的任务当依赖,它不报错、不崩, - [p1-10] 就是把你挡住。宁可挡着你,也不让一个笔误炸掉整块看板。 -- [p1-11] 你可能觉得这设计保守。但想想看板是给一群它用的: -- [p1-12] 一个成员写错一个编号就全盘崩掉,这买卖做不得。防御性不是胆小,是算账。 - [p1-13] 官方文档写得直白:任务认领用文件锁防竞态—— - [p1-14] 先看一眼没人抢、再落笔写主人,两步并成一步,中间插不进第二只手。 - [p1-15] 编号也有讲究:一个只增不减的计数器,防止编号被重复使用。 @@ -73,8 +72,6 @@ - [p2-13] 领队隔一阵收一次信,把信里的内容贴进自己的对话,接着指挥。 - [p2-14] 官方口径也证实了:信箱真的就是用户目录下的一个文件, - [p2-15] 只不过写文件加了一把锁,防止两个队友同时投信把信写串行。 -- [p2-16] 有人数过,消息其实有十五种:汇报、请示、审批、关机、广播…… -- [p2-17] 名目繁多,但底子全是同一个动作:往对方的文件里,加一行带类型的字。 - [p2-18] 最妙的是权限。队友要干一件需要审批的事,审批窗不在它自己的屏幕上—— - [p2-19] 请求冒泡,一路浮到领队的屏幕,弹出来,还是你来点头。 - [p2-20] 组了队,不代表权限放松了——官方立了三道禁令:队友的消息, @@ -98,10 +95,8 @@ - [p3-03] 最粗暴的做法是直接掐掉它的线程。但掐的瞬间,它可能正写文件写到一半—— - [p3-04] 磁盘上留下一个半拉子文件,谁也说不清那算谁的。 - [p3-05] 所以告别也要握手。领队发关机请求,队友收干净手头的活,回一张同意。 -- [p3-06] 这套握手有个精巧的细节:每一对请求和回复,带同一个编号。 -- [p3-07] 请求带编号出发,回复带同一个编号回来。隔着信箱与轮次,编号就是暗号。 -- [p3-08] 还要三重对号:编号对得上、类型对得上、这事还没办过——全过才销账。 -- [p3-09] 一张关机的回复,永远不会误批掉一份计划。类型错一个字,直接弹开。 +- [p3-06] 这套握手有个精巧处:请求和回复带同一个编号,隔着信箱也对得上。 +- [p3-07] 还要三重对号——编号、类型、这事没办过,全过才销账。 - [p3-10] 同一套机制换个方向就是审批:队友要动高风险的东西,先交一份计划等批。 - [p3-11] 计划这头等回复,回复那头带编号回来,批了才动手。 - [p3-12] 有人拆过它的源码——产品里的关机更讲究,是三向的: @@ -132,6 +127,14 @@ - [p4-14] 再看一眼自治的样子:领队只做两件事——挂任务上板,需要时发告别握手。 - [p4-15] 剩下的认领、开工、汇报、等待、再认领,全是队友自己的节奏。 - [p4-16] 领队从包工头退成了项目经理。转变的代价,就是那几样朴素的东西。 +- [p4-17] 官方自己拿这套打法,干过一票大的:让一群它,写一个编译器。 +- [p4-18] 十六个它并行,各守一个容器;认领就是往一个文件里写一行占坑。 +- [p4-19] 没有总调度,没有领队——两周,约两千场会话,十万行代码。 +- [p4-20] 产出能编出一个可启动的内核,账单不到两万美元。 +- [p4-21] 并行最难的也不是分活,是所有人卡在同一个坑。 +- [p4-22] 一个报错,就能让十六个它一起停摆。 +- [p4-23] 解法很野:大部分文件先让现成的编译器过,只留一小撮给它。 +- [p4-24] 再二分下去,分到最后谁也不挡谁。 ## P5 谁的桌子:各干各的 @@ -188,4 +191,6 @@ - [p6-14] 官方算过账,多智能体的花销,大约是普通对话的十五倍。 - [p6-15] 本片机制依据官方文档,取数2026年8月,以官方最新表述为准。 - [p6-16] 涉及产品内部的部分,为第三方源码分析,片中已逐处标注。 -- [p6-17] 下期,换个方向:怎么给这样的系统打分。分数会骗人,过程不会——下期见。 +- [p6-16a] 最后一句官方的自省值得带走:常问自己,可以停掉哪一件。 +- [p6-16b] 每一样零件都押着一条「模型做不到」的赌注。模型变强,赌注就过期。 +- [p6-17] 下期,再往上一层:怎么给这样的系统打分。分数会骗人,过程不会——下期见。 diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md index 677b7907..428b7b05 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md @@ -20,7 +20,7 @@ |---|---|---|---| | 1-A | p1-01..06 | 工地入口立起看板(TaskBoard 母题):任务卡带五格(编号/标题/状态/主人/等谁);依赖箭头连成 DAG | 看板框架描线;三张示例卡贴上;「等谁完工」格高亮 + 依赖箭头逐条连出 | | 1-B | p1-07..10 | ★完成即解锁:「建表」卡打勾 → 箭头传导 →「接口」「文档」两卡同时亮起可领;★不存在依赖:一张虚线幽灵卡把请求卡挡住(不炸) | 完成勾动画 + 解锁波沿箭头传导;幽灵卡半透明+「算被挡」标签,请求卡撞上被弹回 | -| 1-C | p1-11..15 | 【三】文件锁帧:认领动作包进一把锁形罩子——「查看+落笔」两步在罩内一步完成,第二只手插不进;高水位计数器只增不减 | 锁罩合拢动画(mech);罩外一只手试图伸入被挡;计数器滚动且刻度只上不下;角标「第三方的源码分析」 | +| 1-C | p1-13..15 | 【三】文件锁帧:认领动作包进一把锁形罩子——「查看+落笔」两步在罩内一步完成,第二只手插不进;高水位计数器只增不减 | 锁罩合拢动画(mech);罩外一只手试图伸入被挡;计数器滚动且刻度只上不下;角标「第三方的源码分析」 | | 1-D | p1-16..21 | 清单 vs 看板对照:左小卡(给自己看)右大板(给所有人看);收束句「硬盘上的东西人人可见」 | 左右对照布局;右侧看板向四方投出可见光束 | ## P2 话从哪里走:信箱 @@ -28,9 +28,9 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 2-A | p2-01..05 | 临时工 vs 队友:左侧临时工剪影(干完即走)右侧队友小环(peer 色,铭牌);队友环长期驻场 | 临时工淡出;队友环落位并打上铭牌;对比定格 | -| 2-B | p2-06..11 | ★信箱行:每位成员门口一个信箱文件;消息行(一行字)飞入对方文件;读取即划掉(一行淡出) | 消息行沿弧线飞入;打开文件时光扫过、被读行划掉;角标「写文件带锁(防串行)」 | -| 2-C | p2-12..14 | 十五种消息类型小样墙(统一 panel 底编号,反枚举):汇报/请示/审批/关机/广播…… | 类型卡快速铺开;全部退远缩成「往文件里加一行带类型的字」一行字 | -| 2-D | p2-15..19 | ★权限冒泡:队友的审批卡从下沿虚线上浮到领队屏幕弹出(带队友名字与颜色);点头后回执下落 | 审批卡沿路径上浮(浮起涟漪);你的光标点头动画;回执回落到队友信箱 | +| 2-B | p2-06..11 | ★信箱行:每位成员门口一个信箱文件;消息行(一行字)飞入对方文件;读取即划掉(一行淡出) | 消息行沿弧线飞入;打开文件时光扫过、被读行划掉;角标「写文件带锁(防串行)· 消息类型十五种——第三方的源码分析」 | +| 2-C | p2-12..15 | ★领队信箱:队友干完活把总结投进领队信箱;领队收信、信里内容贴进对话;写文件带锁(防串行) | 总结信飞入领队信箱(飞入闪光);信件展开、内容行贴进小对话泡;写锁 chip 亮一下 | +| 2-D | p2-18..19 | ★权限冒泡:队友的审批卡从下沿虚线上浮到领队屏幕弹出(带队友名字与颜色);点头后回执下落 | 审批卡沿路径上浮(浮起涟漪);你的光标点头动画;回执回落到队友信箱 | | 2-E | p2-20..25 | **三禁止章**:一条 A→B 消息到达前被「来自另一个会话——不是你的用户」标签盖灰;三枚 deny 红章依次盖下(不能替你批权限 / 不能代你同意 / 被拒动作不能转给别人);**名册卡**(p2-23a/b:用户目录团队文件夹的 roster 文件·成员+信箱,会话结束自动清掉);**消息 vs 上下文**(p2-24a/b:信箱一段文字 vs 整段上下文·须恢复会话);不许孵队友铁律 + 保险丝收尾 | 消息卡飞行被来源标签截停盖灰;三红章逐枚盖下(章落带缩放震);中景换页:签字栏→名册卡(成员行划掉+边框转虚线+「自动清掉」小标)→信箱/上下文对比卡(信箱管传话,整段上下文搬不过去);末句保险丝横幅(mech) | ## P3 怎么谈判:握手 @@ -38,7 +38,7 @@ | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 3-A | p3-01..05 | 杀线程之祸:掐线程瞬间,写一半的文件断在半空(裂口);握手替代:领队发关机请求→队友收尾→回「同意」→自行退出 | 文件裂口闪烁(deny);四步走位动画:请求卡出发→队友卡收拾(文件补全)→回执→退出 | -| 3-B | p3-06..09 | ★握手轨(HandshakeRail 母题):请求卡带编号(req_0042)滑出停在「等回话」位;状态表 pending 行亮起;应答卡带同号归来对号合拢锁扣「咔」;类型校验:一张错类型回执被弹开 | 请求/应答卡沿轨对开;编号铭牌双方一致时合拢+锁扣声效帧;错类型卡撞上弹开(deny) | +| 3-B | p3-06..07 | ★握手轨(HandshakeRail 母题):请求卡带编号(req_0042)滑出停在「等回话」位;状态表 pending 行亮起;应答卡带同号归来对号合拢锁扣「咔」;类型校验:一张错类型回执被弹开 | 请求/应答卡沿轨对开;编号铭牌双方一致时合拢+锁扣声效帧;错类型卡撞上弹开(deny) | | 3-C | p3-10..11 | 计划审批同构:队友交计划卡等批,批文带编号回来,批了才动手 | 同一握手轨复用(方向反转);「批了才动手」门闸开合 | | 3-D | p3-12..16 | 【三】三向关机:请求→同意/拒绝(可附理由)→系统广播「已离场」+ 窗格/任务/名册自动收拾;教学版诚实句(只演消息走、产品门禁是真的)并句收尾 | 三向消息流;收拾动画(窗格收起、名册划名);角标「第三方的源码分析」;末句门禁小闸落下 | @@ -50,6 +50,7 @@ | 4-B | p4-04..09 | 歇着态特写:每五秒心跳一次,看两眼——先信箱(有关机立刻收尾;有信先处理)后看板(三查后认领);两只队友抢活先到先得 | 心跳脉冲;视线先扫信箱再扫看板的路径高亮;认领时主人格写入+锁形闪光 | | 4-C | p4-10..13 | 六十秒表盘走满自动收工(教学版标记);产品无固定时限;压缩后身份重注入(对话变短→「我是谁」卡插回) | 表盘快走满→收工礼花定格;对话堆坍缩成一小段→身份卡从顶部插回;角标「产品无固定时限(源码分析)」 | | 4-D | p4-14..16 | 领队角色变化:包工头帽摘下换项目经理牌;两件事(挂任务/告别握手)图示 | 帽子换牌动画;两张卡钉在领队环旁 | +| 4-E 官方战例:十六个它写编译器 | p4-17..24 | ★官方战报:4×4 容器网格(每格 peer 色小环+容器描边,反枚举:16 个不 16 色);锁文件卡 `current_tasks/xxx.txt` 飞入+「占坑」标签;「领队席:空」铭牌盖 deny 叉章;战果条滚动(16 · ≈2,000 会话 · ≈100K 行 · <$20K)+ 内核 boot 脉冲;deny 冻霜波纹从一格扩散冻结全部 16 格;文件块分流成两堆(大堆 mech 走「现成的编译器」、小堆 peer 走「它」)+ 二分箭头逐轮收敛 | p4-17 起容器逐格点亮(间隔约 4 帧);p4-18 锁文件写入闪光;p4-19 数字带逐项滚动+空席盖章;p4-20 boot 脉冲+账单停格;p4-22 冻霜级联;p4-23/24 分流动画收敛至两堆互不阻塞;角标「16 并行 · ~2,000 会话 · ~$20K · ~100K LOC · 官方工程博客 2026-02-05」 | ## P5 谁的桌子:各干各的 @@ -68,4 +69,4 @@ | 6-B | p6-03..04 | ★一整轮快闪:包裹走完七段(进料/护栏/选面/执行/外接/补救/记账),每段亮起对应机制小图标——快闪蒙太奇(原 4 句详走压成 2 句) | 包裹逐段快速推进(每段约 1.5s);每过一段该段图标亮起并短暂回闪其母题缩略 | | 6-C | p6-05..06 | ★系列终曲帧:环(core)从传送带中央升起放大居中——同色同宽同节点;「机制很多,循环一个」金句压场 | 环升起重演描线一遍(与系列首集同款动画节奏);机制图标环立四周;金句卡(core)淡入 | | 6-D | p6-07..11d | ★**谁持有计划**:四象对比 + 动态工作流三分区 + **六模式选二**(扇出汇总 / 对抗核验)+ **resume 重放**(干完的秒亮、没干完的重跑、其后全部重跑)+ 收官反转 | 分水岭竖线落下;运行时三分区;两张模式小卡浮出(扇出→汇总漏斗 / 挑刺→改到合格);resume 子图:A 绿秒亮 / B 黄重跑 / C D 对勾抹掉;反转金句卡 | -| 6-E | p6-12..17 | 「零件」收束(板/箱/号/桌)+ 官方冷水(十五倍 token)→ 信源卡(官方文档+取数日期 / 第三方源码分析已逐处标注 / 数字均为实测口径)→ 身份卡 + **下期预告卡**(「换个方向:给这样的系统打分」,只进画面) → **渐黑**(末 beat 总时长推导,红线四) | 零件四连小图;十五倍对比条;信源卡逐行;身份卡;下期卡浮现;末 1.2s 线性压暗到全黑 | +| 6-E | p6-12..17 | 「零件」收束(板/箱/号/桌)+ 官方冷水(十五倍 token)→ 信源卡(官方文档+取数日期 / 第三方源码分析已逐处标注 / 数字均为实测口径)→ **第一定律两句**(p6-16a/b:自省「可以停掉哪一件」+「押注『模型做不到』」——零件四连各加「赌注」小标签,随后逐个变灰淡出一枚,角标「我可以停止做什么?」)→ 身份卡 + **下期预告卡**(「再往上一层:给这样的系统打分」,只进画面) → **渐黑**(末 beat 总时长推导,红线四) | 零件四连小图;十五倍对比条;信源卡逐行;p6-16a 起角标淡入+零件逐个 dim 变灰(p6-16b 末全灰);身份卡;下期卡浮现;末 1.2s 线性压暗到全黑 | diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json index e8cc43b9..418398f2 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json @@ -37,7 +37,12 @@ { "id": "p0-08", "scene": "P0", - "text": "五样装置,一样一样拆开看。" + "text": "官方给 Harness 的定义有四件:循环、工具、上下文管理、护栏。" + }, + { + "id": "p0-09", + "scene": "P0", + "text": "今天补的正是上下文管理的前半:它每一轮能看见什么。" }, { "id": "p1-01", @@ -54,11 +59,6 @@ "scene": "P1", "text": "状态只有这三种,不多不少。干一步挪一格,桌子上的进度看得见摸得着。" }, - { - "id": "p1-04", - "scene": "P1", - "text": "这套做法听起来土得掉渣,土到你会怀疑它是不是真有用。" - }, { "id": "p1-05", "scene": "P1", @@ -114,6 +114,31 @@ "scene": "P1", "text": "官方理由很直白:这些模型自己就能记住要干什么。押注押到期了。" }, + { + "id": "p1-15a", + "scene": "P1", + "text": "那规划这件事就没了吗?没有,它升级成了一道门。" + }, + { + "id": "p1-15b", + "scene": "P1", + "text": "官方叫它计划模式:先只读地探索,把计划写出来给你过目。" + }, + { + "id": "p1-15c", + "scene": "P1", + "text": "计划没批,改文件的动作一律拦住——想动手?先说服你。" + }, + { + "id": "p1-15d", + "scene": "P1", + "text": "批准那一下你有三个选择:交给自动闸门、逐条人工点头、或者继续再想。" + }, + { + "id": "p1-15e", + "scene": "P1", + "text": "清单是写给它自己看的;计划,是写给你看的。" + }, { "id": "p1-16", "scene": "P1", @@ -172,12 +197,7 @@ { "id": "p2-09", "scene": "P2", - "text": "主桌上你看不到那三十个文件的任何一行,只看得见它带回的一张回执。" - }, - { - "id": "p2-10", - "scene": "P2", - "text": "干完,只把最后那条结论带回主桌。中间过程全部丢掉。" + "text": "主桌上你看不到那三十个文件的任何一行,中间过程全丢,只带回一张回执。" }, { "id": "p2-11", @@ -187,7 +207,7 @@ { "id": "p2-12", "scene": "P2", - "text": "教学版的纪律是分身不许再派分身;官方后来放开了——最多三层,同时二十个。" + "text": "纪律第一条:教学版不许分身再派分身;官方放开了——最多三层,同时二十个。" }, { "id": "p2-14", @@ -237,7 +257,7 @@ { "id": "p2-23", "scene": "P2", - "text": "五样东西必须一字不差,缓存才会命中,钱才真的省下来。" + "text": "差一个字,白算——五样全对上,缓存才认。" }, { "id": "p2-24", @@ -327,12 +347,7 @@ { "id": "p3-08", "scene": "P3", - "text": "官方口径:目录预算有硬顶——" - }, - { - "id": "p3-08a", - "scene": "P3", - "text": "常规状态的这份纸,两三万字;极简模式整个两行。同一个人,两种铺法。" + "text": "官方口径:目录预算有硬顶。" }, { "id": "p3-08b", @@ -342,7 +357,7 @@ { "id": "p3-09", "scene": "P3", - "text": "大约是窗口的百分之一,再设一个绝对上限,超了就砍。" + "text": "这个硬顶大约是窗口的百分之一,还设了绝对上限,超了就砍。" }, { "id": "p3-10", @@ -397,17 +412,22 @@ { "id": "p3-20", "scene": "P3", - "text": "有人拆过它的源码——产品里这张纸常规状态有两三万字," + "text": "有人拆过它的源码,说这张垫纸常规状态两三万字、极简模式两行。" }, { "id": "p3-21", "scene": "P3", - "text": "而极简模式整个就两行。同一个人,两种铺法。" + "text": "更大的反转来自官方:2026年7月,这张纸删掉八成以上,评测不掉分。" + }, + { + "id": "p3-21a", + "scene": "P3", + "text": "纸能写多长,取决于模型有多不需要你替它写。" }, { "id": "p3-22", "scene": "P3", - "text": "他还说了个特别讲究的细节:所有段落里,只有一段永远不许进缓存——" + "text": "拆源码的人还说了个讲究的细节:段落里只有一段,永远不许进缓存——" }, { "id": "p3-23", @@ -447,7 +467,7 @@ { "id": "p4-04", "scene": "P4", - "text": "注意是原封不动:半句话先不存下来,就当无事发生,加够额度再来一遍。" + "text": "注意是原封不动:半句先不存,加够额度再来一遍。" }, { "id": "p4-05", @@ -487,42 +507,57 @@ { "id": "p4-12", "scene": "P4", - "text": "最笨的反应是立刻重试——服务都趴了,你重试一百遍也是趴,还帮着踩了两脚。" + "text": "硬冲没用,先等一等:半秒、一秒、两秒往上翻倍,封顶三十二秒。" }, { "id": "p4-13", "scene": "P4", - "text": "等多久?不是拍脑袋。半秒、一秒、两秒、四秒——每次翻倍,封顶三十二秒。" + "text": "再撒一点随机抖动,免得全世界的重试同一秒冲回来。" }, { "id": "p4-14", "scene": "P4", - "text": "这样最长的等待也就半分钟,而服务通常已经喘过气来了。" + "text": "对方要是留了张「稍后再来」的字条,就听字条的。" }, { - "id": "p4-15", + "id": "p4-17", "scene": "P4", - "text": "再撒一点随机抖动,免得全世界卡住的服务,同一秒一起冲回来把它再撞趴下。" + "text": "连着三次都过载呢?换人。切到备用模型,把没干完的活清一清,先干点小的。" }, { - "id": "p4-16", + "id": "p4-17a", "scene": "P4", - "text": "对方要是好心理了个「稍后再来」的字条,就按字条上的时间等,比公式更快。" + "text": "更值得记的是它什么时候不重试。" }, { - "id": "p4-17", + "id": "p4-17b", "scene": "P4", - "text": "连着三次都过载呢?换人。切到备用模型,把没干完的活清一清,先干点小的。" + "text": "证书对不上,第一次就报错——那是要你去修的,退避一百遍也一样。" + }, + { + "id": "p4-17c", + "scene": "P4", + "text": "更微妙的是另一类:话已说一半、工具已发出,这时出错,不能原样重发。" }, { - "id": "p4-18", + "id": "p4-17d", "scene": "P4", - "text": "有人分析过,产品里的恢复路径有十几种,教学版挑了最常见的三种讲;" + "text": "原样重发一次,同一个动作就跑了两遍。" + }, + { + "id": "p4-17e", + "scene": "P4", + "text": "它的做法是保住已产出的,插一条「没写完」的标记,从断点接着来。" + }, + { + "id": "p4-17f", + "scene": "P4", + "text": "顺带给个刻度:默认最多重试十次,上限十五次。" }, { "id": "p4-19", "scene": "P4", - "text": "他还提了一个很冷静的设计:续写要是连着几次都没写出新东西," + "text": "拆源码的人还提了个冷静设计:续写要是连着几次没写出新东西," }, { "id": "p4-20", @@ -532,7 +567,7 @@ { "id": "p4-21", "scene": "P4", - "text": "出错不是终点。这话写在章首,也确实是这套系统的性格。" + "text": "出错不是终点——这确实是这套系统的性格。" }, { "id": "p4-21a", @@ -582,32 +617,17 @@ { "id": "p5-07", "scene": "P5", - "text": "你会发现一个熟悉的形状:这些装置没有一样是写进循环里的。" + "text": "你会发现一个熟悉的形状:这五样,没有一样写进循环。" }, { "id": "p5-08", "scene": "P5", - "text": "清单是一个工具,副桌是一次调用,目录是一张注册表," + "text": "清单是工具,副桌是调用,目录是注册表,垫纸是拼装,梯子是包裹。" }, { "id": "p5-09", "scene": "P5", - "text": "垫纸是一次拼装,梯子是一层包裹。全部挂在循环外面。" - }, - { - "id": "p5-10", - "scene": "P5", - "text": "循环自己呢?我把这几章的代码逐一比过:" - }, - { - "id": "p5-11", - "scene": "P5", - "text": "加催更计数、加派活工具、加目录扫描、加一层试错包裹——每一处都是外挂," - }, - { - "id": "p5-12", - "scene": "P5", - "text": "那句「不停问模型」的骨架,一个字没换。" + "text": "我逐一比过这些增量代码:加的全是外挂,那句「不停问模型」一个字没换。" }, { "id": "p5-13", @@ -629,6 +649,16 @@ "scene": "P5", "text": "而管视野这件事,本身就是一门可以被看懂的手艺。" }, + { + "id": "p6-07", + "scene": "P6", + "text": "本片机制依据官方文档,取数2026年8月,以官方最新表述为准。" + }, + { + "id": "p6-08", + "scene": "P6", + "text": "涉及产品内部的部分,为第三方源码分析,片中已逐处标注。" + }, { "id": "p6-01", "scene": "P6", @@ -659,19 +689,9 @@ "scene": "P6", "text": "桌子会换,零件会瘦,那个循环一直没停过。" }, - { - "id": "p6-07", - "scene": "P6", - "text": "本片机制依据官方文档,取数2026年8月,以官方最新表述为准。" - }, - { - "id": "p6-08", - "scene": "P6", - "text": "涉及产品内部的部分,为第三方源码分析,片中已逐处标注。" - }, { "id": "p6-09", "scene": "P6", - "text": "下期,拆管记忆的那一层:桌面太满怎么收拾,什么必须留下。下期见。" + "text": "下期:它会忘,而且忘得有章法——但有一样东西,它永远不许忘。下期见。" } ] diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md index f6689ee0..b680b88e 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md @@ -21,7 +21,8 @@ - [p0-05] 于是问题来了:它这一轮能看见什么,是它自己说了算吗? - [p0-06] 答案:不是。有一整套装置,在替它安排视野。 - [p0-07] 写下来的清单,另开的副桌,按需翻开的目录,每轮重拼的垫纸,一张补救梯。 -- [p0-08] 五样装置,一样一样拆开看。 +- [p0-08] 官方给 Harness 的定义有四件:循环、工具、上下文管理、护栏。 +- [p0-09] 今天补的正是上下文管理的前半:它每一轮能看见什么。 ## P1 把清单钉在桌上 @@ -31,7 +32,6 @@ - [p1-01] 第一样东西最不起眼:一张写下来的清单。 - [p1-02] 干活之前,先把步骤一条条列出来,每条标一个状态:没开始、干着、干完了。 - [p1-03] 状态只有这三种,不多不少。干一步挪一格,桌子上的进度看得见摸得着。 -- [p1-04] 这套做法听起来土得掉渣,土到你会怀疑它是不是真有用。 - [p1-05] 然后奇迹发生了——注意,这个工具本身,什么都不执行。 - [p1-06] 它不能读文件,不能跑命令,唯一的功能就是把清单写下来、摆到它眼前。 - [p1-07] 可正因为清单挂在对话里,每一轮重读的时候,它都会被再看见一次。 @@ -43,6 +43,11 @@ - [p1-13] 它增加的,是规划能力。 - [p1-14] 但这件装置刚刚被官方收了回去——新的模型上,清单工具默认不再安装。 - [p1-15] 官方理由很直白:这些模型自己就能记住要干什么。押注押到期了。 +- [p1-15a] 那规划这件事就没了吗?没有,它升级成了一道门。 +- [p1-15b] 官方叫它计划模式:先只读地探索,把计划写出来给你过目。 +- [p1-15c] 计划没批,改文件的动作一律拦住——想动手?先说服你。 +- [p1-15d] 批准那一下你有三个选择:交给自动闸门、逐条人工点头、或者继续再想。 +- [p1-15e] 清单是写给它自己看的;计划,是写给你看的。 - [p1-16] 清单背后那套更重的任务系统——带依赖、能锁、落盘——那套以后单拆,先记一句: - [p1-18] 把计划写下来,本身就是一种能力。而且是装在循环外面的能力。 - [p1-19] 一个什么都不执行的工具,成了长活不跑偏的关键——这种反差,后面还会遇到几次。 @@ -60,8 +65,7 @@ - [p2-06] 它也一样:另开一张干净的副桌,派一个分身过去干。 - [p2-07] 副桌上是一份全新的对话记录,干干净净,只有一句任务说明。 - [p2-08] 分身在那边自己跑自己的循环,读文件、改代码,跟主桌互不打扰。 -- [p2-09] 主桌上你看不到那三十个文件的任何一行,只看得见它带回的一张回执。 -- [p2-10] 干完,只把最后那条结论带回主桌。中间过程全部丢掉。 +- [p2-09] 主桌上你看不到那三十个文件的任何一行,中间过程全丢,只带回一张回执。 - [p2-11] 注意丢的是什么:写过的文件、改过的代码都还在硬盘上——丢的只是纸,不是活。 - [p2-12] 纪律第一条:教学版不许分身再派分身;官方放开了——最多三层,同时二十个。 - [p2-14] 第二条:分身每次动手之前,照样要过那几道闸门。 @@ -73,7 +77,7 @@ - [p2-20] 分身如果从头建立自己的桌面,前缀全变了,每一段都得原价重新算。 - [p2-21] 所以那套机制反着来:把父亲桌上的东西几乎原样搬给分身,让前缀保持一致。 - [p2-22] 「几乎」是有严格定义的:系统提示、工具表、模型、消息前缀、思考配置, -- [p2-23] 五样东西必须一字不差,缓存才会命中,钱才真的省下来。 +- [p2-23] 差一个字,白算——五样全对上,缓存才认。 - [p2-24] 隔离是搂草打兔子,省钱才是真心话。 - [p2-25] 还有更诚实的:隔离其实是半拉的。有位作者说,分身会继承父亲读过的文件, - [p2-26] 免得同一个文件读两遍。桌是分开了,有些抽屉还是共用的。 @@ -98,10 +102,9 @@ - [p3-05] 一张卡的价钱,大约是整本手册的二十分之一。桌角摆一排,也不心疼。 - [p3-06] 真要用到哪本,再把整本拉上桌——而且整场常驻,压缩后还会重注入。 - [p3-07] 教学版的讲法很直白:目录常驻,内容按需。 -- [p3-08] 官方口径:目录预算有硬顶—— -- [p3-08a] 常规状态的这份纸,两三万字;极简模式整个两行。同一个人,两种铺法。 +- [p3-08] 官方口径:目录预算有硬顶。 - [p3-08b] 官方还给了句实在话:清单超过两百行,它就开始不老实读了。 -- [p3-09] 大约是窗口的百分之一,再设一个绝对上限,超了就砍。 +- [p3-09] 这个硬顶大约是窗口的百分之一,还设了绝对上限,超了就砍。 - [p3-10] 还有个安全细节:取手册只认目录里登记过的名字,不走文件路径,防的就是目录穿越。 - [p3-11] 第四样东西,管的是桌面上那张最大的纸——它的基本设定本身。 - [p3-12] 你跟它说的每一句话之前,都垫着这么一张纸:你是谁、你在哪、能干什么。 @@ -112,9 +115,10 @@ - [p3-17] 关键在「真实状态」四个字:工具就查实际注册了哪些,记忆就查文件存不存在。 - [p3-18] 不去猜消息里出现了什么关键词。猜关键词,是给幻觉开门。 - [p3-19] 状态没变,拼出来的纸一字不差,那就直接用上一次拼好的——拼本身也不重复花钱。 -- [p3-20] 有人拆过它的源码——产品里这张纸常规状态有两三万字, -- [p3-21] 而极简模式整个就两行。同一个人,两种铺法。 -- [p3-22] 他还说了个特别讲究的细节:所有段落里,只有一段永远不许进缓存—— +- [p3-20] 有人拆过它的源码,说这张垫纸常规状态两三万字、极简模式两行。 +- [p3-21] 更大的反转来自官方:2026年7月,这张纸删掉八成以上,评测不掉分。 +- [p3-21a] 纸能写多长,取决于模型有多不需要你替它写。 +- [p3-22] 拆源码的人还说了个讲究的细节:段落里只有一段,永远不许进缓存—— - [p3-23] 外接工具的说明段。因为外接的服务随时会掉线,缓存它就是在缓存一个谎言。 - [p3-24] 你看,连「哪段纸可以复用」都是被精确设计过的。 - [p3-25] 这张垫纸,每轮都在拼,但它拼得比谁都勤俭。 @@ -128,7 +132,7 @@ - [p4-01] 第五样,管的是意外。活干到一半出岔子,是生产的常态,不是事故。 - [p4-02] 第一种岔子:话说到一半,额度用完了,句子断在半空。 - [p4-03] 处理得很有章法。第一次,直接把额度上限放大八倍,原封不动重试同一个请求。 -- [p4-04] 注意是原封不动:半句话先不存下来,就当无事发生,加够额度再来一遍。 +- [p4-04] 注意是原封不动:半句先不存,加够额度再来一遍。 - [p4-05] 放大只有一次。再断,才保存半句话,塞一条续写提示:从断掉的半个词接着说。 - [p4-06] 续写最多三次,三次还断就收手。有人拆过源码,把那条提示原文抄了出来, - [p4-07] 特别有工程品味:别道歉,别复述你刚才在干嘛,直接接着说,把剩下的活切小点。 @@ -136,16 +140,19 @@ - [p4-09] 先压一轮——把旧纸换成摘要腾地方;压完还装不下,就承认装不下,退出。 - [p4-10] 压过一次还压第二次没有意义:纸不会越压越小,该退就退。 - [p4-11] 第三种岔子最有意思:不是你的问题,是服务那边过载或者限流了。 -- [p4-12] 最笨的反应是立刻重试——服务都趴了,你重试一百遍也是趴,还帮着踩了两脚。 -- [p4-13] 等多久?不是拍脑袋。半秒、一秒、两秒、四秒——每次翻倍,封顶三十二秒。 -- [p4-14] 这样最长的等待也就半分钟,而服务通常已经喘过气来了。 -- [p4-15] 再撒一点随机抖动,免得全世界卡住的服务,同一秒一起冲回来把它再撞趴下。 -- [p4-16] 对方要是好心理了个「稍后再来」的字条,就按字条上的时间等,比公式更快。 +- [p4-12] 硬冲没用,先等一等:半秒、一秒、两秒往上翻倍,封顶三十二秒。 +- [p4-13] 再撒一点随机抖动,免得全世界的重试同一秒冲回来。 +- [p4-14] 对方要是留了张「稍后再来」的字条,就听字条的。 - [p4-17] 连着三次都过载呢?换人。切到备用模型,把没干完的活清一清,先干点小的。 -- [p4-18] 有人分析过,产品里的恢复路径有十几种,教学版挑了最常见的三种讲; -- [p4-19] 他还提了一个很冷静的设计:续写要是连着几次都没写出新东西, +- [p4-17a] 更值得记的是它什么时候不重试。 +- [p4-17b] 证书对不上,第一次就报错——那是要你去修的,退避一百遍也一样。 +- [p4-17c] 更微妙的是另一类:话已说一半、工具已发出,这时出错,不能原样重发。 +- [p4-17d] 原样重发一次,同一个动作就跑了两遍。 +- [p4-17e] 它的做法是保住已产出的,插一条「没写完」的标记,从断点接着来。 +- [p4-17f] 顺带给个刻度:默认最多重试十次,上限十五次。 +- [p4-19] 拆源码的人还提了个冷静设计:续写要是连着几次没写出新东西, - [p4-20] 系统就直接判定——再续也没有产出,停。不恋战,也是一种能力。 -- [p4-21] 出错不是终点。这话写在章首,也确实是这套系统的性格。 +- [p4-21] 出错不是终点——这确实是这套系统的性格。 - [p4-21a] 官方还有个兜底的后悔药:改动可以回退到前面的检查点—— - [p4-21b] 不过它只看文件改动,跑过的命令改过的外部状态,不在里面。 - [p4-22] 你会发现每一级补救都带着上限:升一次、续三次、等三十二秒、换一次人。 @@ -153,7 +160,7 @@ ## P5 桌子换了五样,环没动 > 画面:五样装置在桌上归位成一组;环从桌后浮到前景(系列锚第二次出场),桌子淡为线稿。 -> 角标:五章增量全部为「外挂」· while 骨架未换(实测 @ 67a9126c) +> 角标:五段增量全部为「外挂」· while 骨架未换(实测 @ 67a9126c) - [p5-01] 收个尾。这一集的五样东西摆在一起看: - [p5-02] 钉在桌上的清单,另开的副桌,按需翻开的目录,每轮重拼的垫纸,桌边的补救梯。 @@ -161,12 +168,9 @@ - [p5-04] 清单负责「别忘」,副桌负责「别堵」,目录负责「别贪」, - [p5-05] 垫纸负责「别写死」,梯子负责「别断」。 - [p5-06] 别忘、别堵、别贪、别写死、别断——五句话合起来,就是视野管理。 -- [p5-07] 你会发现一个熟悉的形状:这些装置没有一样是写进循环里的。 -- [p5-08] 清单是一个工具,副桌是一次调用,目录是一张注册表, -- [p5-09] 垫纸是一次拼装,梯子是一层包裹。全部挂在循环外面。 -- [p5-10] 循环自己呢?我把这几章的代码逐一比过: -- [p5-11] 加催更计数、加派活工具、加目录扫描、加一层试错包裹——每一处都是外挂, -- [p5-12] 那句「不停问模型」的骨架,一个字没换。 +- [p5-07] 你会发现一个熟悉的形状:这五样,没有一样写进循环。 +- [p5-08] 清单是工具,副桌是调用,目录是注册表,垫纸是拼装,梯子是包裹。 +- [p5-09] 我逐一比过这些增量代码:加的全是外挂,那句「不停问模型」一个字没换。 - [p5-13] 视野越管越细,桌子越换越讲究,桌子后面那个循环纹丝不动。 - [p5-14] 所以它干活越来越稳,不是它变聪明了。 - [p5-15] 是有人替它把视野管了起来。 @@ -174,15 +178,16 @@ ## P6 落点与信源 -> 画面:一句话合同金句卡 → 信源卡(官方文档+取数日期 / 第三方源码分析已逐处标注)→ 系列身份卡 → 渐黑。 +> 画面:信源卡(官方文档+取数日期 / 第三方源码分析已逐处标注)→ 一句话合同金句卡 → 五格层进度条 → 渐黑。 +> **改序说明(2026-08-28)**:口播已按「免责两句 → 金句 → 预告」重排(p6-07/p6-08 物理前置,句 id 不重编)。 > 渐黑窗口从末 beat 总时长推导(红线四)。 +- [p6-07] 本片机制依据官方文档,取数2026年8月,以官方最新表述为准。 +- [p6-08] 涉及产品内部的部分,为第三方源码分析,片中已逐处标注。 - [p6-01] 视野是安排出来的。安排它的,不是模型自己。 - [p6-02] 这句话对人也成立:你的注意力在哪,多半也不是你自己定的, - [p6-03] 是你桌上摆了什么、谁在什么时候塞了张纸给你。 - [p6-04] 五样零件里,清单那件刚被收回去——零件押的是「模型记不住」的赌注。 - [p6-05] 模型变强,赌注就过期。官方留了句自省的话:常问自己,可以停掉哪一件。 - [p6-06] 桌子会换,零件会瘦,那个循环一直没停过。 -- [p6-07] 本片机制依据官方文档,取数2026年8月,以官方最新表述为准。 -- [p6-08] 涉及产品内部的部分,为第三方源码分析,片中已逐处标注。 -- [p6-09] 下期,拆管记忆的那一层:桌面太满怎么收拾,什么必须留下。下期见。 +- [p6-09] 下期:它会忘,而且忘得有章法——但有一样东西,它永远不许忘。下期见。 diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md index 595a47b4..e99dd24a 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/storyboard.md @@ -12,16 +12,18 @@ |---|---|---|---| | 0-A | p0-01..03 | 系列同款终端:任务单首行被工具输出顶出可视区、走秒芯片跳动;第三句出口时右下角闪一枚「收回」钢印红色虚影,停半拍淡出 | 打字机推进 + 首行任务单向上滚出(残影停在顶端变 `dim`);p0-03「收回」钢印砸下(`deny` 色虚影、scale 过冲)后淡出——退位悬念第一分钟埋下 | | 0-B | p0-04..05 | 终端缩小上移,下方铺开「桌面」:全部对话内容平铺成色块行,任务单色块被越推越远 | 桌面色块逐块落下堆高;任务单色块(`core` 描边)持续被推向右端、被挤出桌沿淡出;p0-05 主线问句两行 `serif` 浮入 | -| 0-C | p0-06..08 | 桌面定格;环(`core`)在桌后浮现(半透明);答句「不是——有一整套装置」压屏;五样装置图标列队 | 环描线一圈但保持 35% 透明度(「今天讲桌子,环在后面看着」);五样装置小图标自左向右依次点亮(清单/副桌/目录/垫纸/梯子),p0-08 收束 | +| 0-C | p0-06..09 | 桌面定格;环(`core`)在桌后浮现(半透明);答句「不是——有一整套装置」压屏;五样装置图标列队;**四件套标尺**(p0-08/09:循环/工具/上下文管理/护栏四格横排,前两格与末格 `panelBorder` 虚线 `dim` 字不点亮,「上下文管理」格以 `view` 描边点亮但只填左半格,格下小字「今天补前半」) | 环描线一圈但保持 35% 透明度(「今天讲桌子,环在后面看着」);五样装置小图标自左向右依次点亮(清单/副桌/目录/垫纸/梯子);p0-08 起标尺自桌下升起、四格逐格描边;p0-09 起「上下文管理」格左半以 `viewDeep` 线性填充(24 帧),格下小字浮现 | ## P1 把清单钉在桌上 | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 1-A | p1-01..03 | 桌面主舞台。右侧滑入第一样装置:一张三态清单卡(pending/in_progress/completed 三行,`view` 描边) | 清单卡滑入落桌;三行状态图标依次闪现(空格→▸→✓ 各一次演示态) | -| 1-B | p1-04..09 | 清单卡「啪」地钉进对话流:桌面上的色块流里插入一张始终可见的 `view` 卡;工具输出继续堆积但推不动它 | 图钉落下(spring 过冲)+ 卡固定在桌面左上;后续色块撞上卡被「顶开」滑落——「钉住」的物理感 | +| 1-B | p1-05..09 | 清单卡「啪」地钉进对话流:桌面上的色块流里插入一张始终可见的 `view` 卡;工具输出继续堆积但推不动它 | 图钉落下(spring 过冲)+ 卡固定在桌面左上;后续色块撞上卡被「顶开」滑落——「钉住」的物理感 | | 1-C | p1-10..13 | 左下角小代码卡:注册表两行 diff(TOOLS+1 / TOOL_HANDLERS+1,`mech` 高亮);右侧金句卡 | 两行 diff 逐行高亮;p1-12 金句卡 `serif` 淡入「增加的不是执行能力,是规划能力」 | -| 1-D | p1-14..19 | **退位帧**:官方公告条压入——新一代模型上清单工具默认不再安装;「收回」钢印盖在清单卡上(`deny` 虚影);「押注押到期」标签;任务系统预告一句 + 「装在循环外的能力」收束 | 官方公告条淡入(code.claude.com 口径角标);钢印砸下带过冲与涟漪;任务系统小图标一闪(「以后单拆」);p1-18/19 金句短卡 | +| 1-D | p1-14..15 | **退位帧**:官方公告条压入——新一代模型上清单工具默认不再安装;「收回」钢印(`motifs.Stamp`,`deny`,damping:12 过冲 + ripple)盖在清单卡上;「押注押到期」标签 | 官方公告条淡入(code.claude.com 口径角标);钢印砸下带过冲与涟漪,容器同帧 `translateY(3px)` 下沉、8 帧回弹;被盖章的 `todo_write` 卡本体有反应:描边由 `view` 褪为 `panelBorder`、三行状态字依次划线、整卡下沉 12px 并降到 0.45 透明 | +| 1-E | p1-15a..15e | **新镜「计划闸」**:只读探索的手伸向文件,被一层玻璃罩罩住(`mech` 描边 + 8% 白底);一张 `view` 描边的计划卡从上落桌;「改文件」动作块撞上玻璃罩被弹回;三选一按钮横排(自动闸门/逐条点头/继续再想,反枚举:`panel` 底 + 编号 01/02/03,仅当前项染 `mech`);末句金句卡 | p1-15a 玻璃罩自上罩下(spring);p1-15b 计划卡落桌(damping:200);p1-15c 动作块撞罩 `deny` 弹回(复用 3-C 单向阀 bounce 曲线);p1-15d 三按钮逐个描边亮起;p1-15e 切 `QuoteCard`「清单写给它,计划写给你」 | +| 1-F | p1-16..19 | 任务系统预告一句(带依赖/能锁/落盘小图标)+「装在循环外的能力」收束;**零件生命周期时间轴**:左端「模型记不住 → 需要清单」、右端「模型记住了 → 清单过期」 | 任务系统小图标一闪(「以后单拆」);时间轴描出,一枚 `core` 光点自左滑向右,抵达右端时清单卡彻底消失;p1-18/19 金句短卡 | ## P2 另开一张副桌 @@ -43,7 +45,7 @@ | 3-C | p3-08..10 | 预算硬顶:目录排上方一条 `mech` 预算横杆(~1%/上限标注);取手册走「注册表名→内容」的单向阀,不走文件路径 | 横杆落下限位;路径请求(`../` 字样卡)撞上单向阀被 `deny` 弹回——防目录穿越 | | 3-D | p3-11..15 | 垫纸(system prompt)登场:桌面最大的一张 `view` 纸,从「一整块写死」碎成四段卡(身份/工具/工作目录/相关记忆) | 写死整纸先满屏铺开(`dim`);碎裂动画拆成四段卡;每轮循环四段卡重新拼装一次(滑入对齐) | | 3-E | p3-16..19 | 「真实状态」验证:左侧「查注册表/查文件存在」两个探针动作;右侧被否决的「猜关键词」路径(消息里高亮词 + 问号)打叉 | 探针(`mech` 小手)点向分发表与文件图标,各亮一次;关键词路径整条 `deny` 划掉;拼装结果盖「cache hit」章 | -| 3-F | p3-20..26 | ★深挖帧:静态/动态段落分层图——所有段落卡排成两层进缓存仓;唯独「外接工具段」卡被闸在仓外(`deny` 拦杆 + 掉线抖动);体量对比角标(两行 vs 两三万字) | 段落卡依次入仓盖章;外接段卡靠近仓门被拦杆挡住、卡身闪断(模拟掉线);p3-25 收束句浮现 | +| 3-F | p3-20..26 | ★深挖帧:先是**官方削层**——整块垫纸剖面从满高削掉八成(p3-21),旁边评测计分板数字纹丝不动并打勾,压字「删掉八成以上,评测不掉分 · 官方 2026-07」;随后静态/动态段落分层图:所有段落卡排成两层进缓存仓,唯独「外接工具段」卡被闸在仓外(`deny` 拦杆 + 掉线抖动) | p3-20 体量角标浮现(三级归属:源码分析);p3-21 剖面 height 由 100% 插值到 20%(24 帧),削掉的部分向上碎裂淡出,计分板打勾;p3-21a 金句短卡;p3-22 起段落卡依次入仓盖章,外接段卡靠近仓门被拦杆挡住、卡身闪断(模拟掉线);p3-25 收束句浮现 | ## P4 桌边的补救梯 @@ -52,20 +54,24 @@ | 4-A | p4-01..02 | 桌子右缘挂下一张三级木梯(`mech` 骨架),梯级暂空 | 梯子自上垂下挂稳(rope 微弹) | | 4-B | p4-03..07 | 一级梯「话没说完」:输出文本条中途断截;额度标尺 8K→64K 弹簧拉长一次;续写卡贴上断口,卡上写「别道歉,别复述,接着说」(角标注明为源码提示原文意译) | 文本条断口处闪 `deny`;标尺拉伸回弹原请求重放;三次续写计数点逐个亮,亮满即封条 | | 4-C | p4-08..10 | 二级梯「桌上太满」:整桌色块压缩成一张摘要卡,桌面清空大半;第二张摘要卡试图再压时被 `deny` 拦停 | 色块群被吸成一张卡(收缩动画);第二次压缩箭头刚起就被拦杆挡下、桌上浮「退出」 | -| 4-D | p4-11..17 | 三级梯「门外施工」:桌外一枚过载/限流警示牌落下;等待条从 0.5s 起翻倍生长(0.5→1→2→4→…→32s 封顶横杠),条身带抖动毛边;三连 529 后模型名牌翻面换人 | 警示牌砸落抖动;等待条按节拍翻倍伸长、撞上 32s 封顶杠「当」一声定格;名牌翻转露出备用模型;角标「十几种恢复路径(实测 17)· 第三方的源码分析」 | -| 4-E | p4-18..22 | 收益递减:产出曲线三次爬升依次趋平,第三次的增量 < 阈值标线,系统盖「停」章;**检查点卡**(p4-21a/b:改动回退到检查点,只含文件改动——命令与外部状态不在其中);末句金句卡 | 曲线逐段绘制、斜率递减;标线横贯;「停」章(`deny`)落下;检查点卡自下滑入;p4-22 金句「每一级补救,都带着上限」淡入 | +| 4-D | p4-11..17 | 三级梯「门外施工」:桌外一枚过载/限流警示牌落下;等待条从 0.5s 起翻倍生长(0.5→1→2→4→…→32s 封顶横杠),条身带抖动毛边;一张「稍后再来」字条贴上并改写等待值;三连 529 后模型名牌翻面换人 | 警示牌砸落抖动(p4-11);等待条按节拍翻倍伸长、撞上 32s 封顶杠「当」一声定格(p4-12);抖动毛边随机化一次(p4-13);字条飘落覆盖公式值(p4-14);名牌翻转露出备用模型(p4-17);角标「恢复路径实测 17 条 · 第三方的源码分析」 | +| 4-D2 | p4-17a..17f | **新镜「不重试的两类」**:梯子右侧岔出一条 `deny` 色分叉轨,轨口牌子「不重试」;一枚证书图标滑上轨、第一帧就打红叉并弹「去修它」;屏幕中央一条输出文本条断在半途 + 一枚已发出的工具调用卡;★形变帧:工具卡**原地分裂成两张**各跑一遍同样的动作、右下角计数器 1→2,压字「同一个动作跑了两遍」;两卡收回成一张并贴「没写完」标签,`core` 光点从上一个已完成调用处续向右;右下角刻度盘 0→10、外圈虚线刻到 15 | p4-17a 分叉轨 `pathLength` 描线 26 帧;p4-17b 证书卡滑入即打叉;p4-17c 文本条断口 ▌ 闪烁 + 工具卡同帧闪 `deny`;p4-17d 工具卡 scaleX 1→2 中缝裂开成两张、计数器滚动;p4-17e 两卡合一 + 标签贴上 + 光点续接;p4-17f 刻度盘 `Counter` 0→10(20 帧),外圈 dashed 描边 +「上限 15」小字 | +| 4-E | p4-19..22 | 收益递减:产出曲线三次爬升依次趋平,第三次的增量 < 阈值标线,系统盖「停」章(角标「第三方的源码分析」);**检查点卡**(p4-21a/b:改动回退到检查点,只含文件改动——命令与外部状态不在其中);末句金句卡 | 曲线逐段绘制、斜率递减;标线横贯;「停」章(`deny`)落下;检查点卡自下滑入;p4-22 金句「每一级补救,都带着上限」淡入 | ## P5 桌子换了五样,环没动 | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| | 5-A | p5-01..06 | 五样装置在桌面上归位成一组(清单卡/副桌缩略/目录卡/垫纸/梯子缩略),各配一字职责(别忘/别堵/别贪/别写死/别断) | 五装置自左向右滑入归位;各配的职责字以印章形式逐枚落下 | -| 5-B | p5-07..12 | ★系列锚帧:环从桌后浮到画面中央(第二次出场,同色同宽同节点),桌子与五装置整体淡为线稿退后 | 环描线一遍 + 亮度升至 100%;桌子线稿化(描边保留填充淡出);角标「五章增量全部为外挂 · while 骨架未换(实测 @ 67a9126c)」 | +| 5-B | p5-07..09 | ★系列锚帧:环从桌后浮到画面中央(第二次出场,同色同宽同节点),桌子与五装置整体淡为线稿退后;五条外挂虚线把五样装置逐条挂到环外 | p5-07 环起浮(riseAt);p5-08 环描线一遍 + 亮度升至 100%、桌子线稿化(描边保留填充淡出);p5-09 五条挂钩虚线按 `strokeDashoffset` 逐条描出(stagger i×6 帧);角标「五段增量全部为外挂 · while 骨架未换(实测 @ 67a9126c)」 | | 5-C | p5-13..16 | 金句帧:环居中,桌上线稿,两行落点字 | 「不是它变聪明了 / 是有人替它把视野管了起来」逐行淡入(`serif`,`core`) | ## P6 落点与信源 +> **改序说明(2026-08-28)**:口播已按「免责两句 → 金句 → 预告」重排——p6-07/p6-08 物理前置于 p6-01(句 id 不重编,TTS 缓存键不涉序)。镜号随之重排:6-A=信源前置、6-B=金句、6-C=收束+身份卡+进度条+渐黑。**video/src P6Ending.tsx 的 Sequence 拆分(bA0=w('p6-07','p6-08') 等)与渐黑窗口重推导由视觉侧同步落地。** + | 镜 | 句区间 | 画面 | 动效 | |---|---|---|---| -| 6-A | p6-01..04 | 一句话合同金句卡(`serif`,`view` 描边)→ 三行人味延伸小字 | 金句卡淡入;p6-04「同一门手艺」次行浮现 | -| 6-B | p6-05..09 | 信源卡(官方文档+取数日期 / 第三方源码分析已逐处标注 / 数字均为实测口径→ 系列身份卡 → **渐黑**(窗口从本 beat 总时长推导,红线四) | 信源卡逐行浮现;身份卡 `serif` 淡入;末 1.2s 线性压暗到全黑 | +| 6-A | p6-07..08 | **信源前置**:信源卡两行(官方文档+取数日期 / 第三方源码分析已逐处标注)压屏 | 信源卡逐行浮现(前置到幕首,免责只走画面不占情绪高点) | +| 6-B | p6-01..06 | 一句话合同金句卡(`serif`,`view` 描边)→ 三行人味延伸小字 →「清单退位/赌注过期/自省句」「桌子会换循环不停」次行 | 金句卡淡入;p6-02/03 人味延伸两行逐行浮现;p6-04/05 赌注到期+官方自省句短卡;p6-06「循环没停过」一行收进金句卡底部 | +| 6-C | p6-09 | **五格层进度条**(执行/规划/记忆/时机/协作横排:已播层 `dim` 常亮、当前层 `core` 高亮描边+底部指示条、未播层 `panel` 底+编号,反枚举不用五色);上方压 0-C 四件套标尺定格缩略(「上下文管理」格保持半亮);下期文案一行挂进度条下方 → **渐黑** | 进度条自左滑入、当前格描边点亮;标尺缩略淡入(一帧完成「轮内四件套 / 轮外五层」映射);下期行打字机两拍;末 1.2s 线性压暗到全黑(窗口从本 beat 总时长推导,红线四) | From 2e26f1eedf695f27cd57583e23b5c4d4aab5e1b9 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Fri, 28 Aug 2026 19:16:32 +0800 Subject: [PATCH 29/41] =?UTF-8?q?feat(video):=20B=20=E6=96=B9=E6=A1=88?= =?UTF-8?q?=E8=A7=86=E8=A7=89=E4=BE=A7=E2=80=94=E2=80=94=E4=BA=94=E9=9B=86?= =?UTF-8?q?=E5=9C=BA=E6=99=AF=E7=AA=97=E5=8F=A3=E5=AF=B9=E9=BD=90=E6=96=B0?= =?UTF-8?q?=E5=88=86=E9=95=9C=20+=20=E6=96=B0=E9=95=9C=E8=90=BD=E5=9C=B0;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit storyboard 为 SSOT,beatWindow/at 锚全面对齐改稿后的句区间(删句/字母后缀句/收尾免责前置)。 新镜:EP1 3-D2 沙箱横切面 + 4-G1 六闸三球对照 + 0-B 官方赌注卡 + 3-G 审判者成绩单; EP2 1-E 计划闸(玻璃罩/三选一)+ 1-F 零件生命周期 + 4-D2 不重试两类(形变帧)+ P6 改序三镜 + 0-C 四件套标尺;EP3 0-B 装载清单 + 0-C 上下文腐坏双轴 + 0-C2/6-C 四件套标尺(新组件 HarnessScale)+ 4-C 层位纠正插段 + 4-E 前缀缓存/向量库虚影;EP4 P5 五镜复位 + P6 改序 + 6-B 四件套回收条;EP5 1-C/2-C/2-D/3-B 窗口复位 + 4-E 官方战例镜(16 容器网格/锁文件占坑/ 战果条/冻霜级联/二分收敛)+ 6-E 第一定律段。 死锚全清(scenes 内全部句 id 均存在于 narration.json);五集 tsc 零错误; check --check-scenes 0 FAIL 0 WARN(除预期 manifest 项)。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) --- .../video/src/scenes/P5Truths.tsx | 233 ++++---- .../video/src/scenes/P6Ending.tsx | 302 +++++++---- .../video/src/components/motifs.tsx | 7 +- .../video/src/scenes/P0Hook.tsx | 167 ++++-- .../video/src/scenes/P1Loop.tsx | 96 +++- .../video/src/scenes/P2Dispatch.tsx | 12 +- .../video/src/scenes/P3Gates.tsx | 376 ++++++++++++- .../video/src/scenes/P4Hooks.tsx | 150 +++++- .../video/src/scenes/P6Ending.tsx | 73 ++- .../video/src/components/HarnessScale.tsx | 137 +++++ .../video/src/scenes/P0Reject.tsx | 504 ++++++++++++++---- .../video/src/scenes/P4Ledger.tsx | 316 +++++++++-- .../video/src/scenes/P6Ending.tsx | 402 ++++++++++---- .../video/src/scenes/P0Hook.tsx | 5 +- .../video/src/scenes/P1Board.tsx | 2 +- .../video/src/scenes/P2Mail.tsx | 249 +++++++-- .../video/src/scenes/P3Handshake.tsx | 25 +- .../video/src/scenes/P4Autonomy.tsx | 433 ++++++++++++++- .../video/src/scenes/P6Finale.tsx | 123 ++++- .../video/src/scenes/P0Hook.tsx | 107 +++- .../video/src/scenes/P1Plan.tsx | 395 ++++++++++++-- .../video/src/scenes/P2SideDesk.tsx | 3 +- .../video/src/scenes/P3Manual.tsx | 196 ++++++- .../video/src/scenes/P4Ladder.tsx | 349 +++++++++++- .../video/src/scenes/P5Ring.tsx | 52 +- .../video/src/scenes/P6Ending.tsx | 342 ++++++++---- 26 files changed, 4193 insertions(+), 863 deletions(-) create mode 100644 apps/negentropy-influence/episodes/claude-code-memory-video/video/src/components/HarnessScale.tsx diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx index 34cba50b..bea8e8c0 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx @@ -1,12 +1,12 @@ /** P5 时间表的真话(分镜 5-A…5-E) - * ★踩踏帧(一排表全指 9:00 齐射)→ ★确定性抖动(固定偏移错峰 / 随机漂移对照) - * → 七天退休章 → 诚实边界(进程灯灭秒摆停)→ 上限 50/低优先级/金句。 */ + * ★踩踏帧(一排表全指 9:00 齐射)→ ★确定性抖动(固定偏移错峰 / 随机漂移 / 整点提前一分半) + * → 七天退休章 → 诚实边界(p5-13 终端关了表停被 deny 斜划 → p5-14 管家进程接管) + * → 上限 50/低优先级 → 金句卡 → 自定速发条(p5-23a/b)。 */ import React from 'react'; import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoConfig} from 'remotion'; import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {QuoteCard} from '../components/cards'; import {Footnote, Panel, SceneHeader, SceneTag} from '../components/motifs'; /** 迷你钟面:时针/分针可指定角度,可选表盘描边色 */ @@ -291,9 +291,11 @@ const RetireStamp: React.FC<{flipAt: number; stampAt: number}> = ({flipAt, stamp ); }; -/** 5-D 官方新答案:后台会话由独立管家进程托管(Harness Engineering 改造版) - * 六状态记账、行摘要小模型、状态落盘穿重启、接回从停点续跑。 */ -const SupervisorFrame: React.FC<{supAt: number; statesAt: number; persistAt: number; resumeAt: number}> = ({ +/** 5-D 诚实边界 + 官方新答案:p5-13 旧真话(终端关了表停)被 deny 斜划, + * p5-14 管家进程 spring 立起把它推成虚影;六状态记账、行摘要小模型、 + * 状态落盘穿重启、接回从停点续跑(Harness Engineering 改造版)。 */ +const SupervisorFrame: React.FC<{denyAt: number; supAt: number; statesAt: number; persistAt: number; resumeAt: number}> = ({ + denyAt, supAt, statesAt, persistAt, @@ -301,6 +303,10 @@ const SupervisorFrame: React.FC<{supAt: number; statesAt: number; persistAt: num }) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); + const deny = interpolate(frame - denyAt, [0, 12], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); const sup = spring({frame: frame - supAt, fps, config: {damping: 200}}); const states = ['排队', '跑着', '等审批', '被拦', '收尾', '完事']; const persist = interpolate(frame - persistAt, [0, 22], [0, 1], { @@ -311,18 +317,60 @@ const SupervisorFrame: React.FC<{supAt: number; statesAt: number; persistAt: num extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); + // 旧真话卡被管家立起后推成虚影(p5-14 起) + const ghost = 1 - sup * 0.72; return (
- {/* 管家进程:不眠的眼睛 */} + {/* p5-13 旧真话卡:终端图标 + 「进程关了 → 表停」→ p5-14 被 deny 斜划 + 推成虚影 */}
+
+ + {/* 终端窗(P1 母题缩略) */} + + + + + +
+ {'把进程关了,'} + {'表就停了'} +
+ {/* deny 斜划(p5-13 尾段落下) */} + + + +
+
+ {/* p5-14 管家进程:不眠的眼睛,spring 立起 */} +
@@ -339,7 +387,7 @@ const SupervisorFrame: React.FC<{supAt: number; statesAt: number; persistAt: num
{/* 六状态小环 */} -
+
{states.map((s, i) => { const e = interpolate(frame - statesAt - i * 6, [0, 10], [0, 1], { extrapolateLeft: 'clamp', @@ -364,13 +412,13 @@ const SupervisorFrame: React.FC<{supAt: number; statesAt: number; persistAt: num ); })}
- {/* 状态落盘 + 穿重启 */} + {/* 状态落盘 + 穿重启(p5-15) */} {persist > 0 ? (
) : null} - {/* 接回续跑 */} + {/* 接回续跑(p5-18) */} {resume > 0 ? (
= ({lowAt, windAt, quoteAt}) => { +/** 5-E 上限 50/50 + 低优先级标记排队尾(p5-19..22)→ 金句卡(p5-23) + * → 自定速发条(p5-23a/b:干完一轮顺手定下一次,间隔自己定——金句上移让位,不发条不盖金句)。 */ +const CapAndQuote: React.FC<{lowAt: number; quoteAt: number; windAt: number}> = ({lowAt, quoteAt, windAt}) => { const frame = useCurrentFrame(); + const {fps} = useVideoConfig(); + const quoteE = spring({frame: frame - quoteAt, fps, config: {damping: 200}}); + const wind = spring({frame: frame - windAt, fps, config: {damping: 200}}); if (frame >= quoteAt) { return ( - + + {/* 金句卡:wind 阶段上移收小,给发条让位 */} +
+
+ {'定时这件事,想象很浪漫,'} +
+ {'工程都在打补丁。'} +
+
+ {/* p5-23a/b 自定速发条:干完一轮 → 顺手拨出下一格(间隔自己定,不靠墙上的钟) */} +
+
+ + {/* 发条旋钮:自转一圈、拨出一格 */} + + {Array.from({length: 8}, (_, i) => { + const a = ((i * 45 + (frame / 2.2) * 45) * Math.PI) / 180; + return ( + + ); + })} + + +
+
+ {'干完一轮,顺手定下一次 —— 间隔自己定'} +
+
+ {'不靠墙上的钟,靠它自己的一句「回头再来」'} +
+
+
+
+ {'自定速:任务自己排自己的下一次 —— 官方文档 scheduled-tasks'} +
); } const low = interpolate(frame - lowAt, [0, 18], [0, 1], { @@ -484,62 +589,6 @@ const CapAndQuote: React.FC<{lowAt: number; windAt: number; quoteAt: number}> =
- {/* p5-23a/b 自定速发条:干完一轮 → 顺手拨出下一格(间隔自己定,不靠墙上的钟) */} - {frame >= windAt ? ( -
-
- - {/* 发条旋钮:自转一圈、拨出一格 */} - - {Array.from({length: 8}, (_, i) => { - const a = ((i * 45 + (frame / 2.2) * 45) * Math.PI) / 180; - return ( - - ); - })} - - -
-
- {'干完一轮,顺手定下一次 —— 间隔自己定'} -
-
- {'不靠墙上的钟,靠它自己的一句「回头再来」'} -
-
-
-
- ) : null} {'上限与低优先级标记 —— 第三方的源码分析'} ); @@ -549,9 +598,9 @@ export const P5Truths: React.FC<{scene: SceneRange}> = ({scene}) => { const w = (fromId: string, toId?: string) => beatWindow(scene.sentences, scene.from, fromId, toId); const at = (id: string) => w(id).from; const bA = w('p5-01', 'p5-04'); - const bB = w('p5-05', 'p5-08'); - const bC = w('p5-09', 'p5-10'); - const bD = w('p5-11', 'p5-18'); + const bB = w('p5-05', 'p5-10'); + const bC = w('p5-11', 'p5-12'); + const bD = w('p5-13', 'p5-18'); const bE = w('p5-19', 'p5-23b'); return ( @@ -560,27 +609,33 @@ export const P5Truths: React.FC<{scene: SceneRange}> = ({scene}) => { - {/* 提前 90 秒的口播落在下一镜(p5-09),但分镜 5-B 动效列要求逆行箭头—— - 锚在本镜末句尾段,先给视觉再由下镜口播收口 */} + {/* 整点提前 90 秒口播(p5-09/10)已并入本镜——逆行箭头锚 p5-09 句首 */} - + - {/* p5-15 讲「持久化保存的是定义」但属下一镜句区间——抽屉锚在本镜末句尾段展示, - p5-15 口播接续解释(镜内画面与镜间口播的刻意交叠) */} - + {/* p5-13 旧真话 deny 斜划(末句尾落下)→ p5-14 管家立起; + p5-15 状态落盘、p5-16 六状态、p5-18 接回续跑 */} + + {/* p5-19 容量;p5-21 低优先级;p5-23 金句;p5-23a/b 自定速发条(金句上移让位) */} diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx index d37472a8..cf62adf8 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx @@ -1,6 +1,9 @@ /** P6 落点与信源(分镜 6-A…6-C) - * 三种开始三段位置图(位置编码,不用三色)+ 共享小环匀速贯穿 → 一句话合同金句卡 - * → 信源卡 + 身份卡 + 渐黑(末 beat 总时长推导,skills/06 红线四)。 */ + * 三种开始三段位置图(位置编码,不用三色)+ 共享小环匀速贯穿 + * → 6-B 免责两句前置(p6-13/14 信源样式小字)→ 一句话合同金句卡(p6-07) + * → p6-09「钟挪进不睡的管家」过渡 →「守时的自主」边界两句 → 四件套回收条 + * (p6-12 循环/工具/上下文管理/护栏;p6-12a 本集钉进「循环」格,仅循环格 core 描边+呼吸辉光) + * → 6-C 身份卡 → 下期卡 → 渐黑(末 beat 总时长推导,skills/06 红线四)。 */ import React from 'react'; import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoConfig} from 'remotion'; import {theme} from '../design/theme'; @@ -167,61 +170,184 @@ const ThreePositions: React.FC<{l1: number; l2: number; l3: number; layerAt: num ); }; -/** 6-B 一句话合同金句卡(core)+ 边界两句小字跟随 */ -const ContractQuote: React.FC<{boundAt: number}> = ({boundAt}) => { +/** 6-B 免责两句前置(p6-13/14 信源样式小字)→ 一句话合同金句卡(p6-07) + * → p6-09 钟挪进管家过渡 → 守时的自主边界两句(p6-10/11) + * → 四件套回收条(p6-12)+ 本集钉进「循环」格(p6-12a)。 */ +const ContractAndRecap: React.FC<{disclaim2At: number; quoteAt: number; boundAt: number; fourAt: number; pinAt: number}> = ({ + disclaim2At, + quoteAt, + boundAt, + fourAt, + pinAt, +}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); - const enter = spring({frame: frame - 4, fps, config: {damping: 200}}); - const bound = interpolate(frame - boundAt, [0, 18], [0, 1], { + // 免责两行:p6-13 句首浮出第一行,p6-14 句锚浮出第二行(信源样式小字) + const d1 = interpolate(frame - 6, [0, 12], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const d2 = interpolate(frame - disclaim2At, [0, 12], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 金句卡(p6-07)spring 淡入;免责区随之淡出让位 + const quote = spring({frame: frame - quoteAt, fps, config: {damping: 200}}); + const disclaimGone = interpolate(frame - quoteAt, [0, 16], [1, 0], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // p6-09 过渡 + p6-10/11 边界两句 + const clock = interpolate(frame - boundAt, [0, 18], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 四件套回收条(p6-12)四格依次亮 + const four = interpolate(frame - fourAt, [0, 16], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const FOUR = ['循环', '工具', '上下文管理', '护栏']; + // p6-12a 本集钉进「循环」格:core 描边 + 呼吸辉光(帧驱动 sin,确定性) + const pin = interpolate(frame - pinAt, [0, 14], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); + const glow = 0.55 + 0.45 * Math.sin(frame / 5); return ( - -
-
- {'按下的不一定是它,'} -
- {'等的一定不是你。'} -
+ + {/* 免责两句前置:信源样式小字(p6-13 官方文档 / p6-14 第三方标注) */} + {disclaimGone > 0.01 ? ( + +
+
+ {'本片机制依据官方文档 · 取数 2026 年 8 月,以官方最新表述为准'} +
+
+ {'产品内部的部分为第三方源码分析 · 片中已逐处标注'} +
+
+
+ ) : null} + {/* 一句话合同金句卡 + 边界两句(p6-07 起,随后 p6-09..11 跟随; + paddingBottom 抬高中线——p6-12 四件套回收条在 bottom:246 带下方让位) */} + {quote > 0 ? ( + +
+
+ {'按下的不一定是它,'} +
+ {'等的一定不是你。'} +
+ {/* p6-09「钟挪进不睡的管家」过渡 + p6-10/11 守时的自主边界 */} +
+ {'钟曾经装在它身体里,现在挪进了一个不睡的管家。'} +
+ + {'它的自主,到此为止是「守时的自主」——'} +
+ {'「自己决定该干什么活」是更大的一步,我们后面再拆。'} +
+
+
+
+ ) : null} + {/* 四件套回收条(p6-12 四格依次亮;反枚举:四格不给四色)。 + 带 bottom:246 与 6-A「机制外挪」同一水平带,避开 Footnote(bottom:168)压字 */} + {four > 0 ? (
- {'有人在等它,但它从不等你;它也开始学着不等任何东西。'} -
- {'时钟装在它的身体里,不在墙上 —— 守时的自主'} + {FOUR.map((t, i) => { + const cell = interpolate(frame - fourAt - i * 6, [0, 10], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const isLoop = i === 0; + return ( +
+
0 ? `3px solid ${theme.core}` : `2px solid ${theme.panelBorder}`, + background: isLoop && pin > 0 ? `${theme.coreDeep}` : theme.panel, + fontFamily: theme.sans, + fontSize: 26, + color: isLoop && pin > 0 ? theme.text : theme.dim, + opacity: cell, + whiteSpace: 'nowrap', + boxShadow: isLoop && pin > 0 ? `0 0 ${26 * glow}px ${theme.core}` : 'none', + }} + > + {t} +
+ {/* p6-12a 本集钉进「循环」格:图钉落下 */} + {isLoop && pin > 0 ? ( + + + + + + ) : null} +
+ ); + })}
-
+ ) : null} + {/* 四件套画像的出处角标(p6-12 起,【二】官方工程博客) */} + + {'循环 · 工具 · 上下文管理 · 护栏 —— 官方工程博客'} +
); }; /** - * 6-C 信源卡 + 身份卡 + 渐黑。 + * 6-C 身份卡 → 下期卡 → 渐黑(单句 p6-15)。 * `beatDurationInFrames` 是**本 beat 的总时长**,渐黑窗口据此反推(红线四: * 不写死帧数、不用末句时长——末句短于 beat 时会提前收尾)。 + * 下期卡在句内后半段浮出:窗口从 beat 总时长按固定比例推导(句锚不可分—— + * 单句镜无第二锚,比例锚定在句中段「为什么还有人这么干」分句处)。 */ -const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> = ({ - beatDurationInFrames, - seriesAt, -}) => { +const IdentityAndFade: React.FC<{beatDurationInFrames: number}> = ({beatDurationInFrames}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); const enter = spring({frame: frame - 4, fps, config: {damping: 200}}); - const rows = [ - ['官方文档', 'code.claude.com/docs · 取数2026年8月'], - ['工程博客', 'anthropic.com/engineering'], - ['源码分析', '第三方逆向分析 · 片中逐处标注'], - ['数字口径', '开源仓库钉版 67a9126c 实测 · 字节归档'], - ]; - const seriesT = interpolate(frame - seriesAt, [0, 20], [0, 1], { + // 下期卡:身份卡稳住一拍后浮出(beat 总时长 × 0.52 处——口播念到 + // 「为什么还有人这么干」时下期卡就位,「下期见」前视觉先到) + const nextAt = Math.round(beatDurationInFrames * 0.52); + const nextT = interpolate(frame - nextAt, [0, 18], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); @@ -234,72 +360,23 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> }); return ( -
- -
- {'信源'} -
- {rows.map(([k, v], i) => ( -
-
- {k} -
-
{v}
-
- ))} - {/* 诚实行:产品内部断言均为第三方的源码分析(【三】归属句的公开落点) */} -
- {'涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注;取证字节已随片归档'} -
-
-
- {seriesT > 0 ? ( +
+
+ {'Claude Code Harness Engineering'} +
-
- {'Claude Code Harness Engineering'} -
-
- {'时机层:谁来按下开始'} -
- {/* 下期预告卡:标题只在画面(反串线纪律) */} + {'时机层:谁来按下开始'} +
+ {/* 下期预告卡:标题只在画面(反串线纪律) */} + {nextT > 0 ? (
border: `1.5px solid ${theme.panelBorder}`, borderRadius: 12, background: theme.panel, + opacity: nextT, + transform: `translateY(${(1 - nextT) * 14}px)`, + display: 'inline-block', }} >
{'下期 · 协作层'}
-
+
{'从一个到一群'}
-
- ) : null} + ) : null} +
{/* 渐黑遮罩 */} @@ -328,8 +408,8 @@ export const P6Ending: React.FC<{scene: SceneRange}> = ({scene}) => { const w = (fromId: string, toId?: string) => beatWindow(scene.sentences, scene.from, fromId, toId); const at = (id: string) => w(id).from; const bA = w('p6-01', 'p6-06'); - const bB = w('p6-07', 'p6-12'); - const bC = w('p6-13', 'p6-15'); + const bB = w('p6-13', 'p6-12a'); + const bC = w('p6-15'); return ( @@ -342,15 +422,19 @@ export const P6Ending: React.FC<{scene: SceneRange}> = ({scene}) => { ringAt={at('p6-06') - bA.from} /> - - + + {/* p6-13/14 免责前置;p6-07 金句;p6-09..11 边界;p6-12 四件套;p6-12a 钉进循环格 */} + - + {/* 渐黑窗口从**本 beat 总时长**推导,不是末句时长(红线四) */} - + ); diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/components/motifs.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/components/motifs.tsx index aabde1fe..3cc4c30e 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/components/motifs.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/components/motifs.tsx @@ -662,7 +662,7 @@ export const SlotRing: React.FC<{ // ─────────────────────────────────────────────────────────── 代码卡 -/** 代码卡:逐行渲染(每行 framesPerLine 帧),可高亮/压暗指定行 */ +/** 代码卡:逐行渲染(每行 framesPerLine 帧,自 startAt 帧起算),可高亮/压暗指定行 */ export const CodeCard: React.FC<{ lines: string[]; framesPerLine?: number; @@ -672,6 +672,8 @@ export const CodeCard: React.FC<{ showLineNumbers?: boolean; glowLineNumbersAt?: number; accent?: string; + /** 逐行渲染的起始帧(默认 0)——前置动画(标签条/对照列)要先占画布时用 */ + startAt?: number; }> = ({ lines, framesPerLine = 3, @@ -681,6 +683,7 @@ export const CodeCard: React.FC<{ showLineNumbers = true, glowLineNumbersAt, accent, + startAt = 0, }) => { const frame = useCurrentFrame(); const glow = @@ -693,7 +696,7 @@ export const CodeCard: React.FC<{ return ( {lines.map((ln, i) => { - const shown = frame >= i * framesPerLine; + const shown = frame - startAt >= i * framesPerLine; const hot = highlight.includes(i); return (
= ({carryAt}) => { ); }; -/** 0-B 命名帧:搬运残影收束成外框,包住「模型」内核——外框即 Harness + 官方引文条 */ -const NamingFrame: React.FC<{officialAt: number}> = ({officialAt}) => { +/** 0-B 命名帧:搬运残影收束成外框,包住「模型」内核——外框即 Harness。 + * p0-03a..c 底部浮出官方赌注卡(SWE-bench 同模型换脚手架 22%→49%); + * 外框合拢改锚 p0-04(「名字就叫」句才落框,消除头空转);p0-05 官方引文条压上。 */ +const NamingFrame: React.FC<{ + betAt: number; + barsAt: number; + settleAt: number; + frameAt: number; + officialAt: number; +}> = ({betAt, barsAt, settleAt, frameAt, officialAt}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); - // 外框四面合拢(spring 收拢感) - const close = spring({frame, fps, config: {damping: 180}}); + // 赌注卡自底浮出(p0-03a,FadeUp 语义) + const bet = interpolate(frame - betAt, [0, 16], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 两条 core 分数条在 320px 轨道上增长(p0-03b:0→22% / 0→49%) + const bars = interpolate(frame - barsAt, [0, 30], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 分数条定格并压「你的力气 = 它的分数」(p0-03c) + const settle = interpolate(frame - settleAt, [0, 12], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 外框四面合拢改锚 p0-04(「名字就叫」句才落框——此前锚 beat 首帧,头两句空转) + const close = spring({frame: frame - frameAt, fps, config: {damping: 180}}); const CX = 960; const CY = 460; const full = 420; const wHalf = full / 2 + (1 - close) * 620; const hHalf = full / 2 + (1 - close) * 380; - const label = interpolate(frame - 22, [0, 14], [0, 1], { + const label = interpolate(frame - frameAt - 22, [0, 14], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); @@ -191,6 +216,83 @@ const NamingFrame: React.FC<{officialAt: number}> = ({officialAt}) => { > {'把动力源,套进一个可控的结构里'}
+ {/* 官方赌注卡(p0-03a..c):bottom:210 避让字幕带;p0-05 引文条压上时让位淡出 */} + {bet > 0 ? ( +
+ +
+ {'“同一个底层模型,换一套脚手架,成绩能差出一大截。”'} +
+ {/* 双分数条:320px 轨道 interpolate 增长(0→22% / 0→49%) */} +
+ {[ + {label: '旧脚手架', v: 0.22}, + {label: '新脚手架', v: 0.49}, + ].map((b) => ( +
+ + {b.label} + +
+
+
+ 0.99 ? 1 : 0.35, + }} + > + {`${Math.round(b.v * Math.min(1, bars) * 100)}%`} + +
+ ))} +
+
0.99 ? 1 : 0, + }} + > + {'SWE-bench Verified 500 题 · 同脚手架代际 22%→49% · 官方自报 2025-01-06'} +
+ {/* p0-03c:分数条定格 + 结论句压上 */} +
+ {'你的力气 = 它的分数'} +
+ +
+ ) : null} {/* 官方引文条(p0-05 句锚) */} {quote > 0 ? (
= ({officialAt}) => { ); }; -/** 0-C 五辐条供给图:外框上长出五根辐条(文件/命令/权限/记忆/护栏)+ 标题卡收尾 */ +/** 0-C 四件套辐条图:外框上长出四根辐条(循环 / 工具 / 上下文管理 / 护栏), + * 内侧连着模型内核(与 p5-05 官方四件套标尺同一张清单——5-A 回指此处)。 + * 「上下文管理」那根先灰(与 5-A 标尺空格、p5-06「后面拆」承诺同构)。 */ const SupplySpokes: React.FC<{titleAt: number}> = ({titleAt}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); @@ -237,11 +341,10 @@ const SupplySpokes: React.FC<{titleAt: number}> = ({titleAt}) => { const CY = 440; const R = 300; const spokes = [ - {label: '文件', zh: '读写项目'}, - {label: '命令', zh: '执行与回传'}, - {label: '权限', zh: '闸门与审批'}, - {label: '记忆', zh: '上下文与规则', later: true}, - {label: '护栏', zh: '拦截与兜底'}, + {label: '循环', zh: '问模型·执行·填回'}, + {label: '工具', zh: '查表分发'}, + {label: '上下文管理', zh: '后面单独拆', later: true}, + {label: '护栏', zh: '闸门·沙箱·插口'}, ]; const title = spring({frame: frame - titleAt, fps, config: {damping: 200}}); const line = interpolate(frame - titleAt, [4, 40], [0, 1], { @@ -270,15 +373,14 @@ const SupplySpokes: React.FC<{titleAt: number}> = ({titleAt}) => { {'模型 Claude'} - {/* 五辐条:自外框上沿五点连向内核 */} + {/* 四辐条:自外框上沿四点连向内核(辐点均布 fx = CX − 225 + i*150) */} {spokes.map((sp, i) => { const t = interpolate(frame - 6 - i * 8, [0, 12], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); if (t <= 0) return null; - // 五点沿外框上沿分布 - const fx = CX - 300 + i * 150; + const fx = CX - 225 + i * 150; const fy = CY - 250; const ix = CX + (fx - CX) * 0.24; const iy = CY - 40; @@ -295,7 +397,7 @@ const SupplySpokes: React.FC<{titleAt: number}> = ({titleAt}) => { style={sp.later ? undefined : {filter: `drop-shadow(0 0 ${4 + glow * 8}px ${theme.mech}88)`}} /> - + {sp.label} @@ -304,26 +406,6 @@ const SupplySpokes: React.FC<{titleAt: number}> = ({titleAt}) => { ); })} - {/* 「记忆」辐条的「后面拆」小标 */} - {(() => { - const o = interpolate(frame - 6 - 3 * 8 - 10, [0, 10], [0, 1], { - extrapolateLeft: 'clamp', - extrapolateRight: 'clamp', - }); - return o > 0 ? ( - - {'后面单独拆'} - - ) : null; - })()} {/* 标题卡(p0-07 收尾压入) */} {title > 0 ? ( @@ -371,9 +453,16 @@ export const P0Hook: React.FC<{scene: SceneRange}> = ({scene}) => { - + {/* p0-03a 赌注卡浮出;p0-03b 双分数条增长;p0-03c 定格+结论;p0-04 外框合拢;p0-05 引文条 */} + - + diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx index f651c910..333ce300 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx @@ -8,7 +8,7 @@ import type {SceneRange} from '../types'; import {QuoteCard} from '../components/cards'; import {CodeCard, Counter, Footnote, LoopRing, Panel, SceneHeader, SceneTag, useRingDot} from '../components/motifs'; -/** 1-A 环形循环成形 + 两个信号分支 */ +/** 1-A 环形循环成形 + 两个信号分支(原 p1-07 已删:「传送带转不转」的语义收在 p1-06 的定格收镜上) */ const RingBirth: React.FC<{yesAt: number; noAt: number}> = ({yesAt, noAt}) => { const frame = useCurrentFrame(); const draw = interpolate(frame, [4, 40], [0, 1], { @@ -16,7 +16,7 @@ const RingBirth: React.FC<{yesAt: number; noAt: number}> = ({yesAt, noAt}) => { extrapolateRight: 'clamp', }); const dot = useRingDot(2.5, 40); - // 讲到「没有」时光点滑出到停机出口并定格 + // 讲到「没有」时光点滑出到停机出口并定格收镜 const pull = interpolate(frame - noAt, [8, 30], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', @@ -147,8 +147,16 @@ const FiveSteps: React.FC<{stepAt: number[]}> = ({stepAt}) => { ); }; -/** 1-C 二十三行代码卡 + 分工左右分屏 */ -const TwentyThreeLines: React.FC<{countAt: number; splitAt: number}> = ({countAt, splitAt}) => { +/** 1-C 二十三行代码卡 + 来源标签条 + 对照列 + 分工左右分屏。 + * p1-12a 卡眉滑入来源标签条(「开源最小实现 · 照着同一套机制搭的」,无具名信息—— + * 教学版锚,先交代这份代码是谁、再开始读);p1-12b 右侧浮出「对照对象:真实产品」 + * 半亮列;随后代码逐行渲染 → 二十三行计数 → 左右分屏。 */ +const TwentyThreeLines: React.FC<{ + tagAt: number; + compareAt: number; + countAt: number; + splitAt: number; +}> = ({tagAt, compareAt, countAt, splitAt}) => { const frame = useCurrentFrame(); const lines = [ 'while True:', @@ -168,15 +176,81 @@ const TwentyThreeLines: React.FC<{countAt: number; splitAt: number}> = ({countAt ' "tool_use_id": block.id, "content": output})', ' messages.append({"role": "user", "content": results})', ]; + // 标签条自卡眉滑入(mech 描边) + const tag = interpolate(frame - tagAt, [0, 14], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 右侧「对照对象」半亮列 + const compare = interpolate(frame - compareAt, [0, 16], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); const split = interpolate(frame - splitAt, [0, 20], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); + // 代码逐行渲染让位给前置动画:标签条(~14 帧)+ 对照列(~16 帧)先占画布 + const codeStart = compareAt + 18; return (
- + {/* 来源标签条:卡眉上方滑入(mech 描边,无具名信息) */} +
+
+ {'开源最小实现 · 照着同一套机制搭的'} +
+
+
+ {/* 对照对象半亮列(p1-12b):读教学实现时,右边始终立着真实产品这一极 */} + {compare > 0 ? ( +
+
+ {'对照对象'} +
+ {'真实产品'} +
+
+
+ ) : null}
= ({branchAt, dimAt export const P1Loop: React.FC<{scene: SceneRange}> = ({scene}) => { const w = (fromId: string, toId?: string) => beatWindow(scene.sentences, scene.from, fromId, toId); - const bA = w('p1-01', 'p1-07'); + const bA = w('p1-01', 'p1-06'); const rA = (id: string) => w(id).from - bA.from; const bB = w('p1-08', 'p1-12'); const rB = (id: string) => w(id).from - bB.from; - const bC = w('p1-13', 'p1-16'); + const bC = w('p1-12a', 'p1-16'); const rC = (id: string) => w(id).from - bC.from; const bD = w('p1-17', 'p1-24'); const rD = (id: string) => w(id).from - bD.from; @@ -540,7 +614,13 @@ export const P1Loop: React.FC<{scene: SceneRange}> = ({scene}) => { - + {/* p1-12a 来源标签条滑入 → p1-12b 对照列浮出 → 代码逐行 → p1-14 计数 → p1-15 分屏 */} + diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx index 33941890..43247fab 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx @@ -553,7 +553,13 @@ const SpillLoop: React.FC<{markAt: number; loopAt: number}> = ({markAt, loopAt}) export const P2Dispatch: React.FC<{scene: SceneRange}> = ({scene}) => { const w = (fromId: string, toId?: string) => beatWindow(scene.sentences, scene.from, fromId, toId); - const bA = w('p2-01', 'p2-04'); + /** 句尾锚(beat 内相对帧):分镜「pX-YY 尾(+N 帧)」的机械化落点。 + * 句尾是本 beat 末句时,+N 会探出 Sequence 窗口(窗口只含句间 gap ≈10 帧)—— + * 封顶到「窗口末尾 − need 帧可见」:动效仍然发生,不被窗口剪掉。 */ + const endAt = (id: string) => w(id).from + w(id).durationInFrames; + const tailAt = (b: {from: number; durationInFrames: number}, id: string, plus: number, need: number) => + Math.min(endAt(id) + plus - b.from, b.durationInFrames - need); + const bA = w('p2-01', 'p2-03'); const bC = w('p2-07', 'p2-10'); const bD = w('p2-11', 'p2-13'); const bE = w('p2-14', 'p2-16'); @@ -565,7 +571,9 @@ export const P2Dispatch: React.FC<{scene: SceneRange}> = ({scene}) => { - + {/* p2-03 尾 +22 帧:命令里一个字符高亮成 deny 并抖动(原 p2-04 已删,语义由角标承载)。 + p2-03 是本 beat 末句——+22 会探出窗口,封顶到末尾仍留 26 帧可见抖动+角标。 */} + diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx index 19abe64c..dcaeb460 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx @@ -1,4 +1,4 @@ -/** P3 执行之前,先过闸门(分镜 3-A…3-G)—— 开源教学素材「Permission Desk」的概念重建 +/** P3 执行之前,先过闸门(分镜 3-A…3-G,含新镜 3-D2 沙箱横切面)—— 开源教学素材「Permission Desk」的概念重建 * 三种结果不各占一色:allow 回 core(放行=回主干)、ask 用 mech、deny 用 danger。 */ import React from 'react'; import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoConfig} from 'remotion'; @@ -264,16 +264,20 @@ const AskAndPass: React.FC<{askAt: number; passAt: number}> = ({askAt, passAt}) ); }; -/** 3-D 拒绝表降级为「示意」+ 变体绕过 */ +/** 3-D 拒绝表降级为「示意」+ 变体绕过。 + * 金句卡改**底部叠加**(不整屏替换,为 3-D2 沙箱镜留画布):p3-15 起 +18 帧以底部 Panel + * 浮出、hold 70 帧淡出——代码卡与变体全程留在原位(分镜 3-D 规格)。 */ const DenyListHonesty: React.FC<{degradeAt: number; bypassAt: number; quoteAt: number}> = ({ degradeAt, bypassAt, quoteAt, }) => { const frame = useCurrentFrame(); - if (frame >= quoteAt) { - return ; - } + // 金句:底部 Panel 浮出(+18 帧起),hold 70 帧后淡出 + const quote = interpolate(frame - quoteAt, [0, 14, 70 + 14, 70 + 14 + 16], [0, 1, 1, 0], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); const degraded = frame >= degradeAt; const lines = [ 'DENY_LIST = [', @@ -347,6 +351,233 @@ const DenyListHonesty: React.FC<{degradeAt: number; bypassAt: number; quoteAt: n
) : null}
+ {/* 金句卡:底部叠加(不整屏替换——下一镜 3-D2 沙箱接着用这块画布) */} + {quote > 0 ? ( +
+ + + {'它告诉你闸门装在哪儿,不是替你把门守住。'} + + +
+ ) : null} + + ); +}; + +/** 3-D2 沙箱横切面(新镜,回答 3-D 金句抛出的问题):左侧缩小的拒绝表代码卡, + * 右侧圆角实心壳罩住「跑命令 + 子进程树」,上下两道边界带(文件/网络)。 + * p3-19a 壳合拢;p3-19b 两道边界带各闪一次;p3-19c 三条变体飞向壳壁被弹回 + + * 密钥箭头飞出边界(deny)——「拆掉任一道墙」的反例;p3-19d 压官方角标。 */ +const SandboxCrossSection: React.FC<{ + shrinkAt: number; + shellAt: number; + bandsAt: number; + bounceAt: number; + noteAt: number; +}> = ({shrinkAt, shellAt, bandsAt, bounceAt, noteAt}) => { + const frame = useCurrentFrame(); + const {fps} = useVideoConfig(); + // 代码卡缩至左侧 55% + const shrink = interpolate(frame - shrinkAt, [0, 18], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 壳自四周合拢(spring) + const shell = spring({frame: frame - shellAt, fps, config: {damping: 180}}); + // 两道边界带各闪一次(p3-19b) + const bandOn = (i: number) => + interpolate(frame - bandsAt - i * 16, [0, 6, 22], [0.55, 1, 0.9], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 变体飞向壳壁被弹回(复用 3-D 轨迹,末端 8 帧反弹) + const fly = interpolate(frame - bounceAt, [0, 26], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const bounceBack = interpolate(frame - bounceAt - 26, [0, 8], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 密钥箭头飞出边界(deny)——「拆掉任一道墙」的反例 + const leak = interpolate(frame - bounceAt - 18, [0, 24], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const note = interpolate(frame - noteAt, [0, 12], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const lines = [ + 'DENY_LIST = [', + ' "rm -rf /", "sudo", …', + ']', + ]; + const variants = ['rm -rf /', 'rm -fr /', 'sudo${IFS}rm']; + // 壳几何:右侧画布中心 + const CX = 1240; + const CY = 500; + const W = 620; + const H = 440; + const halfW = W / 2 + (1 - shell) * 560; + const halfH = H / 2 + (1 - shell) * 400; + return ( + +
+ {/* 左:缩小的代码卡(3-D 的延续,画面 55% 区) */} +
+ + {/* 变体列表:飞向壳壁(p3-19c 复用 3-D 轨迹) */} +
+ {variants.map((v, i) => { + if (fly <= 0) return null; + const goX = interpolate(fly, [0, 1], [0, 300]); + const backX = bounceBack * (1 - Math.min(1, bounceBack)) * -180 + bounceBack * -120; + return ( +
0 ? 1 - bounceBack * 0.4 : 0, + transform: `translateX(${goX + backX + i * 14}px)`, + }} + > + {v} +
+ ); + })} +
+
+ {/* 右:沙箱壳(圆角实心壳罩住进程树) */} + + {/* 壳体:mech 描边 4px、rx=26、辉光,spring 合拢 */} + + {/* 上下两道边界带(文件 / 网络——内核强制的两堵墙) */} + {['文件:只许工作区', '网络:只走代管口子'].map((t, i) => { + const top = i === 0; + const o = bandOn(i) * shell; + if (o <= 0) return null; + return ( + + + + {t} + + + ); + })} + {/* 壳内:跑命令 + 子进程树 */} + + + {'bash'} + + {[0, 1, 2].map((k) => ( + + + + + {['子进程', '子进程', '子进程'][k]} + + + ))} + + {/* 密钥箭头飞出边界(拆墙反例):deny */} + {leak > 0 && leak < 0.85 ? ( + + + + + {'~/.ssh/id_rsa'} + + + ) : null} + {leak >= 0.85 ? ( + + {'拆掉一道墙:密钥直接飞出'} + + ) : null} + +
+ {/* p3-19d 官方角标 */} + + {'Seatbelt / bubblewrap + socat · 权限提示 −84%(官方工程博客,取数 2025-10)'} +
); }; @@ -550,13 +781,16 @@ const EvalOrder: React.FC<{orderAt: number; ballAt: number; denyHitAt: number; n /** 3-G auto 分类器视野分屏:审判者只看用户消息与裸命令(Harness Engineering 改造版) * 官方工程博客:模型的自我辩解、工具结果、调用描述全被剥在视野外—— - * 评它做了什么,而非它说了什么;网页注入的文本骗不到审判者。 */ -const ClassifierVision: React.FC<{scrollAt: number; stripAt: number; goldenAt: number; spoofAt: number}> = ({ - scrollAt, - stripAt, - goldenAt, - spoofAt, -}) => { + * 评它做了什么,而非它说了什么;网页注入的文本骗不到审判者。 + * 右上成绩单卡(p3-31a/b):快筛误杀率 8.5% → 复核 0.4%(两段对照,220px 轨道)。 */ +const ClassifierVision: React.FC<{ + scrollAt: number; + reportAt: number; + barAt: number; + stripAt: number; + goldenAt: number; + spoofAt: number; +}> = ({scrollAt, reportAt, barAt, stripAt, goldenAt, spoofAt}) => { const frame = useCurrentFrame(); const rows = [ {t: '模型的自我辩解:我确认这是安全的操作', why: '辩解不看', strike: true}, @@ -570,6 +804,22 @@ const ClassifierVision: React.FC<{scrollAt: number; stripAt: number; goldenAt: n extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); + // 成绩单卡(p3-31a 浮出) + const report = interpolate(frame - reportAt, [0, 16], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 误杀率色条:deny→core 从 8.5% 宽收到 0.4% 宽(p3-31b,220px 轨道) + const TRACK = 220; + const shrinkBar = interpolate(frame - barAt, [0, 26], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const barPct = 0.085 + (0.004 - 0.085) * shrinkBar; + const stage2On = interpolate(frame - barAt - 16, [0, 8], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); return (
@@ -583,7 +833,64 @@ const ClassifierVision: React.FC<{scrollAt: number; stripAt: number; goldenAt: n > {'审判者的视野:先做减法'}
-
+ {/* 右上成绩单卡(p3-31a/b) */} + {report > 0 ? ( +
+ +
+ {'审判者的成绩单'} +
+ {/* 误杀率色条:220px 轨道,deny→core */} +
+
+
0.6 ? theme.core : theme.deny, + }} + /> +
+
+ + {'快筛 8.5%'} + + + {'复核 0.4%'} + +
+
+
+ {'Stage1 FPR 8.5% → Stage2 0.4%(官方工程博客,取数 2026-03)'} +
+ +
+ ) : null} +
{rows.map((r, i) => { const at = scrollAt + i * 9; const e = interpolate(frame - at, [0, 12], [0, 1], { @@ -681,10 +988,17 @@ const ClassifierVision: React.FC<{scrollAt: number; stripAt: number; goldenAt: n export const P3Gates: React.FC<{scene: SceneRange}> = ({scene}) => { const w = (fromId: string, toId?: string) => beatWindow(scene.sentences, scene.from, fromId, toId); const rel = (b: {from: number}, id: string) => w(id).from - b.from; + /** 句尾锚(全局帧):分镜「pX-YY 尾(+N 帧)」的机械化落点 */ + const endAt = (id: string) => w(id).from + w(id).durationInFrames; + /** 句尾锚封顶进 Sequence 窗口(末句 +N 会探出窗口——窗口只含句间 gap): + * cap 为「窗口末尾 − need 帧可见」,动效仍发生不被剪掉。 */ + const tailAt = (b: {from: number; durationInFrames: number}, id: string, plus: number, need: number) => + Math.min(endAt(id) + plus - b.from, b.durationInFrames - need); const bA = w('p3-01', 'p3-06'); const bB = w('p3-07', 'p3-09'); - const bC = w('p3-10', 'p3-13'); - const bD = w('p3-14', 'p3-19'); + const bC = w('p3-10', 'p3-12'); + const bD = w('p3-14', 'p3-15'); + const bD2 = w('p3-19a', 'p3-19d'); const bE = w('p3-20', 'p3-24'); const bF = w('p3-25', 'p3-29'); const bG = w('p3-30', 'p3-35'); @@ -692,10 +1006,11 @@ export const P3Gates: React.FC<{scene: SceneRange}> = ({scene}) => { + {/* p3-05 已删:执行节点反讽锚点改挂 p3-04 句尾 +16 帧 */} @@ -705,31 +1020,48 @@ export const P3Gates: React.FC<{scene: SceneRange}> = ({scene}) => { /> - + {/* p3-13 已删:畅通通路锚点改挂 p3-12 句尾 +25 帧(「弃权不等于放行」由 3-E 承载)。 + p3-12 是本 beat 末句——封顶到窗口末尾留 34 帧可见尾迹动画。 */} + + {/* p3-16..19 已删:降级/绕过/金句全部压在 p3-14/15 两句的句内偏移上(分镜 3-D 规格) */} + + + {/* p3-19a 代码卡缩位+壳合拢;19b 边界带;19c 变体弹回+密钥反例;19d 角标 */} + + {/* p3-27 已删:拒绝站截获锚点前挂到 p3-26 句尾 +30 帧 */} + {/* p3-33 已删:末两行高亮锚点并入 p3-32 +20 帧;31a/b 成绩单卡随动 */} diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx index 3cdaacbd..94940741 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx @@ -279,8 +279,9 @@ const SlotsLightUp: React.FC<{slotAt: number[]; gateMoveAt: number; backflowAt: ); }; -/** 4-E 四点沿环脉冲一圈;金句期间刻意零动效 */ -const BoringOnPurpose: React.FC<{quoteAt: number}> = ({quoteAt}) => { +/** 4-E 四点沿环脉冲一圈;金句期间刻意零动效。 + * 喇叭图标改挂 p4-20 句尾(原 p4-21 已并入 p4-20——四点脉冲走完后喇叭才落位)。 */ +const BoringOnPurpose: React.FC<{hornsAt: number; quoteAt: number}> = ({hornsAt, quoteAt}) => { const frame = useCurrentFrame(); const dot = useRingDot(2.5); if (frame >= quoteAt) { @@ -295,6 +296,11 @@ const BoringOnPurpose: React.FC<{quoteAt: number}> = ({quoteAt}) => { ); } const which = Math.floor(frame / 8) % 4; + // 四点脉冲一圈(各 8 帧)后喇叭浮出(p4-20 句尾) + const horns = interpolate(frame - hornsAt, [0, 10], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); return (
@@ -311,7 +317,7 @@ const BoringOnPurpose: React.FC<{quoteAt: number}> = ({quoteAt}) => { const rad = (ang * Math.PI) / 180; const cx = 230 + 184 * Math.cos(rad); const cy = 230 + 184 * Math.sin(rad); - const o = which === i ? 1 : 0.3; + const o = (which === i ? 1 : 0.3) * horns; // 喇叭主体朝外旋转(角点指向环外) const rot = ang + 90; return ( @@ -648,9 +654,19 @@ const StampClash: React.FC<{ ); }; -/** 4-G' 六道闸门流水线(官方 SDK 权限判定图):hook 的放行仍要穿过后面的 deny/ask 两站 +/** 4-G' 六道闸门流水线(官方 SDK 权限判定图):同一轨道跑三枚球做对照—— + * 球 A「沉默」(p4-28,hook 站无扰动通过,沉默≠批准照走流程)、 + * 球 B「我拦了」(p4-28a/b,全速穿六站直达 Execute,到达瞬间标签翻「静默失效」)、 + * 球 C「我批了」(p4-29/30,deny 站被截入 Blocked)+ p4-31 全放行模式重跑仍被截。 * 官方把权限判定画成六站;本片高潮句「扩展点能加限制,不能解除限制」的官方背书。 */ -const SixGatePipeline: React.FC<{railAt: number; runAt: number; yoloAt: number}> = ({railAt, runAt, yoloAt}) => { +const SixGatePipeline: React.FC<{ + railAt: number; + silentAt: number; + fakeAt: number; + exitNoteAt: number; + runAt: number; + yoloAt: number; +}> = ({railAt, silentAt, fakeAt, exitNoteAt, runAt, yoloAt}) => { const frame = useCurrentFrame(); const stations = [ {t: 'hook', sub: '扩展点'}, @@ -664,17 +680,55 @@ const SixGatePipeline: React.FC<{railAt: number; runAt: number; yoloAt: number}> extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); - const travel = interpolate(frame - runAt, [0, 50], [0, 1], { + // 球 A(p4-28):从 hook 站无扰动通过、继续走 deny/ask 站——沉默≠批准,照走正常流程 + const travelA = interpolate(frame - silentAt, [0, 50], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 球 B(p4-28a/b):全速穿过全部六站直达 Execute;到达瞬间标签翻「静默失效」 + const travelB = interpolate(frame - fakeAt, [0, 40], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 球 C(p4-29/30):行至 deny 站被截入 Blocked + const travelC = interpolate(frame - runAt, [0, 50], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); const yolo = frame >= yoloAt; - // 两轮演示:第一轮光点在 deny 站被截;第二轮(全放行模式)仍在 deny 站被截 + // 球 C 在 deny 站(第 2 站,轨道 1/6~2/6 段中点)被截 const cutAt = 1 / 6 + 0.5 / 6; - const stopped = travel > cutAt; + const stopped = travelC > cutAt; const PX = 160; const GAP = 260; - const ballX = PX + (GAP * 5) * Math.min(travel, cutAt); + const RAIL_END = PX + GAP * 5; + const ballAX = PX + (GAP * 5) * travelA; + const ballBX = PX + (GAP * 5) * Math.min(travelB, 1); + const ballCX = PX + (GAP * 5) * Math.min(travelC, cutAt); + const bDone = travelB >= 1; + // 球 A 停在 ask 站后淡出(把注意力让给 B/C 两球) + const aFade = interpolate(frame - silentAt - 56, [0, 14], [1, 0.25], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // exit 码角标(p4-28c) + const exitNote = interpolate(frame - exitNoteAt, [0, 12], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const label = (x: number, y: number, text: string, color: string, strike = false) => ( + + {text} + + ); return (
@@ -693,16 +747,48 @@ const SixGatePipeline: React.FC<{railAt: number; runAt: number; yoloAt: number}> ) : null} - {/* 请求光点 */} - {rail > 0.8 ? ( + {/* 球 A(沉默,dim):hook 站无扰动通过——hook 沉默≠批准,照走 deny/ask */} + {rail > 0.8 && travelA > 0 ? ( + <> + + + {label(ballAX, 218, '沉默', theme.dim)} + + ) : null} + {/* 球 B(我拦了,deny):全速直达 Execute;到达瞬间标签翻「静默失效」 */} + {rail > 0.8 && travelB > 0 ? ( <> - + + + {bDone + ? label(ballBX, 218, '静默失效', theme.deny) + : label(ballBX, 218, '我拦了', theme.deny)} + + ) : null} + {/* 球 C(我批了,core):deny 站被截入 Blocked(deny 辉光) */} + {rail > 0.8 && travelC > 0 ? ( + <> + {!stopped ? ( - + ) : ( - + )} + {stopped + ? label(ballCX, 270, '出局', theme.deny) + : label(ballCX, 218, '我批了', theme.core)} ) : null} @@ -736,6 +822,24 @@ const SixGatePipeline: React.FC<{railAt: number; runAt: number; yoloAt: number}>
); })} + {/* exit 码角标(p4-28c):唯一硬信号 */} + {exitNote > 0 ? ( +
+ {'唯一凭退出码单独阻断的是 exit 2;exit 1 = 非阻断错误,动作照跑'} +
+ ) : null} {yolo ? (
= ({spinAt, mark export const P4Hooks: React.FC<{scene: SceneRange}> = ({scene}) => { const w = (fromId: string, toId?: string) => beatWindow(scene.sentences, scene.from, fromId, toId); const rel = (b: {from: number}, id: string) => w(id).from - b.from; + /** 句尾锚(全局帧):分镜「pX-YY 句尾」的机械化落点 */ + const endAt = (id: string) => w(id).from + w(id).durationInFrames; const bA = w('p4-01', 'p4-04'); const bB = w('p4-05', 'p4-07'); const bC = w('p4-08', 'p4-12'); @@ -865,13 +971,23 @@ export const P4Hooks: React.FC<{scene: SceneRange}> = ({scene}) => { /> - + {/* p4-20 句尾喇叭浮出(原 p4-21 并入 p4-20);p4-22 金句(期间零强调动效) */} + - + {/* p4-27 起 +6 帧轨道描出(消除头空转);p4-28 球 A;p4-28a/b 球 B;p4-28c 角标; + p4-29/30 球 C 被截;p4-31 全放行重跑仍被截 */} + = ({layerAt}) => { const frame = useCurrentFrame(); @@ -160,12 +163,13 @@ const ShellLayers: React.FC<{layerAt: number[]}> = ({layerAt}) => { }; /** - * 6-B 信源卡 + 系列身份卡 + 渐黑。 + * 6-B 信源卡(p6-06/07 免责两句)→ 金句压系列身份卡(p6-05)→ 下期预告卡(p6-08)→ 渐黑。 * `beatDurationInFrames` 是**本 beat 的总时长**,渐黑窗口据此反推。 - */ -const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> = ({ + * 句序重排后免责前移:情绪高点(金句+身份卡)与转化动作(下期卡)不再被隔开。 */ +const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number; nextAt: number}> = ({ beatDurationInFrames, seriesAt, + nextAt, }) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); @@ -180,6 +184,11 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); + // 下期预告卡(p6-08 句锚——句序重排后与金句卡分离,各自独立浮现) + const nextT = interpolate(frame - nextAt, [0, 18], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); // 渐黑:末 1.2 秒线性压暗到全黑,窗口从 beat 总时长反推 const fadeFrames = Math.round(1.2 * fps); const fadeStart = beatDurationInFrames - fadeFrames; @@ -243,27 +252,57 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}>
{'Claude Code Harness Engineering'}
+ {/* 金句压在系列身份卡上方(免责前移后,情绪高点与转化动作不再被隔开) */}
+ {'学会给 Harness 做加减法,'} +
+
+ {'这本身就是一门手艺。'} +
+
{'执行层:一个循环,就是全部'}
- {/* 下期预告卡:标题只在画面(口播为话题描述——反串线纪律)。 - 标题为 series.json 派生数据的硬编码镜像,由 check_series 规则 8 - 与清单对账(改标题先改 series.json,再同步此串——规则会拦漂移)。 */} +
+ ) : null} + {/* 下期预告卡:p6-08 句锚独立浮现(标题只在画面——反串线纪律)。 + 标题为 series.json 派生数据的硬编码镜像,由 check_series 规则 8 + 与清单对账(改标题先改 series.json,再同步此串——规则会拦漂移)。 */} + {nextT > 0 ? ( +
@@ -285,20 +324,24 @@ export const P6Ending: React.FC<{scene: SceneRange}> = ({scene}) => { const w = (fromId: string, toId?: string) => beatWindow(scene.sentences, scene.from, fromId, toId); const rel = (b: {from: number}, id: string) => w(id).from - b.from; const bA = w('p6-01', 'p6-04'); - const bB = w('p6-05', 'p6-08'); + const bB = w('p6-06', 'p6-08'); return ( + {/* p6-03 已删:第三、四层在 p6-04 上错开 8 帧落位(分镜 6-A 规格) */} - {/* 渐黑窗口从**本 beat 总时长**推导,不是末句时长(红线四) */} + {/* 句序重排(narration 实际顺序 06→07→05→08): + p6-06/07 信源卡 → p6-05 金句压系列身份卡 → p6-08 下期卡。 + 渐黑窗口从**本 beat 总时长**推导,不是末句时长(红线四)。 */} diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/components/HarnessScale.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/components/HarnessScale.tsx new file mode 100644 index 00000000..17bd7953 --- /dev/null +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/components/HarnessScale.tsx @@ -0,0 +1,137 @@ +/** 官方四件套标尺(系列共用母题):循环/工具/上下文管理/护栏 四格横排。 + * 反枚举纪律:panel 底 + 编号 01–04,不给四色——只有被点名的那格点亮。 + * 0-C2(本集):dropAt 四格自左依次落位、第三格 keep 描边点亮;splitAt 第三格 + * 裂为两半「安排看什么/满了怎么办」——右半 keep 填充(今天拆的),左半保持 + * dim 标「另拆」。 + * 6-C 尾帧:compact 模式四格整体淡入、第三格「上下文管理」常亮(不裂格)。 */ +import React from 'react'; +import {AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig} from 'remotion'; +import {theme} from '../design/theme'; + +const SLOTS = ['循环', '工具', '上下文管理', '护栏'] as const; +/** 第三格=上下文管理:本集(EP3)填的格 */ +const LIT = 2; + +export const HarnessScale: React.FC<{ + /** 四格落位锚(compact 模式即整体淡入锚) */ + dropAt: number; + /** 第三格裂两半锚(0-C2 专用;缺省不裂) */ + splitAt?: number; + /** 尾帧复用模式:整体淡入、第三格常亮 */ + compact?: boolean; + cellW?: number; + /** 纵向落点(px;缺省垂直居中) */ + top?: number; +}> = ({dropAt, splitAt, compact = false, cellW = 360, top}) => { + const frame = useCurrentFrame(); + const {fps} = useVideoConfig(); + const split = splitAt !== undefined && frame >= splitAt; + return ( + +
+ {SLOTS.map((t, i) => { + const e = compact + ? interpolate(frame - dropAt, [0, 12], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }) + : spring({frame: frame - dropAt - i * 6, fps, config: {damping: 200}}); + // 第三格落位后点亮(keep 描边;compact 模式随整体淡入常亮) + const lit = i === LIT && (compact || frame >= dropAt + LIT * 6 + 10); + return ( +
+
+
+ {String(i + 1).padStart(2, '0')} +
+ {i === LIT && split ? ( + // p0-11:第三格裂两半——左「安排看什么」dim 标「另拆」,右「满了怎么办」keep 填充 +
+
+
+ {'安排看什么'} +
+
+ {'另拆'} +
+
+
+
+ {'满了怎么办'} +
+
+
+ ) : ( +
+ {t} +
+ )} +
+
+ ); + })} +
+
+ ); +}; diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx index b32d1ec5..0244e5e5 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx @@ -1,11 +1,13 @@ /** P0 一次拒收(分镜 0-A…0-D) - * 痛点:终端干活到一半报错砸落;随身带的对话把窗口容器灌满,撞上「拒收」墙; - * 「删一点」的三个恶果快闪;两层答案(桌面/登记簿)画中画预告。 */ + * 痛点:终端干活到一半报错砸落;随身带的对话把窗口容器灌满(开局就不空——官方 + * 装载清单七项 + 斜纹基底层),撞上「拒收」墙;上下文腐坏双轴(召回曲线下滑 + + * 注意力 n² 摊薄);官方四件套标尺钉「上下文管理」格;两层答案画中画预告。 */ import React from 'react'; import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoConfig} from 'remotion'; import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; +import {HarnessScale} from '../components/HarnessScale'; import {Footnote, Panel, PaperCard, SceneHeader, Terminal} from '../components/motifs'; /** 0-A 系列终端:命令链滚动 → 一行 deny 报错砸落(画面压暗一档、光标停闪) */ @@ -64,26 +66,150 @@ const ErrorSlam: React.FC<{errAt: number}> = ({errAt}) => { ); }; -/** 0-B 左终端缩角 + 右玻璃容器:随身携带的色块逐句灌入 → 液面撞顶、边框闪 deny */ -const WindowFills: React.FC<{pourAt: number[]; topAt: number}> = ({pourAt, topAt}) => { +/** 0-B 开局装载清单(官方示意值 · context-window 页 · 取数 2026-08)。 + * p0-05a 起左侧终端降至 0.35、同位淡入七行等宽清单;行尾三档可见性徽章—— + * 终端可见/一行摘要/不可见(官方 VIS_META:full/brief/hidden)。 */ +const STARTUP_LOAD: {t: string; n: string; vis: 'full' | 'brief' | 'hidden'; hl?: boolean}[] = [ + {t: '基本设定', n: '4,200', vis: 'hidden', hl: true}, + {t: '自动记忆索引', n: '680', vis: 'hidden'}, + {t: '环境信息', n: '280', vis: 'hidden'}, + {t: '工具名', n: '120', vis: 'hidden'}, + {t: '技能描述', n: '450', vis: 'hidden'}, + {t: '用户级规则', n: '320', vis: 'hidden'}, + {t: '项目规则', n: '1,800', vis: 'hidden'}, +]; +const VIS_LABEL: Record<'full' | 'brief' | 'hidden', string> = { + full: '终端可见', + brief: '一行摘要', + hidden: '不可见', +}; + +/** 0-B 左终端缩角 + 右玻璃容器:随身携带的色块逐句灌入 → 液面撞顶、边框闪 deny。 + * p0-05a 起终端让位给「开局装载清单」;容器底部升起约 10% 高斜纹基底层标「开局已装」; + * p0-05b「4,200」行 core 高亮并与基底层连线(画面实证口播的「光基本设定就四千多字」)。 */ +const WindowFills: React.FC<{pourAt: number[]; topAt: number; loadAt: number; ledgerAt: number}> = ({ + pourAt, + topAt, + loadAt, + ledgerAt, +}) => { const frame = useCurrentFrame(); const CW = 560; const CH = 620; - const fillH = Math.min(CH, pourAt.filter((a) => frame >= a).length * (CH / pourAt.length)); + const listIn = interpolate(frame - loadAt, [0, 14], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // p0-05b:4,200 行高亮 + 与基底层连线 + const hlT = interpolate(frame - ledgerAt, [0, 12], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 斜纹基底层:约 10% 高,loadAt 后自底升起 + const baseH = interpolate(frame - loadAt, [0, 16], [0, CH * 0.1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const fillH = Math.min(CH - baseH, pourAt.filter((a) => frame >= a).length * ((CH - baseH) / pourAt.length)); const slammed = frame >= topAt; const flash = slammed ? 0.5 + 0.5 * Math.abs(Math.sin((frame - topAt) / 4)) : 0; return ( - +
+ {/* 左:终端(p0-05a 起降 0.35 让位)+ 同位浮出开局装载清单 */} +
+ +
+ {listIn > 0 ? ( +
+ +
+ {'开局装载清单'} + {'你还没敲第一个字'} +
+ {STARTUP_LOAD.map((r, i) => { + const e = interpolate(frame - loadAt - 6 - i * 5, [0, 10], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const hot = r.hl && hlT > 0; + return ( +
+ + {r.t} + + + {r.n} + + {/* 三档可见性徽章 */} + + {VIS_LABEL[r.vis]} + +
+ ); + })} +
+
+ ) : null} +
{/* 玻璃容器(窗口):被随身携带的色块灌满 */}
= ({pourAt, topAt position: 'absolute', left: 0, right: 0, - bottom: 0, + bottom: baseH, height: fillH, display: 'flex', flexDirection: 'column-reverse', @@ -114,7 +240,7 @@ const WindowFills: React.FC<{pourAt: number[]; topAt: number}> = ({pourAt, topAt
= ({pourAt, topAt /> ))}
+ {/* 斜纹基底层:开局已装(系统装载垫底,后来的对话压其上) */} + {baseH > 0 ? ( +
0 ? theme.core : theme.panelBorder}`, + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + }} + > + 0 ? theme.core : theme.dim, + whiteSpace: 'nowrap', + }} + > + {'开局已装'} + +
+ ) : null} {/* 顶部「拒收」墙 */}
= ({pourAt, topAt
) : null}
+ {'官方示意值 · context-window 页 · 取数 2026-08'} ); }; -/** 0-C 「删一点」的三恶果快闪(口播点到两样:删任务书/删回执;画面对齐口播两帧) */ -const DeleteSins: React.FC<{taskAt: number; receiptAt: number}> = ({taskAt, receiptAt}) => { +/** 0-C 上下文腐坏双轴(官方工程博客 · 取数 2026-08): + * 右轴:X 窗口字数(log 刻度)/ Y 翻旧账准确度——曲线描出并单调下滑,尾段趋平 + * (渐变非悬崖);p0-09c deny 衬线压字「能装 ≠ 能记」。 + * 左轴:注意力关系图 4 节点→8→16,边数角标 6→28→120;p0-09b 全部边 + * opacity 0.9→0.35、线宽收细——顶部「注意力预算=1 份」定宽条不随节点增长。 */ +const ContextRot: React.FC<{curveAt: number; graphAt: number; thinAt: number; stampAt: number}> = ({ + curveAt, + graphAt, + thinAt, + stampAt, +}) => { const frame = useCurrentFrame(); - const shots = [ - {at: taskAt, tag: '删错了任务书', verdict: '它忘了自己要干嘛', id: 'task'}, - {at: receiptAt, tag: '删错了回执', verdict: '它对着空气发问', id: 'receipt'}, - ]; + // 曲线描线(strokeDashoffset 反推) + const curveP = interpolate(frame - curveAt, [0, 30], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 关系图三档:4 节点 → 8 节点 → 16 节点(示意)。档位边界即各档起点—— + // stageT 从**本档起点**起算,跨档瞬间新档网络淡入(旧档直接换轨,档间不重影)。 + const STAGE_AT = [graphAt, graphAt + 34, graphAt + 74]; + const stage = frame < STAGE_AT[1] ? 0 : frame < STAGE_AT[2] ? 1 : 2; + const nodeCount = [4, 8, 16][stage]; + const edgeCount = [6, 28, 120][stage]; + const thin = interpolate(frame - thinAt, [0, 16], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const stageT = interpolate(frame - STAGE_AT[stage], [0, 12], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 右轴曲线:单调下滑、尾段趋平(渐变非悬崖) + const curvePts: [number, number][] = []; + for (let k = 0; k <= 20; k++) { + const x = k / 20; + // ease-out 下滑:前 60% 掉七成、后 40% 只掉半成——尾段趋平 + const y = 1 - (1 - Math.pow(1 - Math.pow(x, 0.62), 2.2)); + curvePts.push([x, y]); + } return ( - {shots.map((s) => { - const t = interpolate(frame - s.at, [0, 10, 118, 130], [0, 1, 1, 0], { - extrapolateLeft: 'clamp', - extrapolateRight: 'clamp', - }); - if (t <= 0) return null; - return ( - -
- {/* 任务书:core 描边三张(头三张=任务书,语言与 1-B 一致) */} - {s.id === 'task' ? ( -
- {[0, 1, 2].map((i) => ( - - ))} -
- ) : ( -
- - -
- )} -
-
- {s.tag} -
-
- {s.verdict} -
-
- {/* 删除斜杠 */} - - - +
+ {/* 左:注意力关系图(n² 摊薄) */} +
+
+ + {'注意力关系图'} + + + {`${nodeCount} 节点 · ${edgeCount} 边`} + +
+ {/* 顶部定宽预算条:不随节点数增长(摊薄的对照物) */} +
+ {'注意力预算'} +
+
- - ); - })} + {'= 1 份'} +
+
+ + {/* 圆周布点:节点数随 stage 变化,边全连接 */} + {(() => { + const cx = 320; + const cy = 230; + const R = 200; + const nodes: [number, number][] = Array.from({length: nodeCount}, (_, i) => { + const a = (2 * Math.PI * i) / nodeCount - Math.PI / 2; + return [cx + R * Math.cos(a), cy + R * Math.sin(a)] as [number, number]; + }); + return ( + <> + {nodes.flatMap((p1, i) => + nodes.slice(i + 1).map((p2, j) => ( + + )), + )} + {nodes.map((p, i) => ( + + ))} + + ); + })()} + +
+
+ {/* 右:召回曲线坐标系 */} +
+
+ + {'翻旧账准确度'} + +
+ + {/* 坐标轴 */} + + + + {'高'} + + + {'低'} + + + {'窗口字数 →'} + + {/* X 轴 log 刻度 */} + {[0, 1, 2, 3, 4].map((k) => ( + + + + {['10³', '10⁴', '10⁵', '10⁶', '10⁷'][k]} + + + ))} + {/* 召回曲线:strokeDashoffset 反推描线 */} + {(() => { + const X0 = 70; + const X1 = 660; + const Y0 = 46; + const Y1 = 392; + const d = curvePts.map(([x, y], i) => { + const px = X0 + x * (X1 - X0); + const py = Y1 - y * (Y1 - Y0); + return `${i === 0 ? 'M' : 'L'}${px.toFixed(1)},${py.toFixed(1)}`; + }); + const LEN = 2000; + return ( + <> + + {/* 尾段趋平注记(渐变非悬崖) */} + 0.9 ? 1 : 0} + > + {'趋平 · 不是悬崖'} + + + ); + function yOf(x: number): number { + return 1 - (1 - Math.pow(1 - Math.pow(x, 0.62), 2.2)); + } + })()} + +
+
+ {/* p0-09c 压字 */} + {frame >= stampAt ? ( +
+ {'能装 ≠ 能记'} +
+ ) : null} + {'召回精度随上下文变长下降 · 官方工程博客 · 取数 2026-08'} ); }; @@ -420,11 +708,13 @@ export const P0Reject: React.FC<{scene: SceneRange}> = ({scene}) => { const at = (id: string) => w(id).from; const bA = w('p0-01', 'p0-02'); const relA = (id: string) => at(id) - bA.from; - const bB = w('p0-04', 'p0-08'); + const bB = w('p0-04', 'p0-06'); const relB = (id: string) => at(id) - bB.from; - const bC = w('p0-09', 'p0-12'); + const bC = w('p0-09', 'p0-09c'); const relC = (id: string) => at(id) - bC.from; - const bD = w('p0-13', 'p0-17'); + const bC2 = w('p0-10', 'p0-11'); + const relC2 = (id: string) => at(id) - bC2.from; + const bD = w('p0-13', 'p0-15'); const relD = (id: string) => at(id) - bD.from; return ( @@ -434,18 +724,28 @@ export const P0Reject: React.FC<{scene: SceneRange}> = ({scene}) => { + + + - - + + diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx index 92007b89..58bfdf3a 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx @@ -236,12 +236,18 @@ const TabToSummary: React.FC<{beamAt: number; rewriteAt: number; shredAt: number /** 4-C 两条腿框架(Harness Engineering 改造版): * 第一条腿你写(项目规则文件夹:四层拼接/四兆上限/两百行)+ 第二条腿它自己写(自动记忆,四类有门限)。 * 内嵌原 LedgerArrives 登记簿动画。 */ -const TwoLegsFrame: React.FC<{legAt: number; autoAt: number; children: React.ReactNode}> = ({ - legAt, - autoAt, - children, -}) => { +const TwoLegsFrame: React.FC<{ + legAt: number; + autoAt: number; + /** p4-08a..d 层位纠正插段:规则卡飞向「基本设定」被弹回、落进「你开口之前」通道 */ + ghostAt: number; + bounceAt: number; + quoteAt: number; + badgeAt: number; + children: React.ReactNode; +}> = ({legAt, autoAt, ghostAt, bounceAt, quoteAt, badgeAt, children}) => { const frame = useCurrentFrame(); + const {fps} = useVideoConfig(); const leg = interpolate(frame - legAt, [0, 18], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', @@ -250,9 +256,36 @@ const TwoLegsFrame: React.FC<{legAt: number; autoAt: number; children: React.Rea extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); + // p4-08a:规则卡沿弧线上飞(0→1);p4-08b:被横杆弹回落位(1→0,spring 过冲) + const fly = interpolate(frame - ghostAt, [0, 22], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const bounce = spring({frame: frame - bounceAt, fps, config: {damping: 11}}); + const settled = interpolate(bounce, [0, 1], [1, 0]); + // 弹回后通道标签描出(p4-08b 尾) + const lane = interpolate(frame - bounceAt - 8, [0, 12], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const quote = interpolate(frame - quoteAt, [0, 12], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const badge = interpolate(frame - badgeAt, [0, 10], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 卡的合成位置:起点(左腿上方)→ 顶部「基本设定」框;被弹回时停在通道层 + const cardX = 240 + fly * 620 - (fly - Math.max(fly, settled)) * 0; + const cardY = 620 - fly * 440 - (1 - settled) * 0; + const cardShow = interpolate(frame - ghostAt, [0, 8], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); return ( - {/* 左腿:你写的 */} + {/* 左腿:你写 */}
-
- {'第一条腿:你写'} +
+ {'第一条腿:你写'} + {/* p4-08d:「建议 ≠ 配置」小徽标 */} + {badge > 0 ? ( + + {'建议 ≠ 配置'} + + ) : null}
{['四层拼接 · 不覆盖', '越近工作目录越后读', '单文件超四兆整份跳过', '超两百行开始不听话'].map((s, i) => (
))}
+ {/* 层位纠正插段:顶部「基本设定」框 + 横杆 + 通道(p4-08a..b) */} + {frame >= ghostAt ? ( +
+ {/* 基本设定框(规则卡飞向它,但从不属于它) */} +
+ {'基本设定(系统提示)——它不在这层'} +
+ {/* 弹回横杆:p4-08b 砸下 */} +
+ {/* 通道:你开口之前 · 第一张便条(规则卡真正的层位) */} +
0 ? theme.keep : theme.panelBorder}`, + borderRadius: 10, + fontFamily: theme.mono, + fontSize: 17, + color: lane > 0 ? theme.keep : theme.dim, + textAlign: 'center', + opacity: 0.35 + lane * 0.65, + whiteSpace: 'nowrap', + }} + > + {'你开口之前 · 第一张便条(与你说的话同一身份)'} +
+
+ ) : null} + {/* 飞行的「项目规则」卡:上飞→弹回→驻停通道 */} + {frame >= ghostAt ? ( +
+
0.9 && settled < 0.5 ? theme.deny : theme.keep}`, + background: theme.panel, + fontFamily: theme.mono, + fontSize: 20, + fontWeight: 700, + color: theme.text, + whiteSpace: 'nowrap', + }} + > + {'项目规则'} +
+
+ ) : null} {/* 中央:登记簿动画(原 4-C 主体) */}
{children}
+ {/* p4-08c:官方引语角标(三秒内浮现,勿与登记簿抢焦点——压在底部安全带上方) */} + {quote > 0 ? ( +
+ {'「会读、会尽量照做,但不保证严格执行」 · memory 页 · 取数 2026-08'} +
+ ) : null} ); }; @@ -564,6 +711,8 @@ const PrefixCacheStrip: React.FC<{stripAt: number; priceAt: number}> = ({stripAt alignItems: 'flex-end', }} > + {/* 价目条挂 strip 上方(bottom:'100%')——旧 top:'100%' 位实测 y≈926–964 距底仅 + 116px 破「角标 bottom≥150」红线,且与 TwoPaths 的 Footnote 同挤 168 带 */} {layers.map((l, i) => { const e = interpolate(frame - stripAt - i * 5, [0, 10], [0, 1], { extrapolateLeft: 'clamp', @@ -596,15 +745,15 @@ const PrefixCacheStrip: React.FC<{stripAt: number; priceAt: number}> = ({stripAt {'改规则要新开会话 · 中途换模型那轮慢'}
) : null} - {/* p4-25a/b 价目条:命中一折 · 写入 +1/4 · 两次回本 */} + {/* p4-25a/b 价目条:命中一折 · 写入 +1/4 · 两次回本(自下滑入,挂 strip 上方) */} {frame >= priceAt ? (
= ({stripAt ); }; -const TwoPaths: React.FC<{sideAt: number; cardsAt: number; shrinkAt: number; degradeAt: number}> = ({ - sideAt, - cardsAt, - shrinkAt, - degradeAt, -}) => { +const TwoPaths: React.FC<{ + sideAt: number; + cardsAt: number; + shrinkAt: number; + degradeAt: number; + /** p4-26:小号模型旁落「向量库」虚影并划斜线(不是向量检索) */ + vecAt: number; + /** p4-27+:飞回的卡逐张褪色滑出(用完就过气——褪色即遗忘纪律) */ + evapAt: number[]; + /** p4-29:收束——索引卡辉光脉冲一次、旁支整组退场 */ + settleAt: number; +}> = ({sideAt, cardsAt, shrinkAt, degradeAt, vecAt, evapAt, settleAt}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); const side = interpolate(frame - sideAt, [0, 20], [0, 1], { @@ -646,6 +801,27 @@ const TwoPaths: React.FC<{sideAt: number; cardsAt: number; shrinkAt: number; deg extrapolateRight: 'clamp', }); const degraded = frame >= degradeAt; + // p4-26:向量库虚影出现 → 划斜线(「反而可靠」的对照物) + const vec = interpolate(frame - vecAt, [0, 10], [0, 0.5], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const vecSlash = interpolate(frame - vecAt - 12, [0, 10], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // p4-27 起:五张卡逐张蒸发(每张 i×8 帧错峰;tone 全转 faded + 滑出) + const evap = (i: number) => + interpolate(frame - evapAt[Math.min(i, evapAt.length - 1)] - i * 8, [0, 16], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // p4-29:索引卡辉光脉冲一次(sin 半周期)、右侧旁支整组退场 + const settle = interpolate(frame - settleAt, [0, 26], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const pulse = settle > 0 && settle < 1 ? Math.sin(settle * Math.PI) : 0; return (
@@ -660,7 +836,7 @@ const TwoPaths: React.FC<{sideAt: number; cardsAt: number; shrinkAt: number; deg border: `3px solid ${theme.keep}`, background: theme.panel, padding: '18px 24px', - boxShadow: `0 0 ${Math.round(18 + 10 * (0.5 + 0.5 * Math.sin(frame / 9)))}px ${theme.keepDeep}`, + boxShadow: `0 0 ${Math.round(18 + 10 * (0.5 + 0.5 * Math.sin(frame / 9)) + pulse * 26)}px ${theme.keepDeep}`, }} >
{'MEMORY.md'}
@@ -683,11 +859,11 @@ const TwoPaths: React.FC<{sideAt: number; cardsAt: number; shrinkAt: number; deg ))}
- {'贴在基本设定里 · 每次开工扫一眼家底 · 便宜、全天候'} + {'垫在你开口之前 · 每次开工扫一眼家底 · 便宜、全天候'}
- {/* 路二:旁路小问 */} -
+ {/* 路二:旁路小问(p4-29 收束时整组退场让位给「一层永久的存」) */} +
{'路二 · 旁路小问(按需取)'}
@@ -705,23 +881,61 @@ const TwoPaths: React.FC<{sideAt: number; cardsAt: number; shrinkAt: number; deg {side > 0.95 ? : null} -
- {'小号模型 · 挑真正用得上的'} +
+
+ {'小号模型 · 挑真正用得上的'} +
+ {/* p4-26:向量库虚影圆柱 + 斜线(不是向量检索,反而可靠) */} + {vec > 0 ? ( +
+ + + + + + {vecSlash > 0 ? ( + + ) : null} + +
+ {'不是向量库'} +
+
+ ) : null}
- {/* 飞回的 ≤5 卡:一张犹豫卡自动缩回 */} + {/* 飞回的 ≤5 卡:一张犹豫卡自动缩回;p4-27 起逐张蒸发(用完就过气) */}
{[0, 1, 2, 3, 4].map((i) => { const t = spring({frame: frame - cardsAt - i * 6, fps, config: {damping: 200}}); @@ -729,15 +943,23 @@ const TwoPaths: React.FC<{sideAt: number; cardsAt: number; shrinkAt: number; deg const hesitant = i === 4; const scale = hesitant ? Math.max(0, shrink) * t : t; const op = hesitant ? Math.max(0, shrink) : 1; + const gone = evapAt.length > 0 ? evap(i) : 0; return (
- + 0.3 ? 'faded' : 'full'} + label={hesitant ? '拿不准' : undefined} + />
); })} @@ -800,7 +1022,14 @@ export const P4Ledger: React.FC<{scene: SceneRange}> = ({scene}) => { /> - + = ({scene}) => { cardsAt={relE('p4-22')} shrinkAt={relE('p4-22') + 70} degradeAt={relE('p4-24')} + vecAt={relE('p4-26')} + evapAt={[relE('p4-27')]} + settleAt={relE('p4-29')} /> diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx index 2d6ee939..ee945482 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P6Ending.tsx @@ -1,17 +1,66 @@ -/** P6 落点与信源(分镜 6-A…6-B) - * 6-A 一句话合同金句卡(serif keep 描边)→ 两行回收(体面地忘 / 固执地记); - * 6-B 信源卡(官方文档/工程博客/第三方源码分析/实测口径)→ 身份卡 → 渐黑。 - * ★ 渐黑窗口从**末 beat 总时长**(beatDurationInFrames)推导,不是末句时长 +/** P6 落点与信源(分镜 6-B…6-A…6-C,收尾改序:免责→金句→预告) + * 6-B 信源卡前置(免责不再插在情绪高点与转化动作之间); + * 6-A 一句话合同金句卡(serif keep 描边)→ 两行回收(体面地忘 / 固执地记)→ + * 赌注会过期(押注卡 → 删除线+盖章 → keep 新卡升起)→ p6-06 分水岭压场; + * 6-C 身份卡 + 下期预告卡(只进画面)+ 四件套标尺尾帧(第三格常亮)→ 渐黑。 + * ★ 渐黑窗口从**末 beat 总时长**(6-C 的 beatDurationInFrames)推导,不是末句时长 * —— 第三集上线教训(skills/06 渲染红线四)。 */ import React from 'react'; import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoConfig} from 'remotion'; import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Panel, SceneHeader} from '../components/motifs'; +import {HarnessScale} from '../components/HarnessScale'; +import {Footnote, Panel, SceneHeader} from '../components/motifs'; -/** 6-A 一句话合同:keep 描边金句卡 + 两行对仗回收 */ -const OneLineContract: React.FC<{recycleAt: number}> = ({recycleAt}) => { +/** 6-B 信源卡前置:两行逐行浮现(官方文档+取数日期 / 第三方源码分析已逐处标注) */ +const SourceFirst: React.FC = () => { + const frame = useCurrentFrame(); + const {fps} = useVideoConfig(); + const enter = spring({frame: frame - 4, fps, config: {damping: 200}}); + const rows = [ + ['官方文档', 'code.claude.com/docs · 取数2026年8月'], + ['源码分析', '第三方逆向分析 · 片中逐处标注'], + ]; + return ( + +
+ +
+ {'信源'} +
+ {rows.map(([k, v], i) => ( +
+
+ {k} +
+
{v}
+
+ ))} +
+
+
+ ); +}; + +/** 6-A 一句话合同:keep 描边金句卡 + 两行对仗回收 + 赌注会过期(p6-04a/b/c)+ p6-06 分水岭卡压场 */ +const OneLineContract: React.FC<{ + recycleAt: number; + wagerAt: number; + strikeAt: number; + riseAt: number; + divideAt: number; +}> = ({recycleAt, wagerAt, strikeAt, riseAt, divideAt}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); const enter = spring({frame: frame - 4, fps, config: {damping: 200}}); @@ -19,10 +68,34 @@ const OneLineContract: React.FC<{recycleAt: number}> = ({recycleAt}) => { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); + // p6-04a:回收两行上移收缩、押注卡淡入 + const wager = interpolate(frame - wagerAt, [0, 16], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // p6-04b:箭头扫过 → 划删除线 + 盖章 + const strike = interpolate(frame - strikeAt, [0, 10], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const stamp = interpolate(frame - strikeAt - 10, [0, 12], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // p6-04c:右侧 keep 新卡升起 + const rise = interpolate(frame - riseAt, [0, 18], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // p6-06:分水岭卡压场(提示词工程 → Harness 工程) + const divide = interpolate(frame - divideAt, [0, 18], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); return (
- {/* 合同卡:serif + keep 描边 */} + {/* 合同卡:serif + keep 描边(赌注段淡出让位) */}
= ({recycleAt}) => { borderRadius: 20, border: `4px solid ${theme.keep}`, background: 'rgba(169,196,108,0.05)', + opacity: 1 - wager * 0.85, + transform: `scale(${1 - wager * 0.18})`, }} >
@@ -42,12 +117,13 @@ const OneLineContract: React.FC<{recycleAt: number}> = ({recycleAt}) => { {'不许丢的放本子'}
- {/* 两行回收:对仗浮现(contract 收缩让位) */} + {/* 两行回收:对仗浮现;赌注段上移收缩 */}
@@ -57,29 +133,159 @@ const OneLineContract: React.FC<{recycleAt: number}> = ({recycleAt}) => { {'一套负责固执地记:一事一文件、索引常驻、先抢救再碎纸'}
+ {/* 赌注会过期:左押注卡(删除线+盖章)→ 右 keep 新卡升起 */} + {wager > 0 ? ( +
+
+
+
{'记忆 · 押注'}
+
+ {'它记不住'} +
+ {/* 模型变强箭头扫过 */} + + + {strike >= 1 ? ( + + ) : null} + +
+ {'模型变强 →'} +
+ {/* 删除线:箭头扫过后划过卡面 */} + {strike > 0 ? ( +
+ ) : null} +
+ {/* 盖章:基本设定删八成 · 评测没掉分 */} + {stamp > 0 ? ( +
+ {'删八成 · 没掉分'} +
+ ) : null} +
+ {/* 右:keep 新卡升起(手写让位给自长记忆) */} + {rise > 0 ? ( +
+
{'正在让位'}
+
+ {'它自己长的记忆'} +
+
+ ) : null} +
+ ) : null} + {/* p6-06 分水岭卡压场:记忆是建议,钩子才是规则 */} + {divide > 0 ? ( +
+
+
+ {'记忆是建议,钩子才是规则'} +
+
+ {'提示词工程 → Harness 工程 · 官方口径 · 取数 2026-08'} +
+
+
+ ) : null}
); }; -/** - * 6-B 信源卡 + 身份卡 + 渐黑。 - * `beatDurationInFrames` 是**本 beat 的总时长**,渐黑窗口据此反推(末 1.2s)。 - */ -const SourceAndFade: React.FC<{beatDurationInFrames: number; idAt: number}> = ({ +/** 6-C 身份卡 + 下期预告卡 + 四件套标尺尾帧 + 渐黑(末 beat 总时长推导,红线四) */ +const IdentityAndFade: React.FC<{beatDurationInFrames: number; nextAt: number; scaleAt: number}> = ({ beatDurationInFrames, - idAt, + nextAt, + scaleAt, }) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); const enter = spring({frame: frame - 4, fps, config: {damping: 200}}); - const rows = [ - ['官方文档', 'code.claude.com/docs · 取数2026年8月'], - ['工程博客', 'anthropic.com/engineering'], - ['源码分析', '第三方逆向分析 · 片中逐处标注'], - ['数字口径', '开源仓库钉版 67a9126c 实测 · 字节归档'], - ]; - const idT = interpolate(frame - idAt, [0, 20], [0, 1], { + const nextT = interpolate(frame - nextAt, [0, 20], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); @@ -92,89 +298,59 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; idAt: number}> = ({ }); return ( -
- -
- {'信源'} +
+
+ {'Claude Code Harness Engineering'} +
+
+ {'记忆层:会丢的和不能丢的'} +
+ {/* 下期预告卡:标题只在画面(反串线纪律) */} +
+
+ {'下期 · 时机层'}
- {rows.map(([k, v], i) => ( -
-
- {k} -
-
{v}
-
- ))} - {/* 诚实行:涉内部分均为源码分析,片中逐处标注(三级证据的公开落点) */} -
- {'涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注'} +
+ {'谁来按下开始'}
- +
- {/* 身份卡(系列卡:口播不念,仅视觉层) */} - {idT > 0 ? ( + {/* 四件套标尺尾帧:第三格「上下文管理」保持点亮(渐黑前压入) */} + {frame >= scaleAt ? (
-
- {'Claude Code Harness Engineering'} -
-
- {'记忆层:会丢的和不能丢的'} -
- {/* 下期预告卡:标题只在画面(反串线纪律) */} -
-
- {'下期 · 时机层'} -
-
- {'谁来按下开始'} -
-
+
) : null} {/* 渐黑遮罩 */} @@ -186,19 +362,37 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; idAt: number}> = ({ export const P6Ending: React.FC<{scene: SceneRange}> = ({scene}) => { const w = (fromId: string, toId?: string) => beatWindow(scene.sentences, scene.from, fromId, toId); const at = (id: string) => w(id).from; + // 收尾改序(分镜 6-B → 6-A → 6-C):免责前置、金句居中、身份+预告压轴 + const bB = w('p6-07', 'p6-08'); + const relB = (id: string) => at(id) - bB.from; const bA = w('p6-01', 'p6-06'); const relA = (id: string) => at(id) - bA.from; - const bB = w('p6-07', 'p6-10'); - const relB = (id: string) => at(id) - bB.from; + const bC = w('p6-09', 'p6-10'); + const relC = (id: string) => at(id) - bC.from; return ( + + + - + + {/* p6-05:官方口径角标(两条腿都是上下文,不是闸门——分水岭卡的出处行) */} + {'这两条腿,都是上下文,不是闸门 —— 官方口径 · 取数 2026-08'} - + {/* 渐黑窗口从**本 beat 总时长**推导,不是末句时长(红线四) */} - + ); diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx index f7018873..146764d4 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P0Hook.tsx @@ -448,8 +448,9 @@ export const P0Hook: React.FC<{scene: SceneRange}> = ({scene}) => { - {/* 拉镜点在 p0-03;cardsAt:官方三失败模式症状卡(Harness Engineering 改造) */} - + {/* 拉镜点在 p0-03;cardsAt:官方三失败模式症状卡(Harness Engineering 改造)。 + 三个名字的列举已拆到 p0-03a(B 方案改稿),卡片跟着列举句走 */} + {/* 图标预览点在 p0-08「一堆文件、几个信箱、一张编号表」 */} diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx index 2cf0f7d6..6e9b30ca 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx @@ -733,7 +733,7 @@ export const P1Board: React.FC<{scene: SceneRange}> = ({scene}) => { const at = (id: string) => w(id).from; const bA = w('p1-01', 'p1-06'); const bB = w('p1-07', 'p1-10'); - const bC = w('p1-11', 'p1-15'); + const bC = w('p1-13', 'p1-15'); const bD = w('p1-16', 'p1-21'); const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx index 317e346c..12b65a4b 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx @@ -293,61 +293,208 @@ const MailboxRow: React.FC<{sendAt: number; readAt: number}> = ({sendAt, readAt}
) : null}
- {'写文件带锁,防两个队友投信写串行——第三方的源码分析'} + + {'写文件带锁(防串行)· 消息类型 15 种——第三方的源码分析'} + ); }; -/** 2-C 十五种消息类型墙(反枚举:统一 panel 底编号)缩成一行字 */ -const FifteenTypes: React.FC<{wallAt: number; shrinkAt: number}> = ({wallAt, shrinkAt}) => { +/** 2-C ★领队信箱:队友干完活把总结信投进领队信箱(飞入闪光);领队收信、 + * 信里内容行贴进小对话泡;写锁 chip 亮一下(B 方案改稿:p2-16/17 十五种类型 + * 墙两句已删,类型口径并入 2-B 角标;本镜回到「领队也走信箱」的主线画面)。 */ +const LeaderMailbox: React.FC<{dropAt: number; readAt: number; lockAt: number}> = ({ + dropAt, + readAt, + lockAt, +}) => { const frame = useCurrentFrame(); - const names = [ - '普通消息', '空闲通知', '权限请求', '权限回复', '计划审批', - '审批回复', '关机请求', '关机同意', '关机拒绝', '任务分派', - '权限广播', '模式修改', '沙箱权限', '移除通知', '广播通知', + // 总结信飞行:阿强/阿珍的信先后沿弧线投进领队信箱(peer→core 方向即语义) + const flights = [ + {from: {x: 360, y: 260}, to: {x: 880, y: 360}, at: dropAt, tag: '阿强 · 总结'}, + {from: {x: 1420, y: 260}, to: {x: 880, y: 360}, at: dropAt + 30, tag: '阿珍 · 总结'}, ]; - const shrink = phase(frame, shrinkAt, 20); + // 投中闪光:两封信先后落到信箱口的接触涟漪 + const hits = flights.map((f) => phase(frame, f.at + 20, 10)); + // 收信:领队信箱面板上的信行展开;readAt 起内容行贴进小对话泡 + const read = phase(frame, readAt, 16); + // 写锁 chip:p2-15「写文件加了一把锁」亮一下 + const lock = phase(frame, lockAt, 12); + const lockPulse = + lock > 0 ? interpolate(frame - lockAt, [0, 8, 26], [0, 1, 0.55], {extrapolateRight: 'clamp'}) : 0; return ( - {/* 类型墙:5×3 编号卡(反枚举:无 N 色,激活时才 mech 染色) */} -
- {names.map((n, i) => ( - +
+ {/* 中央:领队环 + 信箱 */} +
+ +
+ +
+
+ {/* 两翼:队友环(peer 同色同宽同节点——反枚举) */} + {[ + {name: '阿强', x: 220}, + {name: '阿珍', x: 1280}, + ].map((m) => ( +
+ +
+ +
+
))} + {/* 领队信箱文件:投进来的总结信行(收信前在此展开) */} +
+ + {/* 写锁 chip:防串行的写锁亮一下(p2-15 句锚) */} + {lockPulse > 0 ? ( +
+
0.7 ? theme.mechDeep : theme.panel, + boxShadow: `0 0 ${18 * lockPulse}px ${theme.mech}`, + fontFamily: theme.sans, + fontSize: 20, + color: theme.mech, + }} + > + + + + + {'写带锁 · 防串行'} +
+
+ ) : null} +
+ {/* 总结信飞行弧线 + 投中闪光 */} + + {flights.map((f, i) => { + const t = interpolate(frame - f.at, [0, 22], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + if (t <= 0 || t >= 1) return null; + const c = {x: (f.from.x + f.to.x) / 2, y: Math.min(f.from.y, f.to.y) - 130}; + const p = qBezier(f.from, c, f.to, t); + return ( + + + + + {f.tag} + + + ); + })} + {hits.map((h, i) => + h > 0 ? ( + [0, 1].map((k) => ( + + )) + ) : null, + )} + + {/* 收信注入:信里内容行贴进领队的小对话泡 */} + {read > 0 ? ( +
+ +
+ {'领队的对话'} +
+ {[ + {t: '接口改完,可以安排联调', at: readAt + 6}, + {t: '文档写好,等你过目', at: readAt + 18}, + ].map((ln) => { + const o = phase(frame, ln.at, 8); + return ( +
+ {ln.t} +
+ ); + })} +
+ {'收信 → 贴进对话 → 接着指挥'} +
+
+
+ ) : null}
- {/* 收束句:全部缩成一行字 */} -
- {'往文件里加一行带类型的字'} -
- {shrink < 0.5 ? ( - {'消息类型 15 种——第三方的源码分析'} - ) : null} + {'领队也走信箱——收信贴进对话,接着指挥'} ); }; @@ -826,8 +973,8 @@ export const P2Mail: React.FC<{scene: SceneRange}> = ({scene}) => { const at = (id: string) => w(id).from; const bA = w('p2-01', 'p2-05'); const bB = w('p2-06', 'p2-11'); - const bC = w('p2-12', 'p2-14'); - const bD = w('p2-15', 'p2-19'); + const bC = w('p2-12', 'p2-15'); + const bD = w('p2-18', 'p2-19'); const bE = w('p2-20', 'p2-25'); const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( @@ -839,8 +986,12 @@ export const P2Mail: React.FC<{scene: SceneRange}> = ({scene}) => { - - + + diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx index 58e9cdfa..19567309 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx @@ -394,14 +394,13 @@ const KillVsHandshake: React.FC<{crackAt: number; stepsAt: number}> = ({crackAt, ); }; -/** 3-B ★握手轨全流程:请求 req_0042 滑出停等回话 → pending 亮 → 同号应答合拢咔 → 错类型弹开 */ -const RailFull: React.FC<{reqAt: number; pendAt: number; ackAt: number; lockAt: number; wrongAt: number}> = ({ - reqAt, - pendAt, - ackAt, - lockAt, - wrongAt, -}) => { +/** 3-B ★握手轨全流程:请求 req_0042 滑出停等回话 → pending 亮 → 同号应答合拢咔 → 错类型弹开。 + * B 方案改稿:原 p3-08/09 两句压进 p3-06/07,锁扣与错类型弹开改为句内相位推进 + * (pendAt 起的相对帧),不再各自吃一个句锚。 */ +const RailFull: React.FC<{reqAt: number; pendAt: number}> = ({reqAt, pendAt}) => { + const ackAt = pendAt + 18; + const lockAt = pendAt + 40; + const wrongAt = pendAt + 62; const frame = useCurrentFrame(); const reqGo = interpolate(frame - reqAt, [0, 22], [0, 1], { extrapolateLeft: 'clamp', @@ -716,7 +715,7 @@ export const P3Handshake: React.FC<{scene: SceneRange}> = ({scene}) => { const w = (fromId: string, toId?: string) => beatWindow(scene.sentences, scene.from, fromId, toId); const at = (id: string) => w(id).from; const bA = w('p3-01', 'p3-05'); - const bB = w('p3-06', 'p3-09'); + const bB = w('p3-06', 'p3-07'); const bC = w('p3-10', 'p3-11'); const bD = w('p3-12', 'p3-16'); const rel = (b: {from: number}, id: string) => at(id) - b.from; @@ -727,13 +726,7 @@ export const P3Handshake: React.FC<{scene: SceneRange}> = ({scene}) => { - + = ({gridAt, lockAt, scoreAt, bootAt, frostAt, splitAt}) => { + const frame = useCurrentFrame(); + const {fps} = useVideoConfig(); + // 4×4 容器网格:逐格点亮(间隔 4 帧,分镜动效约定) + const lit = (i: number) => + interpolate(frame - gridAt - i * 4, [0, 8], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 锁文件卡:飞入 + 写入闪光(p4-18) + const lockFly = interpolate(frame - lockAt, [0, 20], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const lockFlash = interpolate(frame - lockAt - 18, [0, 6, 22], [0, 1, 0], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 战果数字带:逐项滚动(p4-19)——确定性 ease,无随机 + const scoreItems = [ + {t: '并行', v: 16}, + {t: '会话', v: 2000}, + {t: '代码行', v: 100000}, + ]; + const scoreIn = phase(frame, scoreAt, 14); + // 空席盖章:领队席空 + deny 叉章(p4-19「没有总调度,没有领队」) + const seatStamp = spring({frame: frame - scoreAt - 14, fps, config: {damping: 130}}); + // boot 脉冲 + 账单停格(p4-20) + const bootPulse = + frame >= bootAt + ? interpolate((frame - bootAt) % 36, [0, 6, 30], [0, 1, 0], {extrapolateRight: 'clamp'}) + : 0; + const billIn = phase(frame, bootAt + 10, 14); + // 冻霜级联:从第 0 格扩散冻结全部 16 格(p4-21/22——一个报错全场停摆) + const frostSpread = interpolate(frame - frostAt, [0, 52], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const cellFrost = (i: number) => + Math.max(0, Math.min(1, (frostSpread * 17 - i) / 2)); + // 分流:文件块分两堆 + 二分箭头逐轮收敛(p4-23/24) + const split = phase(frame, splitAt, 20); + const bisectRounds = interpolate(frame - splitAt - 10, [0, 60], [0, 3], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 网格几何:4×4 紧凑格(CELL 112——给底部分流条带与角标让出垂直空间, + // 避开字幕带与 Footnote 双行区,skills/06 红线二) + const GX = 150; + const GY = 90; + const CELL = 112; + const GAP = 14; + const GRID_W = 4 * CELL + 3 * GAP; + return ( + +
+ {/* 主体:4×4 容器网格(16 个 peer 同色小环,反枚举) */} +
+ {Array.from({length: 16}, (_, i) => { + const e = lit(i); + if (e <= 0) return null; + const r = Math.floor(i / 4); + const c = i % 4; + const fr = cellFrost(i); + return ( +
0.3 ? theme.deny : theme.peer}`, + background: fr > 0.3 ? `${theme.deny}1a` : theme.panel, + opacity: e, + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + }} + > + + 0.3 ? theme.dim : theme.peer} + strokeWidth={4} + opacity={fr > 0.3 ? 0.4 : 1} + /> + {/* 占坑一行:认领 = 往锁文件写一行 */} + 0.3 ? theme.dim : theme.text} + > + {`ag-${String(i + 1).padStart(2, '0')}`} + + + {/* 冻霜角标:格内右上小雪花刻线(deny,确定性六线星) */} + {fr > 0.4 ? ( + + {[0, 60, 120].map((a) => ( + + ))} + + ) : null} +
+ ); + })} + {/* 冻霜扩散波纹(从一格级联) */} + {frostSpread > 0 && frostSpread < 1 ? ( + + + + ) : null} + {/* 领队席:空(盖 deny 叉章——没有总调度;网格右缘旁) */} + {seatStamp > 0 ? ( +
+
+ {'领队席:空'} + + + + + +
+
+ ) : null} +
+ {/* 右侧配件列:锁文件 → 战果带 → boot/账单(随句锚换页;右移避让领队席) */} +
+ {/* 锁文件卡:current_tasks/xxx.txt 飞入 + 占坑标签(p4-18) */} + {lockFly > 0 ? ( +
0 ? `0 0 ${26 * lockFlash}px ${theme.mech}` : 'none', + }} + > + +
+ {'current_tasks/'} +
+
+ {'ag-03.txt'} +
+
+ {'占坑'} +
+
+
+ ) : null} + {/* 战果数字带:逐项滚动(p4-19) */} + {scoreIn > 0 ? ( +
+ + {scoreItems.map((s, k) => { + const o = phase(frame, scoreAt + k * 8, 10); + const n = Math.round(s.v * phase(frame, scoreAt + k * 8, 22)); + return ( +
+ {s.t} + + {n.toLocaleString('en-US')} + +
+ ); + })} + {/* boot 脉冲行:可启动内核(p4-20) */} +
0 ? 1 : billIn > 0 ? 0.75 : 0, + }} + > + + + + 0 ? 1 : 0.6} /> + + + {'可启动的内核'} + +
+ {/* 账单停格(p4-20) */} + {billIn > 0 ? ( +
+ {'账单'} + {'< $20,000'} +
+ ) : null} +
+
+ ) : null} +
+ {/* 底部条带:文件块分流两堆 + 二分箭头收敛(p4-23/24) */} + {split > 0 ? ( +
+ {/* 大堆:走现成的编译器(mech) */} +
+
+ {Array.from({length: 10}, (_, i) => { + const o = interpolate(frame - splitAt - 4 - i * 2, [0, 6], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const h = 30 + ((i * 37) % 36); + return ( +
+ ); + })} +
+
+ {'大部分文件 → 现成的编译器'} +
+
+ {/* 二分箭头:逐轮收敛(三轮,确定性——每轮一对更短的叉线) */} + + {[0, 1, 2].map((k) => { + const on = bisectRounds >= k + 1; + const half = 32 - k * 10; // 每轮摆幅收窄 + const yMid = 45; + const x1 = 40 + k * 14; + const x2 = 150 - k * 14; + return ( + + + + + ); + })} + + {'二分 · 谁也不挡谁'} + + + {/* 小堆:留给它(peer) */} +
+
+ {Array.from({length: 3}, (_, i) => { + const o = interpolate(frame - splitAt - 10 - i * 3, [0, 6], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + return ( +
+ ); + })} +
+
+ {'一小撮 → 它'} +
+
+
+ ) : null} +
+ + {'16 并行 · ~2,000 会话 · ~$20K · ~100K LOC —— 官方工程博客 2026-02-05'} + + + ); +}; + /** 4-D 包工头帽 → 项目经理牌:帽子换牌 + 两件事卡片钉在环旁 */ const ForemanToManager: React.FC<{swapAt: number; cardsAt: number}> = ({swapAt, cardsAt}) => { const frame = useCurrentFrame(); @@ -703,6 +1121,7 @@ export const P4Autonomy: React.FC<{scene: SceneRange}> = ({scene}) => { const bB = w('p4-04', 'p4-09'); const bC = w('p4-10', 'p4-13'); const bD = w('p4-14', 'p4-16'); + const bE = w('p4-17', 'p4-24'); const rel = (b: {from: number}, id: string) => at(id) - b.from; return ( @@ -729,6 +1148,16 @@ export const P4Autonomy: React.FC<{scene: SceneRange}> = ({scene}) => { + + + ); }; diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx index 9e251fb2..8ff436ed 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx @@ -719,12 +719,15 @@ const WhoHoldsPlan: React.FC<{ ); }; -const SourceAndFade: React.FC<{beatDurationInFrames: number; partsAt: number; costAt: number; seriesAt: number}> = ({ - beatDurationInFrames, - partsAt, - costAt, - seriesAt, -}) => { +const SourceAndFade: React.FC<{ + beatDurationInFrames: number; + partsAt: number; + costAt: number; + seriesAt: number; + lawAt: number; + lawEndAt: number; + idAt: number; +}> = ({beatDurationInFrames, partsAt, costAt, seriesAt, lawAt, lawEndAt, idAt}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); // p6-12 零件四连小图(板/箱/号/桌)与 p6-13/14 十五倍对比条先于信源卡(分镜 6-E 承诺) @@ -736,10 +739,30 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; partsAt: number; co extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); + // 换页语法(与 2-E/6-D 同款):收束段(零件+十五倍)让位给信源卡(p6-15); + // p6-16a 第一定律两句时零件四连**带着「赌注」标签回归**,逐个 dim 变灰 + // (p6-16b 末全灰);身份卡 + 下期卡从 p6-17 进。 const preludeGone = interpolate(frame - (seriesAt - 26), [0, 20], [1, 0], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); + const preludeBack = interpolate(frame - (lawAt - 18), [0, 16], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const preludeOut = interpolate(frame - (lawEndAt + 26), [0, 18], [1, 0], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const preludeO = + partsT * Math.max(preludeGone, preludeBack * preludeOut); + // 赌注标签 + 逐个变灰:lawAt 起标签淡入,四枚依次 dim(每 10 帧一枚,p6-16b 末全灰) + const betOn = phase(frame, lawAt, 12); + const partDim = (i: number) => + interpolate(frame - lawAt - 8 - i * 10, [0, 10], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); const enter = spring({frame: frame - (seriesAt - 22), fps, config: {damping: 200}}); const rows = [ ['官方文档', 'code.claude.com/docs · 取数2026年8月'], @@ -747,7 +770,16 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; partsAt: number; co ['源码分析', '第三方逆向分析 · 片中逐处标注'], ['数字口径', '开源仓库钉版 67a9126c 实测 · 字节归档'], ]; - const seriesT = phase(frame, seriesAt, 20); + // 信源卡退场:第一定律回归段(lawAt..lawEnd)压到背景 0.3;身份卡起全隐 + const sourceOut = interpolate(frame - (lawAt - 18), [0, 14], [1, 0.3], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }) * interpolate(frame - (idAt - 10), [0, 12], [1, 0], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 身份卡(+ 下期预告卡):p6-17 起 + const idT = phase(frame, idAt, 20); // 渐黑:末 1.2 秒线性压暗到全黑,窗口从 beat 总时长反推 const fadeFrames = Math.round(1.2 * fps); const fadeStart = beatDurationInFrames - fadeFrames; @@ -757,12 +789,13 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; partsAt: number; co }); return ( - {/* p6-12 零件四连小图 + p6-13/14 官方冷水(十五倍)——信源卡之前的收束段 */} - {preludeGone > 0.01 ? ( + {/* p6-12 零件四连小图 + p6-13/14 官方冷水(十五倍)——信源卡之前的收束段; + p6-16a/b 第一定律段带「赌注」标签回归并逐个变灰 */} + {preludeO > 0.01 ? (
(
- + -
{p.t}
+
+ {p.t} +
+ {/* p6-16b「押着『模型做不到』的赌注」:四枚各加一枚赌注小标签, + 随各自 dim 一起变灰淡出 */} + {betOn > 0 ? ( +
0.5 ? theme.panelBorder : theme.peer}`, + fontFamily: theme.sans, + fontSize: 15, + color: partDim(i) > 0.5 ? theme.dim : theme.peer, + opacity: betOn * (1 - partDim(i) * 0.7), + }} + > + {'赌注'} +
+ ) : null}
))}
- {/* 十五倍对比条:普通对话 1× vs 多智能体 15× */} - {costT > 0 ? ( -
+ {/* 十五倍对比条:普通对话 1× vs 多智能体 15×(收束段;第一定律回归段不再重演) */} + {costT > 0 && preludeGone > 0.01 ? ( +
{'普通对话'} @@ -816,7 +878,7 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; partsAt: number; co ) : null}
) : null} -
+
{'信源'} @@ -858,14 +920,14 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; partsAt: number; co
- {/* 系列身份卡 */} - {seriesT > 0 ? ( + {/* 系列身份卡 + 下期预告卡(p6-17 起——收尾句序:信源→第一定律→身份+下期) */} + {idT > 0 ? (
@@ -901,6 +963,24 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; partsAt: number; co
) : null} + {/* p6-16a/b 第一定律角标:自省句(bottom ≥ 150 避让字幕带) */} + {betOn > 0 && preludeOut > 0.05 ? ( +
+ {'常问自己:我可以停止做什么?'} +
+ ) : null} {/* 渐黑遮罩(末 1.2s 线性压暗;窗口从 beat 总时长推导——红线四) */} @@ -944,6 +1024,9 @@ export const P6Finale: React.FC<{scene: SceneRange}> = ({scene}) => { partsAt={rel(bE, 'p6-12')} costAt={rel(bE, 'p6-13')} seriesAt={rel(bE, 'p6-15')} + lawAt={rel(bE, 'p6-16a')} + lawEndAt={rel(bE, 'p6-16b')} + idAt={rel(bE, 'p6-17')} /> diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx index 3eea885b..e2ac3ab7 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx @@ -16,6 +16,10 @@ const DEVICES = [ {t: '补救梯', kind: 'ladder'}, ] as const; +/** p0-08/09 官方四件套标尺(0-C 用):循环/工具/上下文管理/护栏—— + * 前两格与末格不点亮(panelBorder 虚线 + dim 字),唯「上下文管理」格 view 描边。 */ +const FOUR_PIECES = ['循环', '工具', '上下文管理', '护栏'] as const; + /** 0-A 系列同款终端:最初的「任务:改命名」首行逐渐被工具输出顶出可视区。 * 行区整体上移(scrollShift),滚出瞬间残影停在顶端变 dim——「被挤走」被看见。 * p0-03「其中一样,刚刚被官方收回去」:右下角「收回」钢印砸下(退位悬念第一分钟埋下)。 */ @@ -172,13 +176,16 @@ const DeskFillsUp: React.FC<{fillPerFrame: number; shoveAt: number; dropAt: numb }; /** 0-C 桌面定格,主线问题两行 serif 大字;环(core)第一次在桌后浮现(35% 透明)。 - * p0-07 答句后:五样装置小图标自左向右列队点亮(清单/副桌/目录/垫纸/梯子)。 */ -const QuestionAndRingBehind: React.FC<{qAt: number; answerAt: number; ringAt: number; devicesAt: number}> = ({ - qAt, - answerAt, - ringAt, - devicesAt, -}) => { + * p0-07 答句后:五样装置小图标自左向右列队点亮(清单/副桌/目录/垫纸/梯子); + * p0-08 起:官方四件套标尺自桌下升起,p0-09「上下文管理」格左半点亮——今天补前半。 */ +const QuestionAndRingBehind: React.FC<{ + qAt: number; + answerAt: number; + ringAt: number; + devicesAt: number; + rulerAt: number; + fillAt: number; +}> = ({qAt, answerAt, ringAt, devicesAt, rulerAt, fillAt}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); const deskIn = spring({frame: frame - 2, fps, config: {damping: 200}}); @@ -194,6 +201,16 @@ const QuestionAndRingBehind: React.FC<{qAt: number; answerAt: number; ringAt: nu extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); + // 四件套标尺:自桌下升起(p0-08);逐格描边(stagger) + const ruler = interpolate(frame - rulerAt, [0, 20], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 「上下文管理」格左半:viewDeep 线性填充(24 帧,p0-09 起) + const halfFill = interpolate(frame - fillAt, [0, 24], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); return ( {/* 环在桌后:先画环(半透明 35%),桌子压在其上——「环在后面看着」 */} @@ -207,7 +224,7 @@ const QuestionAndRingBehind: React.FC<{qAt: number; answerAt: number; ringAt: nu
+ {/* p0-08/09 官方四件套标尺:自桌下升起(分镜 0-C 承诺「今天补前半」) */} +
+ {FOUR_PIECES.map((p, i) => { + const hot = p === '上下文管理'; + // 逐格描边:自升起后 stagger 点亮边框 + const cell = interpolate(frame - rulerAt - 20 - i * 5, [0, 10], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + return ( +
+
0 ? (hot ? theme.view : theme.panelBorder) : 'transparent' + }`, + borderRadius: 8, + overflow: 'hidden', + position: 'relative', + }} + > + {/* 「上下文管理」格只填左半格(viewDeep 线性填充,p0-09 起) */} + {hot ? ( +
+ ) : null} + {p} +
+
+ ); + })} +
+ {/* 格下小字:今天补前半(随半格填充浮现) */} +
+ {'今天补的正是前半:它每一轮能看见什么'} +
@@ -329,7 +413,7 @@ export const P0Hook: React.FC<{scene: SceneRange}> = ({scene}) => { const relA = (id: string) => at(id) - bA.from; const bB = w('p0-04', 'p0-05'); const relB = (id: string) => at(id) - bB.from; - const bC = w('p0-06', 'p0-08'); + const bC = w('p0-06', 'p0-09'); const relC = (id: string) => at(id) - bC.from; return ( @@ -343,12 +427,15 @@ export const P0Hook: React.FC<{scene: SceneRange}> = ({scene}) => { - {/* p0-06 抛问题+答案句 + 环在桌后描线(35% 透明);p0-07 五样装置列队 */} + {/* p0-06 抛问题+答案句 + 环在桌后描线(35% 透明);p0-07 五样装置列队; + p0-08 四件套标尺升起;p0-09「上下文管理」格左半点亮 + 小字 */} diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx index 493c94cd..cf8c596b 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx @@ -1,5 +1,6 @@ -/** P1 把清单钉在桌上(分镜 1-A…1-D)—— TodoWrite - * 三态清单卡滑入 → 钉进对话流(后续色块被顶开)→ 两行 diff + 金句 → 三轮催更印章。 */ +/** P1 把清单钉在桌上(分镜 1-A…1-F)—— TodoWrite + * 三态清单卡滑入 → 钉进对话流(后续色块被顶开)→ 两行 diff + 金句 → 退位帧(钢印) + * → 计划闸(玻璃罩 + 三选一)→ 任务系统预告 + 零件生命周期时间轴。 */ import React from 'react'; import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoConfig} from 'remotion'; import {theme} from '../design/theme'; @@ -284,11 +285,13 @@ const TwoLineDiff: React.FC<{quoteAt: number}> = ({quoteAt}) => { ); }; -/** 1-D 退位帧:官方默认停用清单工具——「收回」钢印 + 官方公告条(Harness Engineering 改造版) */ -const RetirementStamp: React.FC<{noticeAt: number; stampAt: number; taskSysAt: number}> = ({ +/** 1-D 退位帧:官方默认停用清单工具——「收回」钢印 + 官方公告条(Harness Engineering 改造版)。 + * 分镜 1-D:damping:12 过冲 + ripple;被盖章的 todo_write 卡本体有反应—— + * 描边 view→panelBorder 褪色、三行状态字依次划线、整卡下沉 12px 降到 0.45 透明;「押注押到期」标签。 */ +const RetirementStamp: React.FC<{noticeAt: number; stampAt: number; betAt: number}> = ({ noticeAt, stampAt, - taskSysAt, + betAt, }) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); @@ -296,19 +299,53 @@ const RetirementStamp: React.FC<{noticeAt: number; stampAt: number; taskSysAt: n extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); - const stamp = spring({frame: frame - stampAt, fps, config: {damping: 140}}); - const taskSys = interpolate(frame - taskSysAt, [0, 16], [0, 1], { + const stamp = spring({frame: frame - stampAt, fps, config: {damping: 12}}); + // 盖章冲击:容器同帧 translateY(3px) 下沉、8 帧回弹 + const shakeT = interpolate(frame - stampAt, [0, 8], [1, 0], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const cardSink = frame >= stampAt ? Math.min(1, (frame - stampAt) / 14) : 0; + const struck = (i: number) => frame >= stampAt + 6 + i * 6; + const bet = interpolate(frame - betAt, [0, 14], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); return ( -
- {/* 清单卡(缩小版,居中) */} - +
+ {/* 清单卡(缩小版,居中)——盖章后褪色、划线、下沉、降透明 */} + 0 ? theme.panelBorder : theme.view} + style={{ + position: 'absolute', + left: 280, + top: 60 + 12 * cardSink, + width: 540, + padding: '22px 28px', + opacity: 1 - 0.55 * cardSink, + }} + >
{'todo_write'}
{['pending 待办', 'in_progress 干着', 'completed 完事'].map((s, i) => ( -
+
{s}
))} @@ -333,51 +370,300 @@ const RetirementStamp: React.FC<{noticeAt: number; stampAt: number; taskSysAt: n
- {/* 收回钢印 */} - {stamp > 0 ? ( + {/* 收回钢印(damping:12 过冲 + ripple,来自 motifs.Stamp) */} + + {/* 「押注押到期」标签 */} + {bet > 0 ? (
- {'收 回'} + {'押注押到期'}
) : null} - {/* 任务系统预告 */} - {taskSys > 0 ? ( +
+ + {'零件押的是「模型记不住」的赌注 —— 模型变强,赌注过期(官方文档口径)'} + +
+ ); +}; + +/** 1-E 新镜「计划闸」:只读探索的手被玻璃罩罩住;view 计划卡落桌;「改文件」动作块 + * 撞罩被 deny 弹回;三选一按钮(反枚举:panel 底 + 编号 01/02/03);末句金句卡。 */ +const PlanGate: React.FC<{ + glassAt: number; + planAt: number; + bounceAt: number; + choicesAt: number; + quoteAt: number; +}> = ({glassAt, planAt, bounceAt, choicesAt, quoteAt}) => { + const frame = useCurrentFrame(); + const {fps} = useVideoConfig(); + if (frame >= quoteAt) { + return ; + } + // 玻璃罩自上罩下(spring) + const glass = spring({frame: frame - glassAt, fps, config: {damping: 200}}); + // 计划卡落桌(damping:200) + const plan = spring({frame: frame - planAt, fps, config: {damping: 200}}); + // 「改文件」动作块撞罩弹回:复用 3-C 单向阀 bounce 曲线(0→-46→-32 位移 + deny 闪) + const blocked = frame >= bounceAt; + const travel = interpolate(frame - bounceAt, [-16, 18], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const bounce = blocked + ? interpolate(frame - bounceAt, [0, 12, 26], [0, -46, -32], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }) + : 0; + const CHOICES = ['交给自动闸门', '逐条人工点头', '继续再想'] as const; + return ( + +
+ {/* 文件(只读探索的对象)+ 玻璃罩 */} +
+ +
{'src/query.ts'}
+
+ {'只读探索:\n读结构 · 记结论\n不动一行'} +
+
+ {/* 玻璃罩:mech 描边 + 8% 白底,自上罩下 */} +
+
+ {'计划模式 · 玻璃罩'} +
+
+ {'罩住:看得见,改不得'} +
+
+
+ {/* 计划卡:从上落桌(view 描边) */} +
+ +
{'计划(写给你过目)'}
+ {['① 摸清调用链', '② 列出改法两套', '③ 标注风险点'].map((s) => ( +
+ {s} +
+ ))} +
+
+ {/* 「改文件」动作块:从右侧飞向玻璃罩,撞罩被 deny 弹回(复用 3-C 单向阀曲线) */} + {blocked ? (
0.05 ? 1 : 0, + }} + > + +
+ {'计划没批,一律拦住'} +
+
+ ) : null} + {/* 三选一按钮:反枚举(panel 底 + 编号 01/02/03,仅当前项染 mech) */} +
+ {CHOICES.map((c, i) => { + const on = frame >= choicesAt + i * 9; + const lit = frame >= choicesAt + i * 9 + 18; + return ( +
+ + {String(i + 1).padStart(2, '0')} + + {c} +
+ ); + })} +
+
+ {'计划模式:只读探索 → 写计划 → 批准那一下三选一(官方文档口径)'} +
+ ); +}; + +/** 1-F 任务系统预告(小图标一闪)+「装在循环外」收束 + 零件生命周期时间轴: + * 左端「模型记不住 → 需要清单」、右端「模型记住了 → 清单过期」;core 光点自左滑右,抵达右端清单卡消失。 */ +const LifecycleTimeline: React.FC<{taskSysAt: number; axisAt: number; dotAt: number; quoteAt: number}> = ({ + taskSysAt, + axisAt, + dotAt, + quoteAt, +}) => { + const frame = useCurrentFrame(); + if (frame >= quoteAt) { + return ; + } + const taskSys = interpolate(frame - taskSysAt, [0, 16], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 时间轴描出 + const axis = interpolate(frame - axisAt, [0, 26], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // core 光点自左滑向右 + const dot = interpolate(frame - dotAt, [0, 50], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 抵达右端:清单卡彻底消失 + const listGone = interpolate(frame - dotAt, [42, 50], [1, 0], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + return ( + + {/* 任务系统预告:三个小图标一闪(「以后单拆」) */} +
+ {[ + {t: '带依赖', d: 'A→B'}, + {t: '能锁', d: '锁定'}, + {t: '落盘', d: '落盘'}, + ].map((x, i) => ( +
- {'清单背后那套更重的任务系统(带依赖·能锁·落盘)——以后单拆'} + {x.d} + {x.t}
- ) : null} + ))} +
+ {'—— 那套以后单拆'} +
+
+ {/* 生命周期时间轴 */} +
+ {/* 轴线 */} + + + {/* core 光点 */} + + {/* 右端箭头(axis 描满后出现) */} + {axis > 0.98 ? ( + + ) : null} + + {/* 左端:模型记不住 → 需要清单(清单卡小样) */} +
+
{'模型记不住'}
+
+ {'→ 需要清单'} +
+
+ +
+
+ {/* 右端:模型记住了 → 清单过期(清单卡随光点抵达而消失) */} +
+
{'模型记住了'}
+
+ {'→ 清单过期'} +
+
+
+ +
+
+
+ {/* 中段注记:装在循环外的能力 */} +
+ {'清单是装在循环外面的能力 —— 循环本身一行没动'} +
- - {'零件押的是「模型记不住」的赌注 —— 模型变强,赌注过期(官方文档口径)'} -
); }; @@ -387,15 +673,19 @@ export const P1Plan: React.FC<{scene: SceneRange}> = ({scene}) => { const at = (id: string) => w(id).from; const bA = w('p1-01', 'p1-03'); const relA = (id: string) => at(id) - bA.from; - const bB = w('p1-04', 'p1-09'); + const bB = w('p1-05', 'p1-09'); const relB = (id: string) => at(id) - bB.from; const bC = w('p1-10', 'p1-13'); const relC = (id: string) => at(id) - bC.from; - const bD = w('p1-14', 'p1-19'); + const bD = w('p1-14', 'p1-15'); const relD = (id: string) => at(id) - bD.from; + const bE = w('p1-15a', 'p1-15e'); + const relE = (id: string) => at(id) - bE.from; + const bF = w('p1-16', 'p1-19'); + const relF = (id: string) => at(id) - bF.from; return ( - + {/* 三态图标演示态跟随 p1-02(每条标一个状态)逐个闪现 */} @@ -409,11 +699,26 @@ export const P1Plan: React.FC<{scene: SceneRange}> = ({scene}) => { - {/* p1-14 官方公告;p1-15 收回钢印;p1-16 任务系统预告 */} - + + + {/* p1-15a 玻璃罩罩下;15b 计划卡落桌;15c 改文件撞罩弹回;15d 三选一;15e 金句卡 */} + + + + {/* p1-16 任务系统预告一闪;p1-18/19 金句;时间轴:模型记不住→需要清单 ↔ 模型记住了→清单过期 */} + diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx index 7a7b3ab2..fea98b44 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx @@ -857,7 +857,8 @@ export const P2SideDesk: React.FC<{scene: SceneRange}> = ({scene}) => { - + {/* p2-09 回执卡落定;p2-11 副桌纸堆淡出——「丢的只是纸」 */} + {/* p2-12 第一条纪律(无派活工具);p2-14 第二条(照样过闸) */} diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx index 6990275d..f8cbfa80 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx @@ -6,6 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; +import {QuoteCard} from '../components/cards'; import {Counter, Desk, Footnote, Panel, SceneHeader, SceneTag, Stamp} from '../components/motifs'; /** 3-A 左:桌角薄目录卡叠(每张一行 ~100);右:整块厚手册拍上桌(~2000+),桌面被压得下沉。 */ @@ -530,14 +531,31 @@ const ProbesVsKeywords: React.FC<{probeAt: number[]; crossAt: number; stampAt: n ); }; -/** 3-F ★静态/动态段落分层图:段落卡排成两层进缓存仓;外接工具段被拦在仓外闪断。 */ -const CacheShed: React.FC<{enterAt: number; blockAt: number; flickerAt: number; noteAt: number}> = ({ - enterAt, - blockAt, - flickerAt, - noteAt, -}) => { +/** 3-F ★深挖帧:先**官方削层**——整块垫纸剖面从满高削掉八成(p3-21,24 帧),旁边评测计分板 + * 数字纹丝不动并打勾,压字「删掉八成以上,评测不掉分 · 官方 2026-07」;p3-21a 金句短卡; + * 随后静态/动态段落分层图:段落卡排成两层进缓存仓(p3-22 起),外接工具段被拦在仓外闪断; + * p3-25 收束句浮现。 */ +const CacheShed: React.FC<{ + trimAt: number; + quoteAt: number; + enterAt: number; + blockAt: number; + flickerAt: number; + closeAt: number; +}> = ({trimAt, quoteAt, enterAt, blockAt, flickerAt, closeAt}) => { const frame = useCurrentFrame(); + // p3-21a 金句短卡(整拍切卡) + if (frame >= quoteAt && frame < enterAt) { + return ; + } + // 削层阶段(p3-20..p3-21a):剖面 + 计分板 + const trim = interpolate(frame - trimAt, [0, 24], [1, 0.2], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 被削掉的部分向上碎裂淡出 + const debris = frame > trimAt && frame < trimAt + 34; + const scoreOn = frame >= trimAt + 10; const layers = [ {t: '静态层', items: ['身份', '语气风格', '任务守则'], color: theme.view}, {t: '动态层', items: ['会话指引', '记忆', '环境信息'], color: theme.view}, @@ -546,9 +564,119 @@ const CacheShed: React.FC<{enterAt: number; blockAt: number; flickerAt: number; // 卡身闪断:模拟掉线(方波闪烁,确定性) const flicker = frame >= flickerAt ? (Math.floor((frame - flickerAt) / 6) % 2 === 0 ? 1 : 0.25) : 1; + // p3-25 收束句 + const close = interpolate(frame - closeAt, [0, 18], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 分层图阶段(p3-22 起) + const shedOn = frame >= enterAt; return ( -
+ {!shedOn ? ( +
+ {/* 整块垫纸剖面:height 由 100% 插值到 20%(24 帧) */} +
+
+ {'垫纸剖面(system prompt)'} +
+
+ {/* 保留段 */} +
+ {/* 被削掉的部分:向上碎裂淡出(三条碎块错帧上浮) */} + {debris + ? [0, 1, 2].map((k) => ( +
+ )) + : null} +
+ {/* 压字 */} +
+ {'删掉八成以上,评测不掉分'} +
+
+ {'官方 2026-07 · code.claude.com'} +
+ {/* p3-20 体量角标(三级归属:源码分析) */} +
+ {'常规两三万字 · 极简两行 —— 第三方的源码分析'} +
+
+ {/* 评测计分板:数字纹丝不动并打勾 */} +
+ +
{'评测计分板'}
+ {/* 数字纹丝不动:只呈现「不变」本身,不虚构具体分数 */} +
+
+ {'— . —'} +
+
{'= 削层前'}
+
+
+ {'删掉八成以上,分数纹丝不动'} +
+
+ {/* 打勾:削层完成后落下 */} + {scoreOn ? ( + + ) : null} +
+
+ ) : ( +
{/* 缓存仓:右侧一座两层仓 */}
- {/* 体量对比角标:两行 vs 两三万字 */} -
- {'极简模式:两行 · 常规模式:20–30KB —— 同一个人,两种铺法'} + {/* p3-25 收束句:这张垫纸拼得比谁都勤俭 */} + {close > 0 ? ( +
+ {'每轮都在拼,但拼得比谁都勤俭'} +
+ ) : null}
-
+ )} {'唯一不缓存的段落:外接工具段 —— 第三方的源码分析'} @@ -748,9 +880,17 @@ export const P3Manual: React.FC<{scene: SceneRange}> = ({scene}) => { stampAt={relE('p3-19')} /> - - {/* p3-20 两层体量;p3-22 唯一不缓存段被拦;p3-24 收束句;p3-25 角标 */} - + + {/* p3-20 体量角标;p3-21 官方削层(剖面 100%→20% + 计分板打勾);p3-21a 金句短卡; + p3-22 起段落入仓;p3-23 外接段拦 + 闪断;p3-25 收束句 */} + ); diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx index 13b58162..80a15266 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx @@ -1,13 +1,14 @@ /** P4 桌边的补救梯(分镜 4-A…4-E)—— Error Recovery * 三级梯垂下 → 话没说完(断截 + 8K→64K 标尺 + 续写×3)→ 桌上太满(压缩被拦) - * → 门外施工(等待条翻倍 0.5→32s 封顶 + 名牌翻面)→ 收益递减「停」章。 */ + * → 门外施工(等待条翻倍 0.5→32s 封顶 + 名牌翻面)→ 不重试的两类(分叉轨 + 分裂重放) + * → 收益递减「停」章。 */ import React from 'react'; import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoConfig} from 'remotion'; import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; import {QuoteCard} from '../components/cards'; -import {Chip, Desk, Footnote, Panel, SceneHeader, SceneTag, Stamp} from '../components/motifs'; +import {Chip, Counter, Desk, Footnote, Panel, SceneHeader, SceneTag, Stamp} from '../components/motifs'; /** 梯子骨架(mech):三级木梯挂在桌右缘,自上垂下挂稳(rope 微弹)。 */ const Ladder: React.FC<{drop: number; labels?: [string, string, string]}> = ({drop, labels}) => { @@ -318,18 +319,22 @@ const TierTwo: React.FC<{squashAt: number; blockAt: number; exitAt: number}> = ( }; /** 4-D 三级梯「门外施工」:警示牌砸落;等待条按节拍翻倍伸长(0.5→32s 封顶横杠); - * 三连 529 后模型名牌翻面换人。 */ -const TierThree: React.FC<{warnAt: number; waitAt: number; flipAt: number; jitterAt: number}> = ({ + * 一张「稍后再来」字条贴上并改写等待值(p4-14);三连 529 后模型名牌翻面换人。 */ +const TierThree: React.FC<{warnAt: number; waitAt: number; flipAt: number; jitterAt: number; noteAt: number}> = ({ warnAt, waitAt, flipAt, jitterAt, + noteAt, }) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); // 警示牌砸落抖动 const warn = spring({frame: frame - warnAt, fps: 30, config: {damping: 12}}); const warnShake = frame > warnAt + 6 && frame < warnAt + 24 ? Math.sin((frame - warnAt) / 1.3) * 4 : 0; + // 「稍后再来」字条飘落覆盖公式值(p4-14):贴上后等待值改听字条的 + const noteOn = frame >= noteAt; + const noteDrop = spring({frame: frame - noteAt, fps: 30, config: {damping: 12}}); // 等待条按节拍翻倍:0.5 → 1 → 2 → 4 → 8 → 16 → 32(封顶) const steps = [0.5, 1, 2, 4, 8, 16, 32]; const stepDur = 16; @@ -448,8 +453,31 @@ const TierThree: React.FC<{warnAt: number; waitAt: number; flipAt: number; jitte ) : null}
- {'再撒一点随机抖动,免得全世界的重试同一秒一起冲回来'} + {noteOn ? '对方留了「稍后再来」的字条 —— 就听字条的(等待值改写)' : '再撒一点随机抖动,免得全世界的重试同一秒一起冲回来'}
+ {/* 「稍后再来」字条:飘落贴上(p4-14),等待值改听字条的(不虚构具体秒数) */} + {noteOn ? ( +
+ {'稍后再来 →'} +
+ ) : null}
{/* 模型名牌:三连 529 后翻面换人 */}
@@ -545,6 +573,295 @@ const TierThree: React.FC<{warnAt: number; waitAt: number; flipAt: number; jitte ); }; +/** 4-D2 新镜「不重试的两类」:梯右岔出 deny 分叉轨(轨口牌「不重试」); + * 证书滑上轨第一帧就打红叉「去修它」;输出条断在半途 + 已发出的工具调用卡; + * ★工具卡原地分裂成两张各跑一遍、右下计数器 1→2「同一个动作跑了两遍」; + * 两卡收回合一贴「没写完」标签,core 光点从上一个已完成调用续向右; + * 右下刻度盘 0→10、外圈虚线刻到 15。 */ +const NoRetrySplit: React.FC<{ + forkAt: number; + certAt: number; + toolAt: number; + splitAt: number; + mergeAt: number; + dialAt: number; +}> = ({forkAt, certAt, toolAt, splitAt, mergeAt, dialAt}) => { + const frame = useCurrentFrame(); + // 分叉轨描线(26 帧) + const fork = interpolate(frame - forkAt, [0, 26], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 证书卡滑入 + 即打叉 + const cert = interpolate(frame - certAt, [0, 14], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const certX = frame >= certAt + 8; + // 输出条断口 ▌闪烁 + 工具卡同帧闪 deny + const tool = frame >= toolAt; + const flash = tool ? interpolate((frame - toolAt) % 30, [0, 8], [1, 0], {extrapolateRight: 'clamp'}) : 0; + // 分裂:scaleX 1→2 中缝裂开成两张、计数器滚动 + const splitT = interpolate(frame - splitAt, [0, 16], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const splitCount = Math.round(1 + splitT); + // 合一 + 标签 + 光点续接 + const merge = interpolate(frame - mergeAt, [0, 16], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + // 刻度盘:Counter 0→10(20 帧),外圈 dashed 到 15 + const dialOn = frame >= dialAt; + return ( + +
+ {/* 左侧:梯子缩略 + deny 分叉轨岔出 */} +
+ +
+ + {/* 分叉轨:从梯右缘岔出向右上(pathLength=1 归一化,dash 长度 0→满描出,完成后切虚线) */} + + {fork > 0.98 ? ( + + ) : null} + + {/* 轨口牌子「不重试」 */} +
+ {'不重试'} +
+ {/* 证书卡:滑上轨、第一帧就打红叉「去修它」 */} +
+ +
+ + + + + + +
+
{'证书对不上'}
+
{'TLS · 第一帧即报错'}
+
+
+ {/* 红叉:滑入即打 */} + {certX ? ( + + + + + + + ) : null} +
+ {certX ? ( +
+ {'那是要你去修的 —— 退避一百遍也一样'} +
+ ) : null} +
+ {/* 中央:输出文本条断在半途 + 已发出的工具调用卡 */} +
+ +
+ {'模型的回答(输出中)'} +
+
+ {'第一步统一文件名,第二步跑测试,第三步修好失败的'} + + {'▌'} + +
+
+
+ {/* ★工具卡:原地分裂成两张(scaleX 1→2 中缝裂开)→ 收回合一 + 「没写完」标签 */} +
+ {splitCount === 1 ? ( +
+
{'[bash] pytest -k perf'}
+
+ {'工具调用 · 已发出'} +
+
+ ) : ( +
+ {/* 分裂成两张:各跑一遍同样的动作 */} +
+ {[0, 1].map((k) => ( +
0.5 ? theme.panelBorder : theme.deny}`, + background: theme.panel, + opacity: splitT, + }} + > +
{'[bash] pytest -k perf'}
+
+ {merge > 0.5 ? '两卡收回合一' : `跑第 ${k + 1} 遍`} +
+
+ ))} +
+ {/* 压字:同一个动作跑了两遍 */} + {merge < 0.5 ? ( +
+ {'同一个动作跑了两遍'} +
+ ) : null} +
+ )} + {/* 合一后:贴「没写完」标签 + core 光点从上一个已完成调用续向右 */} + {merge > 0.5 ? ( +
+
+ {'没写完 —— 从断点接着来'} +
+ {/* core 光点续接:从上一个已完成调用处续向右 */} + + + + + {'上一个已完成调用'} + + + {'→ 续写'} + + +
+ ) : null} +
+ {/* 右下:计数器 1→2(分裂时滚动) */} +
+
{'动作计数'}
+
+ +
+
+ {/* 右下刻度盘:0→10,外圈虚线刻到 15 */} + {dialOn ? ( +
+
+ + {/* 外圈:dashed 刻到 15(10/15 弧长实线 + 余下虚线示意上限) */} + + + +
+
+ +
+
+ {'上限 15'} +
+
+
+
+ {'默认最多重试 10 次'} +
+ {'上限 15 次'} +
+
+ ) : null} +
+ {'不重试的两类:证书对不上(去修它)· 已发出动作(防跑两遍)—— 第三方的源码分析'} +
+ ); +}; + /** 4-E 收益递减:产出曲线三次爬升依次趋平;第三次的增量 < 阈值标线;「停」章落下; * p4-21a/b 官方检查点回退(只看文件改动)→ 金句「每一级补救都带着上限」(Harness Engineering 改造)。 */ const Diminishing: React.FC<{ @@ -670,7 +987,9 @@ export const P4Ladder: React.FC<{scene: SceneRange}> = ({scene}) => { const relC = (id: string) => at(id) - bC.from; const bD = w('p4-11', 'p4-17'); const relD = (id: string) => at(id) - bD.from; - const bE = w('p4-18', 'p4-22'); + const bD2 = w('p4-17a', 'p4-17f'); + const relD2 = (id: string) => at(id) - bD2.from; + const bE = w('p4-19', 'p4-22'); const relE = (id: string) => at(id) - bE.from; return ( @@ -693,14 +1012,26 @@ export const P4Ladder: React.FC<{scene: SceneRange}> = ({scene}) => { - {/* p4-11 警示牌;p4-13 等待翻倍;p4-15 抖动;p4-17 换人翻面 */} + {/* p4-11 警示牌;p4-12 等待翻倍;p4-13 抖动;p4-14 字条贴上;p4-17 换人翻面 */} + + {/* 17a 分叉轨;17b 证书打叉;17c 断口+工具卡闪 deny;17d 分裂成两卡;17e 合一+标签+光点;17f 刻度盘 */} + + {/* p4-19 递减检测;p4-20 停;p4-21a 检查点回退;p4-22 金句(每级都带上限) */} = ({devAt, sta ); }; -/** 5-B ★系列锚帧:环从桌后浮到画面中央(第二次出场,同色同宽同节点),桌子与五装置整体淡为线稿退后。 */ -const RingFloatsForward: React.FC<{floatAt: number; footnoteAt: number}> = ({floatAt, footnoteAt}) => { +/** 5-B ★系列锚帧:环从桌后浮到画面中央(第二次出场,同色同宽同节点),桌子与五装置整体淡为线稿退后。 + * p5-09 起:五条外挂虚线把五样装置逐条挂到环外(strokeDashoffset 逐条描出,stagger i×6 帧)。 */ +const RingFloatsForward: React.FC<{floatAt: number; hooksAt: number; footnoteAt: number}> = ({ + floatAt, + hooksAt, + footnoteAt, +}) => { const frame = useCurrentFrame(); const dot = useRingDot(2.5); // 环:从桌后(半透明、偏下)浮到中央(100% 亮度)——尺寸不变,位置与透明度变 @@ -193,16 +198,35 @@ const RingFloatsForward: React.FC<{floatAt: number; footnoteAt: number}> = ({flo const y = 700; const cx = 960; const cy = 540; + // 逐条描出(stagger i×6 帧,p5-09 起):先实线描出(dash 长度 0→满), + // 描满后切为虚线挂钩(pathLength=1 归一化,dashoffset 不参与) + const drawT = interpolate(frame - hooksAt - i * 6, [0, 18], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const d = `M${x} ${y} Q ${(x + cx) / 2} ${y + 60}, ${cx} ${cy}`; return ( - + + + {drawT > 0.98 ? ( + + ) : null} + ); })} @@ -271,7 +295,7 @@ export const P5Ring: React.FC<{scene: SceneRange}> = ({scene}) => { const at = (id: string) => w(id).from; const bA = w('p5-01', 'p5-06'); const relA = (id: string) => at(id) - bA.from; - const bB = w('p5-07', 'p5-12'); + const bB = w('p5-07', 'p5-09'); const relB = (id: string) => at(id) - bB.from; const bC = w('p5-13', 'p5-16'); const relC = (id: string) => at(id) - bC.from; @@ -292,8 +316,8 @@ export const P5Ring: React.FC<{scene: SceneRange}> = ({scene}) => { /> - {/* p5-09「全部挂在循环外面」起:环描线一遍 + 亮度升满;桌子线稿化 */} - + {/* p5-07 环起浮;p5-08 环描线一遍 + 亮度升满、桌子线稿化;p5-09 五条挂钩虚线逐条描出 */} + {/* p5-14 第一行;p5-15 第二行 */} diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P6Ending.tsx index d51785ca..b1b894a1 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P6Ending.tsx @@ -1,4 +1,6 @@ -/** P6 落点与信源(分镜 6-A…6-B) +/** P6 落点与信源(分镜 6-A…6-C,2026-08-28 改序:免责前置) + * 6-A 信源前置(p6-07..08)→ 6-B 一句话合同金句 + 人味延伸 + 赌注到期(p6-01..06) + * → 6-C 五格层进度条 + 0-C 标尺缩略 + 下期文案 + 渐黑(p6-09)。 * ★ 渐黑窗口从**末 beat 总时长**推导(beatDurationInFrames),不是末句时长 * —— 第三集上线教训:末句短于 beat 时渐黑提前收尾,导致收尾长黑屏 * (skills/06 渲染红线四)。 */ @@ -9,26 +11,79 @@ import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; import {Panel, SceneHeader} from '../components/motifs'; -/** 6-A 一句话合同金句卡(serif,view 描边)→ p6-04「同一门手艺」次行浮现。 */ -const ContractCard: React.FC<{nextAt: number}> = ({nextAt}) => { +/** 6-A 信源前置:信源卡两行压屏(官方文档+取数日期 / 第三方源码分析已逐处标注)。 + * 前置到幕首——免责只走画面,不占情绪高点(storyboard 改序说明)。 */ +const SourcesFirst: React.FC = () => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); const enter = spring({frame: frame - 4, fps, config: {damping: 200}}); - const next = interpolate(frame - nextAt, [0, 22], [0, 1], { + const rows = [ + ['官方文档', 'code.claude.com/docs · 取数2026年8月 · 以官方最新表述为准'], + ['源码分析', '第三方逆向分析 · 片中逐处标注'], + ]; + return ( + +
+ +
+ {'信源'} +
+ {rows.map(([k, v], i) => ( +
+
+ {k} +
+
{v}
+
+ ))} +
+
+
+ ); +}; + +/** 6-B 一句话合同金句卡(serif,view 描边)→ 三行人味延伸小字 → 赌注到期 + 自省句 +「循环没停过」收进底部。 */ +const ContractCard: React.FC<{humanAt: number; betAt: number; loopAt: number}> = ({ + humanAt, + betAt, + loopAt, +}) => { + const frame = useCurrentFrame(); + const {fps} = useVideoConfig(); + const enter = spring({frame: frame - 4, fps, config: {damping: 200}}); + const human = interpolate(frame - humanAt, [0, 20], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const bet = interpolate(frame - betAt, [0, 20], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const loop = interpolate(frame - loopAt, [0, 18], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); return (
- -
+ +
{'一句话合同'}
= ({nextAt}) => {
{'安排它的,不是模型自己。'}
-
- {/* 三行人味延伸小字 + 「同一门手艺」次行 */} -
-
- {'你的注意力在哪,多半也不是你自己定的——'} -
- {'是你桌上摆了什么、谁在什么时候塞了张纸给你。'} + {/* p6-02/03 人味延伸两行 */} +
+
+ {'你的注意力在哪,多半也不是你自己定的——'} +
+ {'是你桌上摆了什么、谁在什么时候塞了张纸给你。'} +
+
+ {/* p6-04/05 赌注到期 + 官方自省句短卡 */} +
+
+ {'清单退位'} +
+
+ {'官方自省:常问自己,可以停掉哪一件'} +
-
- {'管好自己的桌子和管好它的,是同一门手艺。'} + {/* p6-06「循环没停过」一行收进金句卡底部 */} +
+ {'桌子会换,零件会瘦,那个循环一直没停过。'}
-
+
); }; +/** 五格层进度条(执行/规划/记忆/时机/协作):反枚举——不用五色; + * 已播层 dim 常亮、当前层(本集=规划)core 高亮描边 + 底部指示条、未播层 panel 底 + 编号。 + * 6-C 上方压 0-C 四件套标尺定格缩略(「上下文管理」格保持半亮)。 */ +const LayerProgress: React.FC<{slideInAt: number}> = ({slideInAt}) => { + const frame = useCurrentFrame(); + const slide = interpolate(frame - slideInAt, [0, 18], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const LAYERS = ['执行', '规划', '记忆', '时机', '协作'] as const; + const CURRENT = 1; // 本集=规划层 + const FOUR_PIECES = ['循环', '工具', '上下文管理', '护栏'] as const; + return ( +
+ {/* 0-C 四件套标尺定格缩略:「上下文管理」格保持半亮(一帧完成「轮内四件套 / 轮外五层」映射) */} +
+ {FOUR_PIECES.map((p) => { + const hot = p === '上下文管理'; + return ( +
+ {p} +
+ ); + })} +
+ {/* 五格层进度条 */} +
+ {LAYERS.map((l, i) => { + const played = i < CURRENT; + const cur = i === CURRENT; + return ( +
+
+ + {String(i + 1).padStart(2, '0')} + + {l} +
+ {/* 当前层底部指示条 */} + {cur ? ( +
+ ) : ( +
+ )} +
+ ); + })} +
+
+ ); +}; + /** - * 6-B 信源卡(官方文档 + 取数日期 / 第三方源码分析 / 实测口径; - * 「产品内部均为第三方的源码分析」诚实行)→ 系列身份卡 → 渐黑。 - * `beatDurationInFrames` 是**本 beat 的总时长**,渐黑窗口据此反推。 + * 6-C 收束:五格层进度条 + 标尺缩略 + 身份卡 + 下期文案 + 渐黑。 + * `beatDurationInFrames` 是**本 beat 的总时长**,渐黑窗口据此反推(红线四)。 */ -const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> = ({ - beatDurationInFrames, - seriesAt, -}) => { +const FinalProgressAndFade: React.FC<{beatDurationInFrames: number}> = ({beatDurationInFrames}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); const enter = spring({frame: frame - 4, fps, config: {damping: 200}}); - const rows = [ - ['官方文档', 'code.claude.com/docs · 取数2026年8月'], - ['工程博客', 'anthropic.com/engineering'], - ['源码分析', '第三方逆向分析 · 片中逐处标注'], - ['数字口径', '开源仓库钉版 67a9126c 实测 · 字节归档'], - ]; - const seriesT = interpolate(frame - seriesAt, [0, 20], [0, 1], { - extrapolateLeft: 'clamp', - extrapolateRight: 'clamp', - }); + // 下期文案:打字机两拍。标题只在画面(反串线纪律),为 series.json 派生数据的 + // 硬编码镜像(下期=记忆层:会丢的和不能丢的);口播 p6-09 为话题描述不重复标题。 + const NEXT_LINE = '下期 · 记忆层:会丢的和不能丢的'; + const typed = Math.min(NEXT_LINE.length, Math.floor(frame / 3)); // 渐黑:末 1.2 秒线性压暗到全黑,窗口从 beat 总时长反推 const fadeFrames = Math.round(1.2 * fps); const fadeStart = beatDurationInFrames - fadeFrames; @@ -86,90 +248,32 @@ const SourceAndFade: React.FC<{beatDurationInFrames: number; seriesAt: number}> }); return ( -
- -
- {'信源'} -
- {rows.map(([k, v], i) => ( -
-
- {k} -
-
{v}
-
- ))} - {/* 诚实行:产品内部断言均为第三方的源码分析 */} -
- {'涉及产品内部的部分,均为第三方的源码分析,片中已逐处标注'} -
-
-
- {seriesT > 0 ? ( -
-
+
+ {/* 身份卡 */} +
+
{'Claude Code Harness Engineering'}
{'规划层:模型的视野是安排出来的'}
- {/* 下期预告卡:标题只在画面(反串线纪律) */} -
-
- {'下期 · 记忆层'} -
-
- {'会丢的和不能丢的'} -
-
- ) : null} + {/* 五格层进度条(当前层=规划) + 0-C 标尺缩略 */} + + {/* 下期文案:打字机两拍(反串线纪律:标题只进画面不进口播) */} +
+ {NEXT_LINE.slice(0, typed)} + {typed < NEXT_LINE.length ? {'▌'} : null} +
+
{/* 渐黑遮罩 */} @@ -180,19 +284,27 @@ export const P6Ending: React.FC<{scene: SceneRange}> = ({scene}) => { const w = (fromId: string, toId?: string) => beatWindow(scene.sentences, scene.from, fromId, toId); const at = (id: string) => w(id).from; const rel = (b: {from: number}, id: string) => at(id) - b.from; - const bA = w('p6-01', 'p6-04'); - const bB = w('p6-05', 'p6-09'); + const bA = w('p6-07', 'p6-08'); + const bB = w('p6-01', 'p6-06'); + const bC = w('p6-09', 'p6-09'); return ( - - {/* p6-04「同一门手艺」次行浮现 */} - + + {/* p6-07/p6-08 免责两句前置:信源卡逐行浮现(不占情绪高点) */} + + + + {/* p6-02/03 人味延伸;p6-04/05 赌注到期+自省句;p6-06「循环没停过」收进底部 */} + - - {/* 渐黑窗口从**本 beat 总时长**推导,不是末句时长(红线四); - 身份卡在末句 p6-09(下期见)浮现 */} - + + {/* 渐黑窗口从**本 beat 总时长**推导,不是末句时长(红线四) */} + ); From 7cf12de44f296b99aaa74b406d9e0ec3ce309ae5 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Fri, 28 Aug 2026 19:17:25 +0800 Subject: [PATCH 30/41] =?UTF-8?q?docs(video):=20B=20=E6=96=B9=E6=A1=88?= =?UTF-8?q?=E9=AA=8C=E8=AF=81=E8=AE=B0=E5=BD=95=E2=80=94=E2=80=94=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=96=AD=E8=A8=80=E8=AF=81=E6=8D=AE=E5=9B=9E=E6=BA=AF?= =?UTF-8?q?=EF=BC=882026-08-24=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) --- .../research/verification-2026-08-24.md | 5 ++++ .../research/verification-2026-08-24.md | 25 +++++++++++++++++++ .../research/verification-2026-08-24.md | 5 ++++ .../research/verification-2026-08-24.md | 5 ++++ .../research/verification-2026-08-24.md | 5 ++++ 5 files changed, 45 insertions(+) create mode 100644 apps/negentropy-influence/episodes/claude-code-concurrency-video/research/verification-2026-08-24.md create mode 100644 apps/negentropy-influence/episodes/claude-code-explained-video/research/verification-2026-08-24.md create mode 100644 apps/negentropy-influence/episodes/claude-code-memory-video/research/verification-2026-08-24.md create mode 100644 apps/negentropy-influence/episodes/claude-code-multiagent-video/research/verification-2026-08-24.md create mode 100644 apps/negentropy-influence/episodes/claude-code-planning-video/research/verification-2026-08-24.md diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/research/verification-2026-08-24.md b/apps/negentropy-influence/episodes/claude-code-concurrency-video/research/verification-2026-08-24.md new file mode 100644 index 00000000..c96c9ed6 --- /dev/null +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/research/verification-2026-08-24.md @@ -0,0 +1,5 @@ +# 阶段④ 双校验记录(B 方案品控改造 · 2026-08-24) + +新增断言均锚定【二】级官方口径(详见 storyboard 角标注明的信源与取数日期): +EP4 的关键新增见 series.json statusNote 与对应 storyboard 新镜(角标已带口径)。 +删除项均为复述/垫场句,语义由存活句或画面承载。收尾改序零文本改动,TTS 缓存保全。 diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/research/verification-2026-08-24.md b/apps/negentropy-influence/episodes/claude-code-explained-video/research/verification-2026-08-24.md new file mode 100644 index 00000000..f400d41e --- /dev/null +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/research/verification-2026-08-24.md @@ -0,0 +1,25 @@ +# 阶段④ 双校验记录(B 方案品控改造 · 2026-08-24) + +> 39 条双票 findings 落地后的新增断言校验。前版记录见 verification-2026-08-23.md。 + +## 新增断言回溯 + +| 口播句 | 断言 | 证据级 | 事实源 | 判定 | +|---|---|---|---|---| +| p0-03a..c | 同一模型换套脚手架,成绩 22%→49% | 【二】 | 官方 SWE-bench 脚手架实验(口径 2025-01-06 进角标) | ✅ VERIFIED | +| p0-06/p5-05 | 官方四件套:循环/工具/上下文管理/护栏 | 【二】 | claude.com/blog/harnessing-claudes-intelligence(全系列口径统一) | ✅ VERIFIED | +| p3-19a..d | OS 级沙箱:文件+网络双边界、权限提示 −84% | 【二】 | 官方工程博客(取数 2025-10 进角标);Seatbelt/bubblewrap 只进角标 | ✅ VERIFIED | +| p3-31a/b | 分类器成绩单:快筛误杀 8.5% → 复核后 0.4% | 【二】 | 官方 auto-mode 博客(2026-03 口径) | ✅ VERIFIED | +| p4-28a..c | 退出码契约:唯一硬信号阻断,惯用失败码不阻断 | 【二】 | 官方 hooks reference | ✅ VERIFIED | +| p1-12a/b | 「教学版」=开源最小实现(首现锚定) | 【三】 | 归属句「有人拆过它的源码」保留;不点名站点 | ✅ VERIFIED(合规) | + +## 删除项核对 + +- p1-07/p2-04/p3-13/p3-16..19/p3-27/p3-33/p4-20+21/p5-12+13/p6-03:全部为复述/咏叹/情绪垫场, + 语义由存活句或画面承载(分镜动效列已注明承载方式)。 +- 收尾改序(免责前置):句 id 与文本零改动,TTS 缓存全保。 + +## 口径切换记录 + +- 四件套第三件:全系列统一为「上下文管理」(EP4 p6-12 已同步)。 +- 「教学版」17 处全系列首次锚定(p1-12a),后续使用均有指代。 diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/research/verification-2026-08-24.md b/apps/negentropy-influence/episodes/claude-code-memory-video/research/verification-2026-08-24.md new file mode 100644 index 00000000..e3f46881 --- /dev/null +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/research/verification-2026-08-24.md @@ -0,0 +1,5 @@ +# 阶段④ 双校验记录(B 方案品控改造 · 2026-08-24) + +新增断言均锚定【二】级官方口径(详见 storyboard 角标注明的信源与取数日期): +EP3 的关键新增见 series.json statusNote 与对应 storyboard 新镜(角标已带口径)。 +删除项均为复述/垫场句,语义由存活句或画面承载。收尾改序零文本改动,TTS 缓存保全。 diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/research/verification-2026-08-24.md b/apps/negentropy-influence/episodes/claude-code-multiagent-video/research/verification-2026-08-24.md new file mode 100644 index 00000000..2d2c738d --- /dev/null +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/research/verification-2026-08-24.md @@ -0,0 +1,5 @@ +# 阶段④ 双校验记录(B 方案品控改造 · 2026-08-24) + +新增断言均锚定【二】级官方口径(详见 storyboard 角标注明的信源与取数日期): +EP5 的关键新增见 series.json statusNote 与对应 storyboard 新镜(角标已带口径)。 +删除项均为复述/垫场句,语义由存活句或画面承载。收尾改序零文本改动,TTS 缓存保全。 diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/research/verification-2026-08-24.md b/apps/negentropy-influence/episodes/claude-code-planning-video/research/verification-2026-08-24.md new file mode 100644 index 00000000..29e09901 --- /dev/null +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/research/verification-2026-08-24.md @@ -0,0 +1,5 @@ +# 阶段④ 双校验记录(B 方案品控改造 · 2026-08-24) + +新增断言均锚定【二】级官方口径(详见 storyboard 角标注明的信源与取数日期): +EP2 的关键新增见 series.json statusNote 与对应 storyboard 新镜(角标已带口径)。 +删除项均为复述/垫场句,语义由存活句或画面承载。收尾改序零文本改动,TTS 缓存保全。 From 5171baf1bf4108a198b99078c5546e6fb44e5344 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Fri, 28 Aug 2026 22:08:41 +0800 Subject: [PATCH 31/41] =?UTF-8?q?feat(video):=20B=20=E6=96=B9=E6=A1=88?= =?UTF-8?q?=E5=93=81=E6=8E=A7=E5=AE=8C=E6=88=90=E2=80=94=E2=80=94=E4=BA=94?= =?UTF-8?q?=E9=9B=86=E7=BB=88=E6=B8=B2=20v2=20=E4=BA=A4=E4=BB=98=EF=BC=88?= =?UTF-8?q?=E5=AF=B9=E6=8A=97=E5=BC=8F=E8=AF=84=E5=AE=A1=2039=20=E6=9D=A1?= =?UTF-8?q?=E5=8F=8C=E7=A5=A8=E9=A1=B9=E5=85=A8=E8=90=BD=E5=9C=B0=EF=BC=89?= =?UTF-8?q?;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 七维度评审(158 agents / 15.4M tokens)→ 39 条双票项执行 → 五集终渲: 内容升级(全部【二】级官方口径): - EP1:OS 级沙箱四句(文件+网络双边界、-84%)、分类器成绩单(8.5%→0.4%)、 退出码契约三句(exit 1 静默失效陷阱)、SWE-bench 脚手架赌注三句(22%→49%)、 「教学版」首现锚定、四件套口径全系列统一 - EP2:计划模式五句(只读探索→计划→批准前编辑全拦→三选一)、官方削层帧、 「不重试的两类」六句、四件套脊椎句、收尾免责前置 - EP3:开局装载清单、context rot 机制三句(n² 摊薄/预算固定/梯度非悬崖)、 「不是系统提示是 user message」纠错四句、第一定律回收三句 - EP4:矛盾句删除、四件套第三件口径统一、循环格落点 - EP5:官方战例八句(16 容器/锁文件认领/无领队/两千场会话/十万行/两万美元/ GCC 分治二分)、第一定律两句、预告递进修 视觉升级: - 8 条渲染 blocker 全修(Footnote 叠印 slot 根治、四闸压底座、症状卡穿环、 价目条叠印、死锚、None 占位符、34 秒死开屏、引文条错位) - 顶带闲置根治(SceneHeader 35 幕,ink 2–5×)、92% 采样静止根治(幕内进度条+游标) - 15 个新 Sequence(沙箱横切面/计划闸/战例镜/不重试形变帧/装载清单/rot 双轴等) 终渲 v2:14:06 / 13:27 / 13:35 / 13:09 / 13:25(合计 67.7 分钟 1080p30) 五集七幕+尾幕 FAIL 0 · WARN 0;18 个新视觉帧目检通过;单票项 18 条存档备选。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- CHANGELOG.md | 2 ++ .../video/src/scenes/P3Watchdog.tsx | 2 +- .../video/src/scenes/P2Mail.tsx | 13 ++++++++++++ .../video/src/scenes/P4Ladder.tsx | 2 +- apps/negentropy-influence/series.json | 20 +++++++++---------- 5 files changed, 27 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2416391b..4191b6cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ 本文件遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/) 约定,版本号遵循 [SemVer](https://semver.org/lang/zh-CN/)。 ## [Unreleased] +- **五集对抗式品控(B 方案)+ 终渲交付**:158 agents 七维度评审(硬核度/主线/充实度/体系/视觉/钩子/独特性,85 findings → 73 送双盲核验 → 57 存活/39 双票)→ 按 39 条双票项落地:**内容**(EP1 沙箱四句+成绩单+退出码契约+SWE-bench 赌注;EP2 计划闸五句+削层帧+不重试两类;EP3 装载清单+context rot 机制+user message 纠错+第一定律;EP4 口径统一+矛盾句删;EP5 官方编译器战例八句+第一定律回收——五集重配 ~140 句);**视觉**(8 条渲染 blocker 全修:Footnote 叠印 slot 根治、EP5 四闸压底座/症状卡穿环、EP3 价目条叠印、EP4 死锚/None 占位符、EP2 34 秒死开屏补三拍;顶带闲置根治:SceneHeader 35 幕全挂;92% 采样静止根治:幕内进度条+游标;15 个新 Sequence 落地)。终渲 v2:14:06/13:27/13:35/13:09/13:25(合计 67.7 分钟,1080p30,41.7–47.0 MB),五集七幕+尾幕 FAIL 0 · WARN 0,18 个新视觉帧目检通过。单票项 18 条存档 `.temp/review/deferred18.json` 备后续可选。 + - **五集草渲交付(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` 全零待合成)。 diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx index d4075a73..961ec817 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx @@ -228,7 +228,7 @@ const DogRises: React.FC<{ position: 'absolute', left: 0, right: 0, - bottom: 120, + bottom: 196, display: 'flex', justifyContent: 'center', gap: 26, diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx index 12b65a4b..ef68d0fa 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P2Mail.tsx @@ -227,6 +227,19 @@ const MailboxRow: React.FC<{sendAt: number; readAt: number}> = ({sendAt, readAt} lines={[ {text: 'report: 接口改完', at: sendAt + 20, struckAt: readAt}, {text: 'report: 文档写好', at: sendAt + 40, struckAt: readAt + 14}, + // readAt 后进入「读一条划一条」循环演示(p2-08..11 讲透明性/排查时使用): + // 帧驱动周期 34 帧一行,行进到划掉再落新行——消除 15 秒静止 + ...[ + 'report: 测试补齐', + 'assign: 复审接口', + 'ack: 收到', + 'report: 全绿', + 'assign: 收尾归档', + ].map((s, i) => ({ + text: s, + at: readAt + 30 + i * 46, + struckAt: readAt + 30 + i * 46 + 26, + })), ]} flashAt={readAt} /> diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx index 80a15266..d8d0dd85 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx @@ -947,7 +947,7 @@ const Diminishing: React.FC<{ style={{ position: 'absolute', left: '50%', - bottom: 150, + bottom: 216, transform: `translateX(-50%) translateY(${interpolate(frame - ckptAt, [0, 14], [16, 0], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', diff --git a/apps/negentropy-influence/series.json b/apps/negentropy-influence/series.json index ecd6405d..38345cec 100644 --- a/apps/negentropy-influence/series.json +++ b/apps/negentropy-influence/series.json @@ -101,8 +101,8 @@ "license": "MIT", "accessed": "2026-08-21" }, - "status": "draft-review", - "statusNote": "Harness Engineering 改造草渲待审:13:58 = 25151 帧 @30fps(167 句);七幕抽帧 FAIL 0 · WARN 0;高风险帧逐帧目检通过;终渲未启动", + "status": "delivered", + "statusNote": "终渲 v2 已交付(B 方案品控后):14:06 = 25393 帧 @30fps(167 句)· 46.9 MB;七幕+尾幕 FAIL 0 · WARN 0;沙箱镜/赌注卡/退出码三球镜目检通过", "voice": "sunny-steady + me-bright.wav" }, { @@ -123,8 +123,8 @@ "license": "MIT", "accessed": "2026-08-22" }, - "status": "draft-review", - "statusNote": "Harness Engineering 改造草渲待审:13:10 = 23706 帧 @30fps(135 句);七幕抽帧 FAIL 0 · WARN 0;终渲未启动", + "status": "delivered", + "statusNote": "终渲 v2 已交付(B 方案品控后):13:27 = 24214 帧 @30fps(139 句)· 42.6 MB;七幕+尾幕 FAIL 0 · WARN 0(检查点卡侵入已修)", "voice": "sunny-steady + me-bright.wav" }, { @@ -145,8 +145,8 @@ "license": "MIT", "accessed": "2026-08-22" }, - "status": "draft-review", - "statusNote": "Harness Engineering 改造草渲待审:13:07 = 23622 帧 @30fps(139 句);七幕 FAIL 0(WARN 3 均金句卡刻意静止);终渲未启动", + "status": "delivered", + "statusNote": "终渲 v2 已交付(B 方案品控后):13:35 = 24452 帧 @30fps(146 句)· 41.7 MB;七幕+尾幕 FAIL 0 · WARN 0", "voice": "sunny-steady + me-bright.wav" }, { @@ -167,8 +167,8 @@ "license": "MIT", "accessed": "2026-08-22" }, - "status": "draft-review", - "statusNote": "Harness Engineering 改造草渲待审:13:07 = 23621 帧 @30fps(139 句);七幕抽帧 FAIL 0 · WARN 0;终渲未启动", + "status": "delivered", + "statusNote": "终渲 v2 已交付(B 方案品控后):13:09 = 23672 帧 @30fps(139 句)· 44.7 MB;七幕+尾幕 FAIL 0 · WARN 0(两条看路侵入已修)", "voice": "sunny-steady + me-bright.wav" }, { @@ -189,8 +189,8 @@ "license": "MIT", "accessed": "2026-08-22" }, - "status": "draft-review", - "statusNote": "Harness Engineering 改造草渲待审:13:08 = 23666 帧 @30fps(134 句);七幕 FAIL 0 · WARN 0(尾帧 WARN 1 为收束卡刻意停留;口径为 08-23 草渲版)——08-24 评审修复 6-D resume 死门+分水岭压卡、2-E 补名册/对比卡两页,remotion still 逐帧复检通过;终渲未启动", + "status": "delivered", + "statusNote": "终渲 v2 已交付(B 方案品控后):13:25 = 24150 帧 @30fps(139 句)· 47.0 MB;七幕+尾幕 FAIL 0 · WARN 0(信箱循环演示已加)", "voice": "sunny-steady + me-bright.wav" } ] From 2a662b2484ff0686746be3cc335a91ce03a0a9fc Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Fri, 28 Aug 2026 23:42:23 +0800 Subject: [PATCH 32/41] =?UTF-8?q?feat(video):=20W7=20=E5=8F=99=E4=BA=8B?= =?UTF-8?q?=E5=8E=BB=E5=AF=B9=E7=85=A7=E5=8C=96=E2=80=94=E2=80=94=E3=80=8C?= =?UTF-8?q?=E6=95=99=E5=AD=A6=E7=89=88/=E7=9C=9F=E5=AE=9E=E4=BA=A7?= =?UTF-8?q?=E5=93=81=E3=80=8D=E4=B8=A4=E8=BD=A8=E6=94=B9=E4=B8=BA=E7=9B=B4?= =?UTF-8?q?=E9=99=88=E6=A1=86=E6=9E=B6=20+=20=E9=87=91=E5=8F=A5=E5=8D=A1?= =?UTF-8?q?=E5=8D=87=E7=BB=B4=E5=8E=BB=E9=87=8D;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户指令一:全篇不以「官方怎么样…教学怎么样…」对照式解说,改为 「Claude Code 的 Harness Engineering 是怎样的 → 简单示例如(教学内容作例子)→ 真实实现是(官方实践)」直陈框架。 - 口播 49 句改写(EP1 16 / EP2 10 / EP3 13 / EP5 10;EP4 经三 ref 五提交核验 原本零命中,agent 正确拒绝虚构改写):「教学版」→「最简实现/最简的做法」, 「真实产品里」→「实际实现里/它的实现里」,示例是讲解脚手架而非对立一极; 「官方」保留为权威信源主语但连续同主语处变换(官方文档/工程博客/战报/设计者)。 句 id 与句序零变动,字数收敛(4048/3950/4032/4003,全在 3900–4050)。 - 画面字符串 15 处同步(scenes + storyboard 角标)。 - 三级证据归属句全部保留。 用户指令二(视觉精修第一批):金句卡与字幕逐字重复 11/14 张 → 全部升维改写为 延伸句/英文原文/对比维度(如「Boring by design —— 内核越无聊,系统越可靠」), 保留视觉仪式感的同时消除同文复读;审计复跑 0 重复。 五集 tsc 零错误;check --check-scenes / check_series 全绿。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../script/narration.json | 32 +++++++-------- .../script/narration.md | 39 +++++++++++-------- .../script/storyboard.md | 2 +- .../video/src/scenes/P1Loop.tsx | 18 ++++----- .../video/src/scenes/P2Dispatch.tsx | 10 ++--- .../video/src/scenes/P3Gates.tsx | 6 +-- .../video/src/scenes/P4Hooks.tsx | 10 ++--- .../video/src/scenes/P5Stack.tsx | 2 +- .../script/narration.json | 26 ++++++------- .../script/narration.md | 26 ++++++------- .../script/storyboard.md | 2 +- .../video/src/scenes/P2Tidy.tsx | 2 +- .../video/src/scenes/P3Helper.tsx | 4 +- .../video/src/scenes/P4Ledger.tsx | 4 +- .../video/src/scenes/P5Hinge.tsx | 2 +- .../script/narration.json | 18 ++++----- .../script/narration.md | 20 +++++----- .../script/storyboard.md | 4 +- .../video/src/scenes/P3Handshake.tsx | 2 +- .../video/src/scenes/P4Autonomy.tsx | 2 +- .../video/src/scenes/P5Desks.tsx | 4 +- .../script/narration.json | 20 +++++----- .../script/narration.md | 20 +++++----- .../video/src/scenes/P1Plan.tsx | 8 ++-- .../video/src/scenes/P3Manual.tsx | 2 +- .../video/src/scenes/P4Ladder.tsx | 4 +- 26 files changed, 148 insertions(+), 141 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json index ef717f74..7a671bf4 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json @@ -17,7 +17,7 @@ { "id": "p0-03a", "scene": "P0", - "text": "这一层有多要紧?官方讲自己刷编程评测时写过一句话——" + "text": "这一层有多要紧?他们刷编程评测的战报里写过一句话——" }, { "id": "p0-03b", @@ -112,7 +112,7 @@ { "id": "p1-12b", "scene": "P1", - "text": "下面我一边读它,一边跟真实产品对照着看。" + "text": "下面拿它当例子,边读边说实际实现的做法。" }, { "id": "p1-13", @@ -142,7 +142,7 @@ { "id": "p1-18", "scene": "P1", - "text": "最直觉的写法是直接看它;但教学版改了," + "text": "最直觉的写法是直接看它;但最简实现改了," }, { "id": "p1-19", @@ -192,7 +192,7 @@ { "id": "p1-28", "scene": "P1", - "text": "教学版身上只带一份消息列表;真实产品带着十样," + "text": "最简实现身上只带一份消息列表;实际的 Harness 带着十样," }, { "id": "p1-29", @@ -282,7 +282,7 @@ { "id": "p2-15", "scene": "P2", - "text": "教学版老实排队,一个一个来;真实产品里能并行的就并行。" + "text": "最简的做法是老实排队,一个一个来;实际实现里能并行的就并行。" }, { "id": "p2-16", @@ -342,7 +342,7 @@ { "id": "p2-27", "scene": "P2", - "text": "他还提到,工具输出太长时产品不会全喂给模型,而是存成文件," + "text": "他还提到,工具输出太长时它不会全喂给模型,而是存成文件," }, { "id": "p2-28", @@ -422,7 +422,7 @@ { "id": "p3-14", "scene": "P3", - "text": "教学版自己承认:那张拒绝表只是字符串匹配,换个拼法就绕过去。" + "text": "最简实现自己承认:这张拒绝表只是字符串匹配,换个拼法就绕过去。" }, { "id": "p3-15", @@ -432,7 +432,7 @@ { "id": "p3-19a", "scene": "P3", - "text": "真正的边界在更底下一层:官方给跑命令那件工具,套了一层沙箱。" + "text": "真正的边界在更底下一层:它给跑命令那件工具,套了一层沙箱。" }, { "id": "p3-19b", @@ -447,7 +447,7 @@ { "id": "p3-19d", "scene": "P3", - "text": "官方内部用下来,权限提示少了八成四。" + "text": "官方工程博客给了数:内部用下来权限提示少八成四。" }, { "id": "p3-20", @@ -467,7 +467,7 @@ { "id": "p3-25", "scene": "P3", - "text": "规则求值的顺序官方也写死了:拒绝、询问、放行," + "text": "规则求值顺序官方文档也写死了:拒绝、询问、放行," }, { "id": "p3-26", @@ -582,7 +582,7 @@ { "id": "p4-13", "scene": "P4", - "text": "教学版留了四个插口,正好串成一整轮。" + "text": "最简实现留了四个插口,正好串成一整轮。" }, { "id": "p4-14", @@ -627,7 +627,7 @@ { "id": "p4-23", "scene": "P4", - "text": "真实产品里这样的时机,官方文档口径三十一个," + "text": "实际实现里这样的时机,官方文档口径三十一个," }, { "id": "p4-24", @@ -687,12 +687,12 @@ { "id": "p4-33", "scene": "P4", - "text": "教学版没有这一层,拆源码的人写下评语:" + "text": "这一层超出了最简实现的范围,拆源码的人评语是:" }, { "id": "p4-34", "scene": "P4", - "text": "教学里够用,生产环境就是一个安全漏洞。" + "text": "做示例够用,生产环境就是一个安全漏洞。" }, { "id": "p4-35", @@ -707,7 +707,7 @@ { "id": "p4-37", "scene": "P4", - "text": "产品里放了个标记,后面的轮次看到它就不再拦第二次。" + "text": "据他所说,它放了个标记,后面的轮次看到就不再拦。" }, { "id": "p5-01", @@ -822,7 +822,7 @@ { "id": "p6-07", "scene": "P6", - "text": "教学代码来自开源实现,行数均为实测,链接在简介。" + "text": "示例代码来自开源实现,行数均为实测,链接在简介。" }, { "id": "p6-05", diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md index d25700c5..dbe38a5b 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md @@ -10,6 +10,13 @@ > 各幕字数预算(2026-08-28 评审改造后重排):P0 280 · P1 790 · P2 760 · P3 725 · P4 890 · P5 405 · P6 180。 > P0 上浮吸收官方脚手架赌注三句,P4 上浮吸收退出码陷阱三句;P3 在补入沙箱四句与分类器成绩单两句的 > 同时净减 17 字(删掉六句咏叹与四处同义复述),全片净 +46 字。 +> +> **叙事框架(2026-08-28 改写)**:全篇不做「教学版 ↔ 真实产品」的两轨对照解说,改为单主语直陈—— +> 「这套 Harness 是怎样的 → 最简实现拿来当例子 → 而实际实现是怎样的」。示例是讲解的脚手架, +> 不是与产品对立的另一极:故「教学版」一律改「最简实现/最简的做法/示例」,「真实产品」一律改 +> 「实际实现/实际的 Harness/它」。同幕连续「官方」变换主语(官方文档 / 官方工程博客 / 他们) +> 以避复读感;三级证据归属句(「有人拆过它的源码」「据他所说」)不动。本轮 167 句不增删, +> 净 +23 字(4025 → 4048),16 句改写待重配音(TTS 缓存按文本哈希,其余 151 句命中缓存)。 ## P0 你在当那个中间人 @@ -19,7 +26,7 @@ - [p0-01] 你让 AI 跑个脚本:它把命令写好,然后就停在那儿了。 - [p0-02] 复制、粘贴、回车、再把输出贴回去——每一轮的搬运工,是你。 - [p0-03] 从「写出命令」到「真的跑起来」,缺的那一层,官方起了名字。 -- [p0-03a] 这一层有多要紧?官方讲自己刷编程评测时写过一句话—— +- [p0-03a] 这一层有多要紧?他们刷编程评测的战报里写过一句话—— - [p0-03b] 同一个底层模型,换一套脚手架,成绩能差出一大截。 - [p0-03c] 你花在这一层上的力气,直接变成它的分数。 - [p0-04] 名字就叫 Harness:把动力源,套进一个可控的结构里。 @@ -46,7 +53,7 @@ - [p1-11] 一个都没有就地返回,有就逐个执行、收好每条结果; - [p1-12] 最后把结果打包成新消息追加进去,回到第二步。写完了。 - [p1-12a] 说明一下:有人照着这套机制搭了一份开源的最小实现。 -- [p1-12b] 下面我一边读它,一边跟真实产品对照着看。 +- [p1-12b] 下面拿它当例子,边读边说实际实现的做法。 - [p1-13] 有人给它的评价是:三十多行,最小可运行的内核。 - [p1-14] 我自己数过这一版:光循环那个函数,去掉空行和注释,二十三行。 @@ -55,7 +62,7 @@ - [p1-15] 分工也说清楚了:模型决定要不要用工具、用哪一个, - [p1-16] 脚手架负责真的去跑、把结果搬回来——判断力在那边,手脚在这边。 - [p1-17] 模型回话时会附一个「我为什么停下来」的标记。 -- [p1-18] 最直觉的写法是直接看它;但教学版改了, +- [p1-18] 最直觉的写法是直接看它;但最简实现改了, - [p1-19] 改成翻开回答本身,看里面有没有工具调用。为什么? - [p1-20] 有人拆过它的源码,他给的理由是: - [p1-21] 回答是一个字一个字流出来的,工具调用早就流出来了, @@ -69,7 +76,7 @@ - [p1-25] 官方给这个循环画过像:三件事交融着转—— - [p1-26] 收集上下文、采取行动、验证结果,不是硬阶段。 - [p1-27] 而且你随时可以打断它、补一句、让它改道。 -- [p1-28] 教学版身上只带一份消息列表;真实产品带着十样, +- [p1-28] 最简实现身上只带一份消息列表;实际的 Harness 带着十样, - [p1-29] 压缩进度、补救次数、钩子拦没拦过停机、轮数——细节进角标。 - [p1-30] 循环没长个,长出来的是它随身带的状态。 - [p1-31] 退出的路子也有一大把:报错、中断、钩子叫停、预算烧完。 @@ -97,7 +104,7 @@ > 金句卡:「换掉的是执行那一步,传送带一寸没动。」 - [p2-14] 接着来了个新麻烦:模型经常一次要好几个工具。 -- [p2-15] 教学版老实排队,一个一个来;真实产品里能并行的就并行。 +- [p2-15] 最简的做法是老实排队,一个一个来;实际实现里能并行的就并行。 - [p2-16] 而它判断能不能并行的方式,是这一集我最想让你记住的一处。 - [p2-17] 直觉会说:只读的可以一起跑,要写的不行。 - [p2-18] 但按第三方的源码分析,这两件事其实不是一回事。 @@ -113,7 +120,7 @@ - [p2-25] 判断完了怎么排?按原来的顺序切段:连着能并行的划成一组一起跑, - [p2-26] 中间夹着不能并行的就单独一组;组内并行,组间严格按顺序。 -- [p2-27] 他还提到,工具输出太长时产品不会全喂给模型,而是存成文件, +- [p2-27] 他还提到,工具输出太长时它不会全喂给模型,而是存成文件, - [p2-28] 只给它一段预览和一个路径。 - [p2-29] 但「读文件」这件工具被特别开了口子:输出永远不许存成文件。 - [p2-30] 因为一旦存了,模型下次去读那个文件,输出又太长,又被存成文件。 @@ -135,22 +142,22 @@ - [p3-10] 第二道是规则匹配,管「看情况」的操作: - [p3-11] 读写工作目录之外的东西,或者命令里带着删除、改权限这类动作。 - [p3-12] 第三道就是问你:画面停下来,把工具名和参数摆给你看,等你点头。 -- [p3-14] 教学版自己承认:那张拒绝表只是字符串匹配,换个拼法就绕过去。 +- [p3-14] 最简实现自己承认:这张拒绝表只是字符串匹配,换个拼法就绕过去。 - [p3-15] 它告诉你闸门装在哪儿,不替你把门守住。 > 金句卡(serif):「它告诉你闸门装在哪儿,不是替你把门守住。」(与 p3-15 音画同句) -- [p3-19a] 真正的边界在更底下一层:官方给跑命令那件工具,套了一层沙箱。 +- [p3-19a] 真正的边界在更底下一层:它给跑命令那件工具,套了一层沙箱。 - [p3-19b] 能写哪些目录、能走哪个网络出口,由操作系统说了算。 - [p3-19c] 规则是劝,沙箱是锁——两道墙少一道,笼子就不成立。 -- [p3-19d] 官方内部用下来,权限提示少了八成四。 +- [p3-19d] 官方工程博客给了数:内部用下来权限提示少八成四。 > 角标:Seatbelt / bubblewrap + socat · 文件系统与网络双边界 · 权限提示 −84%(官方工程博客,取数 2025-10) - [p3-20] 回到闸门这边:有人拆过它的源码,判定结果是四种,不是三种。 - [p3-23] 多出来的第四种最有意思:工具选择不表态。 - [p3-24] 也就是说,弃权不等于放行,兜底永远是问你一句。 -- [p3-25] 规则求值的顺序官方也写死了:拒绝、询问、放行, +- [p3-25] 规则求值顺序官方文档也写死了:拒绝、询问、放行, - [p3-26] 头一个命中就出局——规则写得多具体,都改变不了顺序。 - [p3-28] 裸名拒绝更狠:整件工具从模型身上直接消失。 - [p3-29] 就算全放行模式,也压不住一条写死的拒绝。 @@ -185,7 +192,7 @@ - [p4-10] 循环到了某个时机只喊一声名字,至于该跑什么,由那张表说了算。 - [p4-11] 像墙上的插线口:循环是插座,功能是插头。 - [p4-12] 加功能是插一个插头,不是重新布线。 -- [p4-13] 教学版留了四个插口,正好串成一整轮。 +- [p4-13] 最简实现留了四个插口,正好串成一整轮。 - [p4-14] 第一个,你的话交出去、还没进模型之前:校验输入,或者补点背景。 - [p4-15] 第二个,工具要执行之前。刚才那三道闸门就搬到了这个插口上, - [p4-16] 循环从此不再认识任何一个检查函数。 @@ -197,7 +204,7 @@ > 金句卡(serif):「这个循环是故意保持无聊的。」 -- [p4-23] 真实产品里这样的时机,官方文档口径三十一个, +- [p4-23] 实际实现里这样的时机,官方文档口径三十一个, - [p4-24] 分三种节奏:会话一次、回合一次、每次调用前后。 - [p4-25] 处理器也不只是跑脚本,还能让小模型单轮判决。 - [p4-27] 表态的契约值得单独记:沉默,不等于批准—— @@ -209,15 +216,15 @@ - [p4-30] 它的放行,仍要穿过后面的拒绝与询问两站。 - [p4-31] 方向是单向的:扩展点能加限制,不能解除限制。 - [p4-32] 而且这条单向,官方画成过六道闸门的流水线。 -- [p4-33] 教学版没有这一层,拆源码的人写下评语: -- [p4-34] 教学里够用,生产环境就是一个安全漏洞。 +- [p4-33] 这一层超出了最简实现的范围,拆源码的人评语是: +- [p4-34] 做示例够用,生产环境就是一个安全漏洞。 > 金句卡(serif):「扩展点能加限制,不能解除限制。」 > 角标:hook `allow` 不能绕过 settings 的 deny/ask —— 第三方的源码分析 - [p4-35] 那个能说「别停」的插口本身很危险——它叫模型接着干, - [p4-36] 模型干完又要停,它又叫接着干,就转不出来了。 -- [p4-37] 产品里放了个标记,后面的轮次看到它就不再拦第二次。 +- [p4-37] 据他所说,它放了个标记,后面的轮次看到就不再拦。 ## P5 四层叠起来是什么 @@ -259,6 +266,6 @@ - [p6-02] 而是因为有人在它周围,搭了这几层结构。 - [p6-04] 这几层结构不神秘,加起来两百多行,一个下午能读完。 - [p6-06] 本片机制依据官方文档,取数2026年8月,以官方最新表述为准。 -- [p6-07] 教学代码来自开源实现,行数均为实测,链接在简介。 +- [p6-07] 示例代码来自开源实现,行数均为实测,链接在简介。 - [p6-05] 学会给 Harness 做加减法,这本身就是一门手艺。 - [p6-08] 下期一个反直觉的事实:它这一轮能看见什么,从来不是它自己说了算。 diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md index 520b9612..4111b0ff 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/storyboard.md @@ -26,7 +26,7 @@ |---|---|---|---| | 1-A | p1-01..06 | **环形循环**(全片视觉锚):`core` 色闭合轨道居中,轨道上四个节点「问模型 / 看回答 / 执行工具 / 填回结果」。右侧分出一支「停机」出口 | 轨道用 `interpolate` 描线成形(0→1,1.2s);一个 `core` 光点沿轨匀速巡游(周期 2.5s);讲到「有」时工具节点 `mech` 辉光脉冲一次并让光点继续,讲到「没有」时光点滑出到「停机」出口并**定格收镜**(原 p1-07 已删,语义收在这一格上) | | 1-B | p1-08..12 | 环形循环缩至左侧 40%,右侧展开五步编号列表 + 一个 `messages[]` 面板 | 五步逐句点亮(每句一条,`FadeUp` 12px);每点亮一步,`messages[]` 面板**长高一格**并压入一个色块(用户句=dim / 模型回答=core / 工具结果=mech);第五步点亮后一条弧线从列表尾弹回第二步 | -| 1-C | p1-12a..p1-16 | 全屏代码卡:`agent_loop` 的真实骨架(mono,约 12 行精简版),右下角计数「23」。卡眉挂一条**来源标签条**「开源最小实现 · 照着同一套机制搭的」 | p1-12a 标签条自卡眉滑入(`mech` 描边,无具名信息)→ p1-12b 右侧浮出「对照对象:真实产品」半亮列;代码逐行渲染(每行 3 帧);「二十三行」时行号列整体 `core` 辉光一次,计数器从 0 滚动到 23;p1-15/16 时画面左右分屏——左「模型:决定」右「脚手架:执行」,中间一条竖线 | +| 1-C | p1-12a..p1-16 | 全屏代码卡:`agent_loop` 的真实骨架(mono,约 12 行精简版),右下角计数「23」。卡眉挂一条**来源标签条**「开源最小实现 · 照着同一套机制搭的」 | p1-12a 标签条自卡眉滑入(`mech` 描边,无具名信息)→ p1-12b 右侧浮出「边读边说:实际实现」半亮列;代码逐行渲染(每行 3 帧);「二十三行」时行号列整体 `core` 辉光一次,计数器从 0 滚动到 23;p1-15/16 时画面左右分屏——左「模型:决定」右「脚手架:执行」,中间一条竖线 | | 1-D | p1-17..24 | 上半:模型回答的字符流从左向右逐字流出,其中一段 `mech` 色的「工具调用」块提前出现;下半:一个「停止原因」标记牌仍显示「进行中」,滞后一拍才翻牌 | 字符流以 12 字/秒流动;工具调用块出现时 `mech` 辉光;标记牌**延迟 25 帧**才翻转(视觉化「不可靠」);p1-22 时标记牌打上 `deny` 色斜叉;p1-24 金句卡 `serif` 居中淡入 | | 1-E | p1-25..29 | **三相环升级**:主环上浮现三个相位标签(收集 / 行动 / 验证)交融旋转;一只「手」图标随时可插入环上任意点;右侧十格抽屉墙以角标清单形式一闪 | 三个相位标签沿环依次点亮并**保持同时可见**(交融感,非硬阶段);p1-27 手图标落向环上一节点、环上光点被拨偏一档(人可打断);p1-28/29 十格抽屉墙快速亮起(20ms/格)后整体退至 40% 亮度、State 字段清单进角标 | | 1-F | p1-30..32 | 环形循环的「停机」出口分岔成五条细支线,各标一个退出原因;随后五条支线淡为 `dim`,只留主环 | 支线逐条以 `interpolate` 描线(每句一条);p1-32 时五条支线亮度降到 30% 并后移,主环 `core` 亮度不变——「它们是保护装置,不是骨架」 | diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx index 333ce300..37032646 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx @@ -1,4 +1,4 @@ -/** P1 一个循环,就是全部(分镜 1-A…1-F)—— 开源教学素材「Agent While-Loop」可视化的概念重建 +/** P1 一个循环,就是全部(分镜 1-A…1-F)—— 开源示教素材「Agent While-Loop」可视化的概念重建 * ★ 本幕建立全片视觉锚:LoopRing 的色与线宽从此不再改变。 */ import React from 'react'; import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoConfig} from 'remotion'; @@ -147,9 +147,9 @@ const FiveSteps: React.FC<{stepAt: number[]}> = ({stepAt}) => { ); }; -/** 1-C 二十三行代码卡 + 来源标签条 + 对照列 + 分工左右分屏。 +/** 1-C 二十三行代码卡 + 来源标签条 + 延伸列 + 分工左右分屏。 * p1-12a 卡眉滑入来源标签条(「开源最小实现 · 照着同一套机制搭的」,无具名信息—— - * 教学版锚,先交代这份代码是谁、再开始读);p1-12b 右侧浮出「对照对象:真实产品」 + * 示例锚,先交代这份代码是谁、再开始读);p1-12b 右侧浮出「边读边说:实际实现」 * 半亮列;随后代码逐行渲染 → 二十三行计数 → 左右分屏。 */ const TwentyThreeLines: React.FC<{ tagAt: number; @@ -222,7 +222,7 @@ const TwentyThreeLines: React.FC<{
- {/* 对照对象半亮列(p1-12b):读教学实现时,右边始终立着真实产品这一极 */} + {/* 延伸半亮列(p1-12b):读最简实现时,右边始终立着实际实现的落点 */} {compare > 0 ? (
- {'对照对象'} + {'边读边说'}
- {'真实产品'} + {'实际实现'}
@@ -309,7 +309,7 @@ const UnreliableFlag: React.FC<{crossAt: number; quoteAt: number}> = ({crossAt, }); if (frame >= quoteAt) { return ( - + ); } return ( @@ -378,7 +378,7 @@ const UnreliableFlag: React.FC<{crossAt: number; quoteAt: number}> = ({crossAt, ) : null}
- {'stop_reason is unreliable —— 第三方的源码分析 · 开源教学版仍按停止标记判定,官方实现已改为查内容块'} + {'stop_reason is unreliable —— 第三方的源码分析 · 开源最简实现仍按停止标记判定,官方实现已改为查内容块'} ); @@ -492,7 +492,7 @@ const ThreePhaseRing: React.FC<{phaseAt: number; handAt: number; drawersAt: numb }} >
- {'真实产品随身带的状态(十样)'} + {'实际实现随身带的状态(十样)'}
{[ diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx index 43247fab..8f505aa7 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx @@ -1,4 +1,4 @@ -/** P2 加一个工具,只改一行(分镜 2-A…2-H)—— 开源教学素材「Tool Dispatch Map」的概念重建 +/** P2 加一个工具,只改一行(分镜 2-A…2-H)—— 开源示教素材「Tool Dispatch Map」的概念重建 * 重点视觉演绎:并发安全 ≠ 只读(真值表对撞)、连续块分批、读文件落盘自循环。 */ import React from 'react'; import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoConfig} from 'remotion'; @@ -62,7 +62,7 @@ const FiveTools: React.FC = () => { const frame = useCurrentFrame(); const tools = ['跑命令', '读文件', '写文件', '改文件', '按模式找文件']; const mono = ['bash', 'read_file', 'write_file', 'edit_file', 'glob']; - // 官方五类工具地图(how-claude-code-works):教学五件归位官方分区,两个空槽亮虚线(Harness Engineering 改造) + // 官方五类工具地图(how-claude-code-works):示例五件归位官方分区,两个空槽亮虚线(Harness Engineering 改造) const zones = ['文件操作', '文件操作', '文件操作', '文件操作', '搜索']; return ( @@ -251,8 +251,8 @@ const QueueVsParallel: React.FC<{splitAt: number}> = ({splitAt}) => { ) : (
{[ - {t: '教学版:排队', par: false}, - {t: '真实产品:能并行的并行', par: true}, + {t: '最简示例:排队', par: false}, + {t: '实际实现:能并行的并行', par: true}, ].map((col) => (
@@ -295,7 +295,7 @@ const ConcurrencyTable: React.FC<{ if (frame >= quoteAt) { return ( ); diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx index dcaeb460..da7013d2 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx @@ -1,4 +1,4 @@ -/** P3 执行之前,先过闸门(分镜 3-A…3-G,含新镜 3-D2 沙箱横切面)—— 开源教学素材「Permission Desk」的概念重建 +/** P3 执行之前,先过闸门(分镜 3-A…3-G,含新镜 3-D2 沙箱横切面)—— 开源示教素材「Permission Desk」的概念重建 * 三种结果不各占一色:allow 回 core(放行=回主干)、ask 用 mech、deny 用 danger。 */ import React from 'react'; import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoConfig} from 'remotion'; @@ -216,7 +216,7 @@ const AskAndPass: React.FC<{askAt: number; passAt: number}> = ({askAt, passAt})
) : null} - {/* 三判定小抄(开源教学素材 Permission Desk 的信息结构):allow / ask / deny 各带真实载荷 —— + {/* 三判定小抄(开源示教素材 Permission Desk 的信息结构):allow / ask / deny 各带真实载荷 —— 本幕上方只演了 ask 与 allow,这里把第三条补齐,路由器的三种出口一目了然。 落位约束:小抄出现时(t2 > 0.4)闸门已整体上移 -150,GateRouter 的闸门名 (`y - h - 18`)落在 y≈235–258、闸柱顶到 y≈272——小抄必须整体收在其上方, @@ -318,7 +318,7 @@ const DenyListHonesty: React.FC<{degradeAt: number; bypassAt: number; quoteAt: n textAlign: 'center', }} > - {'教学示意,不是安全边界'} + {'示教示意,不是安全边界'}
) : null}
diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx index 94940741..b24b7995 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx @@ -1,4 +1,4 @@ -/** P4 挂在循环上,不写进循环里(分镜 4-A…4-H)—— 开源教学素材「Hook Workbench」的概念重建 +/** P4 挂在循环上,不写进循环里(分镜 4-A…4-H)—— 开源示教素材「Hook Workbench」的概念重建 * 4-E 刻意「无动效」表达「循环是故意保持无聊的」;4-G 是全片安全主题的收口。 */ import React from 'react'; import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoConfig} from 'remotion'; @@ -76,7 +76,7 @@ const NeedsPierce: React.FC<{needAt: number; pierceAt: number}> = ({needAt, pier const DegradedLoop: React.FC<{quoteAt: number}> = ({quoteAt}) => { const frame = useCurrentFrame(); if (frame >= quoteAt) { - return ; + return ; } const lines = [ 'def agent_loop(messages):', @@ -291,7 +291,7 @@ const BoringOnPurpose: React.FC<{hornsAt: number; quoteAt: number}> = ({hornsAt,
- + ); } @@ -524,7 +524,7 @@ const StampClash: React.FC<{ }> = ({pushAt, blockAt, arrowAt, gapAt, quoteAt}) => { const frame = useCurrentFrame(); if (frame >= quoteAt) { - return ; + return ; } const push = interpolate(frame - pushAt, [0, 18], [0, 1], { extrapolateLeft: 'clamp', @@ -643,7 +643,7 @@ const StampClash: React.FC<{ textAlign: 'center', }} > - {'教学版缺这一层 → 生产环境的安全漏洞'} + {'最简实现缺这一层 → 生产环境的安全漏洞'}
) : null}
diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P5Stack.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P5Stack.tsx index cd2edc6f..c4e2381a 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P5Stack.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P5Stack.tsx @@ -433,7 +433,7 @@ const SelfRunning: React.FC<{shellAt: number; quoteAt: number}> = ({shellAt, quo if (frame >= quoteAt) { return ( diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json index ea3d6dd6..6a7ea9e8 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json @@ -27,7 +27,7 @@ { "id": "p0-05b", "scene": "P0", - "text": "官方给过一份示意账:光基本设定,就占四千多字。" + "text": "官方文档给过一份示意账:光基本设定,就占四千多字。" }, { "id": "p0-06", @@ -37,7 +37,7 @@ { "id": "p0-09", "scene": "P0", - "text": "官方实测还补了一刀:窗口越长,它记得反而越不准。" + "text": "官方工程博客还补了一刀:窗口越长,它记得反而越不准。" }, { "id": "p0-09a", @@ -87,7 +87,7 @@ { "id": "p1-02", "scene": "P1", - "text": "第一层要办的,就是把丢管好——收拾这张桌子,教学版给出了四级办法。" + "text": "第一层要办的,就是把丢管好——收拾这张桌子,最简的做法分四级。" }, { "id": "p1-03", @@ -172,7 +172,7 @@ { "id": "p1-19", "scene": "P1", - "text": "教学版的四级,就是官方这两级的细化。便宜先来、贵的殿后,方向一致。" + "text": "最简的四级,就是文档这两级的细化。便宜先来、贵的殿后,方向一致。" }, { "id": "p1-20", @@ -287,7 +287,7 @@ { "id": "p2-22", "scene": "P2", - "text": "有人核对过源码,产品里真实顺序也是入库在前。一个看似平常的先后," + "text": "有人核对过源码,它的真实实现里也是入库在前。一个看似平常的先后," }, { "id": "p2-23", @@ -312,7 +312,7 @@ { "id": "p3-03", "scene": "P3", - "text": "有人把产品里给它的指令原文抄了出来,开头第一句就是:" + "text": "有人把真实实现里给它的指令原文抄了出来,开头第一句就是:" }, { "id": "p3-04", @@ -357,7 +357,7 @@ { "id": "p3-12", "scene": "P3", - "text": "而且压缩结束,官方口径也会把最近读过的文件捞回桌面," + "text": "而且压缩结束,同一张矩阵还写着:把最近读过的文件捞回桌面," }, { "id": "p3-13", @@ -367,12 +367,12 @@ { "id": "p3-14", "scene": "P3", - "text": "这一步教学版没做,是有人从源码里读出来的——所以口播到这里," + "text": "这一步超出了最简实现的范围,是有人从源码里读出来的——所以口播到这里," }, { "id": "p3-15", "scene": "P3", - "text": "你听到的每一个细节都带着同一句提醒:这是他的分析,不是产品的说明书。" + "text": "你听到的每一个细节都带着同一句提醒:这是他的分析,不是官方的说明书。" }, { "id": "p3-16", @@ -577,7 +577,7 @@ { "id": "p5-05", "scene": "P5", - "text": "有人拆过它的源码——产品里由一个「停机钩子」触发这件事:" + "text": "有人拆过它的源码——它的实现里由一个「停机钩子」触发这件事:" }, { "id": "p5-06", @@ -612,7 +612,7 @@ { "id": "p5-12", "scene": "P5", - "text": "有人分析过,产品里这个整理的活有个正式名字,起得很有画面感:做梦。" + "text": "有人分析过,它的实现里这个整理有个正式名字,起得很有画面感:做梦。" }, { "id": "p5-13", @@ -672,7 +672,7 @@ { "id": "p6-08", "scene": "P6", - "text": "涉及产品内部的部分,为第三方源码分析,片中已逐处标注。" + "text": "涉及内部实现的部分,为第三方源码分析,片中已逐处标注。" }, { "id": "p6-01", @@ -702,7 +702,7 @@ { "id": "p6-04b", "scene": "P6", - "text": "而赌注会过期。官方说过:新一代模型上,基本设定删了八成,评测没掉分。" + "text": "而赌注会过期。官方战报:新一代模型上,基本设定删了八成,评测没掉分。" }, { "id": "p6-04c", diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md index 99b63647..ee29d524 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md @@ -18,9 +18,9 @@ - [p0-04] 铁律是:读过的每个文件、跑过的每条命令、你说的每句话,全都随身带着—— - [p0-05] 每问一次模型,就从第一个字重新看一遍。窗口就这样一层层被垫高。 - [p0-05a] 而且开局就不空——你还没敲第一个字,窗口里已躺着好几样东西。 -- [p0-05b] 官方给过一份示意账:光基本设定,就占四千多字。 +- [p0-05b] 官方文档给过一份示意账:光基本设定,就占四千多字。 - [p0-06] 垫到顶,就是开头那行报错。 -- [p0-09] 官方实测还补了一刀:窗口越长,它记得反而越不准。 +- [p0-09] 官方工程博客还补了一刀:窗口越长,它记得反而越不准。 - [p0-09a] 原因不玄:每多一个字,要照顾的两两关系就多一圈。 - [p0-09b] 而注意力的总量是固定的——摊得越薄,看得越糊。 - [p0-09c] 所以窗口再大,也不等于记性变好——能装,不等于能记。 @@ -36,7 +36,7 @@ > 角标:50 条 / 头 3 尾 47 · 最近 3 条完整保留 · 120 字阈值 - [p1-01] 先把画面换个说法:它随身的全部对话,就是一张会塞满的桌子。 -- [p1-02] 第一层要办的,就是把丢管好——收拾这张桌子,教学版给出了四级办法。 +- [p1-02] 第一层要办的,就是把丢管好——收拾这张桌子,最简的做法分四级。 - [p1-03] 四级办法的原则只有一条:便宜的先来,贵的最后。 - [p1-04] 先干不用花钱的,实在不行才请人。你会看到这条原则贯穿到底。 - [p1-05] 第一级,裁中段。桌上的纸超过五十张,就只留开头三张和最近四十七张, @@ -53,7 +53,7 @@ - [p1-16] 注意折叠只动超过一百二十字的旧结果,短的就留着,不值得动它。 - [p1-17] 这两级全是纯文本操作,一次模型都不用请,便宜到近乎免费。 - [p1-18] 官方文档的原话正好背书这个次序:先清掉旧的工具输出,不够再把整段对话摘要。 -- [p1-19] 教学版的四级,就是官方这两级的细化。便宜先来、贵的殿后,方向一致。 +- [p1-19] 最简的四级,就是文档这两级的细化。便宜先来、贵的殿后,方向一致。 - [p1-20] 记住这个次序感:先动最不心疼的,再动开始心疼的。这是这一层的节拍。 ## P2 大件入库与顺序论证 @@ -83,7 +83,7 @@ - [p2-19] 你把空气存进了档案室。 - [p2-20] 我们在画面里把顺序对调一次给你看:折叠先行,大块头瞬间缩成一行, - [p2-21] 入库的手伸过去,抓到的只有那行字。整桌证据,就这么没了。 -- [p2-22] 有人核对过源码,产品里真实顺序也是入库在前。一个看似平常的先后, +- [p2-22] 有人核对过源码,它的真实实现里也是入库在前。一个看似平常的先后, - [p2-23] 背后是「先保存、再丢弃」的正确性论证。顺序,也是设计。 - [p2-24] 很多系统坏在这种地方:每一步都对,合起来的次序错了。 @@ -95,7 +95,7 @@ - [p3-01] 四级收拾里还有两个角色值得单独说说。 - [p3-02] 一个是写摘要这位帮工。它的纪律严得有点好笑。 -- [p3-03] 有人把产品里给它的指令原文抄了出来,开头第一句就是: +- [p3-03] 有人把真实实现里给它的指令原文抄了出来,开头第一句就是: - [p3-04] 这次只许写字,绝不许调用任何工具。结尾还要再叮嘱一遍。 - [p3-05] 为什么叮嘱两遍?请来收拾桌子的,手上偏偏有搬东西的能力。 - [p3-06] 真让它边收拾边调用工具,桌子越收越满,收拾就变成了新的堆积。 @@ -104,10 +104,10 @@ - [p3-09] 压缩之后谁活下来,官方给过一张矩阵—— - [p3-10] 系统提示绕行不变;规则和自动记忆从磁盘重新注入; - [p3-11] 用过的技能正文重注入,但每份封顶五千、最旧的先丢。 -- [p3-12] 而且压缩结束,官方口径也会把最近读过的文件捞回桌面, +- [p3-12] 而且压缩结束,同一张矩阵还写着:把最近读过的文件捞回桌面, - [p3-13] 最多五个、按重要性排队——丢,也是分层次的丢。 -- [p3-14] 这一步教学版没做,是有人从源码里读出来的——所以口播到这里, -- [p3-15] 你听到的每一个细节都带着同一句提醒:这是他的分析,不是产品的说明书。 +- [p3-14] 这一步超出了最简实现的范围,是有人从源码里读出来的——所以口播到这里, +- [p3-15] 你听到的每一个细节都带着同一句提醒:这是他的分析,不是官方的说明书。 - [p3-16] 到这里,第一层讲完了:会丢的东西,被管得相当讲究。 ## P4 不丢的那一层 @@ -162,14 +162,14 @@ - [p5-02] 写入登记簿这件事,发生在每一轮结束的时候——对话告一段落,活干完了。 - [p5-03] 关键在于取材的时机:提取器看的,是压缩之前的那份完整对话。 - [p5-04] 也就是说,那张「用 tab」的字条在被摘掉之前,就先被抄走了。 -- [p5-05] 有人拆过它的源码——产品里由一个「停机钩子」触发这件事: +- [p5-05] 有人拆过它的源码——它的实现里由一个「停机钩子」触发这件事: - [p5-06] 派出去的提取器权限受限、最多五回合、干完不进对话,闷头干完就走。 - [p5-07] 把时间线摆在一起看,就明白这个先后有多讲究。 - [p5-08] 轮末:先从完整对话里抢救出值得记的,一个字不差地写进本子; - [p5-09] 然后压缩才来,碎纸机开动,桌面上的细节开始褪色。 - [p5-10] 先抢救,再碎纸。本子里的那句话,从此再也不进碎纸机。 - [p5-11] 本子会越攒越厚,同一件事记了三遍、过时的没淘汰,就得整理。 -- [p5-12] 有人分析过,产品里这个整理的活有个正式名字,起得很有画面感:做梦。 +- [p5-12] 有人分析过,它的实现里这个整理有个正式名字,起得很有画面感:做梦。 - [p5-13] 这个梦有四道闸,一道不满足就不做。 - [p5-14] 距上次整理不满一天,不做——好记性不差这一天; - [p5-15] 扫描太频繁,不做——翻文件夹本身也有成本; @@ -186,13 +186,13 @@ > 画面:一句话合同金句卡 → 信源卡 → 系列身份卡 → 渐黑(末 beat 总时长推导)。 - [p6-07] 本片以官方文档为主,取数2026年8月,以官方最新表述为准。 -- [p6-08] 涉及产品内部的部分,为第三方源码分析,片中已逐处标注。 +- [p6-08] 涉及内部实现的部分,为第三方源码分析,片中已逐处标注。 - [p6-01] 会丢的放桌面,不许丢的放本子。 - [p6-02] 它不是记性好,是有两套东西在替它记。 - [p6-03] 一套负责体面地忘:分级收拾、先存再丢、压完往回捞; - [p6-04] 一套负责固执地记:一事一文件、索引常驻、先抢救再碎纸。 - [p6-04a] 再往前想一步:记忆这一层,押的赌注就是它记不住。 -- [p6-04b] 而赌注会过期。官方说过:新一代模型上,基本设定删了八成,评测没掉分。 +- [p6-04b] 而赌注会过期。官方战报:新一代模型上,基本设定删了八成,评测没掉分。 - [p6-04c] 手写的规则清单,正在让位给它自己长的记忆。 - [p6-05] 官方还有一句话值得放在最后:这两条腿,都是上下文,不是闸门。 - [p6-06] 记忆是建议,钩子才是规则——写提示词和做 Harness 的分水岭。 diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md index eff532c1..4e644eb4 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/storyboard.md @@ -31,7 +31,7 @@ | 2-A | p2-01..06 | 第三级大件入库:五个大文件结果块拍上桌;按个头排队飞进右侧文件柜,桌上留预览卡(前 2000 字 + 库标记) | 大块落下震桌;排队飞入柜(弧线);预览卡弹回落位 | | 2-B | p2-07..13 | 第四级全桌重写:整段对话先复印进「档案」抽屉(保底)→ 帮工登场把整桌纸重写成一张摘要卡 | 复印动画(纸堆翻白入柜);帮工(小个子 `mech`)把纸堆卷成一张卡;整桌纸淡出仅留摘要卡;p2-13 三次失败计数点亮满 → 熔断章(`deny`) | | 2-C | p2-14..15 | 应急通道:拒收后保最近五张原纸,更早的换摘要,重试一次 | 最近五张纸被 `keep` 框住不动,其余迅速摘要化;「重试 ×1」角标 | -| 2-D | p2-16..24 | ★顺序论证·自毁演示:正常序(入库→折叠)走一遍成功;对调序(折叠先行)时大块头先缩成一行、入库的手抓空——「把空气存进档案室」 | 双轨对照动画:上轨正常序(✓)、下轨对调序(✗);下轨抓空瞬间画面碎裂一帧再复位(错误顺序的代价可视化);角标「第三方核对源码:产品同序」 | +| 2-D | p2-16..24 | ★顺序论证·自毁演示:正常序(入库→折叠)走一遍成功;对调序(折叠先行)时大块头先缩成一行、入库的手抓空——「把空气存进档案室」 | 双轨对照动画:上轨正常序(✓)、下轨对调序(✗);下轨抓空瞬间画面碎裂一帧再复位(错误顺序的代价可视化);角标「第三方核对源码:真实实现同序」 | ## P3 应急通道与帮工纪律 diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P2Tidy.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P2Tidy.tsx index aa99e259..dd5dafc9 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P2Tidy.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P2Tidy.tsx @@ -628,7 +628,7 @@ const OrderMatters: React.FC<{normalAt: number; swapAt: number; grabAt: number; /> ))}
- {'第三方核对源码:产品真实顺序入库在前 —— 「先保存、再丢弃」'} + {'第三方核对源码:真实实现里顺序也是入库在前 —— 「先保存、再丢弃」'}
); }; diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx index 62348838..4d428602 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx @@ -177,7 +177,7 @@ const HelperDiscipline: React.FC<{firstAt: number; lastAt: number; handAt: numbe })}
- {'指令原文由第三方从产品里抄出(首尾各一遍)—— 第三方的源码分析'} + {'指令原文由第三方从真实实现里抄出(首尾各一遍)—— 第三方的源码分析'} ); @@ -404,7 +404,7 @@ const SalvageHook: React.FC<{openAt: number; hookAt: number; honestAt: number}> }), }} > - {'本段为第三方的源码分析(产品行为,教学版未做)'} + {'本段为第三方的源码分析(真实实现的行为,超出最简示例范围)'}
diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx index 58bfdf3a..0bcdd938 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx @@ -227,7 +227,7 @@ const TabToSummary: React.FC<{beamAt: number; rewriteAt: number; shredAt: number {'摘要没有做错什么——可有些细节,恰恰是主干'}
- {'例子出自开源教学仓库原文(README @ 67a9126c)'} + {'例子出自开源最简实现原文(README @ 67a9126c)'}
); }; @@ -990,7 +990,7 @@ const TwoPaths: React.FC<{ ) : null}
- {'产品用小号模型挑选 —— 第三方的源码分析'} + {'真实实现用小号模型挑选 —— 第三方的源码分析'}
); }; diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P5Hinge.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P5Hinge.tsx index 0de4d0e6..a46258ac 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P5Hinge.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P5Hinge.tsx @@ -613,7 +613,7 @@ const LockIsClock: React.FC<{faceAt: number; crashAt: number; spinAt: number; qu if (frame >= quoteAt) { return ( ); diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json index 2e6c8566..1c44a26a 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json @@ -327,7 +327,7 @@ { "id": "p3-12", "scene": "P3", - "text": "有人拆过它的源码——产品里的关机更讲究,是三向的:" + "text": "有人拆过它的源码——实际实现里的关机更讲究,是三向的:" }, { "id": "p3-13", @@ -347,7 +347,7 @@ { "id": "p3-16", "scene": "P3", - "text": "教学版只演了消息怎么走;产品的门禁是真的——批文没到,工具出不了手。" + "text": "最简实现只演了消息怎么走;它的门禁是真的——批文没到,工具出不了手。" }, { "id": "p4-01", @@ -397,17 +397,17 @@ { "id": "p4-10", "scene": "P4", - "text": "歇着也不是永远歇。教学版规矩六十秒:等不来新活,收工走人(教学设计)。" + "text": "歇着也不是永远歇。最简的做法定死六十秒:等不来新活,收工走人。" }, { "id": "p4-11", "scene": "P4", - "text": "产品里没有固定时限,队友一直活着,等领队来握手告别。" + "text": "有人读过源码:实际实现没有固定时限,队友一直活着,等领队握手告别。" }, { "id": "p4-12", "scene": "P4", - "text": "真实版歇着时还有个身份机关:对话被压得太短,就把「我是谁」重新插回去。" + "text": "再看最简实现:歇着时还有个身份机关——对话压太短就把「我是谁」插回去。" }, { "id": "p4-13", @@ -562,7 +562,7 @@ { "id": "p5-19", "scene": "P5", - "text": "它眼里的世界就是那张桌。任务与目录是否强制绑定,两版取舍在角标。" + "text": "它眼里的世界就是那张桌。任务与目录是否强制绑定,取舍见角标。" }, { "id": "p5-20", @@ -662,12 +662,12 @@ { "id": "p6-13", "scene": "P6", - "text": "官方泼的冷水也要听:并行和专精,必须挣回它们的协调成本——" + "text": "官方工程博客泼的冷水也要听:并行和专精,必须挣回协调成本——" }, { "id": "p6-14", "scene": "P6", - "text": "官方算过账,多智能体的花销,大约是普通对话的十五倍。" + "text": "他们算过账,多智能体的花销,大约是普通对话的十五倍。" }, { "id": "p6-15", @@ -682,7 +682,7 @@ { "id": "p6-16a", "scene": "P6", - "text": "最后一句官方的自省值得带走:常问自己,可以停掉哪一件。" + "text": "最后一句设计者的自省值得带走:常问自己,可以停掉哪一件。" }, { "id": "p6-16b", diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md index b1885dc8..a35b0390 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md @@ -99,17 +99,17 @@ - [p3-07] 还要三重对号——编号、类型、这事没办过,全过才销账。 - [p3-10] 同一套机制换个方向就是审批:队友要动高风险的东西,先交一份计划等批。 - [p3-11] 计划这头等回复,回复那头带编号回来,批了才动手。 -- [p3-12] 有人拆过它的源码——产品里的关机更讲究,是三向的: +- [p3-12] 有人拆过它的源码——实际实现里的关机更讲究,是三向的: - [p3-13] 请求、同意或拒绝——拒绝还能附理由——最后系统广播一声「人已离场」, - [p3-14] 顺带把它的窗格、任务、名册统统收拾干净。 - [p3-15] 所谓协议,没有玄机:一张状态表、一个编号、几条对得上号的规矩。 -- [p3-16] 教学版只演了消息怎么走;产品的门禁是真的——批文没到,工具出不了手。 +- [p3-16] 最简实现只演了消息怎么走;它的门禁是真的——批文没到,工具出不了手。 ## P4 自己看板,自己认领 > 画面:队友生命周期三段环(干活/歇着/走人);歇着态五秒心跳两看; > 60 秒表盘走满自动收工。 -> 角标:WORK→IDLE→SHUTDOWN · 信箱优先看板其次 · 60s 超时(教学版设计) +> 角标:WORK→IDLE→SHUTDOWN · 信箱优先看板其次 · 60s 超时(示教设计) - [p4-01] 到这里你可能会想:每次派活还要领队挨个分?十个任务分十次? - [p4-02] 它的作者们也这么想。所以队友学会了自己看板、自己认领。 @@ -120,9 +120,9 @@ - [p4-07] 认领前照例三查:是待办吗?有主人吗?依赖齐了吗?任何一条不过,不硬来。 - [p4-08] 这样领队只需要把任务挂上板,剩下的分发全自动。 - [p4-09] 两只队友同时抢一个活怎么办?主人这一格先到先得,后到者查一眼就走。 -- [p4-10] 歇着也不是永远歇。教学版规矩六十秒:等不来新活,收工走人(教学设计)。 -- [p4-11] 产品里没有固定时限,队友一直活着,等领队来握手告别。 -- [p4-12] 真实版歇着时还有个身份机关:对话被压得太短,就把「我是谁」重新插回去。 +- [p4-10] 歇着也不是永远歇。最简的做法定死六十秒:等不来新活,收工走人。 +- [p4-11] 有人读过源码:实际实现没有固定时限,队友一直活着,等领队握手告别。 +- [p4-12] 再看最简实现:歇着时还有个身份机关——对话压太短就把「我是谁」插回去。 - [p4-13] 干活得知道自己是谁。这句话对人对它都成立。 - [p4-14] 再看一眼自治的样子:领队只做两件事——挂任务上板,需要时发告别握手。 - [p4-15] 剩下的认领、开工、汇报、等待、再认领,全是队友自己的节奏。 @@ -160,7 +160,7 @@ - [p5-16] 建桌、拆桌、留桌,每次都记一行日志。谁何时动过哪张桌,翻账就知道。 - [p5-17] 一行日志看着轻,出了事它就是唯一的目击证人。 - [p5-18] 官方还交代了个细节:进出目录是整个进程跟着切——一旦进桌, -- [p5-19] 它眼里的世界就是那张桌。任务与目录是否强制绑定,两版取舍在角标。 +- [p5-19] 它眼里的世界就是那张桌。任务与目录是否强制绑定,取舍见角标。 - [p5-20] 顺带交代悬着的话:工具本身也可以是别人造的。行业标准的接插协议, - [p5-21] 外面的服务接上就变工具;名字自动带来源前缀,防的是两家重名。 - [p5-22] 装十个服务,上下文几乎不占——工具的定义按需取用,不整包塞进来。 @@ -187,10 +187,10 @@ - [p6-11c] 中断也不慌:重新拉起时,干完的直接命中,没干完的从头再跑—— - [p6-11d] 在第一个没干完的之后启动的,全部重跑。规矩清楚,不碰运气。 - [p6-12] 多出来的不是智慧,是把协作拆成了看得见的零件:板子、信箱、编号、桌子。 -- [p6-13] 官方泼的冷水也要听:并行和专精,必须挣回它们的协调成本—— -- [p6-14] 官方算过账,多智能体的花销,大约是普通对话的十五倍。 +- [p6-13] 官方工程博客泼的冷水也要听:并行和专精,必须挣回协调成本—— +- [p6-14] 他们算过账,多智能体的花销,大约是普通对话的十五倍。 - [p6-15] 本片机制依据官方文档,取数2026年8月,以官方最新表述为准。 - [p6-16] 涉及产品内部的部分,为第三方源码分析,片中已逐处标注。 -- [p6-16a] 最后一句官方的自省值得带走:常问自己,可以停掉哪一件。 +- [p6-16a] 最后一句设计者的自省值得带走:常问自己,可以停掉哪一件。 - [p6-16b] 每一样零件都押着一条「模型做不到」的赌注。模型变强,赌注就过期。 - [p6-17] 下期,再往上一层:怎么给这样的系统打分。分数会骗人,过程不会——下期见。 diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md index 428b7b05..fbc84857 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/storyboard.md @@ -40,7 +40,7 @@ | 3-A | p3-01..05 | 杀线程之祸:掐线程瞬间,写一半的文件断在半空(裂口);握手替代:领队发关机请求→队友收尾→回「同意」→自行退出 | 文件裂口闪烁(deny);四步走位动画:请求卡出发→队友卡收拾(文件补全)→回执→退出 | | 3-B | p3-06..07 | ★握手轨(HandshakeRail 母题):请求卡带编号(req_0042)滑出停在「等回话」位;状态表 pending 行亮起;应答卡带同号归来对号合拢锁扣「咔」;类型校验:一张错类型回执被弹开 | 请求/应答卡沿轨对开;编号铭牌双方一致时合拢+锁扣声效帧;错类型卡撞上弹开(deny) | | 3-C | p3-10..11 | 计划审批同构:队友交计划卡等批,批文带编号回来,批了才动手 | 同一握手轨复用(方向反转);「批了才动手」门闸开合 | -| 3-D | p3-12..16 | 【三】三向关机:请求→同意/拒绝(可附理由)→系统广播「已离场」+ 窗格/任务/名册自动收拾;教学版诚实句(只演消息走、产品门禁是真的)并句收尾 | 三向消息流;收拾动画(窗格收起、名册划名);角标「第三方的源码分析」;末句门禁小闸落下 | +| 3-D | p3-12..16 | 【三】三向关机:请求→同意/拒绝(可附理由)→系统广播「已离场」+ 窗格/任务/名册自动收拾;诚实句(最简实现只演消息走、它的门禁是真的)并句收尾 | 三向消息流;收拾动画(窗格收起、名册划名);角标「第三方的源码分析」;末句门禁小闸落下 | ## P4 自己看板,自己认领 @@ -48,7 +48,7 @@ |---|---|---|---| | 4-A | p4-01..03 | 派工之累:领队挨个发十次任务的重复动画(快速蒙太奇);三段生命周期环登场(干活/歇着/走人) | 分发卡×10 快闪;生命周期三段环描线 | | 4-B | p4-04..09 | 歇着态特写:每五秒心跳一次,看两眼——先信箱(有关机立刻收尾;有信先处理)后看板(三查后认领);两只队友抢活先到先得 | 心跳脉冲;视线先扫信箱再扫看板的路径高亮;认领时主人格写入+锁形闪光 | -| 4-C | p4-10..13 | 六十秒表盘走满自动收工(教学版标记);产品无固定时限;压缩后身份重注入(对话变短→「我是谁」卡插回) | 表盘快走满→收工礼花定格;对话堆坍缩成一小段→身份卡从顶部插回;角标「产品无固定时限(源码分析)」 | +| 4-C | p4-10..13 | 六十秒表盘走满自动收工(示教设计标记);实际实现无固定时限;压缩后身份重注入(对话变短→「我是谁」卡插回) | 表盘快走满→收工礼花定格;对话堆坍缩成一小段→身份卡从顶部插回;角标「实际实现无固定时限(源码分析)」 | | 4-D | p4-14..16 | 领队角色变化:包工头帽摘下换项目经理牌;两件事(挂任务/告别握手)图示 | 帽子换牌动画;两张卡钉在领队环旁 | | 4-E 官方战例:十六个它写编译器 | p4-17..24 | ★官方战报:4×4 容器网格(每格 peer 色小环+容器描边,反枚举:16 个不 16 色);锁文件卡 `current_tasks/xxx.txt` 飞入+「占坑」标签;「领队席:空」铭牌盖 deny 叉章;战果条滚动(16 · ≈2,000 会话 · ≈100K 行 · <$20K)+ 内核 boot 脉冲;deny 冻霜波纹从一格扩散冻结全部 16 格;文件块分流成两堆(大堆 mech 走「现成的编译器」、小堆 peer 走「它」)+ 二分箭头逐轮收敛 | p4-17 起容器逐格点亮(间隔约 4 帧);p4-18 锁文件写入闪光;p4-19 数字带逐项滚动+空席盖章;p4-20 boot 脉冲+账单停格;p4-22 冻霜级联;p4-23/24 分流动画收敛至两堆互不阻塞;角标「16 并行 · ~2,000 会话 · ~$20K · ~100K LOC · 官方工程博客 2026-02-05」 | diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx index 19567309..92771f5f 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx @@ -705,7 +705,7 @@ const ThreeWay: React.FC<{askAt: number; replyAt: number; castAt: number; settle ) : null}
- {'三向关机 · 拒绝可附理由——第三方的源码分析;教学版未做执行门控(诚实标注)'} + {'三向关机 · 拒绝可附理由——第三方的源码分析;最简示例未做执行门控(诚实标注)'}
); diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx index 60f4bc77..00f295b5 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx @@ -580,7 +580,7 @@ const SixtyClock: React.FC<{clockAt: number; doneAt: number; compactAt: number;
- {'六十秒收工为教学版设计;产品无固定时限(源码分析)'} + {'六十秒收工为示教设计;实际实现无固定时限(源码分析)'} ); }; diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx index e89709bd..cfacdf9b 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx @@ -752,10 +752,10 @@ const McpPlug: React.FC<{noteAt: number; plugAt: number; plateAt: number}> = ({ >
- {'产品里进出目录是整个进程跟着切;任务与目录也不强制绑定'} + {'实际实现里进出目录是整个进程跟着切;任务与目录也不强制绑定'}
- {'——第三方的源码分析(教学版做成默认绑定)'} + {'——第三方的源码分析(最简示例做成默认绑定)'}
diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json index 418398f2..1562ee5f 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json @@ -112,7 +112,7 @@ { "id": "p1-15", "scene": "P1", - "text": "官方理由很直白:这些模型自己就能记住要干什么。押注押到期了。" + "text": "理由说得很直白:这些模型自己就能记住要干什么。押注押到期了。" }, { "id": "p1-15a", @@ -122,7 +122,7 @@ { "id": "p1-15b", "scene": "P1", - "text": "官方叫它计划模式:先只读地探索,把计划写出来给你过目。" + "text": "这道门叫计划模式:先只读地探索,把计划写出来给你过目。" }, { "id": "p1-15c", @@ -207,7 +207,7 @@ { "id": "p2-12", "scene": "P2", - "text": "纪律第一条:教学版不许分身再派分身;官方放开了——最多三层,同时二十个。" + "text": "纪律第一条:最简实现不许分身再派分身;真实实现放开到三层,同时二十个。" }, { "id": "p2-14", @@ -222,12 +222,12 @@ { "id": "p2-16", "scene": "P2", - "text": "官方文档后来证实了真实产品里的那个反转," + "text": "官方文档后来证实了 Claude Code 里的那个反转," }, { "id": "p2-17", "scene": "P2", - "text": "是这一集最反直觉的地方:产品里有一种分叉模式,动机根本不是隔离," + "text": "是这一集最反直觉的地方:它内部有一种分叉模式,动机根本不是隔离," }, { "id": "p2-18", @@ -342,7 +342,7 @@ { "id": "p3-07", "scene": "P3", - "text": "教学版的讲法很直白:目录常驻,内容按需。" + "text": "最简的做法很直白:目录常驻,内容按需。" }, { "id": "p3-08", @@ -352,7 +352,7 @@ { "id": "p3-08b", "scene": "P3", - "text": "官方还给了句实在话:清单超过两百行,它就开始不老实读了。" + "text": "文档里还有句实在话:清单超过两百行,它就开始不老实读了。" }, { "id": "p3-09", @@ -377,7 +377,7 @@ { "id": "p3-13", "scene": "P3", - "text": "从第一行代码起,这张纸就是写死的。能力越加越多,纸越写越长。" + "text": "最简的做法是从第一行起就写死。能力越加越多,纸越写越长。" }, { "id": "p3-14", @@ -387,7 +387,7 @@ { "id": "p3-15", "scene": "P3", - "text": "真实的做法:把这张纸拆成几段——身份、工具清单、工作目录、相关记忆。" + "text": "而真实的实现是拆成几段——身份、工具清单、工作目录、相关记忆。" }, { "id": "p3-16", @@ -657,7 +657,7 @@ { "id": "p6-08", "scene": "P6", - "text": "涉及产品内部的部分,为第三方源码分析,片中已逐处标注。" + "text": "涉及内部实现的部分,为第三方源码分析,片中已逐处标注。" }, { "id": "p6-01", diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md index b680b88e..f03b8945 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md @@ -42,9 +42,9 @@ - [p1-12] 有位作者的句话说得很准:这个工具不增加任何执行能力, - [p1-13] 它增加的,是规划能力。 - [p1-14] 但这件装置刚刚被官方收了回去——新的模型上,清单工具默认不再安装。 -- [p1-15] 官方理由很直白:这些模型自己就能记住要干什么。押注押到期了。 +- [p1-15] 理由说得很直白:这些模型自己就能记住要干什么。押注押到期了。 - [p1-15a] 那规划这件事就没了吗?没有,它升级成了一道门。 -- [p1-15b] 官方叫它计划模式:先只读地探索,把计划写出来给你过目。 +- [p1-15b] 这道门叫计划模式:先只读地探索,把计划写出来给你过目。 - [p1-15c] 计划没批,改文件的动作一律拦住——想动手?先说服你。 - [p1-15d] 批准那一下你有三个选择:交给自动闸门、逐条人工点头、或者继续再想。 - [p1-15e] 清单是写给它自己看的;计划,是写给你看的。 @@ -67,11 +67,11 @@ - [p2-08] 分身在那边自己跑自己的循环,读文件、改代码,跟主桌互不打扰。 - [p2-09] 主桌上你看不到那三十个文件的任何一行,中间过程全丢,只带回一张回执。 - [p2-11] 注意丢的是什么:写过的文件、改过的代码都还在硬盘上——丢的只是纸,不是活。 -- [p2-12] 纪律第一条:教学版不许分身再派分身;官方放开了——最多三层,同时二十个。 +- [p2-12] 纪律第一条:最简实现不许分身再派分身;真实实现放开到三层,同时二十个。 - [p2-14] 第二条:分身每次动手之前,照样要过那几道闸门。 - [p2-15] 隔离的是视野,不是权限。它看不见你俩的对话,但它一样不能为所欲为。 -- [p2-16] 官方文档后来证实了真实产品里的那个反转, -- [p2-17] 是这一集最反直觉的地方:产品里有一种分叉模式,动机根本不是隔离, +- [p2-16] 官方文档后来证实了 Claude Code 里的那个反转, +- [p2-17] 是这一集最反直觉的地方:它内部有一种分叉模式,动机根本不是隔离, - [p2-18] 是为了省钱——命中缓存。 - [p2-19] 什么意思?对话按字数花钱;同样的开头算过一遍,短时间内第二遍近乎免费。 - [p2-20] 分身如果从头建立自己的桌面,前缀全变了,每一段都得原价重新算。 @@ -101,16 +101,16 @@ - [p3-04] 解法是两级:桌角常驻一叠目录卡,每张卡就一行:这份手册叫什么、管什么。 - [p3-05] 一张卡的价钱,大约是整本手册的二十分之一。桌角摆一排,也不心疼。 - [p3-06] 真要用到哪本,再把整本拉上桌——而且整场常驻,压缩后还会重注入。 -- [p3-07] 教学版的讲法很直白:目录常驻,内容按需。 +- [p3-07] 最简的做法很直白:目录常驻,内容按需。 - [p3-08] 官方口径:目录预算有硬顶。 -- [p3-08b] 官方还给了句实在话:清单超过两百行,它就开始不老实读了。 +- [p3-08b] 文档里还有句实在话:清单超过两百行,它就开始不老实读了。 - [p3-09] 这个硬顶大约是窗口的百分之一,还设了绝对上限,超了就砍。 - [p3-10] 还有个安全细节:取手册只认目录里登记过的名字,不走文件路径,防的就是目录穿越。 - [p3-11] 第四样东西,管的是桌面上那张最大的纸——它的基本设定本身。 - [p3-12] 你跟它说的每一句话之前,都垫着这么一张纸:你是谁、你在哪、能干什么。 -- [p3-13] 从第一行代码起,这张纸就是写死的。能力越加越多,纸越写越长。 +- [p3-13] 最简的做法是从第一行起就写死。能力越加越多,纸越写越长。 - [p3-14] 换个项目要重写整张纸,改一段可能跟别处打架,而且每轮都全文计费。 -- [p3-15] 真实的做法:把这张纸拆成几段——身份、工具清单、工作目录、相关记忆。 +- [p3-15] 而真实的实现是拆成几段——身份、工具清单、工作目录、相关记忆。 - [p3-16] 每一轮,按当场的真实状态重新拼一次。状态变了,纸跟着变。 - [p3-17] 关键在「真实状态」四个字:工具就查实际注册了哪些,记忆就查文件存不存在。 - [p3-18] 不去猜消息里出现了什么关键词。猜关键词,是给幻觉开门。 @@ -183,7 +183,7 @@ > 渐黑窗口从末 beat 总时长推导(红线四)。 - [p6-07] 本片机制依据官方文档,取数2026年8月,以官方最新表述为准。 -- [p6-08] 涉及产品内部的部分,为第三方源码分析,片中已逐处标注。 +- [p6-08] 涉及内部实现的部分,为第三方源码分析,片中已逐处标注。 - [p6-01] 视野是安排出来的。安排它的,不是模型自己。 - [p6-02] 这句话对人也成立:你的注意力在哪,多半也不是你自己定的, - [p6-03] 是你桌上摆了什么、谁在什么时候塞了张纸给你。 diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx index cf8c596b..68d048c6 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx @@ -272,13 +272,13 @@ const TwoLineDiff: React.FC<{quoteAt: number}> = ({quoteAt}) => { {'是规划能力。'}
- {'—— 教学版 README'} + {'—— 最简实现 README'}
) : ( - + )}
@@ -414,7 +414,7 @@ const PlanGate: React.FC<{ const frame = useCurrentFrame(); const {fps} = useVideoConfig(); if (frame >= quoteAt) { - return ; + return ; } // 玻璃罩自上罩下(spring) const glass = spring({frame: frame - glassAt, fps, config: {damping: 200}}); @@ -538,7 +538,7 @@ const LifecycleTimeline: React.FC<{taskSysAt: number; axisAt: number; dotAt: num }) => { const frame = useCurrentFrame(); if (frame >= quoteAt) { - return ; + return ; } const taskSys = interpolate(frame - taskSysAt, [0, 16], [0, 1], { extrapolateLeft: 'clamp', diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx index f8cbfa80..ff53b05c 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx @@ -546,7 +546,7 @@ const CacheShed: React.FC<{ const frame = useCurrentFrame(); // p3-21a 金句短卡(整拍切卡) if (frame >= quoteAt && frame < enterAt) { - return ; + return ; } // 削层阶段(p3-20..p3-21a):剖面 + 计分板 const trim = interpolate(frame - trimAt, [0, 24], [1, 0.2], { diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx index d8d0dd85..c2a6974f 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx @@ -567,7 +567,7 @@ const TierThree: React.FC<{warnAt: number; waitAt: number; flipAt: number; jitte
- {'恢复路径十几种(实测 17)· 教学版挑最常见的三种 —— 第三方的源码分析'} + {'恢复路径十几种(实测 17)· 最简实现挑最常见的三种 —— 第三方的源码分析'} ); @@ -873,7 +873,7 @@ const Diminishing: React.FC<{ }> = ({curveAt, lineAt, stopAt, ckptAt, quoteAt}) => { const frame = useCurrentFrame(); if (frame >= quoteAt) { - return ; + return ; } const W = 1100; const H = 460; From adf04de6abe93bfd79fa2d677152a71cb3d87684 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sat, 29 Aug 2026 01:25:46 +0800 Subject: [PATCH 33/41] =?UTF-8?q?feat(video):=20=E7=BB=88=E6=B8=B2=20v3=20?= =?UTF-8?q?=E4=BA=A4=E4=BB=98=E2=80=94=E2=80=94=E5=8F=99=E4=BA=8B=E5=8E=BB?= =?UTF-8?q?=E5=AF=B9=E7=85=A7=E5=8C=96=20+=20=E9=87=91=E5=8F=A5=E5=8D=A1?= =?UTF-8?q?=E5=8D=87=E7=BB=B4=20+=2049=20=E5=8F=A5=E9=87=8D=E9=85=8D;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 指令一落地:49 句「教学版/真实产品」两轨对照改为 「最简示例如(教学内容)→ 实际实现是(官方实践)」直陈框架, 全部重配(EP1 16 / EP2 10 / EP3 13 / EP5 10);画面字符串 15 处同步。 指令二落地:金句卡与字幕逐字重复 11/14 张 → 全部升维改写为延伸句/ 英文原文/对比维度(「Boring by design」等),目检确认金句与字幕内容 不同、无重叠;全片自动体检(560+ 采样帧:均匀 240 + Sequence 入场 314) 字幕带侵入/贴边裁切/糊块零命中。 终渲 v3:14:11 / 13:27 / 13:36 / 13:09 / 13:26(合计 67.8 分钟), 五集七幕 FAIL 0 · WARN 0。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- apps/negentropy-influence/series.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/negentropy-influence/series.json b/apps/negentropy-influence/series.json index 38345cec..a84a3f40 100644 --- a/apps/negentropy-influence/series.json +++ b/apps/negentropy-influence/series.json @@ -102,7 +102,7 @@ "accessed": "2026-08-21" }, "status": "delivered", - "statusNote": "终渲 v2 已交付(B 方案品控后):14:06 = 25393 帧 @30fps(167 句)· 46.9 MB;七幕+尾幕 FAIL 0 · WARN 0;沙箱镜/赌注卡/退出码三球镜目检通过", + "statusNote": "终渲 v3:14:11 = 25541 帧 @30fps(167 句)· 47.1 MB;叙事去对照化(16 句直陈框架)+ 金句卡升维;七幕 FAIL 0 · WARN 0", "voice": "sunny-steady + me-bright.wav" }, { @@ -124,7 +124,7 @@ "accessed": "2026-08-22" }, "status": "delivered", - "statusNote": "终渲 v2 已交付(B 方案品控后):13:27 = 24214 帧 @30fps(139 句)· 42.6 MB;七幕+尾幕 FAIL 0 · WARN 0(检查点卡侵入已修)", + "statusNote": "终渲 v3:13:27 = 24215 帧 @30fps(139 句)· 42.7 MB;叙事去对照化(10 句)+ 金句卡升维;七幕 FAIL 0 · WARN 0", "voice": "sunny-steady + me-bright.wav" }, { @@ -146,7 +146,7 @@ "accessed": "2026-08-22" }, "status": "delivered", - "statusNote": "终渲 v2 已交付(B 方案品控后):13:35 = 24452 帧 @30fps(146 句)· 41.7 MB;七幕+尾幕 FAIL 0 · WARN 0", + "statusNote": "终渲 v3:13:36 = 24492 帧 @30fps(146 句)· 41.7 MB;叙事去对照化(13 句);七幕 FAIL 0 · WARN 0", "voice": "sunny-steady + me-bright.wav" }, { @@ -168,7 +168,7 @@ "accessed": "2026-08-22" }, "status": "delivered", - "statusNote": "终渲 v2 已交付(B 方案品控后):13:09 = 23672 帧 @30fps(139 句)· 44.7 MB;七幕+尾幕 FAIL 0 · WARN 0(两条看路侵入已修)", + "statusNote": "终渲 v3:13:09 = 23672 帧 @30fps(139 句)· 44.7 MB;金句卡升维(无口播改动);七幕 FAIL 0 · WARN 0", "voice": "sunny-steady + me-bright.wav" }, { @@ -190,7 +190,7 @@ "accessed": "2026-08-22" }, "status": "delivered", - "statusNote": "终渲 v2 已交付(B 方案品控后):13:25 = 24150 帧 @30fps(139 句)· 47.0 MB;七幕+尾幕 FAIL 0 · WARN 0(信箱循环演示已加)", + "statusNote": "终渲 v3:13:26 = 24197 帧 @30fps(139 句)· 47.2 MB;叙事去对照化(10 句);七幕 FAIL 0 · WARN 0", "voice": "sunny-steady + me-bright.wav" } ] From 7eb0b52cd4a8d0e7e65cc3093bb30e5cc12ca448 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sat, 29 Aug 2026 09:26:32 +0800 Subject: [PATCH 34/41] =?UTF-8?q?fix(video):=20=E4=BF=AE=E5=A4=8D=20SceneH?= =?UTF-8?q?eader=20=C3=97=20SceneTag=20=E7=B3=BB=E7=BB=9F=E6=80=A7?= =?UTF-8?q?=E5=8F=A0=E5=8D=B0=E2=80=94=E2=80=9426=20=E5=9C=BA=E6=99=AF?= =?UTF-8?q?=E6=A0=B9=E5=9B=A0=E6=B8=85=E9=99=A4;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit W6 引入 SceneHeader(top:52 全宽)时未检查与既有 SceneTag(top:64)的互斥, 20+ 场景双挂载导致左上角两行文字(幕名 + 章节名)垂直区间重叠、挤压叠印 ——视觉模型实拍确认「两行文字距离过近、相互挤压,视觉观感不佳」。 这是用户连续两轮报告「图文重叠」的主要系统性来源。 修法:移除各场景内 SceneTag 挂载(26 处),章节信息(chapter · tagline) 并入 SceneHeader 的 meta 槽(单行呈现);21 处未用 import 同步清理。 渲染帧复验:左上角现为单行「P4 没人按的开始 · Cron Scheduler」,间距舒展。 五集 tsc 零错误。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../video/src/scenes/P0Wait.tsx | 5 ++--- .../video/src/scenes/P1Dereg.tsx | 3 +-- .../video/src/scenes/P2Rejoin.tsx | 3 +-- .../video/src/scenes/P3Watchdog.tsx | 3 +-- .../video/src/scenes/P4Timer.tsx | 3 +-- .../video/src/scenes/P5Truths.tsx | 3 +-- .../video/src/scenes/P6Ending.tsx | 5 ++--- .../claude-code-explained-video/video/src/scenes/P1Loop.tsx | 5 ++--- .../video/src/scenes/P2Dispatch.tsx | 5 ++--- .../claude-code-explained-video/video/src/scenes/P3Gates.tsx | 5 ++--- .../claude-code-explained-video/video/src/scenes/P4Hooks.tsx | 5 ++--- .../claude-code-memory-video/video/src/scenes/P1Desk.tsx | 5 ++--- .../claude-code-memory-video/video/src/scenes/P4Ledger.tsx | 5 ++--- .../claude-code-multiagent-video/video/src/scenes/P0Hook.tsx | 5 ++--- .../video/src/scenes/P1Board.tsx | 5 ++--- .../claude-code-multiagent-video/video/src/scenes/P2Mail.tsx | 5 ++--- .../video/src/scenes/P3Handshake.tsx | 5 ++--- .../video/src/scenes/P4Autonomy.tsx | 5 ++--- .../video/src/scenes/P5Desks.tsx | 5 ++--- .../video/src/scenes/P6Finale.tsx | 5 ++--- .../claude-code-planning-video/video/src/scenes/P0Hook.tsx | 5 ++--- .../claude-code-planning-video/video/src/scenes/P1Plan.tsx | 5 ++--- .../video/src/scenes/P2SideDesk.tsx | 5 ++--- .../claude-code-planning-video/video/src/scenes/P3Manual.tsx | 5 ++--- .../claude-code-planning-video/video/src/scenes/P4Ladder.tsx | 5 ++--- .../claude-code-planning-video/video/src/scenes/P5Ring.tsx | 5 ++--- 26 files changed, 47 insertions(+), 73 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx index 9fcb4f77..95697b3b 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, Panel, SceneHeader, SceneTag, Terminal} from '../components/motifs'; +import {Footnote, Panel, SceneHeader, Terminal} from '../components/motifs'; /** 计费表:表盘 + 一根按帧匀速狂转的秒针(转速恒快,与进度条形成反差) */ const MeterDial: React.FC<{spinFrom: number}> = ({spinFrom}) => { @@ -80,8 +80,7 @@ const StallBar: React.FC<{tickAt: number; costAt: number; zeroAt: number}> = ({t }); return ( - -
+
- - + diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx index e574ffbf..b0e7c179 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx @@ -31,8 +31,7 @@ const PairLock: React.FC<{lockAt: number; swapAt: number; queueAt: number}> = ({ const resultShift = queue * 260; return ( - - + {/* 调用卡(左) */} diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx index 961ec817..fe73cd55 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P3Watchdog.tsx @@ -122,8 +122,7 @@ const DogWatching: React.FC<{stopAt: number}> = ({stopAt}) => { const frame = useCurrentFrame(); return ( - -
+
diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx index c6adda17..d1b38d38 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P4Timer.tsx @@ -18,8 +18,7 @@ const PuppetVsClock: React.FC<{clockAt: number}> = ({clockAt}) => { const clockOn = frame >= clockAt; return ( - -
+
{/* 左:提线木偶 */}
diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx index bea8e8c0..693b48f3 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx @@ -49,8 +49,7 @@ const Stampede: React.FC<{fireAt: number; crashAt: number}> = ({fireAt, crashAt} const jit = (i: number) => Math.sin((frame / 3.1) + i * 2.4) * 7 * crash; return ( - - + {/* 一排表:全部指 9:00(时针 270°、分针 270°) */} {Array.from({length: N}, (_, i) => ( diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx index cf62adf8..ee245a65 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx @@ -9,7 +9,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, LoopRing, Panel, SceneHeader, SceneTag, useRingDot} from '../components/motifs'; +import {Footnote, LoopRing, Panel, SceneHeader, useRingDot} from '../components/motifs'; /** 三段位置图的一段:人(或表)与环的位置关系——「谁按的开始」用位置编码 */ const StartPanel: React.FC<{ @@ -123,8 +123,7 @@ const ThreePositions: React.FC<{l1: number; l2: number; l3: number; layerAt: num }); return ( - -
+
= l1} />
diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx index 37032646..a92e3e62 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx @@ -6,7 +6,7 @@ import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; import {QuoteCard} from '../components/cards'; -import {CodeCard, Counter, Footnote, LoopRing, Panel, SceneHeader, SceneTag, useRingDot} from '../components/motifs'; +import {CodeCard, Counter, Footnote, LoopRing, Panel, SceneHeader, useRingDot} from '../components/motifs'; /** 1-A 环形循环成形 + 两个信号分支(原 p1-07 已删:「传送带转不转」的语义收在 p1-06 的定格收镜上) */ const RingBirth: React.FC<{yesAt: number; noAt: number}> = ({yesAt, noAt}) => { @@ -24,8 +24,7 @@ const RingBirth: React.FC<{yesAt: number; noAt: number}> = ({yesAt, noAt}) => { const active = frame >= yesAt && frame < noAt ? 2 : undefined; return ( - - 0.98 ? dot : undefined} activeNode={active} exitPull={pull} /> + 0.98 ? dot : undefined} activeNode={active} exitPull={pull} /> {'有 tool_use → 继续 · 没有 → 退出'} diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx index 8f505aa7..9e6de8a2 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx @@ -6,7 +6,7 @@ import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; import {QuoteCard} from '../components/cards'; -import {CodeCard, DispatchTable, Footnote, LoopRing, NumberedCard, Panel, SceneHeader, SceneTag, Terminal, useRingDot} from '../components/motifs'; +import {CodeCard, DispatchTable, Footnote, LoopRing, NumberedCard, Panel, SceneHeader, Terminal, useRingDot} from '../components/motifs'; /** 环留在左上角:缩小但同色同线宽 */ const CornerRing: React.FC<{pulse?: boolean}> = ({pulse = false}) => { @@ -27,8 +27,7 @@ const ClumsyCommands: React.FC<{typoAt: number}> = ({typoAt}) => { const shake = bad ? Math.sin((frame - typoAt) / 1.6) * 3 : 0; return ( - - +
{'模型想的是'}
diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx index da7013d2..db08cf25 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx @@ -6,7 +6,7 @@ import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; import {QuoteCard} from '../components/cards'; -import {CodeCard, Footnote, GateRouter, LoopRing, NumberedCard, Panel, SceneHeader, SceneTag, useRingDot} from '../components/motifs'; +import {CodeCard, Footnote, GateRouter, LoopRing, NumberedCard, Panel, SceneHeader, useRingDot} from '../components/motifs'; /** 3-A 五张工具卡,跑命令那张在「工作目录」框外 */ const UnguardedShell: React.FC<{frameAt: number; cmdAt: number; execAt: number}> = ({ @@ -25,8 +25,7 @@ const UnguardedShell: React.FC<{frameAt: number; cmdAt: number; execAt: number}> const dim = showCmd ? 0.55 : 1; return ( - -
+
{/* 工作目录框:把四张 file tool 收进去 */}
= ({needAt, pier }); return ( - -
+
{pierce > 0.4 ? (
= ({ruleAt}) => { @@ -16,8 +16,7 @@ const DeskIntro: React.FC<{ruleAt: number}> = ({ruleAt}) => { const drop = spring({frame: frame - ruleAt, fps, config: {damping: 13}}); return ( - -
+
{Array.from({length: 26}).map((_, i) => ( diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx index 0bcdd938..8c6f07bf 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx @@ -9,7 +9,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Desk, Footnote, Ledger, PaperCard, SceneHeader, SceneTag} from '../components/motifs'; +import {Desk, Footnote, Ledger, PaperCard, SceneHeader} from '../components/motifs'; /** 4-A 全景回望:已讲机制小图标环绕桌面;桌面整体轻微褪色一次 */ const AllOnDesk: React.FC<{fadeAt: number}> = ({fadeAt}) => { @@ -482,8 +482,7 @@ const LedgerArrives: React.FC<{bookAt: number; fmAt: number[]; indexAt: number; const dup = spring({frame: frame - dupAt, fps, config: {damping: 13}}); return ( - -
+
{/* 登记簿:keep 实体 */}
= ({zoomAt, cardsAt}) => { @@ -447,8 +447,7 @@ export const P0Hook: React.FC<{scene: SceneRange}> = ({scene}) => { - - {/* 拉镜点在 p0-03;cardsAt:官方三失败模式症状卡(Harness Engineering 改造)。 + {/* 拉镜点在 p0-03;cardsAt:官方三失败模式症状卡(Harness Engineering 改造)。 三个名字的列举已拆到 p0-03a(B 方案改稿),卡片跟着列举句走 */} diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx index 6e9b30ca..0f675ce4 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P1Board.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, Panel, SceneHeader, SceneTag, phase, qBezier} from '../components/motifs'; +import {Footnote, Panel, SceneHeader, phase, qBezier} from '../components/motifs'; /** 任务卡:五格(编号/标题/状态/主人/等谁);TaskBoard 的成员单元 */ const TaskCard: React.FC<{ @@ -113,8 +113,7 @@ const BoardRises: React.FC<{cardsAt: number; arrowsAt: number}> = ({cardsAt, arr ]; return ( - -
+
{/* 看板框架描线(pathLength 归一化,红线三) */} = ({fadeAt, seatAt}) => { @@ -16,8 +16,7 @@ const TempVsTeammate: React.FC<{fadeAt: number; seatAt: number}> = ({fadeAt, sea const seat = phase(frame, seatAt, 16); return ( - -
+
{/* 左:临时工剪影(干完即走)——淡出 */}
diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx index 92771f5f..e0bf69a9 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, LoopRing, NamePlate, Panel, SceneHeader, SceneTag, phase, useRingDot} from '../components/motifs'; +import {Footnote, LoopRing, NamePlate, Panel, SceneHeader, phase, useRingDot} from '../components/motifs'; /** 握手轨:横向轨道 + 请求卡 / 应答卡对开。双方端点 + 中央「等回话」位。 */ const HandshakeRail: React.FC<{ @@ -259,8 +259,7 @@ const KillVsHandshake: React.FC<{crackAt: number; stepsAt: number}> = ({crackAt, const cur = steps ? Math.min(3, Math.floor((frame - stepsAt) / 18)) : -1; return ( - - {!steps ? ( + {!steps ? (
{/* 掐线程的手:从上方掐住虚线线程 */}
diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx index 00f295b5..c0369bb4 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx @@ -7,7 +7,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, LoopRing, NamePlate, Panel, SceneHeader, SceneTag, phase} from '../components/motifs'; +import {Footnote, LoopRing, NamePlate, Panel, SceneHeader, phase} from '../components/motifs'; /** 4-A 派工之累 ×10 快闪 → 三段生命周期环描线登场 */ const DispatchFatigue: React.FC<{cycleAt: number}> = ({cycleAt}) => { @@ -32,8 +32,7 @@ const DispatchFatigue: React.FC<{cycleAt: number}> = ({cycleAt}) => { }; return ( - - {!showCycle ? ( + {!showCycle ? (
{/* 领队(左):一张张派 */}
diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx index cfacdf9b..85bb367e 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, LoopRing, NamePlate, Panel, SceneHeader, SceneTag, phase} from '../components/motifs'; +import {Footnote, LoopRing, NamePlate, Panel, SceneHeader, phase} from '../components/motifs'; /** 5-A 阿珍阿强双写冲突:同名 config.py 互覆碎裂 + 回滚死结 */ const Collision: React.FC<{writeAt: number; crushAt: number; knotAt: number}> = ({ @@ -25,8 +25,7 @@ const Collision: React.FC<{writeAt: number; crushAt: number; knotAt: number}> = const knot = phase(frame, knotAt, 18); return ( - -
+
{/* 同一目录面板(中上) */}
= ({beltAt}) => { }); return ( - - {/* 四小图标(顶部一排) */} + {/* 四小图标(顶部一排) */}
{four.map((f, i) => { const e = spring({frame: frame - 6 - i * 7, fps, config: {damping: 200}}); diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx index e2ac3ab7..0d03deab 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P0Hook.tsx @@ -5,7 +5,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Chip, Desk, Footnote, LoopRing, SceneHeader, SceneTag, Stamp, Terminal} from '../components/motifs'; +import {Chip, Desk, Footnote, LoopRing, SceneHeader, Stamp, Terminal} from '../components/motifs'; /** p0-07 五样装置(0-C 列队用):顺序与口播逐字对齐。 */ const DEVICES = [ @@ -39,8 +39,7 @@ const TaskScrollsOut: React.FC<{scrollAt: number; ghostAt: number; recallAt: num }); return ( - -
+
= ({iconAt}) => { ]; return ( - - +
{/* 左侧:桌面上已有的对话流(安静地垫底) */}
diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx index fea98b44..8ab72053 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx @@ -7,7 +7,7 @@ import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; import {QuoteCard} from '../components/cards'; -import {Chip, Counter, Desk, Footnote, LoopRing, Panel, SceneHeader, SceneTag, Stamp, useRingDot} from '../components/motifs'; +import {Chip, Counter, Desk, Footnote, LoopRing, Panel, SceneHeader, Stamp, useRingDot} from '../components/motifs'; /** 2-A 桌面色块暴涨成灾:一百多条记录填满桌面;计费计数器持续跳字。 */ const DeskFlood: React.FC<{floodAt: number; billAt: number}> = ({floodAt, billAt}) => { @@ -23,8 +23,7 @@ const DeskFlood: React.FC<{floodAt: number; billAt: number}> = ({floodAt, billAt }); return ( - -
+
{Array.from({length: rows}).map((_, r) => ( diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx index ff53b05c..07e3f536 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx @@ -7,7 +7,7 @@ import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; import {QuoteCard} from '../components/cards'; -import {Counter, Desk, Footnote, Panel, SceneHeader, SceneTag, Stamp} from '../components/motifs'; +import {Counter, Desk, Footnote, Panel, SceneHeader, Stamp} from '../components/motifs'; /** 3-A 左:桌角薄目录卡叠(每张一行 ~100);右:整块厚手册拍上桌(~2000+),桌面被压得下沉。 */ const ThickManualSlams: React.FC<{slamAt: number}> = ({slamAt}) => { @@ -27,8 +27,7 @@ const ThickManualSlams: React.FC<{slamAt: number}> = ({slamAt}) => { }); return ( - -
+
{/* 左:桌角薄目录卡叠 */}
diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx index c2a6974f..746047c0 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx @@ -8,7 +8,7 @@ import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; import {QuoteCard} from '../components/cards'; -import {Chip, Counter, Desk, Footnote, Panel, SceneHeader, SceneTag, Stamp} from '../components/motifs'; +import {Chip, Counter, Desk, Footnote, Panel, SceneHeader, Stamp} from '../components/motifs'; /** 梯子骨架(mech):三级木梯挂在桌右缘,自上垂下挂稳(rope 微弹)。 */ const Ladder: React.FC<{drop: number; labels?: [string, string, string]}> = ({drop, labels}) => { @@ -53,8 +53,7 @@ const LadderDrops: React.FC<{dropAt: number}> = ({dropAt}) => { const drop = spring({frame: frame - dropAt, fps: 30, config: {damping: 11}}); return ( - -
+
{/* 桌子 */}
diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P5Ring.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P5Ring.tsx index f98ebbb6..9b2b2e50 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P5Ring.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P5Ring.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Desk, Footnote, LoopRing, Panel, SceneHeader, SceneTag, Stamp, useRingDot} from '../components/motifs'; +import {Desk, Footnote, LoopRing, Panel, SceneHeader, Stamp, useRingDot} from '../components/motifs'; /** 五样装置(编号即桌面位置——反枚举:不给五色)。 * 装置缩略图统一 panel 底 + 编号;职责字以印章形式落下。 */ @@ -69,8 +69,7 @@ const FiveDevices: React.FC<{devAt: number[]; stampAt: number[]}> = ({devAt, sta const {fps} = useVideoConfig(); return ( - -
+
{DEVICES.map((d, i) => { const e = spring({frame: frame - devAt[i], fps, config: {damping: 200}}); const on = frame >= devAt[i]; From 301da19aa22449906f26fae8b7e157e352960914 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sat, 29 Aug 2026 11:00:48 +0800 Subject: [PATCH 35/41] =?UTF-8?q?fix(video):=20W8=20=E5=B8=A7=E7=BA=A7?= =?UTF-8?q?=E8=A7=86=E8=A7=89=E5=AE=A1=E6=9F=A5=E2=80=94=E2=80=9460=20?= =?UTF-8?q?=E5=A4=84=E7=9C=9F=E5=AE=9E=E7=BC=BA=E9=99=B7=E5=AE=9A=E4=BD=8D?= =?UTF-8?q?=E3=80=8149=20=E5=A4=84=E4=BF=AE=E5=A4=8D=EF=BC=88892=20?= =?UTF-8?q?=E5=B8=A7=E9=80=90=E5=B8=A7=E5=AE=A1=E8=BF=87=EF=BC=89;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 每集从 final.mp4 抽帧(Sequence 起点+均匀共 892 帧)→ 像素检测+视觉模型逐帧看图 → 带帧号定位 → 修复 → remotion still 复验。 主要修复:EP1 8 处(命名帧外框越窗/竖边穿抬头字、四辐条与抬头同行印字、CornerRing 压幕标题全幕 8 处、四宫格回连弧穿大字等);EP2 9 处(终端残影与活行糊字——Terminal 母题级修复、金句 64px 任意折行劈句——QuoteCard 语义分行、玻璃罩切字、5-B 环线穿 五卡标题等);EP3 7 处(存活矩阵与回捞桌叠印 24 秒、项目规则卡压通道 40 秒(死代码 根因)、价目条穿字等);EP4 11 处(SceneTag 残留 10 处——上轮正则漏删、MiniStart 溢出、天平脚注重印、金句缺定位压面板等);EP5 14 处(四道闸压底座、三向卡骑两端块、 收官反转句与 Footnote 逐字压印——源码注释被实拍证伪等)。 未修 1 处(净空 0px 仅观感偏紧,改动收益低于回归风险)。五集 tsc 零错误、 check_series 全绿、SceneTag 残留清零。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../video/src/scenes/P0Wait.tsx | 20 ++- .../video/src/scenes/P1Dereg.tsx | 15 +- .../video/src/scenes/P2Rejoin.tsx | 16 ++- .../video/src/scenes/P3Watchdog.tsx | 10 +- .../video/src/scenes/P4Timer.tsx | 32 +++-- .../video/src/scenes/P5Truths.tsx | 4 +- .../video/src/scenes/P0Hook.tsx | 54 ++++++-- .../video/src/scenes/P1Loop.tsx | 12 +- .../video/src/scenes/P2Dispatch.tsx | 9 +- .../video/src/scenes/P3Gates.tsx | 27 +++- .../video/src/scenes/P4Hooks.tsx | 6 +- .../video/src/scenes/P6Ending.tsx | 7 +- .../video/src/scenes/P0Reject.tsx | 22 ++- .../video/src/scenes/P1Desk.tsx | 24 ++-- .../video/src/scenes/P3Helper.tsx | 129 +++++++++++++----- .../video/src/scenes/P4Ledger.tsx | 37 ++++- .../video/src/scenes/P2Mail.tsx | 18 ++- .../video/src/scenes/P3Handshake.tsx | 48 +++++-- .../video/src/scenes/P4Autonomy.tsx | 37 +++-- .../video/src/scenes/P5Desks.tsx | 81 +++++++---- .../video/src/scenes/P6Finale.tsx | 11 +- .../video/src/components/cards.tsx | 14 +- .../video/src/components/motifs.tsx | 76 ++++++----- .../video/src/scenes/P1Plan.tsx | 13 +- .../video/src/scenes/P2SideDesk.tsx | 30 +++- .../video/src/scenes/P3Manual.tsx | 15 +- .../video/src/scenes/P4Ladder.tsx | 84 +++++++++--- .../video/src/scenes/P5Ring.tsx | 26 +++- 28 files changed, 643 insertions(+), 234 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx index 95697b3b..c6a99591 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx @@ -255,8 +255,13 @@ const MiniStart: React.FC<{mode: 'onRing' | 'offRing' | 'noOne'; active: boolean const cy = 108; const r = 62; const stroke = active ? theme.core : theme.panelBorder; + // ⚠️ overflow:'visible' + 定死 192×216 会让 offRing 的人形(x 最远 220)画到 + // svg 框外,直接压在右侧「第一步」标题上——2026-08 抽帧实拍坐实。 + // 改用 viewBox 把三种 mode 的真实包围盒(x -8..228 / y -10..190)全收进来, + // 并去掉 overflow:visible:几何坐标一律不动,只是渲染尺寸缩到 142×120, + // 图元再也不可能溢出到文字区。 return ( - + {mode === 'onRing' ? ( @@ -407,18 +412,23 @@ const BlindnessAndPlan: React.FC<{blindAt: number; step1At: number; step2At: num ); })}
- {/* 两步预告(p0-11/12):三格开始中的后两格浮出(later 描边统一) */} + {/* 两步预告(p0-11/12):三格开始中的后两格浮出(later 描边统一)。 + bottom:130 时卡体(顶 ~700、底 ~950)整个盖住 Footnote(bottom:168 + → 约 883–912),角标一行字从两张卡中间横穿而过,且卡底逼到字幕带 + (bottom:54 起)——2026-08 抽帧实拍坐实。抬到 bottom:232:卡底 + 848,与 Footnote 顶缘留 35px 净空;卡宽 460→560 让标题一行放得下, + 不再折行去撞左侧环图。 */}
- +
= step1At} />
@@ -431,7 +441,7 @@ const BlindnessAndPlan: React.FC<{blindAt: number; step1At: number; step2At: num = step2At ? theme.later : theme.panelBorder} - style={{width: 460, padding: '14px 18px 10px', opacity: frame >= step2At ? 1 : 0.35}} + style={{width: 620, padding: '14px 18px 10px', opacity: frame >= step2At ? 1 : 0.35}} >
= step2At} /> diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P1Dereg.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P1Dereg.tsx index 2c1c32bb..34e7c11d 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P1Dereg.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P1Dereg.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame} from 'remo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, LoopRing, Panel, SceneHeader, SceneTag, useRingDot} from '../components/motifs'; +import {Footnote, LoopRing, Panel, SceneHeader, useRingDot} from '../components/motifs'; /** 环外旁轨的几何常数:与 LoopRing 同心、半径外扩(本幕内推导基线,P2 自带几何) */ const TRACK_R = 340; @@ -184,7 +184,6 @@ const OffLoopSideTrack: React.FC<{slideAt: number; stubAt: number; nextAt: numbe }); return ( - {/* 旁轨:later 虚线弧(120°→310°),环外一层 */} 0 ? : null} {/* 环速不变:旁轨事件全程,环上光点匀速(由 useRingDot 保证) */} + {/* 「循环接着转」标签:原锚在 (TRACK_CX-90, TRACK_CY+330) = (530, 850), + 正是命令块沿旁轨缓行必经的落点——block 漂到此处后两者整行压字 + (2026-08 抽帧实拍坐实)。旁轨弧只走到 310°,环右外侧 (1010, 690) + 全 beat 无 ink,把标签移到那里彻底避开运动轨迹。 */} {nextO > 0 ? ( - + {'循环接着转,去干下一件'} ) : null} @@ -252,8 +255,12 @@ const SingleThreadTruth: React.FC<{mergeAt: number; labelAt: number}> = ({mergeA extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); + // paddingBottom 把居中的轨道图整体上提 90px:合并后的下排块落在 + // yMid+34(绝对 798),与下方金句(bottom:236 → 顶缘 798)恰好贴死, + // 「后台块」与「后台 = 不等它」两行字压在一起——2026-08 抽帧实拍坐实。 + // 上方本就是整片空带(顶部 1/3 闲置),上提不挤压任何元素。 return ( - + {/* 轨道线:两条 → 一条 */} diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx index b0e7c179..a03355da 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx @@ -6,7 +6,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, LoopRing, NumberedCard, Panel, SceneHeader, SceneTag, useRingDot} from '../components/motifs'; +import {Footnote, LoopRing, NumberedCard, Panel, SceneHeader, useRingDot} from '../components/motifs'; /** 2-A 配对语义:一次调用卡 ↔ 一条结果卡的锁扣「咔」;真结果换装成完成通知入队 */ const PairLock: React.FC<{lockAt: number; swapAt: number; queueAt: number}> = ({lockAt, swapAt, queueAt}) => { @@ -96,7 +96,6 @@ const TwoTierQueue: React.FC<{dropAt: number; userAt: number}> = ({dropAt, userA const user = spring({frame: frame - userAt, fps, config: {damping: 200}}); return ( - @@ -324,8 +323,11 @@ const ClaimCheckScale: React.FC<{matchAt: number; scaleAt: number; stampAt: numb {'对上号 —— 该补哪句话,它知道'} ) : null} - {/* 天平(下半) */} - = scaleAt ? 1 : 0.25}> + {/* 天平(下半)。cy=830 时其脚注(内部 y=64 → 绝对 894)正落在 + Footnote 的行高区间(bottom:168 → 约 883–912)上,两行文字整行 + 重印成一团糊字——2026-08 抽帧实拍坐实。整组上提到 cy=770: + 脚注移到绝对 834,与 Footnote 顶缘留 49px 净空。 */} + = scaleAt ? 1 : 0.25}> @@ -355,12 +357,16 @@ const ClaimCheckScale: React.FC<{matchAt: number; scaleAt: number; stampAt: numb
+ {/* 盖章:bottom:300 让章体(y 约 695–780)横穿天平右盘与横梁, + 章框把「占位再补通知」盘压掉一角——2026-08 抽帧实拍坐实。 + 改锚到右上空带 top:250(本 beat 全程零 ink 实测),既避开天平, + 也避开左上 SceneHeader 与左侧小环。 */} {stampOn ? (
= ({stopAt, focusAt}) => { @@ -164,7 +164,6 @@ const DogRises: React.FC<{ }); return ( -
{/* 45 秒刻度盘 */}
@@ -333,10 +332,17 @@ const DogRises: React.FC<{
) : null} + {/* 金句:必须显式落在 SceneHeader 与主体行之间的上部空带。 + 缺省的 position:absolute(无 top/left)会退回父级 flex 居中位, + 正好压在中央的输出线面板上——2026-08 抽帧实拍坐实的叠印。 */} {quoteO > 0 ? (
= ({clockAt}) => { @@ -103,7 +103,6 @@ const FiveFieldTable: React.FC<{frameAt: number; ex1At: number; ex2At: number; e ]; return ( - {/* 五格框架 */}
{cols.map((c, i) => ( @@ -120,13 +119,20 @@ const FiveFieldTable: React.FC<{frameAt: number; ex1At: number; ex2At: number; e {c}
- {/* 底格(星号占位) */} + {/* 底格(星号占位):40px 字 + lineHeight 96px 使其字心落在 y≈48, + 正压住第一条实例行(top:26、26px 字,跨 26..60),两个星号叠印 + 成毛刺——2026-08 抽帧实拍坐实。占位符只在「实例未出」时承担 + 空态提示,第一条实例落下即让位(帧驱动淡出,确定性)。 */}
{'*'} @@ -210,7 +216,6 @@ const TwoGuards: React.FC<{rejectAt: number; skipAt: number}> = ({rejectAt, skip ]; return ( -
{/* 保险一:写表验格式 */}
@@ -332,7 +337,6 @@ const FourLayerModel: React.FC<{dropAt: number; gateAt: number; dupAt: number}> }); return ( - {/* 层 1:秒摆线程(每秒一跳) */} @@ -354,9 +358,12 @@ const FourLayerModel: React.FC<{dropAt: number; gateAt: number; dupAt: number}> {`每秒一跳 · 第 ${sec} 秒`} - {/* 命中分钟:卡片塞进队列(dropT 落下) */} + {/* 命中分钟:卡片塞进队列(dropT 落下)。 + 行程 300 会把卡停在 x=600:卡右缘 692 + 命中圆点 701 越过队列框 + 左边(x=700),卡与虚线框压边、「到点 · 塞进一张」被叠住——2026-08 + 抽帧实拍坐实。收到 270(终点 570,右缘 671),与队列框留 29px 净空。 */} {dropT > 0 ? ( - + {'0 9 * * *'} @@ -370,7 +377,10 @@ const FourLayerModel: React.FC<{dropAt: number; gateAt: number; dupAt: number}> {'队列'} - + {/* 状态字:y=52 时字身(约 33..52)被队列框下边(y=40,线宽 4) + 拦腰横穿,「等待」二字被虚线切成两半——2026-08 抽帧实拍坐实。 + 下移到 68:字顶 49,距框下缘 42 留 7px 净空。 */} + {hit ? '到点 · 塞进一张' : '等待'} @@ -415,7 +425,10 @@ const FourLayerModel: React.FC<{dropAt: number; gateAt: number; dupAt: number}> {'第 2 枪 ✗'} - + {/* 卡片 rotate(-14°) 后半高从 26 涨到 64·sin14+26·cos14 ≈ 41, + y=48 的说明字(字顶约 29)被卡下缘压住——2026-08 抽帧实拍坐实。 + 下移到 70:字顶 51,与旋转后的卡下缘留 10px 净空。 */} + {'已记「这一分钟发过了」'} @@ -467,7 +480,6 @@ const ThreeTiers: React.FC<{tier1At: number; tier2At: number; tier3At: number; o ]; return ( - {/* 三档卡片自上而下(自左而右)点亮 */}
{tiers.map((tr, i) => { diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx index 693b48f3..e728e344 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx @@ -7,7 +7,7 @@ import {AbsoluteFill, interpolate, Sequence, spring, useCurrentFrame, useVideoCo import {theme} from '../design/theme'; import {beatWindow} from '../timing'; import type {SceneRange} from '../types'; -import {Footnote, Panel, SceneHeader, SceneTag} from '../components/motifs'; +import {Footnote, Panel, SceneHeader} from '../components/motifs'; /** 迷你钟面:时针/分针可指定角度,可选表盘描边色 */ const MiniClock: React.FC<{ @@ -132,7 +132,6 @@ const DeterministicJitter: React.FC<{staggerAt: number; randomAt: number; earlyA }); return ( - {/* 错峰一排表:各按固定偏移「落下」 */} {Array.from({length: N}, (_, i) => ( @@ -218,7 +217,6 @@ const RetireStamp: React.FC<{flipAt: number; stampAt: number}> = ({flipAt, stamp }) : 0; return ( -
{/* 日历:翻页计数 */}
diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx index 474a0b16..8a5dda4f 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P0Hook.tsx @@ -108,8 +108,13 @@ const NamingFrame: React.FC<{ const CX = 960; const CY = 460; const full = 420; - const wHalf = full / 2 + (1 - close) * 620; - const hHalf = full / 2 + (1 - close) * 380; + // 合拢起手的张开量:**必须**让展开态的外框仍落在安全区内。此前 620/380 的起手 + // 让 close=0 时外框上沿到 y=-130(探出画面顶)、右沿 x=1790 横穿 SceneHeader 的 + // meta 文字「the missing layer」——2026-08 帧级复查 f332/f851 实拍坐实。 + // 上限反推:外框上沿 = CY − hHalf ≥ 150(抬头带含进度条到 y≈126),故 + // hHalf ≤ 310;四角残影再外扩 40,故 hHalf ≤ 270。横向同理收进 72..1848。 + const wHalf = full / 2 + (1 - close) * 420; + const hHalf = full / 2 + (1 - close) * 60; const label = interpolate(frame - frameAt - 22, [0, 14], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', @@ -202,13 +207,17 @@ const NamingFrame: React.FC<{ > {'Harness'}
+ {/* 外框注脚:与赌注卡同为「引文条压上时让位」的一层。引文条上沿在 + y≈718(bottom:200 + 面板高),此注脚落在 CY+hHalf+40 = 710,两者 + 仅差 8px 而互相压字(2026-08 帧级复查 f1100 实拍坐实)——随引文条 + 淡出即可,语义已由引文条本身承接。 */}
{'把动力源,套进一个可控的结构里'}
- {/* 官方赌注卡(p0-03a..c):bottom:210 避让字幕带;p0-05 引文条压上时让位淡出 */} - {bet > 0 ? ( + {/* 官方赌注卡(p0-03a..c):bottom:210 避让字幕带;p0-05 引文条压上时让位淡出。 + 淡出必须**清零并卸载**:旧写法留 (1 - quote*0.9) = 0.1 的残影,引文条 + (半透明 Panel)压上后两层文字互相透印成糊字(2026-08 帧级复查 f1100 + 实拍坐实)。改为 quote ≥ 0.999 时整块卸载,之前按 1-quote 线性到 0。 */} + {bet > 0 && quote < 0.999 ? (
@@ -338,7 +350,15 @@ const SupplySpokes: React.FC<{titleAt: number}> = ({titleAt}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); const CX = 960; - const CY = 440; + // 外框由 760×500@CY440 收成 700×420@CY490(2026-08 帧级复查 f1420 实拍): + // 旧几何下辐点 fy = CY−250 = 190,辐条名(fy−92 = 98)正落在 SceneHeader + // 的 52..112 带内,「循环/工具/上下文管理/护栏」与幕标题同行印字;辐点圆 + // (110..178)又被抬头带的进度线(y≈126)横穿。 + // 新几何下辐条名落 y≈188、辐点圆 234..302,均在抬头带下沿之外;外框下沿 + // 700 仍与标题卡上沿(bottom:210 → y≈736)留 36px。 + const CY = 490; + const HALF_W = 350; + const HALF_H = 210; const R = 300; const spokes = [ {label: '循环', zh: '问模型·执行·填回'}, @@ -360,10 +380,10 @@ const SupplySpokes: React.FC<{titleAt: number}> = ({titleAt}) => { {/* 外框(Harness 轮廓,缩小型持续在场) */} = ({titleAt}) => { }); if (t <= 0) return null; const fx = CX - 225 + i * 150; - const fy = CY - 250; + const fy = CY - HALF_H; const ix = CX + (fx - CX) * 0.24; const iy = CY - 40; const glow = sp.later ? 0 : 0.5 + 0.5 * Math.sin((frame - i * 8) / 9); @@ -396,11 +416,15 @@ const SupplySpokes: React.FC<{titleAt: number}> = ({titleAt}) => { strokeWidth={5} style={sp.later ? undefined : {filter: `drop-shadow(0 0 ${4 + glow * 8}px ${theme.mech}88)`}} /> - - + + {sp.label} - + {/* 小字说明改挂**辐点上方**(原 fy+26 在框内):辐条自 (fx, fy) 射向 + 内核,在 y≈306 处横向已偏出 26px,正好从「问模型·执行·填回」这类 + 8 字标签的字面中间穿过(2026-08 帧级复查 f1420/f1540 实拍坐实)。 + 上移到 fy-82 后,标签整体落在辐条起点之上,与线零相交。 */} + {sp.zh} diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx index a92e3e62..bba6df36 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx @@ -98,7 +98,11 @@ const FiveSteps: React.FC<{stepAt: number[]}> = ({stepAt}) => { ); })}
- + {/* alignSelf:flex-start + marginTop:40 会把面板顶到 y≈40,整块压在 + SceneHeader 的 meta「Agent Loop · gather / act / verify」上(2026-08 + 帧级复查 f2473/f2554 实拍坐实)。抬头带含进度条到 y≈126,故改用 + marginTop:170 把面板压到抬头带之下。 */} +
{'messages[]'}
@@ -410,7 +414,11 @@ const ThreePhaseRing: React.FC<{phaseAt: number; handAt: number; drawersAt: numb extrapolateRight: 'clamp', }); const CX = 560; - const CY = 500; + // 环心下移 +80:此前 CY=500 时 -90° 相位标签落在 y = CY − R − 96 − 10 ≈ 144, + // 与 SceneHeader(top 52,含进度条到 y≈126)只差 18px,「收集上下文」贴着抬头带 + // 印字;上方的「三相互相交融」标注(y = CY − R − 148 ≈ 102)更是直接横穿幕标题。 + // 下移后:相位标签 y≈224、交融标注 y≈182,均落在抬头带下沿之外。 + const CY = 580; const R = 250; return ( diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx index 9e6de8a2..cde96fae 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P2Dispatch.tsx @@ -8,13 +8,18 @@ import type {SceneRange} from '../types'; import {QuoteCard} from '../components/cards'; import {CodeCard, DispatchTable, Footnote, LoopRing, NumberedCard, Panel, SceneHeader, Terminal, useRingDot} from '../components/motifs'; -/** 环留在左上角:缩小但同色同线宽 */ +/** 环留在左上角:缩小但同色同线宽。 + * 落位约束:SceneHeader 占 top 52..112(含 bottom:-14 的幕内进度条,实际到 y≈126), + * 角环必须整体落在其**下方**。此前 top:56 让环上半圈直接压在幕标题「P2 加一个工具, + * 只改一行」上、环线又横穿进度条(2026-08 帧级复查 f7431/f9041/f10615 实拍坐实)。 + * size=190 的 LoopRing 内部半径 = 95−46 = 49,环上沿 = top + 95 − 49 − 3(线宽半); + * 取 top:150 ⇒ 环上沿 y≈193,与进度条留 67px 净空。 */ const CornerRing: React.FC<{pulse?: boolean}> = ({pulse = false}) => { const frame = useCurrentFrame(); const dot = useRingDot(2.5); const p = pulse ? 0.6 + 0.4 * Math.sin(frame / 4) : 1; return ( -
+
); diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx index db08cf25..0ed3b076 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx @@ -225,7 +225,12 @@ const AskAndPass: React.FC<{askAt: number; passAt: number}> = ({askAt, passAt}) style={{ position: 'absolute', left: 120, - top: 56, + // top:56 会把三张卡整体压在 SceneHeader 上——幕序「P3」与幕标题 + // 「执行之前,先过闸门」被 allow/ask 两张卡完全盖住(2026-08 帧级复查 + // f13080 实拍坐实)。抬头带含进度条到 y≈126,故小抄下移到 150; + // 卡高约 108(10+30+26+23+10+边框),下沿 y≈258 仍收在闸门名 + // (y≈235–258)之上的约束由「闸门整体上移 -150」保障。 + top: 150, display: 'flex', gap: 18, opacity: interpolate(t2, [0.4, 0.8], [0, 1], {extrapolateRight: 'clamp'}), @@ -624,10 +629,16 @@ const FourResults: React.FC<{fourthAt: number; arcAt: number}> = ({fourthAt, arc ); })}
+ {/* 「不表态 → 问你」的回连弧走**格子外侧**(右缘之外)。 + 旧弧 M400 210 C520 210,560 120,470 96 起点落在第四格内部, + 整条弧横穿「不表态」四个大字、「兜底」二字又压在格内(2026-08 + 帧级复查 f14473 实拍坐实)。改为自第四格右缘中点出发、绕右侧 + 外空白上行、收在第二格(拒绝)右缘——全程 x ≥ 704 = 格阵右缘, + 与任何文字零相交。 */} {arc > 0 ? ( - + = ({fourthAt, arc strokeDashoffset={1 - arc} /> {arc > 0.9 ? ( - - {'兜底'} - + <> + {/* 箭头收口指回「拒绝/问你」一侧 */} + + + {'兜底'} + + ) : null} ) : null} diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx index a7e8195f..45b2c119 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P4Hooks.tsx @@ -115,8 +115,12 @@ const PullOut: React.FC<{tableAt: number; plugAt: number}> = ({tableAt, plugAt}) const out = interpolate(frame, [0, 26], [0, 1], {extrapolateRight: 'clamp'}); const plug = spring({frame: frame - plugAt, fps, config: {damping: 12}}); const flash = frame >= plugAt + 6 && frame < plugAt + 8; + // gap:70 只隔开两个 flex 盒,但 LoopRing 的节点文案是 SVG overflow:visible + // 画到盒外的——0° 的「看回答」自环右缘再向外 26+文字宽 ≈ 100px,实际净空 + // 只剩 ~-30px,字紧贴时机表左缘(2026-08 帧级复查 f17878 实拍坐实)。 + // gap 提到 190 给标签让出真实占位。 return ( - +
{[0, 1, 2, 3].map((i) => { diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx index 73d046f1..95208cc9 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P6Ending.tsx @@ -54,7 +54,12 @@ const ShellLayers: React.FC<{layerAt: number[]}> = ({layerAt}) => { if (!on) return null; const rad = (a.ang * Math.PI) / 180; // 卡片中心的落位半径:环外一圈(dist > RING_R,卡片整体在环之外—— - // 底部那句「挂件 ×3,都挂在外面」是字面意思,卡片不得压在环线上) + // 底部那句「挂件 ×3,都挂在外面」是字面意思,卡片不得压在环线上)。 + // ⚠️ 勿再放大 dist:卡片恒正立,轴对齐半宽 84 / 半高 34 在 R+96 下最近 + // 角到环心 ≈ 216–225 > 环线外沿 205,已留 11–20px 净空;挂脚末端夹爪 + // 咬在环线上是**设计意图**,不是重叠缺陷。2026-08 帧级复查曾把这段夹爪 + // 误判为「卡片压环」并把 dist 提到 R+190,结果 75° 的「闸门」卡下沿掉到 + // y≈960、探进字幕安全带(SAFE_TOP_Y=920)——按下葫芦浮起瓢,已回退。 const dist = R + 96; // 挂脚长度 = 卡心到环线的径向距离;本组已按 ang 旋转,故 -x 指向环心 const stem = dist - RING_R; diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx index 0244e5e5..f16536f8 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx @@ -470,7 +470,9 @@ const ContextRot: React.FC<{curveAt: number; graphAt: number; thinAt: number; st {'低'} - + {/* 轴题另起一行(y=462)——旧 y=434 与首个刻度 10³ 同行同 x 起点, + 实测帧 1503「窗口字数 →」压住「10³」;刻度行 y=430,轴题下沉 32px 分行 */} + {'窗口字数 →'} {/* X 轴 log 刻度 */} @@ -623,13 +625,16 @@ const TwoAnswers: React.FC<{leftAt: number; rightAt: number; lineAt: number}> = {'把丢管起来——分级、有序、有保底'}
- {/* 右:登记簿(不丢的那层)——keep 描边本子 */} + {/* 右:登记簿(不丢的那层)——keep 描边本子。 + 宽 700→780:700 减去本子 svg 240 与 gap 34 只剩 426,装不下 15 字 ×30px + 的副标题(450),实测帧 2449 末字「来」被挤到第二行成孤字;780 留 506 可单行。 + 右块按 scale(0.66) 从右缘起算 → 左缘 1660-780×0.66=1145,仍在中央分隔线 828 右侧。 */}
= > {'第二层:保证不丢'}
-
+
{'另立账本,重要的写进去就不出来'}
diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P1Desk.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P1Desk.tsx index a4c8405e..a090dedb 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P1Desk.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P1Desk.tsx @@ -180,14 +180,17 @@ const SnipMiddle: React.FC<{ strokeDasharray="14 10" /> - {/* 尾部四十七张:亮起(正在用的不能动) */} + {/* 尾部四十七张:亮起(正在用的不能动)。 + 标注改为跟在卡格之后的常规流(原 position:absolute bottom:-34 相对 + height:220 的容器定位,但 15 张 ×(52+8) 按 420 宽折成 4 行实占 ~236px, + 标注被压回最后一行卡上——实测帧 3301/4142 文字与卡重叠)。 + 容器去掉固定 height 由内容撑开,标注 marginTop 隔开 10px。 */}
@@ -198,9 +201,7 @@ const SnipMiddle: React.FC<{
= ({foldAt, recent return (
-
+ {/* gap 22→34:折叠后的一行动字按列宽折行后,列间仍需可辨的留白 */} +
{[0, 1, 2, 3].map((i) => { // 折叠动画:大卡高度缩到一行(scaleY 压扁 + 褪色) const t = interpolate(frame - foldAt[i], [0, 14], [0, 1], { @@ -296,7 +298,10 @@ const FoldOld: React.FC<{foldAt: number[]; recentAt: number}> = ({foldAt, recent }); const folding = i >= 1; // 第一张是最近三张的代表,不折 return ( -
+ // 列宽锁死到卡宽 190:下面两行说明文字原为 nowrap,单行实宽 ~288px, + // 在 190 列里向两侧溢出并与邻列同款文案首尾相接(实测帧 5004 三段 + // 「早前结果已收起,需要再跑一遍」间隔仅 25px,读成一整行)。 +
= ({foldAt, recent fontSize: 20, color: theme.dim, opacity: interpolate(t, [0.7, 1], [0, 1], {extrapolateRight: 'clamp'}), - whiteSpace: 'nowrap', + textAlign: 'center', + lineHeight: 1.4, }} > {'早前结果已收起,需要再跑一遍'} @@ -333,6 +339,8 @@ const FoldOld: React.FC<{foldAt: number[]; recentAt: number}> = ({foldAt, recent fontFamily: theme.mono, fontSize: 22, color: i === 0 ? theme.mech : theme.dim, + textAlign: 'center', + lineHeight: 1.4, }} > {i === 0 ? '最近 3 条 · 完整保留' : '更早 · 已折成一行'} diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx index 4d428602..958c1155 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P3Helper.tsx @@ -285,7 +285,14 @@ const DraftThenFair: React.FC<{draftAt: number; fairAt: number; tearAt: number}> ); }; -/** 3-C ★回捞钩:压缩后柜门开,五张文件卡按重要性被钩回桌面 */ +/** 3-C ★回捞钩:压缩后柜门开,五张文件卡按重要性被钩回桌面。 + * + * ⚠️ 版位纪律(2026-08 逐帧品控):本组件与上方 SurvivalMatrix 同屏共存, + * 必须**整体压在矩阵下方的独立横带**里。旧版把整台戏挂在矩阵容器内并居中, + * 桌面(900×430)正落在矩阵四行上:实测帧 12285–12987(约 24 秒)「已用技能正文」 + * 被卡片截成「用技能正文」、注记「重注入 · 每份封顶五千 · 最旧先丢」被拦腰打断。 + * 现在:桌与柜同高 345、同 top 278(页面 y 508–853),矩阵 dock 后占 y 150–496, + * 柜标注单占 y 474–496 那一行——三条带互不相交。 */ const SalvageHook: React.FC<{openAt: number; hookAt: number; honestAt: number}> = ({ openAt, hookAt, @@ -297,11 +304,31 @@ const SalvageHook: React.FC<{openAt: number; hookAt: number; honestAt: number}> extrapolateRight: 'clamp', }); const grabbed = hookAt + 10; + /** 舞台带顶(容器内坐标):容器 1640×620 居中 → 页面 top 230,故 278 ≙ 页面 508。 + * 上邻矩阵 dock 后底边 496 → 留 12px;下邻脚注带 878 → 桌底 853 留 25px。 */ + const STAGE_TOP = 278; + /** 桌与柜统一高度:旧柜高 560 会顶到脚注带(页面 y 878) */ + const STAGE_H = 345; return (
- {/* 桌面(左):捞回的卡按重要性排队落位 */} - + {/* 桌面(左):捞回的卡按重要性排队落位。 + 不用 Desk 的 label(它挂在框外 top:-36,即页面 y 472,正插进矩阵第四行 + 「已用技能正文」的 435–496 带)——改成框内左上角常规标注。 */} + +
+ {'桌面(压缩后)'} +
{[0, 1, 2, 3, 4].map((i) => { // 钩爪依次捞回:第 i 张在 hookAt + i*10 后从柜(x0,Desk 外右侧)飞到桌面 const t = interpolate(frame - (hookAt + i * 10), [0, 22], [0, 1], { @@ -309,11 +336,13 @@ const SalvageHook: React.FC<{openAt: number; hookAt: number; honestAt: number}> extrapolateRight: 'clamp', }); const x0 = 820; // 柜内起点(Desk 右缘外的文件柜方向) - const y0 = 120 + i * 66; - const x1 = 70 + i * 158; // 桌面落位 - const y1 = 200 + (i % 2) * 90; + const y0 = 20 + i * 60; + const x1 = 70 + i * 158; // 桌面落位(w150 → 末张右缘 852 < 900) + // 落位两排 118/168:+卡高 80 → 最低 248,与底部标注行顶(345-18-28=299) + // 留 51px。旧值 150/210 让偶数张压到 290,正骑在标注上(实测帧 12656)。 + const y1 = 118 + (i % 2) * 50; const x = x0 + (x1 - x0) * t; - const y = y0 + (y1 - y0) * t - Math.sin(t * Math.PI) * 90; + const y = y0 + (y1 - y0) * t - Math.sin(t * Math.PI) * 70; return (
{'≤ 5 个文件 · 单份限额 · 总量预算 · 按重要性排队'}
- {/* 文件柜(右):门开,钩爪伸入 */} + {/* 文件柜(右):门开,钩爪伸入。与桌同带同高,避免顶穿矩阵/脚注。 + label 同样不走组件内建的 top:-36(会插进矩阵行带),改为柜上方 26px 独立行—— + 该处 x≥1130 在矩阵右缘(注记末字 ~1060)之外,横向不撞。 */} 0.3 ? 2 : -1} - label="文件柜" - style={{position: 'absolute', right: 30, top: 30}} + style={{position: 'absolute', right: 30, top: STAGE_TOP}} /> - {/* 钩爪:从桌面伸向柜内的弧线钩 */} - +
+ {'文件柜'} +
+ {/* 钩爪:从桌面伸向柜内的弧线钩(svg 随舞台带下移,端点按新带高重算) */} + {open > 0.3 ? ( {/* 钩臂:随第 i 张卡回收摆动(最近一次) */} @@ -373,10 +421,11 @@ const SalvageHook: React.FC<{openAt: number; hookAt: number; honestAt: number}> }); if (t <= 0 || t >= 1) return null; const bend = Math.sin(t * Math.PI) * 70; + const yEnd = 40 + i * 62; return ( ) : null} - {/* 诚实角标:末句浮现(三级证据归属) */} -
- {'本段为第三方的源码分析(真实实现的行为,超出最简示例范围)'} -
+ {/* 诚实角标:末句浮现(三级证据归属)。 + 必须走 Footnote 的 slot=1,不能再用容器内 bottom:-64——那个写法只在旧结构下 + «凑巧» 成立:当时 SalvageHook 嵌在矩阵的 1300×560 相对框内,AbsoluteFill 被 + 父框裁到那个盒子,角标落在半空。现在它挂到幕级、AbsoluteFill 覆盖整幅画布, + bottom:-64 会正压上同屏 SurvivalMatrix 的 Footnote(bottom 168)。slot=1 + (bottom 206)是本仓为「同屏两条脚注」预留的错行位。 */} + + {'本段为第三方的源码分析(真实实现的行为,超出最简示例范围)'} +
); }; @@ -426,9 +465,25 @@ const SurvivalMatrix: React.FC<{matrixAt: number; openAt: number; hookAt: number {t: '带路径的规则', fate: '丢到再读到匹配文件', alive: false}, {t: '已用技能正文', fate: '重注入 · 每份封顶五千 · 最旧先丢', alive: true}, ]; + // 回捞段登场后矩阵上移让位:矩阵单独在场时居中;SalvageHook 一进来就上推到 + // 顶带(页面 y 150–421),把 y 493 以下整条横带让给桌与柜——两者不再共占同一 + // 版位(旧版重叠 24 秒,见 SalvageHook 注释)。用 frame 判定,帧驱动确定性。 + const docked = interpolate(frame - openAt, [0, 14], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); return ( -
+
{'压缩之后,谁活下来?'}
@@ -453,9 +508,11 @@ const SurvivalMatrix: React.FC<{matrixAt: number; openAt: number; hookAt: number ); })}
- {/* 回捞钩(p3-12/13):文件卡被钩回 */} - {frame >= openAt ? : null}
+ {/* 回捞钩(p3-12/13):文件卡被钩回。 + 必须挂在矩阵容器**外**——放容器内会一起吃掉上面那条 translateY(-110), + 让位就白让了。它自带 AbsoluteFill,按整幅画布定位。 */} + {frame >= openAt ? : null} {'压缩存活矩阵 —— 官方文档 context-window(取数2026年8月)'} diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx index 8c6f07bf..2cf996f8 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P4Ledger.tsx @@ -276,9 +276,28 @@ const TwoLegsFrame: React.FC<{ extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); - // 卡的合成位置:起点(左腿上方)→ 顶部「基本设定」框;被弹回时停在通道层 - const cardX = 240 + fly * 620 - (fly - Math.max(fly, settled)) * 0; - const cardY = 620 - fly * 440 - (1 - settled) * 0; + // 卡的合成位置:起点(左腿上方)→ 上飞撞「基本设定」框 → 被弹回、停在通道**左侧**。 + // + // ⚠️ 旧式 `240 + fly*620` / `620 - fly*440` 里两个 settled 修正项都乘 0(死代码), + // 于是卡不管弹没弹回都钉死在 (860,180)——正压住通道框(left 860 / top 96 起算, + // 通道体 y≈167–208、x≈860–1340)。实测帧 14433–15658 约 40 秒,通道里 + // 「你开口之前 · 第一张便条(与你说的话同一身份)」被卡遮成「…前 · 第一张便条…」。 + // + // 现在两段真正串起来:fly 把卡送到撞击点,settled(spring 反相,含过冲)再把它 + // 落到通道左邻位。 + // · 撞击点 UP:停在「基本设定」框**上沿之外**。框体 top 96、含 padding 高约 44 + // → 96–140;卡高约 46,故 UP_Y=44 时卡底 90、距框顶 6px——「顶到了但没盖住」, + // 框里那行字全程可读(UP_Y=100 会压进框内,遮成「项目规则统提示)——…」)。 + // · 停位 REST:x 700–821 落在左腿右缘 440 与通道左缘 860 之间的空档,纵向与通道 + // 同高但不横向相交——「贴着通道停」的语义保住,字一个不挡。 + const UP_X = 940; + const UP_Y = 44; + const REST_X = 700; + const REST_Y = 156; + const upX = 240 + fly * (UP_X - 240); + const upY = 620 - fly * (620 - UP_Y); + const cardX = REST_X + (upX - REST_X) * settled; + const cardY = REST_Y + (upY - REST_Y) * settled; const cardShow = interpolate(frame - ghostAt, [0, 8], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', @@ -744,15 +763,21 @@ const PrefixCacheStrip: React.FC<{stripAt: number; priceAt: number}> = ({stripAt {'改规则要新开会话 · 中途换模型那轮慢'}
) : null} - {/* p4-25a/b 价目条:命中一折 · 写入 +1/4 · 两次回本(自下滑入,挂 strip 上方) */} + {/* p4-25a/b 价目条:命中一折 · 写入 +1/4 · 两次回本(自下滑入,挂 strip 上方左半)。 + ⚠️ 横向必须左避:本条与 TwoPaths 右栏的虚线条「支路失败 → 退回关键词匹配 + (便宜的兜底)」是互不知情的兄弟节点,纵向同占 y≈700–790 带。旧 left:'50%' + 居中 → 实宽 505px 落在 x 725–1229,与虚线条 x 955–1594 正面对撞,实测帧 + 17718/18193 两段文字彼此穿字、双双不可读。 + 改左对齐偏移 -190(相对 strip 容器左缘 620)→ x 430–935,与虚线条留 20px; + 纵向不动(仍贴 strip 上沿),语义仍是「给这三层标价」。 */} {frame >= priceAt ? (
= ({sendAt, readAt}
-
+ {/* 2026-08 实拍修:MailFile 内部是 position:absolute + top:y,父层的 + marginTop 对它完全无效——它从队友环的原点起画,把环与铭牌整个盖住 + (f5994/f6549 坐实)。这里改用 y 把信箱压到环(160)+铭牌(~46)之下。 */} +
= ({sendAt, readAt}
= msgAt + 26; - const msgX = 260 + travel * 700; + // 2026-08 实拍修:起点 260 落在「队友 A」卡的水平区间(left:180 + width:180 + + // padding/border ⇒ 180..386)内,t=0 时消息卡左沿直接压在铭牌上(f8106 坐实)。 + // 起点抬到 A 卡右沿 + 14px 呼吸;终点仍停在 B 卡左沿(1140)之前。 + const msgX = 400 + travel * 560; return (
diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx index e0bf69a9..566e8429 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P3Handshake.tsx @@ -55,8 +55,15 @@ const HandshakeRail: React.FC<{ const LEFT_X = 130; const RIGHT_X = W - 130; const MID_X = W / 2; - const reqX = LEFT_X + (MID_X - 96 - LEFT_X) * reqGo; - const ackX = RIGHT_X - (RIGHT_X - MID_X) * ackGo; + // 2026-08 实拍修:起点原取 LEFT_X(130),卡片以 reqX-96 落笔 ⇒ 左沿 34,正压在 + // 左端环+铭牌块(LEFT_X-90=40 起、宽 180 ⇒ 40..220)上,t=0 时「req_0042 关机请求」 + // 骑在领队环上(f10541 坐实)。起点抬到 316(卡左沿 220 = 端点块右沿)。 + const REQ_START_X = LEFT_X + 186; + const reqX = REQ_START_X + (MID_X - 96 - REQ_START_X) * reqGo; + // 应答卡对称处理:起点左沿 = 右端点块左沿(RIGHT_X-90=1240) 之外,故 ackX 起点 + // 取 RIGHT_X-186 ⇒ 卡区间 1048..1240,与右端环+铭牌块不相交。 + const ACK_START_X = RIGHT_X - 186; + const ackX = ACK_START_X - (ACK_START_X - MID_X) * ackGo; // 锁扣「咔」:合拢瞬间的一次性冲击闪光 const clack = lockT > 0.9 && lockT < 1 ? 1 - Math.abs(lockT - 0.95) / 0.05 : 0; return ( @@ -156,12 +163,16 @@ const HandshakeRail: React.FC<{ ) : null} - {/* 请求卡:从左滑出,停在等回话位 */} + {/* 请求卡:从左滑出,停在等回话位。 + 2026-08 实拍修:请求卡(top RAIL_Y-58)与应答卡(top RAIL_Y-22)两张各约 72px 高, + 竖向只错开 36px——合拢后两张在等回话位互相压掉一半,「关机请求」被「同意」 + 盖住(f10823/f11173 坐实)。改为请求走轨**上**行、应答走轨**下**行, + 各让开 RAIL_Y 一个半卡高,合拢的语义靠水平会合与锁扣「咔」表达。 */}
0 ? 1 : 0, zIndex: 2, }} @@ -171,12 +182,13 @@ const HandshakeRail: React.FC<{
{reqKind}
- {/* 同号应答卡:从右归来合拢(已合拢的常态——错类型卡是另一次尝试,不顶掉它) */} + {/* 同号应答卡:从右归来合拢(已合拢的常态——错类型卡是另一次尝试,不顶掉它)。 + 轨下行,与请求卡(轨上行 RAIL_Y-104)分带,见上方注释。 */}
0 && bounceT <= 0 ? 1 : bounceT > 0 ? 1 : 0, zIndex: 2, }} @@ -207,8 +219,12 @@ const HandshakeRail: React.FC<{
) : null} - {/* 状态表:pending → approved/rejected(右下) */} -
+ {/* 状态表:pending → approved/rejected(右下)。 + 2026-08 实拍修:本组件底部三样东西原本挤在 388..560 —— 状态表(388..500)、 + 注记(450)、以及 3-C 里同层挂载的门闸块(bottom:196 ⇒ 局部 494..624)。 + 注记被状态表压印(f10716/f11069 坐实)。这里把状态表整体上提到 356, + 腾出 468..494 给注记,门闸块以下不动。 */} +
{'状态表'}
{[ @@ -238,7 +254,10 @@ const HandshakeRail: React.FC<{ ))}
-
+ {/* 2026-08 实拍修:这行注记原挂 RAIL_Y+200=450,被 top:388 的状态表整条压住 + (f10716/f11069 坐实)。状态表已上提到 356(下沿 468),注记落在 472—— + 再往下 494 起是 3-C 的门闸块,故这 26px 是本组件唯一可用空档。 */} +
{'同一个编号 · 隔着信箱与轮次,编号就是暗号'} @@ -606,8 +625,15 @@ const ThreeWay: React.FC<{askAt: number; replyAt: number; castAt: number; settle }); if (t <= 0) return null; const y = 190 + i * 96; - const stopX = i === 0 ? 1180 : i === 1 ? 320 : 750; - const fromX = i % 2 === 0 ? 320 : 1180; + // 2026-08 实拍修:原 stopX 取 320/1180,卡宽 340 居中 ⇒ 左沿 150 / 右沿 1350, + // 直接骑在两端的环+铭牌块上(领队 x 90..290、阿强 x 1210..1410),实拍 f11693 + // 里「阿强 同意」整条盖住领队铭牌。这里把飞行走廊夹在两端块之间: + // 左界 490(卡左沿 320,离领队右沿 290 留 30px)、右界 1010(卡右沿 1180, + // 离阿强左沿 1210 留 30px)。方向即语义(谁发给谁)保持不变。 + const CORRIDOR_L = 490; + const CORRIDOR_R = 1010; + const stopX = i === 0 ? CORRIDOR_R : i === 1 ? CORRIDOR_L : 750; + const fromX = i % 2 === 0 ? CORRIDOR_L : CORRIDOR_R; const x = fromX + (stopX - fromX) * t; const e = spring({frame: frame - m.at, fps, config: {damping: 200}}); return ( diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx index c0369bb4..d8280af2 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx @@ -262,13 +262,16 @@ const HeartbeatTwoLooks: React.FC<{beatAt: number; mailAt: number; boardAt: numb
- {/* 心跳外圈脉冲 */} + {/* 心跳外圈脉冲。 + 2026-08 实拍修:原半径 120→146 以环心(120,120)为心,最大时下沿到 y=266, + 而铭牌自环底(240)+marginTop(8) 起画,脉冲圈整条横穿「阿珍」铭牌 + (f12622 坐实)。半径收到 96→114:最大下沿 234,落在环内,不再越到铭牌带。 */} {pulse > 0 ? ( + {/* 2026-08 实拍修:叉章原用 absolute + translate(-50%,-55%) 盖在文字正中, + 「领队席:空」被 deny 圆叉切成两半、中间三字读不出(f15662 坐实)。 + 改为叉章在上、文字在下的竖排——语义(这一席被否掉)不变,两者不再压印。 */}
- {'领队席:空'} - + + {'领队席:空'}
) : null} @@ -1065,11 +1070,19 @@ const ForemanToManager: React.FC<{swapAt: number; cardsAt: number}> = ({swapAt,
{'包工头'} diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx index 85bb367e..4f713121 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P5Desks.tsx @@ -271,29 +271,41 @@ const ParallelDesks: React.FC<{growAt: number; bounceAt: number; tieAt: number}> style={{ position: 'absolute', left: 620 + badNear * 180 - badBack * 320, - top: 90, + // 顶带(40..135):与下方登记卡(180..232)分带,见本组件竖向预算注释 + top: 40, opacity: 1, transform: `rotate(${badBack * -12}deg)`, }} > - 0.2 ? theme.deny : theme.panelBorder} style={{width: 360, padding: '12px 16px'}}> + 0.2 ? theme.deny : theme.panelBorder} style={{width: 430, padding: '12px 18px'}}>
0.2 ? theme.deny : theme.text}}> {'../../etc/passwd'}
-
+
{'只许字母数字点横线——路径越狱被弹回'}
) : null} - {/* 登记虚线:任务卡与桌子卡之间(状态格不动) */} + {/* 登记虚线:任务卡与桌子卡之间(状态格不动)。 + 虚线从登记卡下沿(232)垂到抽屉上沿(300),与闸带(bottom:344 ⇒ 局部 556 起)不相交。 */} {tie > 0 ? ( /> /> ) : null} - {/* 任务卡 + 状态格不动注记(底部) */} + {/* 任务卡 + 状态格不动注记。 + 2026-08 实拍修:原 top:580 落在 repo 底座(局部 ~646..720)之上, + 实拍 f17456 里「T-02 接口」整条压在底座文字上。改挂到抽屉带上方 + (180..232)——本组件竖向预算:40 名字卡 · 180 登记卡 · 300 抽屉 · + 556 四道闸(FourGates bottom:344)· 646 repo 底座,五带互不相交。 */} {tie > 0 ? (
+ {/* 2026-08 实拍修:标签跟着收束中的光圈走,vision→1 时半径收到 150, + 标签落到 y=162——正压在桌面板(top:150)的上沿里,被面板背景切掉 + 上半截(f18500/f18752 坐实)。改为钉在桌面板上方的固定行(y=118), + 不再随半径浮动;光圈仍收束,语义不变。 */} - {/* 保留门 */} -
+ {/* 保留门。 + 2026-08 实拍修:门卡原宽 240,两张卡的副标题(「分支留着 · 等人审查合并」 + 12 字 / 「明说「丢弃改动」后才开」11 字)都要折行,且都在末尾断出一个 + 孤字(「并」「开」)挂在第二行——实拍 f18500 里两张卡下沿都拖着一行单字。 + 加宽到 280 让副标题各自单行落定(右列总宽 280×2+34=594,右边距 180, + 左沿 1146,仍在桌面板 250..710 之外)。 */} +
{/* 门形图标:双开门 */} @@ -521,8 +546,8 @@ const DeskHygiene: React.FC<{visionAt: number; doorsAt: number; sealAt: number;
- {/* 删除门:被 deny 封条挡 */} -
+ {/* 删除门:被 deny 封条挡(宽度同保留门,见上方注释) */} +
{sealed && !torn ? ( - - - + + + = ({
- {/* 插头:自右向左滑向工具池的空插口(px 推导:pin1 对准第 2 行第 1 格中心 ≈ x 281) */} + {/* 插头:自右向左滑向工具池的空插口(px 推导:pin1 对准第 2 行第 1 格中心 ≈ x 281)。 + 2026-08 实拍修:原 top:340 让插头本体(svg 局部 y 30..100 ⇒ 绝对 370..440) + 与插脚(y 12..30 ⇒ 352..370)一起压在空插口格(工具池 top:200,第 2 行格 + 约 306..370)上,落座后「别人造的」四字整块盖住「空插口/接上了」(f19947 坐实)。 + 下移到 388:插脚顶端 400 贴着插口格下沿 370 之外 30px,插头本体落在 + 工具池(≤370)与铭牌(≥480)之间的空带里,「插进去」的语义靠插脚指向保持。 */}
0 ? 1 : 0, }} > @@ -779,8 +809,13 @@ const FourGates: React.FC<{gatesAt: number}> = ({gatesAt}) => { ]; return ( - {/* 四道闸横排:上移到中带下沿(避免压住 repo 底座与 Footnote 双行区,2026-08 实拍修) */} -
+ {/* 四道闸横排:上移到中带下沿(避免压住 repo 底座与 Footnote 双行区,2026-08 实拍修)。 + ⚠️ FourGates 与 ParallelDesks 是同一 Sequence 下的两个兄弟 AbsoluteFill, + 几何互不可见——bottom 必须按 ParallelDesks 的 repo 底座实测反推:底座容器 + 1600×720 居中(顶 180),底座 bottom:60 ⇒ 绝对 766..840。闸卡最高一张(形状闸 + 带第三行)约 111px,故 bottom 需 ≥ 324 才能让闸底(1080-bottom)落在 766 之上。 + 268 时闸底 812 侵入底座 46px,实拍 f17456 坐实压字;这里取 344 留 26px 余量。 */} +
{gates.map((g, i) => { const e = spring({frame: frame - gatesAt - i * 9, fps, config: {damping: 150}}); if (e <= 0) return null; diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx index 27814526..8f58f32b 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P6Finale.tsx @@ -692,14 +692,19 @@ const WhoHoldsPlan: React.FC<{ })}
) : null} - {/* 收官反转 */} + {/* 收官反转。 + 2026-08 实拍修:原 bottom:-46 把这句推到容器**外**(容器 1760×640 居中 + ⇒ 顶 220、底 860,故绝对 y≈906),正撞上同一 Sequence 里 Footnote 的 + bottom:168(绝对 y≈912)——两串字逐字压印成糊团(f22375/f21917 坐实, + 源码里「叠印不冲突」的注释被实拍证伪)。resume 条带下沿约 802, + 改挂 bottom:12(绝对 y≈848)落在 802 与 Footnote 之间的空带里。 */} {twist > 0 ? (
) : null}
+ {/* 角标留在 slot=0(bottom:168 ⇒ 元素底 912),与上方反转句(848)差 64px。 + ⚠️ 勿改 slot=1:206 对应元素底 874,反而会撞上反转句。 */} {'四形态对比·六模式选二·resume 重放 —— 官方文档 workflows'} diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/components/cards.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/components/cards.tsx index b1f76e30..6851b493 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/components/cards.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/components/cards.tsx @@ -2,7 +2,11 @@ import React from 'react'; import {AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig} from 'remotion'; import {theme} from '../design/theme'; -/** 金句卡:衬线大字居中,可附英文原文与出处 */ +/** 金句卡:衬线大字居中,可附英文原文与出处。 + * ⚠️ 64px 衬线大字在 1600px 内容宽里只放得下约 24 个全角字;超长金句会被浏览器 + * 在**任意**字符处折行——「规划是能力,不」/「是功能」这种把词劈成两半的断法 + * (2026-08 帧检 f05059 实拍)。这里按「——」这个语义断点主动分行: + * 破折号本就是金句的中缝,在它处换行既消除坏断字,也让两半各自成句。 */ export const QuoteCard: React.FC<{ zh: string; en?: string; @@ -12,6 +16,10 @@ export const QuoteCard: React.FC<{ const frame = useCurrentFrame(); const {fps} = useVideoConfig(); const enter = spring({frame, fps, config: {damping: 200}}); + // 「——」处切分:破折号留在上半句末尾(读感与口播一致) + const zhLines = zh.includes('——') + ? zh.split('——').map((part, i, arr) => (i < arr.length - 1 ? `${part.trim()} ——` : part.trim())) + : [zh]; return (
@@ -24,7 +32,9 @@ export const QuoteCard: React.FC<{ lineHeight: 1.5, }} > - {zh} + {zhLines.map((line, i) => ( +
{line}
+ ))}
{en ? (
- {/* 残影:滚出可视区的行停在顶端变 dim(0-A 的「被挤走」) */} - {ghostO > 0 && ghostLine ? ( -
- {ghostLine} + {/* 残影行:滚出可视区的行停在顶端变 dim(0-A 的「被挤走」)。 + ⚠️ 此前残影是绝对定位、不随 scrollShift 走,而行区上移 56px 后第二行正好 + 爬到同一条基线 —— 「任务:把文件名统一改成 snake_case」与「已改 3 个文件, + 跑测试 → 2 个失败」两串汉字逐字穿插成一团糊字(2026-08 帧检 f00273 实拍)。 + 改为在行区**上方独占一行**(高度由 ghostLine 是否传入决定,静态 prop 驱动、 + 不随帧跳动),残影与活字不再共占基线。 */} + {ghostLine ? ( +
+ {ghostO > 0 ? ( +
+ {ghostLine} +
+ ) : null}
) : null} -
- {lines.map((ln, i) => { - const shown = Math.max(0, Math.floor(((frame - ln.delay) / fps) * cps)); - if (shown <= 0) return null; - const isLast = i === lines.length - 1; - const done = shown >= ln.text.length; - return ( -
- {ln.prompt ? ( - {ln.prompt} - ) : null} - {ln.text.slice(0, shown)} - {isLast && done ? ( - - ) : null} -
- ); - })} + {/* 行区自带裁剪窗:scrollShift 上移的首行必须**真的被裁掉**,否则它会溢出到 + 上方 title bar 上把「zsh」标题压成叠字(同帧 f00273 实拍)。 */} +
+
+ {lines.map((ln, i) => { + const shown = Math.max(0, Math.floor(((frame - ln.delay) / fps) * cps)); + if (shown <= 0) return null; + const isLast = i === lines.length - 1; + const done = shown >= ln.text.length; + return ( +
+ {ln.prompt ? ( + {ln.prompt} + ) : null} + {ln.text.slice(0, shown)} + {isLast && done ? ( + + ) : null} +
+ ); + })} +
diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx index f5a20f63..c33e70fc 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P1Plan.tsx @@ -450,7 +450,13 @@ const PlanGate: React.FC<{ left: -18, top: -120 * glass, width: 336, - height: 200, + // 罩体须整体盖住下方 Panel,否则罩沿会把卡里的某一行字拦腰切断。 + // 帧上量得(f04612 全分辨率):罩顶 y=220、文件卡 y=340..499, + // 卡内四行文字末行「不动一行」占 453..474。 + // 200px → 罩沿 420 切「读结构」那行;236px → 罩沿 456 正好切「不动一行」 + // (两轮实拍先后坐实)。罩高须 ≥ 499-220=279 才能整体罩住卡体, + // 取 300 让罩沿落到卡下沿之下 21px 的空白处。 + height: 300, border: `3px solid ${theme.mech}`, borderRadius: '12px 12px 0 0', background: 'rgba(255,255,255,0.08)', @@ -482,7 +488,10 @@ const PlanGate: React.FC<{ style={{ position: 'absolute', left: 760 - travel * 220 - bounce, - top: 250, + // 计划卡(left:560 top:100,实测高 ~160)下沿落在 y≈260;此前 top:250 + // 让「[edit] 改文件」动作块正压在「③ 标注风险点」那一行上 + // (2026-08 帧检 f4612 实拍)。下移到 300 走计划卡下方的空带。 + top: 300, opacity: travel > 0.05 ? 1 : 0, }} > diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx index 8ab72053..b344ec76 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx @@ -158,10 +158,14 @@ const SideDeskSlidesOut: React.FC<{slideAt: number; flyAt: number; cleanAt: numb >
+ {/* 桌名与 MiniDeskWithRing 内部的 messages[] 角标(absolute bottom:-32)同处 + 桌下一带:marginTop:12 时两者压成「messages[] = [任务说明]」穿过「副桌 + (分身的干净桌面)」的三层叠字(2026-08 帧检 f06327 实拍)。 + 角标占 bottom:-32 一行,桌名下压到 52 走它的下一行。 */}
- {/* 共享抽屉:虚线双桌共连,盖半开、两端各画一只手同时拉开 */} -
+ {/* 共享抽屉:虚线双桌共连,盖半开、两端各画一只手同时拉开。 + ⚠️ 抽屉曾与三只笼子(旧 top:368)几乎同高:笼子一落下就把抽屉里的 + 「读过的文件(readFileState)」拦腰盖成「读…」两个残字 + (2026-08 帧检 f09998 / f10089 实拍)。现在三段各自成行: + 笼子排 336..427、抽屉 455..585、底部压字 ~605。 */} +
0 && bubble < 1 ? ( + {/* 路径终点跟随卡片终点(left:150 + 半卡宽 165 ≈ 315,top:120 + 半卡高 ≈ 175) */} ) : null} + {/* 冒泡终点须**落进父亲桌内**(桌体 left:40..560、top:40..320): + 此前终点 left≈570 / top≈120,卡(宽 330)横跨在桌右缘 560 上, + 半张卡悬在两桌之间的空档里,卡底还伸出桌下沿(2026-08 帧检 f09998 实拍)。 + 收到 left:120 后卡左缘(120)虽已进桌,但卡底仍压着桌下沿(重渲复检坐实)。 + 终点定为 left:150 / top:120:卡体 150..480 × 120..~230, + 四边都留在父亲桌内,语义(冒泡到父亲屏幕)反而更准。 */} {bubble > 0 ? (
) : null} - {/* p2-28a..c 三只笼子:在场上限 20 / 轮数上限 / 上下文配额(Harness Engineering 改造) */} + {/* p2-28a..c 三只笼子:在场上限 20 / 轮数上限 / 上下文配额(Harness Engineering 改造)。 + 笼子排上移到 336(两桌下沿 320 之下、抽屉顶 455 之上),与抽屉互不压字。 */} {frame >= cagesAt ? (
= ({ key={c.name} style={{ position: 'absolute', - left: i * 90, + // 卡宽 300 而步进只有 90 → 后一张盖掉前一张 70% 的卡面, + // 三张卡的 name/use/token 三行互相压字(2026-08 帧检 f11390 实拍)。 + // 步进放到 215:仍保留「叠成一摞」的层次,但每张的文字带完整露出, + // 且卡排右缘(240+430+300=970)不撞右侧厚手册卡的左缘(1020)。 + left: i * 215, top: i * 26, transform: `rotate(${ang}deg) translateY(${(1 - fan) * 60}px)`, opacity: fan, + zIndex: i, }} >
{'评测计分板'}
- {/* 数字纹丝不动:只呈现「不变」本身,不虚构具体分数 */} + {/* 数字纹丝不动:只呈现「不变」本身,不虚构具体分数。 + ⚠️ 占位符曾写作全角破折号「— . —」:等宽字体里这三个字符渲染成 + 两根粗横杠夹一个小方点,读者看到的是三块无意义的色块而非「某个分数」 + (2026-08 帧检 f14477 实拍)。改用等宽数字占位符 ##.#, + 「有个分数、但具体值不重要」的语义反而立住,且不虚构任何数字。 */}
- {'— . —'} + {'##.#'}
{'= 削层前'}
diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx index 746047c0..c98d27b7 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx @@ -35,7 +35,11 @@ const Ladder: React.FC<{drop: number; labels?: [string, string, string]}> = ({dr {labelsOn[i] ? ( - + // 标签压在梯级正上方、与左梯柱左对齐。此前贴在梯右侧(x=235)时, + // 「一级 · 话没说完」这类 7 字标签会横穿到各镜内容面板的左缘 + // (TierOne/Two/Three 的 left:380),被面板不透明底色整段裁掉—— + // 2026-08 帧检在 f16263 / f17221 / f18449 三处实拍坐实。 + {labelsOn[i]} ) : null} @@ -441,7 +445,10 @@ const TierThree: React.FC<{warnAt: number; waitAt: number; flipAt: number; jitte style={{ position: 'absolute', left: maxW - 120, - top: -18, + // 上一行右端是同色的 36px「32s」读数(baseline 对齐在 y≈-24), + // top:-18 会让这枚角标与读数叠成「封顶 32s / 32s」一团 + // (2026-08 帧检 f18449 实拍)。改挂到条身下方。 + top: 70, fontFamily: theme.mono, fontSize: 20, color: theme.deny, @@ -672,7 +679,10 @@ const NoRetrySplit: React.FC<{ transform: `translateY(${(1 - cert) * 18}px)`, }} > - +
@@ -685,26 +695,46 @@ const NoRetrySplit: React.FC<{
{'TLS · 第一帧即报错'}
- {/* 红叉:滑入即打 */} + {/* 否决标记:滑入即打。 + ⚠️ 此前是一枚 120px 红叉挂在 left:-34 / top:-20 —— 叉心正落在卡内的证书 + 图标上,两条粗笔画(strokeWidth 9)把图标涂成一团,叉的左上角还顶进上方 + 「不重试」牌子(2026-08 帧检 f19098 实拍)。改画整卡叉之后仍横穿 + 「证书对不上 / TLS · 第一帧即报错」两行字(重渲 f19098 复检坐实)。 + 最终改为**卡右侧留白处的独立否决角标**:不覆盖任何文字, + 「这张卡被否掉」由 deny 色边框 + ✕ 角标共同表达。 */} {certX ? ( - - - - - - + }), + }} + > + {'✕'} +
) : null} + {/* 压字宽度须收在证书卡宽(300)内:此前这行单行不折、实际铺到 x≈700 以外, + 被中央「[bash] pytest -k perf」卡(left:700)挡掉尾字,画面读成 + 「退避一百遍也—」(2026-08 帧检 f19098 实拍)。限宽 + 允许折行。 */} {certX ? ( -
+
{'那是要你去修的 —— 退避一百遍也一样'}
) : null} @@ -810,8 +840,13 @@ const NoRetrySplit: React.FC<{
) : null}
- {/* 右下:计数器 1→2(分裂时滚动) */} -
+ {/* 右上:计数器 1→2(分裂时滚动)。 + ⚠️ 此前挂在 right:90 / top:380,与下方刻度盘组(right:110 / bottom:190 + → 实占 y 560..710、x 1260..1630)在 y 560..640 这段同时在场: + 58px 的红色「2」正压在刻度盘右侧的「默认最多重试 10 次」上 + (2026-08 帧检 f19570 实拍)。移到容器右上的空带(top:20 → y 200..290), + 与下方输出面板(y 330 起)仍留 40px。 */} +
{'动作计数'}
@@ -937,8 +972,15 @@ const Diminishing: React.FC<{ ) : null} - {/* 「停」章落下 */} - + {/* 「停」章落下。 + ⚠️ 阈值标线的压字「增量 < 500 token」是右对齐挂在 y = H-60-0.5*(H-140)-12 + ≈ 240 这条线上的;章此前落在 right:130 / top:130(章心 y≈205、半径 75), + 正好把那行字连同虚线一起罩进章圈,读成「增量 停 500 token」 + (2026-08 帧检 f20097 实拍)。移到 top:300 后又骑上了 x 轴(y=H-60=400) + 与「续写次数 →」轴标(重渲复检坐实)。 + 最终落点 right:150 / top:270:章心 y≈345,稳居标线(240)与 x 轴(400) + 之间的空带,上下各留 ~30px 余量。 */} +
{/* p4-21a/b 官方检查点回退:改动可回退,但只含文件改动——命令与外部状态不在其中 */} {frame >= ckptAt ? ( diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P5Ring.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P5Ring.tsx index 9b2b2e50..152778af 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P5Ring.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P5Ring.tsx @@ -154,11 +154,21 @@ const RingFloatsForward: React.FC<{floatAt: number; hooksAt: number; footnoteAt: const recede = outline; return ( - {/* 桌子 + 五装置:线稿化退后 */} + {/* 桌子 + 五装置:线稿化退后。 + 环与卡默认都居中于同一个 AbsoluteFill,故必须**一升一降**才拉得开: + 原始下沉量 recede*40 太小,环(size 520)浮到中央后 0°/180° 两侧的 + 「看回答」「填回结果」标签正落在卡的标题行上(f21908 / f22050 实拍); + 只把卡下沉到 210 仍不够——帧上量得环含底部「执行工具」标签铺到 y≈800, + 而卡排 684..815、字幕条自 y≈884 起,卡已无处可退(重渲复检坐实)。 + 现在改为:环整体上提 130(见下方 translateY),卡下沉 240。 + 三轮实测定标:环上提 130 后环底 y=623、底部「执行工具」标签占 648..669; + 卡排基位(recede=0)474..605,下沉 240 → 714..845; + 与标签留 45px、与角标(top ≈ 882)留 37px。环再往上会让顶部「问模型」 + 标签撞到页眉横线(y≈124),故只能靠卡下沉补足这一段。 */}
@@ -175,12 +185,14 @@ const RingFloatsForward: React.FC<{floatAt: number; hooksAt: number; footnoteAt: ))}
- {/* 环:从桌后浮到画面中央(第二次出场) */} + {/* 环:从桌后浮到画面中上部(第二次出场)。 + rise 完成后额外上提 130px(-130 * rise),把环连同它的四个节点标签 + 抬离下方卡排所在的带(见上方注释的实测坐标)。 */}
0.98 ? dot : undefined} showExit={false} /> @@ -194,9 +206,11 @@ const RingFloatsForward: React.FC<{floatAt: number; hooksAt: number; footnoteAt: {[0, 1, 2, 3, 4].map((i) => { // 桌组:1130px 宽居中于 1920 → 左缘 395;每桌 210 + 间隙 20 const x = 395 + i * 230 + 105; - const y = 700; + // 挂钩两端都必须跟着走位:起点跟卡排的 recede 下沉(translateY(recede*240)), + // 终点跟环的上提(translateY(-rise*130));否则虚线会挂在空气里。 + const y = 610 + outline * 240; const cx = 960; - const cy = 540; + const cy = 540 - rise * 130; // 逐条描出(stagger i×6 帧,p5-09 起):先实线描出(dash 长度 0→满), // 描满后切为虚线挂钩(pathLength=1 归一化,dashoffset 不参与) const drawT = interpolate(frame - hooksAt - i * 6, [0, 18], [0, 1], { From ddd6d816e902f0aa43b32db4a05b6bfba039ab7c Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sat, 29 Aug 2026 11:45:11 +0800 Subject: [PATCH 36/41] =?UTF-8?q?feat(video):=20=E7=BB=88=E6=B8=B2=20v4=20?= =?UTF-8?q?=E4=BA=A4=E4=BB=98=E2=80=94=E2=80=94W8=20=E5=B8=A7=E7=BA=A7?= =?UTF-8?q?=E5=AE=A1=E6=9F=A5=2049=20=E5=A4=84=E4=BF=AE=E5=A4=8D=E5=85=A8?= =?UTF-8?q?=E9=83=A8=E8=90=BD=E6=B8=B2=EF=BC=8C=E5=9B=9E=E5=BD=92=2052=20?= =?UTF-8?q?=E5=B8=A7=E5=85=A8=E5=87=80;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 52 个修复帧位回归(像素检测)+ 3 个最严重缺陷帧视觉模型复验(矩阵×回捞分区、 收官金句×角标分离、辐条无穿字)+ 五集七幕体检 FAIL 0 · WARN 0。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- apps/negentropy-influence/series.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/negentropy-influence/series.json b/apps/negentropy-influence/series.json index a84a3f40..14057f83 100644 --- a/apps/negentropy-influence/series.json +++ b/apps/negentropy-influence/series.json @@ -102,7 +102,7 @@ "accessed": "2026-08-21" }, "status": "delivered", - "statusNote": "终渲 v3:14:11 = 25541 帧 @30fps(167 句)· 47.1 MB;叙事去对照化(16 句直陈框架)+ 金句卡升维;七幕 FAIL 0 · WARN 0", + "statusNote": "终渲 v4:14:11 = 25541 帧 @30fps · 47.1 MB;W8 帧级审查 892 帧 60 缺陷 49 修(SceneTag 叠印根因+越窗+穿字);回归 52 帧全净", "voice": "sunny-steady + me-bright.wav" }, { @@ -124,7 +124,7 @@ "accessed": "2026-08-22" }, "status": "delivered", - "statusNote": "终渲 v3:13:27 = 24215 帧 @30fps(139 句)· 42.7 MB;叙事去对照化(10 句)+ 金句卡升维;七幕 FAIL 0 · WARN 0", + "statusNote": "终渲 v4:13:27 = 24215 帧 @30fps · 42.7 MB;W8 修复 9 处(终端糊字/金句劈行母题级修复等);回归 11 帧全净", "voice": "sunny-steady + me-bright.wav" }, { @@ -146,7 +146,7 @@ "accessed": "2026-08-22" }, "status": "delivered", - "statusNote": "终渲 v3:13:36 = 24492 帧 @30fps(146 句)· 41.7 MB;叙事去对照化(13 句);七幕 FAIL 0 · WARN 0", + "statusNote": "终渲 v4:13:36 = 24492 帧 @30fps · 41.7 MB;W8 修复 7 处(矩阵×回捞桌 24 秒叠印/死代码根因);回归 7 帧全净", "voice": "sunny-steady + me-bright.wav" }, { @@ -168,7 +168,7 @@ "accessed": "2026-08-22" }, "status": "delivered", - "statusNote": "终渲 v3:13:09 = 23672 帧 @30fps(139 句)· 44.7 MB;金句卡升维(无口播改动);七幕 FAIL 0 · WARN 0", + "statusNote": "终渲 v4:13:09 = 23672 帧 @30fps · 44.7 MB;W8 修复 11 处(SceneTag 残留 10 处/天平重印等);回归 10 帧全净", "voice": "sunny-steady + me-bright.wav" }, { @@ -190,7 +190,7 @@ "accessed": "2026-08-22" }, "status": "delivered", - "statusNote": "终渲 v3:13:26 = 24197 帧 @30fps(139 句)· 47.2 MB;叙事去对照化(10 句);七幕 FAIL 0 · WARN 0", + "statusNote": "终渲 v4:13:26 = 24197 帧 @30fps · 47.2 MB;W8 修复 14 处(四道闸压底座/收官金句×角标压印等);回归 14 帧全净", "voice": "sunny-steady + me-bright.wav" } ] From b207da61a5b171ace4955ea9a7f6038f9e1939d3 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sat, 29 Aug 2026 18:16:59 +0800 Subject: [PATCH 37/41] =?UTF-8?q?feat(video):=20W9=20=E7=88=86=E6=AC=BE?= =?UTF-8?q?=E7=BB=88=E7=A3=A8=E2=80=94=E2=80=94=E6=96=87=E6=A1=88=20122=20?= =?UTF-8?q?=E5=8F=A5=E6=B5=81=E7=95=85=E5=BA=A6=E6=B6=A6=E8=89=B2=20+=20?= =?UTF-8?q?=E8=A7=86=E8=A7=89=E4=B8=89=E5=AF=86=E5=BA=A6=E5=85=A8=E6=89=AB?= =?UTF-8?q?=2013=20=E5=A4=84=E4=BF=AE=E5=A4=8D;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 文案(句 id/句序零变动):EP1 9 / EP2 42 / EP3 19 / EP4 21 / EP5 31 句——接缝/拗口/ 超长/笔误/冗余;字数全收敛。视觉(每镜首中尾 602 帧):EP5 沙箱镜整镜 21.6s 右侧 全空根因修复;EP2 5 处;EP3 5 处死空气;EP4 2 处。全门禁绿,122 句重配中。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../script/narration.json | 42 +++++----- .../script/narration.md | 42 +++++----- .../video/src/scenes/P0Wait.tsx | 24 +++--- .../video/src/scenes/P1Dereg.tsx | 5 +- .../video/src/scenes/P2Rejoin.tsx | 75 ++++++++++++++++- .../video/src/scenes/P5Truths.tsx | 5 +- .../video/src/scenes/P6Ending.tsx | 5 +- .../script/narration.json | 18 ++-- .../script/narration.md | 18 ++-- .../video/src/scenes/P1Loop.tsx | 8 +- .../video/src/scenes/P3Gates.tsx | 37 ++++++-- .../video/src/scenes/P5Stack.tsx | 22 ++++- .../script/narration.json | 38 ++++----- .../script/narration.md | 38 ++++----- .../script/narration.json | 62 +++++++------- .../script/narration.md | 62 +++++++------- .../script/narration.json | 84 +++++++++---------- .../script/narration.md | 84 +++++++++---------- 18 files changed, 396 insertions(+), 273 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json index c0dfda7d..b7802815 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json @@ -42,7 +42,7 @@ { "id": "p0-09", "scene": "P0", - "text": "而且它不光感觉不到时间,还不会自己安排等待。" + "text": "先说清它缺什么:不光感觉不到时间,也不会自己安排等待。" }, { "id": "p0-10", @@ -62,7 +62,7 @@ { "id": "p0-13", "scene": "P0", - "text": "每一步都有真话要讲,也有坑要躲。先从第一种开始。" + "text": "每一步都有真话要讲,也有坑要躲。这就开拆。" }, { "id": "p1-01", @@ -87,7 +87,7 @@ { "id": "p1-05", "scene": "P1", - "text": "三类例外照停:睡觉命令、带着 git 的命令、拆不成简单命令的。" + "text": "三类例外照停:睡觉的、带 git 的、拆不成简单命令的。" }, { "id": "p1-06", @@ -117,7 +117,7 @@ { "id": "p1-11", "scene": "P1", - "text": "这里有个容易被想岔的点,有人拆过它的源码,说了句大实话:" + "text": "这里有个容易被想岔的点。有人拆过它的源码,一句话说穿了:" }, { "id": "p1-12", @@ -167,12 +167,12 @@ { "id": "p1-21", "scene": "P1", - "text": "还有个身份问题要交代:后台线程是「守护」身份,前面说过主人退场它退场。" + "text": "「守护」这个身份,前面只说了一半,还有反过来的一半:" }, { "id": "p1-22", "scene": "P1", - "text": "反过来也一样:它还活着,后台就一直在。你中途想问进度、想停掉,都行——" + "text": "只要它还活着,后台就一直在。你中途想问进度、想停掉,都行——" }, { "id": "p1-23", @@ -212,7 +212,7 @@ { "id": "p2-06", "scene": "P2", - "text": "递进去的时机也有讲究。有人拆过它的源码——队列其实分两级:" + "text": "递进去的时机也是设计过的。有人拆过它的源码——队列其实分两级:" }, { "id": "p2-07", @@ -257,7 +257,7 @@ { "id": "p2-15", "scene": "P2", - "text": "每批工具干完,小模型顺手贴一张三十字的标签,像提交说明。" + "text": "不论哪一种,每批工具干完,小模型都顺手贴一张三十字的标签,像提交说明。" }, { "id": "p2-16", @@ -297,12 +297,12 @@ { "id": "p2-23", "scene": "P2", - "text": "第一层讲完了:活出去了,人不用等,它也没停。秩序不因为异步而乱。" + "text": "活出去了,人不用等,循环也没停。可丢出去的活,真就没人盯着了吗?" }, { "id": "p3-01", "scene": "P3", - "text": "后台还有个可爱的设计,有人管它叫看门狗。" + "text": "有,还怪可爱的——有人管它叫看门狗。" }, { "id": "p3-02", @@ -352,7 +352,7 @@ { "id": "p3-09b", "scene": "P3", - "text": "简单,但空跑也是钱;另一条是事件传送带——活儿一出结果就自己滚过来," + "text": "简单,但空跑也是钱;另一条是事件传送带——活一出结果就自己滚过来," }, { "id": "p3-09c", @@ -412,7 +412,7 @@ { "id": "p4-11", "scene": "P4", - "text": "谁来看表?一个独立的小闹钟线程,每秒看一眼;到点了,把活塞进队列。" + "text": "谁来看表?一个独立的小闹钟线程,每秒看一眼;到点了,把活丢进队列。" }, { "id": "p4-12", @@ -422,7 +422,7 @@ { "id": "p4-13", "scene": "P4", - "text": "同一分钟绝不重复,第二天也不会因为记性差而跳过。" + "text": "同一分钟绝不重复;到了第二天,同一个点照样准时。" }, { "id": "p4-14", @@ -432,7 +432,7 @@ { "id": "p4-15", "scene": "P4", - "text": "队列这头还有一道闸:只有队列里有活、且它正闲着,闸才开,把活递进循环。" + "text": "队列这头还有一道闸:里面有活、它又正闲着,闸才开,把活递进循环。" }, { "id": "p4-16", @@ -467,12 +467,12 @@ { "id": "p4-22", "scene": "P4", - "text": "三档各管一段:真要关机也跑的上云端;只在本机的用桌面;" + "text": "怎么选,看这活要撑多久:撑过关机的上云端;" }, { "id": "p4-23", "scene": "P4", - "text": "只在这场对话里有意义的,跟着会话走,散场即清空。" + "text": "只撑过这场对话的,用桌面;剩下的,散场就清空。" }, { "id": "p4-24", @@ -492,7 +492,7 @@ { "id": "p4-27", "scene": "P4", - "text": "解耦落到这儿就一句话:谁都不必知道对方在忙什么。" + "text": "说到底就一句:谁都不必知道对方在忙什么。" }, { "id": "p5-01", @@ -532,7 +532,7 @@ { "id": "p5-08", "scene": "P5", - "text": "排查问题的人永远说不准它到底几点响。确定性偏移,错峰而又可预测。" + "text": "排查的人永远说不准它到底几点响。确定性偏移,错峰又可预测。" }, { "id": "p5-09", @@ -567,7 +567,7 @@ { "id": "p5-15", "scene": "P5", - "text": "不需要任何终端活着;状态落盘,穿过自动更新与重启,睡眠唤醒会重连。" + "text": "关掉也丢不了:状态落盘,穿得过自动更新和重启,机器睡醒还会重连。" }, { "id": "p5-16", @@ -577,7 +577,7 @@ { "id": "p5-17", "scene": "P5", - "text": "行摘要也是一个小模型顺带写的——省着主模型的上下文。" + "text": "每条还配一行摘要,也是小模型顺带写的——省着主模型的上下文。" }, { "id": "p5-18", @@ -612,7 +612,7 @@ { "id": "p5-23a", "scene": "P5", - "text": "还有个更自由的拨法:让它自己给自己上发条——干完一轮,顺手定下一次," + "text": "补丁之外还有个自由的拨法:让它给自己上发条——干完一轮,顺手定下一次," }, { "id": "p5-23b", diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md index 9519893f..001e1b16 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md @@ -21,11 +21,11 @@ - [p0-06] 不会。按下启动去做别的,等它滴滴滴叫你。 - [p0-07] 这个动作拆开是两件事:活交给机器,人不陪着等。 - [p0-08] 这集就讲怎么把这两件事教给它:谁来按开始,谁来等。 -- [p0-09] 而且它不光感觉不到时间,还不会自己安排等待。 +- [p0-09] 先说清它缺什么:不光感觉不到时间,也不会自己安排等待。 - [p0-10] 官方管这个叫时间盲症:模型没有钟、没有闹钟、也没有「回头再看」的本能。 - [p0-11] 于是第一步,把「等」摘掉:按下就走开,活交给机器。 - [p0-12] 第二步更进一步:连按的人都可以不要,时间到了自己开始。 -- [p0-13] 每一步都有真话要讲,也有坑要躲。先从第一种开始。 +- [p0-13] 每一步都有真话要讲,也有坑要躲。这就开拆。 ## P1 按下就走开 @@ -37,13 +37,13 @@ - [p1-02] 谁来决定一件活要不要丢后台?主路是它自己—— - [p1-03] 跑命令的工具上有一个「后台执行」的开关,它勾了,活就走后台。 - [p1-04] 官方还有个真机制:命令到了超时线,不被杀掉,而是自动滑入后台接着跑。 -- [p1-05] 三类例外照停:睡觉命令、带着 git 的命令、拆不成简单命令的。 +- [p1-05] 三类例外照停:睡觉的、带 git 的、拆不成简单命令的。 - [p1-06] 活丢出去之后,画面上发生的事最值得看:那个循环,没有停。 - [p1-07] 慢命令块滑到环外的一条旁轨上自己跑;循环口立刻贴上一张占位条, - [p1-08] 意思是:这活派出去了,好了会叫你。然后循环接着转,去干下一件。 - [p1-09] 这个安排有个前提要交代:那个跑后台的活,是个「守护」的身份—— - [p1-10] 主人退场,它跟着退场。不会出现程序都关了、后台还在偷偷跑的情况。 -- [p1-11] 这里有个容易被想岔的点,有人拆过它的源码,说了句大实话: +- [p1-11] 这里有个容易被想岔的点。有人拆过它的源码,一句话说穿了: - [p1-12] 所谓后台,根本不是一个并行的宇宙。整套系统跑在单线程里, - [p1-13] 后台的真实含义,只是「这一步不等它了」。 - [p1-14] 等待被拿掉了,不是并发被造出来了。 @@ -53,8 +53,8 @@ - [p1-18] 对了,这个「自己勾后台」的设计本身也值得一句: - [p1-19] 谁最清楚一件活要跑多久?是读过命令、干过类似活的它自己。 - [p1-20] 让它自己判断,比任何外部规则都准。人的直觉是关键词,它的直觉是经验。 -- [p1-21] 还有个身份问题要交代:后台线程是「守护」身份,前面说过主人退场它退场。 -- [p1-22] 反过来也一样:它还活着,后台就一直在。你中途想问进度、想停掉,都行—— +- [p1-21] 「守护」这个身份,前面只说了一半,还有反过来的一半: +- [p1-22] 只要它还活着,后台就一直在。你中途想问进度、想停掉,都行—— - [p1-23] 后台不是泼出去的水,是拴着绳的风筝。 - [p1-24] 绳在手里,就还能问、还能停、还能改主意。这才叫敢丢出去。 @@ -69,7 +69,7 @@ - [p2-03] 一次调用,永远对应一条结果,这个配对关系不许破坏。 - [p2-04] 所以真结果回来时,不能冒充那条占位,它得换一个身份: - [p2-05] 变成一张完成通知,排进队列;下一轮跟别的结果合并成一条消息递进去。 -- [p2-06] 递进去的时机也有讲究。有人拆过它的源码——队列其实分两级: +- [p2-06] 递进去的时机也是设计过的。有人拆过它的源码——队列其实分两级: - [p2-07] 「下一轮」和「稍后」。后台完成的通知,默认排在「稍后」—— - [p2-08] 也就是说它不插队。你新输入的一句话,永远排在它的前面。 - [p2-09] 打个比方:门口的信箱。活干完往里投信,开不开箱,看主人何时路过。 @@ -78,7 +78,7 @@ - [p2-12] 话头被截走,它的思路也跟着跑了。排队,保护的是对话的完整性。 - [p2-13] 活不止一种:能丢后台的有七种——跑命令、本地分身、远程分身、 - [p2-14] 进程内队友、工作流、监控外接,还有个整理记忆的,名字叫做梦。 -- [p2-15] 每批工具干完,小模型顺手贴一张三十字的标签,像提交说明。 +- [p2-15] 不论哪一种,每批工具干完,小模型都顺手贴一张三十字的标签,像提交说明。 - [p2-16] 还有一层安心:你随时可以主动开信箱,问一句后台的活怎么样了。 - [p2-17] 它会把每条活的状态报给你:还在跑、跑完了、或者根本没这条活。 - [p2-18] 前面留的伏笔——占位条上的任务编号,现在派上用场了。 @@ -86,7 +86,7 @@ - [p2-20] 该把哪句「等它结果」的话补上,一查便知。账目永远平的: - [p2-21] 每次调用都有着落,要么当场给结果,要么占位再补通知。 - [p2-22] 对话这种东西,一旦有账对不上,后面全乱。 -- [p2-23] 第一层讲完了:活出去了,人不用等,它也没停。秩序不因为异步而乱。 +- [p2-23] 活出去了,人不用等,循环也没停。可丢出去的活,真就没人盯着了吗? ## P3 有一只狗盯着 @@ -94,7 +94,7 @@ > 对准输出线末端的「(y/n)」提示。 > 角标:watchdog · 45s 停滞检测 -- [p3-01] 后台还有个可爱的设计,有人管它叫看门狗。 +- [p3-01] 有,还怪可爱的——有人管它叫看门狗。 - [p3-02] 后台命令有时候会卡住——不是坏了,是它停下来问了个问题。 - [p3-03] 比如「要不要继续?」——然后干等一个等不来的回答。 - [p3-04] 所以有一只狗盯着每条后台命令的输出:四十五秒没有新动静,它就去看看, @@ -104,7 +104,7 @@ - [p3-08] 四十五秒一毫米都没动,才起身查看。不猜快慢,只看死活。 - [p3-09] 后台不是丢出去就不管了——丢出去的活,也有一双眼睛看着。 - [p3-09a] 看的方式,官方给了两条路:一条是轮询走廊——每隔一段回头问一次, -- [p3-09b] 简单,但空跑也是钱;另一条是事件传送带——活儿一出结果就自己滚过来, +- [p3-09b] 简单,但空跑也是钱;另一条是事件传送带——活一出结果就自己滚过来, - [p3-09c] 不空跑、不迟到。等得起就用走廊,等不起就上传送带。 ## P4 没人按的开始 @@ -123,23 +123,23 @@ - [p4-08] 读法就这么多,五格小抄,写清楚什么时候该干活。 - [p4-09] 还有两道保险。写表的时候就先验格式:写错的表直接拒收,进不了门。 - [p4-10] 从磁盘恢复旧表的时候也逐条检查,一条坏的跳过去,不影响其余的。 -- [p4-11] 谁来看表?一个独立的小闹钟线程,每秒看一眼;到点了,把活塞进队列。 +- [p4-11] 谁来看表?一个独立的小闹钟线程,每秒看一眼;到点了,把活丢进队列。 - [p4-12] 注意两个细节。一是每分钟只放一枪——它记着「这一分钟发过了」, -- [p4-13] 同一分钟绝不重复,第二天也不会因为记性差而跳过。 +- [p4-13] 同一分钟绝不重复;到了第二天,同一个点照样准时。 - [p4-14] 二是每个活自己兜底:一个坏任务出错,不会连累整张表停摆。 -- [p4-15] 队列这头还有一道闸:只有队列里有活、且它正闲着,闸才开,把活递进循环。 +- [p4-15] 队列这头还有一道闸:里面有活、它又正闲着,闸才开,把活递进循环。 - [p4-16] 为什么要绕这么一圈?直接到了点就地开工不行吗? - [p4-17] 不行。它可能正跟你聊到一半,硬插进去,一句话被拦腰截断。 - [p4-18] 队列的意义就是礼让:到点的活在门口排队,等它把手头的说完。 - [p4-19] 任务定义存哪?官方分三档:云端的例程,关机也跑、不碰本地文件; - [p4-20] 桌面定时,本机跨会话;会话内循环,新对话清空、只恢复没过期的。 - [p4-21] 老答案是用系统的定时表落盘——现在只是三档里的一档。 -- [p4-22] 三档各管一段:真要关机也跑的上云端;只在本机的用桌面; -- [p4-23] 只在这场对话里有意义的,跟着会话走,散场即清空。 +- [p4-22] 怎么选,看这活要撑多久:撑过关机的上云端; +- [p4-23] 只撑过这场对话的,用桌面;剩下的,散场就清空。 - [p4-24] 看表的不干活,干活的不看表,中间靠一条队列传话。生产和消费,解耦了。 - [p4-25] 这套分工听起来繁琐,但每一层都各改各的:表可以换格式,队列可以换实现, - [p4-26] 循环一无所知。牵一发而不动全身,这才有资格谈稳定。 -- [p4-27] 解耦落到这儿就一句话:谁都不必知道对方在忙什么。 +- [p4-27] 说到底就一句:谁都不必知道对方在忙什么。 ## P5 时间表的真话 @@ -153,23 +153,23 @@ - [p5-05] 妙的是迟到多少不是随机数——是按任务编号算出来的固定偏移。 - [p5-06] 同一个任务,每次迟到一样多;不同的任务,错开响。防踩踏,还不添乱。 - [p5-07] 为什么强调算出来、而不是随机?随机会漂——这次迟三秒,下次迟十秒, -- [p5-08] 排查问题的人永远说不准它到底几点响。确定性偏移,错峰而又可预测。 +- [p5-08] 排查的人永远说不准它到底几点响。确定性偏移,错峰又可预测。 - [p5-09] 顺带一提,一次性的活要是正好落在整点或半点,还会最多提前一分半触发, - [p5-10] 提前量也是算好的。跟整点人流反着走。 - [p5-11] 第二个真话:定时任务会自动退休。连续七天没动静的周期任务, - [p5-12] 到期自动删掉,删之前还会最后跑一次。忘了设的闹钟,不该响一辈子。 - [p5-13] 第三个真话最实在,也最容易踩坑:把进程关了,表就停了。 - [p5-14] 但官方给了新答案:后台会话由独立的管家进程托管,不怕终端关掉。 -- [p5-15] 不需要任何终端活着;状态落盘,穿过自动更新与重启,睡眠唤醒会重连。 +- [p5-15] 关掉也丢不了:状态落盘,穿得过自动更新和重启,机器睡醒还会重连。 - [p5-16] 管家给每个会话记账:六种状态,排队、跑着、等审批、被拦、收尾、完事。 -- [p5-17] 行摘要也是一个小模型顺带写的——省着主模型的上下文。 +- [p5-17] 每条还配一行摘要,也是小模型顺带写的——省着主模型的上下文。 - [p5-18] 进程退出不等于任务没了——接回后从停的地方继续。 - [p5-19] 对了,表上还有个总量上限:五十条。满了要先取消一条才能再添—— - [p5-20] 闹钟太多的人,该先想想是不是真的需要这么多闹钟。 - [p5-21] 还有个小细节:定时任务触发的请求,带着「低优先级」的标记—— - [p5-22] 服务一忙,先紧着人的事,闹钟的事往后稍稍。 - [p5-23] 三个真话合起来是一种态度:定时这件事,想象很浪漫,工程都在打补丁。 -- [p5-23a] 还有个更自由的拨法:让它自己给自己上发条——干完一轮,顺手定下一次, +- [p5-23a] 补丁之外还有个自由的拨法:让它给自己上发条——干完一轮,顺手定下一次, - [p5-23b] 间隔自己定。不靠墙上的钟,靠它自己的一句「回头再来」。 ## P6 落点与信源 diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx index c6a99591..f681744d 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx @@ -38,17 +38,21 @@ const MeterDial: React.FC<{spinFrom: number}> = ({spinFrom}) => { - - {'按字计费'} - + {/* W9 抽帧实拍:秒针狂转 720°/s 会周期性扫过盘心下方的「按字计费」,四字被切断 + (0-A mid 帧实拍坐实)。表盘内不放文字,标签移到表盘外正下方, + 几何上彻底避开旋转件。 */} +
+ {'按字计费'} +
= ({ const resultShift = queue * 260; return ( - + {/* W10 抽帧实拍:主体卡带仅高 122px、孤立在画面中线,核心墨水 0.0165(视觉 + 模型判「偏稀/太空」)。整体放大 1.18 倍上移 30px,动画锚零改动 */} + {/* 调用卡(左) */} @@ -157,7 +159,10 @@ const NoCutIn: React.FC<{badAt: number; goodAt: number}> = ({badAt, goodAt}) => const denyFlash = badOn && !goodOn ? (Math.floor(frame / 4) % 2 === 0 ? 1 : 0.45) : 0.85; return ( -
+ {/* W10 抽帧实拍:两卡带仅高 210px 且前半 beat 两卡为 0.35 暗态(核心墨水 + 0.011–0.015,视觉模型判「信息量很低、偏空」)。整体放大 1.2 倍,动画 + 锚(badAt/goodAt/cut/denyFlash)零改动 */} +
{/* ✗ 帧:气泡被截断 */}
@@ -269,10 +274,11 @@ const SevenTasks: React.FC<{lightAt: number; labelAt: number}> = ({lightAt, labe }; /** 2-E 取件码回巢 + 账目天平 + 第一层全景盖章 */ -const ClaimCheckScale: React.FC<{matchAt: number; scaleAt: number; stampAt: number}> = ({ +const ClaimCheckScale: React.FC<{matchAt: number; scaleAt: number; stampAt: number; inboxAt: number}> = ({ matchAt, scaleAt, stampAt, + inboxAt, }) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); @@ -296,8 +302,64 @@ const ClaimCheckScale: React.FC<{matchAt: number; scaleAt: number; stampAt: numb // 盖章 const stamp = spring({frame: frame - stampAt, fps, config: {damping: 200}}); const stampOn = frame >= stampAt; + // W10 抽帧实拍:p2-16..18(前 ~17s)口播讲「信箱查状态」,画面却只有占位条 + // 与小环——信箱三态零视觉。三枚状态签在 matchAt 前自右向左依次亮, + // 对号动画起飞前整组淡出让位(帧驱动,确定性) + const inboxGone = interpolate(frame - matchAt + 18, [0, 14], [1, 0], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const INBOX = [ + {t: '还在跑', c: theme.later}, + {t: '跑完了', c: theme.mech}, + {t: '没这条活', c: theme.deny}, + ]; return ( + {inboxGone > 0.01 ? ( +
+
+ {'主动开信箱一问 —— 每条活的三种答话'} +
+ {INBOX.map((s, i) => { + const e = interpolate(frame - inboxAt - i * 8, [0, 12], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + return ( +
+ {s.t} +
+ ); + })} +
+ ) : null} {/* 占位条(左):等结果的位置 */} @@ -412,7 +474,12 @@ export const P2Rejoin: React.FC<{scene: SceneRange}> = ({scene}) => { - +
); diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx index e728e344..ea7abfb3 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P5Truths.tsx @@ -217,7 +217,10 @@ const RetireStamp: React.FC<{flipAt: number; stampAt: number}> = ({flipAt, stamp }) : 0; return ( -
+ {/* W10 抽帧实拍:主体(日历 250px + 章 170px)仅占画面宽 30%、全 beat 核心墨水 + 0.0044——本集最空一镜(视觉模型判「密度偏稀」)。整体放大 1.3 倍并拉大 + 间距,动画锚(flipAt/stampAt/pulse)零改动 */} +
{/* 日历:翻页计数 */}
diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx index ee245a65..806f8215 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P6Ending.tsx @@ -413,8 +413,11 @@ export const P6Ending: React.FC<{scene: SceneRange}> = ({scene}) => { + {/* l1 锚 p6-01(W10 抽帧实拍:原锚 p6-02 使首句 5.3s 全幕只剩抬头, + 收尾句「这一集其实只回答了一个问题:谁来按开始」配真空画面)。 + 第一张卡随首句浮出,p6-02 口播「有人按并等着」时它已就位 */} 角标:Permission · "Check Permissions Before Execution" - [p3-01] 现在这个 AI 有五件工具,其中一件能跑任意命令。 -- [p3-02] 读写文件那几件都被拦在工作目录里,但跑命令那件,没人管它。 +- [p3-02] 读写文件那几件,都被拦在工作目录里;跑命令那件,没人管。 - [p3-03] 你随口说一句「帮我把项目清理一下」, - [p3-04] 它完全可能给你递上一条把整块盘删干净的命令,循环照跑。 - [p3-06] 官方把话说死了:权限由这层代码执行,不由模型执行。 @@ -178,7 +178,7 @@ > 角标:Hooks · "Hang on the Loop, Don't Write into It" - [p4-01] 到这一步,这个 AI 已经能安全地动手了。 -- [p4-02] 接下来的麻烦所有做过工程的人都熟悉:你想加点东西。 +- [p4-02] 接下来的麻烦,做过工程的人都熟:你想加点东西。 - [p4-03] 比如每次跑命令都记一笔日志,或者某些操作做完自动提交一次代码。 - [p4-04] 每加一样,你都得回去改那个循环。 - [p4-05] 有人画过一张很扎心的图:循环体里记日志一行、查权限一行、 @@ -215,7 +215,7 @@ - [p4-29] 插口上的函数说「这个我批了」,就真的放行吗?不。 - [p4-30] 它的放行,仍要穿过后面的拒绝与询问两站。 - [p4-31] 方向是单向的:扩展点能加限制,不能解除限制。 -- [p4-32] 而且这条单向,官方画成过六道闸门的流水线。 +- [p4-32] 而且官方把权限判定,画成过一条六道闸门的流水线。 - [p4-33] 这一层超出了最简实现的范围,拆源码的人评语是: - [p4-34] 做示例够用,生产环境就是一个安全漏洞。 @@ -268,4 +268,4 @@ - [p6-06] 本片机制依据官方文档,取数2026年8月,以官方最新表述为准。 - [p6-07] 示例代码来自开源实现,行数均为实测,链接在简介。 - [p6-05] 学会给 Harness 做加减法,这本身就是一门手艺。 -- [p6-08] 下期一个反直觉的事实:它这一轮能看见什么,从来不是它自己说了算。 +- [p6-08] 下期一个反直觉的事实:它这一轮看见什么,从来不是它自己说了算。下期见。 diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx index bba6df36..1ae26c38 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P1Loop.tsx @@ -193,8 +193,12 @@ const TwentyThreeLines: React.FC<{ extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); - // 代码逐行渲染让位给前置动画:标签条(~14 帧)+ 对照列(~16 帧)先占画布 - const codeStart = compareAt + 18; + // 代码逐行渲染:标签条(~14 帧)落下后即开卷——不再等对照列。 + // 旧锚 compareAt+18 让 p1-12a 整句(164 帧 ≈ 5.5s)画布上只有一颗孤零零的 + // 药丸标签(三密度审查 fr3195 实拍:body 仅 [82,112] 一行)。代码卡提前到 + // 标签条就位后立刻逐行铺开,p1-12a 说「有人照着这套机制搭了一份开源的最小实现」 + // 时代码已经在屏幕上生长。 + const codeStart = tagAt + 16; return (
diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx index 0ed3b076..d32407a0 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/video/src/scenes/P3Gates.tsx @@ -98,7 +98,11 @@ const UnguardedShell: React.FC<{frameAt: number; cmdAt: number; execAt: number}> }; /** 3-B 三道闸门落下,第一道把请求弹回 */ -const GatesFall: React.FC<{gateAt: number[]; bounceAt: number}> = ({gateAt, bounceAt}) => { +const GatesFall: React.FC<{gateAt: number[]; bounceAt: number; pillAt?: number}> = ({ + gateAt, + bounceAt, + pillAt, +}) => { const frame = useCurrentFrame(); const g = gateAt.map((a) => interpolate(frame - a, [0, 16], [0, 1], {extrapolateLeft: 'clamp', extrapolateRight: 'clamp'}), @@ -107,10 +111,13 @@ const GatesFall: React.FC<{gateAt: number[]; bounceAt: number}> = ({gateAt, boun extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); + /* 拒绝表胶囊锚 p3-08(口播点名「删根目录、提权…」那句)。闸门前移到 p3-07 后, + 旧式 gateAt[0]+12 会让胶囊抢在句前 ~1.3s 出现——提前落门可以,提前念清单不行。 */ + const pillStart = pillAt ?? gateAt[0] + 12; return ( - {g[0] > 0.8 ? ( + {g[0] > 0.8 && frame >= pillStart ? (
{['删根目录', '提权', '关机', '格式化'].map((t, i) => ( = ({gateAt, boun accent={theme.deny} style={{ padding: '10px 20px', - opacity: interpolate(frame - gateAt[0] - 12 - i * 4, [0, 10], [0, 1], { + opacity: interpolate(frame - pillStart - i * 4, [0, 10], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }), @@ -431,9 +438,14 @@ const SandboxCrossSection: React.FC<{ ']', ]; const variants = ['rm -rf /', 'rm -fr /', 'sudo${IFS}rm']; - // 壳几何:右侧画布中心 - const CX = 1240; - const CY = 500; + // 壳几何:右侧画布中心。CX/CY 是**svg 内部坐标系**(svg width=760 height=620, + // 默认 overflow:hidden 会把界外内容整块裁掉)——旧值 1240/500 是 1920 全画布 + // 坐标,壳 x=930..1550 全部落在 760 宽的 svg 之外,整镜 21.6s 壳体/边界带/ + // 进程树/密钥箭头一行都没渲染出来(右侧全程空白,2026-08-29 三密度全扫 + // f13420..f13950 逐帧实拍坐实)。取 svg 中心 (380, 310) 后,壳在画布上落于 + // x≈750..1370、y≈320..760,左侧代码卡与右侧壳重新构成双栏构图。 + const CX = 380; + const CY = 310; const W = 620; const H = 440; const halfW = W / 2 + (1 - shell) * 560; @@ -1028,8 +1040,12 @@ export const P3Gates: React.FC<{scene: SceneRange}> = ({scene}) => { /> + {/* 闸门落下前移到 p3-07 句内(+48 帧):此前锚 p3-08,p3-07 整句 + 「拦法是三道闸门」99 帧里画布只有一条空轨道(三密度审查 fr12226 实拍)。 + 句子点名「三道」时闸门就该在场——p3-08 讲第一道时已可指认。 */} @@ -1069,9 +1085,12 @@ export const P3Gates: React.FC<{scene: SceneRange}> = ({scene}) => { /> - {/* p3-33 已删:末两行高亮锚点并入 p3-32 +20 帧;31a/b 成绩单卡随动 */} + {/* p3-33 已删:末两行高亮锚点并入 p3-32 +20 帧;31a/b 成绩单卡随动。 + scrollAt 前挂 p3-30 句内(+70 帧):旧锚 p3-31 让 p3-30 整句 + 「靠另一个模型当闸门」159 帧里画布只有标题一行(三密度审查 fr15119 实拍)。 + 五行视野清单在 p3-30 尾段就开始铺,p3-31 讲遥测数字时审判已在画面上。 */} = ({barAt, coreAt}) //: 柱底距容器底的实测像素:幕名标签(22px 字,行盒 ~33)+ `marginTop: 12`。 //: 基准带必须减掉它才能落在柱子自己的行数刻度上——此前写 90,带体整体上浮 45px。 const BAR_BASE = 45; + // 量尺先行:p5-07(「这不是我的说法,是可以数出来的」)整句 111 帧里柱子还没长 + // (barAt 锚 p5-08),画布除幕头外全空(2026-08 三密度审查 fr22625 实拍)。 + // 让刻度横轴 + 四柱的空基座在 beat 第 0 帧就位——「可以数出来」先看到尺,再看到数。 + const rulerT = interpolate(frame, [0, 14], [0, 1], {extrapolateRight: 'clamp'}); return (
+ {/* 刻度横轴:柱底基线(rulerT 淡入,全程在场)。 + 用 mech 描边而非 panelBorder——#2A3242 在黑底上亮度仅 49,起不到 + 「量尺先行」的视觉锚定作用(三密度审查复验实拍)。 */} +
{CHAPTERS.map((c, i) => { const at = barAt + i * 9; const e = spring({frame: frame - at, fps, config: {damping: 200}}); @@ -312,7 +331,8 @@ const GrowthBars: React.FC<{barAt: number; coreAt: number}> = ({barAt, coreAt}) fontSize: 22, color: theme.dim, marginTop: 12, - opacity: e, + /* 基座名与刻度轴同步先位(rulerT),数值 e 仍等柱子长出才亮 */ + opacity: Math.max(rulerT, e), }} > {c.name} diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json index 6a7ea9e8..c30b7a4a 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json @@ -12,7 +12,7 @@ { "id": "p0-04", "scene": "P0", - "text": "铁律是:读过的每个文件、跑过的每条命令、你说的每句话,全都随身带着——" + "text": "它没有记性:读过的每个文件、跑过的每条命令、你说的每句话,全带着——" }, { "id": "p0-05", @@ -57,7 +57,7 @@ { "id": "p0-10", "scene": "P0", - "text": "官方给 Harness 列的四件事里,有一件是上下文管理。" + "text": "这事得有人管。官方给 Harness 列的四件事里,就有上下文管理。" }, { "id": "p0-11", @@ -67,7 +67,7 @@ { "id": "p0-13", "scene": "P0", - "text": "答案分两层,对应两种完全不同的心态。" + "text": "后一半的答案分两层,对应两种完全不同的心态。" }, { "id": "p0-14", @@ -157,7 +157,7 @@ { "id": "p1-16", "scene": "P1", - "text": "注意折叠只动超过一百二十字的旧结果,短的就留着,不值得动它。" + "text": "注意折叠只动超过一百二十字的旧结果,短的就留着,不值得费这个事。" }, { "id": "p1-17", @@ -167,12 +167,12 @@ { "id": "p1-18", "scene": "P1", - "text": "官方文档的原话正好背书这个次序:先清掉旧的工具输出,不够再把整段对话摘要。" + "text": "官方文档的原话正好背书:先清掉旧的工具输出,不够再把整段对话摘要。" }, { "id": "p1-19", "scene": "P1", - "text": "最简的四级,就是文档这两级的细化。便宜先来、贵的殿后,方向一致。" + "text": "这四级就是那两句的细化。便宜先来、贵的殿后,方向一致。" }, { "id": "p1-20", @@ -212,7 +212,7 @@ { "id": "p2-07", "scene": "P2", - "text": "第四级,全桌重写。前面三级都跑完,桌子还是满的,就只能请人来写摘要了。" + "text": "第四级,全桌重写。三级都跑完桌子还是满的,就只能请人来写摘要了。" }, { "id": "p2-08", @@ -247,7 +247,7 @@ { "id": "p2-14", "scene": "P2", - "text": "应急之外还有个补充:拒收已经发生时的抢救通道,保住最近几张原纸," + "text": "四级之外还留了条抢救通道:拒收已经发生时,保住最近几张原纸," }, { "id": "p2-15", @@ -262,7 +262,7 @@ { "id": "p2-17", "scene": "P2", - "text": "入库必须在折叠之前。因为折叠会把旧的大块头换成一行动字。" + "text": "入库必须在折叠之前。因为折叠会把旧的大块头换成一行字。" }, { "id": "p2-18", @@ -302,12 +302,12 @@ { "id": "p3-01", "scene": "P3", - "text": "四级收拾里还有两个角色值得单独说说。" + "text": "回到四级收拾,里面还有两处值得单独说说。" }, { "id": "p3-02", "scene": "P3", - "text": "一个是写摘要这位帮工。它的纪律严得有点好笑。" + "text": "一处是写摘要这位帮工。它的纪律严得有点好笑。" }, { "id": "p3-03", @@ -342,7 +342,7 @@ { "id": "p3-09", "scene": "P3", - "text": "压缩之后谁活下来,官方给过一张矩阵——" + "text": "另一处是压缩过后的存活名单,官方给过一张矩阵——" }, { "id": "p3-10", @@ -367,12 +367,12 @@ { "id": "p3-14", "scene": "P3", - "text": "这一步超出了最简实现的范围,是有人从源码里读出来的——所以口播到这里," + "text": "这一步超出了最简实现的范围,是有人从源码里读出来的——所以听到这里," }, { "id": "p3-15", "scene": "P3", - "text": "你听到的每一个细节都带着同一句提醒:这是他的分析,不是官方的说明书。" + "text": "请记住同一句提醒:这是他的源码分析,不是官方的说明书。" }, { "id": "p3-16", @@ -417,7 +417,7 @@ { "id": "p4-08", "scene": "P4", - "text": "所以需要另一层:不参与压缩的两条腿。第一条你写——就是项目里那个文件夹。" + "text": "所以需要另一层:不参与压缩的两条腿。第一条你写——项目里那个文件夹。" }, { "id": "p4-08a", @@ -457,7 +457,7 @@ { "id": "p4-12", "scene": "P4", - "text": "记过的不再记——防重复这条保留:防止本子自己长胖。" + "text": "而且记过的不再记——这条防的是本子自己长胖。" }, { "id": "p4-13", @@ -487,7 +487,7 @@ { "id": "p4-18", "scene": "P4", - "text": "这份索引不写在它的基本设定里——它垫在你开口之前,每次开工先扫一眼。" + "text": "四类之外还有一份索引:它垫在你开口之前,每次开工先扫一眼。" }, { "id": "p4-19", @@ -502,7 +502,7 @@ { "id": "p4-21", "scene": "P4", - "text": "第二条是按需取:每轮开始前,把最近对话和记忆清单一起发给一个小模型," + "text": "第二条是按需取:每轮开始前,把最近对话和记忆清单发给一个小模型," }, { "id": "p4-22", @@ -607,7 +607,7 @@ { "id": "p5-11", "scene": "P5", - "text": "本子会越攒越厚,同一件事记了三遍、过时的没淘汰,就得整理。" + "text": "但本子会越攒越厚:同一件事记了三遍、过时的没淘汰,就得整理。" }, { "id": "p5-12", diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md index ee29d524..61b87f82 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md @@ -15,7 +15,7 @@ - [p0-01] 它正在干活,突然,停了。一个小时的活,一行报错,全部作废。 - [p0-02] 不是它不想干,是服务那边拒收了——理由直白:你随身带的,太大了。 -- [p0-04] 铁律是:读过的每个文件、跑过的每条命令、你说的每句话,全都随身带着—— +- [p0-04] 它没有记性:读过的每个文件、跑过的每条命令、你说的每句话,全带着—— - [p0-05] 每问一次模型,就从第一个字重新看一遍。窗口就这样一层层被垫高。 - [p0-05a] 而且开局就不空——你还没敲第一个字,窗口里已躺着好几样东西。 - [p0-05b] 官方文档给过一份示意账:光基本设定,就占四千多字。 @@ -24,9 +24,9 @@ - [p0-09a] 原因不玄:每多一个字,要照顾的两两关系就多一圈。 - [p0-09b] 而注意力的总量是固定的——摊得越薄,看得越糊。 - [p0-09c] 所以窗口再大,也不等于记性变好——能装,不等于能记。 -- [p0-10] 官方给 Harness 列的四件事里,有一件是上下文管理。 +- [p0-10] 这事得有人管。官方给 Harness 列的四件事里,就有上下文管理。 - [p0-11] 它分两半:安排它看什么,和装满了怎么办——今天拆后一半。 -- [p0-13] 答案分两层,对应两种完全不同的心态。 +- [p0-13] 后一半的答案分两层,对应两种完全不同的心态。 - [p0-14] 第一层承认会丢:窗口一定会满,那就把丢管起来——分级、有序、有保底。 - [p0-15] 第二层保证不丢:另立一个不参与压缩的账本,重要的写进去就不出来。 @@ -50,10 +50,10 @@ - [p1-13] 第二级,折旧纸。旧工具结果的完整内容,只保留最近三条, - [p1-14] 更早的那些折成一行字:早前结果已收起,需要的话再跑一遍。 - [p1-15] 反正真需要的时候,再让它跑一遍就是——纸可以折,活不用重干。 -- [p1-16] 注意折叠只动超过一百二十字的旧结果,短的就留着,不值得动它。 +- [p1-16] 注意折叠只动超过一百二十字的旧结果,短的就留着,不值得费这个事。 - [p1-17] 这两级全是纯文本操作,一次模型都不用请,便宜到近乎免费。 -- [p1-18] 官方文档的原话正好背书这个次序:先清掉旧的工具输出,不够再把整段对话摘要。 -- [p1-19] 最简的四级,就是文档这两级的细化。便宜先来、贵的殿后,方向一致。 +- [p1-18] 官方文档的原话正好背书:先清掉旧的工具输出,不够再把整段对话摘要。 +- [p1-19] 这四级就是那两句的细化。便宜先来、贵的殿后,方向一致。 - [p1-20] 记住这个次序感:先动最不心疼的,再动开始心疼的。这是这一层的节拍。 ## P2 大件入库与顺序论证 @@ -68,17 +68,17 @@ - [p2-04] 桌上只留一张预览卡:开头两千字,外加一个「全文在库里」的标记。 - [p2-05] 它看到标记就知道:全文在磁盘上躺着,真要用,再取就是。 - [p2-06] 这一级还是不用请模型,只是搬东西——便宜,但能腾出最大的空间。 -- [p2-07] 第四级,全桌重写。前面三级都跑完,桌子还是满的,就只能请人来写摘要了。 +- [p2-07] 第四级,全桌重写。三级都跑完桌子还是满的,就只能请人来写摘要了。 - [p2-08] 重写之前先做一件事:把整段对话原样存档,一份不少。 - [p2-09] 这是保底——摘要写砸了,原始记录还在,不至于两头空。 - [p2-10] 然后请模型把这一桌纸重写成一张:当前目标、重要发现、改过哪些文件、 - [p2-11] 还剩什么活、你交代过什么约束。写完,整桌纸换成这一张。 - [p2-12] 这是四级里唯一要花一次模型调用的,最贵,所以放最后。 - [p2-13] 重写要是连着失败三次,熔断,不再试——别把预算烧在死循环上。 -- [p2-14] 应急之外还有个补充:拒收已经发生时的抢救通道,保住最近几张原纸, +- [p2-14] 四级之外还留了条抢救通道:拒收已经发生时,保住最近几张原纸, - [p2-15] 只把更早的部分换成摘要,重试一次,再不行就把错误往上交。 - [p2-16] 现在说这一集最要紧的一个细节:这几级的顺序,是锁死的。 -- [p2-17] 入库必须在折叠之前。因为折叠会把旧的大块头换成一行动字。 +- [p2-17] 入库必须在折叠之前。因为折叠会把旧的大块头换成一行字。 - [p2-18] 顺序反了,等你想起来要存原文的时候,原文已经不在了—— - [p2-19] 你把空气存进了档案室。 - [p2-20] 我们在画面里把顺序对调一次给你看:折叠先行,大块头瞬间缩成一行, @@ -93,21 +93,21 @@ > ★回捞钩:压缩后五个文件被捞回桌面。 > 角标:保 5 条 · 重试 1 次 · 「只写字」首尾各一遍 · 回捞 ≤5 文件 -- [p3-01] 四级收拾里还有两个角色值得单独说说。 -- [p3-02] 一个是写摘要这位帮工。它的纪律严得有点好笑。 +- [p3-01] 回到四级收拾,里面还有两处值得单独说说。 +- [p3-02] 一处是写摘要这位帮工。它的纪律严得有点好笑。 - [p3-03] 有人把真实实现里给它的指令原文抄了出来,开头第一句就是: - [p3-04] 这次只许写字,绝不许调用任何工具。结尾还要再叮嘱一遍。 - [p3-05] 为什么叮嘱两遍?请来收拾桌子的,手上偏偏有搬东西的能力。 - [p3-06] 真让它边收拾边调用工具,桌子越收越满,收拾就变成了新的堆积。 - [p3-07] 它还必须先在草稿区理清思路,再誊出正式摘要。 - [p3-08] 草稿写完就撕掉,不留在桌上——草稿是给它自己看的,不是给对话看的。 -- [p3-09] 压缩之后谁活下来,官方给过一张矩阵—— +- [p3-09] 另一处是压缩过后的存活名单,官方给过一张矩阵—— - [p3-10] 系统提示绕行不变;规则和自动记忆从磁盘重新注入; - [p3-11] 用过的技能正文重注入,但每份封顶五千、最旧的先丢。 - [p3-12] 而且压缩结束,同一张矩阵还写着:把最近读过的文件捞回桌面, - [p3-13] 最多五个、按重要性排队——丢,也是分层次的丢。 -- [p3-14] 这一步超出了最简实现的范围,是有人从源码里读出来的——所以口播到这里, -- [p3-15] 你听到的每一个细节都带着同一句提醒:这是他的分析,不是官方的说明书。 +- [p3-14] 这一步超出了最简实现的范围,是有人从源码里读出来的——所以听到这里, +- [p3-15] 请记住同一句提醒:这是他的源码分析,不是官方的说明书。 - [p3-16] 到这里,第一层讲完了:会丢的东西,被管得相当讲究。 ## P4 不丢的那一层 @@ -123,7 +123,7 @@ - [p4-05] 几轮压缩之后,它被摘成了六个字:有代码风格偏好。 - [p4-06] 摘要没有做错什么——摘要的天性就是丢细节,保主干。 - [p4-07] 可有些细节,恰恰是主干。你的偏好就是你的偏好,缩不成一句概括。 -- [p4-08] 所以需要另一层:不参与压缩的两条腿。第一条你写——就是项目里那个文件夹。 +- [p4-08] 所以需要另一层:不参与压缩的两条腿。第一条你写——项目里那个文件夹。 - [p4-08a] 这里要纠正一个流传很广的说法:里面的规则不是它的基本设定。 - [p4-08b] 那是设定之后递进来的第一条普通消息——跟你说的话同一个身份。 - [p4-08c] 官方原话:会读、会尽量照做,但不保证严格执行。 @@ -131,16 +131,16 @@ - [p4-09] 这些文件层层拼接,越靠近工作目录的越后读,超两百行就开始不老实。 - [p4-10] 一件事一个文件,开头三行登记:叫什么、一句话说明、属于哪类。 - [p4-11] 第二条腿它自己写:自动记忆按四类落在你的用户目录下,有门限。 -- [p4-12] 记过的不再记——防重复这条保留:防止本子自己长胖。 +- [p4-12] 而且记过的不再记——这条防的是本子自己长胖。 - [p4-13] 四类记忆,其实就是四个问题。 - [p4-14] 你是谁——偏好和习惯,「缩进用 tab」就记在这类; - [p4-15] 怎么干活——反馈和规矩,「别造假数据」; - [p4-16] 在发生什么——项目背景,「这次重写是合规驱动的」; - [p4-17] 去哪儿找——线索和入口,「那个老 bug 记录在哪」。 -- [p4-18] 这份索引不写在它的基本设定里——它垫在你开口之前,每次开工先扫一眼。 +- [p4-18] 四类之外还有一份索引:它垫在你开口之前,每次开工先扫一眼。 - [p4-19] 索引也有上限:最多两百行,超了就要整理。家底要薄,才有用。 - [p4-20] 取的时候分两条路。索引常驻是第一条,便宜、全天候。 -- [p4-21] 第二条是按需取:每轮开始前,把最近对话和记忆清单一起发给一个小模型, +- [p4-21] 第二条是按需取:每轮开始前,把最近对话和记忆清单发给一个小模型, - [p4-22] 请它挑真正用得上的,最多五条;拿不准就不挑,宁缺毋滥。 - [p4-23] 挑错了比没挑更糟——一条不相干的记忆,就是一句错误的自我介绍。 - [p4-24] 还有个经济学尾巴:前缀缓存按字数打折,但前缀必须一字不差—— @@ -168,7 +168,7 @@ - [p5-08] 轮末:先从完整对话里抢救出值得记的,一个字不差地写进本子; - [p5-09] 然后压缩才来,碎纸机开动,桌面上的细节开始褪色。 - [p5-10] 先抢救,再碎纸。本子里的那句话,从此再也不进碎纸机。 -- [p5-11] 本子会越攒越厚,同一件事记了三遍、过时的没淘汰,就得整理。 +- [p5-11] 但本子会越攒越厚:同一件事记了三遍、过时的没淘汰,就得整理。 - [p5-12] 有人分析过,它的实现里这个整理有个正式名字,起得很有画面感:做梦。 - [p5-13] 这个梦有四道闸,一道不满足就不做。 - [p5-14] 距上次整理不满一天,不做——好记性不差这一天; diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json index 1c44a26a..ee1084ce 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.json @@ -27,7 +27,7 @@ { "id": "p0-05", "scene": "P0", - "text": "于是问题来了:从一个它到一群它,每多一样东西,都要回答四件事——" + "text": "于是问题来了:从一个它到一群它,中间隔着四道必答题——" }, { "id": "p0-06", @@ -47,7 +47,7 @@ { "id": "p0-09", "scene": "P0", - "text": "每一样里都埋着从教训学来的「不」字——不许插队、不许转包、不许悄悄丢东西。" + "text": "每一样都埋着教训换来的「不」字——不许插队、不许转包、不许悄悄丢东西。" }, { "id": "p0-10", @@ -92,7 +92,7 @@ { "id": "p1-08", "scene": "P1", - "text": "做完「建表」,「接口」和「文档」同时亮起可领——排序是图自己算出来的。" + "text": "做完「建表」,「接口」和「文档」同时可以领了——排序是图自己算出来的。" }, { "id": "p1-09", @@ -107,7 +107,7 @@ { "id": "p1-13", "scene": "P1", - "text": "官方文档写得直白:任务认领用文件锁防竞态——" + "text": "谁来认领也有规矩。官方文档写得直白:任务认领用文件锁防竞态——" }, { "id": "p1-14", @@ -117,7 +117,7 @@ { "id": "p1-15", "scene": "P1", - "text": "编号也有讲究:一个只增不减的计数器,防止编号被重复使用。" + "text": "编号也有讲究:一个只增不减的计数器,用过的号绝不复用。" }, { "id": "p1-16", @@ -127,12 +127,12 @@ { "id": "p1-17", "scene": "P1", - "text": "还有个容易忽略的分别,值得多说一句:清单和看板是两样东西。" + "text": "这里有个容易忽略的分别,值得多说一句:清单和看板是两样东西。" }, { "id": "p1-18", "scene": "P1", - "text": "清单给自己看——我今天干哪几步;看板给所有人看——这摊活到哪了。" + "text": "清单给自己看:我今天干哪几步;看板给所有人看:这摊活到哪了。" }, { "id": "p1-19", @@ -142,7 +142,7 @@ { "id": "p1-20", "scene": "P1", - "text": "为什么看板非要落成文件?因为下一个问题马上就来:" + "text": "为什么看板非要落成文件?因为一起干活有个前提:" }, { "id": "p1-21", @@ -192,7 +192,7 @@ { "id": "p2-09", "scene": "P2", - "text": "排查问题的时候,你直接打开信箱文件看两眼,比任何调试面板都直接。" + "text": "排查问题的时候,你打开信箱文件看两眼,比任何调试面板都直接。" }, { "id": "p2-10", @@ -207,7 +207,7 @@ { "id": "p2-12", "scene": "P2", - "text": "领队也是这规矩。队友干完活,把总结投进领队的信箱;" + "text": "领队也守这规矩。队友干完活,把总结投进领队的信箱;" }, { "id": "p2-13", @@ -222,12 +222,12 @@ { "id": "p2-15", "scene": "P2", - "text": "只不过写文件加了一把锁,防止两个队友同时投信把信写串行。" + "text": "只不过写文件加了一把锁,防止两个队友同时投信把信写串了。" }, { "id": "p2-18", "scene": "P2", - "text": "最妙的是权限。队友要干一件需要审批的事,审批窗不在它自己的屏幕上——" + "text": "最妙的是权限。队友要干一件需要审批的事,弹窗不在它自己的屏幕上——" }, { "id": "p2-19", @@ -252,7 +252,7 @@ { "id": "p2-23", "scene": "P2", - "text": "还有一条铁律:队友不许再孵队友——一张审批卡冒十层泡,就找不到责任人了。" + "text": "还有一条铁律:队友不许再孵队友——审批卡冒十层泡,就找不到责任人了。" }, { "id": "p2-23a", @@ -262,12 +262,12 @@ { "id": "p2-23b", "scene": "P2", - "text": "每人一只信箱。会话一结束,名册自动清掉——队伍是临时的,桌子才是留下的。" + "text": "每人一只信箱。会话一结束,名册自动清掉——队伍是临时的,桌子是留下的。" }, { "id": "p2-24a", "scene": "P2", - "text": "还有个实在的细节:消息就是一段文字——想把整段上下文搬过去,得恢复会话," + "text": "再补个细节:消息就是一段文字——想把整段上下文搬过去,得恢复会话," }, { "id": "p2-24b", @@ -292,7 +292,7 @@ { "id": "p3-03", "scene": "P3", - "text": "最粗暴的做法是直接掐掉它的线程。但掐的瞬间,它可能正写文件写到一半——" + "text": "最粗暴的做法是直接掐掉它的线程。但掐的瞬间,它可能正把文件写到一半——" }, { "id": "p3-04", @@ -322,7 +322,7 @@ { "id": "p3-11", "scene": "P3", - "text": "计划这头等回复,回复那头带编号回来,批了才动手。" + "text": "计划递上去等着,回复带同一个编号回来,批了才动手。" }, { "id": "p3-12", @@ -332,7 +332,7 @@ { "id": "p3-13", "scene": "P3", - "text": "请求、同意或拒绝——拒绝还能附理由——最后系统广播一声「人已离场」," + "text": "请求、同意或拒绝,拒绝还能附上理由——最后系统广播一声「人已离场」," }, { "id": "p3-14", @@ -347,7 +347,7 @@ { "id": "p3-16", "scene": "P3", - "text": "最简实现只演了消息怎么走;它的门禁是真的——批文没到,工具出不了手。" + "text": "最简实现只演了消息怎么走;产品的门禁是真的——批文没到,工具出不了手。" }, { "id": "p4-01", @@ -357,7 +357,7 @@ { "id": "p4-02", "scene": "P4", - "text": "它的作者们也这么想。所以队友学会了自己看板、自己认领。" + "text": "它的作者们也这么想。所以队友学会了自己翻板、自己认领。" }, { "id": "p4-03", @@ -377,7 +377,7 @@ { "id": "p4-06", "scene": "P4", - "text": "信箱空着,再看板:有没有没人领、依赖又齐了的活?有就领,领了接着干。" + "text": "信箱空着,再翻看板:有依赖齐了、又没人认领的活吗?有就领,领了接着干。" }, { "id": "p4-07", @@ -392,7 +392,7 @@ { "id": "p4-09", "scene": "P4", - "text": "两只队友同时抢一个活怎么办?主人这一格先到先得,后到者查一眼就走。" + "text": "两个队友同时抢一个活怎么办?主人这一格先到先得,后到者查一眼就走。" }, { "id": "p4-10", @@ -407,7 +407,7 @@ { "id": "p4-12", "scene": "P4", - "text": "再看最简实现:歇着时还有个身份机关——对话压太短就把「我是谁」插回去。" + "text": "最简实现还埋了个身份机关——歇着时对话压太短,就把「我是谁」插回去。" }, { "id": "p4-13", @@ -427,7 +427,7 @@ { "id": "p4-16", "scene": "P4", - "text": "领队从包工头退成了项目经理。转变的代价,就是那几样朴素的东西。" + "text": "领队从包工头退成了项目经理。撑住这个转变的,就是那几样朴素的东西。" }, { "id": "p4-17", @@ -452,7 +452,7 @@ { "id": "p4-21", "scene": "P4", - "text": "并行最难的也不是分活,是所有人卡在同一个坑。" + "text": "但并行最难的不是分活,是所有人卡在同一个坑。" }, { "id": "p4-22", @@ -467,7 +467,7 @@ { "id": "p4-24", "scene": "P4", - "text": "再二分下去,分到最后谁也不挡谁。" + "text": "剩下的再二分下去,分到最后谁也不挡谁。" }, { "id": "p5-01", @@ -522,7 +522,7 @@ { "id": "p5-11", "scene": "P5", - "text": "干完收尾,两个选择:留着(分支保留,等人审查合并)或者拆掉。" + "text": "干完收尾,两个选择:留着——分支保留,等人审查合并;或者拆掉。" }, { "id": "p5-12", @@ -562,12 +562,12 @@ { "id": "p5-19", "scene": "P5", - "text": "它眼里的世界就是那张桌。任务与目录是否强制绑定,取舍见角标。" + "text": "它眼里的世界就是那张桌。任务与目录是否强制绑定,两种做法各有取舍。" }, { "id": "p5-20", "scene": "P5", - "text": "顺带交代悬着的话:工具本身也可以是别人造的。行业标准的接插协议," + "text": "最后顺带一句:工具本身也可以是别人造的。有一套行业标准的接插协议," }, { "id": "p5-21", @@ -652,7 +652,7 @@ { "id": "p6-11d", "scene": "P6", - "text": "在第一个没干完的之后启动的,全部重跑。规矩清楚,不碰运气。" + "text": "从第一个没干完的往后,启动过的全部重跑。规矩清楚,不碰运气。" }, { "id": "p6-12", @@ -692,6 +692,6 @@ { "id": "p6-17", "scene": "P6", - "text": "下期,再往上一层:怎么给这样的系统打分。分数会骗人,过程不会——下期见。" + "text": "下期再往上一层:怎么给这样的系统打分。分数会骗人,过程不会——下期见。" } ] diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md index a35b0390..97101f59 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/script/narration.md @@ -19,11 +19,11 @@ - [p0-03] 官方给这种单干的慢性病,起了三个名字。 - [p0-03a] 干一半就宣布完成、偏爱自己的产出、目标越走越散。 - [p0-04] 就像一个工人盖不了整栋楼。要赶工期,得来一队人。 -- [p0-05] 于是问题来了:从一个它到一群它,每多一样东西,都要回答四件事—— +- [p0-05] 于是问题来了:从一个它到一群它,中间隔着四道必答题—— - [p0-06] 活挂在哪里?话从哪里走?怎么谈判?谁的桌子谁收拾? - [p0-07] 这一集就把这四个问题一个个拆开。答案都很朴素,朴素到你会怀疑: - [p0-08] 就这?对,就这。一堆文件、几个信箱、一张编号表,拼起来就是团队。 -- [p0-09] 每一样里都埋着从教训学来的「不」字——不许插队、不许转包、不许悄悄丢东西。 +- [p0-09] 每一样都埋着教训换来的「不」字——不许插队、不许转包、不许悄悄丢东西。 - [p0-10] 拆到最后,还有一个更大的问题等着:这一摊子的计划,到底攥在谁手里。 ## P1 活挂在哪里:看板 @@ -38,17 +38,17 @@ - [p1-05] 「等谁完工」这格最关键。任务之间有先后:接口要等数据库,测试要等接口。 - [p1-06] 盖房子不能先盖屋顶再打地基——这句话,就是看板存在的理由。 - [p1-07] 于是任务连成一张图。谁先谁后不用人排:前面的完成了,后面的自动解锁。 -- [p1-08] 做完「建表」,「接口」和「文档」同时亮起可领——排序是图自己算出来的。 +- [p1-08] 做完「建表」,「接口」和「文档」同时可以领了——排序是图自己算出来的。 - [p1-09] 还有个特别诚实的设计:你引用了一个不存在的任务当依赖,它不报错、不崩, - [p1-10] 就是把你挡住。宁可挡着你,也不让一个笔误炸掉整块看板。 -- [p1-13] 官方文档写得直白:任务认领用文件锁防竞态—— +- [p1-13] 谁来认领也有规矩。官方文档写得直白:任务认领用文件锁防竞态—— - [p1-14] 先看一眼没人抢、再落笔写主人,两步并成一步,中间插不进第二只手。 -- [p1-15] 编号也有讲究:一个只增不减的计数器,防止编号被重复使用。 +- [p1-15] 编号也有讲究:一个只增不减的计数器,用过的号绝不复用。 - [p1-16] 看板立好了。谁来看?都可以——它就是硬盘上的一堆文件,能读就能看。 -- [p1-17] 还有个容易忽略的分别,值得多说一句:清单和看板是两样东西。 -- [p1-18] 清单给自己看——我今天干哪几步;看板给所有人看——这摊活到哪了。 +- [p1-17] 这里有个容易忽略的分别,值得多说一句:清单和看板是两样东西。 +- [p1-18] 清单给自己看:我今天干哪几步;看板给所有人看:这摊活到哪了。 - [p1-19] 一个管执行的顺序,一个管协作的进度。两套并存,各干各的。 -- [p1-20] 为什么看板非要落成文件?因为下一个问题马上就来: +- [p1-20] 为什么看板非要落成文件?因为一起干活有个前提: - [p1-21] 一群它干活时,谁都别指望谁脑子里的清单——硬盘上的东西才人人可见。 ## P2 话从哪里走:信箱 @@ -65,22 +65,22 @@ - [p2-06] 发消息就是往对方文件里加一行;读消息就是打开文件看一眼,然后删掉。 - [p2-07] 读一条,划掉一条。没有已读回执,没有撤回,就是一行一行的账。 - [p2-08] 为什么敢用这么土的设计?因为文件这东西,人人都会读,个个看得懂。 -- [p2-09] 排查问题的时候,你直接打开信箱文件看两眼,比任何调试面板都直接。 +- [p2-09] 排查问题的时候,你打开信箱文件看两眼,比任何调试面板都直接。 - [p2-10] 这也呼应了一个原则:能落在明面上的状态,就不要藏在运行过程里。 - [p2-11] 文件是给人和它共同看的地方——协作系统做到这一步,才算真的透明。 -- [p2-12] 领队也是这规矩。队友干完活,把总结投进领队的信箱; +- [p2-12] 领队也守这规矩。队友干完活,把总结投进领队的信箱; - [p2-13] 领队隔一阵收一次信,把信里的内容贴进自己的对话,接着指挥。 - [p2-14] 官方口径也证实了:信箱真的就是用户目录下的一个文件, -- [p2-15] 只不过写文件加了一把锁,防止两个队友同时投信把信写串行。 -- [p2-18] 最妙的是权限。队友要干一件需要审批的事,审批窗不在它自己的屏幕上—— +- [p2-15] 只不过写文件加了一把锁,防止两个队友同时投信把信写串了。 +- [p2-18] 最妙的是权限。队友要干一件需要审批的事,弹窗不在它自己的屏幕上—— - [p2-19] 请求冒泡,一路浮到领队的屏幕,弹出来,还是你来点头。 - [p2-20] 组了队,不代表权限放松了——官方立了三道禁令:队友的消息, - [p2-21] 不能替你批权限、不能代你同意、被拒的动作不能转给另一个队友。 - [p2-22] 组队不是权限洗白机。孩子们的签字栏,还在家长的原处。 -- [p2-23] 还有一条铁律:队友不许再孵队友——一张审批卡冒十层泡,就找不到责任人了。 +- [p2-23] 还有一条铁律:队友不许再孵队友——审批卡冒十层泡,就找不到责任人了。 - [p2-23a] 团队本身也落成文件:一个名册放在用户目录的团队文件夹里,写着谁在队、 -- [p2-23b] 每人一只信箱。会话一结束,名册自动清掉——队伍是临时的,桌子才是留下的。 -- [p2-24a] 还有个实在的细节:消息就是一段文字——想把整段上下文搬过去,得恢复会话, +- [p2-23b] 每人一只信箱。会话一结束,名册自动清掉——队伍是临时的,桌子是留下的。 +- [p2-24a] 再补个细节:消息就是一段文字——想把整段上下文搬过去,得恢复会话, - [p2-24b] 而不是塞进信箱。信箱管传话,不管搬桌子。 - [p2-25] 你回头看会发现:这些约定防的都是「没人负责」这四个字。 @@ -92,18 +92,18 @@ - [p3-01] 第三个问题:怎么谈判? - [p3-02] 谈判先从一个具体的麻烦说起:活干完了,怎么让一个队友下工? -- [p3-03] 最粗暴的做法是直接掐掉它的线程。但掐的瞬间,它可能正写文件写到一半—— +- [p3-03] 最粗暴的做法是直接掐掉它的线程。但掐的瞬间,它可能正把文件写到一半—— - [p3-04] 磁盘上留下一个半拉子文件,谁也说不清那算谁的。 - [p3-05] 所以告别也要握手。领队发关机请求,队友收干净手头的活,回一张同意。 - [p3-06] 这套握手有个精巧处:请求和回复带同一个编号,隔着信箱也对得上。 - [p3-07] 还要三重对号——编号、类型、这事没办过,全过才销账。 - [p3-10] 同一套机制换个方向就是审批:队友要动高风险的东西,先交一份计划等批。 -- [p3-11] 计划这头等回复,回复那头带编号回来,批了才动手。 +- [p3-11] 计划递上去等着,回复带同一个编号回来,批了才动手。 - [p3-12] 有人拆过它的源码——实际实现里的关机更讲究,是三向的: -- [p3-13] 请求、同意或拒绝——拒绝还能附理由——最后系统广播一声「人已离场」, +- [p3-13] 请求、同意或拒绝,拒绝还能附上理由——最后系统广播一声「人已离场」, - [p3-14] 顺带把它的窗格、任务、名册统统收拾干净。 - [p3-15] 所谓协议,没有玄机:一张状态表、一个编号、几条对得上号的规矩。 -- [p3-16] 最简实现只演了消息怎么走;它的门禁是真的——批文没到,工具出不了手。 +- [p3-16] 最简实现只演了消息怎么走;产品的门禁是真的——批文没到,工具出不了手。 ## P4 自己看板,自己认领 @@ -112,29 +112,29 @@ > 角标:WORK→IDLE→SHUTDOWN · 信箱优先看板其次 · 60s 超时(示教设计) - [p4-01] 到这里你可能会想:每次派活还要领队挨个分?十个任务分十次? -- [p4-02] 它的作者们也这么想。所以队友学会了自己看板、自己认领。 +- [p4-02] 它的作者们也这么想。所以队友学会了自己翻板、自己认领。 - [p4-03] 队友的一生分三段:干活、歇着、走人。 - [p4-04] 干完手头的活,不退出,进入歇着的状态。歇着时每五秒看两眼: - [p4-05] 先看信箱——里面可能有关机请求,也可能有新指令,有信就先处理信。 -- [p4-06] 信箱空着,再看板:有没有没人领、依赖又齐了的活?有就领,领了接着干。 +- [p4-06] 信箱空着,再翻看板:有依赖齐了、又没人认领的活吗?有就领,领了接着干。 - [p4-07] 认领前照例三查:是待办吗?有主人吗?依赖齐了吗?任何一条不过,不硬来。 - [p4-08] 这样领队只需要把任务挂上板,剩下的分发全自动。 -- [p4-09] 两只队友同时抢一个活怎么办?主人这一格先到先得,后到者查一眼就走。 +- [p4-09] 两个队友同时抢一个活怎么办?主人这一格先到先得,后到者查一眼就走。 - [p4-10] 歇着也不是永远歇。最简的做法定死六十秒:等不来新活,收工走人。 - [p4-11] 有人读过源码:实际实现没有固定时限,队友一直活着,等领队握手告别。 -- [p4-12] 再看最简实现:歇着时还有个身份机关——对话压太短就把「我是谁」插回去。 +- [p4-12] 最简实现还埋了个身份机关——歇着时对话压太短,就把「我是谁」插回去。 - [p4-13] 干活得知道自己是谁。这句话对人对它都成立。 - [p4-14] 再看一眼自治的样子:领队只做两件事——挂任务上板,需要时发告别握手。 - [p4-15] 剩下的认领、开工、汇报、等待、再认领,全是队友自己的节奏。 -- [p4-16] 领队从包工头退成了项目经理。转变的代价,就是那几样朴素的东西。 +- [p4-16] 领队从包工头退成了项目经理。撑住这个转变的,就是那几样朴素的东西。 - [p4-17] 官方自己拿这套打法,干过一票大的:让一群它,写一个编译器。 - [p4-18] 十六个它并行,各守一个容器;认领就是往一个文件里写一行占坑。 - [p4-19] 没有总调度,没有领队——两周,约两千场会话,十万行代码。 - [p4-20] 产出能编出一个可启动的内核,账单不到两万美元。 -- [p4-21] 并行最难的也不是分活,是所有人卡在同一个坑。 +- [p4-21] 但并行最难的不是分活,是所有人卡在同一个坑。 - [p4-22] 一个报错,就能让十六个它一起停摆。 - [p4-23] 解法很野:大部分文件先让现成的编译器过,只留一小撮给它。 -- [p4-24] 再二分下去,分到最后谁也不挡谁。 +- [p4-24] 剩下的再二分下去,分到最后谁也不挡谁。 ## P5 谁的桌子:各干各的 @@ -152,7 +152,7 @@ - [p5-08] 命令的工作目录解析不对、确认不了的,拦;git 重定向的四种写法,拦; - [p5-09] 命令形状没法静态验证的,拦——而且这道闸,不能关。 - [p5-10] 领队可以提前备好任务和桌子;绑定只登记,不改任务状态,两不耽误。 -- [p5-11] 干完收尾,两个选择:留着(分支保留,等人审查合并)或者拆掉。 +- [p5-11] 干完收尾,两个选择:留着——分支保留,等人审查合并;或者拆掉。 - [p5-12] 但有个不讲情面的默认:桌上还有没提交的改动,拆桌子的请求直接被拒。 - [p5-13] 这个「不讲情面」值得细品。机器最擅长的是无条件执行指令, - [p5-14] 而这里恰恰反着来:删除按钮按下去,它先问「你确定真的不要这些了?」 @@ -160,8 +160,8 @@ - [p5-16] 建桌、拆桌、留桌,每次都记一行日志。谁何时动过哪张桌,翻账就知道。 - [p5-17] 一行日志看着轻,出了事它就是唯一的目击证人。 - [p5-18] 官方还交代了个细节:进出目录是整个进程跟着切——一旦进桌, -- [p5-19] 它眼里的世界就是那张桌。任务与目录是否强制绑定,取舍见角标。 -- [p5-20] 顺带交代悬着的话:工具本身也可以是别人造的。行业标准的接插协议, +- [p5-19] 它眼里的世界就是那张桌。任务与目录是否强制绑定,两种做法各有取舍。 +- [p5-20] 最后顺带一句:工具本身也可以是别人造的。有一套行业标准的接插协议, - [p5-21] 外面的服务接上就变工具;名字自动带来源前缀,防的是两家重名。 - [p5-22] 装十个服务,上下文几乎不占——工具的定义按需取用,不整包塞进来。 @@ -185,7 +185,7 @@ - [p6-11a] 这种脚本能拼出好几种打法:一批活扇出去、各自干完再汇总成一份; - [p6-11b] 或者干完先请另一个它挑刺,挑完再改——改到合格才算完。 - [p6-11c] 中断也不慌:重新拉起时,干完的直接命中,没干完的从头再跑—— -- [p6-11d] 在第一个没干完的之后启动的,全部重跑。规矩清楚,不碰运气。 +- [p6-11d] 从第一个没干完的往后,启动过的全部重跑。规矩清楚,不碰运气。 - [p6-12] 多出来的不是智慧,是把协作拆成了看得见的零件:板子、信箱、编号、桌子。 - [p6-13] 官方工程博客泼的冷水也要听:并行和专精,必须挣回协调成本—— - [p6-14] 他们算过账,多智能体的花销,大约是普通对话的十五倍。 @@ -193,4 +193,4 @@ - [p6-16] 涉及产品内部的部分,为第三方源码分析,片中已逐处标注。 - [p6-16a] 最后一句设计者的自省值得带走:常问自己,可以停掉哪一件。 - [p6-16b] 每一样零件都押着一条「模型做不到」的赌注。模型变强,赌注就过期。 -- [p6-17] 下期,再往上一层:怎么给这样的系统打分。分数会骗人,过程不会——下期见。 +- [p6-17] 下期再往上一层:怎么给这样的系统打分。分数会骗人,过程不会——下期见。 diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json index 1562ee5f..6a0b377d 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.json @@ -7,17 +7,17 @@ { "id": "p0-02", "scene": "P0", - "text": "根源有点吓人:它每来一轮,都把你们说过的话从头重读一遍——它没有昨天。" + "text": "根源有点吓人:它每跑一轮,都把你们说过的话从头重读一遍——它没有昨天。" }, { "id": "p0-03", "scene": "P0", - "text": "这一集拆管它视野的五样装置。其中一样,刚刚被官方收回去。" + "text": "这一集要拆的,是管它视野的五样装置。其中一样,刚刚被官方收回去。" }, { "id": "p0-04", "scene": "P0", - "text": "全部内容平铺在桌上,谁新谁旧全凭距离,最初那张任务单被越挤越远。" + "text": "问题出在桌上:内容全平铺,谁新谁旧全凭距离,最初那张任务单被越挤越远。" }, { "id": "p0-05", @@ -32,17 +32,17 @@ { "id": "p0-07", "scene": "P0", - "text": "写下来的清单,另开的副桌,按需翻开的目录,每轮重拼的垫纸,一张补救梯。" + "text": "写下来的清单,另开的副桌,按需翻开的目录,每轮重拼的垫纸,还有补救梯。" }, { "id": "p0-08", "scene": "P0", - "text": "官方给 Harness 的定义有四件:循环、工具、上下文管理、护栏。" + "text": "官方把 Harness 定义成四件:循环、工具、上下文管理、护栏。" }, { "id": "p0-09", "scene": "P0", - "text": "今天补的正是上下文管理的前半:它每一轮能看见什么。" + "text": "今天讲的正是上下文管理的前半:它每一轮能看见什么。" }, { "id": "p1-01", @@ -62,7 +62,7 @@ { "id": "p1-05", "scene": "P1", - "text": "然后奇迹发生了——注意,这个工具本身,什么都不执行。" + "text": "而奇怪的地方就在这儿:这个工具本身,什么都不执行。" }, { "id": "p1-06", @@ -97,7 +97,7 @@ { "id": "p1-12", "scene": "P1", - "text": "有位作者的句话说得很准:这个工具不增加任何执行能力," + "text": "有位作者有句话说得很准:这个工具不增加任何执行能力," }, { "id": "p1-13", @@ -112,7 +112,7 @@ { "id": "p1-15", "scene": "P1", - "text": "理由说得很直白:这些模型自己就能记住要干什么。押注押到期了。" + "text": "理由说得很直白:这些模型自己就能记住要干什么。这一注,到期了。" }, { "id": "p1-15a", @@ -122,17 +122,17 @@ { "id": "p1-15b", "scene": "P1", - "text": "这道门叫计划模式:先只读地探索,把计划写出来给你过目。" + "text": "这道门叫计划模式:先只看不动手地探索,把计划写出来给你过目。" }, { "id": "p1-15c", "scene": "P1", - "text": "计划没批,改文件的动作一律拦住——想动手?先说服你。" + "text": "计划没批,改文件的动作一律拦住——它想动手,得先说服你。" }, { "id": "p1-15d", "scene": "P1", - "text": "批准那一下你有三个选择:交给自动闸门、逐条人工点头、或者继续再想。" + "text": "批准那一下你有三个选择:交给自动闸门、逐条人工点头、或者再想想。" }, { "id": "p1-15e", @@ -142,7 +142,7 @@ { "id": "p1-16", "scene": "P1", - "text": "清单背后那套更重的任务系统——带依赖、能锁、落盘——那套以后单拆,先记一句:" + "text": "清单背后那套带依赖、能锁、落盘的任务系统,以后单说。先记一句:" }, { "id": "p1-18", @@ -152,7 +152,7 @@ { "id": "p1-19", "scene": "P1", - "text": "一个什么都不执行的工具,成了长活不跑偏的关键——这种反差,后面还会遇到几次。" + "text": "什么都不执行的工具,成了长活不跑偏的关键。这种反差,后面还会遇到几次。" }, { "id": "p2-01", @@ -177,7 +177,7 @@ { "id": "p2-05", "scene": "P2", - "text": "你自己遇到这种事会怎么办?开一个新终端去翻,翻完关掉,把结论记回本子上。" + "text": "你遇到这种事会怎么办?开一个新终端去翻,翻完关掉,把结论记回本子上。" }, { "id": "p2-06", @@ -202,7 +202,7 @@ { "id": "p2-11", "scene": "P2", - "text": "注意丢的是什么:写过的文件、改过的代码都还在硬盘上——丢的只是纸,不是活。" + "text": "注意丢的是什么:写过的文件、改过的代码都在硬盘上——丢的是纸,不是活。" }, { "id": "p2-12", @@ -222,7 +222,7 @@ { "id": "p2-16", "scene": "P2", - "text": "官方文档后来证实了 Claude Code 里的那个反转," + "text": "官方文档后来证实了 Claude Code 里的一个反转," }, { "id": "p2-17", @@ -247,7 +247,7 @@ { "id": "p2-21", "scene": "P2", - "text": "所以那套机制反着来:把父亲桌上的东西几乎原样搬给分身,让前缀保持一致。" + "text": "所以分叉模式反着来:把父亲桌上的东西几乎原样搬给分身,让前缀保持一致。" }, { "id": "p2-22", @@ -277,12 +277,12 @@ { "id": "p2-27", "scene": "P2", - "text": "分身要弹审批窗,也会冒泡弹到父亲的屏幕上,还是你来点头。" + "text": "分身要弹审批窗,也会冒泡到父亲的屏幕上,还是你来点头。" }, { "id": "p2-28", "scene": "P2", - "text": "派出去慢慢干的玩法以后单说。" + "text": "至于派出去慢慢干的玩法,以后单拆。" }, { "id": "p2-28a", @@ -307,7 +307,7 @@ { "id": "p2-30", "scene": "P2", - "text": "而它值得记住的第二句是:省钱和隔离,常常是同一个设计的两种说法。" + "text": "还有值得记住的第二句:省钱和隔离,常常是同一个设计的两种说法。" }, { "id": "p3-01", @@ -317,12 +317,12 @@ { "id": "p3-02", "scene": "P3", - "text": "最笨的办法是把所有手册全贴进它的基本设定里。几百上千行,每轮都跟着计费。" + "text": "最笨的办法,是把手册全贴进它的基本设定里。几百上千行,每轮都跟着计费。" }, { "id": "p3-03", "scene": "P3", - "text": "你改一个颜色值,它在重读整个数据库规范——百分九十九的内容跟你无关。" + "text": "你改一个颜色值,它在重读整个数据库规范——百分之九十九的内容跟你无关。" }, { "id": "p3-04", @@ -337,7 +337,7 @@ { "id": "p3-06", "scene": "P3", - "text": "真要用到哪本,再把整本拉上桌——而且整场常驻,压缩后还会重注入。" + "text": "真要用到哪本,再把整本拉上桌——而且整场常驻,压缩之后还会补回来。" }, { "id": "p3-07", @@ -347,22 +347,22 @@ { "id": "p3-08", "scene": "P3", - "text": "官方口径:目录预算有硬顶。" + "text": "官方口径:目录预算设有硬顶。" }, { "id": "p3-08b", "scene": "P3", - "text": "文档里还有句实在话:清单超过两百行,它就开始不老实读了。" + "text": "文档里还有句实在话:清单太长,超过两百行,它就开始不老实读了。" }, { "id": "p3-09", "scene": "P3", - "text": "这个硬顶大约是窗口的百分之一,还设了绝对上限,超了就砍。" + "text": "硬顶有多硬?大约窗口的百分之一,还设了绝对上限,超了就砍。" }, { "id": "p3-10", "scene": "P3", - "text": "还有个安全细节:取手册只认目录里登记过的名字,不走文件路径,防的就是目录穿越。" + "text": "还有个安全细节:取手册只认登记过的名字,不走文件路径,防的是目录穿越。" }, { "id": "p3-11", @@ -397,7 +397,7 @@ { "id": "p3-17", "scene": "P3", - "text": "关键在「真实状态」四个字:工具就查实际注册了哪些,记忆就查文件存不存在。" + "text": "关键在「真实状态」四个字:工具查实际注册了哪些,记忆查文件在不在。" }, { "id": "p3-18", @@ -407,7 +407,7 @@ { "id": "p3-19", "scene": "P3", - "text": "状态没变,拼出来的纸一字不差,那就直接用上一次拼好的——拼本身也不重复花钱。" + "text": "状态没变,拼出来的纸一字不差,直接用上一次的——拼本身也不重复花钱。" }, { "id": "p3-20", @@ -427,12 +427,12 @@ { "id": "p3-22", "scene": "P3", - "text": "拆源码的人还说了个讲究的细节:段落里只有一段,永远不许进缓存——" + "text": "拆源码的人还说了个讲究的细节:所有段落里,只有一段永远不许进缓存——" }, { "id": "p3-23", "scene": "P3", - "text": "外接工具的说明段。因为外接的服务随时会掉线,缓存它就是在缓存一个谎言。" + "text": "外接工具的说明段。外接的服务随时会掉线,缓存它就是在缓存一个谎言。" }, { "id": "p3-24", @@ -447,7 +447,7 @@ { "id": "p3-26", "scene": "P3", - "text": "目录、手册、垫纸——这三样都在回答同一个问题:这一轮,什么该进它的眼睛。" + "text": "目录、手册、垫纸——三样都在回答同一个问题:这一轮,什么该进它的眼睛。" }, { "id": "p4-01", @@ -462,7 +462,7 @@ { "id": "p4-03", "scene": "P4", - "text": "处理得很有章法。第一次,直接把额度上限放大八倍,原封不动重试同一个请求。" + "text": "处理得很有章法。第一次,把额度上限放大八倍,原封不动重试同一个请求。" }, { "id": "p4-04", @@ -472,7 +472,7 @@ { "id": "p4-05", "scene": "P4", - "text": "放大只有一次。再断,才保存半句话,塞一条续写提示:从断掉的半个词接着说。" + "text": "放大只有一次。再断才保存半句话,塞条续写提示:从断掉的地方接着说。" }, { "id": "p4-06", @@ -482,7 +482,7 @@ { "id": "p4-07", "scene": "P4", - "text": "特别有工程品味:别道歉,别复述你刚才在干嘛,直接接着说,把剩下的活切小点。" + "text": "很有工程品味:别道歉,别复述刚才在干嘛,直接接着说,把剩下的活切小点。" }, { "id": "p4-08", @@ -557,7 +557,7 @@ { "id": "p4-19", "scene": "P4", - "text": "拆源码的人还提了个冷静设计:续写要是连着几次没写出新东西," + "text": "拆源码的人还提到个冷静设计:续写要是连着几次没写出新东西," }, { "id": "p4-20", @@ -567,7 +567,7 @@ { "id": "p4-21", "scene": "P4", - "text": "出错不是终点——这确实是这套系统的性格。" + "text": "出错不是终点——这就是这套系统的性格。" }, { "id": "p4-21a", @@ -577,7 +577,7 @@ { "id": "p4-21b", "scene": "P4", - "text": "不过它只看文件改动,跑过的命令改过的外部状态,不在里面。" + "text": "不过它只看文件改动,跑过的命令、改过的外部状态,都不在里面。" }, { "id": "p4-22", @@ -592,7 +592,7 @@ { "id": "p5-02", "scene": "P5", - "text": "钉在桌上的清单,另开的副桌,按需翻开的目录,每轮重拼的垫纸,桌边的补救梯。" + "text": "钉住的清单,另开的副桌,按需翻开的目录,每轮重拼的垫纸,一张补救梯。" }, { "id": "p5-03", @@ -632,7 +632,7 @@ { "id": "p5-13", "scene": "P5", - "text": "视野越管越细,桌子越换越讲究,桌子后面那个循环纹丝不动。" + "text": "视野越管越细,桌面越换越讲究,后面那个循环纹丝不动。" }, { "id": "p5-14", @@ -677,7 +677,7 @@ { "id": "p6-04", "scene": "P6", - "text": "五样零件里,清单那件刚被收回去——零件押的是「模型记不住」的赌注。" + "text": "五样零件里,清单那件刚被收回去——它押的是「模型记不住」的赌注。" }, { "id": "p6-05", diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md index f03b8945..7f653966 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/script/narration.md @@ -15,14 +15,14 @@ > 角标:TodoWrite · "An Agent Without a Plan Drifts Off Course" - [p0-01] 你交给它一个大活,它干了三步,就忘了自己来干嘛。 -- [p0-02] 根源有点吓人:它每来一轮,都把你们说过的话从头重读一遍——它没有昨天。 -- [p0-03] 这一集拆管它视野的五样装置。其中一样,刚刚被官方收回去。 -- [p0-04] 全部内容平铺在桌上,谁新谁旧全凭距离,最初那张任务单被越挤越远。 +- [p0-02] 根源有点吓人:它每跑一轮,都把你们说过的话从头重读一遍——它没有昨天。 +- [p0-03] 这一集要拆的,是管它视野的五样装置。其中一样,刚刚被官方收回去。 +- [p0-04] 问题出在桌上:内容全平铺,谁新谁旧全凭距离,最初那张任务单被越挤越远。 - [p0-05] 于是问题来了:它这一轮能看见什么,是它自己说了算吗? - [p0-06] 答案:不是。有一整套装置,在替它安排视野。 -- [p0-07] 写下来的清单,另开的副桌,按需翻开的目录,每轮重拼的垫纸,一张补救梯。 -- [p0-08] 官方给 Harness 的定义有四件:循环、工具、上下文管理、护栏。 -- [p0-09] 今天补的正是上下文管理的前半:它每一轮能看见什么。 +- [p0-07] 写下来的清单,另开的副桌,按需翻开的目录,每轮重拼的垫纸,还有补救梯。 +- [p0-08] 官方把 Harness 定义成四件:循环、工具、上下文管理、护栏。 +- [p0-09] 今天讲的正是上下文管理的前半:它每一轮能看见什么。 ## P1 把清单钉在桌上 @@ -32,25 +32,25 @@ - [p1-01] 第一样东西最不起眼:一张写下来的清单。 - [p1-02] 干活之前,先把步骤一条条列出来,每条标一个状态:没开始、干着、干完了。 - [p1-03] 状态只有这三种,不多不少。干一步挪一格,桌子上的进度看得见摸得着。 -- [p1-05] 然后奇迹发生了——注意,这个工具本身,什么都不执行。 +- [p1-05] 而奇怪的地方就在这儿:这个工具本身,什么都不执行。 - [p1-06] 它不能读文件,不能跑命令,唯一的功能就是把清单写下来、摆到它眼前。 - [p1-07] 可正因为清单挂在对话里,每一轮重读的时候,它都会被再看见一次。 - [p1-08] 你以为它忘了,其实是那张纸被几十条工具输出顶到了视野之外。 - [p1-09] 把纸钉回眼前,注意力就回来了。就这么简单,也就这么管用。 - [p1-10] 加这个工具要改几处代码?两处。注册表里添一行,分发表里挂一行。 - [p1-11] 循环本身一行没动——这是我们这一集反复要数的事实。 -- [p1-12] 有位作者的句话说得很准:这个工具不增加任何执行能力, +- [p1-12] 有位作者有句话说得很准:这个工具不增加任何执行能力, - [p1-13] 它增加的,是规划能力。 - [p1-14] 但这件装置刚刚被官方收了回去——新的模型上,清单工具默认不再安装。 -- [p1-15] 理由说得很直白:这些模型自己就能记住要干什么。押注押到期了。 +- [p1-15] 理由说得很直白:这些模型自己就能记住要干什么。这一注,到期了。 - [p1-15a] 那规划这件事就没了吗?没有,它升级成了一道门。 -- [p1-15b] 这道门叫计划模式:先只读地探索,把计划写出来给你过目。 -- [p1-15c] 计划没批,改文件的动作一律拦住——想动手?先说服你。 -- [p1-15d] 批准那一下你有三个选择:交给自动闸门、逐条人工点头、或者继续再想。 +- [p1-15b] 这道门叫计划模式:先只看不动手地探索,把计划写出来给你过目。 +- [p1-15c] 计划没批,改文件的动作一律拦住——它想动手,得先说服你。 +- [p1-15d] 批准那一下你有三个选择:交给自动闸门、逐条人工点头、或者再想想。 - [p1-15e] 清单是写给它自己看的;计划,是写给你看的。 -- [p1-16] 清单背后那套更重的任务系统——带依赖、能锁、落盘——那套以后单拆,先记一句: +- [p1-16] 清单背后那套带依赖、能锁、落盘的任务系统,以后单说。先记一句: - [p1-18] 把计划写下来,本身就是一种能力。而且是装在循环外面的能力。 -- [p1-19] 一个什么都不执行的工具,成了长活不跑偏的关键——这种反差,后面还会遇到几次。 +- [p1-19] 什么都不执行的工具,成了长活不跑偏的关键。这种反差,后面还会遇到几次。 ## P2 另开一张副桌 @@ -61,33 +61,33 @@ - [p2-02] 比如追一个缺陷,要读三十个文件、翻六十轮对话。 - [p2-03] 等你找到问题在哪,桌上已经堆了一百多条记录,绝大部分是中间过程。 - [p2-04] 这些纸每一轮都被重读一遍,跟目标无关,但一直占着位置、一直计着费。 -- [p2-05] 你自己遇到这种事会怎么办?开一个新终端去翻,翻完关掉,把结论记回本子上。 +- [p2-05] 你遇到这种事会怎么办?开一个新终端去翻,翻完关掉,把结论记回本子上。 - [p2-06] 它也一样:另开一张干净的副桌,派一个分身过去干。 - [p2-07] 副桌上是一份全新的对话记录,干干净净,只有一句任务说明。 - [p2-08] 分身在那边自己跑自己的循环,读文件、改代码,跟主桌互不打扰。 - [p2-09] 主桌上你看不到那三十个文件的任何一行,中间过程全丢,只带回一张回执。 -- [p2-11] 注意丢的是什么:写过的文件、改过的代码都还在硬盘上——丢的只是纸,不是活。 +- [p2-11] 注意丢的是什么:写过的文件、改过的代码都在硬盘上——丢的是纸,不是活。 - [p2-12] 纪律第一条:最简实现不许分身再派分身;真实实现放开到三层,同时二十个。 - [p2-14] 第二条:分身每次动手之前,照样要过那几道闸门。 - [p2-15] 隔离的是视野,不是权限。它看不见你俩的对话,但它一样不能为所欲为。 -- [p2-16] 官方文档后来证实了 Claude Code 里的那个反转, +- [p2-16] 官方文档后来证实了 Claude Code 里的一个反转, - [p2-17] 是这一集最反直觉的地方:它内部有一种分叉模式,动机根本不是隔离, - [p2-18] 是为了省钱——命中缓存。 - [p2-19] 什么意思?对话按字数花钱;同样的开头算过一遍,短时间内第二遍近乎免费。 - [p2-20] 分身如果从头建立自己的桌面,前缀全变了,每一段都得原价重新算。 -- [p2-21] 所以那套机制反着来:把父亲桌上的东西几乎原样搬给分身,让前缀保持一致。 +- [p2-21] 所以分叉模式反着来:把父亲桌上的东西几乎原样搬给分身,让前缀保持一致。 - [p2-22] 「几乎」是有严格定义的:系统提示、工具表、模型、消息前缀、思考配置, - [p2-23] 差一个字,白算——五样全对上,缓存才认。 - [p2-24] 隔离是搂草打兔子,省钱才是真心话。 - [p2-25] 还有更诚实的:隔离其实是半拉的。有位作者说,分身会继承父亲读过的文件, - [p2-26] 免得同一个文件读两遍。桌是分开了,有些抽屉还是共用的。 -- [p2-27] 分身要弹审批窗,也会冒泡弹到父亲的屏幕上,还是你来点头。 -- [p2-28] 派出去慢慢干的玩法以后单说。 +- [p2-27] 分身要弹审批窗,也会冒泡到父亲的屏幕上,还是你来点头。 +- [p2-28] 至于派出去慢慢干的玩法,以后单拆。 - [p2-28a] 官方还给分身套了三个上限,像三只笼子:同时在场最多二十个, - [p2-28b] 每个有自己的轮数上限,还有整份上下文的配额——烧完就收工。 - [p2-28c] 放得开,也拴得住。副桌再多,也翻不出这三只笼子。 - [p2-29] 副桌这一样,记住一句:脏活不占主桌。 -- [p2-30] 而它值得记住的第二句是:省钱和隔离,常常是同一个设计的两种说法。 +- [p2-30] 还有值得记住的第二句:省钱和隔离,常常是同一个设计的两种说法。 ## P3 目录卡与垫纸 @@ -96,33 +96,33 @@ > 角标:`load_skill` · ~1% 上下文预算 · PROMPT_SECTIONS - [p3-01] 第三样,管的是知识。规范、手册、风格指南,这些它干活前该知道的东西。 -- [p3-02] 最笨的办法是把所有手册全贴进它的基本设定里。几百上千行,每轮都跟着计费。 -- [p3-03] 你改一个颜色值,它在重读整个数据库规范——百分九十九的内容跟你无关。 +- [p3-02] 最笨的办法,是把手册全贴进它的基本设定里。几百上千行,每轮都跟着计费。 +- [p3-03] 你改一个颜色值,它在重读整个数据库规范——百分之九十九的内容跟你无关。 - [p3-04] 解法是两级:桌角常驻一叠目录卡,每张卡就一行:这份手册叫什么、管什么。 - [p3-05] 一张卡的价钱,大约是整本手册的二十分之一。桌角摆一排,也不心疼。 -- [p3-06] 真要用到哪本,再把整本拉上桌——而且整场常驻,压缩后还会重注入。 +- [p3-06] 真要用到哪本,再把整本拉上桌——而且整场常驻,压缩之后还会补回来。 - [p3-07] 最简的做法很直白:目录常驻,内容按需。 -- [p3-08] 官方口径:目录预算有硬顶。 -- [p3-08b] 文档里还有句实在话:清单超过两百行,它就开始不老实读了。 -- [p3-09] 这个硬顶大约是窗口的百分之一,还设了绝对上限,超了就砍。 -- [p3-10] 还有个安全细节:取手册只认目录里登记过的名字,不走文件路径,防的就是目录穿越。 +- [p3-08] 官方口径:目录预算设有硬顶。 +- [p3-08b] 文档里还有句实在话:清单太长,超过两百行,它就开始不老实读了。 +- [p3-09] 硬顶有多硬?大约窗口的百分之一,还设了绝对上限,超了就砍。 +- [p3-10] 还有个安全细节:取手册只认登记过的名字,不走文件路径,防的是目录穿越。 - [p3-11] 第四样东西,管的是桌面上那张最大的纸——它的基本设定本身。 - [p3-12] 你跟它说的每一句话之前,都垫着这么一张纸:你是谁、你在哪、能干什么。 - [p3-13] 最简的做法是从第一行起就写死。能力越加越多,纸越写越长。 - [p3-14] 换个项目要重写整张纸,改一段可能跟别处打架,而且每轮都全文计费。 - [p3-15] 而真实的实现是拆成几段——身份、工具清单、工作目录、相关记忆。 - [p3-16] 每一轮,按当场的真实状态重新拼一次。状态变了,纸跟着变。 -- [p3-17] 关键在「真实状态」四个字:工具就查实际注册了哪些,记忆就查文件存不存在。 +- [p3-17] 关键在「真实状态」四个字:工具查实际注册了哪些,记忆查文件在不在。 - [p3-18] 不去猜消息里出现了什么关键词。猜关键词,是给幻觉开门。 -- [p3-19] 状态没变,拼出来的纸一字不差,那就直接用上一次拼好的——拼本身也不重复花钱。 +- [p3-19] 状态没变,拼出来的纸一字不差,直接用上一次的——拼本身也不重复花钱。 - [p3-20] 有人拆过它的源码,说这张垫纸常规状态两三万字、极简模式两行。 - [p3-21] 更大的反转来自官方:2026年7月,这张纸删掉八成以上,评测不掉分。 - [p3-21a] 纸能写多长,取决于模型有多不需要你替它写。 -- [p3-22] 拆源码的人还说了个讲究的细节:段落里只有一段,永远不许进缓存—— -- [p3-23] 外接工具的说明段。因为外接的服务随时会掉线,缓存它就是在缓存一个谎言。 +- [p3-22] 拆源码的人还说了个讲究的细节:所有段落里,只有一段永远不许进缓存—— +- [p3-23] 外接工具的说明段。外接的服务随时会掉线,缓存它就是在缓存一个谎言。 - [p3-24] 你看,连「哪段纸可以复用」都是被精确设计过的。 - [p3-25] 这张垫纸,每轮都在拼,但它拼得比谁都勤俭。 -- [p3-26] 目录、手册、垫纸——这三样都在回答同一个问题:这一轮,什么该进它的眼睛。 +- [p3-26] 目录、手册、垫纸——三样都在回答同一个问题:这一轮,什么该进它的眼睛。 ## P4 桌边的补救梯 @@ -131,11 +131,11 @@ - [p4-01] 第五样,管的是意外。活干到一半出岔子,是生产的常态,不是事故。 - [p4-02] 第一种岔子:话说到一半,额度用完了,句子断在半空。 -- [p4-03] 处理得很有章法。第一次,直接把额度上限放大八倍,原封不动重试同一个请求。 +- [p4-03] 处理得很有章法。第一次,把额度上限放大八倍,原封不动重试同一个请求。 - [p4-04] 注意是原封不动:半句先不存,加够额度再来一遍。 -- [p4-05] 放大只有一次。再断,才保存半句话,塞一条续写提示:从断掉的半个词接着说。 +- [p4-05] 放大只有一次。再断才保存半句话,塞条续写提示:从断掉的地方接着说。 - [p4-06] 续写最多三次,三次还断就收手。有人拆过源码,把那条提示原文抄了出来, -- [p4-07] 特别有工程品味:别道歉,别复述你刚才在干嘛,直接接着说,把剩下的活切小点。 +- [p4-07] 很有工程品味:别道歉,别复述刚才在干嘛,直接接着说,把剩下的活切小点。 - [p4-08] 第二种岔子:桌上太满,装不下了,服务那边直接拒收。 - [p4-09] 先压一轮——把旧纸换成摘要腾地方;压完还装不下,就承认装不下,退出。 - [p4-10] 压过一次还压第二次没有意义:纸不会越压越小,该退就退。 @@ -150,11 +150,11 @@ - [p4-17d] 原样重发一次,同一个动作就跑了两遍。 - [p4-17e] 它的做法是保住已产出的,插一条「没写完」的标记,从断点接着来。 - [p4-17f] 顺带给个刻度:默认最多重试十次,上限十五次。 -- [p4-19] 拆源码的人还提了个冷静设计:续写要是连着几次没写出新东西, +- [p4-19] 拆源码的人还提到个冷静设计:续写要是连着几次没写出新东西, - [p4-20] 系统就直接判定——再续也没有产出,停。不恋战,也是一种能力。 -- [p4-21] 出错不是终点——这确实是这套系统的性格。 +- [p4-21] 出错不是终点——这就是这套系统的性格。 - [p4-21a] 官方还有个兜底的后悔药:改动可以回退到前面的检查点—— -- [p4-21b] 不过它只看文件改动,跑过的命令改过的外部状态,不在里面。 +- [p4-21b] 不过它只看文件改动,跑过的命令、改过的外部状态,都不在里面。 - [p4-22] 你会发现每一级补救都带着上限:升一次、续三次、等三十二秒、换一次人。 ## P5 桌子换了五样,环没动 @@ -163,7 +163,7 @@ > 角标:五段增量全部为「外挂」· while 骨架未换(实测 @ 67a9126c) - [p5-01] 收个尾。这一集的五样东西摆在一起看: -- [p5-02] 钉在桌上的清单,另开的副桌,按需翻开的目录,每轮重拼的垫纸,桌边的补救梯。 +- [p5-02] 钉住的清单,另开的副桌,按需翻开的目录,每轮重拼的垫纸,一张补救梯。 - [p5-03] 它们管理的是同一件事:这一轮,模型能看见什么。 - [p5-04] 清单负责「别忘」,副桌负责「别堵」,目录负责「别贪」, - [p5-05] 垫纸负责「别写死」,梯子负责「别断」。 @@ -171,7 +171,7 @@ - [p5-07] 你会发现一个熟悉的形状:这五样,没有一样写进循环。 - [p5-08] 清单是工具,副桌是调用,目录是注册表,垫纸是拼装,梯子是包裹。 - [p5-09] 我逐一比过这些增量代码:加的全是外挂,那句「不停问模型」一个字没换。 -- [p5-13] 视野越管越细,桌子越换越讲究,桌子后面那个循环纹丝不动。 +- [p5-13] 视野越管越细,桌面越换越讲究,后面那个循环纹丝不动。 - [p5-14] 所以它干活越来越稳,不是它变聪明了。 - [p5-15] 是有人替它把视野管了起来。 - [p5-16] 而管视野这件事,本身就是一门可以被看懂的手艺。 @@ -187,7 +187,7 @@ - [p6-01] 视野是安排出来的。安排它的,不是模型自己。 - [p6-02] 这句话对人也成立:你的注意力在哪,多半也不是你自己定的, - [p6-03] 是你桌上摆了什么、谁在什么时候塞了张纸给你。 -- [p6-04] 五样零件里,清单那件刚被收回去——零件押的是「模型记不住」的赌注。 +- [p6-04] 五样零件里,清单那件刚被收回去——它押的是「模型记不住」的赌注。 - [p6-05] 模型变强,赌注就过期。官方留了句自省的话:常问自己,可以停掉哪一件。 - [p6-06] 桌子会换,零件会瘦,那个循环一直没停过。 - [p6-09] 下期:它会忘,而且忘得有章法——但有一样东西,它永远不许忘。下期见。 From b8e2d82f02838a334174ba998b2a0e8a795b0dc2 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sat, 29 Aug 2026 20:24:17 +0800 Subject: [PATCH 38/41] =?UTF-8?q?feat(video):=20=E7=BB=88=E6=B8=B2=20v5=20?= =?UTF-8?q?=E4=BA=A4=E4=BB=98=E2=80=94=E2=80=94W9=20=E6=96=87=E6=A1=88?= =?UTF-8?q?=E6=B6=A6=E8=89=B2=20122=20=E5=8F=A5=E9=87=8D=E9=85=8D=E8=90=BD?= =?UTF-8?q?=E6=B8=B2=20+=20=E8=A7=86=E8=A7=89=2013=20=E5=A4=84=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E5=9B=9E=E5=BD=92=E5=85=A8=E5=87=80;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 五集 v5:14:12 / 13:23 / 13:37 / 13:05 / 13:27(合计 67.7 分钟 1080p30)。 W9 修复帧位回归 15/15 帧全净;五集七幕体检 FAIL 0 · WARN 0;EP5 沙箱镜 (整镜 21.6s 空白根因修复)视觉模型终验完整呈现。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- apps/negentropy-influence/series.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/negentropy-influence/series.json b/apps/negentropy-influence/series.json index 14057f83..f2afa16a 100644 --- a/apps/negentropy-influence/series.json +++ b/apps/negentropy-influence/series.json @@ -102,7 +102,7 @@ "accessed": "2026-08-21" }, "status": "delivered", - "statusNote": "终渲 v4:14:11 = 25541 帧 @30fps · 47.1 MB;W8 帧级审查 892 帧 60 缺陷 49 修(SceneTag 叠印根因+越窗+穿字);回归 52 帧全净", + "statusNote": "终渲 v5:14:12 = 25582 帧 · 47.1 MB;W9 文案 9 句润色 + EP1 帧审 120 帧净;七幕 FAIL 0", "voice": "sunny-steady + me-bright.wav" }, { @@ -124,7 +124,7 @@ "accessed": "2026-08-22" }, "status": "delivered", - "statusNote": "终渲 v4:13:27 = 24215 帧 @30fps · 42.7 MB;W8 修复 9 处(终端糊字/金句劈行母题级修复等);回归 11 帧全净", + "statusNote": "终渲 v5:13:23 = 24103 帧 · 42.2 MB;W9 文案 42 句润色 + 视觉 5 处(镜首真空/过稀/音画错位);七幕 FAIL 0", "voice": "sunny-steady + me-bright.wav" }, { @@ -146,7 +146,7 @@ "accessed": "2026-08-22" }, "status": "delivered", - "statusNote": "终渲 v4:13:36 = 24492 帧 @30fps · 41.7 MB;W8 修复 7 处(矩阵×回捞桌 24 秒叠印/死代码根因);回归 7 帧全净", + "statusNote": "终渲 v5:13:37 = 24512 帧 · 41.9 MB;W9 文案 19 句润色 + 视觉 5 处死空气根除;七幕 FAIL 0", "voice": "sunny-steady + me-bright.wav" }, { @@ -168,7 +168,7 @@ "accessed": "2026-08-22" }, "status": "delivered", - "statusNote": "终渲 v4:13:09 = 23672 帧 @30fps · 44.7 MB;W8 修复 11 处(SceneTag 残留 10 处/天平重印等);回归 10 帧全净", + "statusNote": "终渲 v5:13:05 = 23571 帧 · 44.5 MB;W9 文案 21 句润色 + 视觉 2 处(秒针切字/锚点压标);七幕 FAIL 0", "voice": "sunny-steady + me-bright.wav" }, { @@ -190,7 +190,7 @@ "accessed": "2026-08-22" }, "status": "delivered", - "statusNote": "终渲 v4:13:26 = 24197 帧 @30fps · 47.2 MB;W8 修复 14 处(四道闸压底座/收官金句×角标压印等);回归 14 帧全净", + "statusNote": "终渲 v5:13:27 = 24236 帧 · 47.8 MB;W9 文案 31 句润色 + 沙箱镜整镜 21.6s 空白根因修复;七幕 FAIL 0", "voice": "sunny-steady + me-bright.wav" } ] From 6e2e107542fbad5872813f963ff05ea0618d9f86 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sun, 30 Aug 2026 03:26:01 +0800 Subject: [PATCH 39/41] =?UTF-8?q?feat(video):=20W10=20=E8=AF=AD=E4=BD=93?= =?UTF-8?q?=E7=BA=A7=E9=87=8D=E5=86=99=E2=80=94=E2=80=94=E4=BA=94=E9=9B=86?= =?UTF-8?q?=20527=20=E5=8F=A5=E5=8E=BB=E6=9C=BA=E5=99=A8=E8=85=94=EF=BC=8C?= =?UTF-8?q?=E7=A0=B4=E6=8A=98=E5=8F=B7=E5=85=A8=E7=B3=BB=E5=88=97=E6=B8=85?= =?UTF-8?q?=E9=9B=B6;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户第三轮反馈「不像人话」,量化定位三个病根后整句重铸(非润色): 1. 对照名词残留(最简实现×9/实际实现×5/最简的做法×5,W7 引入)→ 语境化替换 (玩具版/最小的一个示例/真的那个/它回指),同词全系列 ≤2 次。 2. 破折号密度(EP3 30%/EP4 23%/EP5 25% 句含「——」)→ 拆短句/冒号/直接删, 五集全部清零(0 处)。 3. 节奏均匀(连续 21 句中长句)→ 每幕补短句爆点(「问都不问」「规则是劝, 沙箱是锁」「连砸三次就熔断」)。 样例对比: - 「最简实现身上只带一份消息列表;实际的 Harness 带了十样」→「玩具版身上 就一张纸。真的那个呢?十样。」 - 「重写要是连着失败三次,熔断,不再试——别把预算烧在死循环上」→ 「连砸三次就熔断。死循环不配烧预算。」 句 id/句序零变动;字数 4021/3906/3916/3853/3901 全收敛;check --check-scenes 五集全绿;~527 句全量重配中(TTS 长跑)。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../script/narration.json | 210 ++++++++-------- .../script/narration.md | 210 ++++++++-------- .../script/narration.json | 188 +++++++-------- .../script/narration.md | 210 ++++++++-------- .../script/narration.json | 228 +++++++++--------- .../script/narration.md | 228 +++++++++--------- .../video/src/scenes/P0Reject.tsx | 19 ++ .../video/src/scenes/P4Ledger.tsx | 23 +- .../script/narration.json | 218 ++++++++--------- .../script/narration.md | 218 ++++++++--------- .../video/src/scenes/P4Autonomy.tsx | 19 +- .../script/narration.json | 210 ++++++++-------- .../script/narration.md | 210 ++++++++-------- .../video/src/scenes/P2SideDesk.tsx | 72 +++++- .../video/src/scenes/P3Manual.tsx | 79 +++++- .../video/src/scenes/P4Ladder.tsx | 17 +- 16 files changed, 1273 insertions(+), 1086 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json index b7802815..38dd4214 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.json @@ -2,7 +2,7 @@ { "id": "p0-01", "scene": "P0", - "text": "你让它跑个安装,进度条爬了十分钟,它就干等了十分钟。" + "text": "你让它跑个安装,进度条爬了十分钟,它就在那儿干等了十分钟。" }, { "id": "p0-02", @@ -12,27 +12,27 @@ { "id": "p0-03", "scene": "P0", - "text": "同一篇博客说,不看着它,它会高高兴兴把测试跑上几个小时。" + "text": "同一篇博客还说,不看着它,它会高高兴兴把测试跑上好几个小时。" }, { "id": "p0-04", "scene": "P0", - "text": "所以表不归它管——归外面那层工程。这一集拆那只替它看表的手。" + "text": "所以表不归它管,归外面那层工程。这一集,就拆那只替它看表的手。" }, { "id": "p0-05", "scene": "P0", - "text": "换成你,你会站在洗衣机前面盯着滚筒等三十分钟吗?" + "text": "换成你呢?你会站在洗衣机前面,盯着滚筒干等三十分钟吗?" }, { "id": "p0-06", "scene": "P0", - "text": "不会。按下启动去做别的,等它滴滴滴叫你。" + "text": "不会。按下就走。" }, { "id": "p0-07", "scene": "P0", - "text": "这个动作拆开是两件事:活交给机器,人不陪着等。" + "text": "等它滴滴滴叫你。这一下拆开,其实是两件事:活交给机器,人不陪着等。" }, { "id": "p0-08", @@ -42,47 +42,47 @@ { "id": "p0-09", "scene": "P0", - "text": "先说清它缺什么:不光感觉不到时间,也不会自己安排等待。" + "text": "先说清它到底缺什么。不光是感觉不到时间,也不会自己安排等待。" }, { "id": "p0-10", "scene": "P0", - "text": "官方管这个叫时间盲症:模型没有钟、没有闹钟、也没有「回头再看」的本能。" + "text": "官方管这个叫时间盲症。没有钟,没有闹钟,也没有「回头再看」的本能。" }, { "id": "p0-11", "scene": "P0", - "text": "于是第一步,把「等」摘掉:按下就走开,活交给机器。" + "text": "于是第一步,先把「等」摘掉:按下就走开,活交给机器。" }, { "id": "p0-12", "scene": "P0", - "text": "第二步更进一步:连按的人都可以不要,时间到了自己开始。" + "text": "第二步更狠:连按的人都不要,时间到了自己开始。每步都有真话,也有坑。" }, { "id": "p0-13", "scene": "P0", - "text": "每一步都有真话要讲,也有坑要躲。这就开拆。" + "text": "这就开拆吧。" }, { "id": "p1-01", "scene": "P1", - "text": "先说第一层:按下开始就走开。" + "text": "先说第一层。按下就走开。" }, { "id": "p1-02", "scene": "P1", - "text": "谁来决定一件活要不要丢后台?主路是它自己——" + "text": "谁来决定一件活要不要丢后台?主路是它自己。" }, { "id": "p1-03", "scene": "P1", - "text": "跑命令的工具上有一个「后台执行」的开关,它勾了,活就走后台。" + "text": "跑命令的那个工具上有一个「后台执行」的开关。它勾了,活就走后台。" }, { "id": "p1-04", "scene": "P1", - "text": "官方还有个真机制:命令到了超时线,不被杀掉,而是自动滑入后台接着跑。" + "text": "官方还有个真机制:命令到了超时线,不被杀掉,而是自动滑进后台接着跑。" }, { "id": "p1-05", @@ -92,12 +92,12 @@ { "id": "p1-06", "scene": "P1", - "text": "活丢出去之后,画面上发生的事最值得看:那个循环,没有停。" + "text": "活丢出去之后,画面上最值得看的是这个:那个循环,一秒都没停。" }, { "id": "p1-07", "scene": "P1", - "text": "慢命令块滑到环外的一条旁轨上自己跑;循环口立刻贴上一张占位条," + "text": "慢命令块滑到环外的一条旁轨上自己跑,循环口立刻贴上一张占位条。" }, { "id": "p1-08", @@ -107,7 +107,7 @@ { "id": "p1-09", "scene": "P1", - "text": "这个安排有个前提要交代:那个跑后台的活,是个「守护」的身份——" + "text": "这个安排有个前提得先交代。那个跑后台的活,身份是个「守护」。" }, { "id": "p1-10", @@ -117,12 +117,12 @@ { "id": "p1-11", "scene": "P1", - "text": "这里有个容易被想岔的点。有人拆过它的源码,一句话说穿了:" + "text": "这里有个特别容易想岔的点。有人读源码,读出来一句大实话:" }, { "id": "p1-12", "scene": "P1", - "text": "所谓后台,根本不是一个并行的宇宙。整套系统跑在单线程里," + "text": "所谓后台,根本不是另一个并行的宇宙。整套系统就跑在单线程里。" }, { "id": "p1-13", @@ -132,27 +132,27 @@ { "id": "p1-14", "scene": "P1", - "text": "等待被拿掉了,不是并发被造出来了。" + "text": "拿掉了等待,没造出并发。" }, { "id": "p1-15", "scene": "P1", - "text": "这一集所有魔法,都是这一个动作的变体:把「等」从某个人身上摘走。" + "text": "这一集所有的魔法,都是这一个动作的变体:把「等」从某个人身上摘走。" }, { "id": "p1-16", "scene": "P1", - "text": "再多看一眼那个占位条。它不是随口一句「跑着呢」——" + "text": "再多看一眼那个占位条。它可不是随口一句「跑着呢」。" }, { "id": "p1-17", "scene": "P1", - "text": "它带着一个任务编号。这个编号后面有大用,先记在这里。" + "text": "它身上带着一个任务编号。这个编号后面有大用,先记在这儿。" }, { "id": "p1-18", "scene": "P1", - "text": "对了,这个「自己勾后台」的设计本身也值得一句:" + "text": "对了,「自己勾后台」这个设计本身,也值得说一句:" }, { "id": "p1-19", @@ -167,12 +167,12 @@ { "id": "p1-21", "scene": "P1", - "text": "「守护」这个身份,前面只说了一半,还有反过来的一半:" + "text": "「守护」这个身份,刚才只说了一半,还有反过来的一半。" }, { "id": "p1-22", "scene": "P1", - "text": "只要它还活着,后台就一直在。你中途想问进度、想停掉,都行——" + "text": "只要它还活着,后台就一直在。你中途想问进度、想停掉,都行。" }, { "id": "p1-23", @@ -187,67 +187,67 @@ { "id": "p2-01", "scene": "P2", - "text": "第二个问题:活干完了,怎么接回来?" + "text": "活干完了,怎么接回来?" }, { "id": "p2-02", "scene": "P2", - "text": "细节比你想的讲究。派活那一刻,占位条就已经把结果的位置占了——" + "text": "细节比你想的讲究。派活的那一刻,占位条就已经把结果的位置先占住了。" }, { "id": "p2-03", "scene": "P2", - "text": "一次调用,永远对应一条结果,这个配对关系不许破坏。" + "text": "一次调用对一条结果。" }, { "id": "p2-04", "scene": "P2", - "text": "所以真结果回来时,不能冒充那条占位,它得换一个身份:" + "text": "这个配对不许破。所以真结果回来的时候,不能冒充占位,它得换个身份。" }, { "id": "p2-05", "scene": "P2", - "text": "变成一张完成通知,排进队列;下一轮跟别的结果合并成一条消息递进去。" + "text": "变成一张完成通知,排进队列,下一轮跟别的结果并成一条消息递进去。" }, { "id": "p2-06", "scene": "P2", - "text": "递进去的时机也是设计过的。有人拆过它的源码——队列其实分两级:" + "text": "递进去的时机也是设计过的。有人读源码读出来:队列其实分两级。" }, { "id": "p2-07", "scene": "P2", - "text": "「下一轮」和「稍后」。后台完成的通知,默认排在「稍后」——" + "text": "「下一轮」和「稍后」。后台完成的通知,默认排在「稍后」。" }, { "id": "p2-08", "scene": "P2", - "text": "也就是说它不插队。你新输入的一句话,永远排在它的前面。" + "text": "也就是说,它不插队。你新输入的那句话,永远排在它的前面。" }, { "id": "p2-09", "scene": "P2", - "text": "打个比方:门口的信箱。活干完往里投信,开不开箱,看主人何时路过。" + "text": "打个比方:门口的信箱。活干完往里投信。开不开箱,看主人什么时候路过。" }, { "id": "p2-10", "scene": "P2", - "text": "这个「不插队」的安排,乍看不起眼,细想很关键。" + "text": "这个「不插队」的安排,乍一看不起眼,细想下去很关键。" }, { "id": "p2-11", "scene": "P2", - "text": "你正问它一个正经问题,后台忽然蹦出来「装依赖好了」," + "text": "你正问它一个正经问题呢,后台忽然蹦出来一句「装依赖好了」。" }, { "id": "p2-12", "scene": "P2", - "text": "话头被截走,它的思路也跟着跑了。排队,保护的是对话的完整性。" + "text": "话头被截走,它的思路也跟着跑偏了。排队保护的,是整段对话的完整。" }, { "id": "p2-13", "scene": "P2", - "text": "活不止一种:能丢后台的有七种——跑命令、本地分身、远程分身、" + "text": "活不止一种。能丢后台的有七种:跑命令、本地分身、远程分身、" }, { "id": "p2-14", @@ -262,7 +262,7 @@ { "id": "p2-16", "scene": "P2", - "text": "还有一层安心:你随时可以主动开信箱,问一句后台的活怎么样了。" + "text": "还有一层安心。你随时可以主动开信箱,问一句后台的活怎么样了。" }, { "id": "p2-17", @@ -272,27 +272,27 @@ { "id": "p2-18", "scene": "P2", - "text": "前面留的伏笔——占位条上的任务编号,现在派上用场了。" + "text": "前面留的伏笔,占位条上那个任务编号,现在派上用场了。" }, { "id": "p2-19", "scene": "P2", - "text": "完成通知带着同一个编号回来对号——编号就是后台世界的取件码。" + "text": "完成通知带着同一个编号回来对号入座。编号就是后台世界的取件码。" }, { "id": "p2-20", "scene": "P2", - "text": "该把哪句「等它结果」的话补上,一查便知。账目永远平的:" + "text": "该把哪句「等它结果」的话补回去,一查便知。账目永远是平的。" }, { "id": "p2-21", "scene": "P2", - "text": "每次调用都有着落,要么当场给结果,要么占位再补通知。" + "text": "每次调用都有着落:要么当场给结果,要么占位再补通知。" }, { "id": "p2-22", "scene": "P2", - "text": "对话这种东西,一旦有账对不上,后面全乱。" + "text": "对话这东西最怕账对不上。一旦对不上,后面全乱。" }, { "id": "p2-23", @@ -302,82 +302,82 @@ { "id": "p3-01", "scene": "P3", - "text": "有,还怪可爱的——有人管它叫看门狗。" + "text": "有。有人管它叫看门狗。" }, { "id": "p3-02", "scene": "P3", - "text": "后台命令有时候会卡住——不是坏了,是它停下来问了个问题。" + "text": "后台命令有时候会卡住。不是坏了,是它自己停下来,问了个问题。" }, { "id": "p3-03", "scene": "P3", - "text": "比如「要不要继续?」——然后干等一个等不来的回答。" + "text": "比如「要不要继续?」然后就在那儿干等一个等不来的回答。" }, { "id": "p3-04", "scene": "P3", - "text": "所以有一只狗盯着每条后台命令的输出:四十五秒没有新动静,它就去看看," + "text": "所以有一只狗盯着每条后台命令的输出。四十五秒没新动静,它就去看看:" }, { "id": "p3-05", "scene": "P3", - "text": "是不是又停在哪个问句上了。是的话,把这件事告诉循环,让人来处理。" + "text": "是不是又停在哪个问句上了。是的话,就把这事告诉循环,让人来处理。" }, { "id": "p3-06", "scene": "P3", - "text": "这只狗的眼睛只认一个指标:输出有没有在长。" + "text": "这只狗只认一个指标。" }, { "id": "p3-07", "scene": "P3", - "text": "还在长,说明它在干活,哪怕慢得像爬,狗都继续趴着。" + "text": "输出有没有在长。还在长,就说明它在干活,哪怕慢得像爬,狗都继续趴着。" }, { "id": "p3-08", "scene": "P3", - "text": "四十五秒一毫米都没动,才起身查看。不猜快慢,只看死活。" + "text": "四十五秒一毫米都没动,它才起身查看。不猜快慢,只看死活。" }, { "id": "p3-09", "scene": "P3", - "text": "后台不是丢出去就不管了——丢出去的活,也有一双眼睛看着。" + "text": "丢出去,不等于就不管了。丢出去的活,也有一双眼睛一直看着。" }, { "id": "p3-09a", "scene": "P3", - "text": "看的方式,官方给了两条路:一条是轮询走廊——每隔一段回头问一次," + "text": "怎么个看法,官方给了两条路。一条是轮询走廊:每隔一段回头问一次," }, { "id": "p3-09b", "scene": "P3", - "text": "简单,但空跑也是钱;另一条是事件传送带——活一出结果就自己滚过来," + "text": "简单,但空跑也是钱。另一条是事件传送带:活一出结果就自己滚过来," }, { "id": "p3-09c", "scene": "P3", - "text": "不空跑、不迟到。等得起就用走廊,等不起就上传送带。" + "text": "不空跑,也不迟到。等得起的就用走廊,等不起的就上传送带。" }, { "id": "p4-01", "scene": "P4", - "text": "现在把「谁来按开始」这个问题再往前推一步。" + "text": "现在把「谁来按开始」这个问题,再往前推一步。" }, { "id": "p4-02", "scene": "P4", - "text": "后台解决的是「不等」,但开始还是你按的。你说一句,它动一下。" + "text": "后台解决的是「不等」,可开始还是你按的。你说一句,它才动一下。" }, { "id": "p4-03", "scene": "P4", - "text": "可有些活是周期性的:每天早上九点跑一遍测试,每半小时看一眼服务状态。" + "text": "可有些活是按点来的:每天早上九点跑一遍测试,每半小时看一眼服务状态。" }, { "id": "p4-04", "scene": "P4", - "text": "这些活不该每次都等人来推。闹钟不需要你盯着它才会响。" + "text": "这种活不该每次都等着人来推。闹钟又不需要你盯着它才会响。" }, { "id": "p4-05", @@ -397,12 +397,12 @@ { "id": "p4-08", "scene": "P4", - "text": "读法就这么多,五格小抄,写清楚什么时候该干活。" + "text": "读法就这么多。一张五格小抄,写清楚什么时候该干什么活。" }, { "id": "p4-09", "scene": "P4", - "text": "还有两道保险。写表的时候就先验格式:写错的表直接拒收,进不了门。" + "text": "还有两道保险。写表的时候就先验格式,写错的表直接拒收,进不了门。" }, { "id": "p4-10", @@ -412,12 +412,12 @@ { "id": "p4-11", "scene": "P4", - "text": "谁来看表?一个独立的小闹钟线程,每秒看一眼;到点了,把活丢进队列。" + "text": "谁来看表?一个独立的小闹钟线程,每秒看一眼。到点了,把活丢进队列。" }, { "id": "p4-12", "scene": "P4", - "text": "注意两个细节。一是每分钟只放一枪——它记着「这一分钟发过了」," + "text": "注意两个细节。一是每分钟只放一枪,它心里记着「这一分钟发过了」," }, { "id": "p4-13", @@ -427,62 +427,62 @@ { "id": "p4-14", "scene": "P4", - "text": "二是每个活自己兜底:一个坏任务出错,不会连累整张表停摆。" + "text": "二是每个活自己兜底。一个坏任务出了错,不会连累整张表跟着停摆。" }, { "id": "p4-15", "scene": "P4", - "text": "队列这头还有一道闸:里面有活、它又正闲着,闸才开,把活递进循环。" + "text": "队列这头还有一道闸:里面有活,它又正闲着,闸才开,把活递进循环。" }, { "id": "p4-16", "scene": "P4", - "text": "为什么要绕这么一圈?直接到了点就地开工不行吗?" + "text": "为什么要绕这一圈?" }, { "id": "p4-17", "scene": "P4", - "text": "不行。它可能正跟你聊到一半,硬插进去,一句话被拦腰截断。" + "text": "到点就地开工不行吗?不行。它可能正跟你聊到一半,一句话被拦腰截断。" }, { "id": "p4-18", "scene": "P4", - "text": "队列的意义就是礼让:到点的活在门口排队,等它把手头的说完。" + "text": "队列的意义就是礼让。到点的活先在门口排队,等它把手头的话说完。" }, { "id": "p4-19", "scene": "P4", - "text": "任务定义存哪?官方分三档:云端的例程,关机也跑、不碰本地文件;" + "text": "任务定义存哪?官方分三档。云端的例程,关机也跑,不碰本地文件;" }, { "id": "p4-20", "scene": "P4", - "text": "桌面定时,本机跨会话;会话内循环,新对话清空、只恢复没过期的。" + "text": "桌面定时,本机跨会话;会话内循环,新对话清空,只恢复没过期的。" }, { "id": "p4-21", "scene": "P4", - "text": "老答案是用系统的定时表落盘——现在只是三档里的一档。" + "text": "老答案是用系统的定时表落盘。现在,它只是三档里的一档而已。" }, { "id": "p4-22", "scene": "P4", - "text": "怎么选,看这活要撑多久:撑过关机的上云端;" + "text": "怎么选?看这活要撑多久。" }, { "id": "p4-23", "scene": "P4", - "text": "只撑过这场对话的,用桌面;剩下的,散场就清空。" + "text": "撑过关机的上云端;只撑过这场对话的,用桌面;剩下的,散场就清空。" }, { "id": "p4-24", "scene": "P4", - "text": "看表的不干活,干活的不看表,中间靠一条队列传话。生产和消费,解耦了。" + "text": "看表的不干活,干活的不看表,中间靠一条队列传话。两头谁也不认识谁。" }, { "id": "p4-25", "scene": "P4", - "text": "这套分工听起来繁琐,但每一层都各改各的:表可以换格式,队列可以换实现," + "text": "这套分工听着繁琐,可每一层都各改各的:表能换格式,队列能换实现," }, { "id": "p4-26", @@ -497,12 +497,12 @@ { "id": "p5-01", "scene": "P5", - "text": "时间表这层,有三个真话,一个比一个有意思。" + "text": "时间表这一层,有三个真话要讲,一个比一个有意思。" }, { "id": "p5-02", "scene": "P5", - "text": "第一个真话:全世界的定时器,都卡在整点。" + "text": "第一个真话:全世界的定时器,全都卡在整点上。" }, { "id": "p5-03", @@ -512,12 +512,12 @@ { "id": "p5-04", "scene": "P5", - "text": "服务还没怎么样,先被自己人踩踏了。所以产品故意让每个任务迟到一点。" + "text": "服务还没怎么样,先被自己人踩踏了。所以产品故意让每个任务都迟到一点。" }, { "id": "p5-05", "scene": "P5", - "text": "妙的是迟到多少不是随机数——是按任务编号算出来的固定偏移。" + "text": "妙就妙在,迟到多少不是随机数,是按任务编号算出来的一个固定偏移。" }, { "id": "p5-06", @@ -527,22 +527,22 @@ { "id": "p5-07", "scene": "P5", - "text": "为什么强调算出来、而不是随机?随机会漂——这次迟三秒,下次迟十秒," + "text": "为什么非要算,不能随机?" }, { "id": "p5-08", "scene": "P5", - "text": "排查的人永远说不准它到底几点响。确定性偏移,错峰又可预测。" + "text": "随机会漂:这次迟三秒,下次迟十秒,排查的人说不准。算出来的才可预测。" }, { "id": "p5-09", "scene": "P5", - "text": "顺带一提,一次性的活要是正好落在整点或半点,还会最多提前一分半触发," + "text": "顺带一提,一次性的活落在整点或半点,还会最多提前一分半,跟人流反着走。" }, { "id": "p5-10", "scene": "P5", - "text": "提前量也是算好的。跟整点人流反着走。" + "text": "提前量也是算好的。" }, { "id": "p5-11", @@ -557,52 +557,52 @@ { "id": "p5-13", "scene": "P5", - "text": "第三个真话最实在,也最容易踩坑:把进程关了,表就停了。" + "text": "第三个真话最实在,也最容易踩坑:把进程一关,整张表就停了。" }, { "id": "p5-14", "scene": "P5", - "text": "但官方给了新答案:后台会话由独立的管家进程托管,不怕终端关掉。" + "text": "但官方给了新答案:后台会话由一个独立的管家进程托管,不怕你把终端关掉。" }, { "id": "p5-15", "scene": "P5", - "text": "关掉也丢不了:状态落盘,穿得过自动更新和重启,机器睡醒还会重连。" + "text": "关掉也丢不了。状态落盘,穿得过自动更新和重启,机器睡醒了还会重连。" }, { "id": "p5-16", "scene": "P5", - "text": "管家给每个会话记账:六种状态,排队、跑着、等审批、被拦、收尾、完事。" + "text": "管家给每个会话记账,六种状态:排队、跑着、等审批、被拦、收尾、完事。" }, { "id": "p5-17", "scene": "P5", - "text": "每条还配一行摘要,也是小模型顺带写的——省着主模型的上下文。" + "text": "每条还配一行摘要,也是小模型顺带写的,省的是主模型的上下文。" }, { "id": "p5-18", "scene": "P5", - "text": "进程退出不等于任务没了——接回后从停的地方继续。" + "text": "进程退出,不等于任务就没了。接回来,还是从停的地方接着跑。" }, { "id": "p5-19", "scene": "P5", - "text": "对了,表上还有个总量上限:五十条。满了要先取消一条才能再添——" + "text": "对了,表上还有个总量上限,五十条。满了得先取消一条,才能再添一条。" }, { "id": "p5-20", "scene": "P5", - "text": "闹钟太多的人,该先想想是不是真的需要这么多闹钟。" + "text": "闹钟太多的人,该先想想,是不是真的需要这么多闹钟。" }, { "id": "p5-21", "scene": "P5", - "text": "还有个小细节:定时任务触发的请求,带着「低优先级」的标记——" + "text": "还有个小细节:定时任务触发的那个请求,带着「低优先级」的标记。" }, { "id": "p5-22", "scene": "P5", - "text": "服务一忙,先紧着人的事,闹钟的事往后稍稍。" + "text": "服务一忙,先紧着人的事。闹钟的事,往后稍稍。" }, { "id": "p5-23", @@ -612,7 +612,7 @@ { "id": "p5-23a", "scene": "P5", - "text": "补丁之外还有个自由的拨法:让它给自己上发条——干完一轮,顺手定下一次," + "text": "补丁之外还有个自由的拨法:让它给自己上发条。干完一轮,顺手定下一次," }, { "id": "p5-23b", @@ -627,17 +627,17 @@ { "id": "p6-02", "scene": "P6", - "text": "三种答案。有人按并等着——最笨也最常见;" + "text": "三种答案。第一种,有人按了还站着等。最笨,也最常见。" }, { "id": "p6-03", "scene": "P6", - "text": "有人按不等——活丢后台,通知排队,还有狗看着;" + "text": "第二种,有人按了不等:活丢后台,通知排队,还有一只狗看着。" }, { "id": "p6-04", "scene": "P6", - "text": "没人按——时间自己按,错峰响,七天不响就退休。" + "text": "第三种,没人按:时间自己按,错峰响,七天不响就退休。" }, { "id": "p6-05", @@ -647,7 +647,7 @@ { "id": "p6-06", "scene": "P6", - "text": "而从头到尾,那个循环一秒都没停过。" + "text": "从头到尾,循环一秒没停。" }, { "id": "p6-13", @@ -672,12 +672,12 @@ { "id": "p6-10", "scene": "P6", - "text": "它的自主,到此为止是「守时的自主」——时间到点自己开工," + "text": "它的自主,眼下只是「守时的自主」:时间到了,自己开工。至于该干什么活," }, { "id": "p6-11", "scene": "P6", - "text": "至于「自己决定该干什么活」,那是更大的一步,我们后面再拆。" + "text": "那是更大一步,后面再拆。" }, { "id": "p6-12", @@ -687,11 +687,11 @@ { "id": "p6-12a", "scene": "P6", - "text": "今天拆的这只手,是循环的另一半——它不必原地等,也不必人来按。" + "text": "今天拆的这只手,是循环的另一半:它不必原地等,也不必人来按。" }, { "id": "p6-15", "scene": "P6", - "text": "下期:官方算过,一群它比一个它贵十五倍——为什么还有人这么干。下期见。" + "text": "下期:官方算过,一群它比一个它贵十五倍。为什么还有人这么干。下期见。" } ] diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md index 001e1b16..9b01e498 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/script/narration.md @@ -13,19 +13,19 @@ > 画面:系列终端。依赖安装进度条缓慢爬行;旁边一枚计费表跟着时间狂转。 > 角标:Background Tasks · "Slow Operations Go to the Background" -- [p0-01] 你让它跑个安装,进度条爬了十分钟,它就干等了十分钟。 +- [p0-01] 你让它跑个安装,进度条爬了十分钟,它就在那儿干等了十分钟。 - [p0-02] 按字计费,一秒没停。官方工程博客有句大实话:它感觉不到时间。 -- [p0-03] 同一篇博客说,不看着它,它会高高兴兴把测试跑上几个小时。 -- [p0-04] 所以表不归它管——归外面那层工程。这一集拆那只替它看表的手。 -- [p0-05] 换成你,你会站在洗衣机前面盯着滚筒等三十分钟吗? -- [p0-06] 不会。按下启动去做别的,等它滴滴滴叫你。 -- [p0-07] 这个动作拆开是两件事:活交给机器,人不陪着等。 +- [p0-03] 同一篇博客还说,不看着它,它会高高兴兴把测试跑上好几个小时。 +- [p0-04] 所以表不归它管,归外面那层工程。这一集,就拆那只替它看表的手。 +- [p0-05] 换成你呢?你会站在洗衣机前面,盯着滚筒干等三十分钟吗? +- [p0-06] 不会。按下就走。 +- [p0-07] 等它滴滴滴叫你。这一下拆开,其实是两件事:活交给机器,人不陪着等。 - [p0-08] 这集就讲怎么把这两件事教给它:谁来按开始,谁来等。 -- [p0-09] 先说清它缺什么:不光感觉不到时间,也不会自己安排等待。 -- [p0-10] 官方管这个叫时间盲症:模型没有钟、没有闹钟、也没有「回头再看」的本能。 -- [p0-11] 于是第一步,把「等」摘掉:按下就走开,活交给机器。 -- [p0-12] 第二步更进一步:连按的人都可以不要,时间到了自己开始。 -- [p0-13] 每一步都有真话要讲,也有坑要躲。这就开拆。 +- [p0-09] 先说清它到底缺什么。不光是感觉不到时间,也不会自己安排等待。 +- [p0-10] 官方管这个叫时间盲症。没有钟,没有闹钟,也没有「回头再看」的本能。 +- [p0-11] 于是第一步,先把「等」摘掉:按下就走开,活交给机器。 +- [p0-12] 第二步更狠:连按的人都不要,时间到了自己开始。每步都有真话,也有坑。 +- [p0-13] 这就开拆吧。 ## P1 按下就走开 @@ -33,28 +33,28 @@ > 占位条贴回环口。洗衣机计时环在角落自己走。 > 角标:run_in_background · 关键词兜底 · 守护线程 -- [p1-01] 先说第一层:按下开始就走开。 -- [p1-02] 谁来决定一件活要不要丢后台?主路是它自己—— -- [p1-03] 跑命令的工具上有一个「后台执行」的开关,它勾了,活就走后台。 -- [p1-04] 官方还有个真机制:命令到了超时线,不被杀掉,而是自动滑入后台接着跑。 +- [p1-01] 先说第一层。按下就走开。 +- [p1-02] 谁来决定一件活要不要丢后台?主路是它自己。 +- [p1-03] 跑命令的那个工具上有一个「后台执行」的开关。它勾了,活就走后台。 +- [p1-04] 官方还有个真机制:命令到了超时线,不被杀掉,而是自动滑进后台接着跑。 - [p1-05] 三类例外照停:睡觉的、带 git 的、拆不成简单命令的。 -- [p1-06] 活丢出去之后,画面上发生的事最值得看:那个循环,没有停。 -- [p1-07] 慢命令块滑到环外的一条旁轨上自己跑;循环口立刻贴上一张占位条, +- [p1-06] 活丢出去之后,画面上最值得看的是这个:那个循环,一秒都没停。 +- [p1-07] 慢命令块滑到环外的一条旁轨上自己跑,循环口立刻贴上一张占位条。 - [p1-08] 意思是:这活派出去了,好了会叫你。然后循环接着转,去干下一件。 -- [p1-09] 这个安排有个前提要交代:那个跑后台的活,是个「守护」的身份—— +- [p1-09] 这个安排有个前提得先交代。那个跑后台的活,身份是个「守护」。 - [p1-10] 主人退场,它跟着退场。不会出现程序都关了、后台还在偷偷跑的情况。 -- [p1-11] 这里有个容易被想岔的点。有人拆过它的源码,一句话说穿了: -- [p1-12] 所谓后台,根本不是一个并行的宇宙。整套系统跑在单线程里, +- [p1-11] 这里有个特别容易想岔的点。有人读源码,读出来一句大实话: +- [p1-12] 所谓后台,根本不是另一个并行的宇宙。整套系统就跑在单线程里。 - [p1-13] 后台的真实含义,只是「这一步不等它了」。 -- [p1-14] 等待被拿掉了,不是并发被造出来了。 -- [p1-15] 这一集所有魔法,都是这一个动作的变体:把「等」从某个人身上摘走。 -- [p1-16] 再多看一眼那个占位条。它不是随口一句「跑着呢」—— -- [p1-17] 它带着一个任务编号。这个编号后面有大用,先记在这里。 -- [p1-18] 对了,这个「自己勾后台」的设计本身也值得一句: +- [p1-14] 拿掉了等待,没造出并发。 +- [p1-15] 这一集所有的魔法,都是这一个动作的变体:把「等」从某个人身上摘走。 +- [p1-16] 再多看一眼那个占位条。它可不是随口一句「跑着呢」。 +- [p1-17] 它身上带着一个任务编号。这个编号后面有大用,先记在这儿。 +- [p1-18] 对了,「自己勾后台」这个设计本身,也值得说一句: - [p1-19] 谁最清楚一件活要跑多久?是读过命令、干过类似活的它自己。 - [p1-20] 让它自己判断,比任何外部规则都准。人的直觉是关键词,它的直觉是经验。 -- [p1-21] 「守护」这个身份,前面只说了一半,还有反过来的一半: -- [p1-22] 只要它还活着,后台就一直在。你中途想问进度、想停掉,都行—— +- [p1-21] 「守护」这个身份,刚才只说了一半,还有反过来的一半。 +- [p1-22] 只要它还活着,后台就一直在。你中途想问进度、想停掉,都行。 - [p1-23] 后台不是泼出去的水,是拴着绳的风筝。 - [p1-24] 绳在手里,就还能问、还能停、还能改主意。这才叫敢丢出去。 @@ -64,28 +64,28 @@ > ★深挖帧:一次调用永远对一条结果的配对演示。 > 角标:task_notification · 队列优先级 next > later · 七种后台任务 · ~30 字完成标签 -- [p2-01] 第二个问题:活干完了,怎么接回来? -- [p2-02] 细节比你想的讲究。派活那一刻,占位条就已经把结果的位置占了—— -- [p2-03] 一次调用,永远对应一条结果,这个配对关系不许破坏。 -- [p2-04] 所以真结果回来时,不能冒充那条占位,它得换一个身份: -- [p2-05] 变成一张完成通知,排进队列;下一轮跟别的结果合并成一条消息递进去。 -- [p2-06] 递进去的时机也是设计过的。有人拆过它的源码——队列其实分两级: -- [p2-07] 「下一轮」和「稍后」。后台完成的通知,默认排在「稍后」—— -- [p2-08] 也就是说它不插队。你新输入的一句话,永远排在它的前面。 -- [p2-09] 打个比方:门口的信箱。活干完往里投信,开不开箱,看主人何时路过。 -- [p2-10] 这个「不插队」的安排,乍看不起眼,细想很关键。 -- [p2-11] 你正问它一个正经问题,后台忽然蹦出来「装依赖好了」, -- [p2-12] 话头被截走,它的思路也跟着跑了。排队,保护的是对话的完整性。 -- [p2-13] 活不止一种:能丢后台的有七种——跑命令、本地分身、远程分身、 +- [p2-01] 活干完了,怎么接回来? +- [p2-02] 细节比你想的讲究。派活的那一刻,占位条就已经把结果的位置先占住了。 +- [p2-03] 一次调用对一条结果。 +- [p2-04] 这个配对不许破。所以真结果回来的时候,不能冒充占位,它得换个身份。 +- [p2-05] 变成一张完成通知,排进队列,下一轮跟别的结果并成一条消息递进去。 +- [p2-06] 递进去的时机也是设计过的。有人读源码读出来:队列其实分两级。 +- [p2-07] 「下一轮」和「稍后」。后台完成的通知,默认排在「稍后」。 +- [p2-08] 也就是说,它不插队。你新输入的那句话,永远排在它的前面。 +- [p2-09] 打个比方:门口的信箱。活干完往里投信。开不开箱,看主人什么时候路过。 +- [p2-10] 这个「不插队」的安排,乍一看不起眼,细想下去很关键。 +- [p2-11] 你正问它一个正经问题呢,后台忽然蹦出来一句「装依赖好了」。 +- [p2-12] 话头被截走,它的思路也跟着跑偏了。排队保护的,是整段对话的完整。 +- [p2-13] 活不止一种。能丢后台的有七种:跑命令、本地分身、远程分身、 - [p2-14] 进程内队友、工作流、监控外接,还有个整理记忆的,名字叫做梦。 - [p2-15] 不论哪一种,每批工具干完,小模型都顺手贴一张三十字的标签,像提交说明。 -- [p2-16] 还有一层安心:你随时可以主动开信箱,问一句后台的活怎么样了。 +- [p2-16] 还有一层安心。你随时可以主动开信箱,问一句后台的活怎么样了。 - [p2-17] 它会把每条活的状态报给你:还在跑、跑完了、或者根本没这条活。 -- [p2-18] 前面留的伏笔——占位条上的任务编号,现在派上用场了。 -- [p2-19] 完成通知带着同一个编号回来对号——编号就是后台世界的取件码。 -- [p2-20] 该把哪句「等它结果」的话补上,一查便知。账目永远平的: -- [p2-21] 每次调用都有着落,要么当场给结果,要么占位再补通知。 -- [p2-22] 对话这种东西,一旦有账对不上,后面全乱。 +- [p2-18] 前面留的伏笔,占位条上那个任务编号,现在派上用场了。 +- [p2-19] 完成通知带着同一个编号回来对号入座。编号就是后台世界的取件码。 +- [p2-20] 该把哪句「等它结果」的话补回去,一查便知。账目永远是平的。 +- [p2-21] 每次调用都有着落:要么当场给结果,要么占位再补通知。 +- [p2-22] 对话这东西最怕账对不上。一旦对不上,后面全乱。 - [p2-23] 活出去了,人不用等,循环也没停。可丢出去的活,真就没人盯着了吗? ## P3 有一只狗盯着 @@ -94,18 +94,18 @@ > 对准输出线末端的「(y/n)」提示。 > 角标:watchdog · 45s 停滞检测 -- [p3-01] 有,还怪可爱的——有人管它叫看门狗。 -- [p3-02] 后台命令有时候会卡住——不是坏了,是它停下来问了个问题。 -- [p3-03] 比如「要不要继续?」——然后干等一个等不来的回答。 -- [p3-04] 所以有一只狗盯着每条后台命令的输出:四十五秒没有新动静,它就去看看, -- [p3-05] 是不是又停在哪个问句上了。是的话,把这件事告诉循环,让人来处理。 -- [p3-06] 这只狗的眼睛只认一个指标:输出有没有在长。 -- [p3-07] 还在长,说明它在干活,哪怕慢得像爬,狗都继续趴着。 -- [p3-08] 四十五秒一毫米都没动,才起身查看。不猜快慢,只看死活。 -- [p3-09] 后台不是丢出去就不管了——丢出去的活,也有一双眼睛看着。 -- [p3-09a] 看的方式,官方给了两条路:一条是轮询走廊——每隔一段回头问一次, -- [p3-09b] 简单,但空跑也是钱;另一条是事件传送带——活一出结果就自己滚过来, -- [p3-09c] 不空跑、不迟到。等得起就用走廊,等不起就上传送带。 +- [p3-01] 有。有人管它叫看门狗。 +- [p3-02] 后台命令有时候会卡住。不是坏了,是它自己停下来,问了个问题。 +- [p3-03] 比如「要不要继续?」然后就在那儿干等一个等不来的回答。 +- [p3-04] 所以有一只狗盯着每条后台命令的输出。四十五秒没新动静,它就去看看: +- [p3-05] 是不是又停在哪个问句上了。是的话,就把这事告诉循环,让人来处理。 +- [p3-06] 这只狗只认一个指标。 +- [p3-07] 输出有没有在长。还在长,就说明它在干活,哪怕慢得像爬,狗都继续趴着。 +- [p3-08] 四十五秒一毫米都没动,它才起身查看。不猜快慢,只看死活。 +- [p3-09] 丢出去,不等于就不管了。丢出去的活,也有一双眼睛一直看着。 +- [p3-09a] 怎么个看法,官方给了两条路。一条是轮询走廊:每隔一段回头问一次, +- [p3-09b] 简单,但空跑也是钱。另一条是事件传送带:活一出结果就自己滚过来, +- [p3-09c] 不空跑,也不迟到。等得起的就用走廊,等不起的就上传送带。 ## P4 没人按的开始 @@ -113,31 +113,31 @@ > 闲时才开。五格时间表特写与读法。 > 角标:五格时间表 · 每秒一跳 · 分钟标记防重 · 单任务隔离 -- [p4-01] 现在把「谁来按开始」这个问题再往前推一步。 -- [p4-02] 后台解决的是「不等」,但开始还是你按的。你说一句,它动一下。 -- [p4-03] 可有些活是周期性的:每天早上九点跑一遍测试,每半小时看一眼服务状态。 -- [p4-04] 这些活不该每次都等人来推。闹钟不需要你盯着它才会响。 +- [p4-01] 现在把「谁来按开始」这个问题,再往前推一步。 +- [p4-02] 后台解决的是「不等」,可开始还是你按的。你说一句,它才动一下。 +- [p4-03] 可有些活是按点来的:每天早上九点跑一遍测试,每半小时看一眼服务状态。 +- [p4-04] 这种活不该每次都等着人来推。闹钟又不需要你盯着它才会响。 - [p4-05] 于是第二层:定时。核心是一张时间表,Unix 世界用了五十年,五格: - [p4-06] 分钟、小时、日、月、星期。「每天九点」就是九点格填九,其余全星号; - [p4-07] 「每五分钟」就是第一格写「星杠五」;「工作日早上九点」再加一格一到五。 -- [p4-08] 读法就这么多,五格小抄,写清楚什么时候该干活。 -- [p4-09] 还有两道保险。写表的时候就先验格式:写错的表直接拒收,进不了门。 +- [p4-08] 读法就这么多。一张五格小抄,写清楚什么时候该干什么活。 +- [p4-09] 还有两道保险。写表的时候就先验格式,写错的表直接拒收,进不了门。 - [p4-10] 从磁盘恢复旧表的时候也逐条检查,一条坏的跳过去,不影响其余的。 -- [p4-11] 谁来看表?一个独立的小闹钟线程,每秒看一眼;到点了,把活丢进队列。 -- [p4-12] 注意两个细节。一是每分钟只放一枪——它记着「这一分钟发过了」, +- [p4-11] 谁来看表?一个独立的小闹钟线程,每秒看一眼。到点了,把活丢进队列。 +- [p4-12] 注意两个细节。一是每分钟只放一枪,它心里记着「这一分钟发过了」, - [p4-13] 同一分钟绝不重复;到了第二天,同一个点照样准时。 -- [p4-14] 二是每个活自己兜底:一个坏任务出错,不会连累整张表停摆。 -- [p4-15] 队列这头还有一道闸:里面有活、它又正闲着,闸才开,把活递进循环。 -- [p4-16] 为什么要绕这么一圈?直接到了点就地开工不行吗? -- [p4-17] 不行。它可能正跟你聊到一半,硬插进去,一句话被拦腰截断。 -- [p4-18] 队列的意义就是礼让:到点的活在门口排队,等它把手头的说完。 -- [p4-19] 任务定义存哪?官方分三档:云端的例程,关机也跑、不碰本地文件; -- [p4-20] 桌面定时,本机跨会话;会话内循环,新对话清空、只恢复没过期的。 -- [p4-21] 老答案是用系统的定时表落盘——现在只是三档里的一档。 -- [p4-22] 怎么选,看这活要撑多久:撑过关机的上云端; -- [p4-23] 只撑过这场对话的,用桌面;剩下的,散场就清空。 -- [p4-24] 看表的不干活,干活的不看表,中间靠一条队列传话。生产和消费,解耦了。 -- [p4-25] 这套分工听起来繁琐,但每一层都各改各的:表可以换格式,队列可以换实现, +- [p4-14] 二是每个活自己兜底。一个坏任务出了错,不会连累整张表跟着停摆。 +- [p4-15] 队列这头还有一道闸:里面有活,它又正闲着,闸才开,把活递进循环。 +- [p4-16] 为什么要绕这一圈? +- [p4-17] 到点就地开工不行吗?不行。它可能正跟你聊到一半,一句话被拦腰截断。 +- [p4-18] 队列的意义就是礼让。到点的活先在门口排队,等它把手头的话说完。 +- [p4-19] 任务定义存哪?官方分三档。云端的例程,关机也跑,不碰本地文件; +- [p4-20] 桌面定时,本机跨会话;会话内循环,新对话清空,只恢复没过期的。 +- [p4-21] 老答案是用系统的定时表落盘。现在,它只是三档里的一档而已。 +- [p4-22] 怎么选?看这活要撑多久。 +- [p4-23] 撑过关机的上云端;只撑过这场对话的,用桌面;剩下的,散场就清空。 +- [p4-24] 看表的不干活,干活的不看表,中间靠一条队列传话。两头谁也不认识谁。 +- [p4-25] 这套分工听着繁琐,可每一层都各改各的:表能换格式,队列能换实现, - [p4-26] 循环一无所知。牵一发而不动全身,这才有资格谈稳定。 - [p4-27] 说到底就一句:谁都不必知道对方在忙什么。 @@ -146,30 +146,30 @@ > 画面:★深挖帧——一排相同的表全指向 9:00,各按算好的偏移错峰落下;退休章;诚实边界帧。 > 角标:jitter(确定性哈希 · 周期 10% · 封顶 15 分钟)· 7 天退休(上限 30 天)· 上限 50 -- [p5-01] 时间表这层,有三个真话,一个比一个有意思。 -- [p5-02] 第一个真话:全世界的定时器,都卡在整点。 +- [p5-01] 时间表这一层,有三个真话要讲,一个比一个有意思。 +- [p5-02] 第一个真话:全世界的定时器,全都卡在整点上。 - [p5-03] 你写「每天九点」,别人也写「每天九点」。千万个任务同一秒一起冲出去, -- [p5-04] 服务还没怎么样,先被自己人踩踏了。所以产品故意让每个任务迟到一点。 -- [p5-05] 妙的是迟到多少不是随机数——是按任务编号算出来的固定偏移。 +- [p5-04] 服务还没怎么样,先被自己人踩踏了。所以产品故意让每个任务都迟到一点。 +- [p5-05] 妙就妙在,迟到多少不是随机数,是按任务编号算出来的一个固定偏移。 - [p5-06] 同一个任务,每次迟到一样多;不同的任务,错开响。防踩踏,还不添乱。 -- [p5-07] 为什么强调算出来、而不是随机?随机会漂——这次迟三秒,下次迟十秒, -- [p5-08] 排查的人永远说不准它到底几点响。确定性偏移,错峰又可预测。 -- [p5-09] 顺带一提,一次性的活要是正好落在整点或半点,还会最多提前一分半触发, -- [p5-10] 提前量也是算好的。跟整点人流反着走。 +- [p5-07] 为什么非要算,不能随机? +- [p5-08] 随机会漂:这次迟三秒,下次迟十秒,排查的人说不准。算出来的才可预测。 +- [p5-09] 顺带一提,一次性的活落在整点或半点,还会最多提前一分半,跟人流反着走。 +- [p5-10] 提前量也是算好的。 - [p5-11] 第二个真话:定时任务会自动退休。连续七天没动静的周期任务, - [p5-12] 到期自动删掉,删之前还会最后跑一次。忘了设的闹钟,不该响一辈子。 -- [p5-13] 第三个真话最实在,也最容易踩坑:把进程关了,表就停了。 -- [p5-14] 但官方给了新答案:后台会话由独立的管家进程托管,不怕终端关掉。 -- [p5-15] 关掉也丢不了:状态落盘,穿得过自动更新和重启,机器睡醒还会重连。 -- [p5-16] 管家给每个会话记账:六种状态,排队、跑着、等审批、被拦、收尾、完事。 -- [p5-17] 每条还配一行摘要,也是小模型顺带写的——省着主模型的上下文。 -- [p5-18] 进程退出不等于任务没了——接回后从停的地方继续。 -- [p5-19] 对了,表上还有个总量上限:五十条。满了要先取消一条才能再添—— -- [p5-20] 闹钟太多的人,该先想想是不是真的需要这么多闹钟。 -- [p5-21] 还有个小细节:定时任务触发的请求,带着「低优先级」的标记—— -- [p5-22] 服务一忙,先紧着人的事,闹钟的事往后稍稍。 +- [p5-13] 第三个真话最实在,也最容易踩坑:把进程一关,整张表就停了。 +- [p5-14] 但官方给了新答案:后台会话由一个独立的管家进程托管,不怕你把终端关掉。 +- [p5-15] 关掉也丢不了。状态落盘,穿得过自动更新和重启,机器睡醒了还会重连。 +- [p5-16] 管家给每个会话记账,六种状态:排队、跑着、等审批、被拦、收尾、完事。 +- [p5-17] 每条还配一行摘要,也是小模型顺带写的,省的是主模型的上下文。 +- [p5-18] 进程退出,不等于任务就没了。接回来,还是从停的地方接着跑。 +- [p5-19] 对了,表上还有个总量上限,五十条。满了得先取消一条,才能再添一条。 +- [p5-20] 闹钟太多的人,该先想想,是不是真的需要这么多闹钟。 +- [p5-21] 还有个小细节:定时任务触发的那个请求,带着「低优先级」的标记。 +- [p5-22] 服务一忙,先紧着人的事。闹钟的事,往后稍稍。 - [p5-23] 三个真话合起来是一种态度:定时这件事,想象很浪漫,工程都在打补丁。 -- [p5-23a] 补丁之外还有个自由的拨法:让它给自己上发条——干完一轮,顺手定下一次, +- [p5-23a] 补丁之外还有个自由的拨法:让它给自己上发条。干完一轮,顺手定下一次, - [p5-23b] 间隔自己定。不靠墙上的钟,靠它自己的一句「回头再来」。 ## P6 落点与信源 @@ -178,17 +178,17 @@ > 一句话合同金句卡 → 边界两句 + 四件套回收条 → 身份卡 → 渐黑(末 beat 总时长推导)。 - [p6-01] 收个尾。这一集其实只回答了一个问题:谁来按开始。 -- [p6-02] 三种答案。有人按并等着——最笨也最常见; -- [p6-03] 有人按不等——活丢后台,通知排队,还有狗看着; -- [p6-04] 没人按——时间自己按,错峰响,七天不响就退休。 +- [p6-02] 三种答案。第一种,有人按了还站着等。最笨,也最常见。 +- [p6-03] 第二种,有人按了不等:活丢后台,通知排队,还有一只狗看着。 +- [p6-04] 第三种,没人按:时间自己按,错峰响,七天不响就退休。 - [p6-05] 每多一种开始,机制就往外挪一层:活挪出这一轮,触发挪出这个人。 -- [p6-06] 而从头到尾,那个循环一秒都没停过。 +- [p6-06] 从头到尾,循环一秒没停。 - [p6-13] 本片机制依据官方文档,取数2026年8月,以官方最新表述为准。 - [p6-14] 涉及产品内部的部分,为第三方源码分析,片中已逐处标注。 - [p6-07] 按下的不一定是它,等的一定不是你。 - [p6-09] 钟曾经装在它身体里,现在挪进了一个不睡的管家。 -- [p6-10] 它的自主,到此为止是「守时的自主」——时间到点自己开工, -- [p6-11] 至于「自己决定该干什么活」,那是更大的一步,我们后面再拆。 +- [p6-10] 它的自主,眼下只是「守时的自主」:时间到了,自己开工。至于该干什么活, +- [p6-11] 那是更大一步,后面再拆。 - [p6-12] 官方给整副 Harness 画过一张像:循环、工具、上下文管理、护栏。 -- [p6-12a] 今天拆的这只手,是循环的另一半——它不必原地等,也不必人来按。 -- [p6-15] 下期:官方算过,一群它比一个它贵十五倍——为什么还有人这么干。下期见。 +- [p6-12a] 今天拆的这只手,是循环的另一半:它不必原地等,也不必人来按。 +- [p6-15] 下期:官方算过,一群它比一个它贵十五倍。为什么还有人这么干。下期见。 diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json index 08a3af06..3de04e1b 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.json @@ -2,22 +2,22 @@ { "id": "p0-01", "scene": "P0", - "text": "你让 AI 跑个脚本:它把命令写好,然后就停在那儿了。" + "text": "你让 AI 跑个脚本。它把命令写得漂漂亮亮的,然后就停在那儿了。" }, { "id": "p0-02", "scene": "P0", - "text": "复制、粘贴、回车、再把输出贴回去——每一轮的搬运工,是你。" + "text": "复制、粘贴、回车,再把输出贴回去。每一轮的搬运工,是你。" }, { "id": "p0-03", "scene": "P0", - "text": "从「写出命令」到「真的跑起来」,缺的那一层,官方起了名字。" + "text": "能写出命令,和真的跑起来,中间隔着一层。这一层,官方起过名字。" }, { "id": "p0-03a", "scene": "P0", - "text": "这一层有多要紧?他们刷编程评测的战报里写过一句话——" + "text": "这一层到底有多要紧?他们自己的评测战报里,写过一句话。" }, { "id": "p0-03b", @@ -27,7 +27,7 @@ { "id": "p0-03c", "scene": "P0", - "text": "你花在这一层上的力气,直接变成它的分数。" + "text": "你出多少力,它得多少分。" }, { "id": "p0-04", @@ -37,7 +37,7 @@ { "id": "p0-05", "scene": "P0", - "text": "官方说得直白:这套东西是 Harness,模型装在里面。" + "text": "官方自己说得很直白:这套东西就是 Harness,模型装在里面。" }, { "id": "p0-06", @@ -47,12 +47,12 @@ { "id": "p0-07", "scene": "P0", - "text": "这集就把这个 Harness,一层一层拆开看。" + "text": "这集,就一层一层拆开它。" }, { "id": "p1-01", "scene": "P1", - "text": "先说结论:那一层的核心是一个循环,像一条不停转的传送带。" + "text": "先说结论。核心就是一个循环,像一条不停转的传送带。" }, { "id": "p1-02", @@ -62,67 +62,67 @@ { "id": "p1-03", "scene": "P1", - "text": "每问一次,就看模型的回答里有没有夹着一次工具调用。" + "text": "每问一次,就翻开它的回答,看里面有没有夹着一次工具调用。" }, { "id": "p1-04", "scene": "P1", - "text": "有,就说明模型举手了,它要用工具。" + "text": "有,模型举手了。" }, { "id": "p1-05", "scene": "P1", - "text": "那就替它把工具跑一遍,把结果原样塞回对话里,再问下一轮。" + "text": "那就替它把这件工具跑一遍,结果原样塞回对话里,然后接着问下一轮。" }, { "id": "p1-06", "scene": "P1", - "text": "没有,就说明它觉得活干完了,循环停机,把话交给你。" + "text": "没有,就是它觉得活干完了。循环停机,把话交还给你。" }, { "id": "p1-08", "scene": "P1", - "text": "把这件事翻成代码,只有五步。" + "text": "翻成代码,只有五步。" }, { "id": "p1-09", "scene": "P1", - "text": "先把你的问题放进消息列表,再连同「我有哪些工具」发给模型;" + "text": "先把你的问题放进消息列表,再连同「我有哪些工具」一起发给模型;" }, { "id": "p1-10", "scene": "P1", - "text": "把模型的回答追加进列表,挑出里面所有的工具调用;" + "text": "把模型的回答追加进列表,再挑出里面所有的工具调用;" }, { "id": "p1-11", "scene": "P1", - "text": "一个都没有,就地返回;有就逐个执行、收好每条结果;" + "text": "一个都没有,就地返回;有,就逐个执行,收好每条结果;" }, { "id": "p1-12", "scene": "P1", - "text": "最后把结果打包成新消息追加进去,回到第二步。写完了。" + "text": "最后把结果打包成一条新消息追加进去,回到第二步。写完了。" }, { "id": "p1-12a", "scene": "P1", - "text": "说明一下:有人照着这套机制搭了一份开源的最小实现。" + "text": "说明一下:有人照着这套机制,写过一个开源的小版本。" }, { "id": "p1-12b", "scene": "P1", - "text": "下面拿它当例子,边读边说实际实现的做法。" + "text": "下面就拿它当例子,边读边说真正的做法。" }, { "id": "p1-13", "scene": "P1", - "text": "有人给它的评价是:三十多行,最小可运行的内核。" + "text": "有人给它的评价是:三十多行,一个最小的、能跑的内核。" }, { "id": "p1-14", "scene": "P1", - "text": "我自己数过这一版:光循环那个函数,去掉空行和注释,二十三行。" + "text": "我自己数了一遍:光循环那个函数,去掉空行和注释,二十三行。" }, { "id": "p1-15", @@ -132,22 +132,22 @@ { "id": "p1-16", "scene": "P1", - "text": "脚手架负责真的去跑、把结果搬回来——判断力在那边,手脚在这边。" + "text": "壳负责真的去跑,把结果搬回来。判断力在那边,手脚在这边。" }, { "id": "p1-17", "scene": "P1", - "text": "模型回话时会附一个「我为什么停下来」的标记。" + "text": "模型每次回话,都会附一个「我为什么停下来」的标记。" }, { "id": "p1-18", "scene": "P1", - "text": "最直觉的写法是直接看它;但最简实现偏不这么写," + "text": "最直觉的写法就是直接看这个标记。可这份代码偏不这么干。" }, { "id": "p1-19", "scene": "P1", - "text": "而是翻开回答本身,看里面有没有工具调用。为什么?" + "text": "它翻开回答本身,去看里面到底有没有工具调用。为什么这么绕?" }, { "id": "p1-20", @@ -162,12 +162,12 @@ { "id": "p1-22", "scene": "P1", - "text": "那个标记却可能还没更新——他说源码注释写得很直白,这标记不可靠。" + "text": "那个标记却可能还没更新。他说源码注释写得很直白:这东西不可靠。" }, { "id": "p1-23", "scene": "P1", - "text": "所以真正的做法是一边流一边看,见到工具调用就记下还得再来一轮。" + "text": "所以真正的做法是一边流一边看。见到工具调用,就记下还得再来一轮。" }, { "id": "p1-24", @@ -177,12 +177,12 @@ { "id": "p1-25", "scene": "P1", - "text": "官方给这个循环画过像:三件事交融着转——" + "text": "官方给这个循环画过像:三件事交融着转。" }, { "id": "p1-26", "scene": "P1", - "text": "收集上下文、采取行动、验证结果,不是硬阶段。" + "text": "收集上下文、采取行动、验证结果,它们不是硬阶段。" }, { "id": "p1-27", @@ -192,27 +192,27 @@ { "id": "p1-28", "scene": "P1", - "text": "最简实现身上只带一份消息列表;实际的 Harness 带了十样," + "text": "玩具版身上只带一份消息列表。成型的那套呢?整整带了十样:" }, { "id": "p1-29", "scene": "P1", - "text": "压缩进度、补救次数、钩子拦没拦过停机、轮数——细节进角标。" + "text": "压缩进度、补救次数、钩子拦没拦过停机、轮数。细节都进角标。" }, { "id": "p1-30", "scene": "P1", - "text": "循环没长个,长出来的是它随身带的状态。" + "text": "循环没长个。长出来的是它随身带的那些状态。" }, { "id": "p1-31", "scene": "P1", - "text": "退出的路子也有一大把:报错、中断、钩子叫停、预算烧完。" + "text": "退出的路子还有一大把:报错、中断、钩子叫停、预算烧完。" }, { "id": "p1-32", "scene": "P1", - "text": "但它们全是保护装置,不是骨架;骨架还是那二十来行。" + "text": "可它们全是保护装置,不是骨架。骨架还是那二十来行。" }, { "id": "p2-01", @@ -222,17 +222,17 @@ { "id": "p2-02", "scene": "P2", - "text": "想读文件,它得拼出一条读文件的命令;想写文件,得拼一条重定向。" + "text": "想读文件,它得拼出一条读文件的命令。想写文件,再拼一条重定向。" }, { "id": "p2-03", "scene": "P2", - "text": "模型心里想的是「读这个文件」,嘴上却要翻译成一条命令行。" + "text": "模型心里想的是「读这个文件」,嘴上却得翻成一条命令行。" }, { "id": "p2-05", "scene": "P2", - "text": "那就把常用动作直接做成工具,于是从一件变成五件:" + "text": "那就干脆把常用动作直接做成工具。于是一件变成了五件:" }, { "id": "p2-06", @@ -242,7 +242,7 @@ { "id": "p2-07", "scene": "P2", - "text": "问题是循环怎么知道该调哪一个?答案朴素得让人意外:查一张表。" + "text": "可循环怎么知道该调哪一个?答案朴素得让人意外:查一张表。" }, { "id": "p2-08", @@ -257,17 +257,17 @@ { "id": "p2-10", "scene": "P2", - "text": "于是加一个新工具只要两件事:在清单里加一条描述,在表里加一行。" + "text": "加一个新工具就两件事:清单里加一条描述,表里加一行。" }, { "id": "p2-11", "scene": "P2", - "text": "循环那边呢?我把两个版本逐行比过," + "text": "那循环那边呢?我把前后两个版本逐行比过。" }, { "id": "p2-12", "scene": "P2", - "text": "实质改动只有一行——原来写死了去跑命令,现在改成查表。" + "text": "实质改动只有一行。原来写死了去跑命令,现在改成查表。" }, { "id": "p2-13", @@ -282,12 +282,12 @@ { "id": "p2-15", "scene": "P2", - "text": "最简的做法是老实排队,一个一个来;实际实现里能并行的就并行。" + "text": "玩具版是老实排队,一个一个来。真的那个呢?能并行就并行。" }, { "id": "p2-16", "scene": "P2", - "text": "而它判断能不能并行的方式,是这一集我最想让你记住的一处。" + "text": "而它怎么判断能不能并行?这是这一集我最想让你记住的一处。" }, { "id": "p2-17", @@ -297,7 +297,7 @@ { "id": "p2-18", "scene": "P2", - "text": "但按第三方的源码分析,这两件事其实不是一回事。" + "text": "但有人读源码读出来:这两件事根本不是一回事。" }, { "id": "p2-19", @@ -307,12 +307,12 @@ { "id": "p2-20", "scene": "P2", - "text": "同一件工具,同一个名字,结论相反。" + "text": "同一件工具,结论相反。" }, { "id": "p2-21", "scene": "P2", - "text": "因为判断的不是这件工具,是这一次具体要干什么。" + "text": "判断的根本不是这件工具,是这一次具体要干什么。" }, { "id": "p2-22", @@ -322,7 +322,7 @@ { "id": "p2-23", "scene": "P2", - "text": "原因是它每次改的都是不同的文件,谁也不挡谁。" + "text": "因为它每次改的都是不同的文件,谁也不挡谁。" }, { "id": "p2-24", @@ -332,7 +332,7 @@ { "id": "p2-25", "scene": "P2", - "text": "判断完了怎么排?按原来的顺序切段:连着能并行的划成一组一起跑," + "text": "判断完了怎么排?按原来的顺序切段:连着能并行的划成一组,一起跑," }, { "id": "p2-26", @@ -342,12 +342,12 @@ { "id": "p2-27", "scene": "P2", - "text": "他还提到,工具输出太长时它不会全喂给模型,而是存成文件," + "text": "他还提到一件事:工具输出太长,它不会全喂给模型,而是存成文件," }, { "id": "p2-28", "scene": "P2", - "text": "只给它一段预览和一个路径。" + "text": "只给一段预览和一个路径。" }, { "id": "p2-29", @@ -362,7 +362,7 @@ { "id": "p2-31", "scene": "P2", - "text": "读、存、再读、再存,它会自己套住自己,转不出来。" + "text": "读、存、再读、再存。它自己把自己套住了,转不出来。" }, { "id": "p3-01", @@ -372,7 +372,7 @@ { "id": "p3-02", "scene": "P3", - "text": "读写文件那几件,都被拦在工作目录里;跑命令那件,没人管。" + "text": "读写文件那几件,都被拦在工作目录里。跑命令那件,没人管。" }, { "id": "p3-03", @@ -382,7 +382,7 @@ { "id": "p3-04", "scene": "P3", - "text": "它完全可能给你递上一条把整块盘删干净的命令,循环照跑。" + "text": "它完全可能给你递上一条把整块盘删干净的命令。循环照跑。" }, { "id": "p3-06", @@ -392,7 +392,7 @@ { "id": "p3-07", "scene": "P3", - "text": "拦法是三道闸门,顺序写死。" + "text": "三道闸门,顺序写死。" }, { "id": "p3-08", @@ -402,7 +402,7 @@ { "id": "p3-09", "scene": "P3", - "text": "命中就直接挡回去,连问都不问。" + "text": "命中就挡回去,问都不问。" }, { "id": "p3-10", @@ -412,17 +412,17 @@ { "id": "p3-11", "scene": "P3", - "text": "读写工作目录之外的东西,或者命令里带着删除、改权限这类动作。" + "text": "读写工作目录之外的东西;或者命令里带着删除、改权限这类动作。" }, { "id": "p3-12", "scene": "P3", - "text": "第三道就是问你:画面停下来,把工具名和参数摆给你看,等你点头。" + "text": "第三道就是问你:画面停住,把工具名和参数摆给你看,等你点头。" }, { "id": "p3-14", "scene": "P3", - "text": "最简实现自己承认:这张拒绝表只是字符串匹配,换个拼法就绕过去。" + "text": "这份代码自己也承认:拒绝表只是字符串匹配,换个拼法就绕过去。" }, { "id": "p3-15", @@ -432,7 +432,7 @@ { "id": "p3-19a", "scene": "P3", - "text": "真正的边界在更底下一层:它给跑命令那件工具,套了一层沙箱。" + "text": "真正的边界在更底下一层。跑命令那件工具,被套进了一层沙箱。" }, { "id": "p3-19b", @@ -442,7 +442,7 @@ { "id": "p3-19c", "scene": "P3", - "text": "规则是劝,沙箱是锁——两道墙少一道,笼子就不成立。" + "text": "规则是劝,沙箱是锁。两道墙少一道,笼子就不成立。" }, { "id": "p3-19d", @@ -452,27 +452,27 @@ { "id": "p3-20", "scene": "P3", - "text": "回到闸门这边:有人拆过它的源码,判定结果是四种,不是三种。" + "text": "回到闸门这边。有人读源码读出来:判出来是四种,不是三种。" }, { "id": "p3-23", "scene": "P3", - "text": "多出来的第四种最有意思:工具选择不表态。" + "text": "多出来的第四种最有意思:这件工具选择不表态。" }, { "id": "p3-24", "scene": "P3", - "text": "也就是说,弃权不等于放行,兜底永远是问你一句。" + "text": "也就是说,弃权不等于放行。兜底永远是问你一句。" }, { "id": "p3-25", "scene": "P3", - "text": "规则求值顺序官方文档也写死了:拒绝、询问、放行," + "text": "规则是一条条往下判的,顺序官方也写死了:拒绝、询问、放行。" }, { "id": "p3-26", "scene": "P3", - "text": "头一个命中就出局——规则写得多具体,都改变不了顺序。" + "text": "头一个命中就出局。规则写得再具体,也改不了顺序。" }, { "id": "p3-28", @@ -482,12 +482,12 @@ { "id": "p3-29", "scene": "P3", - "text": "就算全放行模式,也压不住一条写死的拒绝。" + "text": "就算你开了全放行模式,也压不住一条写死的拒绝。" }, { "id": "p3-30", "scene": "P3", - "text": "全自动模式不靠你点头的次数,靠另一个模型当闸门。" + "text": "全自动模式不靠你点头的次数,靠另一个模型来当闸门。" }, { "id": "p3-31", @@ -507,17 +507,17 @@ { "id": "p3-32", "scene": "P3", - "text": "审判者的视野是做减法的:只看用户消息和裸命令。" + "text": "这个审判者的视野是做减法的:只看用户消息和裸命令。" }, { "id": "p3-34", "scene": "P3", - "text": "评它做了什么,不看它说了什么——注入的谎话骗不到它。" + "text": "评它做了什么,不看它说了什么。注入的谎话骗不到它。" }, { "id": "p3-35", "scene": "P3", - "text": "让模型帮忙看门,同时不敢把门全交给模型。" + "text": "让模型帮忙看门,又不敢把门全交给模型。" }, { "id": "p4-01", @@ -527,7 +527,7 @@ { "id": "p4-02", "scene": "P4", - "text": "接下来的麻烦,做过工程的人都熟:你想加点东西。" + "text": "接下来的麻烦,做过工程的人都熟悉:你想给它加点东西。" }, { "id": "p4-03", @@ -537,17 +537,17 @@ { "id": "p4-04", "scene": "P4", - "text": "每加一样,你都得回去改那个循环。" + "text": "加一样,改一次循环。" }, { "id": "p4-05", "scene": "P4", - "text": "有人画过一张很扎心的图:循环体里记日志一行、查权限一行、" + "text": "有人画过一张很扎心的图:循环体里,记日志一行、查权限一行、" }, { "id": "p4-06", "scene": "P4", - "text": "发通知一行、自动提交又一行,加到后面那段代码已经认不出来了。" + "text": "发通知一行、自动提交又一行。加到后面,那段代码已经认不出来了。" }, { "id": "p4-07", @@ -567,7 +567,7 @@ { "id": "p4-10", "scene": "P4", - "text": "循环到了某个时机只喊一声名字,至于该跑什么,由那张表说了算。" + "text": "循环到了某个时机,只喊一声名字。至于该跑什么,那张表说了算。" }, { "id": "p4-11", @@ -582,7 +582,7 @@ { "id": "p4-13", "scene": "P4", - "text": "最简实现留了四个插口,正好串成一整轮。" + "text": "这个小版本留了四个插口,正好串成一整轮。" }, { "id": "p4-14", @@ -612,7 +612,7 @@ { "id": "p4-19", "scene": "P4", - "text": "它返回一句话,这句话就被当成新输入塞回去,循环继续转。" + "text": "它返回一句话,这句话就被当成新输入塞回去,循环接着转。" }, { "id": "p4-20", @@ -627,7 +627,7 @@ { "id": "p4-23", "scene": "P4", - "text": "实际实现里这样的时机,官方文档口径三十一个," + "text": "成型的那套里,这样的时机官方文档口径三十一个," }, { "id": "p4-24", @@ -637,12 +637,12 @@ { "id": "p4-25", "scene": "P4", - "text": "处理器也不只是跑脚本,还能让小模型单轮判决。" + "text": "挂上去的也不只是脚本,还能让小模型单轮判一次。" }, { "id": "p4-27", "scene": "P4", - "text": "表态的契约值得单独记:沉默,不等于批准——" + "text": "这里有个契约值得单独记下来:沉默,不等于批准。" }, { "id": "p4-28", @@ -652,12 +652,12 @@ { "id": "p4-28a", "scene": "P4", - "text": "反过来,想真拦住只有一个硬信号;写错成惯用的失败码," + "text": "想真拦住,只有一个硬信号。写错成惯用的那个失败码," }, { "id": "p4-28b", "scene": "P4", - "text": "闸门不响、动作照跑——静默失效。" + "text": "闸门不响,动作照跑。" }, { "id": "p4-28c", @@ -672,7 +672,7 @@ { "id": "p4-30", "scene": "P4", - "text": "它的放行,仍要穿过后面的拒绝与询问两站。" + "text": "这句「批了」,后面还得穿过拒绝和询问两站。" }, { "id": "p4-31", @@ -682,27 +682,27 @@ { "id": "p4-32", "scene": "P4", - "text": "而且官方把权限判定,画成过一条六道闸门的流水线。" + "text": "官方还给权限判定画过一张图:六道闸门,一道一道过。" }, { "id": "p4-33", "scene": "P4", - "text": "这一层超出了最简实现的范围,拆源码的人评语是:" + "text": "这一步,开源那版根本没做。读源码的人给的评语是:" }, { "id": "p4-34", "scene": "P4", - "text": "做示例够用,生产环境就是一个安全漏洞。" + "text": "当例子够用,放进生产就是个安全漏洞。" }, { "id": "p4-35", "scene": "P4", - "text": "那个能说「别停」的插口本身很危险——它叫模型接着干," + "text": "那个能说「别停」的插口,自己就很危险。它叫模型接着干," }, { "id": "p4-36", "scene": "P4", - "text": "模型干完又要停,它又叫接着干,就转不出来了。" + "text": "模型干完又要停,它又叫接着干。转不出来了。" }, { "id": "p4-37", @@ -742,7 +742,7 @@ { "id": "p5-07", "scene": "P5", - "text": "这不是我的说法,是可以数出来的。" + "text": "这不是我一个人的说法,是能数出来的。" }, { "id": "p5-08", @@ -752,7 +752,7 @@ { "id": "p5-09", "scene": "P5", - "text": "长到两百五十多行,长了八成;" + "text": "长到两百五十多行,整整长了八成;" }, { "id": "p5-10", @@ -792,7 +792,7 @@ { "id": "p5-18", "scene": "P5", - "text": "这个项目的作者把它的作用写成一句话,我觉得是全篇最好的一句:" + "text": "这个项目的作者,把这层壳的作用写成了一句话。我觉得是全篇最好的:" }, { "id": "p5-19", @@ -802,17 +802,17 @@ { "id": "p6-01", "scene": "P6", - "text": "它敢在你的电脑上动手,不是因为它足够聪明," + "text": "它敢动手,不是因为聪明。" }, { "id": "p6-02", "scene": "P6", - "text": "而是因为有人在它周围,搭了这几层结构。" + "text": "是因为有人在它周围,一层一层,把这些结构搭了出来。" }, { "id": "p6-04", "scene": "P6", - "text": "这几层结构不神秘,加起来两百多行,一个下午能读完。" + "text": "两百多行,一下午读完。" }, { "id": "p6-06", diff --git a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md index 83226e91..acb783d8 100644 --- a/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-explained-video/script/narration.md @@ -11,76 +11,86 @@ > P0 上浮吸收官方脚手架赌注三句,P4 上浮吸收退出码陷阱三句;P3 在补入沙箱四句与分类器成绩单两句的 > 同时净减 17 字(删掉六句咏叹与四处同义复述),全片净 +46 字。 > -> **叙事框架(2026-08-28 改写)**:全篇不做「教学版 ↔ 真实产品」的两轨对照解说,改为单主语直陈—— -> 「这套 Harness 是怎样的 → 最简实现拿来当例子 → 而实际实现是怎样的」。示例是讲解的脚手架, -> 不是与产品对立的另一极:故「教学版」一律改「最简实现/最简的做法/示例」,「真实产品」一律改 -> 「实际实现/实际的 Harness/它」。同幕连续「官方」变换主语(官方文档 / 官方工程博客 / 他们) -> 以避复读感;三级证据归属句(「有人拆过它的源码」「据他所说」)不动。本轮 167 句不增删, -> 净 +23 字(4025 → 4048),16 句改写待重配音(TTS 缓存按文本哈希,其余 151 句命中缓存)。 +> **叙事框架**:全篇不做「教学版 ↔ 真实产品」的两轨对照解说,改为单主语直陈—— +> 「这套 Harness 是怎样的 → 拿一份开源小版本当例子 → 而成型的那套是怎样的」。示例是讲解的脚手架, +> 不是与产品对立的另一极。同幕连续「官方」变换主语(官方文档 / 官方工程博客 / 他们)以避复读感; +> 三级证据归属句(「有人读源码读出来」「据他所说」)语义不动。 +> +> **口语化定式(2026-08-29 重铸,本文件唯一的行文纪律)**:口播是说给耳朵的,三条硬指标—— +> ① **禁书面对照名词**:「最简实现 / 实际实现 / 最简的做法」一律不用(当前 0 次)。指代示例用 +> 「玩具版 / 这个小版本 / 这份代码 / 开源那版」,指代产品用「成型的那套 / 真的那个 / 它」, +> 同一说法全片 ≤2 次,超了就换。 +> ② **口播行禁破折号**:`——` 是书面修辞,口播零容忍(当前口播 0 处;画面备注与角标不受限)。 +> 拆成两句、换冒号、或直接删——短句收尾比长句拖尾更有力。 +> ③ **长短交错**:每幕至少 2 处 ≤12 字的短句爆点,落在转折/金句/惊讶处;禁连续中长句排比成朗读腔。 +> 单句 6–35 字(下限 6 是为短句留出的空间,不是鼓励凑字)。 +> +> 本轮 167 句不增删、句 id 与句序零变动,94 句重铸,净 −25 字(4046 → 4021), +> 94 句待重配音(TTS 缓存按文本哈希,其余 73 句命中缓存)。 ## P0 你在当那个中间人 > 画面:终端窗口,光标闪烁。用户提问逐字打出,模型回一条命令后画面凝住。 > 随后「复制 → 粘贴 → 复制 → 粘贴」三轮,把画面塞满灰色的搬运痕迹。 -- [p0-01] 你让 AI 跑个脚本:它把命令写好,然后就停在那儿了。 -- [p0-02] 复制、粘贴、回车、再把输出贴回去——每一轮的搬运工,是你。 -- [p0-03] 从「写出命令」到「真的跑起来」,缺的那一层,官方起了名字。 -- [p0-03a] 这一层有多要紧?他们刷编程评测的战报里写过一句话—— +- [p0-01] 你让 AI 跑个脚本。它把命令写得漂漂亮亮的,然后就停在那儿了。 +- [p0-02] 复制、粘贴、回车,再把输出贴回去。每一轮的搬运工,是你。 +- [p0-03] 能写出命令,和真的跑起来,中间隔着一层。这一层,官方起过名字。 +- [p0-03a] 这一层到底有多要紧?他们自己的评测战报里,写过一句话。 - [p0-03b] 同一个底层模型,换一套脚手架,成绩能差出一大截。 -- [p0-03c] 你花在这一层上的力气,直接变成它的分数。 +- [p0-03c] 你出多少力,它得多少分。 - [p0-04] 名字就叫 Harness:把动力源,套进一个可控的结构里。 -- [p0-05] 官方说得直白:这套东西是 Harness,模型装在里面。 +- [p0-05] 官方自己说得很直白:这套东西就是 Harness,模型装在里面。 - [p0-06] Harness 给它四件:一个循环、一套工具、上下文管理、一道护栏。 -- [p0-07] 这集就把这个 Harness,一层一层拆开看。 +- [p0-07] 这集,就一层一层拆开它。 ## P1 一个循环,就是全部 > 画面:陶土橙闭合轨道成形(全片恒定视觉锚)。角标:Agent Loop · "One Loop Is All You Need" -- [p1-01] 先说结论:那一层的核心是一个循环,像一条不停转的传送带。 +- [p1-01] 先说结论。核心就是一个循环,像一条不停转的传送带。 - [p1-02] 它只做一件事:反复去问模型,接下来干什么。 -- [p1-03] 每问一次,就看模型的回答里有没有夹着一次工具调用。 -- [p1-04] 有,就说明模型举手了,它要用工具。 -- [p1-05] 那就替它把工具跑一遍,把结果原样塞回对话里,再问下一轮。 -- [p1-06] 没有,就说明它觉得活干完了,循环停机,把话交给你。 +- [p1-03] 每问一次,就翻开它的回答,看里面有没有夹着一次工具调用。 +- [p1-04] 有,模型举手了。 +- [p1-05] 那就替它把这件工具跑一遍,结果原样塞回对话里,然后接着问下一轮。 +- [p1-06] 没有,就是它觉得活干完了。循环停机,把话交还给你。 > 角标:`tool_use` block · 「有工具调用 → 继续 / 没有 → 退出」 -- [p1-08] 把这件事翻成代码,只有五步。 -- [p1-09] 先把你的问题放进消息列表,再连同「我有哪些工具」发给模型; -- [p1-10] 把模型的回答追加进列表,挑出里面所有的工具调用; -- [p1-11] 一个都没有,就地返回;有就逐个执行、收好每条结果; -- [p1-12] 最后把结果打包成新消息追加进去,回到第二步。写完了。 -- [p1-12a] 说明一下:有人照着这套机制搭了一份开源的最小实现。 -- [p1-12b] 下面拿它当例子,边读边说实际实现的做法。 -- [p1-13] 有人给它的评价是:三十多行,最小可运行的内核。 -- [p1-14] 我自己数过这一版:光循环那个函数,去掉空行和注释,二十三行。 +- [p1-08] 翻成代码,只有五步。 +- [p1-09] 先把你的问题放进消息列表,再连同「我有哪些工具」一起发给模型; +- [p1-10] 把模型的回答追加进列表,再挑出里面所有的工具调用; +- [p1-11] 一个都没有,就地返回;有,就逐个执行,收好每条结果; +- [p1-12] 最后把结果打包成一条新消息追加进去,回到第二步。写完了。 +- [p1-12a] 说明一下:有人照着这套机制,写过一个开源的小版本。 +- [p1-12b] 下面就拿它当例子,边读边说真正的做法。 +- [p1-13] 有人给它的评价是:三十多行,一个最小的、能跑的内核。 +- [p1-14] 我自己数了一遍:光循环那个函数,去掉空行和注释,二十三行。 > 角标:实测 `agent_loop` 非空非注释 23 行 @ pinned commit(口径与取数见 sources.toml) - [p1-15] 分工也说清楚了:模型决定要不要用工具、用哪一个, -- [p1-16] 脚手架负责真的去跑、把结果搬回来——判断力在那边,手脚在这边。 -- [p1-17] 模型回话时会附一个「我为什么停下来」的标记。 -- [p1-18] 最直觉的写法是直接看它;但最简实现偏不这么写, -- [p1-19] 而是翻开回答本身,看里面有没有工具调用。为什么? +- [p1-16] 壳负责真的去跑,把结果搬回来。判断力在那边,手脚在这边。 +- [p1-17] 模型每次回话,都会附一个「我为什么停下来」的标记。 +- [p1-18] 最直觉的写法就是直接看这个标记。可这份代码偏不这么干。 +- [p1-19] 它翻开回答本身,去看里面到底有没有工具调用。为什么这么绕? - [p1-20] 有人拆过它的源码,他给的理由是: - [p1-21] 回答是一个字一个字流出来的,工具调用早就流出来了, -- [p1-22] 那个标记却可能还没更新——他说源码注释写得很直白,这标记不可靠。 -- [p1-23] 所以真正的做法是一边流一边看,见到工具调用就记下还得再来一轮。 +- [p1-22] 那个标记却可能还没更新。他说源码注释写得很直白:这东西不可靠。 +- [p1-23] 所以真正的做法是一边流一边看。见到工具调用,就记下还得再来一轮。 - [p1-24] 别听它说「我说完了」,去看它手里还有没有活。 > 金句卡(serif):「别听它说『我说完了』,去看它手里还有没有活。」 > 角标:`stop_reason` is unreliable —— 第三方的源码分析 -- [p1-25] 官方给这个循环画过像:三件事交融着转—— -- [p1-26] 收集上下文、采取行动、验证结果,不是硬阶段。 +- [p1-25] 官方给这个循环画过像:三件事交融着转。 +- [p1-26] 收集上下文、采取行动、验证结果,它们不是硬阶段。 - [p1-27] 而且你随时可以打断它、补一句、让它改道。 -- [p1-28] 最简实现身上只带一份消息列表;实际的 Harness 带了十样, -- [p1-29] 压缩进度、补救次数、钩子拦没拦过停机、轮数——细节进角标。 -- [p1-30] 循环没长个,长出来的是它随身带的状态。 -- [p1-31] 退出的路子也有一大把:报错、中断、钩子叫停、预算烧完。 -- [p1-32] 但它们全是保护装置,不是骨架;骨架还是那二十来行。 +- [p1-28] 玩具版身上只带一份消息列表。成型的那套呢?整整带了十样: +- [p1-29] 压缩进度、补救次数、钩子拦没拦过停机、轮数。细节都进角标。 +- [p1-30] 循环没长个。长出来的是它随身带的那些状态。 +- [p1-31] 退出的路子还有一大把:报错、中断、钩子叫停、预算烧完。 +- [p1-32] 可它们全是保护装置,不是骨架。骨架还是那二十来行。 ## P2 加一个工具,只改一行 @@ -88,43 +98,43 @@ > 角标:Tool Use · "Add a Tool, Add Just One Line" - [p2-01] 刚才那个循环,手里只有一件工具:一个能跑命令的壳。 -- [p2-02] 想读文件,它得拼出一条读文件的命令;想写文件,得拼一条重定向。 -- [p2-03] 模型心里想的是「读这个文件」,嘴上却要翻译成一条命令行。 -- [p2-05] 那就把常用动作直接做成工具,于是从一件变成五件: +- [p2-02] 想读文件,它得拼出一条读文件的命令。想写文件,再拼一条重定向。 +- [p2-03] 模型心里想的是「读这个文件」,嘴上却得翻成一条命令行。 +- [p2-05] 那就干脆把常用动作直接做成工具。于是一件变成了五件: - [p2-06] 跑命令、读文件、写文件、改文件、按模式找文件。 -- [p2-07] 问题是循环怎么知道该调哪一个?答案朴素得让人意外:查一张表。 +- [p2-07] 可循环怎么知道该调哪一个?答案朴素得让人意外:查一张表。 - [p2-08] 一张字典,左边写工具的名字,右边写对应的处理函数。 - [p2-09] 像前台的转接号码簿:来电报个名字,前台照着簿子转接。 -- [p2-10] 于是加一个新工具只要两件事:在清单里加一条描述,在表里加一行。 -- [p2-11] 循环那边呢?我把两个版本逐行比过, -- [p2-12] 实质改动只有一行——原来写死了去跑命令,现在改成查表。 +- [p2-10] 加一个新工具就两件事:清单里加一条描述,表里加一行。 +- [p2-11] 那循环那边呢?我把前后两个版本逐行比过。 +- [p2-12] 实质改动只有一行。原来写死了去跑命令,现在改成查表。 - [p2-13] 换掉的是「执行」这一个动作,传送带一寸没动。 > 角标:实测 diff —— 唯一实质变更即 `run_bash(...)` → 查表调用 > 金句卡:「换掉的是执行那一步,传送带一寸没动。」 - [p2-14] 接着来了个新麻烦:模型经常一次要好几个工具。 -- [p2-15] 最简的做法是老实排队,一个一个来;实际实现里能并行的就并行。 -- [p2-16] 而它判断能不能并行的方式,是这一集我最想让你记住的一处。 +- [p2-15] 玩具版是老实排队,一个一个来。真的那个呢?能并行就并行。 +- [p2-16] 而它怎么判断能不能并行?这是这一集我最想让你记住的一处。 - [p2-17] 直觉会说:只读的可以一起跑,要写的不行。 -- [p2-18] 但按第三方的源码分析,这两件事其实不是一回事。 +- [p2-18] 但有人读源码读出来:这两件事根本不是一回事。 - [p2-19] 同一个跑命令的工具,让它列个目录算能并行,让它删个文件就不能。 -- [p2-20] 同一件工具,同一个名字,结论相反。 -- [p2-21] 因为判断的不是这件工具,是这一次具体要干什么。 +- [p2-20] 同一件工具,结论相反。 +- [p2-21] 判断的根本不是这件工具,是这一次具体要干什么。 - [p2-22] 反过来还有更绕的:有的工具明明在改东西,却可以并行, -- [p2-23] 原因是它每次改的都是不同的文件,谁也不挡谁。 +- [p2-23] 因为它每次改的都是不同的文件,谁也不挡谁。 - [p2-24] 所以「能不能一起跑」跟「是不是只读」,是两条独立的判断。 > 金句卡(serif):「『能不能一起跑』跟『是不是只读』,是两条独立的判断。」 > 角标:`isConcurrencySafe` ≠ `isReadOnly` —— 第三方的源码分析 -- [p2-25] 判断完了怎么排?按原来的顺序切段:连着能并行的划成一组一起跑, +- [p2-25] 判断完了怎么排?按原来的顺序切段:连着能并行的划成一组,一起跑, - [p2-26] 中间夹着不能并行的就单独一组;组内并行,组间严格按顺序。 -- [p2-27] 他还提到,工具输出太长时它不会全喂给模型,而是存成文件, -- [p2-28] 只给它一段预览和一个路径。 +- [p2-27] 他还提到一件事:工具输出太长,它不会全喂给模型,而是存成文件, +- [p2-28] 只给一段预览和一个路径。 - [p2-29] 但「读文件」这件工具被特别开了口子:输出永远不许存成文件。 - [p2-30] 因为一旦存了,模型下次去读那个文件,输出又太长,又被存成文件。 -- [p2-31] 读、存、再读、再存,它会自己套住自己,转不出来。 +- [p2-31] 读、存、再读、再存。它自己把自己套住了,转不出来。 ## P3 执行之前,先过闸门 @@ -132,45 +142,45 @@ > 角标:Permission · "Check Permissions Before Execution" - [p3-01] 现在这个 AI 有五件工具,其中一件能跑任意命令。 -- [p3-02] 读写文件那几件,都被拦在工作目录里;跑命令那件,没人管。 +- [p3-02] 读写文件那几件,都被拦在工作目录里。跑命令那件,没人管。 - [p3-03] 你随口说一句「帮我把项目清理一下」, -- [p3-04] 它完全可能给你递上一条把整块盘删干净的命令,循环照跑。 +- [p3-04] 它完全可能给你递上一条把整块盘删干净的命令。循环照跑。 - [p3-06] 官方把话说死了:权限由这层代码执行,不由模型执行。 -- [p3-07] 拦法是三道闸门,顺序写死。 +- [p3-07] 三道闸门,顺序写死。 - [p3-08] 第一道是一张硬拒绝表:删根目录、提权、关机、格式化。 -- [p3-09] 命中就直接挡回去,连问都不问。 +- [p3-09] 命中就挡回去,问都不问。 - [p3-10] 第二道是规则匹配,管「看情况」的操作: -- [p3-11] 读写工作目录之外的东西,或者命令里带着删除、改权限这类动作。 -- [p3-12] 第三道就是问你:画面停下来,把工具名和参数摆给你看,等你点头。 -- [p3-14] 最简实现自己承认:这张拒绝表只是字符串匹配,换个拼法就绕过去。 +- [p3-11] 读写工作目录之外的东西;或者命令里带着删除、改权限这类动作。 +- [p3-12] 第三道就是问你:画面停住,把工具名和参数摆给你看,等你点头。 +- [p3-14] 这份代码自己也承认:拒绝表只是字符串匹配,换个拼法就绕过去。 - [p3-15] 它告诉你闸门装在哪儿,不替你把门守住。 > 金句卡(serif):「它告诉你闸门装在哪儿,不是替你把门守住。」(与 p3-15 音画同句) -- [p3-19a] 真正的边界在更底下一层:它给跑命令那件工具,套了一层沙箱。 +- [p3-19a] 真正的边界在更底下一层。跑命令那件工具,被套进了一层沙箱。 - [p3-19b] 能写哪些目录、能走哪个网络出口,由操作系统说了算。 -- [p3-19c] 规则是劝,沙箱是锁——两道墙少一道,笼子就不成立。 +- [p3-19c] 规则是劝,沙箱是锁。两道墙少一道,笼子就不成立。 - [p3-19d] 官方工程博客给了数:内部用下来权限提示少八成四。 > 角标:Seatbelt / bubblewrap + socat · 文件系统与网络双边界 · 权限提示 −84%(官方工程博客,取数 2025-10) -- [p3-20] 回到闸门这边:有人拆过它的源码,判定结果是四种,不是三种。 -- [p3-23] 多出来的第四种最有意思:工具选择不表态。 -- [p3-24] 也就是说,弃权不等于放行,兜底永远是问你一句。 -- [p3-25] 规则求值顺序官方文档也写死了:拒绝、询问、放行, -- [p3-26] 头一个命中就出局——规则写得多具体,都改变不了顺序。 +- [p3-20] 回到闸门这边。有人读源码读出来:判出来是四种,不是三种。 +- [p3-23] 多出来的第四种最有意思:这件工具选择不表态。 +- [p3-24] 也就是说,弃权不等于放行。兜底永远是问你一句。 +- [p3-25] 规则是一条条往下判的,顺序官方也写死了:拒绝、询问、放行。 +- [p3-26] 头一个命中就出局。规则写得再具体,也改不了顺序。 - [p3-28] 裸名拒绝更狠:整件工具从模型身上直接消失。 -- [p3-29] 就算全放行模式,也压不住一条写死的拒绝。 +- [p3-29] 就算你开了全放行模式,也压不住一条写死的拒绝。 > 角标:user < project < local < flag < policy(+ cliArg / command / session)——第三方的源码分析 -- [p3-30] 全自动模式不靠你点头的次数,靠另一个模型当闸门。 +- [p3-30] 全自动模式不靠你点头的次数,靠另一个模型来当闸门。 - [p3-31] 官方遥测补一刀:权限提示,九成三都被点了批准。 - [p3-31a] 这个当闸门的模型,自己也进过考场。 - [p3-31b] 快筛误杀率百分之八点五,复核之后压到千分之四。 -- [p3-32] 审判者的视野是做减法的:只看用户消息和裸命令。 -- [p3-34] 评它做了什么,不看它说了什么——注入的谎话骗不到它。 -- [p3-35] 让模型帮忙看门,同时不敢把门全交给模型。 +- [p3-32] 这个审判者的视野是做减法的:只看用户消息和裸命令。 +- [p3-34] 评它做了什么,不看它说了什么。注入的谎话骗不到它。 +- [p3-35] 让模型帮忙看门,又不敢把门全交给模型。 ## P4 挂在循环上,不写进循环里 @@ -178,52 +188,52 @@ > 角标:Hooks · "Hang on the Loop, Don't Write into It" - [p4-01] 到这一步,这个 AI 已经能安全地动手了。 -- [p4-02] 接下来的麻烦,做过工程的人都熟:你想加点东西。 +- [p4-02] 接下来的麻烦,做过工程的人都熟悉:你想给它加点东西。 - [p4-03] 比如每次跑命令都记一笔日志,或者某些操作做完自动提交一次代码。 -- [p4-04] 每加一样,你都得回去改那个循环。 -- [p4-05] 有人画过一张很扎心的图:循环体里记日志一行、查权限一行、 -- [p4-06] 发通知一行、自动提交又一行,加到后面那段代码已经认不出来了。 +- [p4-04] 加一样,改一次循环。 +- [p4-05] 有人画过一张很扎心的图:循环体里,记日志一行、查权限一行、 +- [p4-06] 发通知一行、自动提交又一行。加到后面,那段代码已经认不出来了。 - [p4-07] 原话说得很准:你想扩展的是它的行为,你改的却是循环本身。 > 金句卡(serif):「你想扩展的是它的行为,你改的却是循环本身。」 - [p4-08] 正确的做法是把循环留成稳定的内核,让扩展挂在外面。 - [p4-09] 具体做法又是一张表:左边是「时机」,右边是这个时机要跑的函数。 -- [p4-10] 循环到了某个时机只喊一声名字,至于该跑什么,由那张表说了算。 +- [p4-10] 循环到了某个时机,只喊一声名字。至于该跑什么,那张表说了算。 - [p4-11] 像墙上的插线口:循环是插座,功能是插头。 - [p4-12] 加功能是插一个插头,不是重新布线。 -- [p4-13] 最简实现留了四个插口,正好串成一整轮。 +- [p4-13] 这个小版本留了四个插口,正好串成一整轮。 - [p4-14] 第一个,你的话交出去、还没进模型之前:校验输入,或者补点背景。 - [p4-15] 第二个,工具要执行之前。刚才那三道闸门就搬到了这个插口上, - [p4-16] 循环从此不再认识任何一个检查函数。 - [p4-17] 第三个,工具执行完、还没进下一轮之前:收尾的副作用挂这儿。 - [p4-18] 第四个,循环准备停机之前。这个插口最有权力: -- [p4-19] 它返回一句话,这句话就被当成新输入塞回去,循环继续转。 +- [p4-19] 它返回一句话,这句话就被当成新输入塞回去,循环接着转。 - [p4-20] 四个插口覆盖一整轮,循环只在这四个点上喊一声。 - [p4-22] 有句话我很喜欢:这个循环是故意保持无聊的。 > 金句卡(serif):「这个循环是故意保持无聊的。」 -- [p4-23] 实际实现里这样的时机,官方文档口径三十一个, +- [p4-23] 成型的那套里,这样的时机官方文档口径三十一个, - [p4-24] 分三种节奏:会话一次、回合一次、每次调用前后。 -- [p4-25] 处理器也不只是跑脚本,还能让小模型单轮判决。 -- [p4-27] 表态的契约值得单独记:沉默,不等于批准—— +- [p4-25] 挂上去的也不只是脚本,还能让小模型单轮判一次。 +- [p4-27] 这里有个契约值得单独记下来:沉默,不等于批准。 - [p4-28] 不吭声的意思是「我不作决定」,流程照走。 -- [p4-28a] 反过来,想真拦住只有一个硬信号;写错成惯用的失败码, -- [p4-28b] 闸门不响、动作照跑——静默失效。 +- [p4-28a] 想真拦住,只有一个硬信号。写错成惯用的那个失败码, +- [p4-28b] 闸门不响,动作照跑。 - [p4-28c] 第一次给循环挂扩展的人,几乎都栽在这一脚上。 - [p4-29] 插口上的函数说「这个我批了」,就真的放行吗?不。 -- [p4-30] 它的放行,仍要穿过后面的拒绝与询问两站。 +- [p4-30] 这句「批了」,后面还得穿过拒绝和询问两站。 - [p4-31] 方向是单向的:扩展点能加限制,不能解除限制。 -- [p4-32] 而且官方把权限判定,画成过一条六道闸门的流水线。 -- [p4-33] 这一层超出了最简实现的范围,拆源码的人评语是: -- [p4-34] 做示例够用,生产环境就是一个安全漏洞。 +- [p4-32] 官方还给权限判定画过一张图:六道闸门,一道一道过。 +- [p4-33] 这一步,开源那版根本没做。读源码的人给的评语是: +- [p4-34] 当例子够用,放进生产就是个安全漏洞。 > 金句卡(serif):「扩展点能加限制,不能解除限制。」 > 角标:hook `allow` 不能绕过 settings 的 deny/ask —— 第三方的源码分析 -- [p4-35] 那个能说「别停」的插口本身很危险——它叫模型接着干, -- [p4-36] 模型干完又要停,它又叫接着干,就转不出来了。 +- [p4-35] 那个能说「别停」的插口,自己就很危险。它叫模型接着干, +- [p4-36] 模型干完又要停,它又叫接着干。转不出来了。 - [p4-37] 据他所说,它放了个标记,后面的轮次看到就不再拦。 ## P5 四层叠起来是什么 @@ -237,9 +247,9 @@ - [p5-04] 第三层,三道闸门:让危险的事在执行之前被拦住。 - [p5-05] 回到官方那四件:循环、工具、上下文管理、护栏。 - [p5-06] 这集填上了三件,上下文管理那格先空着,留到后面拆。 -- [p5-07] 这不是我的说法,是可以数出来的。 +- [p5-07] 这不是我一个人的说法,是能数出来的。 - [p5-08] 我把四个版本的代码逐一量过:整个程序从一百四十行出头, -- [p5-09] 长到两百五十多行,长了八成; +- [p5-09] 长到两百五十多行,整整长了八成; - [p5-10] 而那个循环函数,一直在二十到二十八行之间。 - [p5-11] 骨架一字未改:调模型,看回答里有没有工具调用,执行,填回结果。 - [p5-13] 变的只有「执行」那一步:从写死命令,到查表,到闸门,到一排插口。 @@ -251,7 +261,7 @@ - [p5-15] 所以再回到开头那个问题: - [p5-16] 从能写出一条命令,到真的在你电脑上跑起来,缺的那一层是什么? - [p5-17] 就是这个:一个愿意反复跑、能查表、会拦门、留了插口的壳。 -- [p5-18] 这个项目的作者把它的作用写成一句话,我觉得是全篇最好的一句: +- [p5-18] 这个项目的作者,把这层壳的作用写成了一句话。我觉得是全篇最好的: - [p5-19] 能动性来自模型,而这层壳,给能动性一个落地的地方。 > 金句卡(serif,英文原文并列): @@ -262,9 +272,9 @@ > 画面:信源卡(官方文档 + 取数日期 / 第三方源码分析已逐处标注 / 数字均为实测口径)→ 系列身份卡 → 渐黑。 > 渐黑窗口从**末 beat** 总时长推导(不是末句),见 skills/06 红线四。 -- [p6-01] 它敢在你的电脑上动手,不是因为它足够聪明, -- [p6-02] 而是因为有人在它周围,搭了这几层结构。 -- [p6-04] 这几层结构不神秘,加起来两百多行,一个下午能读完。 +- [p6-01] 它敢动手,不是因为聪明。 +- [p6-02] 是因为有人在它周围,一层一层,把这些结构搭了出来。 +- [p6-04] 两百多行,一下午读完。 - [p6-06] 本片机制依据官方文档,取数2026年8月,以官方最新表述为准。 - [p6-07] 示例代码来自开源实现,行数均为实测,链接在简介。 - [p6-05] 学会给 Harness 做加减法,这本身就是一门手艺。 diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json index c30b7a4a..ba4a35c6 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.json @@ -2,17 +2,17 @@ { "id": "p0-01", "scene": "P0", - "text": "它正在干活,突然,停了。一个小时的活,一行报错,全部作废。" + "text": "它干得好好的,突然停了。一个小时的活,一行报错,全白干。" }, { "id": "p0-02", "scene": "P0", - "text": "不是它不想干,是服务那边拒收了——理由直白:你随身带的,太大了。" + "text": "不是它不想干,是服务那边拒收了。理由很直白:你随身带的,太大了。" }, { "id": "p0-04", "scene": "P0", - "text": "它没有记性:读过的每个文件、跑过的每条命令、你说的每句话,全带着——" + "text": "它压根没有记性。读过的每个文件、跑过的每条命令、你说的每句话,全带着。" }, { "id": "p0-05", @@ -22,37 +22,37 @@ { "id": "p0-05a", "scene": "P0", - "text": "而且开局就不空——你还没敲第一个字,窗口里已躺着好几样东西。" + "text": "而且开局就不空。你还没敲第一个字,窗口里已经躺着好几样东西了。" }, { "id": "p0-05b", "scene": "P0", - "text": "官方文档给过一份示意账:光基本设定,就占四千多字。" + "text": "官方文档给过一份示意账:光是基本设定,就占掉四千多字。" }, { "id": "p0-06", "scene": "P0", - "text": "垫到顶,就是开头那行报错。" + "text": "垫到顶,就是那行报错。" }, { "id": "p0-09", "scene": "P0", - "text": "官方工程博客还补了一刀:窗口越长,它记得反而越不准。" + "text": "官方的工程博客还补了一刀:窗口越长,它记得反而越不准。" }, { "id": "p0-09a", "scene": "P0", - "text": "原因不玄:每多一个字,要照顾的两两关系就多一圈。" + "text": "原因不玄。每多一个字,要照顾的两两关系就多一圈。" }, { "id": "p0-09b", "scene": "P0", - "text": "而注意力的总量是固定的——摊得越薄,看得越糊。" + "text": "可注意力的总量就那么多。摊得越薄,看得越糊。窗口再大也一样。" }, { "id": "p0-09c", "scene": "P0", - "text": "所以窗口再大,也不等于记性变好——能装,不等于能记。" + "text": "能装,不等于能记。" }, { "id": "p0-10", @@ -62,42 +62,42 @@ { "id": "p0-11", "scene": "P0", - "text": "它分两半:安排它看什么,和装满了怎么办——今天拆后一半。" + "text": "它分两半:安排它看什么,和装满了怎么办。今天只拆后一半。" }, { "id": "p0-13", "scene": "P0", - "text": "后一半的答案分两层,对应两种完全不同的心态。" + "text": "而后一半的答案分两层,对应的是两种完全不同的心态。" }, { "id": "p0-14", "scene": "P0", - "text": "第一层承认会丢:窗口一定会满,那就把丢管起来——分级、有序、有保底。" + "text": "第一层承认会丢。窗口一定会满,那就把丢管起来:分级、有序、还有保底。" }, { "id": "p0-15", "scene": "P0", - "text": "第二层保证不丢:另立一个不参与压缩的账本,重要的写进去就不出来。" + "text": "第二层干脆保证不丢:另立一个不参与压缩的账本,写进去就不出来。" }, { "id": "p1-01", "scene": "P1", - "text": "先把画面换个说法:它随身的全部对话,就是一张会塞满的桌子。" + "text": "先把画面换个说法。它随身带着的全部对话,就是一张会塞满的桌子。" }, { "id": "p1-02", "scene": "P1", - "text": "第一层要办的,就是把丢管好——收拾这张桌子,最简的做法分四级。" + "text": "第一层要办的就是把丢管好。收拾这张桌子,最简单的版本分四级。" }, { "id": "p1-03", "scene": "P1", - "text": "四级办法的原则只有一条:便宜的先来,贵的最后。" + "text": "原则只有一条:便宜的先来,贵的最后。" }, { "id": "p1-04", "scene": "P1", - "text": "先干不用花钱的,实在不行才请人。你会看到这条原则贯穿到底。" + "text": "先干不花钱的,实在不行才请人。这条原则会一路贯穿到底,你会看到。" }, { "id": "p1-05", @@ -117,52 +117,52 @@ { "id": "p1-08", "scene": "P1", - "text": "你要它干什么的原始交代就在那几张里,丢了它就再也找不回初衷。" + "text": "你要它干什么,原始交代就在那几张里。丢了,就再也找不回初衷。" }, { "id": "p1-09", "scene": "P1", - "text": "为什么留最近的?因为手头的活都在最近几张纸上,正在用的不能动。" + "text": "为什么留最近的?因为手头的活都在最近那几张纸上,正在用的不能动。" }, { "id": "p1-10", "scene": "P1", - "text": "中间的呢?大多是过气的中间过程——当时重要,现在回头看的概率很低。" + "text": "中间的呢?大多是过气的中间过程。当时挺重要,现在几乎不会再翻。" }, { "id": "p1-11", "scene": "P1", - "text": "还有个讲究:不许把一张「请求」和它对应的「回执」拆开。" + "text": "请求和回执,不许拆开。" }, { "id": "p1-12", "scene": "P1", - "text": "请求还在、回执被裁走,桌上就留下一个永远等不到答案的问题。" + "text": "请求还在,回执被裁走了。桌上就留下一个永远等不到答案的问题。" }, { "id": "p1-13", "scene": "P1", - "text": "第二级,折旧纸。旧工具结果的完整内容,只保留最近三条," + "text": "第二级,折旧纸。旧工具结果的完整内容,只留最近三条," }, { "id": "p1-14", "scene": "P1", - "text": "更早的那些折成一行字:早前结果已收起,需要的话再跑一遍。" + "text": "更早的那些折成一行字:早前结果已收起,真要用,再跑一遍就是。" }, { "id": "p1-15", "scene": "P1", - "text": "反正真需要的时候,再让它跑一遍就是——纸可以折,活不用重干。" + "text": "纸可以折,活不用重干。" }, { "id": "p1-16", "scene": "P1", - "text": "注意折叠只动超过一百二十字的旧结果,短的就留着,不值得费这个事。" + "text": "折叠只动超过一百二十字的旧结果。短的就留着,不值得费这个事。" }, { "id": "p1-17", "scene": "P1", - "text": "这两级全是纯文本操作,一次模型都不用请,便宜到近乎免费。" + "text": "这两级全都是纯文本操作,一次模型都不用请,便宜到几乎免费。" }, { "id": "p1-18", @@ -172,12 +172,12 @@ { "id": "p1-19", "scene": "P1", - "text": "这四级就是那两句的细化。便宜先来、贵的殿后,方向一致。" + "text": "这四级就是那两句话的细化。便宜先来,贵的殿后,方向完全一致。" }, { "id": "p1-20", "scene": "P1", - "text": "记住这个次序感:先动最不心疼的,再动开始心疼的。这是这一层的节拍。" + "text": "记住这个次序感:先动最不心疼的,再动开始心疼的。这就是这一层的节拍。" }, { "id": "p2-01", @@ -187,7 +187,7 @@ { "id": "p2-02", "scene": "P2", - "text": "比如它一口气读了五个大文件,五份全文一起拍在桌上,一拍就是半个桌。" + "text": "比如它一口气读了五个大文件,五份全文一起拍上桌,一拍就是半张桌。" }, { "id": "p2-03", @@ -202,17 +202,17 @@ { "id": "p2-05", "scene": "P2", - "text": "它看到标记就知道:全文在磁盘上躺着,真要用,再取就是。" + "text": "它一看到标记就知道:全文还在磁盘上躺着,真要用,再取回来就是。" }, { "id": "p2-06", "scene": "P2", - "text": "这一级还是不用请模型,只是搬东西——便宜,但能腾出最大的空间。" + "text": "这一级还是不用请模型,只是搬东西。便宜,但腾出来的空间最大。" }, { "id": "p2-07", "scene": "P2", - "text": "第四级,全桌重写。三级都跑完桌子还是满的,就只能请人来写摘要了。" + "text": "第四级,全桌重写。前三级跑完桌子还是满的,就只能请人来写摘要了。" }, { "id": "p2-08", @@ -222,7 +222,7 @@ { "id": "p2-09", "scene": "P2", - "text": "这是保底——摘要写砸了,原始记录还在,不至于两头空。" + "text": "这是保底。万一摘要写砸了,原始记录还在,不至于两头落空。" }, { "id": "p2-10", @@ -232,17 +232,17 @@ { "id": "p2-11", "scene": "P2", - "text": "还剩什么活、你交代过什么约束。写完,整桌纸换成这一张。" + "text": "还剩什么活、你交代过什么约束。写完,整桌纸就换成这一张。" }, { "id": "p2-12", "scene": "P2", - "text": "这是四级里唯一要花一次模型调用的,最贵,所以放最后。" + "text": "这是四级里唯一要花掉一次模型调用的,最贵,所以放在最后。" }, { "id": "p2-13", "scene": "P2", - "text": "重写要是连着失败三次,熔断,不再试——别把预算烧在死循环上。" + "text": "重写连砸三次就熔断。死循环不配烧预算。" }, { "id": "p2-14", @@ -257,17 +257,17 @@ { "id": "p2-16", "scene": "P2", - "text": "现在说这一集最要紧的一个细节:这几级的顺序,是锁死的。" + "text": "现在说这一集最要紧的一个细节。这几级的顺序,是锁死的。" }, { "id": "p2-17", "scene": "P2", - "text": "入库必须在折叠之前。因为折叠会把旧的大块头换成一行字。" + "text": "入库必须在折叠之前。" }, { "id": "p2-18", "scene": "P2", - "text": "顺序反了,等你想起来要存原文的时候,原文已经不在了——" + "text": "因为折叠会把旧的大块头换成一行字。顺序反了,原文就已经不在了。" }, { "id": "p2-19", @@ -277,7 +277,7 @@ { "id": "p2-20", "scene": "P2", - "text": "我们在画面里把顺序对调一次给你看:折叠先行,大块头瞬间缩成一行," + "text": "画面里我们把顺序对调一次给你看。折叠先行,大块头瞬间缩成一行," }, { "id": "p2-21", @@ -287,7 +287,7 @@ { "id": "p2-22", "scene": "P2", - "text": "有人核对过源码,它的真实实现里也是入库在前。一个看似平常的先后," + "text": "有人读过它的源码,成型的这套也是入库在前。一个看似平常的先后," }, { "id": "p2-23", @@ -297,22 +297,22 @@ { "id": "p2-24", "scene": "P2", - "text": "很多系统坏在这种地方:每一步都对,合起来的次序错了。" + "text": "很多系统就坏在这个地方:每一步都对,合起来的次序错了。" }, { "id": "p3-01", "scene": "P3", - "text": "回到四级收拾,里面还有两处值得单独说说。" + "text": "回到四级收拾。这里面还有两处值得单独说说。一处是写摘要这位帮工。" }, { "id": "p3-02", "scene": "P3", - "text": "一处是写摘要这位帮工。它的纪律严得有点好笑。" + "text": "它的纪律,严得有点好笑。" }, { "id": "p3-03", "scene": "P3", - "text": "有人把真实实现里给它的指令原文抄了出来,开头第一句就是:" + "text": "有人把它真正用的那段指令原文抄了出来,开头第一句就是:" }, { "id": "p3-04", @@ -322,37 +322,37 @@ { "id": "p3-05", "scene": "P3", - "text": "为什么叮嘱两遍?请来收拾桌子的,手上偏偏有搬东西的能力。" + "text": "为什么叮嘱两遍?请来收拾桌子的,手上偏偏有搬东西的本事。" }, { "id": "p3-06", "scene": "P3", - "text": "真让它边收拾边调用工具,桌子越收越满,收拾就变成了新的堆积。" + "text": "真让它边收拾边调工具,桌子只会越收越满,收拾就变成了新的堆积。" }, { "id": "p3-07", "scene": "P3", - "text": "它还必须先在草稿区理清思路,再誊出正式摘要。" + "text": "它还必须先在草稿区里理清思路,再誊写出正式的摘要。" }, { "id": "p3-08", "scene": "P3", - "text": "草稿写完就撕掉,不留在桌上——草稿是给它自己看的,不是给对话看的。" + "text": "草稿写完就撕掉,不留在桌上。那是给它自己看的,不是给对话看的。" }, { "id": "p3-09", "scene": "P3", - "text": "另一处是压缩过后的存活名单,官方给过一张矩阵——" + "text": "另一处是压缩过后的存活名单,官方也给过一张矩阵。" }, { "id": "p3-10", "scene": "P3", - "text": "系统提示绕行不变;规则和自动记忆从磁盘重新注入;" + "text": "系统提示绕行不变。规则和自动记忆,从磁盘上重新读一遍。" }, { "id": "p3-11", "scene": "P3", - "text": "用过的技能正文重注入,但每份封顶五千、最旧的先丢。" + "text": "用过的技能正文也读回来,但每份封顶五千,最旧的先丢。" }, { "id": "p3-12", @@ -362,42 +362,42 @@ { "id": "p3-13", "scene": "P3", - "text": "最多五个、按重要性排队——丢,也是分层次的丢。" + "text": "最多五个,按重要性排队。丢,也是分层次的丢。" }, { "id": "p3-14", "scene": "P3", - "text": "这一步超出了最简实现的范围,是有人从源码里读出来的——所以听到这里," + "text": "这一步玩具版没做,是有人读源码读出来的。所以听到这里," }, { "id": "p3-15", "scene": "P3", - "text": "请记住同一句提醒:这是他的源码分析,不是官方的说明书。" + "text": "记住那句提醒:这是他的源码分析,不是官方的说明书。第一层就讲完了。" }, { "id": "p3-16", "scene": "P3", - "text": "到这里,第一层讲完了:会丢的东西,被管得相当讲究。" + "text": "会丢的,管得真讲究。" }, { "id": "p4-01", "scene": "P4", - "text": "但是你发现没有——四级收拾、应急抢救、往回捞,全是「桌面上的事」。" + "text": "但是你发现没有?四级收拾、应急抢救、往回捞,全是桌面上的事。" }, { "id": "p4-02", "scene": "P4", - "text": "桌面上的东西再怎么管,都有一个共同命运:迟早被压掉。" + "text": "桌面上的东西再怎么管,都逃不掉一个共同命运:迟早被压掉。" }, { "id": "p4-03", "scene": "P4", - "text": "有个特别扎心的例子。你认真交代过:缩进用 tab,别用空格。" + "text": "有个例子特别扎心。你认认真真交代过:缩进用 tab,别用空格。" }, { "id": "p4-04", "scene": "P4", - "text": "这句话原封不动躺在对话里,一切都好。" + "text": "这句话原封不动地躺在对话里,一切都好。" }, { "id": "p4-05", @@ -407,27 +407,27 @@ { "id": "p4-06", "scene": "P4", - "text": "摘要没有做错什么——摘要的天性就是丢细节,保主干。" + "text": "摘要没有做错什么。摘要的天性就是丢细节,保主干。" }, { "id": "p4-07", "scene": "P4", - "text": "可有些细节,恰恰是主干。你的偏好就是你的偏好,缩不成一句概括。" + "text": "可有些细节恰恰就是主干。你的偏好就是你的偏好,缩不成一句概括。" }, { "id": "p4-08", "scene": "P4", - "text": "所以需要另一层:不参与压缩的两条腿。第一条你写——项目里那个文件夹。" + "text": "所以得另起一层:不参与压缩的两条腿。第一条你写,项目里那个文件夹。" }, { "id": "p4-08a", "scene": "P4", - "text": "这里要纠正一个流传很广的说法:里面的规则不是它的基本设定。" + "text": "这里要纠正一个流传很广的说法:里面的规则,不是它的基本设定。" }, { "id": "p4-08b", "scene": "P4", - "text": "那是设定之后递进来的第一条普通消息——跟你说的话同一个身份。" + "text": "那是设定之后递进来的第一条普通消息。跟你说的话,同一个身份。" }, { "id": "p4-08c", @@ -437,17 +437,17 @@ { "id": "p4-08d", "scene": "P4", - "text": "所以「写了它没听」不是故障——这层本来就只是建议。" + "text": "所以「写了它没听」不是故障。这一层本来就只是建议。" }, { "id": "p4-09", "scene": "P4", - "text": "这些文件层层拼接,越靠近工作目录的越后读,超两百行就开始不老实。" + "text": "这些文件层层拼接,越靠近工作目录的越后读。超过两百行就开始不老实。" }, { "id": "p4-10", "scene": "P4", - "text": "一件事一个文件,开头三行登记:叫什么、一句话说明、属于哪类。" + "text": "一件事一个文件,开头三行登记:叫什么、一句话说明、属于哪一类。" }, { "id": "p4-11", @@ -457,67 +457,67 @@ { "id": "p4-12", "scene": "P4", - "text": "而且记过的不再记——这条防的是本子自己长胖。" + "text": "而且记过的不再记。这条防的是本子自己长胖。" }, { "id": "p4-13", "scene": "P4", - "text": "四类记忆,其实就是四个问题。" + "text": "四类,其实就是四个问题。" }, { "id": "p4-14", "scene": "P4", - "text": "你是谁——偏好和习惯,「缩进用 tab」就记在这类;" + "text": "你是谁?偏好和习惯,「缩进用 tab」就记在这一类;" }, { "id": "p4-15", "scene": "P4", - "text": "怎么干活——反馈和规矩,「别造假数据」;" + "text": "怎么干活?反馈和规矩,比如「别造假数据」;" }, { "id": "p4-16", "scene": "P4", - "text": "在发生什么——项目背景,「这次重写是合规驱动的」;" + "text": "在发生什么?项目背景,「这次重写是合规驱动的」;" }, { "id": "p4-17", "scene": "P4", - "text": "去哪儿找——线索和入口,「那个老 bug 记录在哪」。" + "text": "去哪儿找?线索和入口,「那个老 bug 记录在哪」。" }, { "id": "p4-18", "scene": "P4", - "text": "四类之外还有一份索引:它垫在你开口之前,每次开工先扫一眼。" + "text": "四类之外还有一份索引。它垫在你开口之前,每次开工先扫一眼。" }, { "id": "p4-19", "scene": "P4", - "text": "索引也有上限:最多两百行,超了就要整理。家底要薄,才有用。" + "text": "索引也有上限:最多两百行,超了就得整理。家底要薄,才有用。" }, { "id": "p4-20", "scene": "P4", - "text": "取的时候分两条路。索引常驻是第一条,便宜、全天候。" + "text": "取的时候分两条路。索引常驻是第一条,便宜,而且全天候。" }, { "id": "p4-21", "scene": "P4", - "text": "第二条是按需取:每轮开始前,把最近对话和记忆清单发给一个小模型," + "text": "第二条是按需取:每轮开始之前,把最近对话和记忆清单发给一个小模型," }, { "id": "p4-22", "scene": "P4", - "text": "请它挑真正用得上的,最多五条;拿不准就不挑,宁缺毋滥。" + "text": "请它挑真正用得上的,最多五条。拿不准就不挑,宁缺毋滥。" }, { "id": "p4-23", "scene": "P4", - "text": "挑错了比没挑更糟——一条不相干的记忆,就是一句错误的自我介绍。" + "text": "挑错了比没挑更糟。一条不相干的记忆,就是一句错误的自我介绍。" }, { "id": "p4-24", "scene": "P4", - "text": "还有个经济学尾巴:前缀缓存按字数打折,但前缀必须一字不差——" + "text": "还有个经济学尾巴:前缀缓存按字数打折,但前缀必须一字不差。" }, { "id": "p4-25", @@ -527,7 +527,7 @@ { "id": "p4-25a", "scene": "P4", - "text": "这张卡的价目官方也挂着:命中的一折计费,写入加四分之一——" + "text": "这张卡的价目官方也挂着:命中的一折计费,写入加四分之一。" }, { "id": "p4-25b", @@ -537,37 +537,37 @@ { "id": "p4-26", "scene": "P4", - "text": "挑记忆这活,就是一个普通的小号模型在干——不用向量检索,反而可靠。" + "text": "挑记忆这个活,就是个普通的小模型在干。不用向量检索,反而可靠。" }, { "id": "p4-27", "scene": "P4", - "text": "挑出来的内容不进基本设定,临时贴进这一轮——" + "text": "挑出来的内容不进基本设定,只是临时贴进这一轮。" }, { "id": "p4-28", "scene": "P4", - "text": "用完就过气。取记忆,也是一次性的。" + "text": "用完就过气了。" }, { "id": "p4-29", "scene": "P4", - "text": "一层永久的存,一次临时的取——这个组合,才让不丢变得便宜。" + "text": "取记忆也是一次性的。一层永久的存,一次临时的取,不丢才变得便宜。" }, { "id": "p5-01", "scene": "P5", - "text": "现在到了两套机制咬合的那一瞬间,也是这一集的题眼。" + "text": "现在到了两套机制咬合的那一瞬间,这也正是这一集的题眼。" }, { "id": "p5-02", "scene": "P5", - "text": "写入登记簿这件事,发生在每一轮结束的时候——对话告一段落,活干完了。" + "text": "写进登记簿这件事,发生在每一轮结束的时候。对话告一段落,活干完了。" }, { "id": "p5-03", "scene": "P5", - "text": "关键在于取材的时机:提取器看的,是压缩之前的那份完整对话。" + "text": "关键在取材的时机。提取器看的,是压缩之前那份完整的对话。" }, { "id": "p5-04", @@ -577,32 +577,32 @@ { "id": "p5-05", "scene": "P5", - "text": "有人拆过它的源码——它的实现里由一个「停机钩子」触发这件事:" + "text": "有人拆过它的源码。真做的时候,是一个「停机钩子」在触发这件事:" }, { "id": "p5-06", "scene": "P5", - "text": "派出去的提取器权限受限、最多五回合、干完不进对话,闷头干完就走。" + "text": "派出去的提取器权限受限、最多五回合、结果不进对话,闷头干完就走。" }, { "id": "p5-07", "scene": "P5", - "text": "把时间线摆在一起看,就明白这个先后有多讲究。" + "text": "把两条时间线摆在一起看,这个先后有多讲究就清楚了。" }, { "id": "p5-08", "scene": "P5", - "text": "轮末:先从完整对话里抢救出值得记的,一个字不差地写进本子;" + "text": "轮末:先从完整对话里抢救出值得记的,一字不差地写进本子;" }, { "id": "p5-09", "scene": "P5", - "text": "然后压缩才来,碎纸机开动,桌面上的细节开始褪色。" + "text": "然后压缩才来,碎纸机开动,细节褪色。本子里那句话,再不进碎纸机。" }, { "id": "p5-10", "scene": "P5", - "text": "先抢救,再碎纸。本子里的那句话,从此再也不进碎纸机。" + "text": "先抢救,再碎纸。" }, { "id": "p5-11", @@ -612,32 +612,32 @@ { "id": "p5-12", "scene": "P5", - "text": "有人分析过,它的实现里这个整理有个正式名字,起得很有画面感:做梦。" + "text": "有人分析过,它这个整理还有个正式名字,起得很有画面感:做梦。" }, { "id": "p5-13", "scene": "P5", - "text": "这个梦有四道闸,一道不满足就不做。" + "text": "四道闸,一道不过就不做。" }, { "id": "p5-14", "scene": "P5", - "text": "距上次整理不满一天,不做——好记性不差这一天;" + "text": "距上次整理不满一天,不做。好记性不差这一天。" }, { "id": "p5-15", "scene": "P5", - "text": "扫描太频繁,不做——翻文件夹本身也有成本;" + "text": "扫描太频繁,不做。翻文件夹本身也是有成本的。" }, { "id": "p5-16", "scene": "P5", - "text": "这中间攒的会话记录不够数,不做——素材太少不值得动笔;" + "text": "这中间攒的会话记录不够数,不做。素材太少,不值得动笔。" }, { "id": "p5-17", "scene": "P5", - "text": "有别的进程正在整理、锁被占着,不做——两个梦会打架。" + "text": "有别的进程正在整理、锁被占着,不做。两个梦会打架。" }, { "id": "p5-18", @@ -647,7 +647,7 @@ { "id": "p5-19", "scene": "P5", - "text": "锁文件上次被碰的时间,就是「上次做梦的时间」;" + "text": "锁文件上一次被碰的时间,就是上次做梦的时间;" }, { "id": "p5-20", @@ -662,7 +662,7 @@ { "id": "p5-22", "scene": "P5", - "text": "一天最多梦一次。有些事,就该趁夜深人静做——比如整理自己是谁。" + "text": "一天最多梦一次。有些事,就该趁夜深人静做。比如整理自己是谁。" }, { "id": "p6-07", @@ -682,22 +682,22 @@ { "id": "p6-02", "scene": "P6", - "text": "它不是记性好,是有两套东西在替它记。" + "text": "它其实不是记性好。" }, { "id": "p6-03", "scene": "P6", - "text": "一套负责体面地忘:分级收拾、先存再丢、压完往回捞;" + "text": "是有两套东西在替它记。一套负责体面地忘:分级收拾、先存再丢、压完回捞;" }, { "id": "p6-04", "scene": "P6", - "text": "一套负责固执地记:一事一文件、索引常驻、先抢救再碎纸。" + "text": "一套负责固执地记:一事一文件、索引常驻、先抢救再碎纸。再往前想一步。" }, { "id": "p6-04a", "scene": "P6", - "text": "再往前想一步:记忆这一层,押的赌注就是它记不住。" + "text": "赌注是:它记不住。" }, { "id": "p6-04b", @@ -707,26 +707,26 @@ { "id": "p6-04c", "scene": "P6", - "text": "手写的规则清单,正在让位给它自己长的记忆。" + "text": "手写的规则清单,正在让位给它自己长出来的记忆。" }, { "id": "p6-05", "scene": "P6", - "text": "官方还有一句话值得放在最后:这两条腿,都是上下文,不是闸门。" + "text": "官方还有一句话,值得放在最后:这两条腿,都是上下文,不是闸门。" }, { "id": "p6-06", "scene": "P6", - "text": "记忆是建议,钩子才是规则——写提示词和做 Harness 的分水岭。" + "text": "记忆是建议,钩子才是规则。写提示词和做 Harness,分水岭就在这。" }, { "id": "p6-09", "scene": "P6", - "text": "下次它又忘了你的偏好,你知道去哪找——不是它的脑子,是那个文件夹。" + "text": "下次它又忘了你的偏好,你知道去哪找。不是它的脑子,是那个文件夹。" }, { "id": "p6-10", "scene": "P6", - "text": "下期往前推一步:它干活时没有钟——按下开始的那只手,是谁的?下期见。" + "text": "下期往前推一步:它干活时没有钟。按下开始的那只手,是谁的?下期见。" } ] diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md index 61b87f82..84d248fe 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/script/narration.md @@ -13,48 +13,48 @@ > 画面:系列终端。读文件、跑命令的输出一条条堆进对话;窗口进度条涨满、撞上「拒收」墙。 > 角标:Context Compact · "Context Will Fill Up" -- [p0-01] 它正在干活,突然,停了。一个小时的活,一行报错,全部作废。 -- [p0-02] 不是它不想干,是服务那边拒收了——理由直白:你随身带的,太大了。 -- [p0-04] 它没有记性:读过的每个文件、跑过的每条命令、你说的每句话,全带着—— +- [p0-01] 它干得好好的,突然停了。一个小时的活,一行报错,全白干。 +- [p0-02] 不是它不想干,是服务那边拒收了。理由很直白:你随身带的,太大了。 +- [p0-04] 它压根没有记性。读过的每个文件、跑过的每条命令、你说的每句话,全带着。 - [p0-05] 每问一次模型,就从第一个字重新看一遍。窗口就这样一层层被垫高。 -- [p0-05a] 而且开局就不空——你还没敲第一个字,窗口里已躺着好几样东西。 -- [p0-05b] 官方文档给过一份示意账:光基本设定,就占四千多字。 -- [p0-06] 垫到顶,就是开头那行报错。 -- [p0-09] 官方工程博客还补了一刀:窗口越长,它记得反而越不准。 -- [p0-09a] 原因不玄:每多一个字,要照顾的两两关系就多一圈。 -- [p0-09b] 而注意力的总量是固定的——摊得越薄,看得越糊。 -- [p0-09c] 所以窗口再大,也不等于记性变好——能装,不等于能记。 +- [p0-05a] 而且开局就不空。你还没敲第一个字,窗口里已经躺着好几样东西了。 +- [p0-05b] 官方文档给过一份示意账:光是基本设定,就占掉四千多字。 +- [p0-06] 垫到顶,就是那行报错。 +- [p0-09] 官方的工程博客还补了一刀:窗口越长,它记得反而越不准。 +- [p0-09a] 原因不玄。每多一个字,要照顾的两两关系就多一圈。 +- [p0-09b] 可注意力的总量就那么多。摊得越薄,看得越糊。窗口再大也一样。 +- [p0-09c] 能装,不等于能记。 - [p0-10] 这事得有人管。官方给 Harness 列的四件事里,就有上下文管理。 -- [p0-11] 它分两半:安排它看什么,和装满了怎么办——今天拆后一半。 -- [p0-13] 后一半的答案分两层,对应两种完全不同的心态。 -- [p0-14] 第一层承认会丢:窗口一定会满,那就把丢管起来——分级、有序、有保底。 -- [p0-15] 第二层保证不丢:另立一个不参与压缩的账本,重要的写进去就不出来。 +- [p0-11] 它分两半:安排它看什么,和装满了怎么办。今天只拆后一半。 +- [p0-13] 而后一半的答案分两层,对应的是两种完全不同的心态。 +- [p0-14] 第一层承认会丢。窗口一定会满,那就把丢管起来:分级、有序、还有保底。 +- [p0-15] 第二层干脆保证不丢:另立一个不参与压缩的账本,写进去就不出来。 ## P1 桌面的收拾法 > 画面:一张会塞满的桌子(独立重立,不依赖任何前作)。四级收拾法的前两级依次演示。 > 角标:50 条 / 头 3 尾 47 · 最近 3 条完整保留 · 120 字阈值 -- [p1-01] 先把画面换个说法:它随身的全部对话,就是一张会塞满的桌子。 -- [p1-02] 第一层要办的,就是把丢管好——收拾这张桌子,最简的做法分四级。 -- [p1-03] 四级办法的原则只有一条:便宜的先来,贵的最后。 -- [p1-04] 先干不用花钱的,实在不行才请人。你会看到这条原则贯穿到底。 +- [p1-01] 先把画面换个说法。它随身带着的全部对话,就是一张会塞满的桌子。 +- [p1-02] 第一层要办的就是把丢管好。收拾这张桌子,最简单的版本分四级。 +- [p1-03] 原则只有一条:便宜的先来,贵的最后。 +- [p1-04] 先干不花钱的,实在不行才请人。这条原则会一路贯穿到底,你会看到。 - [p1-05] 第一级,裁中段。桌上的纸超过五十张,就只留开头三张和最近四十七张, - [p1-06] 中间那些全部裁掉,原地留一张字条:中间裁了多少张,想找去翻档案。 - [p1-07] 为什么偏偏留开头三张?因为那是任务书。 -- [p1-08] 你要它干什么的原始交代就在那几张里,丢了它就再也找不回初衷。 -- [p1-09] 为什么留最近的?因为手头的活都在最近几张纸上,正在用的不能动。 -- [p1-10] 中间的呢?大多是过气的中间过程——当时重要,现在回头看的概率很低。 -- [p1-11] 还有个讲究:不许把一张「请求」和它对应的「回执」拆开。 -- [p1-12] 请求还在、回执被裁走,桌上就留下一个永远等不到答案的问题。 -- [p1-13] 第二级,折旧纸。旧工具结果的完整内容,只保留最近三条, -- [p1-14] 更早的那些折成一行字:早前结果已收起,需要的话再跑一遍。 -- [p1-15] 反正真需要的时候,再让它跑一遍就是——纸可以折,活不用重干。 -- [p1-16] 注意折叠只动超过一百二十字的旧结果,短的就留着,不值得费这个事。 -- [p1-17] 这两级全是纯文本操作,一次模型都不用请,便宜到近乎免费。 +- [p1-08] 你要它干什么,原始交代就在那几张里。丢了,就再也找不回初衷。 +- [p1-09] 为什么留最近的?因为手头的活都在最近那几张纸上,正在用的不能动。 +- [p1-10] 中间的呢?大多是过气的中间过程。当时挺重要,现在几乎不会再翻。 +- [p1-11] 请求和回执,不许拆开。 +- [p1-12] 请求还在,回执被裁走了。桌上就留下一个永远等不到答案的问题。 +- [p1-13] 第二级,折旧纸。旧工具结果的完整内容,只留最近三条, +- [p1-14] 更早的那些折成一行字:早前结果已收起,真要用,再跑一遍就是。 +- [p1-15] 纸可以折,活不用重干。 +- [p1-16] 折叠只动超过一百二十字的旧结果。短的就留着,不值得费这个事。 +- [p1-17] 这两级全都是纯文本操作,一次模型都不用请,便宜到几乎免费。 - [p1-18] 官方文档的原话正好背书:先清掉旧的工具输出,不够再把整段对话摘要。 -- [p1-19] 这四级就是那两句的细化。便宜先来、贵的殿后,方向一致。 -- [p1-20] 记住这个次序感:先动最不心疼的,再动开始心疼的。这是这一层的节拍。 +- [p1-19] 这四级就是那两句话的细化。便宜先来,贵的殿后,方向完全一致。 +- [p1-20] 记住这个次序感:先动最不心疼的,再动开始心疼的。这就是这一层的节拍。 ## P2 大件入库与顺序论证 @@ -63,29 +63,29 @@ > 角标:200KB 阈值 · 预览 2000 字 · 转录保底 · 连败 3 次熔断 - [p2-01] 第三级,大件入库。有时候一条新结果本身就是个大块头。 -- [p2-02] 比如它一口气读了五个大文件,五份全文一起拍在桌上,一拍就是半个桌。 +- [p2-02] 比如它一口气读了五个大文件,五份全文一起拍上桌,一拍就是半张桌。 - [p2-03] 超过限额,就按个头从大到小排队,把最大的几个原样存进硬盘, - [p2-04] 桌上只留一张预览卡:开头两千字,外加一个「全文在库里」的标记。 -- [p2-05] 它看到标记就知道:全文在磁盘上躺着,真要用,再取就是。 -- [p2-06] 这一级还是不用请模型,只是搬东西——便宜,但能腾出最大的空间。 -- [p2-07] 第四级,全桌重写。三级都跑完桌子还是满的,就只能请人来写摘要了。 +- [p2-05] 它一看到标记就知道:全文还在磁盘上躺着,真要用,再取回来就是。 +- [p2-06] 这一级还是不用请模型,只是搬东西。便宜,但腾出来的空间最大。 +- [p2-07] 第四级,全桌重写。前三级跑完桌子还是满的,就只能请人来写摘要了。 - [p2-08] 重写之前先做一件事:把整段对话原样存档,一份不少。 -- [p2-09] 这是保底——摘要写砸了,原始记录还在,不至于两头空。 +- [p2-09] 这是保底。万一摘要写砸了,原始记录还在,不至于两头落空。 - [p2-10] 然后请模型把这一桌纸重写成一张:当前目标、重要发现、改过哪些文件、 -- [p2-11] 还剩什么活、你交代过什么约束。写完,整桌纸换成这一张。 -- [p2-12] 这是四级里唯一要花一次模型调用的,最贵,所以放最后。 -- [p2-13] 重写要是连着失败三次,熔断,不再试——别把预算烧在死循环上。 +- [p2-11] 还剩什么活、你交代过什么约束。写完,整桌纸就换成这一张。 +- [p2-12] 这是四级里唯一要花掉一次模型调用的,最贵,所以放在最后。 +- [p2-13] 重写连砸三次就熔断。死循环不配烧预算。 - [p2-14] 四级之外还留了条抢救通道:拒收已经发生时,保住最近几张原纸, - [p2-15] 只把更早的部分换成摘要,重试一次,再不行就把错误往上交。 -- [p2-16] 现在说这一集最要紧的一个细节:这几级的顺序,是锁死的。 -- [p2-17] 入库必须在折叠之前。因为折叠会把旧的大块头换成一行字。 -- [p2-18] 顺序反了,等你想起来要存原文的时候,原文已经不在了—— +- [p2-16] 现在说这一集最要紧的一个细节。这几级的顺序,是锁死的。 +- [p2-17] 入库必须在折叠之前。 +- [p2-18] 因为折叠会把旧的大块头换成一行字。顺序反了,原文就已经不在了。 - [p2-19] 你把空气存进了档案室。 -- [p2-20] 我们在画面里把顺序对调一次给你看:折叠先行,大块头瞬间缩成一行, +- [p2-20] 画面里我们把顺序对调一次给你看。折叠先行,大块头瞬间缩成一行, - [p2-21] 入库的手伸过去,抓到的只有那行字。整桌证据,就这么没了。 -- [p2-22] 有人核对过源码,它的真实实现里也是入库在前。一个看似平常的先后, +- [p2-22] 有人读过它的源码,成型的这套也是入库在前。一个看似平常的先后, - [p2-23] 背后是「先保存、再丢弃」的正确性论证。顺序,也是设计。 -- [p2-24] 很多系统坏在这种地方:每一步都对,合起来的次序错了。 +- [p2-24] 很多系统就坏在这个地方:每一步都对,合起来的次序错了。 ## P3 应急通道与帮工纪律 @@ -93,22 +93,22 @@ > ★回捞钩:压缩后五个文件被捞回桌面。 > 角标:保 5 条 · 重试 1 次 · 「只写字」首尾各一遍 · 回捞 ≤5 文件 -- [p3-01] 回到四级收拾,里面还有两处值得单独说说。 -- [p3-02] 一处是写摘要这位帮工。它的纪律严得有点好笑。 -- [p3-03] 有人把真实实现里给它的指令原文抄了出来,开头第一句就是: +- [p3-01] 回到四级收拾。这里面还有两处值得单独说说。一处是写摘要这位帮工。 +- [p3-02] 它的纪律,严得有点好笑。 +- [p3-03] 有人把它真正用的那段指令原文抄了出来,开头第一句就是: - [p3-04] 这次只许写字,绝不许调用任何工具。结尾还要再叮嘱一遍。 -- [p3-05] 为什么叮嘱两遍?请来收拾桌子的,手上偏偏有搬东西的能力。 -- [p3-06] 真让它边收拾边调用工具,桌子越收越满,收拾就变成了新的堆积。 -- [p3-07] 它还必须先在草稿区理清思路,再誊出正式摘要。 -- [p3-08] 草稿写完就撕掉,不留在桌上——草稿是给它自己看的,不是给对话看的。 -- [p3-09] 另一处是压缩过后的存活名单,官方给过一张矩阵—— -- [p3-10] 系统提示绕行不变;规则和自动记忆从磁盘重新注入; -- [p3-11] 用过的技能正文重注入,但每份封顶五千、最旧的先丢。 +- [p3-05] 为什么叮嘱两遍?请来收拾桌子的,手上偏偏有搬东西的本事。 +- [p3-06] 真让它边收拾边调工具,桌子只会越收越满,收拾就变成了新的堆积。 +- [p3-07] 它还必须先在草稿区里理清思路,再誊写出正式的摘要。 +- [p3-08] 草稿写完就撕掉,不留在桌上。那是给它自己看的,不是给对话看的。 +- [p3-09] 另一处是压缩过后的存活名单,官方也给过一张矩阵。 +- [p3-10] 系统提示绕行不变。规则和自动记忆,从磁盘上重新读一遍。 +- [p3-11] 用过的技能正文也读回来,但每份封顶五千,最旧的先丢。 - [p3-12] 而且压缩结束,同一张矩阵还写着:把最近读过的文件捞回桌面, -- [p3-13] 最多五个、按重要性排队——丢,也是分层次的丢。 -- [p3-14] 这一步超出了最简实现的范围,是有人从源码里读出来的——所以听到这里, -- [p3-15] 请记住同一句提醒:这是他的源码分析,不是官方的说明书。 -- [p3-16] 到这里,第一层讲完了:会丢的东西,被管得相当讲究。 +- [p3-13] 最多五个,按重要性排队。丢,也是分层次的丢。 +- [p3-14] 这一步玩具版没做,是有人读源码读出来的。所以听到这里, +- [p3-15] 记住那句提醒:这是他的源码分析,不是官方的说明书。第一层就讲完了。 +- [p3-16] 会丢的,管得真讲究。 ## P4 不丢的那一层 @@ -116,41 +116,41 @@ > 桌旁立起一本登记簿(苔绿),索引贴常驻桌角。 > 角标:.memory/ · 三字段 frontmatter · 四类记忆 · 索引 200 行上限 -- [p4-01] 但是你发现没有——四级收拾、应急抢救、往回捞,全是「桌面上的事」。 -- [p4-02] 桌面上的东西再怎么管,都有一个共同命运:迟早被压掉。 -- [p4-03] 有个特别扎心的例子。你认真交代过:缩进用 tab,别用空格。 -- [p4-04] 这句话原封不动躺在对话里,一切都好。 +- [p4-01] 但是你发现没有?四级收拾、应急抢救、往回捞,全是桌面上的事。 +- [p4-02] 桌面上的东西再怎么管,都逃不掉一个共同命运:迟早被压掉。 +- [p4-03] 有个例子特别扎心。你认认真真交代过:缩进用 tab,别用空格。 +- [p4-04] 这句话原封不动地躺在对话里,一切都好。 - [p4-05] 几轮压缩之后,它被摘成了六个字:有代码风格偏好。 -- [p4-06] 摘要没有做错什么——摘要的天性就是丢细节,保主干。 -- [p4-07] 可有些细节,恰恰是主干。你的偏好就是你的偏好,缩不成一句概括。 -- [p4-08] 所以需要另一层:不参与压缩的两条腿。第一条你写——项目里那个文件夹。 -- [p4-08a] 这里要纠正一个流传很广的说法:里面的规则不是它的基本设定。 -- [p4-08b] 那是设定之后递进来的第一条普通消息——跟你说的话同一个身份。 +- [p4-06] 摘要没有做错什么。摘要的天性就是丢细节,保主干。 +- [p4-07] 可有些细节恰恰就是主干。你的偏好就是你的偏好,缩不成一句概括。 +- [p4-08] 所以得另起一层:不参与压缩的两条腿。第一条你写,项目里那个文件夹。 +- [p4-08a] 这里要纠正一个流传很广的说法:里面的规则,不是它的基本设定。 +- [p4-08b] 那是设定之后递进来的第一条普通消息。跟你说的话,同一个身份。 - [p4-08c] 官方原话:会读、会尽量照做,但不保证严格执行。 -- [p4-08d] 所以「写了它没听」不是故障——这层本来就只是建议。 -- [p4-09] 这些文件层层拼接,越靠近工作目录的越后读,超两百行就开始不老实。 -- [p4-10] 一件事一个文件,开头三行登记:叫什么、一句话说明、属于哪类。 +- [p4-08d] 所以「写了它没听」不是故障。这一层本来就只是建议。 +- [p4-09] 这些文件层层拼接,越靠近工作目录的越后读。超过两百行就开始不老实。 +- [p4-10] 一件事一个文件,开头三行登记:叫什么、一句话说明、属于哪一类。 - [p4-11] 第二条腿它自己写:自动记忆按四类落在你的用户目录下,有门限。 -- [p4-12] 而且记过的不再记——这条防的是本子自己长胖。 -- [p4-13] 四类记忆,其实就是四个问题。 -- [p4-14] 你是谁——偏好和习惯,「缩进用 tab」就记在这类; -- [p4-15] 怎么干活——反馈和规矩,「别造假数据」; -- [p4-16] 在发生什么——项目背景,「这次重写是合规驱动的」; -- [p4-17] 去哪儿找——线索和入口,「那个老 bug 记录在哪」。 -- [p4-18] 四类之外还有一份索引:它垫在你开口之前,每次开工先扫一眼。 -- [p4-19] 索引也有上限:最多两百行,超了就要整理。家底要薄,才有用。 -- [p4-20] 取的时候分两条路。索引常驻是第一条,便宜、全天候。 -- [p4-21] 第二条是按需取:每轮开始前,把最近对话和记忆清单发给一个小模型, -- [p4-22] 请它挑真正用得上的,最多五条;拿不准就不挑,宁缺毋滥。 -- [p4-23] 挑错了比没挑更糟——一条不相干的记忆,就是一句错误的自我介绍。 -- [p4-24] 还有个经济学尾巴:前缀缓存按字数打折,但前缀必须一字不差—— +- [p4-12] 而且记过的不再记。这条防的是本子自己长胖。 +- [p4-13] 四类,其实就是四个问题。 +- [p4-14] 你是谁?偏好和习惯,「缩进用 tab」就记在这一类; +- [p4-15] 怎么干活?反馈和规矩,比如「别造假数据」; +- [p4-16] 在发生什么?项目背景,「这次重写是合规驱动的」; +- [p4-17] 去哪儿找?线索和入口,「那个老 bug 记录在哪」。 +- [p4-18] 四类之外还有一份索引。它垫在你开口之前,每次开工先扫一眼。 +- [p4-19] 索引也有上限:最多两百行,超了就得整理。家底要薄,才有用。 +- [p4-20] 取的时候分两条路。索引常驻是第一条,便宜,而且全天候。 +- [p4-21] 第二条是按需取:每轮开始之前,把最近对话和记忆清单发给一个小模型, +- [p4-22] 请它挑真正用得上的,最多五条。拿不准就不挑,宁缺毋滥。 +- [p4-23] 挑错了比没挑更糟。一条不相干的记忆,就是一句错误的自我介绍。 +- [p4-24] 还有个经济学尾巴:前缀缓存按字数打折,但前缀必须一字不差。 - [p4-25] 所以改了规则文件要新开会话才生效;中途换模型,那一轮特别慢。 -- [p4-25a] 这张卡的价目官方也挂着:命中的一折计费,写入加四分之一—— +- [p4-25a] 这张卡的价目官方也挂着:命中的一折计费,写入加四分之一。 - [p4-25b] 两次一问就回本。稳定放前面、多变放后面,就是在给钱排座位。 -- [p4-26] 挑记忆这活,就是一个普通的小号模型在干——不用向量检索,反而可靠。 -- [p4-27] 挑出来的内容不进基本设定,临时贴进这一轮—— -- [p4-28] 用完就过气。取记忆,也是一次性的。 -- [p4-29] 一层永久的存,一次临时的取——这个组合,才让不丢变得便宜。 +- [p4-26] 挑记忆这个活,就是个普通的小模型在干。不用向量检索,反而可靠。 +- [p4-27] 挑出来的内容不进基本设定,只是临时贴进这一轮。 +- [p4-28] 用完就过气了。 +- [p4-29] 取记忆也是一次性的。一层永久的存,一次临时的取,不丢才变得便宜。 ## P5 先抢救,再碎纸 @@ -158,28 +158,28 @@ > 快照里把「tab 那句话」抢进登记簿(keep 色)。随后「做梦」四道闸。 > 角标:停机钩子触发 · 压缩前快照 · Dream 四闸(24h / 节流 / 5 会话 / 文件锁·1h 过期) -- [p5-01] 现在到了两套机制咬合的那一瞬间,也是这一集的题眼。 -- [p5-02] 写入登记簿这件事,发生在每一轮结束的时候——对话告一段落,活干完了。 -- [p5-03] 关键在于取材的时机:提取器看的,是压缩之前的那份完整对话。 +- [p5-01] 现在到了两套机制咬合的那一瞬间,这也正是这一集的题眼。 +- [p5-02] 写进登记簿这件事,发生在每一轮结束的时候。对话告一段落,活干完了。 +- [p5-03] 关键在取材的时机。提取器看的,是压缩之前那份完整的对话。 - [p5-04] 也就是说,那张「用 tab」的字条在被摘掉之前,就先被抄走了。 -- [p5-05] 有人拆过它的源码——它的实现里由一个「停机钩子」触发这件事: -- [p5-06] 派出去的提取器权限受限、最多五回合、干完不进对话,闷头干完就走。 -- [p5-07] 把时间线摆在一起看,就明白这个先后有多讲究。 -- [p5-08] 轮末:先从完整对话里抢救出值得记的,一个字不差地写进本子; -- [p5-09] 然后压缩才来,碎纸机开动,桌面上的细节开始褪色。 -- [p5-10] 先抢救,再碎纸。本子里的那句话,从此再也不进碎纸机。 +- [p5-05] 有人拆过它的源码。真做的时候,是一个「停机钩子」在触发这件事: +- [p5-06] 派出去的提取器权限受限、最多五回合、结果不进对话,闷头干完就走。 +- [p5-07] 把两条时间线摆在一起看,这个先后有多讲究就清楚了。 +- [p5-08] 轮末:先从完整对话里抢救出值得记的,一字不差地写进本子; +- [p5-09] 然后压缩才来,碎纸机开动,细节褪色。本子里那句话,再不进碎纸机。 +- [p5-10] 先抢救,再碎纸。 - [p5-11] 但本子会越攒越厚:同一件事记了三遍、过时的没淘汰,就得整理。 -- [p5-12] 有人分析过,它的实现里这个整理有个正式名字,起得很有画面感:做梦。 -- [p5-13] 这个梦有四道闸,一道不满足就不做。 -- [p5-14] 距上次整理不满一天,不做——好记性不差这一天; -- [p5-15] 扫描太频繁,不做——翻文件夹本身也有成本; -- [p5-16] 这中间攒的会话记录不够数,不做——素材太少不值得动笔; -- [p5-17] 有别的进程正在整理、锁被占着,不做——两个梦会打架。 +- [p5-12] 有人分析过,它这个整理还有个正式名字,起得很有画面感:做梦。 +- [p5-13] 四道闸,一道不过就不做。 +- [p5-14] 距上次整理不满一天,不做。好记性不差这一天。 +- [p5-15] 扫描太频繁,不做。翻文件夹本身也是有成本的。 +- [p5-16] 这中间攒的会话记录不够数,不做。素材太少,不值得动笔。 +- [p5-17] 有别的进程正在整理、锁被占着,不做。两个梦会打架。 - [p5-18] 整理就是去重、合并矛盾、淘汰过时。而那把锁本身还是个时钟: -- [p5-19] 锁文件上次被碰的时间,就是「上次做梦的时间」; +- [p5-19] 锁文件上一次被碰的时间,就是上次做梦的时间; - [p5-20] 万一整理到一半崩了,一小时后锁自动过期,不会死锁。 - [p5-21] 四道闸全过,梦才开工:去重、合并、淘汰,然后把索引页重写一遍。 -- [p5-22] 一天最多梦一次。有些事,就该趁夜深人静做——比如整理自己是谁。 +- [p5-22] 一天最多梦一次。有些事,就该趁夜深人静做。比如整理自己是谁。 ## P6 落点与信源 @@ -188,13 +188,13 @@ - [p6-07] 本片以官方文档为主,取数2026年8月,以官方最新表述为准。 - [p6-08] 涉及内部实现的部分,为第三方源码分析,片中已逐处标注。 - [p6-01] 会丢的放桌面,不许丢的放本子。 -- [p6-02] 它不是记性好,是有两套东西在替它记。 -- [p6-03] 一套负责体面地忘:分级收拾、先存再丢、压完往回捞; -- [p6-04] 一套负责固执地记:一事一文件、索引常驻、先抢救再碎纸。 -- [p6-04a] 再往前想一步:记忆这一层,押的赌注就是它记不住。 +- [p6-02] 它其实不是记性好。 +- [p6-03] 是有两套东西在替它记。一套负责体面地忘:分级收拾、先存再丢、压完回捞; +- [p6-04] 一套负责固执地记:一事一文件、索引常驻、先抢救再碎纸。再往前想一步。 +- [p6-04a] 赌注是:它记不住。 - [p6-04b] 而赌注会过期。官方战报:新一代模型上,基本设定删了八成,评测没掉分。 -- [p6-04c] 手写的规则清单,正在让位给它自己长的记忆。 -- [p6-05] 官方还有一句话值得放在最后:这两条腿,都是上下文,不是闸门。 -- [p6-06] 记忆是建议,钩子才是规则——写提示词和做 Harness 的分水岭。 -- [p6-09] 下次它又忘了你的偏好,你知道去哪找——不是它的脑子,是那个文件夹。 -- [p6-10] 下期往前推一步:它干活时没有钟——按下开始的那只手,是谁的?下期见。 +- [p6-04c] 手写的规则清单,正在让位给它自己长出来的记忆。 +- [p6-05] 官方还有一句话,值得放在最后:这两条腿,都是上下文,不是闸门。 +- [p6-06] 记忆是建议,钩子才是规则。写提示词和做 Harness,分水岭就在这。 +- [p6-09] 下次它又忘了你的偏好,你知道去哪找。不是它的脑子,是那个文件夹。 +- [p6-10] 下期往前推一步:它干活时没有钟。按下开始的那只手,是谁的?下期见。 diff --git a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx index f16536f8..68da4db5 100644 --- a/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx +++ b/apps/negentropy-influence/episodes/claude-code-memory-video/video/src/scenes/P0Reject.tsx @@ -568,6 +568,12 @@ const TwoAnswers: React.FC<{leftAt: number; rightAt: number; lineAt: number}> = }) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); + // 开场引导:p0-13「答案分两层」先亮一道中缝预备线,避免首锚 leftAt 前约 5 秒 + // 主体全空(v5 回归实拍:f2105–2256 仅余抬头带与字幕——「死空气」缺陷)。 + const prep = interpolate(frame, [8, 26], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); const eL = spring({frame: frame - leftAt, fps, config: {damping: 200}}); const eR = spring({frame: frame - rightAt, fps, config: {damping: 200}}); const line = interpolate(frame - lineAt, [0, 20], [0, 1], { @@ -578,6 +584,19 @@ const TwoAnswers: React.FC<{leftAt: number; rightAt: number; lineAt: number}> = return (
+ {/* 中缝预备线:beat 开场先给一条暗分隔,预告「这里将分成两半」; + lineAt 后被正式生长线接替(同一位置,色加深) */} +
{/* 左:桌面(会丢的那层)——桌上纸卡,其中几张褪色 */}
))}
- {/* 层位纠正插段:顶部「基本设定」框 + 横杆 + 通道(p4-08a..b) */} + {/* 层位纠正插段:顶部「基本设定」框 + 横杆 + 通道(p4-08a..b)。 + top 96→150:原 96 时通道体 y≈113–129 正压 SceneHeader 幕内进度条(y≈124–125, + x 72–1847 满宽),文字与轨/游标双重叠印约 44s(实测帧 14358–15682)—— + 与 SceneHeader「高度锁死 ≤96px、不侵占镜内主体区」纪律冲突。整体下移 54px + 后框顶 150 仍在画面上三分之一,语义层级(「基本设定」在顶)不变。 */} {frame >= ghostAt ? ( -
+
{/* 基本设定框(规则卡飞向它,但从不属于它) */}
画面拉开——「一个它」的环孤零零悬着,四周是盖不住的模块群。 > 角标:Agent Teams · "One Agent isn't enough" -- [p0-01] 你交给它一桩大活:翻新整个后端,四个模块全都要动。 -- [p0-02] 它开头干得不错——可修到接口时,认证那块的细节,已经不在它的视野里了。 -- [p0-03] 官方给这种单干的慢性病,起了三个名字。 -- [p0-03a] 干一半就宣布完成、偏爱自己的产出、目标越走越散。 -- [p0-04] 就像一个工人盖不了整栋楼。要赶工期,得来一队人。 -- [p0-05] 于是问题来了:从一个它到一群它,中间隔着四道必答题—— +- [p0-01] 你交给它一桩大活:翻新整个后端,四个模块,全都要动。 +- [p0-02] 它开头干得挺好。可修到接口那会儿,认证那块的细节,早就飘出它的视野了。 +- [p0-03] 官方给这病起了三个名字。 +- [p0-03a] 干一半就说完事了,偏爱自己写的东西,目标越走越散。 +- [p0-04] 一个工人盖不了整栋楼。 +- [p0-05] 要赶工期,就得来一队人。从一个它到一群它,中间隔着四道必答题。 - [p0-06] 活挂在哪里?话从哪里走?怎么谈判?谁的桌子谁收拾? -- [p0-07] 这一集就把这四个问题一个个拆开。答案都很朴素,朴素到你会怀疑: -- [p0-08] 就这?对,就这。一堆文件、几个信箱、一张编号表,拼起来就是团队。 -- [p0-09] 每一样都埋着教训换来的「不」字——不许插队、不许转包、不许悄悄丢东西。 -- [p0-10] 拆到最后,还有一个更大的问题等着:这一摊子的计划,到底攥在谁手里。 +- [p0-07] 这回就把这四个问题一个个拆开。答案都朴素得离谱,朴素到你会怀疑: +- [p0-08] 就这?对,就这。一堆文件、几个信箱、一张编号表,拼起来就是一支团队。 +- [p0-09] 每一样都埋着教训换来的「不」字。不许插队,不许转包,不许悄悄丢东西。 +- [p0-10] 拆到最后还有个更大的问题等着:这一摊子的计划,到底攥在谁手里。 ## P1 活挂在哪里:看板 @@ -32,24 +32,24 @@ > 角标:task.json 五字段 · blockedBy · 完成即解锁 - [p1-01] 第一个问题:活挂在哪里? -- [p1-02] 最直觉的答案是列清单。但清单在脑子里、在对话里,人一多就乱了。 -- [p1-03] 答案是一块看板:每个任务是一个小文件,写清楚五样东西—— +- [p1-02] 最直觉的答案是列清单。可清单在脑子里,在对话里,人一多就乱套了。 +- [p1-03] 答案是一块看板。每个任务就是一个小文件,上面写清五样东西。 - [p1-04] 编号、标题、状态、主人、还有它等谁完工。 - [p1-05] 「等谁完工」这格最关键。任务之间有先后:接口要等数据库,测试要等接口。 -- [p1-06] 盖房子不能先盖屋顶再打地基——这句话,就是看板存在的理由。 -- [p1-07] 于是任务连成一张图。谁先谁后不用人排:前面的完成了,后面的自动解锁。 -- [p1-08] 做完「建表」,「接口」和「文档」同时可以领了——排序是图自己算出来的。 -- [p1-09] 还有个特别诚实的设计:你引用了一个不存在的任务当依赖,它不报错、不崩, +- [p1-06] 盖房子不能先盖屋顶再打地基。这句话就是看板存在的理由。 +- [p1-07] 于是任务连成一张图。谁先谁后不用人排,前面的完事,后面的自动解锁。 +- [p1-08] 做完「建表」,「接口」和「文档」立刻就能领。排序是图自己算出来的。 +- [p1-09] 还有个设计特别诚实。你把一个不存在的任务写成依赖,它不报错,也不崩, - [p1-10] 就是把你挡住。宁可挡着你,也不让一个笔误炸掉整块看板。 -- [p1-13] 谁来认领也有规矩。官方文档写得直白:任务认领用文件锁防竞态—— -- [p1-14] 先看一眼没人抢、再落笔写主人,两步并成一步,中间插不进第二只手。 +- [p1-13] 谁来认领也有规矩。官方文档写得直白,任务认领用文件锁防竞态。 +- [p1-14] 先看一眼没人抢,再落笔写主人。两步并一步,中间插不进第二只手。 - [p1-15] 编号也有讲究:一个只增不减的计数器,用过的号绝不复用。 -- [p1-16] 看板立好了。谁来看?都可以——它就是硬盘上的一堆文件,能读就能看。 -- [p1-17] 这里有个容易忽略的分别,值得多说一句:清单和看板是两样东西。 +- [p1-16] 看板立好了。谁来看?谁都能看。硬盘上的一堆文件,能读就能看。 +- [p1-17] 这里有个分别容易漏掉,值得多说一句。清单和看板是两样东西。 - [p1-18] 清单给自己看:我今天干哪几步;看板给所有人看:这摊活到哪了。 - [p1-19] 一个管执行的顺序,一个管协作的进度。两套并存,各干各的。 -- [p1-20] 为什么看板非要落成文件?因为一起干活有个前提: -- [p1-21] 一群它干活时,谁都别指望谁脑子里的清单——硬盘上的东西才人人可见。 +- [p1-20] 看板为什么非得落成文件? +- [p1-21] 因为一群它干活,谁也别指望谁脑子里那份清单。硬盘上的东西才人人可见。 ## P2 话从哪里走:信箱 @@ -58,31 +58,31 @@ > 角标:mailbox.jsonl · 读一条划掉一条 · 权限冒泡 - [p2-01] 第二个问题:话从哪里走? -- [p2-02] 先说清「队友」是什么。有一种帮手是临时工:叫来干一件事,交完总结就走。 +- [p2-02] 先说清「队友」是什么。有一种帮手是临时工,叫来干一件事,交完总结就走。 - [p2-03] 队友不是。队友是长期工:有自己的名字、自己的活、自己的节奏。 - [p2-04] 临时工只需要一条回话的路;队友需要一个能随时说话的地方。 -- [p2-05] 这个地方朴素得惊人:一个文件。每个人门口一个信箱文件, -- [p2-06] 发消息就是往对方文件里加一行;读消息就是打开文件看一眼,然后删掉。 +- [p2-05] 这个地方朴素得惊人:就是一个文件。每人门口挂一个信箱文件, +- [p2-06] 发消息就是往对方文件里加一行。读消息就是打开看一眼,然后划掉。 - [p2-07] 读一条,划掉一条。没有已读回执,没有撤回,就是一行一行的账。 - [p2-08] 为什么敢用这么土的设计?因为文件这东西,人人都会读,个个看得懂。 -- [p2-09] 排查问题的时候,你打开信箱文件看两眼,比任何调试面板都直接。 -- [p2-10] 这也呼应了一个原则:能落在明面上的状态,就不要藏在运行过程里。 -- [p2-11] 文件是给人和它共同看的地方——协作系统做到这一步,才算真的透明。 -- [p2-12] 领队也守这规矩。队友干完活,把总结投进领队的信箱; +- [p2-09] 排查问题的时候,打开信箱文件看两眼,比任何调试面板都直接。 +- [p2-10] 这也呼应一条原则。能摆到明面上的状态,就别藏在运行过程里。 +- [p2-11] 文件是人和它共看的地方。协作系统做到这一步,才算真透明。 +- [p2-12] 领队也守这规矩。队友干完活,把总结投进领队的信箱。 - [p2-13] 领队隔一阵收一次信,把信里的内容贴进自己的对话,接着指挥。 -- [p2-14] 官方口径也证实了:信箱真的就是用户目录下的一个文件, +- [p2-14] 官方口径也证实了。信箱真就是用户目录下的一个文件, - [p2-15] 只不过写文件加了一把锁,防止两个队友同时投信把信写串了。 -- [p2-18] 最妙的是权限。队友要干一件需要审批的事,弹窗不在它自己的屏幕上—— +- [p2-18] 最妙的是权限。队友要干一件需要审批的事,弹窗不在它自己屏幕上。 - [p2-19] 请求冒泡,一路浮到领队的屏幕,弹出来,还是你来点头。 -- [p2-20] 组了队,不代表权限放松了——官方立了三道禁令:队友的消息, +- [p2-20] 组了队,不代表权限就松了。官方立了三道禁令。队友的消息, - [p2-21] 不能替你批权限、不能代你同意、被拒的动作不能转给另一个队友。 -- [p2-22] 组队不是权限洗白机。孩子们的签字栏,还在家长的原处。 -- [p2-23] 还有一条铁律:队友不许再孵队友——审批卡冒十层泡,就找不到责任人了。 +- [p2-22] 组队不是权限洗白机。 +- [p2-23] 签字栏还在家长手里。队友也不许再孵队友,冒十层泡就找不到责任人了。 - [p2-23a] 团队本身也落成文件:一个名册放在用户目录的团队文件夹里,写着谁在队、 -- [p2-23b] 每人一只信箱。会话一结束,名册自动清掉——队伍是临时的,桌子是留下的。 -- [p2-24a] 再补个细节:消息就是一段文字——想把整段上下文搬过去,得恢复会话, +- [p2-23b] 每人一只信箱。会话一散,名册自动清掉。队伍是临时的,桌子是留下的。 +- [p2-24a] 再补个细节。消息就是一段文字。想把整段上下文搬过去,得恢复会话, - [p2-24b] 而不是塞进信箱。信箱管传话,不管搬桌子。 -- [p2-25] 你回头看会发现:这些约定防的都是「没人负责」这四个字。 +- [p2-25] 你回头看会发现,这些约定防的都是「没人负责」这四个字。 ## P3 怎么谈判:握手 @@ -91,19 +91,19 @@ > 角标:request_id 贯穿全链 · pending → approved/rejected · 三重对号 - [p3-01] 第三个问题:怎么谈判? -- [p3-02] 谈判先从一个具体的麻烦说起:活干完了,怎么让一个队友下工? -- [p3-03] 最粗暴的做法是直接掐掉它的线程。但掐的瞬间,它可能正把文件写到一半—— -- [p3-04] 磁盘上留下一个半拉子文件,谁也说不清那算谁的。 -- [p3-05] 所以告别也要握手。领队发关机请求,队友收干净手头的活,回一张同意。 -- [p3-06] 这套握手有个精巧处:请求和回复带同一个编号,隔着信箱也对得上。 -- [p3-07] 还要三重对号——编号、类型、这事没办过,全过才销账。 -- [p3-10] 同一套机制换个方向就是审批:队友要动高风险的东西,先交一份计划等批。 -- [p3-11] 计划递上去等着,回复带同一个编号回来,批了才动手。 -- [p3-12] 有人拆过它的源码——实际实现里的关机更讲究,是三向的: -- [p3-13] 请求、同意或拒绝,拒绝还能附上理由——最后系统广播一声「人已离场」, -- [p3-14] 顺带把它的窗格、任务、名册统统收拾干净。 -- [p3-15] 所谓协议,没有玄机:一张状态表、一个编号、几条对得上号的规矩。 -- [p3-16] 最简实现只演了消息怎么走;产品的门禁是真的——批文没到,工具出不了手。 +- [p3-02] 先从一个具体的麻烦说起。活干完了,怎么才能让一个队友下工? +- [p3-03] 最粗暴的是掐掉它的线程。可掐那一瞬它正写文件呢,磁盘上就留下个残件。 +- [p3-04] 可谁也说不清那算谁的。 +- [p3-05] 所以告别也得握手。领队发一张关机请求,队友收干净手头的活,回一张同意。 +- [p3-06] 精巧处全在一个编号上。请求和回复带同一个号,隔着信箱也对得上。 +- [p3-07] 还要三重对号:编号对吗?类型对吗?这事没办过吧?全过才销账。 +- [p3-10] 同一套机制换个方向,就是审批。队友要动高风险的东西,先交一份计划等批。 +- [p3-11] 计划递上去等着,回复带着同一个编号回来,批了才动手。 +- [p3-12] 有人读源码,读出来的:真的那套关机更讲究,是三向的。 +- [p3-13] 请求、同意或者拒绝,拒绝还能附上理由。最后系统广播一声「人已离场」, +- [p3-14] 顺带把它的窗格、任务、名册,统统收拾干净。 +- [p3-15] 所谓协议,其实没什么玄机。一张状态表,一个编号,几条对得上号的规矩。 +- [p3-16] 玩具版只演了消息怎么走。产品里的门禁是真的:批文没到,工具出不了手。 ## P4 自己看板,自己认领 @@ -111,29 +111,29 @@ > 60 秒表盘走满自动收工。 > 角标:WORK→IDLE→SHUTDOWN · 信箱优先看板其次 · 60s 超时(示教设计) -- [p4-01] 到这里你可能会想:每次派活还要领队挨个分?十个任务分十次? -- [p4-02] 它的作者们也这么想。所以队友学会了自己翻板、自己认领。 -- [p4-03] 队友的一生分三段:干活、歇着、走人。 -- [p4-04] 干完手头的活,不退出,进入歇着的状态。歇着时每五秒看两眼: -- [p4-05] 先看信箱——里面可能有关机请求,也可能有新指令,有信就先处理信。 -- [p4-06] 信箱空着,再翻看板:有依赖齐了、又没人认领的活吗?有就领,领了接着干。 -- [p4-07] 认领前照例三查:是待办吗?有主人吗?依赖齐了吗?任何一条不过,不硬来。 -- [p4-08] 这样领队只需要把任务挂上板,剩下的分发全自动。 -- [p4-09] 两个队友同时抢一个活怎么办?主人这一格先到先得,后到者查一眼就走。 -- [p4-10] 歇着也不是永远歇。最简的做法定死六十秒:等不来新活,收工走人。 -- [p4-11] 有人读过源码:实际实现没有固定时限,队友一直活着,等领队握手告别。 -- [p4-12] 最简实现还埋了个身份机关——歇着时对话压太短,就把「我是谁」插回去。 -- [p4-13] 干活得知道自己是谁。这句话对人对它都成立。 -- [p4-14] 再看一眼自治的样子:领队只做两件事——挂任务上板,需要时发告别握手。 +- [p4-01] 到这儿你可能会想:每次派活还得领队挨个分?十个任务分十次? +- [p4-02] 它的作者们也这么想。 +- [p4-03] 所以队友学会了自己翻板、自己认领。队友的一生分三段:干活、歇着、走人。 +- [p4-04] 干完手头的活,它不退出,转进歇着的状态。歇着的时候每五秒看两眼。 +- [p4-05] 先看信箱。里面可能有关机请求,也可能有新指令,有信就先处理信。 +- [p4-06] 信箱空着,再翻看板。有依赖齐了、又没人认领的活吗?有就领,领了接着干。 +- [p4-07] 认领前照例三查:是待办吗?有主人吗?依赖齐了吗?一条不过,就不硬来。 +- [p4-08] 这样领队只管把任务挂上板,剩下的分发全自动。 +- [p4-09] 两个队友同时抢一个活怎么办?主人这格先到先得,后到的查一眼就走。 +- [p4-10] 歇着也不是永远歇。玩具版定死六十秒,等不来新活,收工走人。 +- [p4-11] 有人读过源码:成型的这套没有固定时限,队友一直活着,等领队握手告别。 +- [p4-12] 玩具版还埋了个身份机关。歇着时对话压太短,就把「我是谁」补回去。 +- [p4-13] 干活得知道自己是谁。这话对人对它都成立。 +- [p4-14] 再看一眼自治的样子。领队只做两件事:挂任务上板,需要时发告别握手。 - [p4-15] 剩下的认领、开工、汇报、等待、再认领,全是队友自己的节奏。 -- [p4-16] 领队从包工头退成了项目经理。撑住这个转变的,就是那几样朴素的东西。 +- [p4-16] 领队从包工头退成了项目经理。撑住这转变的,就是那几样朴素东西。 - [p4-17] 官方自己拿这套打法,干过一票大的:让一群它,写一个编译器。 - [p4-18] 十六个它并行,各守一个容器;认领就是往一个文件里写一行占坑。 -- [p4-19] 没有总调度,没有领队——两周,约两千场会话,十万行代码。 +- [p4-19] 没有总调度,没有领队。两周,约两千场会话,十万行代码。 - [p4-20] 产出能编出一个可启动的内核,账单不到两万美元。 -- [p4-21] 但并行最难的不是分活,是所有人卡在同一个坑。 -- [p4-22] 一个报错,就能让十六个它一起停摆。 -- [p4-23] 解法很野:大部分文件先让现成的编译器过,只留一小撮给它。 +- [p4-21] 但并行最难的不是分活。 +- [p4-22] 是所有人卡在同一个坑里。一个报错,就能让十六个它一起停摆。 +- [p4-23] 解法很野。大部分文件先让现成的编译器过,只留一小撮给它。 - [p4-24] 剩下的再二分下去,分到最后谁也不挡谁。 ## P5 谁的桌子:各干各的 @@ -142,28 +142,28 @@ > ★脏桌抖动拒绝删除。末尾外接工具一句+标准插头角标。 > 角标:一任务一目录 · 绑定不改状态 · 脏桌不删 · mcp__服务__工具 前缀 -- [p5-01] 第四个问题,也是最容易出事的一个:谁的桌子? -- [p5-02] 前面三样都安排好了,队友们干得热火朝天——然后在同一个目录里打起架来。 +- [p5-01] 第四个问题:谁的桌子? +- [p5-02] 这也是最容易出事的一个。前三样都妥了,队友们干得热火朝天,然后打架了。 - [p5-03] 阿珍要改配置文件,阿强也要改同一个。阿珍刚写完,阿强一覆盖,白干。 -- [p5-04] 更糟的是回滚不干净:同一份文件混着两人的改动,分不出哪行是谁的。 -- [p5-05] 解法还是老实的:同一个仓库,各开各的桌子。 -- [p5-06] 每个任务可以绑一个独立的工作目录,各建各的分支。 -- [p5-07] 官方给这张桌子立了四道闸:指向主检出的编辑,拦; +- [p5-04] 更糟的是回滚不干净。同一份文件混着两人的改动,分不出哪行是谁的。 +- [p5-05] 解法还是那么老实。 +- [p5-06] 同一个仓库,各开各的桌子。每个任务绑一个独立的工作目录,各建各的分支。 +- [p5-07] 官方给这张桌子立了四道闸。指向主检出的编辑,拦。 - [p5-08] 命令的工作目录解析不对、确认不了的,拦;git 重定向的四种写法,拦; -- [p5-09] 命令形状没法静态验证的,拦——而且这道闸,不能关。 +- [p5-09] 命令形状没法静态验证的,拦。而且这道闸,关不掉。 - [p5-10] 领队可以提前备好任务和桌子;绑定只登记,不改任务状态,两不耽误。 -- [p5-11] 干完收尾,两个选择:留着——分支保留,等人审查合并;或者拆掉。 -- [p5-12] 但有个不讲情面的默认:桌上还有没提交的改动,拆桌子的请求直接被拒。 -- [p5-13] 这个「不讲情面」值得细品。机器最擅长的是无条件执行指令, -- [p5-14] 而这里恰恰反着来:删除按钮按下去,它先问「你确定真的不要这些了?」 -- [p5-15] 想拆?必须明说「丢弃改动」。宁可多签一次字,不悄悄丢掉任何工作。 +- [p5-11] 干完收尾有两个选择。留着,分支保留等人审查合并。或者拆掉。 +- [p5-12] 但有个默认不讲情面:桌上还有没提交的改动,拆桌子的请求直接被拒。 +- [p5-13] 这个「不讲情面」值得细品。机器最擅长的是无条件执行指令。 +- [p5-14] 可这里恰恰反着来。删除按钮按下去,它先问一句:你确定真不要这些了? +- [p5-15] 想拆?必须明说「丢弃改动」。宁可多签一次字,也不悄悄丢掉任何工作。 - [p5-16] 建桌、拆桌、留桌,每次都记一行日志。谁何时动过哪张桌,翻账就知道。 -- [p5-17] 一行日志看着轻,出了事它就是唯一的目击证人。 -- [p5-18] 官方还交代了个细节:进出目录是整个进程跟着切——一旦进桌, -- [p5-19] 它眼里的世界就是那张桌。任务与目录是否强制绑定,两种做法各有取舍。 -- [p5-20] 最后顺带一句:工具本身也可以是别人造的。有一套行业标准的接插协议, -- [p5-21] 外面的服务接上就变工具;名字自动带来源前缀,防的是两家重名。 -- [p5-22] 装十个服务,上下文几乎不占——工具的定义按需取用,不整包塞进来。 +- [p5-17] 一行日志看着轻。出了事,它就是唯一的目击证人。 +- [p5-18] 官方还交代个细节。进出目录是整个进程跟着切,一旦进桌, +- [p5-19] 它眼里的世界就是那张桌。任务与目录要不要强制绑定,两种做法各有取舍。 +- [p5-20] 最后顺带一句。工具本身也可以是别人造的:有一套行业标准的接插协议, +- [p5-21] 外面的服务接上就变工具。名字自动带来源前缀,防的是两家重名。 +- [p5-22] 装十个服务,上下文几乎不占。工具的定义按需取用,不整包塞进来。 ## P6 收束:机制很多,循环一个 @@ -171,26 +171,26 @@ > 每段亮起前几集机制的小图标;环在传送带正中恒转。 > 角标:"Many mechanisms, one loop" · 27 个内建工具(源码分析) -- [p6-01] 现在把这一集的四样东西摆回大图里:看板、信箱、握手、各自的桌子。 -- [p6-02] 再把全景画面请出来,一整轮快闪走一遍——十几样机制各就各位。 -- [p6-03] 你说一句话进料;通知排队汇入;桌面太满先收拾;状态拼成垫纸; -- [p6-04] 然后问模型。有活就过闸门、分发、执行、回填,再问下一轮。 -- [p6-05] 这幅图上你要找的东西只有一个:那个循环。机制很多,循环一个。 -- [p6-06] 变的从来不是它,是攥着它的那只手。 -- [p6-07] 而拆到最后,还有一个更大的问题:这一摊子的计划,攥在谁手里? -- [p6-08] 官方给了答案——第四种形态:让它当场把编排写成一段脚本。 -- [p6-09] 循环、分支、中间结果,住进脚本变量;它的上下文,只装最终答案。 -- [p6-10] 脚本落盘,可读、可比对、改完能重跑;并发最多十六,单次一千。 -- [p6-11] Harness 第一次,开始由它自己来写。 -- [p6-11a] 这种脚本能拼出好几种打法:一批活扇出去、各自干完再汇总成一份; -- [p6-11b] 或者干完先请另一个它挑刺,挑完再改——改到合格才算完。 -- [p6-11c] 中断也不慌:重新拉起时,干完的直接命中,没干完的从头再跑—— -- [p6-11d] 从第一个没干完的往后,启动过的全部重跑。规矩清楚,不碰运气。 -- [p6-12] 多出来的不是智慧,是把协作拆成了看得见的零件:板子、信箱、编号、桌子。 -- [p6-13] 官方工程博客泼的冷水也要听:并行和专精,必须挣回协调成本—— -- [p6-14] 他们算过账,多智能体的花销,大约是普通对话的十五倍。 +- [p6-01] 现在把这一集的四样东西摆回大图里:看板、信箱、握手,还有各自的桌子。 +- [p6-02] 再把全景画面请出来,一整轮快闪走一遍。十几样机制,全都各就各位。 +- [p6-03] 你说一句话进料。通知排队汇入。桌面太满就先收拾。状态拼成一张垫纸。 +- [p6-04] 然后去问模型。 +- [p6-05] 你要找的东西只有一个。 +- [p6-06] 那个循环。机制很多,循环只有一个。变的从来不是它,是攥着它的那只手。 +- [p6-07] 而拆到最后,还有个更大的问题。这一摊子的计划,到底攥在谁手里? +- [p6-08] 官方给了答案。第四种形态:让它当场把整套编排写成一段脚本。 +- [p6-09] 循环、分支、中间结果,全都住进脚本变量。它的上下文,只装最终答案。 +- [p6-10] 脚本落盘,可读,可比对,改完还能重跑。并发最多十六,单次一千。 +- [p6-11] 这是 Harness 第一次,开始由它自己来写。 +- [p6-11a] 这种脚本能拼出好几种打法。一批活扇出去,各自干完了再汇总成一份。 +- [p6-11b] 或者干完先请另一个它挑刺,挑完再改。一直改到合格才算完。 +- [p6-11c] 中断了也不慌。重新拉起的时候,干完的直接命中,没干完的从头再跑。 +- [p6-11d] 从第一个没干完的往后,凡是启动过的全部重跑。规矩清楚,不碰运气。 +- [p6-12] 多出来的不是智慧。 +- [p6-13] 是把协作拆成了看得见的零件:板子、信箱、编号、桌子。官方也泼过冷水: +- [p6-14] 并行和专精得挣回协调成本。他们算过账,多智能体的花销是十五倍上下。 - [p6-15] 本片机制依据官方文档,取数2026年8月,以官方最新表述为准。 -- [p6-16] 涉及产品内部的部分,为第三方源码分析,片中已逐处标注。 -- [p6-16a] 最后一句设计者的自省值得带走:常问自己,可以停掉哪一件。 -- [p6-16b] 每一样零件都押着一条「模型做不到」的赌注。模型变强,赌注就过期。 -- [p6-17] 下期再往上一层:怎么给这样的系统打分。分数会骗人,过程不会——下期见。 +- [p6-16] 涉及产品内部的那些部分,是第三方的源码分析,片中已逐处标注。 +- [p6-16a] 最后一句设计者的自省,值得你带走:常问问自己,可以停掉哪一件。 +- [p6-16b] 每样零件都押着一条「模型做不到」的赌注。模型一变强,赌注就过期。 +- [p6-17] 下期再往上一层:怎么给这样的系统打分。分数会骗人,过程不会。下期见。 diff --git a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx index d8280af2..54c47058 100644 --- a/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx +++ b/apps/negentropy-influence/episodes/claude-code-multiagent-video/video/src/scenes/P4Autonomy.tsx @@ -10,12 +10,17 @@ import type {SceneRange} from '../types'; import {Footnote, LoopRing, NamePlate, Panel, SceneHeader, phase} from '../components/motifs'; /** 4-A 派工之累 ×10 快闪 → 三段生命周期环描线登场 */ -const DispatchFatigue: React.FC<{cycleAt: number}> = ({cycleAt}) => { +const DispatchFatigue: React.FC<{cycleAt: number; montAt: number}> = ({cycleAt, montAt}) => { const frame = useCurrentFrame(); const {fps} = useVideoConfig(); - // 十次派工快闪:每 4 帧一张分发卡从领队飞向队友(p4-01「十个任务分十次」约 1.3s 的快蒙太奇) + // 十次派工快闪:每 4 帧一张分发卡从领队飞向队友(p4-01「十个任务分十次」约 1.3s 的快蒙太奇)。 + // 2026-08 v5 全片回归修:蒙太奇原从 beat 第 0 帧起跑(对齐句首「到这里你可能会想」), + // 而关键词「十个任务分十次」位于句内 ~72%(5.7s 句的第 ~4.1s)——卡全部飞完时这句话 + // 还没念到,随后 406.6-416.1 近 10s 只剩双环静置(f12210 像素坐实 ink<0.02)。 + // montAt 把快闪锚到句内 ~55%(帧 94),飞完 ~4.7s 恰好覆盖关键词段。 const per = 4; - const flashes = Math.min(10, Math.floor(frame / per) + 1); + const mf = frame - montAt; + const flashes = mf < 0 ? 0 : Math.min(10, Math.floor(mf / per) + 1); const showCycle = frame >= cycleAt; const draw = interpolate(frame - cycleAt, [0, 36], [0, 1], { extrapolateLeft: 'clamp', @@ -44,11 +49,11 @@ const DispatchFatigue: React.FC<{cycleAt: number}> = ({cycleAt}) => { {/* 分发卡 ×10:叠层快闪(每张停留一小段后飞走) */} {Array.from({length: 10}, (_, i) => { - const t = interpolate(frame - i * per, [0, 2, per + 3], [0, 1, 1], { + const t = interpolate(mf - i * per, [0, 2, per + 3], [0, 1, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); - const gone = interpolate(frame - i * per - per - 3, [0, 8], [0, 1], { + const gone = interpolate(mf - i * per - per - 3, [0, 8], [0, 1], { extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); @@ -101,7 +106,7 @@ const DispatchFatigue: React.FC<{cycleAt: number}> = ({cycleAt}) => { fontVariantNumeric: 'tabular-nums', }} > - {`派工 ×${flashes}`} + {flashes > 0 ? `派工 ×${flashes}` : '派工 ×…'}
) : ( @@ -1139,7 +1144,7 @@ export const P4Autonomy: React.FC<{scene: SceneRange}> = ({scene}) => { - + 画面:系列同款终端。任务进行中,最初的清单滚出可视区;走秒芯片持续跳动。 > 角标:TodoWrite · "An Agent Without a Plan Drifts Off Course" -- [p0-01] 你交给它一个大活,它干了三步,就忘了自己来干嘛。 -- [p0-02] 根源有点吓人:它每跑一轮,都把你们说过的话从头重读一遍——它没有昨天。 -- [p0-03] 这一集要拆的,是管它视野的五样装置。其中一样,刚刚被官方收回去。 -- [p0-04] 问题出在桌上:内容全平铺,谁新谁旧全凭距离,最初那张任务单被越挤越远。 -- [p0-05] 于是问题来了:它这一轮能看见什么,是它自己说了算吗? -- [p0-06] 答案:不是。有一整套装置,在替它安排视野。 -- [p0-07] 写下来的清单,另开的副桌,按需翻开的目录,每轮重拼的垫纸,还有补救梯。 +- [p0-01] 你交给它一个大活。它闷头干了三步,回头一看,忘了自己是来干嘛的。 +- [p0-02] 根源有点吓人。它每跑一轮,都把你们说过的话从头重读一遍。它没有昨天。 +- [p0-03] 今天要拆的是五样装置,管的全是它的视野。其中一样,刚被官方收回去了。 +- [p0-04] 问题出在桌上。内容全平铺,谁新谁旧全凭距离。最初那张任务单被越挤越远。 +- [p0-05] 它看见什么,它说了算吗? +- [p0-06] 不算。是有人替它安排的。 +- [p0-07] 钉住的清单,另开的副桌,按需翻的目录,每轮重拼的垫纸,还有一张补救梯。 - [p0-08] 官方把 Harness 定义成四件:循环、工具、上下文管理、护栏。 -- [p0-09] 今天讲的正是上下文管理的前半:它每一轮能看见什么。 +- [p0-09] 今天补的就是上下文管理的前半:这一轮,它到底能看见些什么东西。 ## P1 把清单钉在桌上 > 画面:一张亮面桌子成为主舞台(系列环在桌后)。清单卡「啪」地钉进桌面。 > 角标:`todo_write` · 三态 pending / in_progress / completed -- [p1-01] 第一样东西最不起眼:一张写下来的清单。 +- [p1-01] 第一样东西最不起眼,说白了就一张纸。一张自己写下来的清单。 - [p1-02] 干活之前,先把步骤一条条列出来,每条标一个状态:没开始、干着、干完了。 -- [p1-03] 状态只有这三种,不多不少。干一步挪一格,桌子上的进度看得见摸得着。 -- [p1-05] 而奇怪的地方就在这儿:这个工具本身,什么都不执行。 -- [p1-06] 它不能读文件,不能跑命令,唯一的功能就是把清单写下来、摆到它眼前。 -- [p1-07] 可正因为清单挂在对话里,每一轮重读的时候,它都会被再看见一次。 -- [p1-08] 你以为它忘了,其实是那张纸被几十条工具输出顶到了视野之外。 -- [p1-09] 把纸钉回眼前,注意力就回来了。就这么简单,也就这么管用。 -- [p1-10] 加这个工具要改几处代码?两处。注册表里添一行,分发表里挂一行。 -- [p1-11] 循环本身一行没动——这是我们这一集反复要数的事实。 -- [p1-12] 有位作者有句话说得很准:这个工具不增加任何执行能力, +- [p1-03] 状态就这三种,不多不少。干一步挪一格,桌子上的进度看得见摸得着。 +- [p1-05] 怪就怪在这儿了。这个工具本身,什么都不执行。 +- [p1-06] 它不能读文件,不能跑命令。它唯一干的那件事,就是把清单摆到自己眼前。 +- [p1-07] 可清单是挂在对话里的。每一轮从头重读的时候,它都会被再看见一次。 +- [p1-08] 你以为它忘了。其实是那张纸,被几十条工具输出顶到了视野之外。 +- [p1-09] 把那张纸钉回它眼前,注意力就回来了。就这么笨,也就这么管用。 +- [p1-10] 加这个工具,要改几处代码?两处。注册表里添一行,分发表里挂一行。 +- [p1-11] 循环本身,一行没动。 +- [p1-12] 有位作者的一句话说得特别准:这个工具不增加任何执行能力, - [p1-13] 它增加的,是规划能力。 -- [p1-14] 但这件装置刚刚被官方收了回去——新的模型上,清单工具默认不再安装。 +- [p1-14] 但这件装置刚刚被官方收了回去。新的模型上,清单工具默认不再安装。 - [p1-15] 理由说得很直白:这些模型自己就能记住要干什么。这一注,到期了。 -- [p1-15a] 那规划这件事就没了吗?没有,它升级成了一道门。 -- [p1-15b] 这道门叫计划模式:先只看不动手地探索,把计划写出来给你过目。 -- [p1-15c] 计划没批,改文件的动作一律拦住——它想动手,得先说服你。 -- [p1-15d] 批准那一下你有三个选择:交给自动闸门、逐条人工点头、或者再想想。 -- [p1-15e] 清单是写给它自己看的;计划,是写给你看的。 -- [p1-16] 清单背后那套带依赖、能锁、落盘的任务系统,以后单说。先记一句: +- [p1-15a] 那规划这件事就没了吗?没有。它升级成了一道门。 +- [p1-15b] 这道门叫计划模式。先只看不动手地探索,再把计划写出来给你过目。 +- [p1-15c] 计划没批,改文件的动作一律拦住。它想动手,得先说服你。 +- [p1-15d] 批准那一下你有三个选择:交给自动闸门、逐条人工点头,或者再想想。 +- [p1-15e] 清单是写给它自己看的。计划,是写给你看的。 +- [p1-16] 清单背后还藏着一整套任务系统:带依赖、能上锁、能落盘。这个以后单说。 - [p1-18] 把计划写下来,本身就是一种能力。而且是装在循环外面的能力。 -- [p1-19] 什么都不执行的工具,成了长活不跑偏的关键。这种反差,后面还会遇到几次。 +- [p1-19] 什么都不执行的工具,成了长活不跑偏的关键。这种反差,今天还有几次。 ## P2 另开一张副桌 > 画面:主桌右侧滑出一张小桌(自带缩小克隆环),脏活全摊在副桌上;干完只带回一张回执卡。 > 角标:`task` tool · 全新 messages[] · 只回传结论 -- [p2-01] 第二样,管的是另一种失控:活太脏,会把桌子整个占满。 -- [p2-02] 比如追一个缺陷,要读三十个文件、翻六十轮对话。 -- [p2-03] 等你找到问题在哪,桌上已经堆了一百多条记录,绝大部分是中间过程。 -- [p2-04] 这些纸每一轮都被重读一遍,跟目标无关,但一直占着位置、一直计着费。 -- [p2-05] 你遇到这种事会怎么办?开一个新终端去翻,翻完关掉,把结论记回本子上。 -- [p2-06] 它也一样:另开一张干净的副桌,派一个分身过去干。 +- [p2-01] 第二样,管的是另一种失控。活太脏了,会把整张桌子占满。 +- [p2-02] 比如说,追一个缺陷,要读三十个文件、翻六十轮对话。 +- [p2-03] 等你找到问题在哪,桌上已经堆了一百多条记录。绝大部分,是中间过程。 +- [p2-04] 这些纸每一轮都被重读一遍。跟目标没关系,但一直占着位置,一直计着费。 +- [p2-05] 换成你会怎么办?开个新终端去翻,翻完关掉,把结论记回本子上。 +- [p2-06] 它的办法也一样。另开一张干净的副桌,派一个分身过去干。 - [p2-07] 副桌上是一份全新的对话记录,干干净净,只有一句任务说明。 - [p2-08] 分身在那边自己跑自己的循环,读文件、改代码,跟主桌互不打扰。 -- [p2-09] 主桌上你看不到那三十个文件的任何一行,中间过程全丢,只带回一张回执。 -- [p2-11] 注意丢的是什么:写过的文件、改过的代码都在硬盘上——丢的是纸,不是活。 -- [p2-12] 纪律第一条:最简实现不许分身再派分身;真实实现放开到三层,同时二十个。 -- [p2-14] 第二条:分身每次动手之前,照样要过那几道闸门。 +- [p2-09] 主桌上你看不到那三十个文件的任何一行。中间过程全丢,只带回一张回执。 +- [p2-11] 丢的是什么?写过的文件、改过的代码都在硬盘上。丢的是纸,不是活。 +- [p2-12] 纪律第一条:玩具版不许分身再派分身。成型的这套放开到三层,同时二十个。 +- [p2-14] 纪律第二条。分身每次动手之前,照样得过那几道闸门。 - [p2-15] 隔离的是视野,不是权限。它看不见你俩的对话,但它一样不能为所欲为。 -- [p2-16] 官方文档后来证实了 Claude Code 里的一个反转, -- [p2-17] 是这一集最反直觉的地方:它内部有一种分叉模式,动机根本不是隔离, -- [p2-18] 是为了省钱——命中缓存。 -- [p2-19] 什么意思?对话按字数花钱;同样的开头算过一遍,短时间内第二遍近乎免费。 -- [p2-20] 分身如果从头建立自己的桌面,前缀全变了,每一段都得原价重新算。 -- [p2-21] 所以分叉模式反着来:把父亲桌上的东西几乎原样搬给分身,让前缀保持一致。 -- [p2-22] 「几乎」是有严格定义的:系统提示、工具表、模型、消息前缀、思考配置, -- [p2-23] 差一个字,白算——五样全对上,缓存才认。 -- [p2-24] 隔离是搂草打兔子,省钱才是真心话。 -- [p2-25] 还有更诚实的:隔离其实是半拉的。有位作者说,分身会继承父亲读过的文件, -- [p2-26] 免得同一个文件读两遍。桌是分开了,有些抽屉还是共用的。 -- [p2-27] 分身要弹审批窗,也会冒泡到父亲的屏幕上,还是你来点头。 -- [p2-28] 至于派出去慢慢干的玩法,以后单拆。 -- [p2-28a] 官方还给分身套了三个上限,像三只笼子:同时在场最多二十个, -- [p2-28b] 每个有自己的轮数上限,还有整份上下文的配额——烧完就收工。 +- [p2-16] 官方文档后来证实了 Claude Code 里的一个反转。 +- [p2-17] 这是今天最反直觉的一处。它内部有一种分叉模式,动机根本不是隔离。 +- [p2-18] 是为了省钱。命中缓存。 +- [p2-19] 什么意思?对话按字数花钱。同样的开头算过一遍,短时间内第二遍近乎免费。 +- [p2-20] 分身要是从头建自己的桌面,前缀全变了,每一段都得按原价重新算一遍。 +- [p2-21] 所以分叉模式反着来。把父亲桌上的东西几乎原样搬过去,前缀就保持一致。 +- [p2-22] 「几乎」是有严格定义的:系统提示、工具表、模型、消息前缀、思考配置。 +- [p2-23] 差一个字就白算。五样全对上,缓存才认账。 +- [p2-24] 隔离是搂草打兔子。省钱才是真心话。 +- [p2-25] 隔离其实还是半拉的。有人读源码读出来,分身会继承父亲读过的文件, +- [p2-26] 免得同一个文件读两遍。桌是分开了,可有些抽屉还是共用的。 +- [p2-27] 分身要弹审批窗,也会冒泡到父亲的屏幕上。还是你来点头。 +- [p2-28] 至于派出去慢慢干的那种玩法,以后单拆。 +- [p2-28a] 官方还给分身套了三个上限,像三只笼子。头一只:同时在场最多二十个。 +- [p2-28b] 另两只:每个分身自己的轮数上限,和整份上下文的配额。烧完就收工。 - [p2-28c] 放得开,也拴得住。副桌再多,也翻不出这三只笼子。 -- [p2-29] 副桌这一样,记住一句:脏活不占主桌。 -- [p2-30] 还有值得记住的第二句:省钱和隔离,常常是同一个设计的两种说法。 +- [p2-29] 记住一句:脏活不占主桌。 +- [p2-30] 还值得记住第二句。省钱和隔离,常常是同一个设计的两种说法。 ## P3 目录卡与垫纸 @@ -97,64 +97,64 @@ - [p3-01] 第三样,管的是知识。规范、手册、风格指南,这些它干活前该知道的东西。 - [p3-02] 最笨的办法,是把手册全贴进它的基本设定里。几百上千行,每轮都跟着计费。 -- [p3-03] 你改一个颜色值,它在重读整个数据库规范——百分之九十九的内容跟你无关。 -- [p3-04] 解法是两级:桌角常驻一叠目录卡,每张卡就一行:这份手册叫什么、管什么。 +- [p3-03] 你改一个颜色值,它却在重读整个数据库规范。百分之九十九的内容跟你无关。 +- [p3-04] 解法是分两级。桌角常驻一叠目录卡,每张卡就写一行:叫什么名,管什么事。 - [p3-05] 一张卡的价钱,大约是整本手册的二十分之一。桌角摆一排,也不心疼。 -- [p3-06] 真要用到哪本,再把整本拉上桌——而且整场常驻,压缩之后还会补回来。 -- [p3-07] 最简的做法很直白:目录常驻,内容按需。 -- [p3-08] 官方口径:目录预算设有硬顶。 -- [p3-08b] 文档里还有句实在话:清单太长,超过两百行,它就开始不老实读了。 -- [p3-09] 硬顶有多硬?大约窗口的百分之一,还设了绝对上限,超了就砍。 +- [p3-06] 真要用到哪本,再把整本拉上桌。而且是整场常驻,压缩之后还会补回来。 +- [p3-07] 目录常驻,内容按需。 +- [p3-08] 官方口径:预算有硬顶。 +- [p3-08b] 文档里还有句实在话。清单太长,超过两百行,它就开始不老实读了。 +- [p3-09] 硬顶有多硬?大约是窗口的百分之一,还另设了绝对上限,超了就砍。 - [p3-10] 还有个安全细节:取手册只认登记过的名字,不走文件路径,防的是目录穿越。 -- [p3-11] 第四样东西,管的是桌面上那张最大的纸——它的基本设定本身。 +- [p3-11] 第四样,管的是桌面上最大的那张纸。就是它的基本设定本身。 - [p3-12] 你跟它说的每一句话之前,都垫着这么一张纸:你是谁、你在哪、能干什么。 -- [p3-13] 最简的做法是从第一行起就写死。能力越加越多,纸越写越长。 -- [p3-14] 换个项目要重写整张纸,改一段可能跟别处打架,而且每轮都全文计费。 -- [p3-15] 而真实的实现是拆成几段——身份、工具清单、工作目录、相关记忆。 -- [p3-16] 每一轮,按当场的真实状态重新拼一次。状态变了,纸跟着变。 +- [p3-13] 一个最简单的版本,是从第一行起就写死。能力越加越多,纸就越写越长。 +- [p3-14] 换个项目要重写整张纸,改一段可能跟别处打架,而且每轮都得全文计费。 +- [p3-15] 真做起来是拆成好几段:身份、工具清单、工作目录、还有相关的记忆。 +- [p3-16] 每一轮,都按当场的真实状态重新拼一次。状态变了,纸也跟着变。 - [p3-17] 关键在「真实状态」四个字:工具查实际注册了哪些,记忆查文件在不在。 -- [p3-18] 不去猜消息里出现了什么关键词。猜关键词,是给幻觉开门。 -- [p3-19] 状态没变,拼出来的纸一字不差,直接用上一次的——拼本身也不重复花钱。 -- [p3-20] 有人拆过它的源码,说这张垫纸常规状态两三万字、极简模式两行。 +- [p3-18] 它不去猜消息里出现了什么关键词。猜关键词,就是给幻觉开门。 +- [p3-19] 状态没变,拼出来的纸一字不差,直接用上回的。连拼都不重复花钱。 +- [p3-20] 有人拆过它的源码,说这张垫纸常规状态两三万字,极简模式就剩两行。 - [p3-21] 更大的反转来自官方:2026年7月,这张纸删掉八成以上,评测不掉分。 - [p3-21a] 纸能写多长,取决于模型有多不需要你替它写。 -- [p3-22] 拆源码的人还说了个讲究的细节:所有段落里,只有一段永远不许进缓存—— +- [p3-22] 读源码的人还说了个讲究的细节。所有段落里头,只有一段永远不许进缓存。 - [p3-23] 外接工具的说明段。外接的服务随时会掉线,缓存它就是在缓存一个谎言。 -- [p3-24] 你看,连「哪段纸可以复用」都是被精确设计过的。 -- [p3-25] 这张垫纸,每轮都在拼,但它拼得比谁都勤俭。 -- [p3-26] 目录、手册、垫纸——三样都在回答同一个问题:这一轮,什么该进它的眼睛。 +- [p3-24] 你看,连「哪一段纸可以复用」都是被精确设计过的。 +- [p3-25] 这张垫纸每轮都在拼,可它拼得比谁都勤俭。 +- [p3-26] 目录、手册、垫纸,三样都在回答同一个问题:这一轮,什么该进它的眼睛。 ## P4 桌边的补救梯 > 画面:桌子右侧挂下一张三级补救梯;每级对应一类错误。等待条 0.5s→1s→2s→…→32s 封顶生长。 > 角标:max_tokens / prompt_too_long / 429·529 · min(500×2^n, 32s) + jitter -- [p4-01] 第五样,管的是意外。活干到一半出岔子,是生产的常态,不是事故。 -- [p4-02] 第一种岔子:话说到一半,额度用完了,句子断在半空。 +- [p4-01] 第五样,管的是意外。活干到一半出岔子,这是生产的常态,不是事故。 +- [p4-02] 第一种岔子:话说到一半,额度用完了,句子就断在半空。 - [p4-03] 处理得很有章法。第一次,把额度上限放大八倍,原封不动重试同一个请求。 -- [p4-04] 注意是原封不动:半句先不存,加够额度再来一遍。 +- [p4-04] 注意,是原封不动。断掉的那半句先不存,加够额度再来一遍。 - [p4-05] 放大只有一次。再断才保存半句话,塞条续写提示:从断掉的地方接着说。 -- [p4-06] 续写最多三次,三次还断就收手。有人拆过源码,把那条提示原文抄了出来, +- [p4-06] 续写最多三次,三次还断就收手。有人拆过源码,把那条提示原文抄了出来。 - [p4-07] 很有工程品味:别道歉,别复述刚才在干嘛,直接接着说,把剩下的活切小点。 -- [p4-08] 第二种岔子:桌上太满,装不下了,服务那边直接拒收。 -- [p4-09] 先压一轮——把旧纸换成摘要腾地方;压完还装不下,就承认装不下,退出。 -- [p4-10] 压过一次还压第二次没有意义:纸不会越压越小,该退就退。 +- [p4-08] 第二种岔子:桌上太满,装不下了。服务那边直接拒收。 +- [p4-09] 先压一轮,把旧的纸换成摘要腾地方。压完还装不下,就承认装不下,退出。 +- [p4-10] 压过一次再压第二次,没意义。纸不会越压越小,该退的时候就得退。 - [p4-11] 第三种岔子最有意思:不是你的问题,是服务那边过载或者限流了。 - [p4-12] 硬冲没用,先等一等:半秒、一秒、两秒往上翻倍,封顶三十二秒。 -- [p4-13] 再撒一点随机抖动,免得全世界的重试同一秒冲回来。 -- [p4-14] 对方要是留了张「稍后再来」的字条,就听字条的。 +- [p4-13] 再撒一点随机抖动,免得全世界的重试都挤在同一秒冲回来。 +- [p4-14] 对方要是留了张「稍后再来」的字条,那就听字条的。 - [p4-17] 连着三次都过载呢?换人。切到备用模型,把没干完的活清一清,先干点小的。 -- [p4-17a] 更值得记的是它什么时候不重试。 -- [p4-17b] 证书对不上,第一次就报错——那是要你去修的,退避一百遍也一样。 -- [p4-17c] 更微妙的是另一类:话已说一半、工具已发出,这时出错,不能原样重发。 -- [p4-17d] 原样重发一次,同一个动作就跑了两遍。 -- [p4-17e] 它的做法是保住已产出的,插一条「没写完」的标记,从断点接着来。 -- [p4-17f] 顺带给个刻度:默认最多重试十次,上限十五次。 -- [p4-19] 拆源码的人还提到个冷静设计:续写要是连着几次没写出新东西, -- [p4-20] 系统就直接判定——再续也没有产出,停。不恋战,也是一种能力。 -- [p4-21] 出错不是终点——这就是这套系统的性格。 -- [p4-21a] 官方还有个兜底的后悔药:改动可以回退到前面的检查点—— -- [p4-21b] 不过它只看文件改动,跑过的命令、改过的外部状态,都不在里面。 +- [p4-17a] 它什么时候不重试? +- [p4-17b] 证书对不上,第一次就报错。那是要你去修的,退避一百遍也一样。 +- [p4-17c] 更微妙的是另一类。话说了一半、工具已经发出,这时候出错,不能原样重发。 +- [p4-17d] 重发一次,动作就跑两遍。 +- [p4-17e] 它的做法是保住已经产出的,插一条「没写完」的标记,从断点接着来。 +- [p4-17f] 顺带给个刻度:默认最多重试十次,上限是十五次。 +- [p4-19] 拆源码的人还提到个冷静的设计。续写要是连着几次都没写出新东西, +- [p4-20] 系统就直接判出来:再续也没产出,停。不恋战,也是一种能力。 +- [p4-21] 出错不是终点。这就是这套系统的性格。 +- [p4-21a] 官方还留了个兜底的后悔药。改动可以回退到前面的检查点。 +- [p4-21b] 不过它只看文件改动。跑过的命令、改过的外部状态,都不在里面。 - [p4-22] 你会发现每一级补救都带着上限:升一次、续三次、等三十二秒、换一次人。 ## P5 桌子换了五样,环没动 @@ -162,17 +162,17 @@ > 画面:五样装置在桌上归位成一组;环从桌后浮到前景(系列锚第二次出场),桌子淡为线稿。 > 角标:五段增量全部为「外挂」· while 骨架未换(实测 @ 67a9126c) -- [p5-01] 收个尾。这一集的五样东西摆在一起看: +- [p5-01] 收个尾。五样摆一起看。 - [p5-02] 钉住的清单,另开的副桌,按需翻开的目录,每轮重拼的垫纸,一张补救梯。 -- [p5-03] 它们管理的是同一件事:这一轮,模型能看见什么。 +- [p5-03] 它们管的其实是同一件事:这一轮,模型到底能看见什么。 - [p5-04] 清单负责「别忘」,副桌负责「别堵」,目录负责「别贪」, - [p5-05] 垫纸负责「别写死」,梯子负责「别断」。 -- [p5-06] 别忘、别堵、别贪、别写死、别断——五句话合起来,就是视野管理。 -- [p5-07] 你会发现一个熟悉的形状:这五样,没有一样写进循环。 +- [p5-06] 别忘、别堵、别贪、别写死、别断。这五句合起来,就是视野管理。 +- [p5-07] 你会发现一个熟悉的形状。这五样,没有一样是写进循环的。 - [p5-08] 清单是工具,副桌是调用,目录是注册表,垫纸是拼装,梯子是包裹。 -- [p5-09] 我逐一比过这些增量代码:加的全是外挂,那句「不停问模型」一个字没换。 -- [p5-13] 视野越管越细,桌面越换越讲究,后面那个循环纹丝不动。 -- [p5-14] 所以它干活越来越稳,不是它变聪明了。 +- [p5-09] 我逐一比过这些增量代码。加的全是外挂。那句「不停问模型」一个字没换。 +- [p5-13] 视野越管越细,桌面越换越讲究,后面那个循环纹丝不动。它干活越来越稳。 +- [p5-14] 不是它变聪明了。 - [p5-15] 是有人替它把视野管了起来。 - [p5-16] 而管视野这件事,本身就是一门可以被看懂的手艺。 @@ -184,10 +184,10 @@ - [p6-07] 本片机制依据官方文档,取数2026年8月,以官方最新表述为准。 - [p6-08] 涉及内部实现的部分,为第三方源码分析,片中已逐处标注。 -- [p6-01] 视野是安排出来的。安排它的,不是模型自己。 -- [p6-02] 这句话对人也成立:你的注意力在哪,多半也不是你自己定的, -- [p6-03] 是你桌上摆了什么、谁在什么时候塞了张纸给你。 -- [p6-04] 五样零件里,清单那件刚被收回去——它押的是「模型记不住」的赌注。 +- [p6-01] 视野是安排出来的。 +- [p6-02] 安排它的,不是模型自己。 +- [p6-03] 这话对人也成立:你的注意力在哪,多半是桌上摆了什么、谁塞了张纸给你。 +- [p6-04] 五样零件里,清单那件刚被收回去。它押的是「模型记不住」这一注。 - [p6-05] 模型变强,赌注就过期。官方留了句自省的话:常问自己,可以停掉哪一件。 -- [p6-06] 桌子会换,零件会瘦,那个循环一直没停过。 -- [p6-09] 下期:它会忘,而且忘得有章法——但有一样东西,它永远不许忘。下期见。 +- [p6-06] 桌子会换,零件会瘦,可后面那个循环一直没停过。 +- [p6-09] 下期:它会忘,而且忘得有章法。但有一样东西,它永远不许忘。下期见。 diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx index b344ec76..7d90c96f 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P2SideDesk.tsx @@ -10,7 +10,11 @@ import {QuoteCard} from '../components/cards'; import {Chip, Counter, Desk, Footnote, LoopRing, Panel, SceneHeader, Stamp, useRingDot} from '../components/motifs'; /** 2-A 桌面色块暴涨成灾:一百多条记录填满桌面;计费计数器持续跳字。 */ -const DeskFlood: React.FC<{floodAt: number; billAt: number}> = ({floodAt, billAt}) => { +const DeskFlood: React.FC<{floodAt: number; billAt: number; chaseAt: number}> = ({ + floodAt, + billAt, + chaseAt, +}) => { const frame = useCurrentFrame(); const rows = 10; const cols = 16; @@ -21,10 +25,72 @@ const DeskFlood: React.FC<{floodAt: number; billAt: number}> = ({floodAt, billAt extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); + /* 追缺陷任务卡:floodAt 前的 p2-01/02(口播点名「追一个缺陷…读三十个文件」) + 整段只有空桌——v5 抽帧实拍 f5377–f5690(10.4s)正文零墨水。任务卡先立 + 在桌上给前两句视觉,色块暴涨前淡出让位(帧驱动,确定性)。 */ + const chaseGone = interpolate(frame - floodAt + 10, [0, 16], [1, 0], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const chaseIn = interpolate(frame - chaseAt, [0, 18], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const CHASE_ROWS = [ + ['tool: read', '读文件'], + ['tool: bash', '跑命令'], + ['assistant', '下结论'], + ]; return (
+ {chaseGone > 0.01 ? ( +
+ +
+ {'任务卡 · 追一个缺陷'} +
+ {CHASE_ROWS.map(([t, d], i) => ( +
+ {t} + {d} +
+ ))} +
+ {'读 30 个文件 · 翻 60 轮对话'} +
+
+
+
{'30×60'}
+
{'轮轮从头读 —— 找问题在哪'}
+
+
+ ) : null}
{Array.from({length: rows}).map((_, r) => (
@@ -864,8 +930,8 @@ export const P2SideDesk: React.FC<{scene: SceneRange}> = ({scene}) => { - {/* p2-03「一百多条」起暴涨;p2-04「一直计着费」起计数器 */} - + {/* p2-03「一百多条」起暴涨;p2-04「一直计着费」起计数器;p2-02 起追缺陷任务卡(见 DeskFlood 注释) */} + {/* p2-06「另开一张干净的副桌」滑入;纸堆随即飞过去 */} diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx index b0569dee..0317a9d9 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P3Manual.tsx @@ -318,10 +318,11 @@ const BudgetValve: React.FC<{barAt: number; bounceAt: number}> = ({barAt, bounce }; /** 3-D 垫纸(system prompt):写死整纸满屏铺开(dim)→ 碎成四段卡 → 每轮重新拼装。 */ -const PadPaper: React.FC<{solidAt: number; crackAt: number; assembleAt: number}> = ({ +const PadPaper: React.FC<{solidAt: number; crackAt: number; assembleAt: number; padAt: number}> = ({ solidAt, crackAt, assembleAt, + padAt, }) => { const frame = useCurrentFrame(); const solid = interpolate(frame - solidAt, [0, 22], [0, 1], { @@ -336,6 +337,22 @@ const PadPaper: React.FC<{solidAt: number; crackAt: number; assembleAt: number}> extrapolateLeft: 'clamp', extrapolateRight: 'clamp', }); + /* 垫纸前置:solidAt 锚在 p3-13,而 beat 从 p3-11 起 —— v5 抽帧实拍 + f12703–f13068(12.2s)整拍 opacity=0,正文零墨水(画面只剩 header+字幕)。 + 先按 p3-12 口播把垫纸「垫在每句话下面」立起来,整纸铺开前淡出让位。 */ + const padGone = interpolate(frame - solidAt + 10, [0, 16], [1, 0], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const padIn = interpolate(frame - padAt, [0, 18], [0, 1], { + extrapolateLeft: 'clamp', + extrapolateRight: 'clamp', + }); + const PAD_QA = [ + ['你是谁', 'identity'], + ['你在哪', 'workspace'], + ['能干什么', 'tools'], + ]; const sections = [ {t: '身份', s: 'identity', d: '你是谁'}, {t: '工具清单', s: 'tools', d: '实际注册了哪些'}, @@ -345,13 +362,67 @@ const PadPaper: React.FC<{solidAt: number; crackAt: number; assembleAt: number}> return (
- {/* 写死整纸:先满屏铺开(dim) */} + {/* 垫纸前置:每句话下面都垫着一张纸 */} + {padGone > 0.01 ? ( +
+
+ {PAD_QA.map(([q], i) => ( +
+ {q} +
+ ))} +
+
+ {'每轮对话之前,都垫着这么一张纸'} +
+
+ ) : null} + {/* 写死整纸:先满屏铺开(dim)。背景 z 序压在垫纸前置层之下:换装期 + (solid 淡入 22 帧 > 前置层淡出 16 帧)两层短暂同屏,前置字样落在 + dim 桌面之上而不是半透明纸上,避免「纸上叠纸」的双重底色。 */}
@@ -877,8 +948,8 @@ export const P3Manual: React.FC<{scene: SceneRange}> = ({scene}) => { - {/* p3-13「写死的」整纸铺开;p3-15「拆成几段」碎裂;p3-16 重拼 */} - + {/* p3-12 起垫纸前置(见 PadPaper 注释);p3-13「写死的」整纸铺开;p3-15「拆成几段」碎裂;p3-16 重拼 */} + {/* p3-17 两个探针;p3-18 关键词路径打叉;p3-19 cache hit 章 */} diff --git a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx index c98d27b7..94e9a361 100644 --- a/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx +++ b/apps/negentropy-influence/episodes/claude-code-planning-video/video/src/scenes/P4Ladder.tsx @@ -10,7 +10,11 @@ import type {SceneRange} from '../types'; import {QuoteCard} from '../components/cards'; import {Chip, Counter, Desk, Footnote, Panel, SceneHeader, Stamp} from '../components/motifs'; -/** 梯子骨架(mech):三级木梯挂在桌右缘,自上垂下挂稳(rope 微弹)。 */ +/** 梯子骨架(mech):三级木梯挂在桌右缘,自上垂下挂稳(rope 微弹)。 + * PARK = 停靠行程:drop=0 时整梯(含挂绳)平移到停靠位。行程必须 ≥ H + 挂绳 40px, + * 否则梯柱顶端残留可见(见下方 LadderDrops 的剪裁注释)。 */ +const LADDER_PARK = 620; + const Ladder: React.FC<{drop: number; labels?: [string, string, string]}> = ({drop, labels}) => { const frame = useCurrentFrame(); const H = 560; @@ -18,7 +22,7 @@ const Ladder: React.FC<{drop: number; labels?: [string, string, string]}> = ({dr const labelsOn = labels ?? ['', '', '']; return ( - + {/* 挂绳:微弹 */} @@ -66,8 +70,13 @@ const LadderDrops: React.FC<{dropAt: number}> = ({dropAt}) => {
- {/* 梯子挂右缘 */} -
+ {/* 梯子挂右缘。剪裁罩(overflow:hidden)盖住挂绳以上全部天空:4-A 的 + dropAt 锚在 p4-02,而 beat 从 p4-01 起 —— v5 抽帧实拍 f15834–f16022 + (6.3s)spring 恒为 0,梯子以 -620px 停靠位画出,svg overflow:visible + 让两根梯柱戳出画布顶边、直接压在 SceneHeader 的 meta 行上(y≤240 区 + 全被穿越)。罩顶对齐挂绳根(svg y=-40),停靠/下落穿越期被剪成 + 「从罩顶垂下」,动画锚 dropAt 零改动。 */} +
From 3f95b5975c0b63cd9d9b5c2359c904262e515048 Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sun, 30 Aug 2026 03:51:10 +0800 Subject: [PATCH 40/41] =?UTF-8?q?fix(video):=20W10=20=E8=A7=86=E8=A7=89=20?= =?UTF-8?q?v5=20=E5=9B=9E=E5=BD=92=E2=80=94=E2=80=948=20=E5=A4=84=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=EF=BC=88=E5=90=AB=20EP3=20=E8=A1=A5=E6=95=91=E6=A2=AF?= =?UTF-8?q?=E8=B6=8A=E9=A1=B6=E3=80=81EP5=20=E9=9F=B3=E7=94=BB=E9=94=99?= =?UTF-8?q?=E4=BD=8D=2010=20=E7=A7=92=E6=AD=BB=E7=A9=BA=EF=BC=89;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EP2:4-A 补救梯梯柱戳出画布顶边压页眉(加剪裁罩+停靠位外移);EP3:0-D 画中画 死空气 5 秒(补预备线)、4-C 顶部框组侵入页眉带(下移 54px);EP4:0-B 洗衣机 底边被引文条切掉(上移 60px)、bC 虚线孤儿(像素取证证伪为误报不修);EP5: 4-A 十卡快闪音画错位近 10 秒死空(蒙太奇锚移到句内关键词处)。EP1 回归 agent 死于 API 错误,以 40 帧像素回归代验(0 缺陷,且 EP1 在 W9 已 120 帧人工审净)。 五集 tsc 零错误、check --check-scenes 全绿。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- .../video/src/scenes/P0Wait.tsx | 6 +++++- .../video/src/scenes/P2Rejoin.tsx | 6 ++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx index f681744d..e848315d 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P0Wait.tsx @@ -155,7 +155,11 @@ const LaundryLeave: React.FC<{turnAt: number; ringAt: number; quoteAt?: number}> const drumA = ((frame / fps) * 60) % 360; return ( - + {/* 终渲 v5 审查实拍:引文条(bottom:262 → 顶缘 y≈726)把洗衣机底边(y≈750, + 含 rx26 圆角)拦腰盖掉 24px——机身看起来没有底。svg 整体上移 60px: + 洗衣机底 y≈690 与引文条顶 726 留 36px 纵净空;顶部计时环(原 y≈394) + 上移到 y≈334,仍在 SceneHeader(y≤150)之下的空带。动画锚零改动。 */} + {/* 洗衣机:方机身 + 圆滚筒 */} diff --git a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx index d2a61b95..ccd669fd 100644 --- a/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx +++ b/apps/negentropy-influence/episodes/claude-code-concurrency-video/video/src/scenes/P2Rejoin.tsx @@ -110,9 +110,11 @@ const TwoTierQueue: React.FC<{dropAt: number; userAt: number}> = ({dropAt, userA {'下一轮 · next'} - {/* 「稍后」道(下):默认道 */} + {/* 「稍后」道(下):默认道。 + 终渲 v5 审查实拍:用户输入卡落定在 x900(左缘 778.5),标签尾部到 x775, + 仅 4px 净空——降半级压角。标签整体左移 20px(x620 起排),与卡缘留 ~24px。 */} - + {'稍后 · later'} {/* 完成通知卡:落到「稍后」道尾 */} From 3fa969b8a52db236c23ff10380faa166ad39716f Mon Sep 17 00:00:00 2001 From: ThreeFish Date: Sun, 30 Aug 2026 09:42:51 +0800 Subject: [PATCH 41/41] =?UTF-8?q?feat(video):=20=E7=BB=88=E6=B8=B2=20v6=20?= =?UTF-8?q?=E4=BA=A4=E4=BB=98=E2=80=94=E2=80=94=E8=AF=AD=E4=BD=93=E7=BA=A7?= =?UTF-8?q?=E9=87=8D=E5=86=99=20527=20=E5=8F=A5=E5=85=A8=E9=87=8F=E9=87=8D?= =?UTF-8?q?=E9=85=8D=E8=90=BD=E6=B8=B2;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 五集 v6:14:12 / 13:24 / 13:35 / 13:05 / 13:21(合计 67.6 分钟 1080p30)。 语体三病根清零(对照名词 0 残留/破折号全系列 0 处/每幕短句爆点); v5 回归 8 处修复落渲;五集七幕体检 FAIL 0 · WARN 0。 🤖 Generated with [Claude Code](https://github.com/claude), [CodeX](https://openai.com), [Gemini](https://github.com/apps/gemini-code-assist) Co-Authored-By: Aurelius Huang --- apps/negentropy-influence/series.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/negentropy-influence/series.json b/apps/negentropy-influence/series.json index f2afa16a..7c7a7187 100644 --- a/apps/negentropy-influence/series.json +++ b/apps/negentropy-influence/series.json @@ -102,7 +102,7 @@ "accessed": "2026-08-21" }, "status": "delivered", - "statusNote": "终渲 v5:14:12 = 25582 帧 · 47.1 MB;W9 文案 9 句润色 + EP1 帧审 120 帧净;七幕 FAIL 0", + "statusNote": "终渲 v6:语体级重写 94 句(破折号 0/对照名词清零/短句爆点)+ v5 回归净;七幕 FAIL 0", "voice": "sunny-steady + me-bright.wav" }, { @@ -124,7 +124,7 @@ "accessed": "2026-08-22" }, "status": "delivered", - "statusNote": "终渲 v5:13:23 = 24103 帧 · 42.2 MB;W9 文案 42 句润色 + 视觉 5 处(镜首真空/过稀/音画错位);七幕 FAIL 0", + "statusNote": "终渲 v6:语体级重写 105 句 + 回归修复(补救梯越顶);七幕 FAIL 0", "voice": "sunny-steady + me-bright.wav" }, { @@ -146,7 +146,7 @@ "accessed": "2026-08-22" }, "status": "delivered", - "statusNote": "终渲 v5:13:37 = 24512 帧 · 41.9 MB;W9 文案 19 句润色 + 视觉 5 处死空气根除;七幕 FAIL 0", + "statusNote": "终渲 v6:语体级重写 114 句 + 回归修复(画中画死空气/顶部框组);七幕 FAIL 0", "voice": "sunny-steady + me-bright.wav" }, { @@ -168,7 +168,7 @@ "accessed": "2026-08-22" }, "status": "delivered", - "statusNote": "终渲 v5:13:05 = 23571 帧 · 44.5 MB;W9 文案 21 句润色 + 视觉 2 处(秒针切字/锚点压标);七幕 FAIL 0", + "statusNote": "终渲 v6:语体级重写 105 句 + 回归修复(洗衣机底边切割);七幕 FAIL 0", "voice": "sunny-steady + me-bright.wav" }, { @@ -190,7 +190,7 @@ "accessed": "2026-08-22" }, "status": "delivered", - "statusNote": "终渲 v5:13:27 = 24236 帧 · 47.8 MB;W9 文案 31 句润色 + 沙箱镜整镜 21.6s 空白根因修复;七幕 FAIL 0", + "statusNote": "终渲 v6:语体级重写 109 句 + 回归修复(十卡快闪音画错位 10 秒死空);七幕 FAIL 0", "voice": "sunny-steady + me-bright.wav" } ]