Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
117 commits
Select commit Hold shift + click to select a range
e833314
verdict(eval:a2a): 2026-07-09-eval-a2a-restart-clean-keep-observe — k…
bouillipx Jul 9, 2026
5d178c1
verdict(eval:friction): 2026-07-09-eval-friction-timeout-singleton-wi…
bouillipx Jul 9, 2026
b6120f2
Merge remote-tracking branch 'upstream/main'
github-actions[bot] Jul 9, 2026
9d21a0d
verdict(eval:a2a): 2026-07-11-eval-a2a-low-traffic-clean-keep-observe…
bouillipx Jul 11, 2026
30f5ba1
verdict(eval:friction): 2026-07-12-eval-friction-singleton-user-feedb…
bouillipx Jul 12, 2026
3157ca4
verdict(eval:a2a): 2026-07-12-eval-a2a-denominator-recovered-clean-ke…
bouillipx Jul 12, 2026
2057de4
verdict(eval:qc): 2026-07-12-eval-qc-zero-baseline-w28 — keep_observe…
bouillipx Jul 12, 2026
bd36863
verdict(eval:anchor-first): 2026-07-12-eval-anchor-first-c1-keep-obse…
bouillipx Jul 12, 2026
a0ac71e
verdict(eval:a2a): 2026-07-13-eval-a2a-subthreshold-c2-regression-kee…
bouillipx Jul 13, 2026
68e7808
Merge remote-tracking branch 'upstream/main'
github-actions[bot] Jul 13, 2026
96d4f7c
Merge remote-tracking branch 'upstream/main'
github-actions[bot] Jul 14, 2026
5c05f5e
verdict(eval:friction): 2026-07-15-eval-friction-empty-window-after-s…
bouillipx Jul 15, 2026
c5b9611
verdict(eval:a2a): 2026-07-15-eval-a2a-subthreshold-multi-signal-drif…
bouillipx Jul 15, 2026
a1eee60
Merge remote-tracking branch 'upstream/main'
github-actions[bot] Jul 15, 2026
118b4c8
verdict(eval:a2a): 2026-07-16-eval-a2a-c2-rate-recovered-keep-observe…
bouillipx Jul 16, 2026
0ccd97c
verdict(eval:a2a): 2026-07-17-eval-a2a-c2-flat-counts-keep-observe — …
bouillipx Jul 17, 2026
31ffcdf
verdict(eval:friction): 2026-07-18-eval-friction-second-empty-window-…
bouillipx Jul 18, 2026
967ecd5
verdict(eval:a2a): 2026-07-18-eval-a2a-subthreshold-void-hold-noise-k…
bouillipx Jul 18, 2026
341e62a
verdict(eval:qc): 2026-07-19-eval-qc-zero-baseline-w29 — keep_observe…
bouillipx Jul 19, 2026
e1e1aaf
verdict(eval:a2a): 2026-07-19-eval-a2a-post-restart-clean-keep-observ…
bouillipx Jul 19, 2026
a076c1a
verdict(eval:anchor-first): 2026-07-19-eval-anchor-first-c1-low-sampl…
bouillipx Jul 19, 2026
8db6b94
verdict(eval:a2a): 2026-07-20-eval-a2a-subthreshold-void-hold-recurre…
bouillipx Jul 20, 2026
e1dd5d3
verdict(eval:a2a): 2026-07-21-eval-a2a-void-hold-diluted-keep-observe…
bouillipx Jul 21, 2026
4e735c1
verdict(eval:friction): 2026-07-21-eval-friction-third-empty-window-s…
bouillipx Jul 21, 2026
abd8c9c
verdict(eval:a2a): 2026-07-22-eval-a2a-stable-post-restart-baseline-k…
bouillipx Jul 22, 2026
f0c1a08
verdict(eval:a2a): 2026-07-23-eval-a2a-post-restart-stable-keep-obser…
bouillipx Jul 23, 2026
36c9df4
verdict(eval:a2a): 2026-07-24-eval-a2a-long-stable-window-keep-observ…
bouillipx Jul 24, 2026
da7043a
verdict(eval:a2a): 2026-07-25-eval-a2a-long-stable-window-keep-observ…
bouillipx Jul 25, 2026
690195d
verdict(eval:qc): 2026-07-26-eval-qc-zero-baseline-w30 — keep_observe…
bouillipx Jul 26, 2026
248e92e
verdict(eval:anchor-first): 2026-07-26-eval-anchor-first-c1-higher-vo…
bouillipx Jul 26, 2026
9901bf5
verdict(eval:a2a): 2026-07-26-eval-a2a-record-stable-window-keep-obse…
bouillipx Jul 26, 2026
ae92958
verdict(eval:a2a): 2026-07-27-eval-a2a-record-window-keep-observe — k…
bouillipx Jul 27, 2026
41ca21a
verdict(eval:a2a): 2026-07-28-eval-a2a-record-window-keep-observe — k…
bouillipx Jul 28, 2026
4dd0b84
verdict(eval:a2a): 2026-07-29-eval-a2a-grounding-depth-gap-keep-obser…
bouillipx Jul 29, 2026
4181595
verdict(eval:a2a): 2026-07-30-eval-a2a-grounding-depth-gap-keep-obser…
bouillipx Jul 30, 2026
afe7fb9
verdict(eval:a2a): 2026-07-31-eval-a2a-grounding-sample-retention-bui…
bouillipx Jul 31, 2026
58296df
verdict(eval:a2a): 2026-08-01-eval-a2a-grounding-sample-retention-bui…
bouillipx Aug 1, 2026
3b8ee0f
verdict(eval:a2a): 2026-08-02-eval-a2a-grounding-sample-retention-bui…
bouillipx Aug 2, 2026
82465b4
verdict(eval:anchor-first): 2026-08-02-eval-anchor-first-low-sample-k…
bouillipx Aug 2, 2026
0b763d0
verdict(eval:a2a): 2026-08-03-eval-a2a-grounding-retention-recovery-w…
bouillipx Aug 3, 2026
39564c1
fix(ci): split expired public directory exceptions (#1164)
zts212653 Jul 17, 2026
d4b8e6d
docs(plugin): define K-2 Host Broker boundary (#1166)
zts212653 Jul 17, 2026
fb1c6d5
docs(plugin): assess K-2 wire protocol shape (#1167)
zts212653 Jul 17, 2026
5deb884
docs(plugin): require wire byte-budget proofs (#1168)
zts212653 Jul 17, 2026
a2dd609
fix(quota): use native Codex auth for refresh
Sizhe-Yang Jul 18, 2026
51ed4a9
fix(quota): refresh configured accounts only
Sizhe-Yang Jul 18, 2026
edbd22d
fix(quota): show usage for named OAuth accounts
Sizhe-Yang Jul 18, 2026
68c2542
fix(quota): show remaining weekly usage
Sizhe-Yang Jul 18, 2026
f59caf7
docs(review): request quota display review
Sizhe-Yang Jul 18, 2026
7428ab7
fix(quota): honor credential and provider boundaries
Sizhe-Yang Jul 18, 2026
dabdec1
fix(quota): isolate refresh sources
Sizhe-Yang Jul 18, 2026
8ca6590
fix(quota): surface partial credential failures
zts212653 Jul 18, 2026
9605e09
feat(catagent): add write/exec tools for native agent provider
bouillipx Jul 9, 2026
9febbf6
fix(catagent): normalize anthropic base URL to prevent double-slash
bouillipx Jul 9, 2026
77f3196
refactor(catagent): extract vendor-neutral protocol adapter seam
bouillipx Jul 9, 2026
81f6c17
feat(catagent): add OpenAI chat adapter for multi-provider support
bouillipx Jul 9, 2026
2857e2f
fix(catagent): restore parseCatConfig + add catAgentProtocol to schema
bouillipx Jul 9, 2026
0aed873
fix(catagent): resolve CI build + lint failures on upstream PR
bouillipx Jul 9, 2026
b998b79
feat(catagent): plumb catAgentProtocol through cats API routes
bouillipx Jul 9, 2026
07077c6
test(catagent): add route regression tests for catAgentProtocol persi…
bouillipx Jul 9, 2026
2cb5a10
fix(catagent): enforce MAX_WRITE_BYTES cap on patch_file results
bouillipx Jul 9, 2026
b04d400
style: fix Biome formatting in catAgentProtocol tests
bouillipx Jul 9, 2026
d979831
fix(catagent): validate account family against catAgentProtocol
bouillipx Jul 9, 2026
e6ef59a
fix(catagent): include catAgentProtocol in PATCH providerConfigTouche…
bouillipx Jul 9, 2026
72858a3
fix(catagent): harden Phase F write/exec + OpenAI adapter (P2 gate)
bouillipx Jul 10, 2026
7d82d9f
fix(catagent): reject symlinks in patch_file to prevent byte-cap bypass
bouillipx Jul 10, 2026
4600c3b
fix(catagent): serialize write/patch CAS + fix timeout pipe-holding
bouillipx Jul 11, 2026
386d14e
fix(catagent): harden tool execution boundaries
Jul 13, 2026
4406dc5
fix(catagent): audit-after-mutation honesty + scope callback injection
bouillipx Jul 14, 2026
8f95294
chore: biome format fix for audit-degraded test lambdas
bouillipx Jul 14, 2026
3fce141
fix(test): update callback scope test for CatAgent-only injection
bouillipx Jul 14, 2026
d09e148
fix(catagent): resolve all deferred review findings (G2/G3 gate)
bouillipx Jul 14, 2026
5cd067b
chore: fix Biome formatting in commandPolicy test array
bouillipx Jul 14, 2026
bac9c64
fix(catagent): plumb clientFamily through Hub account create/edit path
bouillipx Jul 14, 2026
c1d0676
fix(catagent): complete clientFamily Hub plumbing — Accounts tab + re…
bouillipx Jul 14, 2026
d3548da
chore: fix Biome formatting in clientFamily test
bouillipx Jul 14, 2026
dcf2976
fix(catagent): preserve clientFamily on edit of clientId-less accounts
bouillipx Jul 14, 2026
4ba9573
fix(catagent): use protocol-aware family in invocation preflight
bouillipx Jul 14, 2026
79f91f7
fix(catagent): stream parser fail-closed + run_command audit honesty …
bouillipx Jul 14, 2026
e33e712
style: fix Biome formatting in golden test files
bouillipx Jul 14, 2026
7110900
fix(catagent): reject non-object tool inputs as validation errors
bouillipx Jul 14, 2026
9be2868
fix(catagent): audit-degraded error path + path-resolution audit + cl…
bouillipx Jul 15, 2026
77cb8d0
test: update clientFamily assertion for API-key-first init
bouillipx Jul 15, 2026
b95dda5
fix(catagent): reject non-regular files before L1 hashing reads
bouillipx Jul 15, 2026
6513774
fix(catagent): reject non-regular files in patch_file before readFile
bouillipx Jul 15, 2026
4e05400
test(catagent): add FIFO regression for non-regular file rejection
bouillipx Jul 15, 2026
61de780
test(catagent): add bounded-failure deadline to FIFO regression tests
bouillipx Jul 16, 2026
abd9c67
fix(catagent): address 4 Codex R5 P2 findings — fail-closed guards + …
bouillipx Jul 18, 2026
7137e17
fix(catagent): address 2 Codex R6 P2 findings — family guard ordering…
bouillipx Jul 18, 2026
59d4ded
fix(catagent): allow empty write_file content and whitespace-only pat…
bouillipx Jul 18, 2026
29a2148
style(catagent): biome format long schema property lines
bouillipx Jul 18, 2026
0f14bba
fix(catagent): reject OpenAI tool calls without upstream IDs
bouillipx Jul 18, 2026
eebb59c
fix(catagent): reject Anthropic tool_use blocks without upstream IDs
bouillipx Jul 18, 2026
735c1b4
fix(catagent): normalize non-object Anthropic tool inputs to sentinel
bouillipx Jul 18, 2026
9d59e59
fix(catagent): positive tool-use stop gate + child-process FIFO tests
bouillipx Jul 18, 2026
9da510d
test(catagent): add R5–R11 focused regression coverage (18 tests)
bouillipx Jul 18, 2026
c5b4cc7
test(catagent): add service-level R11 stop_reason suppression coverage
bouillipx Jul 18, 2026
9c380e5
fix(test): stabilize process-tree timeout test against cold-start fla…
bouillipx Jul 19, 2026
0b06f2f
fix(catagent): audit task-status validation rejections via rejectWith…
bouillipx Jul 19, 2026
0295f8a
fix(hub): preserve catAgentProtocol in editor form state for account …
bouillipx Jul 19, 2026
25a2309
fix(hub): filter family-typed API-key accounts by effective client in…
bouillipx Jul 19, 2026
74f6b4c
fix(hub): apply clientFamily filtering to Google and Kimi branches in…
bouillipx Jul 19, 2026
8a59b04
fix(security): add .cat-cafe and data to workspace denylist
bouillipx Jul 19, 2026
f661c28
fix(security): remove overbroad 'data' segment denylist + add .cat-ca…
bouillipx Jul 19, 2026
17ce1b4
fix(test): skip search_content .cat-cafe test when rg unavailable
bouillipx Jul 19, 2026
92619cd
fix(security): reject protected namespaces as workspace roots + defen…
bouillipx Jul 19, 2026
dd3ebad
fix(security): canonical root validation in shared resolvers + case-i…
bouillipx Jul 19, 2026
089812a
fix(security): make filename denylist patterns case-insensitive
bouillipx Jul 19, 2026
32edb09
fix(memory): activate embeddings after sidecar install (#1163)
zts212653 Jul 19, 2026
0cf6b24
fix(security): use --iglob for case-insensitive ripgrep denylist globs
bouillipx Jul 19, 2026
277dbb8
fix(catagent): make task progress snapshot best-effort after canonica…
bouillipx Jul 19, 2026
a212058
test(security): add --iglob regression tests at rg invocation boundary
bouillipx Jul 19, 2026
0aa248a
fix(security): resolve root independently before target in resolveWor…
bouillipx Jul 19, 2026
5cdd400
feat(F205): Video Forge — declarative protocol engine + inline video …
mindfn Jul 19, 2026
d386f20
fix(web): preserve legacy untyped API-key accounts on edit
bouillipx Jul 19, 2026
08c0f7c
fix(catagent): make dispatch rejection audit best-effort
bouillipx Jul 19, 2026
219b4f6
fix(catagent): guard legacy account clientId + add --no-config to rg
bouillipx Jul 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
14 changes: 0 additions & 14 deletions .dir-exceptions.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,20 +69,6 @@
"reason": "F235 RedisCommunityIssueDraftStore 加入后 redis/ 达 25 files;与 ports/(26) 同源——每个 store port 一个 Redis impl。需在 F23 follow-up 中按 proposal/community/session 子域拆分。THIRD-ROUND unblock(二轮到 2026-06-30)。",
"expiresAt": "2026-07-31",
"ticket": "F23-followup"
},
{
"path": "packages/api/src/domains/community",
"owner": "opus",
"reason": "F168 Phase D D-PR1 新增 3 files(RedisNarratorDedupStore / community-closure-checklist / community-route-recommendation)后达 25 files。D-PR2 reconciler 可能再加 2-3 个;Phase D 结束后按 closure/reconciler/narrator 子域拆分。",
"expiresAt": "2026-07-15",
"ticket": "F168"
},
{
"path": "packages/api/src/domains/cats/services/stores/redis-keys",
"owner": "opus",
"reason": "redis-keys 27 files;每个 store 一个专属 key-builder 模块,与 stores/ports 和 stores/redis 同源增长。待 F23 follow-up 按 proposal/community/session 子域拆分。",
"expiresAt": "2026-07-15",
"ticket": "F23-followup"
}
]
}
4 changes: 4 additions & 0 deletions cat-cafe-skills/anime-forge/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
name: anime-forge
tips_exempt: delivery error row only — no new user-facing capability; continuity commit will reference video-forge SOT
description: >
AI 生成动画短片生产线:图(关键帧锁确定性)→ 视频(i2v 给活气)→ 后期(剪辑做节奏)。
Use when: 做动画短剧/角色 IP 短片、猫咖日记系列新集、图生视频管线、剧情类 AI 视频。
Expand Down Expand Up @@ -36,6 +37,7 @@ description: >
5. **素材账本**:入库即登记 md5/时长/状态;视频 gitignored 账本作存在证明 → 范例 `assets/README.md`
6. **Animatic 检查点(行为刹车)**:烧贵素材前先用静帧+占位拼粗剪验证节奏;剧本结构问题(见下)必须在这层抓
7. **EDL 渲染**:`animatic/edl-v1.mjs`(时长/字幕/段序真相源)+ `build-animatic.mjs`(零 npm 依赖:Chrome 当字幕/字卡渲染器 + ffmpeg)——改数字重渲,画幅参数化
8. **交付/预览**:最终成片必须在 Console 里内联可看,不要只丢工作区路径。外部直链可直接发 rich block;本地 mp4 先变成 `/uploads/...` 再发 `kind:"file"` + `mimeType:"video/mp4"`。只有你明确需要 `autoplay muted` 且拿到的是外部直链时,才退回 `html_widget` + `<video>`

## 实测分工路由(硬约束,不是偏好)

Expand All @@ -56,6 +58,7 @@ description: >

| 错误 | 后果 | 修复 |
|---|---|---|
| 异源/异锚图片段硬拼成伪一镜到底 | 三段像三个世界,`xfade` 遮 cut 遮不住画风漂移 | 连续性合约 SOT 在 `video-forge/SKILL.md` → "多段拼接连续性合约";AI 域的额外约束:共享锚图、同路由、同调色 |
| i2v prompt 写风格描述词 | 邀请重采样→第二帧跳变 | 风格 100% 来自首帧,prompt 零风格词(配方 §0.6) |
| 正面段写 "the man/adult human" | 往写实拉 | 角色用名字;反幼态只进末尾负面清单 |
| 动作太稀(10s 只给 2 动作) | 模型自己编戏 | 3-4 个 Then 串联填满时间线 |
Expand All @@ -66,6 +69,7 @@ description: >
| 不先问素材画幅就定输出画幅 | 横竖分裂,pad 兜底但割裂 | 开抽前统一画幅;混了用 blur-pad 过渡,终态重抽 |
| 静态 PNG overlay 长片尾段 | ~66s 后 framesync 失效字幕全挂 | PNG 输入加 `-loop 1`(builder 已内置) |
| 字幕长句贴 max-width | 折行被渲染窗裁掉 | 字号留安全区;改完必抽帧亲眼验 |
| 最终只产出工作区 mp4,不把成片挂回对话 | operator 看不到片,只能点文件路径,验收断层 | 终稿交付时把视频变成可访问 URL;`/uploads/...` 用 `file` rich block,外部直链才考虑 `html_widget` |

## 和其他 skill 的区别(GOTCHA)

Expand Down
14 changes: 12 additions & 2 deletions cat-cafe-skills/refs/rich-blocks.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
| card | Review 结论、状态报告、决策摘要 |
| diff | 代码修改建议、重构前后对比 |
| checklist | 待办项、检查清单、验证步骤 |
| file | 已有文件、成片视频、导出物;`video/*` 文件会内联播放 |
| media_gallery | 发送已有图片(头像、照片)、截图、设计稿、多图对比 — 不需要现场生成! |
| audio | 问候、情感表达、定时播报(系统自动合成语音) |
| interactive | 需要用户选择/确认的场景(选方案、选猫、确认操作) |
Expand All @@ -33,8 +34,11 @@
| card | title | bodyMarkdown, tone (info/success/warning/danger), fields |
| diff | filePath, diff | languageHint |
| checklist | items (id+text) | title |
| file | url, fileName | mimeType, fileSize |
| media_gallery | items (url) | title, alt, caption |
| audio | text | — |
| interactive | interactiveType, options (id+label) | title, description, maxSelect, allowRandom, messageTemplate |
| html_widget | html | title, height (50-2000, default 300) |

### media_gallery 图片 URL 规范

Expand All @@ -59,8 +63,14 @@ Codex `image_gen` 和 Antigravity 生成的图片现已**自动发布**:
**手动发布**(仅当自动路径不适用时):调用 `publishGeneratedImage({ sourcePath, mimeType, publicationKey, provider, toolName })`。

不要把”源码仓里存在这个文件”和”当前 API 正在服务这个文件”混为一谈。runtime 可能跑在另一套 worktree / 另一份 `packages/api/uploads/`。
| interactive | interactiveType, options (id+label) | title, description, maxSelect, allowRandom, messageTemplate |
| html_widget | html | title, height (50-2000, default 300) |

### file 文件 / 视频 URL 规范

`file.url` 同样只接受 `/uploads/...`、`/api/...` 或 `https://...`。

- 文档、压缩包等普通文件:显示下载卡片
- `mimeType` 以 `video/` 开头,或文件名扩展是 `mp4/mov/webm/avi/mkv/m4v/ogv`:Web UI 直接渲染内联 `<video>` 播放器
- 当前共享自动发布合约只覆盖图片;**本地视频/通用文件还没有自动 publish helper**,需要先显式放到 `/uploads/...`

## 创建方式

Expand Down
18 changes: 17 additions & 1 deletion cat-cafe-skills/rich-messaging/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
name: rich-messaging
tips_exempt: file kind docs sync only — existing capability-rich-messaging tip covers the skill; sourceRef stays at wakeup-index
description: >
富媒体消息发送:语音、图片、卡片、清单、代码 diff、交互选择。
Use when: 发语音、发图、发卡片、展示结构化信息、长结构化汇报、想发一堆文字/日志/步骤、庆祝、给我听听、给我看看、让用户选、确认操作。
Expand Down Expand Up @@ -52,14 +53,15 @@ triggers:

当你想发一堆文字、日志、步骤,或回复已经有 3+ 结构化信号(列表、表格、代码块、diff、状态字段、行动项)时,默认用 1-2 句自然语言摘要 + `cat_cafe_create_rich_block`。纯长 Markdown 只在 rich block 不适合或工具不可用时使用,并说明原因。

## 七种 Rich Block 一览
## 八种 Rich Block 一览

| Kind | 什么时候用 | 关键字段 |
|------|-----------|---------|
| **audio** | 打招呼、表达情感、庆祝、鼓励、定时播报 | `text`(短句口语化) |
| **card** | 状态报告、决策摘要、review 结论 | `title` + `tone` |
| **checklist** | 待办、验证步骤、行动项 | `items` |
| **diff** | 代码修改建议、重构对比 | `filePath` + `diff` |
| **file** | 发送已有文件、文档、音视频成片;`video/*` 可内联播放 | `url` + `fileName` |
| **media_gallery** | 发送已有图片(头像、照片)、截图、设计稿、多图对比 | `items` (url) |
| **interactive** | 让用户选方案、勾选项、确认操作 | `interactiveType` + `options` (id+label) |
| **html_widget** | 你写的 HTML 直接挂上去:图表、计算器、CSS 动画、数据面板 | `html`(完整 HTML/JS/CSS 代码字符串) |
Expand Down Expand Up @@ -90,6 +92,12 @@ triggers:
{"id": "d1", "kind": "diff", "v": 1, "filePath": "src/foo.ts", "diff": "- old line\n+ new line", "languageHint": "typescript"}
```

### 文件(file)

```json
{"id": "f1", "kind": "file", "v": 1, "url": "/uploads/final-cut.mp4", "fileName": "final-cut.mp4", "mimeType": "video/mp4"}
```

### 图片画廊(media_gallery)

```json
Expand Down Expand Up @@ -132,6 +140,13 @@ operator拍板:"简单的用富文本,复杂的用猫主动打开浏览器

**仅当共享合约不可用时**才手动复制到 runtime 的 uploadDir。

如果你要发的是**已有文件或本地成片视频**:

- 用 `kind:"file"`,不是 `media_gallery`
- `url` 必须是 `/uploads/...`、`/api/...` 或 `https://...`
- `mimeType` 以 `video/` 开头时,Web UI 会渲染内联 `<video>` 播放器
- **当前自动发布合约只覆盖图片**;本地视频/通用文件没有 `publishGeneratedVideo()`,需要你先显式放到 `/uploads/...`

## 三条纪律

1. **先文字后块** — 先用 `post_message` 写 1-2 句自然语言,再发 rich block
Expand All @@ -144,6 +159,7 @@ operator拍板:"简单的用富文本,复杂的用猫主动打开浏览器
|------|------|----------|
| 不知道自己能发语音 | operator说"发语音"你说"我是文字猫" | 你可以!用 audio block |
| "发图"只想到 image-generation | 走 Chrome MCP 现场生成,慢且不稳定 | 先看家里有没有已有图片(`/avatars/`、`/uploads/`),有就 media_gallery 直接发 |
| 本地成片视频只贴文件路径 | 前端拿不到,线程里也没有内联播放器 | 先把视频放到 `/uploads/...`,再用 `file` rich block;`mimeType:"video/mp4"` 时会内联播放 |
| 本地生成图直接用 `file://` 或源码仓路径 | rich block 发得出去,但前端取不到 | 用 `publishGeneratedImage()` 发布到 `/uploads/...`(F172 共享合约自动解析 uploadDir) |
| audio 写长段话 | 合成效果差 | 短句口语化,1-2 句 |
| 只发 block 不写文字 | 猫猫朋友看不懂上下文 | 先写 1-2 句自然语言摘要,再发 block |
Expand Down
103 changes: 103 additions & 0 deletions cat-cafe-skills/video-forge/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
---
name: video-forge
tips_exempt: internal quality discipline (continuity contract teaches cats, not users); no new user-facing capability
description: >
视频制作全链路:素材入库 → 剧本冻结 → 全局配音 → 对齐 → 渲染 → 审查 → 交付。
Use when: 做视频、做 showcase、做教程视频、录屏剪辑、video review、节奏审查。
Expand Down Expand Up @@ -92,6 +93,61 @@ description: >
| P1 | 敏感信息泄露 | 截图里有 token / API key / 私人信息 |
| P2 | 画面选取不佳 | "这段换个更好的片段" |

## AI 视频生成(短片段素材)

当素材来源是 AI 生成(而非人工录制)时,使用可用的视频生成工具(如 MCP 提供的 text2video / image2video 能力)。

### 单段限制

AI 视频生成 API 通常有单次时长限制(如 4-6 秒)。**不要试图用一次调用生成完整长视频。**

### 多段生成策略

目标时长超过单次限制时:
1. **分镜拆段**:按 video-spec 的 segment contract 拆分,每段一个生成任务
2. **逐段生成**:每段独立 submit → poll → 获取 resultUrl
3. **下载素材**:将各段视频下载到 `docs/videos/{project}/assets/` 目录
4. **FFmpeg 拼接**:按 segment 顺序拼接,注意转场处理
```bash
# 简单拼接(同编码格式)
ffmpeg -f concat -safe 0 -i segments.txt -c copy output.mp4
# 需要重编码时(不同分辨率/编码)
ffmpeg -f concat -safe 0 -i segments.txt -c:v libx264 -crf 23 -c:a aac output.mp4
```
5. **预览拼接结果**:用 rich block 内联播放(见「视频预览」章节)

### 注意事项

- 多段拼接必须过连续性合约(见下方「多段拼接连续性合约」)
- AI 生成的素材视为原始素材,后续配音/对齐/审查流程不变

## 多段拼接连续性合约

多段生成是正常的。假连续性不是。

拼接前先分类目标输出:

| 类型 | 定义 | 拼接约束 |
|------|------|---------|
| **Montage** | 显式多镜头序列 | 异源片段正常;转场可见且有意 |
| **Pseudo-one-shot** | 伪一镜到底 / 连续动作 | 必须通过连续性检查(见 [`refs/continuity.md`](refs/continuity.md)) |

**核心边界**:`concat`、`xfade`、crop、grading 是收尾工具,不是连续性修复工具。源片段不兼容时,后处理可以打磨接缝,但不能把它当作连续性的证明。

### Seam Review Gate(多段 pseudo-one-shot 必过)

成片后、final render 前,逐接缝回答 5 问:

1. 角色是否仍然是同一个?
2. 环境是否仍然是同一个场景?
3. 色温是否足够稳定?
4. 镜头方向是否连贯?
5. 运动是否暗示同一个动作,还是独立片段?

**任一项 "否" → 不能宣称 pseudo-one-shot → 走降级路径**(见 [`refs/continuity.md`](refs/continuity.md))。

> 详细的事前预测清单、降级路径和 15s 典型失败案例见 [`refs/continuity.md`](refs/continuity.md)。

## 素材管理规范

### 目录结构
Expand Down Expand Up @@ -145,6 +201,53 @@ ffmpeg -i input.mov -c:v libx264 -crf 23 -c:a aac -b:a 128k output.mp4
| 加速后沿用原始时间轴切段 | **加速会压缩时长,后续段的起始时间必须重新计算。** 例:A 段原 130s 以 2x 输出 65s,B 段在 final timeline 从 65s 开始而非 130s。用 output duration 逐段累加,不要用 source timestamps 直接拼 |
| 只加速长等待段忽略短等待 | 分段不够细时,"Thinking"状态可能散落在多个区间里。逐段审素材,把所有等待态都标出来分别处理 |

## 视频预览(Console 内联播放)

生成的视频**必须在 Console 中内联可看**,不要只贴 URL 或本地路径。

### 优先级

1. **本地终稿 / `/uploads/...` URL** → 优先用 `kind:"file"` rich block,`mimeType:"video/mp4"`。Web UI 会直接渲染内联 `<video>` 播放器,并进入 artifact 索引
2. **外部直链 URL**(如云端生成结果)→ 可直接发 `kind:"file"`;若你明确要 `autoplay muted`,再退回 `html_widget` + `<video>`
3. **只有工作区本地文件、还没可访问 URL** → 先放到 `/uploads/...`,再发 rich block;不要直接贴源码路径

### 示例:优先用 file rich block

```
cat_cafe_create_rich_block({
block: JSON.stringify({
id: "video-<唯一标识>",
kind: "file",
v: 1,
url: "/uploads/final-cut.mp4",
fileName: "final-cut.mp4",
mimeType: "video/mp4"
})
})
```

### 示例:外部直链需要 autoplay 时再用 html_widget

```
cat_cafe_create_rich_block({
block: JSON.stringify({
id: "video-<唯一标识>",
kind: "html_widget",
v: 1,
title: "视频标题",
height: 420,
html: "<video controls autoplay muted playsinline style='width:100%;max-width:720px;border-radius:12px'><source src='<resultUrl>' type='video/mp4'></video>"
})
})
```

### 注意事项

- `file` rich block 保证的是**内联播放器**;如果你要强制自动播放,再考虑 `html_widget` + 外部直链
- 本地视频目前没有图片那样的自动发布合约;要想稳定显示,先显式放到 `/uploads/...`
- 如果 `create_rich_block` 返回 `stale_ignored`,说明回调凭据过期(见 #1092),可尝试在消息文本中嵌入 `` ```cc_rich `` 格式作为降级
- 多段视频先用 FFmpeg 拼接成完整文件,再用一个 rich block 播放最终版

## 技术栈

| 层 | 组件 | License |
Expand Down
62 changes: 62 additions & 0 deletions cat-cafe-skills/video-forge/refs/continuity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# 多段拼接连续性参考

> 核心规则在 `../SKILL.md` → "多段拼接连续性合约"。本文件是补充细则。

## 事前预测清单(Pre-Generation Predictor)

在生成/采集多段素材之前,评估以下 6 项。生成前只能预测风险,成片后才能判决事实——**预测器宽、判决器严**。

### 硬门禁(破了就是"三个世界",后期无解)

| # | 条件 | 说明 |
|---|------|------|
| 1 | 同角色锚 | 所有段必须共享同一角色/主体 |
| 2 | 同场景 identity | 所有段必须发生在同一视觉环境中 |

### 风险预警(升风险但不一票否决)

| # | 条件 | 说明 |
|---|------|------|
| 3 | 同 provider family | 同一生成模型/路由;跨 provider 偶尔配上但风险高 |
| 4 | 同画幅 / 镜头语言 | 画幅突变 = 观众意识到剪辑;镜头焦段应一致 |
| 5 | 同运动方向 / 相机语法 | 运动轴和相机运动应衔接 |
| 6 | 同色彩基线 / grade family | 后期调色能微调但不能桥接完全不同的色温 |

## 降级路径

当 pseudo-one-shot 连续性无法维持时,必须降级——不要继续赌"再来一段"。

**降级触发**:预先声明的 retry budget 耗尽。在 video-spec 冻结时声明允许几次重试,budget 到了就降级,不要散文式"试一两次"。

| 优先级 | 降级方式 | 说明 |
|--------|---------|------|
| 1 | 同一生成物内做文章 | 裁剪 / 变速 / 局部重放(衔接 SKILL.md retiming 优先级) |
| 2 | 同锚图重抽 | 同一首帧/锚图重新生成,属"准同源",仍需过 Seam Gate |
| 3 | 重写分镜为显式 montage | 让 cut 变得可见和有意,不再伪装连续 |
| 4 | freeze / B-roll / insert shot 桥接 | 用时间填充手段代替硬拼(衔接 retiming 优先级表) |

## 典型失败案例:15s = 3×5s

**场景**:目标 15s 猫骑摩托雨夜短片。API 限制 ~5s/次。决策:生成 3 段 5s 拼接。

**render.sh 管线**(来源:`_skill_test1/docs/videos/cat-motorcycle-rain/render.sh`):

```text
[entry.mp4] crop=1248:702, sat=0.92, contrast=1.08, brightness=-0.05
↓ xfade 0.30s
[apex.mp4] crop=1600:900, sat=1.10, contrast=1.03
↓ xfade 0.30s
[exit.mp4] crop=1600:900, sat=1.05, contrast=1.02
```

**为什么失败**:

1. 三段 crop 参数不同(entry 1248×702 vs apex/exit 1600×900)→ 构图跳变
2. saturation 从 0.92 → 1.10 → 1.05 → 色温不连续
3. 实际帧:entry 是后方跟拍黄猫 + 运动摩托;apex 跳成正侧面黑猫 / 巡航车 / 另一套城市空间
4. 角色、车辆、镜头语法、场景 identity 同时断裂
5. xfade 只把断点变软,没有把它变成同一动作

**预测清单诊断**:硬门禁 #1(角色锚)直接失败——不应尝试 pseudo-one-shot。

**正确做法**:降级路径 3——重写为"雨夜蒙太奇"(显式多镜头序列),让 cut 变得有意而非藏着。
Loading