@@ -946,7 +946,7 @@ High-level groups verified from the source repo:
946946 都保持在同一 canonical notebook URL,没有再漂到 ` ?addSource=true `
947947 - ` source-add-url ` 在本轮修复后也成功创建临时 web source,说明 detached 瞬态至少在这条 live 路径上已缓解
948948
949- ## 2026-03-31 From-0 Integration Test Summary (9 Modules)
949+ ## 2026-03-31 From-0 Integration Test Summary (9 Modules, Historical Only )
950950
951951### Test Environment
952952- Browser Bridge daemon: port 19825, extension v1.5.5, connected
@@ -1030,9 +1030,9 @@ High-level groups verified from the source repo:
10301030- ` source --help ` 、` notes --help ` 、` download --help ` 、` language --help ` → 全部正常
10311031- ` language get ` 和 ` language-get ` → 均 PASS(alias 正常)
10321032
1033- ### PR 准入评估
1033+ ### 历史测试结论(不作为当前统一 PR 判断依据)
10341034
1035- ** 可以进入统一 PR 的命令 :**
1035+ ** 当时可直接确认的命令 :**
103610361 . ` status ` / ` list ` — 稳定,RPC
103710372 . ` create ` / ` rename ` / ` delete ` / ` remove-from-recent ` — 稳定,RPC,闭环验证通过
103810383 . ` current ` / ` get ` / ` metadata ` / ` describe ` — 稳定
@@ -1046,7 +1046,7 @@ High-level groups verified from the source repo:
1046104611 . ` language-list ` / ` language-get ` / ` language-set ` — 稳定,RPC
1047104712 . 命令树三层结构和帮助文本 — 框架稳定
10481048
1049- ** 不该混进统一 PR(需要更多运行态验证) :**
1049+ ** 当时受运行态影响、未纳入判断的命令 :**
10501050- ` source-rename ` / ` source-refresh ` / ` source-delete ` — browser drift 导致测试不稳定,需要稳定性修复后再验证
10511051- ` notes delete ` / ` notes-save ` — 同上
10521052- ` download audio ` / ` download slide-deck ` — artifact URL 过期是运行态问题,不是代码缺陷;但需要稳定可用的 artifact 样本才能验证
@@ -1056,7 +1056,26 @@ High-level groups verified from the source repo:
10561056- ` bind-current ` 在无 notebook tab 时失败是设计预期,需要先 navigate
10571057- ` download audio/slide-deck ` 的 "fetch failed" 是 URL 过期,不是实现问题
10581058
1059- ### 关键运行态问题:Browser Drift
1059+ ## Artifact-ID Completion Findings
1060+
1061+ - ` opencli ` 原有 ` completion.ts ` 只支持静态 command-path segment 补全,不支持按 flag/value 位置返回动态候选。
1062+ - 要给 ` --artifact-id ` 做 live 候选,completion fast-path 必须异步化:
1063+ - ` src/main.ts ` 的 ` --get-completions ` 分支需要 ` await getCompletions(...) `
1064+ - ` src/completion.ts ` 需要支持按已解析命令和当前 flag 定位到目标参数
1065+ - 生产态 ` discoverClis ` 默认优先走 manifest;对于 TS 命令,registry 初始拿到的是 lazy stub。
1066+ - 因此如果 completion 只读 manifest stub,会拿不到 TS 命令里定义的 runtime ` arg.completion ` 回调。
1067+ - 最小可行修正是:
1068+ - completion 在命中具体命令后,对该 lazy TS adapter 做一次最小 lazy-load
1069+ - 然后再从更新后的 registry 读取真实 ` args ` metadata
1070+ - NotebookLM ` artifact-id ` completion 不需要完整 ` artifact/* ` :
1071+ - 候选直接来自当前 notebook 的 ` listNotebooklmDownloadArtifactsViaRpc(page) `
1072+ - 再按 ` artifact_type ` 过滤成纯 ` artifact_id ` 列表
1073+ - NotebookLM completion helper 还需要复用命令执行路径的 browser workspace:
1074+ - ` workspace: site:notebooklm `
1075+ - 否则会连到错误 browser session,拿不到当前 notebook 索引
1076+ - 当前 shell 侧只要求纯字符串候选即可,因此返回纯 ` artifact_id ` 已足够。
1077+
1078+ ### 历史运行态问题:Browser Drift(仅用于排障记录)
10601079- 每次 CLI 命令执行后,browser bridge CDP session 会偶发漂回 home 页
10611080- 在连续 2-3 条命令后必然发生
10621081- 影响所有 notebook-context 命令的连续测试
@@ -1124,7 +1143,7 @@ High-level groups verified from the source repo:
11241143 - ` status = ready `
11251144 - ` status_code = 2 `
11261145
1127- ## 2026-03-31 From-0 Integration Test Results
1146+ ## 2026-03-31 From-0 Integration Test Results (Historical Only)
11281147
11291148### Test Environment
11301149- Browser Bridge 连接正常,当前 Chrome 停在 NotebookLM ** home** 页面(不是 notebook 页面)
@@ -1179,19 +1198,228 @@ High-level groups verified from the source repo:
11791198| ` language-get -f json ` | PASS |
11801199| ` language-set en/zh_Hans -f json ` | PASS |
11811200
1182- ### 结构性结论
1201+ ### 历史结构性结论(不作为当前统一 PR 判断依据)
11831202
1184- ** 可进入统一 PR :**
1203+ ** 当时可直接确认的能力 :**
118512041 . ` status ` / ` list ` — 稳定,RPC
118612052 . ` create ` / ` rename ` / ` delete ` / ` remove-from-recent ` — 稳定,RPC
118712063 . ` language-list ` / ` language-get ` / ` language-set ` — 稳定,RPC
118812074 . 命令树框架(三层 + 别名)— 框架稳定
11891208
1190- ** 不该混进统一 PR(notebook-context) :**
1209+ ** 当时因测试前置条件不足而未纳入判断的能力 :**
11911210- 所有 ` source/* ` 、` notes/* ` 、` ask ` 、` generate/* ` 、` download/* ` 、` share-status ` 、` describe ` 、` current ` 、` get ` 、` metadata ` 、` summary ` 、` history `
11921211- 这些实现正确,代码无需修改,但 live 验证依赖 browser 停在 notebook URL
11931212
11941213** 运行态阻塞点:**
11951214- ` bind-current ` 无法接受 notebook-id 参数:CLI 设计就是"绑定当前活动 tab",没有 ` opencli notebooklm bind-current <id> ` 这种用法
11961215- ` use ` 是 ` bind-current ` 的 alias,行为一致
11971216- 如需切换 notebook,必须先手动在 Chrome 里打开目标 notebook URL,然后运行 ` bind-current ` 或 ` use `
1217+
1218+ ## 2026-03-31 统一 PR 前验证(第 2 轮)
1219+
1220+ > 以下结论是当前统一 PR 的唯一判断口径。上面的 From-0 结果只保留为历史排障记录,不再作为 PR judgment 依据。
1221+
1222+ ### 测试前提
1223+ - notebook: ` a45591ed-37bd-4038-a131-141a295c024b ` (浏览器自动化工具全解析)
1224+ - ` bind-current ` → ✅
1225+ - ` status ` → ✅ ` page: "notebook" `
1226+
1227+ ### 模块 A:Source ingest 闭环
1228+ - ` source-add-text ` ✅ — RPC,source id 返回
1229+ - ` source wait ` ✅ — ` status_code: 2, status: "ready" `
1230+ - ` source wait-for-sources ` ✅ — 逗号分隔 ids 可用
1231+ - ` source-add-file ` ❌ — ` fetch failed ` ,resumable upload URL 过期(运行态)
1232+
1233+ ### 模块 B:Notes 精确操作
1234+ - ` notes list ` ✅ — 3 条,含两条同名"新建笔记"
1235+ - ` notes get --note-id ` ✅ — 绕过重复标题歧义,精确命中
1236+ - ` notes create ` ✅ — RPC,id 返回
1237+ - ` notes delete --note-id ` ✅ — RPC
1238+ - ` notes rename --note-id ` ✅ — RPC
1239+ - ` notes-save ` ❌ — 无 visible note editor(设计边界,预期)
1240+
1241+ ### 模块 C:Generate 最小闭环
1242+ - ` generate report --wait ` ✅ — artifact id ` c0674240-... ` ,完整闭环,download report 写出 9.9K
1243+ - ` generate audio ` ❌ — ` status: failed ` ,artifact_id=null(notebook 内容限制,非代码缺陷)
1244+ - ` generate audio --wait ` ❌ — 超时
1245+ - ` generate slide-deck ` ❌ — ` status: failed `
1246+ - ` generate slide-deck --wait ` ❌ — 超时
1247+
1248+ ### 模块 D:Download 闭环
1249+ - ` download list ` ✅ — 正确索引 report + slide_deck
1250+ - ` download report ` ✅ — 新 artifact,9.9K 写出
1251+ - ` download slide-deck ` ❌ — ` fetch failed ` ,URL 过期(运行态)
1252+
1253+ ### 模块 E:artifact-id 补全
1254+ - ` download slide-deck --artifact-id ` ✅ — 补全 slide-deck id
1255+ - ` download report --artifact-id ` ✅ — 补全 report id
1256+ - ` download audio --artifact-id ` ✅ — 空(无 audio artifact)
1257+ - ` download video --artifact-id ` ✅ — 空(无 video artifact)
1258+ - 平面 alias ` download-slide-deck ` / ` download-report ` ✅ — 同样补全
1259+
1260+ ### 统一 PR 准入(当前有效)
1261+ ** 可进入统一 PR:**
1262+ 1 . ` source-add-text ` / ` source wait ` / ` source wait-for-sources ` / ` source delete `
1263+ 2 . ` notes list ` / ` notes get --note-id ` / ` notes create ` / ` notes delete --note-id ` / ` notes rename --note-id `
1264+ 3 . ` generate report --wait ` — 完整闭环
1265+ 4 . ` download list ` / ` download report `
1266+ 5 . ` completion --artifact-id ` 补全
1267+
1268+ ** 运行态问题(不应阻塞 PR):**
1269+ - ` source-add-file ` — 该能力此前已 live 验证通过;最新定向验证中的失败属于 daemon 侧网络/上传会话问题,非 adapter 代码缺陷
1270+ - ` download slide-deck ` — 该能力此前已用 fresh artifact live 验证通过;最新定向验证未能建立新 artifact 前置条件,不应反向否定实现
1271+ - ` notes-save ` — 设计边界,需 visible editor
1272+
1273+ ** 仍待独立调查(不排除代码实现问题的可能性):**
1274+ - ` generate audio ` — 在内容丰富的 notebook(10 sources)上仍 ` status: failed ` ;report 成功说明核心 RPC 正确;疑似 audio/slide-deck payload 与 report 不同,或该 notebook 有 server-side 限制
1275+ - ` generate slide-deck ` — 与 audio 同失败模式
1276+
1277+ ** 设计边界:**
1278+ - signed download URL TTL ~ 1 天
1279+ - resumable upload URL TTL
1280+ - ` notes-save ` 要求 visible note editor
1281+
1282+ ## 2026-03-31 剩余运行态定向验证(第 3 轮)
1283+
1284+ > 本轮用于检查剩余边界,不覆盖此前已经完成的 live 成功样本;若与更早的成功验证冲突,以“能力已验证通过,但本轮样本/环境未满足前置条件”记载。
1285+
1286+ ### 测试前提
1287+ - notebook: ` a45591ed-37bd-4038-a131-141a295c024b ` (10 sources,pdf/web/youtube/pasted-text/audio,内容丰富)
1288+ - 该 notebook 之前已成功 generate report ✅
1289+ - ` bind-current ` + ` status ` ✅
1290+
1291+ ### 验证结果
1292+
1293+ | 模块 | 结果 | 分类 |
1294+ | ------| ------| ------|
1295+ | ` source-add-file ` | ❌ HTTP fetch failed | 本轮受 daemon 网络/上传会话影响;该能力此前已 live 验证通过 |
1296+ | ` notes-save ` | ⚠️ 前置条件未满足 | 设计边界,需 visible editor |
1297+ | ` generate audio ` | ❌ ` status: failed ` | 在丰富 notebook 上仍失败;report 成功≠网络问题;** 不排除代码实现问题** |
1298+ | ` generate slide-deck ` | ❌ ` status: failed ` | 同上,与 audio 同根因 |
1299+ | ` download slide-deck ` | ⚠️ 本轮前置条件未满足 | 本轮依赖模块 4;该能力此前已用 fresh artifact live 验证通过 |
1300+
1301+ ### 关键发现
1302+ - ` generate audio/slide-deck ` 在该 notebook 上失败,而 report 成功,说明:
1303+ - 网络通道正常
1304+ - R7cb6c 对 report 类型有效
1305+ - audio/slide-deck 类型的 payload 可能与 report 不同,或存在 server-side 生成限制
1306+ - 这值得独立调查 audio/slide-deck 的 R7cb6c payload 差异,但不推翻当前统一 PR 的 report/download 主路径
1307+ - ` source-add-file ` 本轮失败是 daemon 侧网络/上传会话问题,不是 adapter 代码缺陷;该能力此前已 live 验证通过
1308+
1309+ ## 2026-03-31 Generate Audio / Slide-Deck专项调查
1310+
1311+ ### Static Comparison
1312+
1313+ - opencli 当前 3 个 generate builder 都走同一个 RPC:
1314+ - ` R7cb6c `
1315+ - 当前 opencli payload:
1316+ - report:
1317+ - ` [..., 2, sourceTriples, ..., [null, [title, description, null, sourceDoubles, "en", prompt, null, true]]] `
1318+ - audio:
1319+ - ` [..., 1, sourceTriples, ..., [null, [null, null, null, sourceDoubles, "en", null, null]]] `
1320+ - slide-deck:
1321+ - ` [..., 8, sourceTriples, ..., [[null, "en", null, null]]] `
1322+ - 与上游 ` notebooklm-py ` 对比后确认:
1323+ - report / audio / slide-deck 的 payload 结构在 opencli 中与上游默认 builder 对齐
1324+ - audio 和 slide-deck 并不是“少了整个 type-specific 子结构”
1325+ - opencli 当前只是把 type-specific knobs 保持为默认 ` null `
1326+ - 额外用 live RPC probe 验证了最可疑的默认枚举位:
1327+ - audio 显式补 ` length=2 `
1328+ - audio 显式补 ` format=1/2 `
1329+ - slide-deck 显式补 ` format=1/2, length=1 `
1330+ - 结果全部仍然返回同一类 ` UserDisplayableError `
1331+ - 结论:
1332+ - 当前没有证据支持“只差一个 format/length 默认值”这个假设
1333+
1334+ ### Live RPC Evidence
1335+
1336+ - 当前 notebook:
1337+ - ` a45591ed-37bd-4038-a131-141a295c024b `
1338+ - 当前 source count(RPC probe 时):
1339+ - ` 8 `
1340+ - live ` R7cb6c ` 结果对比:
1341+ - report:
1342+ - 返回完整 artifact row
1343+ - ` artifact_id = 18457f58-f566-4702-939f-edc276d85303 `
1344+ - ` status_code = 1 `
1345+ - audio:
1346+ - ` wrb.fr("R7cb6c", null, ..., UserDisplayableError, ...) `
1347+ - ` result = null `
1348+ - slide-deck:
1349+ - ` wrb.fr("R7cb6c", null, ..., UserDisplayableError, ...) `
1350+ - ` result = null `
1351+ - audio 与 slide-deck 的失败模式不是 timeout,也不是 artifact 后续不可见:
1352+ - 是提交当下就被服务端拒绝
1353+
1354+ ### UI Evidence
1355+
1356+ - 同一 live notebook 的 Studio 面板已直接出现明确文案:
1357+ - ` 您已达到每日音频概览和幻灯片数量上限,改日再来吧。 或进行升级。 `
1358+ - 这条文案与 RPC 行为完全一致:
1359+ - report 仍可生成
1360+ - audio / slide-deck 触发 ` UserDisplayableError `
1361+ - 因此当前最可能根因是:
1362+ - server-side quota / eligibility gate
1363+ - 作用范围正好覆盖 ` audio overview ` 和 ` slide deck `
1364+ - 不是 opencli transport 整体故障
1365+ - 也没有证据表明是最小 payload 结构错误
1366+
1367+ ### Practical Conclusion
1368+
1369+ - 对本轮问题,最可信的判断顺序是:
1370+ 1 . 不是 generic network failure
1371+ 2 . 不是“只差 type code”
1372+ 3 . 也不是“只差一个 format/length 默认枚举”
1373+ 4 . 当前最像的是服务端对 account / notebook 的 daily quota 或 eligibility 限制
1374+ - 如果后续要修 opencli,最小修复点不该先改 payload builder。
1375+ - 更合理的最小修复点应落在:
1376+ - ` src/clis/notebooklm/rpc.ts `
1377+ - 更细分 ` UserDisplayableError ` 的 batchexecute 响应
1378+ - 或 ` src/clis/notebooklm/utils.ts `
1379+ - 在 generate helper / parser 中把这类结果归一化为明确的 quota/eligibility failure
1380+ - 当前没有足够证据支持直接修改:
1381+ - ` buildNotebooklmGenerateAudioParams(...) `
1382+ - ` buildNotebooklmGenerateSlideDeckParams(...) `
1383+
1384+ ## Generate Revalidation On The New Account
1385+
1386+ - 这轮先把 browser bridge tab 重新导航回 rich notebook:
1387+ - ` a45591ed-37bd-4038-a131-141a295c024b `
1388+ - live 重新验证结果:
1389+ - ` generate report ` :仍然成功提交
1390+ - ` generate report --wait ` :闭环成功,返回 completed artifact
1391+ - ` generate audio ` :仍然提交即失败,` artifact_id = null `
1392+ - ` generate slide-deck ` :仍然提交即失败,` artifact_id = null `
1393+ - 与之前 old account 的关键差异是:
1394+ - 这次 raw ` R7cb6c ` 响应里仍然能确认 ` UserDisplayableError `
1395+ - 但响应体不再携带可读 message,只剩内部 envelope:
1396+ - audio: ` [8,null,[[type.googleapis.com/...UserDisplayableError, [[null,[[1]]]]]]] `
1397+ - slide-deck: ` [8,null,[[type.googleapis.com/...UserDisplayableError,[null,null,null,null,null,null,null,[null,[[1]]]]]]] `
1398+ - 页面当前也没有再次出现之前那个明确的“每日额度/升级”可读文案
1399+ - 因此这轮新的最稳结论是:
1400+ - 新账号下,audio / slide-deck 依旧被服务端在提交阶段拒绝
1401+ - 但当前证据不足以把它继续稳定归因为 ` daily_limit_reached `
1402+ - 也没有足够证据把它归因为 ` content_insufficient `
1403+ - 在没有可读 message 的前提下,当前最保守、最正确的分类是 ` generation_failed_unknown `
1404+
1405+ ## Generate Error Classification Enhancement
1406+
1407+ - 这轮没有改 generate payload builder。
1408+ - 最小修复点落在:
1409+ - ` src/clis/notebooklm/rpc.ts `
1410+ - ` src/clis/notebooklm/utils.ts `
1411+ - ` src/clis/notebooklm/shared.ts `
1412+ - 当前行为:
1413+ - raw batchexecute body 中若出现 ` UserDisplayableError `
1414+ - 会先尝试提取可读 message
1415+ - 再按 message 归类为:
1416+ - ` daily_limit_reached `
1417+ - ` feature_not_eligible `
1418+ - ` content_insufficient `
1419+ - ` generation_failed_unknown `
1420+ - 当前 generate row 会额外返回:
1421+ - ` error_type `
1422+ - ` message `
1423+ - 新账号当前 live 结果证明:
1424+ - 这套增强至少已经把“原先只看到 failed”的返回,提升成了“明确是 ` UserDisplayableError ` 但无可读 message,所以归到 ` generation_failed_unknown ` ”
1425+ - 若将来服务端重新带出可读 quota / eligibility / content 文案,当前分类器已经能直接映射到更具体的错误类型
0 commit comments