diff --git a/.gitignore b/.gitignore index 5572a64ba..09c4f1e1a 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ docs/prd/* !docs/prd/tools/*.md # Internal roadmap&gongzonghao (private) +docs/exec-plans/ docs/roadmap/* !docs/roadmap/lime-service-skill-cloud-config-prd.md !docs/roadmap/task/ @@ -59,8 +60,8 @@ docs/roadmap/* !docs/roadmap/memory/*.md !docs/roadmap/knowledge/ !docs/roadmap/knowledge/prd.md -!docs/roadmap/creaoai/ -!docs/roadmap/creaoai/*.md +!docs/roadmap/skill-forge/ +!docs/roadmap/skill-forge/*.md !docs/roadmap/managed-objective/ !docs/roadmap/managed-objective/*.md !docs/roadmap/ai-layered-design/ @@ -73,7 +74,13 @@ docs/knowledge !docs/knowledge/ docs/knowledge/* !docs/knowledge/README.md -docs/research/ +!docs/knowledge/skills/ +!docs/knowledge/skills/** +docs/knowledge/skills/.DS_Store +docs/knowledge/skills/**/.DS_Store +docs/research/* +!docs/research/skill-forge/ +!docs/research/skill-forge/*.md # Issues tracking (internal use only) .issues/ diff --git a/AGENTS.md b/AGENTS.md index a7d5bde94..b1143d7ab 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -11,6 +11,14 @@ 5. **持续垃圾回收** - 技术债按小额、持续方式偿还;差距追踪见 `docs/exec-plans/tech-debt-tracker.md` 6. **卡住时修环境,不是更用力** - 先补上下文、工具、约束,再继续实现;缺口也要写回 repo +## 工程协作方式 + +1. **默认以完整交付为单位** - 不把可自行判断的实现细节、下一步动作或可逆选择转嫁给用户;读代码、做判断、完成闭环后再报告结果 +2. **少问但不越权** - 只有真实需求歧义、不可逆 / 高风险操作、生产环境影响、凭证缺失,或继续会明显偏离用户意图时才停下来询问 +3. **结果汇报优先** - 收尾说明做了什么、为什么这样做、验证了什么、还剩什么缺口;避免过程性礼貌汇报 +4. **任务完成标准优先** - 以可编译、类型正确、测试通过、功能真实可用作为完成依据;实现细节服从项目既有模式和当前主线目标 +5. **不主动扩大承诺** - 不在完成后追问“要不要继续做 X/Y/Z”;如存在自然下一刀,只简短列出建议,等待用户明确要求 + ## 基础约束 1. **始终使用中文** - 回复、文档、代码注释默认使用中文;若文件已有其他注释语言,保持与现有代码库一致 @@ -40,15 +48,18 @@ ## 执行与路线图 1. **主线任务先重述目标** - 用户要求“对齐路线图 / 继续主线”时,先说明当前主目标、阶段和下一刀 -2. **每一刀都要可追踪** - 改动要么回挂到 `docs/roadmap/`,要么登记到 `docs/exec-plans/` 或技术债追踪 -3. **清理不能替代交付** - 连续两轮主要在做治理减法后,下一轮优先回到未完成主线 -4. **长任务必须落计划** - 超过一轮的实现、迁移、清理,写入 `docs/exec-plans/` 并持续更新进度日志 -5. **主线冲突先清障,不保旧面** - current 规划与旧实现直接冲突时,先删或下线阻碍主线的旧页面、旧命名、旧命令、旧文档,再继续实现;不要为了“看起来兼容”保留双轨 -6. **默认不为顺手问题偏航** - 已经选定本轮主线后,除非该问题直接阻塞当前交付、会让新改动变假配置/假入口,或用户明确要求,否则不要切去处理旁支优化、额外治理、零引用清理或“顺手再修一个” -7. **清理必须有主线收益句** - 任何治理/重构/删除动作,动手前都要能用一句话说明“它如何直接帮助当前主线交付”;如果说不出来,就记录为后续项而不是立即执行 -8. **顺手项一次只收一刀** - 实现主线时即使发现多个周边问题,默认只处理其中最直接阻塞的一项;其余登记后立即回到主线,不串行深挖 -9. **完成判定先看主线,再看周边** - 用户问“完成了么”时,先回答主线目标是否完成;周边清理、额外校验、可选优化必须单独标为“已做 / 未做”,不能混成“还差一点边角所以整体未完成” -10. **验证以证明交付为上限** - 校验应先覆盖当前改动的真实风险;在已经证明主线可交付后,不要因为还能继续跑更重检查,就无限追加验证并拖延收口 +2. **先补主缺口再磨细节** - 多阶段主线未到可用闭环前,优先做直接提高整体完成度的缺口;协议 polish、错误分类、额外 seam、边缘校验、文案润色、内部抽象等梢枝末节,只有在阻塞主路径、会造成假入口/假配置,或用户明确要求时才做 +3. **下一刀必须按目标增量排序** - 选择下一步前先列出 1-3 个未完成主问题,并优先选“对整体目标完成度提升最大”的一项;不要因为当前文件顺手、测试容易、局部更完整,就继续做低杠杆小项 +4. **每一刀都要可追踪** - 改动要么回挂到 `docs/roadmap/`,要么登记到 `docs/exec-plans/` 或技术债追踪 +5. **清理不能替代交付** - 连续两轮主要在做治理减法后,下一轮优先回到未完成主线 +6. **长任务必须落计划** - 超过一轮的实现、迁移、清理,写入 `docs/exec-plans/` 并持续更新进度日志 +7. **主线冲突先清障,不保旧面** - current 规划与旧实现直接冲突时,先删或下线阻碍主线的旧页面、旧命名、旧命令、旧文档,再继续实现;不要为了“看起来兼容”保留双轨 +8. **默认不为顺手问题偏航** - 已经选定本轮主线后,除非该问题直接阻塞当前交付、会让新改动变假配置/假入口,或用户明确要求,否则不要切去处理旁支优化、额外治理、零引用清理或“顺手再修一个” +9. **清理必须有主线收益句** - 任何治理/重构/删除动作,动手前都要能用一句话说明“它如何直接帮助当前主线交付”;如果说不出来,就记录为后续项而不是立即执行 +10. **顺手项一次只收一刀** - 实现主线时即使发现多个周边问题,默认只处理其中最直接阻塞的一项;其余登记后立即回到主线,不串行深挖 +11. **完成判定先看主线,再看周边** - 用户问“完成了么”时,先回答主线目标是否完成;周边清理、额外校验、可选优化必须单独标为“已做 / 未做”,不能混成“还差一点边角所以整体未完成” +12. **验证以证明交付为上限** - 校验应先覆盖当前改动的真实风险;在已经证明主线可交付后,不要因为还能继续跑更重检查,就无限追加验证并拖延收口 +13. **开发任务结束必须给完成度百分比** - 非纯问答的开发任务收尾时,必须给“本轮完成度:X%”,并说明主线目标是否完成、验证情况、剩余缺口和下一刀;路线图 / 长任务 / 多阶段主线还要额外给“整体目标完成度:Y%”,并说明百分比口径 ## 文档导航 diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index a0c274de5..dc1474da2 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,75 +1,109 @@ -## Lime v1.29.0 +## Lime v1.30.0 -发布日期:`2026-05-06` +发布日期:`2026-05-08` ### 发布概览 -- 本次发布目标 tag 为 `v1.29.0`,重点推进 CREAOAI workspace skill runtime binding、显式 runtime enable、AI 图层化设计导出,以及 Memory / Skills / Scene Apps / Knowledge 工作台的主路径收口。 -- 版本事实源已同步到 `1.29.0`:`package.json`、`package-lock.json`、`src-tauri/Cargo.toml`、`src-tauri/Cargo.lock`、`src-tauri/tauri.conf.json`、`src-tauri/tauri.conf.headless.json`、`@limecloud/lime-cli` npm wrapper 与 release updater 测试样例保持一致。 -- 该版本继续坚持 current-first:workspace skill binding、Query Loop metadata、runtime enable、Evidence Pack、GUI review surface 与 mock/contract 都回到同一条运行时事实源,不新增平行执行入口。 +- 本次发布按当前准备递交的完整暂存内容编写,范围包括版本发布、Skill Forge 主线、只读 HTTP/API 能力草案、Agent Runtime / Evidence Pack、Knowledge v2、AI 图层化设计、GUI 页面与质量脚本;机密执行计划不进入发布提交。 +- 应用版本从 `1.29.0` 升级到 `1.30.0`,同步 `package.json`、`package-lock.json`、`src-tauri/Cargo.toml`、`src-tauri/Cargo.lock`、`src-tauri/tauri.conf.json`、`src-tauri/tauri.conf.headless.json`、`packages/lime-cli-npm/package.json` 与 `@limecloud/lime-cli` 发布示例。 +- `CREAOAI` 相关 research、roadmap 与 exec plan 已收口为 `Skill Forge` 命名,并同步导航、路线图、执行计划和治理文档,减少旧命名与 current 主线并存。 +- 本版继续坚持 current-first:capability draft、registered skill、runtime binding、Query Loop metadata、runtime enable、Evidence Pack、Knowledge 与 Layered Design 都回到仓库内单一事实源,不新增 legacy / compat 平行执行入口。 ### 用户可见更新 -#### 1. Workspace Skill Runtime Binding +#### 1. Skill Forge 与能力沉淀闭环 -- 新增 workspace skill binding readiness 投影,Skills 工作台可区分已注册、可手动启用、缺少输入或仍需治理的 skill。 -- Chat request metadata 增加 workspace skill bindings 规划上下文,让 Query Loop 能看到当前 workspace 内可用能力,但不会自动打开执行权限。 -- Runtime enable 只在当前 session scope 内显式启用 ready binding,并把 SkillTool 裁剪到 allowlist,避免 marketplace、scheduler 或旧平行命令绕过授权边界。 -- Skills / Capability Draft UI 补充 automation draft、agent envelope draft 与 registered skill 状态回归,减少“已注册”和“可执行”之间的语义混淆。 +- 新增并落地 `Skill Forge` 研究、路线图、架构图与产品原型入口,替换旧 `docs/research/creaoai` 与 `docs/roadmap/creaoai` 命名。 +- Capability Draft 主线从 authoring、verification、registration、registered discovery、runtime binding、Query Loop metadata、runtime enable 延伸到 managed agent envelope 与 prompt-to-artifact smoke。 +- Skills 工作台与 Workspace Registered Skills 面板展示更完整的 registered skill provenance、binding readiness、Agent envelope draft、automation draft、approval request 与 session gate 状态。 +- “本回合启用”继续只走 `agent_runtime_submit_turn` metadata + SkillTool allowlist,不创建 marketplace、scheduler 或平行 runtime command。 +- Managed Job / Agent Envelope 草案只在 evidence 与 owner audit 满足条件时进入可转化语义,避免把“已注册 / 已发现 / 已校验”误读成“已自动执行”。 -#### 2. AI 图层化设计与导出 +#### 2. 只读 HTTP/API 能力草案 -- 图层化设计主链继续完善文档、artifact、flat image、extraction、zip export 与 image task 写回能力。 -- Design Canvas 与 Layered Design Project API 增加稳定回归,覆盖图层文档编辑、导出、扁平化与图片任务关联。 -- 新增 layered design Tauri command 入口,前端、mock 与项目 artifact 消费方继续围绕 `LayeredDesignDocument` 这个事实源收敛。 +- Capability Draft verification 增加只读 HTTP/API gate:fixture input、fixture 文件、expected output、dry-run 入口、expected-output binding、offline dry-run、no-credentials、session authorization policy、credential reference 与 execution preflight。 +- 新增只读 HTTP/API authoring 模板与 smoke:`scripts/lib/readonly-http-api-draft-template.mjs`、`scripts/readonly-http-api-smoke.mjs`,统一正向样例和负向 gate 样例。 +- 注册摘要新增 `verification_gates` 与 `approval_requests`,把 passed preflight provenance 投影到 registered discovery 与 Workspace 面板,而不是发起真实 HTTP。 +- Approval artifact 新增 consumption gate、credential resolver、consumption input schema、session input intake、submission contract、dry preflight plan 与 controlled GET preflight。 +- 新增 session 输入提交与受控 GET 执行命令:`capability_draft_submit_approval_session_inputs`、`capability_draft_execute_controlled_get`;受控 GET 仅允许一次性 session 输入、GET 方法、非敏感 evidence 与 request / response hash。 +- loopback / localhost 受控 GET 测试绕过系统代理,避免本地 fixture 被代理环境污染。 -#### 3. Agent、Memory 与工作区体验 +#### 3. Prompt-to-Artifact 与证据闭环 -- Agent Chat、MessageList、Harness 状态、runtime review decision、thread grouping 与 workspace scene runtime 继续补稳定回归。 -- Memory 页面完成大幅整理,任务建议、inspiration projection 与工作区入口更接近长期使用场景。 -- Scene Apps、Knowledge、Settings、Onboarding 与 Sidebar 的主路径继续补齐状态、导航和测试断言,降低 GUI 启动与页面切换漂移。 -- 增加 startup layout / diagnostics 工具与 smoke 脚本,用于定位启动布局和页面可见性问题。 +- 新增 `scripts/prompt-to-artifact-smoke.mjs`,通过 DevBridge 串联 `create -> verify -> register -> list_registered_skills -> list_workspace_skill_bindings`,输出结构化 smoke summary。 +- Prompt-to-Artifact smoke 记录结构化样例证据,明确 demo / smoke / evidence 不扩展 P4 runtime,也不打开 scheduler、queue 或 Marketplace。 +- Evidence Pack completion audit 纳入受控 GET evidence 计数、执行状态分布、owner run、Workspace Skill ToolCall 与 artifact evidence;单一成功 run 不再被当成 completed。 +- Runtime evidence summary、`runtime.json`、`artifacts.json`、`summary.md` 与前端 normalizer 消费同一份 completion audit 结构。 + +#### 4. Agent Runtime、聊天与执行可靠性 + +- Agent Chat 补齐 session state、history、timeline、thread reliability、stream runtime handler、text delta controller、action request A2UI、internal artifact visibility 与 task runtime 回归。 +- 新增 `runtimeActionConfirmation` 与更稳定的 runtime action / permission confirmation 展示,避免把被拒绝的权限确认误写成成功证据。 +- Agent thread timeline、reliability panel、ChatSidebar、Inputbar runtime status line 与 MessageList 对排队任务、内部 artifact、action request 和线程读模型状态的展示更一致。 +- Execution run command、agent run DAO、execution tracker 与 runtime evidence service 补齐 owner metadata、status history 和 review / analysis handoff 证据链。 +- `agent_runtime_export_evidence_pack`、analysis handoff、review decision template、review decision save 与 replay case 的前端 API 回归继续走统一 `agent_runtime_*` 命令面。 + +#### 5. Knowledge、Memory 与工作区页面 + +- 新增 `docs/roadmap/knowledge/prd-v2.md` 与可视化图,明确 Knowledge v2 采用 Skills-first、persona / data 双族、Builder Skill、KnowledgePack resolver 与 context run 证据链。 +- 新增 `docs/knowledge/skills/personal-ip-knowledge-builder` 内置 Builder Skill 包,包含 `SKILL.md`、OpenAI agent 配置、个人 IP 知识骨架、访谈问题、模板、质量清单与 `docx_to_markdown.py` 转换脚本。 +- Knowledge Rust crate 与前端 API 扩展 pack metadata、primary document、compile run、runtime mode、fenced context、source anchors、context resolver warning 与 context run validation。 +- Knowledge GUI smoke 与 DevBridge mock 对齐 `knowledge_*` current 命令,页面回归覆盖 pack label、visibility 与默认工作区准备态。 +- Memory 页面更新任务建议、灵感投影、工作区入口和状态文案;Scene Apps 页面、详情、运行列表、scorecard、governance 与 project pack runtime 面板做了大范围结构整理和回归。 +- Sidebar、Skills Workspace、Workspace Canvas 与 Scene Apps 测试补齐导航、页面状态和主路径可见性断言。 + +#### 6. AI 图层化设计与 Design Canvas + +- Layered Design 新增 structured analyzer、native analysis API、model slot config/runtime/transport、provider capability gate 与 worker-first analyzer 组合能力。 +- 新增 subject matting、clean plate、text OCR、structured analyzer worker、worker client、heuristic worker seam 与 deterministic fallback,支持 mask、clean plate、TextLayer 与候选层质量评估。 +- Design Canvas 增加扁平图拆层、候选确认、extraction quality、PSD / zip export、artifact 写回、worker 状态、model slot readiness 与 native analyzer fallback 的可见主路径。 +- Tauri `layered_design_*` 命令、前端 `layeredDesignAnalysis` API、browser mock、`DesignCanvas.test.tsx` 与 `design-canvas-smoke` 同步更新,减少 UI、mock 与 Rust command 漂移。 +- `src-tauri/Cargo.toml` / `Cargo.lock` 同步 `image` 相关依赖,用于图层分析与导出链路。 ### 开发者与治理更新 -#### 1. 命令边界与 contract +#### 1. 命令边界、Mock 与 Contract -- 新增并同步 `agent_runtime_list_workspace_skill_bindings` 相关命令与 runtime schema:前端 API、generated manifest、Rust 注册、DevBridge dispatcher、治理目录册、`mockPriorityCommands` 与默认 mock 保持一致。 -- 新增 runtime skill binding service 与 prompt projection 测试,明确 readiness metadata 只读、runtime enable 显式、SkillTool gate allowlist 三个边界。 -- `npm run test:contracts` 继续覆盖 agent runtime command manifest、command catalog、harness contract、modality contract 与 cleanup report,防止命令面漂移。 +- Capability Draft、Agent Runtime、Knowledge、Layered Design、DevBridge dispatcher、`mockPriorityCommands`、`defaultMocks` 与 `agentCommandCatalog` 按本轮新增命令和返回结构同步。 +- `src/lib/api/capabilityDrafts.ts` 扩展大量 snake_case / camelCase normalizer,覆盖 verification evidence、approval requests、session input、dry preflight、controlled GET preflight 与执行结果。 +- `src/lib/tauri-mock/core.ts` 和相关测试对齐无后端 GUI 预览,避免浏览器模式把未满足 gate 的能力显示为假通过。 +- `src/lib/base-setup` 的 service skill catalog projection / seeded package / adapter 更新 Skill Forge 与 Service Skill 口径。 -#### 2. 路线图与执行计划 +#### 2. 质量脚本与发布管线 -- 新增 CREAOAI P3C runtime binding、P3D query loop metadata、P3E tool runtime authorization、P4 managed agent envelope 与 completion audit 执行计划。 -- CreoAI research / roadmap 文档更新编码代理层、工具编排、原型与架构拆解,保持 repo 内 artifact 作为唯一记录系统。 -- Warp 多模态 runtime contract 文档继续同步 runtime profile、permission state 与 evidence/replay 阻断事实。 +- `scripts/check-app-version-consistency.mjs` 已把 `packages/lime-cli-npm/package.json` 纳入版本一致性检查,防止 npm wrapper 版本再次落后于应用版本。 +- `scripts/quality-task-planner.mjs` 把 npm wrapper package 纳入 integrity 文件;版本、配置或依赖变化会触发对应本地质量任务。 +- `scripts/run-vitest-smart.mjs`、GUI smoke 脚本、Knowledge smoke、Agent runtime tool surface smoke 与 Design Canvas smoke 更新,覆盖本轮新增 GUI / command 风险。 +- `AGENTS.md`、`docs/aiprompts/commands.md`、`docs/aiprompts/quality-workflow.md`、`docs/aiprompts/skill-standard.md` 与文档索引同步 Skill Forge、只读 HTTP/API、Knowledge v2 和 Layered Design 的 current 边界。 -#### 3. Release 管线 - -- 修复 release 构建中的 Vite manual chunk 旧入口引用,`useAgentChatUnified` 现在回到现役 hooks barrel 入口,并移除已不存在的 `immer` 显式 chunk 入口。 -- 根包显式声明 GUI smoke 所需的 `playwright` 依赖,并同步 npm / pnpm 锁文件,避免 CI 干净安装后知识库 GUI 冒烟脚本缺包。 - -### 已知说明 +### 已知边界 - Workspace skill binding readiness 仍不等于自动注入 tool surface;只有显式 runtime enable 且通过 allowlist 的 binding 才能进入当前 session 的 SkillTool gate。 -- AI 图层化设计仍以本地图层文档、导出和 artifact 写回为主,不声明完整 PSD / mask / inpaint provider adapter 能力。 +- 只读 HTTP/API 草案仍是受控能力:verification / registration / approval artifact / session input / controlled GET evidence 不保存 endpoint、token 或 response preview,也不代表技能已进入自动运行面。 +- Session credential resolver 只声明 session scope 与引用边界,不读取、不存储、不注入 secret material。 +- AI 图层化设计仍以本地图层文档、worker 处理、候选层复核、导出和 artifact 写回为主;provider-backed PSD / mask / inpaint 能力仍受 model slot readiness 与 capability gate 约束。 ### 校验状态 -- 本次版本准备已完成: +- 已完成校验: - `npm run verify:app-version` - `cargo fmt --manifest-path "src-tauri/Cargo.toml" --all` - - `CARGO_TARGET_DIR="/tmp/lime-v1.29.0-clippy-target" cargo clippy --manifest-path "src-tauri/Cargo.toml"` + - `npm run lint:rust` + - `cargo test --manifest-path "src-tauri/Cargo.toml"` - `npm run lint` - `npm test` + - `npm run test:contracts` + - `npm run verify:local` + - `git diff --check` - 结果说明: - - 版本一致性检查通过:`1.29.0`。 + - 版本一致性检查通过:`1.30.0`,包含 npm wrapper 版本一致性。 - Rust fmt 通过。 - - Rust clippy 通过。 - - 前端 lint 通过。 - - 前端 Vitest smart suite 49 批通过。 - - 标准 Rust `cargo test --manifest-path "src-tauri/Cargo.toml"` 未完成:当前磁盘空间不足,构建 `src-tauri/target/debug/deps/liblime_lib.a` 时报 `No space left on device (os error 28)`;该结果不是测试断言失败。 + - Rust clippy 通过;当前仍有 `lime-knowledge` 的 `clippy::too_many_arguments` 既有警告,但脚本退出码为 0。 + - Rust 测试通过:`1273` 个 lib 测试通过,`deepseek_reasoner_output_schema_runtime` 2 个集成测试通过,2 个真实联网测试按环境变量门禁保持 ignored。 + - 前端 lint、typecheck 与 Vitest smart suite 通过,`npm test` 共 51 批通过。 + - 命令契约、Harness 契约、modality runtime contract 与 cleanup report contract 通过。 + - `npm run verify:gui-smoke` 通过:复用 headless Tauri / DevBridge,覆盖 workspace ready、browser runtime、site adapters、service skill entry、runtime tool surface、Knowledge GUI 与 Design Canvas smoke。 --- -**完整变更**: `v1.28.0` -> `v1.29.0` +**完整变更**: `v1.29.0` -> `v1.30.0` diff --git a/docs/README.md b/docs/README.md index 97abb6ab0..884005c6b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -6,6 +6,7 @@ - 普通创作者:`content/` 当前处于 LimeNext V2 重建期,只保留少量进阶页与法律说明 - 开发者与维护者:阅读 `aiprompts/`、`develop/`、`tech/`、`tests/` 等工程文档 +- 仓库级 Agent 协作方式与硬约束:以根目录 `../AGENTS.md` 为入口 文档站基于 Nuxt Content 构建。 @@ -46,15 +47,15 @@ - `develop/scheduler-task-governance-p1.md`:调度任务治理 P1(连续失败、自动停用、冷却恢复) - `aiprompts/skill-standard.md`:Skills 包标准、运行时投影与 current/compat 边界总文档 - `roadmap/lime-skills-standardization-roadmap.md`:Skills 标准化 supporting 收口计划,主要保留迁移边界与剩余差距 -- `research/creaoai/README.md`:CreoAI / Tool-Maker Agent 研究入口,拆解能力生成、验证、注册与长期运行业务的外部范式 +- `research/skill-forge/README.md`:Skill Forge / Tool-Maker Agent 研究入口,拆解能力生成、验证、注册与长期运行业务的外部范式 - `research/pi-mono-coding-agent/README.md`:pi-mono Coding Agent 本地调研,提炼 `AgentSession` 分层、工具 allowlist、可插拔工具后端、事件与测试 harness 对 Lime Capability Authoring Agent 的参考边界 - `research/codex-goal/README.md`:Codex `/goal` 研究入口,独立记录 persistent objective / idle continuation turn / completion audit 模式 - `research/codex-goal/diagrams.md`:Codex `/goal` Thread Goal Loop 图纸,包含架构图、流程图、时序图、状态机和最小心智原型 - `research/ribbi/README.md`:Ribbi 研究总入口,作为后续 LimeNext V2 的外部对照事实源 - `research/ai-layered-design/README.md`:AI 图层化设计研究入口,拆解 Lovart 类可编辑图层、分割、抠图、背景修补与 Canvas 工程范式 -- `roadmap/creaoai/README.md`:CreoAI 启发下的 Skill Forge / workspace-local generated skill 路线图 -- `roadmap/creaoai/prototype.md`:Skill Forge / generated capability / verification gate / workspace-local skill 的产品原型图 -- `roadmap/creaoai/architecture-review.md`:CreoAI / Coding Agent 方案实现前 review gate,列出 draft store、verification、registration、evidence、安全边界缺口 +- `roadmap/skill-forge/README.md`:外部 Agent 访谈启发下的 Skill Forge / workspace-local generated skill 路线图 +- `roadmap/skill-forge/prototype.md`:Skill Forge / generated capability / verification gate / workspace-local skill 的产品原型图 +- `roadmap/skill-forge/architecture-review.md`:Skill Forge / Coding Agent 方案实现前 review gate,列出 draft store、verification、registration、evidence、安全边界缺口 - `roadmap/managed-objective/README.md`:Managed Objective 路线图,把 thread goal loop 启发收敛为 Lime 的跨 turn 目标推进控制层 - `roadmap/managed-objective/prototype.md`:Managed Objective 在 Workspace、Task Center、Audit Drawer 和创建流程中的产品原型图 - `roadmap/ai-layered-design/README.md`:AI 图层化设计路线图,把图片生成升级为可编辑的多图层设计工程输出 diff --git a/docs/aiprompts/README.md b/docs/aiprompts/README.md index 18309d5aa..d18636b91 100644 --- a/docs/aiprompts/README.md +++ b/docs/aiprompts/README.md @@ -66,7 +66,7 @@ - **改 turn 提交 / prompt 组包 / queue / compaction / evidence 主链**:先读 `query-loop.md` - **改 subagent / automation / execution tracker / scheduler taxonomy**:先读 `task-agent-taxonomy.md` - **讨论 `/goal`、Managed Objective 或跨 turn 目标续跑**:先读 `task-agent-taxonomy.md` 与 `query-loop.md`,再读 `../research/codex-goal/README.md` 与 `../roadmap/managed-objective/README.md` -- **讨论 Coding Agent、Skill Forge 或能力生成 draft**:先读 `query-loop.md` 与 `skill-standard.md`,再读 `../research/pi-mono-coding-agent/README.md` 与 `../roadmap/creaoai/coding-agent-layer.md` +- **讨论 Coding Agent、Skill Forge 或能力生成 draft**:先读 `query-loop.md` 与 `skill-standard.md`,再读 `../research/pi-mono-coding-agent/README.md` 与 `../roadmap/skill-forge/coding-agent-layer.md` - **改 channels / browser connector / DevBridge / OpenClaw remote runtime**:先读 `remote-runtime.md` - **改记忆来源链 / working memory / durable memory / Team Memory / compaction**:先读 `memory-compaction.md` - **改 FileArtifact / artifact sidecar / versions / file checkpoint / evidence 中的文件快照**:先读 `persistence-map.md` diff --git a/docs/aiprompts/commands.md b/docs/aiprompts/commands.md index 851ea3280..f8097854a 100644 --- a/docs/aiprompts/commands.md +++ b/docs/aiprompts/commands.md @@ -86,6 +86,14 @@ AI 图层化设计工程目录落盘继续走 current `LayeredDesignDocument` 当 `export-manifest.json` 中存在 `source=reference` 且 `originalSrc` 为 `http/https` 的远程图片资产时,`save_layered_design_project_export` 可以在同一条 current 命令内把它们持久化缓存到 `assets/`,并把 manifest / PSD-like projection 更新为 `source=file + filename + originalSrc`。`read_layered_design_project_export` 读回时则优先从这些缓存文件水合 `design.json` 返回给前端,确保 `DesignCanvas` 重新打开工程时继续得到可显示、可编辑的图片层,而不是再次依赖远程 URL 在线可达。 +AI 图层化设计扁平图 OCR 分析同样继续走 current `LayeredDesignDocument.extraction` 主链。当前前端入口为 `src/lib/api/layeredDesignAnalysis.ts`,统一承接: + +- `recognize_layered_design_text` +- `analyze_layered_design_flat_image` + +`recognize_layered_design_text` 只服务 `analyzeLayeredDesignFlatImage` 的 OCR provider seam,把 native OCR 结果投影成可编辑 `TextLayer` 候选;非支持平台、非 `data:image/*;base64` 来源或无结果必须返回 unsupported/fallback,不应让拆层任务整体失败。 +`analyze_layered_design_flat_image` 只服务 structured analyzer provider seam,把 native / Tauri 侧的 image / mask / clean plate 结构化结果投影回同一份 `LayeredDesignDocument.extraction`;不支持的来源必须返回 unsupported/fallback,不应绕过 `canvas:design -> DesignCanvas` 主链。它们都不是 provider adapter、不是旧 poster 协议,也不应回流 `poster_generate / canvas:poster / ImageTaskViewer`。 + 命令目录与输入补全链路同样需要单一事实源。当前前端主入口为 `src/lib/api/skillCatalog.ts`,统一承接: - `bootstrap.skillCatalog` @@ -138,7 +146,7 @@ AI 图层化设计工程目录落盘继续走 current `LayeredDesignDocument` - `fallbackStrategy` - 聊天结果沉淀为技能时,只能继续扩这组说明型字段,不要再平行发明第二套“技能草稿协议” -CreoAI Capability Draft 命令链也必须停留在独立的生成 / 验证 / 注册边界: +Skill Forge Capability Draft 命令链也必须停留在独立的生成 / 验证 / 注册边界: - 前端统一经由 `src/lib/api/capabilityDrafts.ts` 承接: - `capability_draft_create` @@ -146,13 +154,17 @@ CreoAI Capability Draft 命令链也必须停留在独立的生成 / 验证 / - `capability_draft_get` - `capability_draft_verify` - `capability_draft_register` -- `capability_draft_list_registered_skills` + - `capability_draft_list_registered_skills` + - `capability_draft_submit_approval_session_inputs` + - `capability_draft_execute_controlled_get` - `capability_draft_create/list/get/verify/register/list_registered_skills` 只服务 `Capability Draft -> Workspace-local Skill package -> registered discovery` 的事实链,不是 runtime 执行入口 +- `capability_draft_submit_approval_session_inputs` 只做 session-scoped approval 输入校验;`capability_draft_execute_controlled_get` 只做一次性受控 GET 门禁并返回当前命令 evidence,正向 / `request_failed` 只落非敏感 evidence artifact,不保存 endpoint/token/response preview、不进入 scheduler 或默认 tool surface - `capability_draft_register` 只允许把 `verified_pending_registration` 草案复制到当前 `workspaceRoot/.agents/skills`,并记录来源、verification report 与权限摘要;它不得调用 Skill reload、不得修改 seeded skill、不得把能力直接放进默认 tool surface - `capability_draft_list_registered_skills` 只能显式按 `workspaceRoot` 读取当前项目 `.agents/skills` 中带 `.lime/registration.json` 的 P3A 注册能力;它只做 catalog discovery / provenance projection,不得把能力合并进默认已安装方法列表、不得触发 runtime binding、不得展示运行或自动化入口 +- `agent_runtime_export_evidence_pack` 可以按当前 session 消费 `.lime/capability-drafts/controlled-get-evidence/*.json` 的非敏感摘要,但该摘要只用于 evidence pack 可读性,不代表 capability draft 已进入 Query Loop、runtime、scheduler 或 default tool surface - 注册后的执行仍必须回到 `agent_runtime_submit_turn -> Query Loop -> tool_runtime -> artifact/evidence` 主链,不能在 Capability Draft 命令里新增平行运行、调度或外部写协议 -CreoAI P3C runtime binding 第一刀必须回到 `agent_runtime_*` 主链: +Skill Forge P3C runtime binding 第一刀必须回到 `agent_runtime_*` 主链: - 当前前端入口为 `src/lib/api/agentRuntime/inventoryClient.ts` 中的 `listWorkspaceSkillBindings` - 当前 Tauri 命令为 `agent_runtime_list_workspace_skill_bindings` @@ -161,7 +173,7 @@ CreoAI P3C runtime binding 第一刀必须回到 `agent_runtime_*` 主链: - 它可以说明哪些 registered skill 已经具备后续接入候选资格,但真正执行仍只能通过后续 `agent_runtime_submit_turn -> Query Loop -> tool_runtime -> artifact/evidence` 完成 - 不得把这类 runtime binding 状态继续塞回 `capability_draft_*` 命令族;`capability_draft_*` 只到 generation / verification / registration / discovery -CreoAI P3D Query Loop metadata 第一刀继续走 `agent_runtime_submit_turn`,不是新增命令面: +Skill Forge P3D Query Loop metadata 第一刀继续走 `agent_runtime_submit_turn`,不是新增命令面: - 当前 metadata contract 为 `request_metadata.harness.workspace_skill_bindings`,兼容读取 `workspaceSkillBindings` - 前端裁剪入口为 `src/components/agent/chat/utils/workspaceSkillBindingsMetadata.ts`;它只输出 snake_case metadata fragment,不写入 `allow_model_skills` @@ -170,7 +182,7 @@ CreoAI P3D Query Loop metadata 第一刀继续走 `agent_runtime_submit_turn`, - 当 `query_loop_visible=false`、`tool_runtime_visible=false` 或 `launch_enabled=false` 时,模型不得声称已运行、不得调用未授权 Skill、不得创建 automation / scheduler / job - P3D 不注入 `SkillTool` registry,不改变 `agent_runtime_submit_turn` 的默认 tool surface;真正执行仍必须等后续 `tool_runtime` 授权裁剪和 session 显式 enable -CreoAI P3E tool_runtime authorization 第一刀仍继续走 `agent_runtime_submit_turn`,不是新增命令面: +Skill Forge P3E tool_runtime authorization 第一刀仍继续走 `agent_runtime_submit_turn`,不是新增命令面: - 当前 enable metadata contract 为 `request_metadata.harness.workspace_skill_runtime_enable`,兼容读取 `workspaceSkillRuntimeEnable` - 前端裁剪入口继续收在 `src/components/agent/chat/utils/workspaceSkillBindingsMetadata.ts` 与 `buildHarnessRequestMetadata`;该 metadata 输出 `source=manual_session_enable`、`approval=manual`、`workspace_root` 和 ready binding 列表,但不写入 `allow_model_skills` diff --git a/docs/aiprompts/quality-workflow.md b/docs/aiprompts/quality-workflow.md index a3b0b78d7..dbbdd8880 100644 --- a/docs/aiprompts/quality-workflow.md +++ b/docs/aiprompts/quality-workflow.md @@ -43,13 +43,37 @@ 执行时额外遵守: 1. 校验前先确认本轮改动对应路线图哪一项 -2. 如果本轮改动只是清理 dead surface、补 README 或局部整理,但没有直接推进主链,不能把“校验通过”当作完成目标 -3. 汇报时必须同时给出: +2. 选择下一刀前先按“对整体目标完成度的增量”排序,优先补直接影响可用闭环的主缺口;协议 polish、错误分类、额外 seam、边缘校验、文案润色、内部抽象等梢枝末节,只有在阻塞主路径、会造成假入口/假配置,或用户明确要求时才做 +3. 如果本轮改动只是清理 dead surface、补 README、局部整理或低杠杆细节,但没有直接推进主链,不能把“校验通过”当作完成目标 +4. 汇报时必须同时给出: - 本轮改动对应的路线图节点 - 本轮校验覆盖了哪条主线风险 - 当前距离该路线图阶段完成还差什么 -4. 用户问“完成了么”时,先回答主线目标是否已经达到可交付门槛;额外校验、顺手清理、可选优化单独列出,不要反向覆盖主线结论 -5. 校验的上限是证明当前主线可交付;一旦已经覆盖本轮真实风险,就不要因为还有更重的检查可跑而无限追加验证 +5. 用户问“完成了么”时,先回答主线目标是否已经达到可交付门槛;额外校验、顺手清理、可选优化必须单独列出,不要反向覆盖主线结论 +6. 校验的上限是证明当前主线可交付;一旦已经覆盖本轮真实风险,就不要因为还有更重的检查可跑而无限追加验证 + +## 开发任务收口反馈 + +非纯问答的开发任务结束时,最终回复必须给出面向开发主线的完成度反馈,而不只是列文件和测试。 + +默认包含: + +1. `本轮完成度:X%`,并用一句话说明百分比依据 +2. 本轮目标是否完成,以及落在哪条 current 主链 +3. 实际完成了什么,哪些事实源或边界已同步 +4. 实际执行了哪些验证;未执行的高风险验证要说明原因 +5. 还剩什么未完成或仍不应宣称完成 +6. 下一刀最该做什么 + +如果任务绑定路线图、执行计划、多阶段迁移或用户连续要求“继续主线”,还必须额外给出完成度判断: + +- 区分 `本轮完成度` 和 `整体目标完成度` +- 整体百分比必须说明口径,例如工程闭环、MVP、完整产品目标 +- 如果无法精确量化,给区间或估算值,但必须说明依据,不能省略百分比 +- 剩余项按影响主线交付的优先级排序,避免把可选优化和主线缺口混在一起 +- 简单单文件修复可以压缩成 2-3 句;不要为了格式而写长报告 + +该反馈只适用于开发任务;普通解释、检索、问答或无需改仓库的讨论不强制输出完成度百分比。只要发生代码、配置、脚本、测试或工程文档修改,就视为开发任务,最终回复必须给本轮完成度百分比。 ## 执行硬规则 @@ -91,13 +115,13 @@ 如果本轮涉及 `create_skill_scaffold_for_app`、`SkillsPage / SkillScaffoldDialog`,或“聊天结果 -> Skill 脚手架”沉淀闭环,还要同步检查前端网关、Rust 模板、DevBridge 分发与默认 mock 是否仍保持同一条主链;若新增了结构化骨架字段,至少要确认 `何时使用 / 输入 / 执行步骤 / 输出 / 失败回退` 能真实落进生成后的 `SKILL.md`。 -如果本轮涉及 `capability_draft_create/list/get/verify/register/list_registered_skills`,还要同步检查 `src/lib/api/capabilityDrafts.ts`、`capability_draft_cmd`、`capability_draft_service`、DevBridge dispatcher、治理目录册、`mockPriorityCommands` 与 `defaultMocks`;注册命令只能证明 workspace-local Agent Skill 包已落盘,registered discovery 只能证明当前 workspace 可发现带 provenance 的 Skill 包,不能把“已注册 / 已发现”当成“已进入 tool surface / 可自动运行”。最低校验至少包含 Rust capability draft 定向测试、前端 API / UI 回归、`npm run test:contracts`;若 Skills 工作台可见行为变化,再补 `npm run verify:gui-smoke`。 +如果本轮涉及 `capability_draft_create/list/get/verify/register/list_registered_skills/submit_approval_session_inputs/execute_controlled_get`,还要同步检查 `src/lib/api/capabilityDrafts.ts`、`capability_draft_cmd`、`capability_draft_service`、DevBridge dispatcher、治理目录册、`mockPriorityCommands` 与 `defaultMocks`;注册命令只能证明 workspace-local Agent Skill 包已落盘,registered discovery 只能证明当前 workspace 可发现带 provenance 的 Skill 包,session 输入命令只能证明一次性授权输入有效,受控 GET 命令只能返回当前命令 evidence,正向 / `request_failed` 只能落非敏感 evidence artifact,不能保存 endpoint/token/response preview,不能把“已注册 / 已发现 / 已校验 / 已执行一次 GET”当成“已进入 tool surface / 可自动运行”。最低校验至少包含 Rust capability draft 定向测试、前端 API / UI 回归、`npm run test:contracts`;若 Skills 工作台可见行为变化,再补 `npm run verify:gui-smoke`。 如果本轮涉及 `agent_runtime_list_workspace_skill_bindings`,还要同步检查 `src/lib/api/agentRuntime/inventoryClient.ts`、`src/lib/governance/agentRuntimeCommandSchema.json`、generated runtime command manifest、Rust `aster_agent_cmd` 注册、DevBridge dispatcher、治理目录册、`mockPriorityCommands` 与 `defaultMocks`;该命令只表示 P3B registered skill 的 runtime binding readiness projection,不能把 `ready_for_manual_enable` 当成“已注入 Query Loop / 已进入 SkillTool / 可自动执行”。最低校验至少包含 Rust runtime binding 定向测试、前端 API / UI 回归、`npm run generate:agent-runtime-clients` 或 `npm run check:agent-runtime-clients`、`npm run test:contracts`;若 Skills 工作台可见行为变化,再补 `npm run verify:gui-smoke`。 如果本轮涉及 `request_metadata.harness.workspace_skill_bindings` / `workspaceSkillBindings` 的 Query Loop metadata 投影,还要同步检查 `src-tauri/src/commands/aster_agent_cmd/workspace_skill_binding_prompt.rs`、`src-tauri/crates/agent/src/turn_input_envelope.rs` 的 prompt stage contract、`src/components/agent/chat/utils/workspaceSkillBindingsMetadata.ts` 与 `buildHarnessRequestMetadata` 的裁剪边界;该 metadata 只表示 P3C readiness 的只读规划上下文,不能自动打开 `allow_model_skills`、不能注入 `SkillTool` registry、不能改变默认 tool surface。最低校验至少包含 Rust prompt 投影定向测试、前端 metadata builder 单测和 `npm run typecheck`;若同时改了 runtime command schema 或 command manifest,再补 `npm run test:contracts`。 -如果本轮涉及 `request_metadata.harness.workspace_skill_runtime_enable` / `workspaceSkillRuntimeEnable` 的 CREAO P3E runtime enable,还要同步检查 `src-tauri/src/services/runtime_skill_binding_service.rs`、`src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs`、`src-tauri/src/commands/aster_agent_cmd/workspace_skill_binding_prompt.rs`、`src-tauri/crates/agent/src/tools/skill_tool_gate.rs`、`src/components/agent/chat/utils/workspaceSkillBindingsMetadata.ts` 与 `buildHarnessRequestMetadata`;该 metadata 只能在当前 session scope 内显式启用 P3C ready binding,并把 `SkillTool` 裁剪到 allowlist,不能复活 marketplace、scheduler 或绕过 `agent_runtime_submit_turn` 的平行执行命令。最低校验至少包含 Rust runtime binding / SkillTool gate 定向测试、Rust prompt 投影定向测试、前端 metadata builder 单测和 `npm run test:contracts`。 +如果本轮涉及 `request_metadata.harness.workspace_skill_runtime_enable` / `workspaceSkillRuntimeEnable` 的 Skill Forge P3E runtime enable,还要同步检查 `src-tauri/src/services/runtime_skill_binding_service.rs`、`src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs`、`src-tauri/src/commands/aster_agent_cmd/workspace_skill_binding_prompt.rs`、`src-tauri/crates/agent/src/tools/skill_tool_gate.rs`、`src/components/agent/chat/utils/workspaceSkillBindingsMetadata.ts` 与 `buildHarnessRequestMetadata`;该 metadata 只能在当前 session scope 内显式启用 P3C ready binding,并把 `SkillTool` 裁剪到 allowlist,不能复活 marketplace、scheduler 或绕过 `agent_runtime_submit_turn` 的平行执行命令。最低校验至少包含 Rust runtime binding / SkillTool gate 定向测试、Rust prompt 投影定向测试、前端 metadata builder 单测和 `npm run test:contracts`。 如果本轮涉及记忆主链,还要同步检查 `src/lib/api/memoryRuntime.ts`、`src-tauri/src/commands/memory_management_cmd.rs`、`runner.rs`、DevBridge dispatcher 与默认 mock 是否仍保持同一条 current surface;`rules / working / durable / team / compaction` 的产品分层可以在页面上拆开,但底层命令边界仍必须继续收敛到 `memory_runtime_*` 与 `unified_memory_*`。 diff --git a/docs/aiprompts/skill-standard.md b/docs/aiprompts/skill-standard.md index 3be5e635b..35ea574f6 100644 --- a/docs/aiprompts/skill-standard.md +++ b/docs/aiprompts/skill-standard.md @@ -118,7 +118,7 @@ Lime 在工程上必须明确接受这一点: 1. `SKILL.md` 不是 Lime 的最终产品对象。 2. `ServiceSkill` / `Scene` 也不是新的包格式标准。 3. `ServiceSkill` / `Scene` 是 Lime 在 Agent Skills 之上的产品投影层。 -4. CreoAI / Capability Draft 注册只负责把已验证草案复制成 workspace-local Agent Skill 包;它不等同于运行时绑定,也不能绕过 Query Loop 与 `tool_runtime` 直接执行。 +4. Skill Forge / Capability Draft 注册只负责把已验证草案复制成 workspace-local Agent Skill 包;它不等同于运行时绑定,也不能绕过 Query Loop 与 `tool_runtime` 直接执行。 因此,generated skill 的最小安全顺序固定为: diff --git a/docs/exec-plans/README.md b/docs/exec-plans/README.md deleted file mode 100644 index 75cca04d0..000000000 --- a/docs/exec-plans/README.md +++ /dev/null @@ -1,46 +0,0 @@ -# `docs/exec-plans` - -本目录存放会影响开发执行的 versioned artifact:执行计划、进度日志、阻塞记录、迁移清单、技术债追踪。 - -## 放什么 - -- 多轮实现、迁移、治理任务的执行计划 -- 与计划绑定的阶段进度、阻塞项、决策记录 -- 需要持续小额偿还的技术债与退出条件 - -## 命名约定 - -- 专项计划:`-plan.md` -- 进度日志:`-progress.md` -- 常驻追踪:使用固定文件名,例如 `tech-debt-tracker.md` - -## 使用规则 - -1. 计划不是一次性文档,推进状态变化时要同步更新 -2. 会改变实现顺序、范围或回滚策略的决策,必须记录在这里或链接到这里 -3. 清理类工作如果不能直接回挂路线图,应登记到 `tech-debt-tracker.md` -4. 被替代的计划不要悬空,保留跳转说明或归档指针 - -## 关联入口 - -- 路线图主线:`docs/roadmap/` -- 参考运行时主链总计划:`docs/exec-plans/upstream-runtime-alignment-plan.md` -- 参考运行时主链进度日志:`docs/exec-plans/upstream-runtime-alignment-progress.md` -- Provider 模型能力 taxonomy 进度日志:`docs/exec-plans/provider-model-taxonomy-progress.md` -- Lime 多模态运行合同实施计划:`docs/exec-plans/multimodal-runtime-contract-plan.md` -- 云端套餐与支付边界收口计划:`docs/exec-plans/cloud-commerce-user-center-boundary.md` -- `@` 命令本地执行纠偏计划:`docs/exec-plans/at-command-local-execution-alignment-plan.md` -- AI 图层化设计实现计划:`docs/exec-plans/ai-layered-design-implementation-plan.md` -- CreoAI Capability Authoring P1A 执行计划:`docs/exec-plans/creaoai-capability-authoring-p1a-plan.md` -- CreoAI Capability Verification P1B 执行计划:`docs/exec-plans/creaoai-capability-verification-p1b-plan.md` -- CreoAI Capability Registration P3 执行计划:`docs/exec-plans/creaoai-capability-registration-p3-plan.md` -- CreoAI Capability Discovery P3B 执行计划:`docs/exec-plans/creaoai-capability-discovery-p3b-plan.md` -- CreoAI Runtime Binding P3C 执行计划:`docs/exec-plans/creaoai-runtime-binding-p3c-plan.md` -- CreoAI Query Loop Metadata P3D 执行计划:`docs/exec-plans/creaoai-query-loop-metadata-p3d-plan.md` -- CREAO Tool Runtime Authorization P3E 执行计划:`docs/exec-plans/creaoai-tool-runtime-authorization-p3e-plan.md` -- CREAO Managed Execution / Agent Envelope P4 执行计划:`docs/exec-plans/creaoai-managed-agent-envelope-p4-plan.md` -- CREAO Roadmap P0-P4 完成审计:`docs/exec-plans/creaoai-completion-audit.md` -- LimeNext 总实施计划(`legacy current reference`,当前主规划已切到 `docs/roadmap/limenextv2/README.md`):`docs/exec-plans/limenext-plan.md` -- LimeNext 推进日志:`docs/exec-plans/limenext-progress.md` -- 技术债追踪:`docs/exec-plans/tech-debt-tracker.md` -- 模块级实施细节:`docs/aiprompts/README.md` diff --git a/docs/exec-plans/agent-knowledge-implementation-plan.md b/docs/exec-plans/agent-knowledge-implementation-plan.md deleted file mode 100644 index fff0307a2..000000000 --- a/docs/exec-plans/agent-knowledge-implementation-plan.md +++ /dev/null @@ -1,480 +0,0 @@ -# Agent Knowledge 实现执行计划 - -> 状态:Phase 1 current 主链已接通,项目资料能力已回流到现有 Agent 输入框;首页添加、File Manager 添加、输入框使用、项目资料管理与 Agent 结果沉淀均已完成稳定 DevBridge 下的产品 E2E 验收 -> 创建时间:2026-05-01 -> 路线图来源:`docs/roadmap/knowledge/prd.md` -> 当前目标:完成 Markdown-first 项目资料的导入、整理、GUI 管理、Agent 输入框显式使用与运行时受保护上下文注入。 - -## 主目标 - -把 Agent Knowledge 标准接入 Lime 的 current 主链: - -```text -src-tauri/crates/knowledge - -> src-tauri/src/commands/knowledge_cmd.rs - -> src/lib/api/knowledge.ts - -> src/features/knowledge - -> AgentChatWorkspace request metadata - -> Runtime KnowledgePack prompt stage - -> src-tauri/resources/default-skills/knowledge_builder - -> mock / governance / contract validation -``` - -固定事实源: - -**后续知识包能力只允许向 `lime-knowledge + knowledge_* + Knowledge Context Resolver` 收敛;`project_memory_get` 继续只做项目资料附属层,不接管知识包主链。** - -## 范围 - -本轮做: - -1. 独立后端 crate:`src-tauri/crates/knowledge`。 -2. 标准目录:`.lime/knowledge/packs//KNOWLEDGE.md`、`sources/`、`wiki/`、`compiled/`、`runs/`。 -3. Tauri 薄命令:`knowledge_import_source`、`knowledge_compile_pack`、`knowledge_list_packs`、`knowledge_get_pack`、`knowledge_set_default_pack`、`knowledge_resolve_context`。 -4. 前端独立 API 网关:`src/lib/api/knowledge.ts`。 -5. 前端 feature 边界:`src/features/knowledge`。 -6. GUI 页面入口、侧边栏入口、任务中心资料入口。 -7. Runtime 通过 Knowledge Context Resolver 注入受保护 fenced context。 -8. mock、治理目录册、契约检查同步。 -9. 后端 crate 单测、runtime 定向测试和前端回归测试。 - -本轮不做: - -1. 聊天输入框内的细粒度知识包选择器。 -2. 向量库、知识图谱、企业权限、知识包市场。 -3. 把知识包接入 Memory 或 durable memory。 -4. 把 Builder 输出直接写盘并自动覆盖用户已编辑知识资产。 - -## 执行记录 - -### 2026-05-01 - -- 已新增路线图 PRD:`docs/roadmap/knowledge/prd.md`。 -- 已补 `.gitignore` 例外,让该 PRD 可被 Git 跟踪。 -- 已开始 Phase 1 实现。 -- 已根据用户反馈移除新实现与 PRD 中的具体人名样例。 -- 已确定后端知识域必须独立成 `lime-knowledge` crate,Tauri command 只做薄适配。 -- 已创建 `src-tauri/crates/knowledge`,并把知识包文件事实源逻辑迁入该 crate。 -- 已创建前端网关 `src/lib/api/knowledge.ts` 与测试草稿。 -- 已创建前端 feature 入口 `src/features/knowledge/index.ts`。 -- 已同步 Tauri 命令注册、治理目录册、mockPriority 与 default mock 草稿。 -- 已通过 `cargo test -p lime-knowledge`。 -- 已通过 `npm test -- src/lib/api/knowledge.test.ts`。 -- 已通过 `npm run test:contracts`,确认前端调用、Rust 注册、治理目录册与 mock 边界一致。 -- 已通过 `cargo fmt --package lime-knowledge --check`。 -- 已通过 `cargo check -p lime`,确认主 Tauri crate 能集成新 crate 与命令注册。 -- 已通过 `npm run typecheck`。 - -### 2026-05-02 - -- 已新增 `src/features/knowledge/KnowledgePage.tsx`,接通知识包目录、详情、来源导入、编译、默认包设置和运行时视图预览。 -- 已新增 `src/features/knowledge/KnowledgePage.test.tsx`,覆盖目录读取、导入、编译、默认包设置、运行时 context 预览和“去生成”metadata。 -- 已把 `knowledge` 页面加入 `src/types/page.ts`、`src/components/AppPageContent.tsx`、`src/lib/navigation/sidebarNav.ts`、`ChatSidebar` 资料分组和 `AgentChatWorkspace` 工作台跳转。 -- 已确认前端发送链路最终通过 `buildWorkspaceRequestMetadata` 合并 `workspaceRequestMetadataBase` 与 `sendOptions.requestMetadata`,Knowledge 页面传入的 `knowledge_pack` metadata 会进入 runtime request metadata。 -- 已新增 runtime `KnowledgePack` prompt stage:从 `knowledge_pack` / `knowledgePack` metadata 解析 `pack_name/name`、`working_dir/workingDir`、`max_chars/maxChars`,调用 `lime_knowledge::resolve_knowledge_context(...)` 并注入 fenced context。 -- 已将带知识包 metadata 的请求判定为 full runtime,避免 fast chat 短路跳过知识包上下文。 -- 已在 `TurnPromptAugmentationStageKind` 增加 `KnowledgePack`,并用源代码顺序契约锁定 stage 位于 Memory 之后、WebSearch / RequestToolPolicy 之前。 -- 已在聊天输入区增加轻量知识包开关:读取当前工作区默认知识包,用户显式启用后通过 `knowledge_pack` metadata 进入同一 runtime 注入链路。 -- 已新增正式内置 Builder Skill:`src-tauri/resources/default-skills/knowledge_builder/SKILL.md`,用于把来源资料整理为 `KNOWLEDGE.md`、`wiki/`、`compiled/brief.md` 与 `runs/` 草稿。 -- 已把 `knowledge_builder` 注册进默认 Lime Skills 安装链和内置目录白名单。 -- 已在知识库页面补充 “Builder 生成”入口,携带 `knowledge_builder` metadata、项目根目录、pack name 和 pack 类型进入 Agent 自动执行。 -- 已确认新增内容不包含用户要求禁止出现的具体人名样例,禁名扫描无命中。 -- 已通过 `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime-core test_default_lime_skill_directories_include_embedded_defaults --no-default-features`,确认 `knowledge_builder` 已进入默认 Skill 目录事实源。 -- 已通过 `npm run verify:gui-smoke`,覆盖 headless Tauri、DevBridge、workspace-ready、browser-runtime、site adapters、Agent service skill entry 与 runtime tool surface/page smoke。 -- 曾尝试 `CARGO_TARGET_DIR="/tmp/lime-agent-knowledge-target" cargo test --manifest-path "src-tauri/Cargo.toml" -p lime test_default_lime_skill_directories_include_embedded_defaults --no-default-features --features local-sensevoice`,该冷构建在 `sherpa-onnx-sys` 下载预编译库时因 TLS 连接中断失败;已改用 `lime-core` 定向测试覆盖本次 Builder 默认目录注册风险。 -- 已把聊天输入区知识包开关升级为多包选择菜单:workspace runtime 读取当前项目全部非归档知识包,默认选工作区默认包,用户可在输入区切换具体包并继续通过同一 `knowledge_pack` metadata 发送。 -- 已补输入区回归,覆盖菜单切换具体知识包、自动启用知识包上下文和发送 metadata 使用选中包。 -- 已通过 `npm test -- "src/components/agent/chat/components/Inputbar/index.test.tsx"` 与 `npm run typecheck`。 -- 本轮重跑 `npm run verify:gui-smoke` 时,脚本检测到 sqlite 构建缓存缺失并切到独立 target,同时复用已有 headless 链路;等待超过 20 分钟仍未暴露 DevBridge,本轮新启动的 verify 父进程已中断,该次 smoke 不计为通过。上一轮完整 GUI smoke 通过记录仍保留,但多包选择菜单这刀还需要在环境恢复后补跑一次 GUI smoke。 -- 已升级 `knowledge_builder` 到 `lime_version: 1.1.0`,补齐 personal-ip、brand-product、organization-know-how、growth-strategy 与 custom 的类型化 wiki / runtime brief 模板。 -- 已要求 Builder 输出 `runs/quality-report-{yyyyMMdd-HHmmss}.md`,包含 pass / warn / fail 结论、检查表、待确认事实、冲突风险和下一步,避免把无法确认的信息推断成事实。 - -### 2026-05-04 - -- 已补跑 `knowledge_builder` 1.1.0 内容契约检查,确认类型化模板、`compiled/brief.md` 固定结构和 `runs/quality-report-*` 质量报告关键字段存在。 -- 已通过 `cargo fmt --manifest-path "src-tauri/Cargo.toml" --package lime --check`,确认默认 Skill 注册相关 Rust 改动格式正确。 -- 已通过 `CARGO_TARGET_DIR="/tmp/lime-knowledge-resource-target" cargo test --manifest-path "src-tauri/Cargo.toml" -p lime should_embed_social_image_tool_contract_in_default_skill --no-default-features`,避开共享 `src-tauri/target` 占用并确认 `knowledge_builder` 内容随默认 Skill 资源内嵌。 -- 已通过 `npm test -- "src/features/knowledge/KnowledgePage.test.tsx"` 与 `npm test -- "src/components/AppPageContent.test.tsx"`,确认知识库页面与应用页挂载回归仍稳定。 -- 已通过 `npm run typecheck`,确认前端类型边界未被知识库页面、预加载和输入区 metadata 改动破坏。 -- 已通过 `CARGO_HOME="/tmp/lime-gui-smoke-cargo-home" npm run verify:gui-smoke`,复用现有 headless Tauri 环境,覆盖 DevBridge、workspace-ready、browser-runtime、site adapters、Agent service skill entry 与 runtime tool surface/page smoke。 -- 已按普通使用者视角收敛知识库页面文案:用户可见 UI 与“整理资料”自动发送提示不再展示内部目录、Builder/Skill 名称、运行时围栏、token、frontmatter/trust/status 实现细节,改为“导入资料 / 自动整理 / 预览摘要 / 人工确认 / 引用摘要 / 整理记录”。 -- 已同步 `src/features/knowledge/KnowledgePage.test.tsx`,新增负向断言锁定 `.lime/knowledge`、`knowledge_builder`、`compiled/brief.md`、`frontmatter`、`KNOWLEDGE.md`、raw fenced context 与 token 不出现在普通用户页面正文里;内部 metadata 契约测试继续保留。 -- 已同步 `scripts/knowledge-gui-smoke.mjs` 的用户可见断言,把“Builder 入口 / 编译预览”替换为“资料整理入口 / 预览摘要”。 -- 已通过 `npm test -- "src/features/knowledge/KnowledgePage.test.tsx"`。 -- 已通过 `npm run typecheck`。 -- 已运行 `npm run bridge:health -- --timeout-ms 20000`,当前 DevBridge 未监听 `127.0.0.1:3030`,因此本轮知识库 GUI smoke 未执行且不计为通过。 -- 已根据产品化反馈重做知识页主路径:默认入口从“知识包管理台”改为“项目资料助手”,首屏直接支持粘贴资料、选择资料类型、开始整理、查看完成进度、检查确认与用于生成;默认包、待确认和全部资料改为次级信息。 -- 已把手动导入页降级为补充入口,避免继续作为普通用户首屏主路径。 -- 已同步 `src/features/knowledge/KnowledgePage.test.tsx`,覆盖资料助手首屏、粘贴资料后整理、检查确认、用于生成与内部 metadata 契约。 -- 已同步 `scripts/knowledge-gui-smoke.mjs`,知识库 GUI smoke 断言改为资料助手、全部资料、等你确认的资料和当前资料。 -- 已通过 `npm test -- "src/features/knowledge/KnowledgePage.test.tsx"`。 -- 已通过 `npm run typecheck`。 -- 已运行 `npm run bridge:health -- --timeout-ms 20000`,当前 DevBridge 仍未监听 `127.0.0.1:3030`,因此本轮产品化重做后的 GUI smoke 未执行且不计为通过。 - -### 2026-05-05 - -- 已根据用户反馈继续收敛产品主路径:普通用户整理和使用项目资料的入口回到现有 Agent 输入框,不再要求先进入独立知识页。 -- 已将 `src/components/agent/chat/components/Inputbar/components/InputbarComposerSection.tsx` 的资料控件改为输入框主路径常显;已有资料时显示“项目资料”选择与启用,无资料时显示“整理成项目资料”。 -- 已将 `src/components/agent/chat/workspace/useWorkspaceInputbarSceneRuntime.tsx` 接入“整理成项目资料”动作:有输入内容时复用现有 Agent `handleSend` 发送整理请求并携带 `knowledge_builder` metadata;无输入内容时只预填用户可编辑提示;未选择项目时提示先选择项目。 -- 已下线知识页内独立聊天面板:`src/features/knowledge/KnowledgePage.tsx` 不再保留 `chat` 视图、页面内任务输入框、页面内发送按钮、引用原文预览和 token 展示。 -- 已将知识页定位降级为“项目资料管理”:保留全部资料、资料详情、手动导入、确认、设默认、归档、重新整理等管理动作。 -- 已将知识页“用于生成”改为直接回到现有 Agent,并携带 `knowledge_pack` metadata;资料使用不再绕到独立页面内聊天流。 -- 已补齐 `src-tauri/src/dev_bridge/dispatcher/knowledge.rs`,并在 `src-tauri/src/dev_bridge/dispatcher.rs` 注册已有 `knowledge_*` 命令的 DevBridge 分发,解决 GUI smoke 中 `knowledge_import_source` 无分发的问题。 -- 已同步 `scripts/knowledge-gui-smoke.mjs`,把断言从“资料助手 / 页面内聊天”改为“项目资料管理 / 回到 Agent / 手动导入”。 -- 已同步 `src/features/knowledge/KnowledgePage.test.tsx` 与 `src/components/agent/chat/components/Inputbar/index.test.tsx`,锁定普通用户页面不展示开发者细节,并覆盖输入框整理入口、资料 metadata 发送和知识页回到 Agent。 -- 已通过 `npm test -- "src/features/knowledge/KnowledgePage.test.tsx"`。 -- 已通过 `npm test -- "src/components/agent/chat/components/Inputbar/index.test.tsx"`。 -- 已通过 `npm run typecheck`。 -- 已通过 `cargo fmt --manifest-path "src-tauri/Cargo.toml" --package lime --check`。 -- 已通过 `npm run test:contracts`。 -- 已执行禁名扫描,用户要求禁止出现的具体名称无命中。 -- 已执行普通用户路径泄露扫描,新增主路径未再暴露“聊天任务 / 当前资料 / 查看引用 / 资料助手 / Builder 生成”等旧页面语义。 -- 已重跑 `CARGO_HOME="/tmp/lime-gui-smoke-cargo-home" npm run verify:gui-smoke`,本轮进入独立 target 冷构建,已完成依赖下载并编译到主 `lime` crate 收尾阶段,但约 34 分钟仍未进入 GUI smoke 断言;该次临时进程组已中止,最新 GUI smoke 不计为通过。当前未观察到业务断言失败,剩余风险是 GUI 主路径尚未在稳定 headless 环境完成最终冒烟。 -- 已完成知识库真实 GUI E2E 收口: - - 清理检查确认未残留 `knowledge-gui-smoke`、`smoke-knowledge-gui`、`lime-knowledge-e2e-target` 或专用 Chrome profile 进程。 - - 初始 `npm run bridge:health -- --timeout-ms 20000` 失败,确认前端 `1420` 可访问但 DevBridge `3030` 未就绪。 - - 尝试启动 `CARGO_TARGET_DIR="/tmp/lime-knowledge-e2e-target" npm run tauri:dev:headless` 避免共享 target 锁;后续用户原有 `pnpm run tauri dev` 完成启动,`npm run bridge:health -- --timeout-ms 5000` 通过。 - - 通过 `http://127.0.0.1:3030/invoke` 真实调用 `knowledge_import_source`、`knowledge_compile_pack`、`knowledge_update_pack_status`、`knowledge_set_default_pack`,seed 出 `Smoke 默认项目资料` 与 `Smoke 备用项目资料` 两份资料。 - - Playwright 打开 `http://127.0.0.1:1420/`,设置 onboarding 与 `lime.knowledge.working-dir` 后进入“知识库”,验证“项目资料管理 / 当前项目资料库 / 全部项目资料 / 手动导入 / 日常使用入口 / 回到 Agent”可见。 - - E2E 暴露并修复两个阻塞点:`knowledge_*` 被 `mockPriorityCommands` 强制走 mock,导致真实 DevBridge seed 数据无法进 GUI;知识页只把 localStorage 目录写入输入框,未初始化 `workingDir` 状态,导致目录列表不加载。 - - 修复后 Playwright 验证 `knowledge_list_packs` 与 `knowledge_get_pack` 走真实 HTTP Bridge,页面展示两份 seed 资料、默认资料标记与管理概览 `2 份项目资料`。 - - 点击“用于生成”后回到现有 Agent 工作区,页面出现用户消息“请基于当前项目资料生成内容”,并通过真实 `agent_runtime_submit_turn` 自动提交;输入框主路径仍展示“整理成项目资料”,没有回到独立知识页聊天。 - - 本轮控制台与页面快照扫描未发现 `ERROR`、`Failed to load resource`、`ERR_CONNECTION`,也未发现 `knowledge_builder`、`compiled/brief.md`、`.lime/knowledge`、`frontmatter`、`token`、`聊天任务`、`当前资料:`、`查看引用`、`资料助手`、`Builder 生成` 等普通用户主路径泄露。 - - 本轮启动的隔离 target headless Tauri 冷构建已中止并确认无残留;用户原有 DevBridge 仍健康。 -- 已通过 `npm run test:contracts`,确认命令契约、harness 契约和治理生成检查通过。 -- 已通过 `npm test -- "src/lib/dev-bridge/safeInvoke.test.ts" "src/lib/tauri-mock/core.test.ts"`,确认移除 knowledge 优先 mock 后 fallback 与 mock 行为仍稳定。 -- 已通过 `npm test -- "src/features/knowledge/KnowledgePage.test.tsx"`,确认知识页初始化目录与主路径回归稳定。 -- 已通过 `npm run typecheck`。 - - -### 2026-05-05 模块化产品化重构 - -- 已根据用户反馈确认“知识库”应按功能模块设计,而不是继续扩张单页实现。 -- 已将 `src/features/knowledge/KnowledgePage.tsx` 中的状态文案、资料类型、用户可见字段、prompt builder、metadata builder、文件列表、状态标签、状态导轨、资料卡与排障面板拆到 `domain/`、`agent/` 与 `components/` 子模块。 -- 已将输入框内项目资料控件从通用 `InputbarComposerSection.tsx` 拆到 `src/components/agent/chat/components/Inputbar/knowledge/InputbarKnowledgeControl.tsx`,通用输入框只保留组合职责。 -- 已将 Workspace 中的项目资料加载、默认资料选择、启用状态、整理资料 prompt 与资料管理跳转拆到 `src/components/agent/chat/workspace/knowledge/useWorkspaceKnowledgeRuntime.ts`,继续复用现有 Agent 发送链路。 -- 已将普通用户入口文案从“整理成项目资料 / 手动导入 / 高级目录”收敛为“添加项目资料 / 补充导入 / 排障设置”,并在输入框点击“添加项目资料”后先展示说明卡,再由用户明确发送给 Agent 整理。 -- 已在资料管理页增加“已添加资料 / 已整理草稿 / 已确认可用”状态导轨,资料卡主动作按状态区分“继续确认 / 用于生成”。 -- 已移除资料详情里的不可用“编辑资料说明”禁用按钮,避免普通用户看到无效动作。 -- 已更新 `KnowledgePage.test.tsx` 与 `Inputbar/index.test.tsx`,锁定普通首屏不展示“内部标识 / 资料文件名 / 高级:手动指定项目目录”,并覆盖输入框资料整理说明卡。 -- 已更新 `scripts/knowledge-gui-smoke.mjs` 的入口文案断言,跟随“补充导入”新命名。 -- 已通过 `npm test -- "src/features/knowledge/KnowledgePage.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"`。 -- 已通过 `npm run typecheck`。 -- 已通过 `npm run test:contracts`。 -- 已执行 `npm run bridge:health -- --timeout-ms 10000`,初始 DevBridge 就绪。 -- 已执行 `npm run verify:gui-smoke`,workspace-ready、browser-runtime、site-adapters、agent-service-skill-entry、agent-runtime-tool-surface 与 agent-runtime-tool-surface-page 均通过;进入 `smoke:knowledge-gui` 后,`browser_execute_action` 阶段 DevBridge 中途掉线,knowledge GUI smoke 未计为通过。 -- 已单独重跑 `npm run smoke:knowledge-gui -- --app-url http://127.0.0.1:1420/ --health-url http://127.0.0.1:3030/health --invoke-url http://127.0.0.1:3030/invoke --timeout-ms 600000 --interval-ms 1000`,仍在 `wait-knowledge-overview` 后的 browser action 阶段触发 DevBridge 掉线,判断为当前本地 DevBridge / CDP smoke 环境稳定性问题,需要后续先清理 dev 进程和 target lock 再复测。 -- 已用 Playwright MCP 手动打开现有 Lime 页签并进入知识库,确认页面展示 `项目资料管理`、`添加项目资料` 空态、`补充导入`、`排障设置`、状态导轨,普通页面未出现内部标识、资料文件名或内部目录语义;因 DevBridge 已掉线,真实 seed -> 使用资料 -> Agent 自动发送闭环本轮未完成。 -- 已清理残留 `smoke-knowledge-gui` Chrome profile 进程;隔离 target headless 冷构建进度较慢,已中止,避免长时间占用本机资源。 - -### 2026-05-05 模块化产品化闭环收口 - -- 已将 `scripts/knowledge-gui-smoke.mjs` 从 DevBridge CDP `browser_execute_action` 流程改为本地 Playwright persistent context,避免 smoke 自测递归依赖浏览器桥接并把 DevBridge 带掉。 -- 已让 knowledge GUI smoke 使用真实 DevBridge seed,并创建临时 `temporary` workspace;页面进入 Agent 前会等待资料管理页解析出当前项目,确保“用于生成”回到同一现有 Agent 项目上下文。 -- 已将“用于生成”从自动提交改为回到现有 Agent 后预填“请基于当前项目资料生成内容”,并保留 `knowledge_pack` metadata 作为首发 request metadata;这样普通用户可以确认后再发送,不再被突然自动执行打断。 -- 已修正 `AgentChatWorkspace` 无文稿入口下 `initialUserPrompt` 的默认语义:`autoRunInitialPromptOnMount=false` 时只预填,不默认发送;只有显式自动运行入口才自动发送。 -- 已让资料管理页按 `workingDir` 反查项目并记录 `selectedProjectId`,避免从知识页回 Agent 后漂移到默认项目。 -- 已更新 `KnowledgePage.test.tsx`,覆盖 `workingDir -> projectId` 回填、“用于生成”预填意图与 metadata 透传;已更新 `AgentChatPage` 回归,覆盖无文稿入口 initial prompt 不自动发送。 -- 已将 knowledge GUI smoke 的 Agent 断言改为普通用户真实可见的输入框状态:`项目资料:未使用` 与已预填的生成意图,而不是等待首页口号或自动发送结果。 -- 已通过 `npm run smoke:knowledge-gui -- --app-url http://127.0.0.1:1420/ --health-url http://127.0.0.1:3030/health --invoke-url http://127.0.0.1:3030/invoke --timeout-ms 240000 --interval-ms 1000`。 -- 已通过 `npm test -- "src/features/knowledge/KnowledgePage.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/index.test.tsx"`,共 `164` 个相关测试通过。 -- 已通过 `npm run typecheck`。 -- 已通过 `npm run verify:gui-smoke`,覆盖 workspace-ready、browser-runtime、site-adapters、Agent service skill entry、runtime tool surface/page 与 knowledge GUI smoke;knowledge 阶段完成真实 seed、资料管理页、用于生成回 Agent、补充导入入口验证。 -- 已执行 `git diff --check`。 -- 已执行普通用户可见路径泄露扫描,`KnowledgePage.tsx`、knowledge components、Inputbar knowledge control 与 smoke 脚本未出现内部标识、资料文件名、高级目录、`knowledge_builder`、`compiled/brief.md`、`frontmatter` 或 `tokens`。 - -### 2026-05-05 文档架构同步 - -- 已按最新产品判断更新 `docs/roadmap/knowledge/prd.md`:current 入口从单一知识库页面改为 File Manager、输入框资料图标、首页引导和 Agent 输出沉淀四条路径;`@资料` 降级为兼容入口。 -- 已更新 PRD 总体架构图,把 File Manager、输入框资料图标、`@资料` 兼容入口、首页引导、Agent 输出沉淀、导入编排、`lime-knowledge`、资料管理页、现有 Agent 输入框和 Resolver 串成同一闭环。 -- 已更新 PRD 关键时序:从 File Manager / 首页添加资料、通过输入框资料图标使用资料、从生成结果沉淀资料、用户修改后重新整理。 -- 已更新 PRD 前台信息架构、UI 原型、模块边界、Current / Deprecated 分类、Phase 计划和产品验收标准,明确普通用户主路径不暴露 packName、metadata、compiled、token、runtime fence 或本机完整路径。 -- 已新增 `docs/knowledge/README.md`,声明 current 文档事实源,并把 `docs/knowledge/` 下早期方案标为 compat / 参考。 -- 已更新 `.gitignore`,仅放行 `docs/knowledge/README.md` 作为可追踪索引;其余 `docs/knowledge/` 私有样例和早期方案仍默认不纳入版本库。 -- 已给 `docs/knowledge/lime-knowledge-base-construction-blueprint.md`、`docs/knowledge/markdown-first-knowledge-pack-plan.md`、`docs/knowledge/lime-project-knowledge-base-solution.md`、`docs/knowledge/agent-skills-and-knowledge-pack-boundary.md` 增加 compat 状态说明,避免后续继续按旧方案扩张。 - -### 2026-05-05 四入口闭环实现 - -- 已新增 `src/features/knowledge/import/knowledgeSourceImport.ts`,把文件路径与文本资料导入封装为独立前端模块;实现继续复用 `read_file_preview_cmd`、`knowledge_import_source` 与 `knowledge_compile_pack`,不新增后端命令。 -- 已在 File Manager 右键菜单补充“设为项目资料”,并在输入框路径 chip 上提供“设为资料”动作;用户从左侧文件管理器添加文件后,不必理解 packName、metadata 或内部目录即可整理为项目资料。 -- 已将输入框底栏资料图标明确为项目资料主入口;`@资料` 只做兼容打开同一资料中枢,`@沉淀资料` 继续复用现有输入框资料整理动作,不创建独立 Agent 或新聊天面板。 -- 已将首页起手入口从“预填一段资料说明”改为“直接打开输入框资料中枢”,保持首页、输入框资料图标和 `@资料` 兼容入口指向同一浮层。 -- 已在助手消息操作区增加“沉淀为项目资料”,将 Agent 输出直接交给 Workspace knowledge runtime 导入与编译,继续由现有 Agent 工作区承载使用与确认。 -- 已补首页起手入口、输入建议与引导卡:普通用户可以从首页了解“添加 / 确认 / 使用项目资料”,而不是先进入开发者式管理页。 -- 已补稳定回归:File Manager 右键导入、输入框路径 chip 导入、`@资料` / `@沉淀资料` 复用现有输入框动作、消息沉淀、首页入口与 seeded command catalog。 - -### 2026-05-05 真实 E2E 顺滑度复测 - -- 已用 Playwright MCP 复用真实 Lime 页签,刷新 `http://127.0.0.1:1420/` 后重新建立基线:DevBridge 健康、首页可交互、控制台 error 为 0。 -- 首页点击 `添加资料` 可直接打开输入框资料中枢,且不会把说明文字预填进输入框;这一段顺利。 -- 资料中枢点击 `去确认资料` 能进入项目资料管理页;确认、设为默认、用于生成回 Agent 均能走真实 DevBridge,不依赖 mock fallback。 -- `用于生成` 回到 Agent 后会预填 `请基于当前项目资料生成内容`,但视觉状态仍是 `项目资料:未使用`,用户还要再点资料中枢里的 `使用这份资料`;这会让普通用户误以为“用于生成”没有真正生效。 -- 手动点击资料中枢 `使用这份资料` 后,输入框状态能变为 `正在使用:资料名称`;这一段顺利,但多了一步。 -- 从 Agent 输出点击 `沉淀为项目资料` 时,Playwright 正常点击被消息区覆盖层拦截;通过 JS click 才触发 `knowledge_import_source` 与 `knowledge_compile_pack`。这说明普通用户也可能遇到命中区域不稳定或按钮难点的问题。 -- 资料详情仍暴露 `custom`、Markdown 结构、运行时边界、`name/status/trust`、source 路径等内部信息;人工确认后引用摘要里仍显示 `status: draft`、`trust: unreviewed`,与页面“已确认”状态冲突。 -- 回到知识库后出现项目上下文漂移:页面显示了 smoke 临时项目资料和临时目录提示,而不是当前默认项目资料;说明 workingDir / selectedProjectId 的恢复仍不够稳定。 -- 结论:自动 smoke 主链通过,但普通用户真实 E2E 不够顺滑;当前最大问题不是桥接失败,而是状态语义、上下文恢复、点击命中和普通用户文案仍有产品化缺口。 - -### 2026-05-05 真实 E2E 问题修复 - -- 已给 `用于生成` 增加 `initialKnowledgePackSelection` 导航参数,并贯通 `AgentPageParams -> AppPageContent -> AgentChatWorkspace -> Workspace knowledge runtime`,从资料管理回 Agent 后直接显示 `正在使用:资料名称`,不再要求用户二次点击。 -- 已把知识页项目恢复顺序改为显式页面参数优先,其次最近项目 ID,最后默认项目;临时 smoke 目录不再单独作为普通入口默认项目,避免刷新或回知识库时上下文漂移。 -- 已将资料详情、列表卡片和文件条目统一走普通用户预览清洗:隐藏 `custom`、`metadata`、`compiled/brief.md`、`sources/...`、本机完整路径、运行时摘要和 `status/trust` 原始字段;无效资料摘要改为“缺少原始内容,请补充后再确认”。 -- 已把助手消息的“沉淀为项目资料”改为常显文字按钮,并修复普通 Playwright click 被消息气泡拦截的问题;无原始内容的助手结果会提示先补充资料,不再继续沉淀成项目资料。 -- 已同步 `scripts/knowledge-gui-smoke.mjs`,GUI smoke 断言从旧的 `项目资料:未使用` 更新为 `正在使用:资料名称`,让自动 E2E 对齐当前产品语义。 -- 已继续清理历史脏资料摘要:列表与详情不再展示 `何时使用`、`缺失事实时`、`不编造来源资料` 等 Builder 模板腔,避免普通用户看到像开发提示词的内容。 - -## 待完成清单 - -- [x] 给 `docs/knowledge/` 早期方案补 compat 状态说明,避免继续误用旧架构。 -- [x] 新增 `docs/knowledge/README.md`,明确 current / compat 文档事实源。 -- [x] 更新 `.gitignore`,让 `docs/knowledge/README.md` 作为 knowledge 文档索引进入 repo。 -- [x] 更新 current PRD 的项目资料产品闭环、架构图、时序图和阶段计划。 -- [x] 实现 File Manager 右键与输入框路径 chip 的“设为项目资料”入口。 -- [x] 实现 `@资料` 与 `@沉淀资料`,并复用现有 Agent 输入框主链。 -- [x] 将可见资料口令收敛为 `@资料`,保留内部 command key 与现有 Agent 主链不变。 -- [x] 将 `@资料` 从单一启用动作升级为资料中枢:按当前状态引导添加、确认、选择、使用、关闭或补充资料。 -- [x] 将资料中枢主入口收口到输入框底栏资料图标,`@资料` 只保留为兼容兜底,不再作为普通命令标签或主路径宣传。 -- [x] 将首页“添加资料”入口改为直接打开输入框资料中枢,不再预填说明文字或制造第二条入口语义。 -- [x] 实现 Agent 输出“沉淀为项目资料”入口。 -- [x] 将 Agent 输出“沉淀为项目资料”纳入 `smoke:knowledge-gui`,完成普通点击、真实导入 / 编译和管理页待确认资料可见的 E2E 验收。 -- [x] 在首页补充项目资料添加与使用引导。 -- [x] 收口 File Manager 与输入框路径 chip 的可用性判断:仅对 Markdown / 文本文件展示直接整理入口,PDF / Word 等非文本资料给出普通用户可执行提示,避免误导为已支持直接解析。 -- [x] 修正 `lime-knowledge` crate 编译问题和格式问题。 -- [x] 补齐 Tauri command 注册与主 crate 依赖。 -- [x] 补齐 `defaultMocks` 中的 knowledge 命令 mock。 -- [x] 确认 `agentCommandCatalog`、`mockPriorityCommands`、Rust 注册、前端调用四侧一致。 -- [x] 运行 `cargo test -p lime-knowledge`。 -- [x] 运行 `npm run test -- src/lib/api/knowledge.test.ts` 或仓库等价 vitest 定向入口。 -- [x] 运行 `npm run test:contracts`。 -- [x] 根据结果更新本执行计划。 -- [x] 新增并挂载知识库 GUI 页面。 -- [x] 补齐知识库页面、导航、任务中心入口的前端回归测试。 -- [x] 将知识包选择 metadata 接到 AgentChatWorkspace 发送链路。 -- [x] 将 Knowledge Context Resolver 接入 full runtime system prompt。 -- [x] 补齐 runtime 知识包注入和 prompt stage 顺序测试。 -- [x] 在聊天输入区补轻量知识包选择器,让用户不必先进入知识库页面再“去生成”。 -- [x] 产品化 Builder Skill,让来源资料能通过正式 Skill 生成更完整的 `wiki/` 与 `compiled/` 草稿。 -- [x] 为聊天输入区知识包开关增加多包选择菜单,继续复用 `knowledge_pack` metadata 与 runtime fenced context。 -- [x] 为 `knowledge_builder` 增加类型化模板和质量检查输出,覆盖个人 IP、品牌产品、组织 Know-how、增长策略四类。 -- [x] 对知识库页面做普通用户语言降噪,隐藏内部协议、目录、Builder/Skill、token 与 fenced context 等开发者细节。 -- [x] 重做知识页产品主路径:默认展示资料助手,而不是知识包管理台。 -- [x] 将项目资料主入口回流到现有 Agent 输入框。 -- [x] 下线知识页内独立聊天面板。 -- [x] 将知识页定位收敛为项目资料管理页。 -- [x] 补齐 knowledge DevBridge dispatcher。 -- [x] 在稳定 DevBridge + Playwright 环境完成知识库 GUI 主路径 E2E:真实 seed、资料列表、用于生成回 Agent、Agent 自动发送。 -- [x] 完成 Knowledge 前端 feature module 拆分:domain / agent / components / Inputbar knowledge / Workspace knowledge runtime。 -- [x] 在清理本地 DevBridge / CDP smoke 环境后,重跑 `smoke:knowledge-gui` 并补齐真实 seed -> 使用资料 -> 回到现有 Agent 预填生成意图闭环。 -- [x] 修复真实 E2E 暴露的用于生成未自动启用、项目上下文漂移、详情页内部信息泄露和消息沉淀按钮命中问题。 - -## 验证记录 - -```bash -cargo test -p lime-knowledge -npm test -- src/lib/api/knowledge.test.ts -npm run test:contracts -cargo fmt --package lime-knowledge --check -cargo check -p lime -npm run typecheck -npm test -- "src/features/knowledge/KnowledgePage.test.tsx" "src/components/AppPageContent.test.tsx" "src/components/agent/chat/components/ChatSidebar.test.tsx" "src/components/AppSidebar.test.tsx" "src/lib/navigation/sidebarNav.test.ts" "src/i18n/__tests__/translation-coverage.test.ts" -cargo fmt --package lime --check -cargo test -p lime merge_system_prompt_with_knowledge_context_should_append_fenced_context_from_metadata -cargo test -p lime knowledge_pack_metadata_should_force_full_runtime_context -cargo test -p lime test_runtime_turn_source_keeps_full_runtime_prompt_stage_order_contract -npm run typecheck -npm run verify:gui-smoke -npm test -- "src/components/agent/chat/components/Inputbar/index.test.tsx" -npm run typecheck -cargo fmt --manifest-path "src-tauri/Cargo.toml" --package lime --check -npm test -- "src/features/knowledge/KnowledgePage.test.tsx" -cargo test --manifest-path "src-tauri/Cargo.toml" -p lime should_embed_social_image_tool_contract_in_default_skill --no-default-features --features local-sensevoice -cargo test --manifest-path "src-tauri/Cargo.toml" -p lime-core test_default_lime_skill_directories_include_embedded_defaults --no-default-features -禁名扫描:新增路线图、执行计划、Builder Skill、默认 Skill 注册与 Knowledge 前端模块无命中。 -CARGO_HOME="/tmp/lime-gui-smoke-cargo-home" npm run verify:gui-smoke -npm test -- "src/components/agent/chat/components/Inputbar/index.test.tsx" -npm run typecheck -CARGO_HOME="/tmp/lime-gui-smoke-cargo-home" npm run verify:gui-smoke -# 2026-05-02 重跑未完成:独立 target 重建 + 既有 headless 链路长时间未暴露 DevBridge,未计为通过。 -cargo fmt --manifest-path "src-tauri/Cargo.toml" --package lime --check -# 内容契约脚本输出:knowledge_builder content contract ok -CARGO_TARGET_DIR="/tmp/lime-knowledge-resource-target" cargo test --manifest-path "src-tauri/Cargo.toml" -p lime should_embed_social_image_tool_contract_in_default_skill --no-default-features -npm test -- "src/features/knowledge/KnowledgePage.test.tsx" -npm test -- "src/components/AppPageContent.test.tsx" -npm run typecheck -CARGO_HOME="/tmp/lime-gui-smoke-cargo-home" npm run verify:gui-smoke -npm test -- "src/features/knowledge/KnowledgePage.test.tsx" -npm run typecheck -npm run bridge:health -- --timeout-ms 20000 -# 2026-05-04 知识库降噪后 GUI smoke 未执行:DevBridge 未监听 127.0.0.1:3030,health check 超时。 -npm test -- "src/features/knowledge/KnowledgePage.test.tsx" -npm run typecheck -npm run bridge:health -- --timeout-ms 20000 -# 2026-05-05 资料助手主路径重做后 GUI smoke 未执行:DevBridge 未监听 127.0.0.1:3030,health check 超时。 -npm test -- "src/features/knowledge/KnowledgePage.test.tsx" -npm test -- "src/components/agent/chat/components/Inputbar/index.test.tsx" -npm run typecheck -cargo fmt --manifest-path "src-tauri/Cargo.toml" --package lime --check -npm run test:contracts -# 禁名扫描:用户要求禁止出现的具体名称无命中。 -# 普通用户路径泄露扫描:新增主路径未再暴露“聊天任务 / 当前资料 / 查看引用 / 资料助手 / Builder 生成”等旧页面语义。 -CARGO_HOME="/tmp/lime-gui-smoke-cargo-home" npm run verify:gui-smoke -# 2026-05-05 Agent 输入框回流后 GUI smoke 未完成:独立 target 冷构建约 34 分钟仍未进入 smoke 断言,临时进程组已中止,该次不计为通过。 -npm run bridge:health -- --timeout-ms 5000 -# 2026-05-05 Bridge 就绪:127.0.0.1:3030 health status=ok。 -# 2026-05-05 Playwright E2E:真实 DevBridge seed 两份项目资料,进入知识库,确认项目资料管理页、全部项目资料、手动导入、用于生成可见;点击用于生成后回到现有 Agent,并通过 agent_runtime_submit_turn 自动发送“请基于当前项目资料生成内容”。 -npm run test:contracts -npm test -- "src/lib/dev-bridge/safeInvoke.test.ts" "src/lib/tauri-mock/core.test.ts" -npm test -- "src/features/knowledge/KnowledgePage.test.tsx" -npm run typecheck -# 控制台 / 页面泄露扫描:无 ERROR / Failed / ERR_CONNECTION;无 knowledge_builder、compiled/brief.md、.lime/knowledge、frontmatter、token、聊天任务、当前资料:、查看引用、资料助手、Builder 生成。 -npm run smoke:knowledge-gui -- --app-url "http://127.0.0.1:1420/" --health-url "http://127.0.0.1:3030/health" --invoke-url "http://127.0.0.1:3030/invoke" --timeout-ms 240000 --interval-ms 1000 -npm test -- "src/features/knowledge/KnowledgePage.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/index.test.tsx" -npm run typecheck -npm run verify:gui-smoke -git diff --check -# 普通用户可见路径泄露扫描:KnowledgePage、knowledge components、Inputbar knowledge control 与 knowledge GUI smoke 无内部实现词命中。 -test -f docs/roadmap/knowledge/prd.md && test -f docs/knowledge/README.md -rg -n "File Manager|@资料|沉淀为项目资料|knowledge_import_source|knowledge_resolve_context|KnowledgePack" docs/roadmap/knowledge/prd.md -# 文档禁名扫描:current PRD、执行计划、docs/knowledge README 与 compat 方案无命中。 -git diff --check -- docs/roadmap/knowledge/prd.md docs/exec-plans/agent-knowledge-implementation-plan.md docs/knowledge/README.md docs/knowledge/lime-knowledge-base-construction-blueprint.md docs/knowledge/markdown-first-knowledge-pack-plan.md docs/knowledge/lime-project-knowledge-base-solution.md docs/knowledge/agent-skills-and-knowledge-pack-boundary.md -# 2026-05-05 文档架构同步:knowledge docs validation ok。 -npm test -- "src/components/agent/chat/components/FileManager/FileManagerSidebar.test.tsx" "src/components/agent/chat/components/Inputbar/components/InputbarCore.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/MessageList.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/lib/base-setup/seededCommandPackage.test.ts" -npm run typecheck -npm run test:contracts -# 2026-05-05 四入口闭环实现:File Manager、输入框路径 chip、@资料、@沉淀资料、Agent 输出沉淀与首页入口定向回归通过。 -npm run verify:gui-smoke -# 2026-05-05 四入口闭环 GUI smoke 通过:已补齐当前工作树 runtime_evidence_pack_service.rs 的 AgentThreadItem 导入编译缺口;本轮 cold target 里 sherpa-onnx-sys 下载仍出现 TLS close_notify 警告,但 DevBridge 已就绪,workspace-ready、browser-runtime、site-adapters、Agent service skill entry、runtime tool surface/page 与 knowledge GUI smoke 均通过。 -npm test -- "src/features/knowledge/import/knowledgeSourceSupport.test.ts" "src/components/agent/chat/components/FileManager/FileManagerSidebar.test.tsx" "src/components/agent/chat/components/Inputbar/components/InputbarCore.test.tsx" -npm run typecheck -# 2026-05-05 文件导入可用性收口:Markdown / 文本文件保留直接整理入口;PDF 等非文本文件不再在输入框展示“设为资料”,File Manager 右键菜单展示禁用态与可执行提示。 -npm run verify:gui-smoke -# 2026-05-05 文件导入可用性收口后 GUI smoke 通过:复用已有 headless Tauri 与 DevBridge,workspace-ready、browser-runtime、site-adapters、Agent service skill entry、runtime tool surface/page 与 knowledge GUI smoke 均通过。 -npm test -- "src/lib/base-setup/seededCommandPackage.test.ts" "src/components/agent/chat/components/Inputbar/index.test.tsx" -npm run test:contracts -npm run typecheck -npm run verify:gui-smoke -# 2026-05-05 资料口令产品化收口:可见 mention 从模块名收敛为 `@资料`,`knowledge_pack` 内部 command key 与现有 Agent 输入框主链保持不变。 -# 2026-05-05 资料口令收口后 GUI smoke 通过:复用已有 headless Tauri 与 DevBridge,knowledge GUI smoke 通过。 -npm test -- "src/components/agent/chat/components/Inputbar/knowledge/knowledgeHubState.test.ts" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/lib/base-setup/seededCommandPackage.test.ts" -npm run typecheck -npm run test:contracts -# 2026-05-05 `@资料` 闭环修正:`@资料` 不再直接启用资料,而是打开资料中枢;无资料、待确认、未启用、已启用四类状态均有主动作回归。 -npm test -- "src/components/agent/chat/components/Inputbar/knowledge/knowledgeHubState.test.ts" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/lib/base-setup/seededCommandPackage.test.ts" -npm run typecheck -npm run verify:gui-smoke -# 2026-05-05 追加修正:初始 capability route 带 `@资料` 时也会打开资料中枢,不再渲染普通 builtin command badge。 -# 2026-05-05 追加修正后 GUI smoke 通过:复用已有 headless Tauri 与 DevBridge,knowledge GUI smoke 通过。 -npm test -- "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/home/buildHomeSkillSurface.test.ts" "src/components/agent/chat/home/HomeStarterChips.test.tsx" -npm test -- "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/Inputbar/knowledge/knowledgeHubState.test.ts" "src/lib/base-setup/seededCommandPackage.test.ts" -npm run typecheck -npm run test:contracts -npm run verify:gui-smoke -# 2026-05-05 首页添加资料入口收口:点击首页“添加资料”直接打开输入框资料中枢,不再预填解释 prompt;GUI smoke 通过,knowledge GUI 阶段覆盖资料管理页、用于生成回 Agent 与补充导入入口。 -git diff --check -- src/components/agent/chat/home/homeSurfaceTypes.ts src/components/agent/chat/home/homeSurfaceCopy.ts src/components/agent/chat/home/HomeStarterChips.tsx src/components/agent/chat/home/buildHomeSkillSurface.test.ts src/components/agent/chat/components/EmptyState.tsx src/components/agent/chat/components/EmptyState.test.tsx docs/roadmap/knowledge/prd.md docs/exec-plans/agent-knowledge-implementation-plan.md -# 2026-05-05 首页资料入口收口后禁名 / 用户可见泄露扫描无命中。 -npm run bridge:health -- --timeout-ms 120000 -npm run smoke:knowledge-gui -- --app-url "http://127.0.0.1:1420/" --health-url "http://127.0.0.1:3030/health" --invoke-url "http://127.0.0.1:3030/invoke" --timeout-ms 240000 --interval-ms 1000 -# 2026-05-05 Playwright MCP 真实 E2E 顺滑度复测:自动 knowledge smoke 通过;手动用户流暴露用于生成后未自动启用资料、消息沉淀按钮点击命中不稳定、详情页内部信息泄露、项目上下文漂移四类产品化问题。 -npm test -- "src/features/knowledge/KnowledgePage.test.tsx" -npm test -- "src/components/agent/chat/components/MessageList.test.tsx" -npm test -- "src/components/agent/chat/index.test.tsx" -npm test -- "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/Inputbar/knowledge/knowledgeHubState.test.ts" -npm run typecheck -# 2026-05-05 typecheck 未通过:阻塞项来自当前工作树既有 capabilityDrafts / tauri-mock 类型错误,非本轮 knowledge 改动。 -npm run test:contracts -npm run bridge:health -- --timeout-ms 120000 -npm run smoke:knowledge-gui -- --app-url "http://127.0.0.1:1420/" --health-url "http://127.0.0.1:3030/health" --invoke-url "http://127.0.0.1:3030/invoke" --timeout-ms 240000 --interval-ms 1000 -# 2026-05-05 修复后 Playwright MCP 复测:用于生成回 Agent 后输入框显示“正在使用:资料名”;普通 click 可点击“沉淀为项目资料”;控制台 error 为 0。 -npm run verify:gui-smoke -# 2026-05-05 修复后 GUI smoke 通过:复用已有 headless Tauri 与 DevBridge,workspace-ready、browser-runtime、site-adapters、Agent service skill entry、runtime tool surface/page 与 knowledge GUI smoke 均通过。 -npm test -- "src/features/knowledge/KnowledgePage.test.tsx" -npm run typecheck -npm run test:contracts -npm run smoke:knowledge-gui -- --app-url "http://127.0.0.1:1420/" --health-url "http://127.0.0.1:3030/health" --invoke-url "http://127.0.0.1:3030/invoke" --timeout-ms 240000 --interval-ms 1000 -# 2026-05-05 历史脏资料摘要降噪后:KnowledgePage 定向测试、typecheck、contracts 通过;knowledge GUI smoke 因 DevBridge 未监听 3030 未执行成功,尝试重启 headless 时遇到其他工作树 Rust 文件持续变更触发 watch 重建,已中止该次环境进程,不计为通过。 -npm run smoke:knowledge-gui -- --app-url "http://127.0.0.1:1420/" --health-url "http://127.0.0.1:3030/health" --invoke-url "http://127.0.0.1:3030/invoke" --timeout-ms 240000 --interval-ms 1000 -# 2026-05-05 产品 E2E 验收收口:knowledge GUI smoke 已覆盖真实 seed、用于生成回 Agent、Agent 结果样本普通点击“沉淀为项目资料”、真实导入 / 编译、管理页出现待确认资料和补充导入入口。 -node --check "scripts/knowledge-gui-smoke.mjs" -npm run typecheck -npm run test:contracts -npm run verify:gui-smoke -# 2026-05-05 GUI smoke 全量通过:workspace-ready、browser-runtime、site-adapters、Agent service skill entry、runtime tool surface/page、knowledge GUI smoke 与 design-canvas 均通过。 -``` - -## 后续切片 - -1. 把 File Manager 文本文件识别从扩展名 / mimeType 扩展到 PDF / DOCX 的“先预览再整理”安全路径,但仍不向普通用户暴露内部转换细节。 -2. 继续收口普通用户语言:管理页只展示资料名称、状态、风险提醒、引用摘要和确认动作;内部文件名、Skill 名称、目录结构只保留在开发文档和测试 mock 中。 -3. 为运行时 Knowledge Context Resolver 增加更细的章节选择和成本控制,但只在开发者诊断或高级设置中展示,不进入普通用户默认路径。 -4. 为 `knowledge_builder` 增加示例输入 / 输出快照测试,锁定不同 `pack_type` 的生成结构。 - -## 2026-05-05 产品 E2E 闭环续测 - -- 页面 / URL:`http://127.0.0.1:1420/`,从首页进入知识库,再点击“用于生成”回到现有 Agent 输入框。 -- 已完成步骤:知识库加载、普通用户可见文案检查、资料中枢打开、已确认资料启用、Agent 输入框显示“正在使用:资料名”、发送“请基于当前项目资料生成内容”。 -- 暴露问题:知识页默认展示排障目录预览,属于普通用户信息泄露;输入框资料中枢把待确认 / 缺素材资料放在可用选项里,属于体验误导;发送后 DevBridge 出现 `workspace_get` / `agent_runtime_get_session` / event stream 超时,属于桥接稳定性缺口。 -- 本轮修复:排障入口改为“项目识别异常?”并默认隐藏本机路径;资料中枢只把已确认资料作为可用选项,待确认资料只显示数量和“管理资料”;运行时默认资料选择优先已确认资料,避免默认草稿抢占生成路径。 -- 新增 skill:`.codex/skills/lime-product-e2e-loop/SKILL.md`,沉淀“真实用户路径 E2E -> 问题分类 -> 最小产品化修复 -> 复测记录”的复用流程。 -- 验证通过:`npm test -- "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/Inputbar/knowledge/knowledgeHubState.test.ts" "src/components/agent/chat/workspace/knowledge/useWorkspaceKnowledgeRuntime.test.ts" "src/features/knowledge/KnowledgePage.test.tsx"`;追加 `npm test -- "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/workspace/knowledge/useWorkspaceKnowledgeRuntime.test.ts" "src/features/knowledge/KnowledgePage.test.tsx"`;`git diff --check` 通过;禁名扫描无命中;skill 基础结构校验通过。 -- 验证未完成:`npm run typecheck` 当前失败在既有 `src/lib/layered-design/imageTasks.ts` 类型错误,非本轮 Knowledge 改动;`npm run bridge:health -- --timeout-ms 15000` 失败,当前 DevBridge 3030 监听进程无响应,headless Tauri watch 反复因其他工作树 Rust 文件变化重建并等待 Cargo lock,因此本轮 Playwright 复测停在修复前用户流和组件回归,尚未完成修复后真实 GUI 复走。 - -## 2026-05-05 项目资料产品化二次收口 - -- 页面 / URL:`http://127.0.0.1:1420/`;手动 Playwright 从首页进入左侧 `项目资料`,再回到 Agent 输入框资料中枢,最后发送一次带资料引用的消息。 -- 闭环结果:模块入口已从左侧 `知识库` 收敛为 `项目资料`;管理页首屏只保留“管理与确认”职责;空资料态明确提示三条添加路径:输入框添加、文件管理器添加、对话结果沉淀;输入框无资料时不再同时露出“管理资料”这种管理动作。 -- 本轮修复:更新 `src/lib/navigation/sidebarNav.ts`、`src/components/agent/chat/components/ChatSidebar.tsx` 的入口命名;更新 `KnowledgePage` 的首屏、空态和主按钮;更新 `InputbarKnowledgeControl` / `knowledgeHubState` 的无资料文案、菜单按钮和二级管理动作条件;同步 `scripts/knowledge-gui-smoke.mjs` 的导航断言。 -- 用户视角验证:知识管理页截图 `knowledge-after-optimization.png` 已确认不再把模块包装成独立聊天页;输入框资料中枢可选择已确认资料,点击后显示 `正在使用:资料名`;发送时页面进入现有 Agent 对话流,没有新建独立 Agent。 -- 控制台 / Bridge 状态:冷构建后的 DevBridge 已恢复,`npm run bridge:health -- --timeout-ms 30000` 通过;手动发送曾在 DevBridge 未就绪期间出现 `无法创建会话`,Bridge 恢复后 `smoke:knowledge-gui` 真实通过。 -- 验证通过:`npm test -- "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/Inputbar/knowledge/knowledgeHubState.test.ts"`;`npm test -- "src/lib/navigation/sidebarNav.test.ts" "src/components/AppSidebar.test.tsx" "src/components/agent/chat/components/ChatSidebar.test.tsx" "src/features/knowledge/KnowledgePage.test.tsx"`;`npm run typecheck`;`npm run smoke:knowledge-gui -- --app-url "http://127.0.0.1:1420/" --health-url "http://127.0.0.1:3030/health" --invoke-url "http://127.0.0.1:3030/invoke" --timeout-ms 240000 --interval-ms 1000`。 -- 验证未完成:`npm run verify:gui-smoke` 未通过,失败在 `smoke:agent-runtime-tool-surface-page` 的浏览器 CDP 标签页读取 `http://127.0.0.1:15668/json/list`,不在本轮项目资料 UI / smoke 脚本改动边界;全局 `git diff --check` 仍受其它工作树文件尾随空白影响,本轮改动文件的 `git diff --check -- ` 通过。 - -## 2026-05-05 项目资料产品化三次收口 - -- 页面 / URL:`http://127.0.0.1:1420/`;手动 Playwright 从首页 `添加资料`、输入框资料图标、左侧 `项目资料`、File Manager 四条路径复走。 -- 用户闭环结果:`添加资料` 和管理页 `回到 Agent 添加` 现在都会打开输入框项目资料浮层;浮层在已有资料时同时给出 `添加新资料`、`检查资料`、`使用这份资料`,不再把用户困在“只能使用已有资料”的分支里。 -- 本轮修复:输入框项目资料浮层新增常显补充入口,并把二级管理动作改为 `检查资料`;知识页回 Agent 添加改为直达现有 Agent 输入框资料浮层;File Manager 文本文件普通点击改为 `加入对话`,行内提供 `设为资料`,避免点击文件直接调系统打开;输入框本地文件 chip 隐藏本机绝对路径,只保留文件名和 `本地文件 / 本地文件夹`。 -- 普通用户信息边界:默认页面不再暴露本机目录、`.lime/knowledge`、`compiled/brief.md`、`metadata/status/trust`、`knowledge_builder` 或命令名;路径只在测试 mock 和内部 metadata 中存在。 -- Playwright 证据:首页点击 `添加资料` 后浮层可见 `添加新资料 / 检查资料 / 使用这份资料`;点击 `添加新资料` 后输入框填入整理资料提示;File Manager 打开后文本文件行内出现 `加入对话 / 设为资料`;点击文本文件后没有再触发 `open_with_default_app` unknown command,新控制台仅剩 DevBridge event stream 在重建期间的环境噪音。 -- 验证通过:`npm test -- "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/Inputbar/knowledge/knowledgeHubState.test.ts"`;`npm test -- "src/features/knowledge/KnowledgePage.test.tsx" "src/components/agent/chat/components/FileManager/FileManagerSidebar.test.tsx"`;`npm test -- "src/components/agent/chat/components/Inputbar/components/InputbarCore.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx"`;`npm run typecheck`;`npm run smoke:knowledge-gui -- --app-url "http://127.0.0.1:1420/" --health-url "http://127.0.0.1:3030/health" --invoke-url "http://127.0.0.1:3030/invoke" --timeout-ms 240000 --interval-ms 1000` 主流程通过。 -- 验证未完成:`npm run verify:gui-smoke` 本轮仍失败在 `smoke:agent-runtime-tool-surface-page` 的 `launch_browser_session fetch failed`;同时 headless Tauri watch 期间其它 Rust 文件持续变更触发重建,导致 DevBridge 3030 多次断开。`smoke:knowledge-gui` 已通过主断言,但清理临时项目时也因 DevBridge 重建出现 `workspace_delete fetch failed`,记录为环境 / 并发重建噪音,不判定为项目资料主链失败。 - -## 2026-05-05 产品 E2E 验收补测与修复 - -- 页面 / URL:`http://127.0.0.1:1420/`;Playwright 从首页、输入框项目资料浮层、File Manager、项目资料管理页和最近结果路径复走。 -- 闭环判定:A 首页 / 输入框添加资料、B File Manager 加入对话与设为资料、C 项目资料管理页确认与用于生成回 Agent 已按普通用户路径补测;D Agent 结果沉淀当前样本未稳定展示可点击结果按钮,本轮只记录为 `warn`,不判定完成。 -- 本轮发现:File Manager 顶部仍显示本机完整路径,属于信息泄露;首页空态输入框的本地文件 chip 没有透传“设为项目资料”动作,属于产品阻塞;浏览器 mock 文件路径进入真实文件预览时会报 `No such file or directory`,属于 mock / bridge 组合缺口;`回到 Agent 添加` 存在重复按钮定位,E2E 脚本需用 `.first()` 或明确作用域。 -- 本轮修复:File Manager 顶部位置改为“本地位置”,`title` 不再放绝对路径;`EmptyState -> EmptyStateComposerPanel -> InputbarCore` 补齐 `onImportPathReferenceAsKnowledge` 透传,首页和空态 chip 也能直接“设为资料”;`knowledgeSourceImport` 对浏览器文件管理器 mock 文本路径增加产品化 fallback,避免普通 click 后出现文件元信息错误。 -- Playwright 证据:修复后 B 路径显示 `brief.md / 本地文件 / 设为项目资料`,普通 click 可命中 chip 的设为资料动作,File Manager 和输入框正文不再展示 `/Users/...`;C 路径管理页首屏未出现 `.lime/knowledge`、`compiled/brief.md`、`metadata`、`status/trust`、`knowledge_builder`、`frontmatter` 或 `token`。 -- 验证通过:`npm test -- "src/features/knowledge/import/knowledgeSourceImport.test.ts" "src/features/knowledge/import/knowledgeSourceSupport.test.ts"`;`npm test -- "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx" "src/components/agent/chat/components/FileManager/FileManagerSidebar.test.tsx"`;`npm test -- "src/components/agent/chat/index.test.tsx" -t "点击顶部加号应在任务中心新标签内嵌首页起手页"`;`npm run typecheck`;本轮触达文件 `git diff --check` 通过;禁名扫描通过。 -- 验证警告:`npm test -- "src/components/agent/chat/index.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/Inputbar/components/InputbarCore.test.tsx"` 首次全量组合仅 1 个任务中心标签用例失败,单测定向重跑通过,按当前工作树并发负载下的组合级波动记录。 -- 验证未完成:本轮最终 `npm run bridge:health -- --timeout-ms 10000` 未就绪,`npm run tauri:dev:headless` 停在 Tauri / Cargo dev 进程等待阶段且 3030 未监听;因此修复后的完整 A/B/C/D Playwright 复走仍缺稳定 DevBridge 复验,不能把产品 E2E 验收宣称为全部完成。 - -## 2026-05-05 产品 E2E 验收收口 - -- 页面 / URL:`http://127.0.0.1:1420/`;复用已就绪 DevBridge,并通过 `smoke:knowledge-gui` 走完整项目资料产品闭环。 -- 闭环判定:A 首页 / 输入框添加资料、B File Manager 文本资料设为项目资料、C 项目资料管理页用于生成回现有 Agent、D Agent 输出沉淀为项目资料均已纳入可重复 E2E;本轮不再保留 D 路径 `warn`。 -- 本轮修复:`scripts/knowledge-gui-smoke.mjs` 在创建临时项目后再按实际项目根目录 seed 知识资料,避免页面项目根与 seed 根不一致;同时加入 Agent 结果样本,普通点击“沉淀为项目资料”,等待真实 `knowledge_import_source` / `knowledge_compile_pack` 完成,并在管理页验证待确认资料可见。 -- 产品证据:`smoke:knowledge-gui` 阶段顺序包含 `open-agent-with-knowledge -> wait-agent -> prepare-agent-result -> wait-agent-result -> capture-agent-result -> wait-agent-result-captured -> wait-captured-agent-result -> open-import-view`,确认从“使用资料”到“结果沉淀”再回“管理确认”的闭环顺序。 -- 验证通过:`node --check "scripts/knowledge-gui-smoke.mjs"`;`npm run smoke:knowledge-gui -- --app-url "http://127.0.0.1:1420/" --health-url "http://127.0.0.1:3030/health" --invoke-url "http://127.0.0.1:3030/invoke" --timeout-ms 240000 --interval-ms 1000`;`npm run typecheck`;`npm run test:contracts`;`npm run verify:gui-smoke`。 -- 当前剩余风险:Agent 结果样本由 E2E 脚本注入历史消息以避开真实模型配置依赖;点击、导入、编译和管理页展示均走真实 GUI / DevBridge。后续如要覆盖真实模型生成,只应作为模型配置可用时的增强验收,不再阻塞当前项目资料产品闭环。 - -## 2026-05-06 产品 E2E 验收最终复跑 - -- 页面 / URL:`http://127.0.0.1:1420/`;使用隔离 `CARGO_TARGET_DIR="/tmp/lime-knowledge-headless-target"` 启动 headless Tauri,并复用已有 Vite 前端。 -- 用户闭环判定:已完成首页 `添加资料` 打开资料中枢、File Manager `brief.md -> 设为项目资料`、项目资料页 `用于生成` 回现有 Agent、Agent 结果 `沉淀为项目资料`、回管理页继续确认的完整闭环;本轮达到产品 E2E 可交付门槛。 -- 本轮发现:File Manager 行本身是可点击区域,自动化按文本找 `设为资料` 时命中了包含同名文案的文件行,实际触发的是“加入对话”,属于 `测试缺口` 与 `点击命中风险`,不是资料导入后端失败。 -- 本轮修复:File Manager 行内 `设为资料` 增加稳定可访问名 `设为项目资料 <文件名>`;`scripts/knowledge-gui-smoke.mjs` 改为在 File Manager 作用域内点击该可访问名,并等待真实 `knowledge_list_packs` 出现由文件导入生成的资料。 -- 验证通过:`node --check "scripts/knowledge-gui-smoke.mjs"`;`npm test -- "src/components/agent/chat/components/FileManager/FileManagerSidebar.test.tsx"`;`npm run bridge:health -- --timeout-ms 10000`;`npm run smoke:knowledge-gui -- --app-url "http://127.0.0.1:1420/" --health-url "http://127.0.0.1:3030/health" --invoke-url "http://127.0.0.1:3030/invoke" --timeout-ms 240000 --interval-ms 1000`;`npm run typecheck`;`npm run test:contracts`;`npm run verify:gui-smoke -- --reuse-running`。 -- 质量收口:`npm run verify:gui-smoke -- --reuse-running` 覆盖 workspace-ready、browser-runtime、site-adapters、Agent service skill entry、runtime tool surface/page、knowledge GUI 与 design canvas,全部通过。 - -## 2026-05-06 输入框资料入口排版收口与启动修复 - -- 页面 / URL:`http://127.0.0.1:1420/`;本轮聚焦输入框底栏和项目资料浮层,不把 `项目资料` 收进 `高级设置`,因为它是本次生成的上下文来源,不是配置项。 -- 本轮 UI 收口:底栏顺序调整为 `资料 / 模型 / 高级设置 / 文件管理器`;模型 badge 文案从 `当前模型` 收敛为 `模型`;资料状态收敛为 `资料可用 / 资料待确认 / 添加资料 / 资料:<名称>`,减少普通用户看到的长解释和重复按钮。 -- 浮层收口:项目资料主按钮合并下拉入口,取消单独小箭头按钮;浮层改成上下文选择器语气,保留 `添加新资料 / 检查资料 / 使用这份资料`,不再呈现为设置面板。 -- 启动阻塞修复:`tauri:dev:headless` 失败的直接原因依次为 1420 被 `vite preview` 占用、`SkillsPage.tsx` 出现中文弯引号导致 Vite optimize 失败、`MemoryPage.tsx` 存在未闭合 JSX 标签导致 typecheck 失败、隔离 Cargo target 一度写入失败提示磁盘不足;本轮只做语法级最小修复,并恢复 1420 / 3030 可用。 -- 运行态处理:磁盘空间恢复后仍优先避免再次触发 Cargo 大编译,改用 `npm run dev:web-bridge` 启动 1420,再直接运行既有 `src-tauri/target/debug/lime` 恢复 DevBridge;当前验证时 1420 / 3030 均已监听。 -- E2E 结果:`smoke:knowledge-gui` 已复走首页添加资料、File Manager 设为项目资料、项目资料页用于生成回现有 Agent、Agent 结果沉淀为项目资料、回管理页继续确认的完整闭环。 -- 验证通过:`node --check "scripts/knowledge-gui-smoke.mjs" && node --check "scripts/agent-service-skill-entry-smoke.mjs"`;`npm test -- "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/Inputbar/knowledge/knowledgeHubState.test.ts" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx"`;`npm run bridge:health -- --timeout-ms 30000`;`npm run smoke:knowledge-gui -- --app-url "http://127.0.0.1:1420/" --health-url "http://127.0.0.1:3030/health" --invoke-url "http://127.0.0.1:3030/invoke" --timeout-ms 240000 --interval-ms 1000`;`npm run typecheck`。 -- 验证说明:本轮未重新跑完整 `npm run verify:gui-smoke -- --reuse-running`,因为上一轮被中断后留下的 browser-runtime smoke、1420 preview 占用和 Cargo target 空间问题需要先处理;本轮用知识库专项 GUI smoke 证明项目资料主链已恢复。 diff --git a/docs/exec-plans/agentui-implementation-progress.md b/docs/exec-plans/agentui-implementation-progress.md deleted file mode 100644 index 9303b41f8..000000000 --- a/docs/exec-plans/agentui-implementation-progress.md +++ /dev/null @@ -1,4133 +0,0 @@ -# AgentUI 实施进度 - -> 状态:进行中 -> 更新时间:2026-05-05 -> 路线图:`docs/roadmap/agentui/lime-agentui-implementation-roadmap.md` - -## 主目标 - -逐步实现 Lime AgentUI 下一阶段主线,优先解决旧会话恢复慢、首字慢、tab 卡顿、流式重复吐字和过程信息噪声。 - -## 当前阶段 - -P1:Tab 与 Task Capsule 已完成多轮性能止血;结构主线进入 P3 的前置闭环,先做对话事实源盘点与最小 Projection Store,不再继续把状态堆进 `AgentChatWorkspace` / `useAgentSession` / `MessageList`。 - -当前结构收敛口径: - -```text -Warp runtime fact sources - -> Conversation Projection Store - -> Session / Stream / Queue / Render controllers - -> selectors - -> UI -``` - -`Conversation Projection Store` 是 UI projection,不是 runtime fact source;Warp 仍是 `ModalityRuntimeContract`、`Execution Profile`、`Artifact Graph`、`Evidence / Replay / Task Index` 的事实源。 - -## 本轮执行准则更新:旧 UI 顺路清理 - -主线仍以旧会话性能数值分析和首字/流式体验优化为优先级;遇到现有 UI 老旧、不适合继续承载 AgentUI 主链时,可以顺路清理,但清理必须直接服务当前交付,不能偏航成纯治理或视觉翻新。 - -### 准入条件 - -仅当旧 UI 满足以下任一条件时,本轮允许顺路清理: - -- 直接造成旧会话打开、切换、新建对话或流式输出卡顿,例如重复渲染非活跃会话、旧面板抢占 hydrate、旧入口触发额外查询。 -- 直接造成用户路径错误,例如新建对话被旧界面跳走、无法同时打开多个历史对话、输入区/对话区位置与 AgentUI 规划冲突。 -- 直接造成重复事实源,例如同一状态同时由旧 tab、旧任务面板和新 capsule 独立维护,导致状态不同步或额外 render。 -- 直接违反当前 Lime UI 规范并影响可用性,例如半透明主表面、多层套卡、重复标题、伪交互、中文排版被压缩。 - -### 分类与动作 - -- `current`:继续沿 AgentUI 当前主链演进;性能采样、消息窗口、tab/capsule、新建对话入口都应向这里收敛。 -- `compat`:只允许委托和适配,不新增状态、查询、渲染分支;如果旧 UI 仍被调用,必须写清退出条件。 -- `deprecated`:只允许迁移和下线;遇到影响主线的旧 UI,优先从主入口摘除,再登记后续删除。 -- `dead`:确认无入口或与 current 规划冲突时直接删除或补治理守卫,防止后续重新接回主链。 - -### 清理边界 - -- 每一刀最多顺路清理一个直接阻塞主线的旧 UI surface,其余旧面先登记,不连续深挖。 -- 不新增平行的新旧两套组件;能收敛到现有 AgentUI current 组件时,不再补新的 compat 包装层。 -- 清理后仍需保持桌面 GUI 气质:实体主表面、清晰边界、中文优先、按钮层级明确,避免半透明主体和过度嵌套套卡。 -- 如果清理会触及 Tauri command、Bridge、mock 或 session 数据事实源,必须另起命令边界检查,不把 UI 清理伪装成纯样式改动。 - -### 验收口径 - -- 性能侧:用 `window.__LIME_AGENTUI_PERF__.summary()` 对比清理前后,至少看 `clickToMessageListPaintMs`、`runtimeGetSessionDurationMs`、`finalRenderedMessagesCount`、`hiddenHistoryCount`。 -- 交互侧:覆盖新建对话、打开旧会话 A、打开旧会话 B、旧会话间切换、发送短句看首字和流式输出。 -- UI 侧:补稳定回归或 snapshot,必要时复用现有 Lime 页签做 Playwright E2E;不使用会新开 isolated profile 或 `--no-sandbox` 临时浏览器的验证方式。 -- 治理侧:如果删除或下线旧入口,补 `current / compat / deprecated / dead` 分类说明;必要时运行 `npm run governance:legacy-report` 或 `npm run test:contracts`。 - -## 进度日志 - -### 2026-04-30:P0 第一刀,流式主链观测与渲染降频 - -已完成: - -- 在 stream request state 中补齐首字慢分段字段: - - listener bound - - submit dispatched / accepted / failed - - first event - - first runtime status - - first text delta - - first text paint - - text render flush / backlog -- 在 `agentStreamTurnEventBinding.ts` 记录 listener bound 和 first event。 -- 在 `agentStreamSubmitExecution.ts` 记录 submit dispatched / accepted / failed。 -- 在 `agentStreamRuntimeHandler.ts` 记录 first runtime status、first text delta、first text paint、text render flush。 -- 保留并补齐已有 text_delta 低频刷新策略,避免每个字符都刷新消息树。 -- 保留并补齐已有 thinking 关闭策略,`thinking_delta` 不再污染最终正文。 -- 保留并补齐已有 `final_done` reconcile 防线,避免最终文本整段重复追加。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/components/MessageList.test.tsx" "src/components/agent/chat/components/StreamingRenderer.test.tsx" -npm run typecheck -npm run verify:gui-smoke -``` - -结果: - -- 流式定向测试:通过,`17` 个测试通过。 -- AgentUI P0 定向测试:通过,`131` 个测试通过。 -- TypeScript:通过。 -- GUI smoke:通过。 - -下一步: - -1. 跑 touched files 的 lint/type 校验。 -2. 继续 P0 旧会话渐进恢复:确认 active tab 与非 active tab 的 hydrate 边界,减少旧会话打开时 MessageList/timeline 同步负担。 -3. 再进入 P1 tab/capsule:避免多历史会话同时全量渲染。 - -### 2026-04-30:P0 第二刀复核,旧会话渐进恢复现状 - -已确认当前工作区已有以下旧会话恢复优化: - -- `useAgentSession.ts`: - - `getSession` 恢复路径统一带 `historyLimit: 40`。 - - recent session prefetch 使用 `SESSION_DETAIL_PREFETCH_HISTORY_LIMIT = 40`。 - - cached snapshot fresh 时延迟 detail hydrate。 - - detail hydrate 进入 `startTransition`,降低切换时主线程抢占。 - - “加载更多历史”改为分页:`SESSION_HISTORY_LOAD_PAGE_SIZE = 50`,使用 `historyOffset` / `historyBeforeMessageId`。 -- `MessageList.tsx`: - - 旧会话只先渲染最近消息窗口。 - - 旧会话隐藏历史不自动逐批补齐,必须用户点击展开。 - - 历史 timeline 延迟到 idle,完成历史 timeline 可先折叠为轻量摘要。 - - 超长历史助手消息和较长历史助手消息先展示纯文本预览。 - - 历史 Markdown 使用 light render mode,避免首帧挂载重 Markdown。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/components/MessageList.test.tsx" "src/components/agent/chat/components/StreamingRenderer.test.tsx" -npm run typecheck -npm run verify:gui-smoke -``` - -结果:通过,`MessageList` / `StreamingRenderer` 定向测试共 `114` 个通过,TypeScript 检查通过,GUI smoke 通过。 - -下一步: - -1. 进入 P1 tab/capsule 前,先用 Playwright 复测真实多历史会话打开路径,采集 `runtimeGetSession.*`、`switchTopic.*`、`AgentStream.*` 日志。 -2. 若 E2E 仍出现切换卡顿,下一刀优先做非活跃 tab snapshot/freeze,而不是继续压 MessageList 单点。 - -### 2026-04-30:P1 第一刀,旧会话切换期间延迟运行轨迹投影 - -已完成: - -- 在 `useWorkspaceConversationSceneRuntime.tsx` 增加 session runtime projection defer: - - 旧会话恢复首帧继续立即透传 `messages`,保证正文和输入区先可交互。 - - `turns`、`threadItems`、`threadRead`、`pendingActions`、`queuedTurns`、`childSubagentSessions` 延迟到 idle 后再挂载,减少点击历史会话时的同步投影和 timeline 构建压力。 - - 延迟状态按 `sessionId + 首尾 message + 尾部 turn/item` 绑定,避免从一个历史会话切到另一个同长度历史会话时复用上一会话的“已投影”状态。 - - 正在发送、聚焦 timeline、存在 pending A2UI 表单时不延迟,避免影响运行中反馈和用户待处理动作。 -- 在 `useWorkspaceConversationSceneRuntime.test.ts` 补回归: - - 恢复旧会话首帧应先透传消息,并延迟运行轨迹投影。 - - 切换到另一条同长度旧会话时应重新延迟运行轨迹投影。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.test.ts" "src/components/agent/chat/workspace/WorkspaceConversationScene.test.tsx" "src/components/agent/chat/components/MessageList.test.tsx" -npm run typecheck -``` - -结果: - -- Workspace / MessageList 定向回归:通过,`96` 个测试通过。 -- TypeScript:通过。 - -未完成验证: - -- `npm run verify:gui-smoke` 本轮未完成。原因是本地 `DevBridge` 3030 未就绪,smoke 复用/拉起 headless 链路时触发新的 Rust 编译链,持续数分钟占用 CPU;继续等待会污染“旧会话打开是否卡顿”的真实判断。已清理本轮 `verify-gui-smoke` 派生的临时编译链,未清理用户已有的长期 `tauri:dev:headless` / 其他 Rust 校验进程。 -- 真实 Chrome 页签 E2E 续测暂未完成。当前前端 `http://127.0.0.1:1420/` 可访问,但 `http://127.0.0.1:3030/health` 未监听;需先恢复 DevBridge 后再复测多历史会话切换。 - -下一步: - -1. 恢复 DevBridge 3030 后,用现有 Chrome 页签复测:新建对话、打开两个历史会话、来回切换、观察控制台 error 和 `switchTopic.*` 日志。 -2. 若旧会话仍有体感卡顿,继续 P1:把 tab/shell 层的 running/queued/needs_input 胶囊化,并进一步降低非当前过程面板的更新频率。 - -### 2026-04-30:P1 第二刀,覆盖 history window hydrate 后的重投影卡顿 - -已完成: - -- 扩展 `useWorkspaceConversationSceneRuntime.tsx` 的旧会话运行轨迹延迟投影触发条件: - - 不再只依赖 `isAutoRestoringSession`。 - - 当 `sessionHistoryWindow.totalMessages > sessionHistoryWindow.loadedMessages` 时,也按旧会话窗口处理,覆盖 cached snapshot 已显示、detail hydrate 后恢复大量 `turns/threadItems` 的场景。 - - 同一个 session 尾部追加新消息时不重新延迟投影,避免首字和流式输出被 700ms 延迟误伤。 - - 继续保持发送中、timeline 聚焦、存在 pending A2UI 表单时不延迟,保护实时反馈和用户待处理动作。 - - 延迟投影状态写入改为“值未变化则返回当前 state”,避免 ready/pending 状态重复写入造成额外 render。 -- 补齐 `useWorkspaceConversationSceneRuntime.test.ts` 回归: - - `isAutoRestoringSession=false` 但存在截断历史窗口时,首帧仍先显示消息、延迟运行轨迹。 - - 发送中会话不延迟运行轨迹。 - - 聚焦 timeline 或存在 A2UI 表单时不延迟运行轨迹。 -- 顺手补齐语音快捷键相关测试 fixture 的 `fn_*` 字段,修复当前工作区 `typecheck` 阻塞;该修复只闭合测试 mock 类型,不扩展语音功能面。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.test.ts" -npm exec -- vitest run "src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.test.ts" "src/components/agent/chat/workspace/WorkspaceConversationScene.test.tsx" "src/components/agent/chat/components/MessageList.test.tsx" -npm exec -- vitest run "src/components/onboarding/steps/VoiceShortcutTestStep.test.tsx" "src/components/settings-v2/general/hotkeys/hotkeyCatalog.test.ts" -npm run typecheck -curl -fsS "http://127.0.0.1:3030/health" -``` - -结果: - -- Workspace 单测:通过,`13` 个测试通过。 -- Workspace / MessageList 组合回归:通过,`99` 个测试通过。 -- 语音 fixture 定向回归:通过,`4` 个测试通过。 -- TypeScript:通过。 -- DevBridge 健康检查:失败,`127.0.0.1:3030` 未监听;当前只确认 `127.0.0.1:1420` 前端 dev server 在监听。第二轮 render 收紧后复查结果一致。 - -未完成验证: - -- 真实 Chrome 页签 E2E 暂未执行。原因是 DevBridge 3030 未就绪,强行启动 `verify:gui-smoke` 会触发新的 Rust 编译链并污染旧会话卡顿判断。 - -下一步: - -1. 恢复 DevBridge 3030 后,复用现有 Chrome/Lime 页签做多历史会话切换 E2E。 -2. 若体感卡顿仍明显,下一刀进入 tab/shell 层:冻结非活跃 tab 的重运行时投影,只保留标题、状态、未读和最后预览。 - -### 2026-04-30:P1 第三刀,收紧 tab/shell 同步小开销与验证阻塞 - -已完成: - -- `AgentChatWorkspace.tsx` 为 `topics` 建立单次 `topicById` Map: - - 初始会话切换策略、任务中心打开旧会话、detached 判断和顶部 tab item 生成复用 Map 查询。 - - 减少旧会话切换路径里多处 `topics.find/some` 扫描;当前非活跃 tab 本身只渲染标题/状态/未读,不渲染正文或 timeline。 -- `useWorkspaceConversationSceneRuntime.tsx` 收紧延迟投影状态更新: - - 空投影数组改为模块级稳定常量,避免下游 `useMemo` 因每次新建 `[]` 失效。 - - 延迟投影 ready/pending 写入保持“值未变则返回当前 state”,避免无意义二次 render。 -- 修复当前工作区两个验证阻塞: - - 语音快捷键测试 fixture 补齐 `fn_*` 字段。 - - 媒体任务测试 fixture 与浏览器 mock 输出补齐 transcript 汇总字段,保持 `MediaTaskModalityRuntimeContractIndex` 契约一致。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/index.test.tsx" -t "任务中心初始会话标签" -npm exec -- vitest run "src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.test.ts" "src/components/agent/chat/workspace/WorkspaceConversationScene.test.tsx" "src/components/agent/chat/components/MessageList.test.tsx" -npm exec -- vitest run "src/components/agent/chat/workspace/useWorkspaceAudioTaskPreviewRuntime.test.tsx" "src/components/agent/chat/workspace/useWorkspaceImageTaskPreviewRuntime.test.tsx" "src/lib/tauri-mock/core.test.ts" -npx eslint "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.tsx" "src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.test.ts" "src/components/agent/chat/workspace/useWorkspaceAudioTaskPreviewRuntime.test.tsx" "src/components/agent/chat/workspace/useWorkspaceImageTaskPreviewRuntime.test.tsx" "src/lib/tauri-mock/core.ts" "src/components/onboarding/steps/VoiceShortcutTestStep.test.tsx" "src/components/settings-v2/general/hotkeys/hotkeyCatalog.test.ts" --max-warnings 0 -npm run typecheck -npm run test:contracts -curl -fsS "http://127.0.0.1:3030/health" -``` - -结果: - -- 任务中心定向回归:通过,`11` 个测试通过。 -- Workspace / MessageList 组合回归:通过,`99` 个测试通过。 -- 媒体任务 / mock 回归:通过,`54` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript:通过。 -- Contract:通过。 -- DevBridge 健康检查:失败,`127.0.0.1:3030` 未监听;`127.0.0.1:1420` 前端 dev server 仍在监听。 - -未完成验证: - -- 真实 Chrome 页签 E2E 仍未执行。原因同上一刀:DevBridge 3030 未就绪,当前不应启动新的 Playwright profile 或强行触发重编译链。 - -下一步: - -1. 待 DevBridge 恢复后,复用现有 Chrome/Lime 页签采样:打开旧会话、打开第二个旧会话、来回切换、发送 DeepSeek 短句,看首字前占位、真实 first text delta 和 long task。 -2. 若旧会话仍慢,下一刀不再继续做 tab 微调,优先做 MessageList 动态高度虚拟化或 `agent_runtime_get_session` 分块返回方案评估。 - -### 2026-04-30:P1 第四刀,旧会话首帧推迟 Prompt Cache 配置扫描 - -已完成: - -- `MessageList.tsx` 推迟旧会话恢复首帧的 Provider 配置自动加载: - - 旧会话恢复或历史窗口 hydrate 阶段,`useConfiguredProviders` 先以 `autoLoad: false` 运行。 - - 首帧消息可见后再在 idle 阶段允许 Provider 配置加载,避免 Prompt Cache 提示为了历史消息扫描抢占旧会话打开主链。 - - 保留实时发送、当前会话和普通新会话的 Provider 能力提示,不影响新 token 到达后的说明能力。 -- `MessageList.tsx` 同步收紧最新助手消息定位: - - `lastAssistantMessageId` 与当前 timeline 映射不再复制数组反向查找。 - - 减少旧会话窗口里消息列表重算时的短期内存峰值。 -- `MessageList.test.tsx` 补回归: - - 旧会话恢复首帧应关闭 Provider 配置自动加载。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/components/MessageList.test.tsx" -npx eslint "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" --max-warnings 0 -npm exec -- vitest run "src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.test.ts" "src/components/agent/chat/workspace/WorkspaceConversationScene.test.tsx" "src/components/agent/chat/components/MessageList.test.tsx" -npm run typecheck -npm run test:contracts -curl -fsS "http://127.0.0.1:3030/health" -``` - -结果: - -- MessageList 定向回归:通过,`85` 个测试通过。 -- MessageList ESLint:通过。 -- Workspace / MessageList 组合回归:通过,`100` 个测试通过。 -- TypeScript:通过。 -- Contract:通过。 -- DevBridge 健康检查:通过,返回 `status=ok`。 - -未完成验证: - -- 真实 Chrome 页签 E2E 仍需复用现有 Lime 页签继续;当前 Chrome DevTools MCP 被已有 `chrome-profile` 占用,不能按工具提示启动 isolated 新实例,也不应启用 `--no-sandbox` 的临时 Playwright profile。 - -下一步: - -1. 复用现有 Lime 页签或恢复 Chrome DevTools MCP 会话后,执行旧会话 A / 旧会话 B / 新建对话切换采样。 -2. 如果旧会话仍有明显鼠标 loading、CPU 或内存峰值,优先评估 MessageList 动态高度虚拟化,避免继续在 tab shell 做边际优化。 - -### 2026-04-30:P1 第五刀,点击旧会话不再即时预取抢占切换链路 - -已完成: - -- `AppSidebarConversationShelf.tsx` 取消点击路径上的即时预取: - - 移除 `onPointerDown` 的立即 prefetch。 - - `onFocus` 改为延迟预取,并在 `onClick` / `onBlur` / `onPointerLeave` 时取消尚未触发的预取。 - - 保留真正悬停或键盘聚焦停留时的旧会话预热,但避免“鼠标按下 -> 预取 hydrate -> 正式切换复用同一 promise”造成点击后主链多做一次旧会话 hydrate。 -- `MessageList.tsx` 继续减少热路径小分配: - - `renderGroups` 从 `assistantMessages.map(...).find(...)` 改为单次循环,避免每个消息组创建临时数组。 - -主线收益: - -- 用户点击旧会话时,正式切换链路直接进入 `switchTopic.fetchDetail`,不再先被侧栏 prefetch 的 snapshot hydrate 抢占。 -- 只有用户悬停停留足够久时才做预热,符合“后台预取不能拖慢明确点击”的优先级。 - -已验证: - -```bash -npm exec -- vitest run "src/components/AppSidebar.test.tsx" -t "旧会话预取|已有会话" -npm exec -- vitest run "src/components/agent/chat/components/MessageList.test.tsx" -t "旧会话恢复首帧|复杂任务完成后" -npx eslint "src/components/app-sidebar/AppSidebarConversationShelf.tsx" "src/components/AppSidebar.test.tsx" "src/components/agent/chat/components/MessageList.tsx" --max-warnings 0 -npm run typecheck -git diff --check -- "docs/exec-plans/agentui-implementation-progress.md" "src/components/app-sidebar/AppSidebarConversationShelf.tsx" "src/components/AppSidebar.test.tsx" "src/components/agent/chat/components/MessageList.tsx" -npm exec -- vitest run "src/components/AppSidebar.test.tsx" -npm exec -- vitest run "src/components/agent/chat/components/MessageList.test.tsx" -``` - -结果: - -- AppSidebar 定向回归:通过,`4` 个测试通过。 -- MessageList 定向回归:通过,`2` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript:通过。 -- diff whitespace:通过。 -- AppSidebar 全量回归:通过,`38` 个测试通过。 -- MessageList 全量回归:通过,`85` 个测试通过。 - -未完成验证: - -- `npm run verify:gui-smoke` 本轮执行到 `smoke:agent-runtime-tool-surface-page` 时失败:`launch_browser_session` 对 DevBridge 的请求连续返回 `fetch failed`,随后 `3030` DevBridge 端口不可用。当前 `tauri dev` 正在重新编译 Rust 侧,暂不能继续真实 E2E。 -- Chrome DevTools MCP 仍被既有 `chrome-profile` 占用;不能按工具提示启动 isolated 新实例,也不应使用带 `--no-sandbox` 的临时 Playwright profile。 - -下一步: - -1. 等 DevBridge 3030 恢复后,先只做真实页签 E2E,不再重复触发会重启/重编 Rust 的 GUI smoke。 -2. E2E 重点采样:点击旧会话是否还出现鼠标 loading、打开第二个旧会话是否并发卡住、新建对话 tab 是否立即可打开。 -3. 若仍慢,下一刀进入真正的 MessageList 虚拟化或后端 `getSession` 分块返回,不继续做 prefetch / tab shell 边际优化。 - -### 2026-04-30:P1 第六刀,补 AgentUI 性能数值采集 - -已完成: - -- 新增 `src/lib/agentUiPerformanceMetrics.ts`: - - 浏览器内维护 `AgentUI` 性能 ring buffer,最多保留 `500` 条。 - - 自动暴露 `window.__LIME_AGENTUI_PERF__`,E2E 可直接读取: - - `window.__LIME_AGENTUI_PERF__.entries()` - - `window.__LIME_AGENTUI_PERF__.summary()` - - `window.__LIME_AGENTUI_PERF__.clear()` - - `summary()` 按 `sessionId` 汇总旧会话打开关键耗时: - - `clickToSwitchStartMs` - - `clickToCachedSnapshotMs` - - `clickToPendingShellMs` - - `clickToFetchStartMs` - - `fetchDetailDurationMs` - - `runtimeGetSessionDurationMs` - - `clickToSwitchSuccessMs` - - `clickToMessageListPaintMs` - - `finalRenderedMessagesCount / hiddenHistoryCount / persistedHiddenHistoryCount` - - 可用时同步采集 `usedJSHeapSize / totalJSHeapSize` -- 采样点已接入: - - `AppSidebarConversationShelf.tsx`:旧会话 hover/focus 预取 schedule / cancel / fire、点击旧会话。 - - `sessionClient.ts`:`agentRuntime.listSessions`、`agentRuntime.getSession` start / success / error 及 duration。 - - `useAgentSession.ts`:session prefetch、switch start、cached snapshot、pending shell、fetch detail、switch success。 - - `MessageList.tsx`:旧会话恢复 / 分页历史窗口 commit 与 post-paint 消息数、turn 数、timeline defer 状态。 -- E2E 读取建议: - -```ts -await page.evaluate(() => window.__LIME_AGENTUI_PERF__?.clear()); -// 执行:点击旧会话 A -> 点击旧会话 B -> 新建对话 -> 切回旧会话 -const snapshot = await page.evaluate(() => window.__LIME_AGENTUI_PERF__?.summary()); -console.table(snapshot?.sessions ?? []); -``` - -已验证: - -```bash -npm exec -- vitest run "src/lib/agentUiPerformanceMetrics.test.ts" "src/components/agent/chat/components/MessageList.test.tsx" -t "agentUiPerformanceMetrics|旧会话首帧应记录|旧会话恢复首帧" -npm exec -- vitest run "src/components/AppSidebar.test.tsx" -t "旧会话预取|已有会话" -npm exec -- vitest run "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" -t "thread timeline|hydrate|switchTopic" -npm exec -- vitest run "src/lib/api/agent.test.ts" -t "getSession|listSessions|runtime" -npx eslint "src/lib/agentUiPerformanceMetrics.ts" "src/lib/agentUiPerformanceMetrics.test.ts" "src/lib/api/agentRuntime/sessionClient.ts" "src/components/agent/chat/hooks/useAgentSession.ts" "src/components/app-sidebar/AppSidebarConversationShelf.tsx" "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" --max-warnings 0 -npm run typecheck -``` - -结果: - -- 性能采集器 / MessageList 定向回归:通过,`4` 个测试通过。 -- AppSidebar 旧会话点击 / 预取回归:通过,`4` 个测试通过。 -- useAsterAgentChat 定向回归:通过,`9` 个测试通过。 -- Agent Runtime API 定向回归:通过,`15` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript:通过。 - -下一步: - -1. 复用现有 Lime 页签时先执行 `window.__LIME_AGENTUI_PERF__.clear()`。 -2. 完成多旧会话切换后导出 `summary().sessions`,用 `clickToMessageListPaintMs`、`runtimeGetSessionDurationMs`、`finalRenderedMessagesCount` 判断瓶颈是在桥接、后端查询还是前端渲染。 -3. 如果 `runtimeGetSessionDurationMs` 低但 `clickToMessageListPaintMs` 高,下一刀优先 MessageList 虚拟化;如果两者都高,优先后端 `getSession` 分块/缓存。 - -## 风险记录 - -- 当前工作区已有多处未提交改动,本计划只记录本轮 AgentUI 主线增量;合并前需继续保护用户已有改动,不做回滚。 -- 本轮没有新增 Tauri command,不需要同步 command catalog / mock;后续若新增 session snapshot 或 timeline page command,必须按命令边界四侧同步。 - -### 2026-04-30:P1 第七刀,旧会话列表分页降载与路由追平去重 - -采集事实: - -- 首轮 Playwright 性能探针显示,点击新建 / 旧会话附近仍有侧边栏 `agent_runtime_list_sessions(limit=37)` 在 DevBridge 通道内运行:浏览器侧记录约 `10.2s`,同时 `workspace_get` 出现 `timeout after 5000ms`,导致旧会话列表和新建任务入口体感卡顿。 -- 后端日志对比显示,降载前异常环境下 `limit=37` / `limit=60` 最高可到数秒级;降载后同一工作区常规请求收敛到 `limit=11` / `limit=21`,最近采样约 `47-218ms`。 -- 二次 Playwright 探针发现“侧栏打开旧会话 -> 路由追平”会让同一历史会话出现 `switchStartCount=2` / `runtimeGetSessionStartCount=2`,即同一次用户意图触发两次 `getSession`。 - -已完成: - -- `AppSidebar.tsx`:最近 / 归档会话列表改成可见数量 `+1` 的哨兵分页: - - 最近会话首屏请求从强制 `37` 降到 `11`。 - - 归档首屏请求从 `17` 降到 `9`。 - - 点击“查看更多”时再按当前可见数量继续增加请求窗口,避免首页一次性预取两页以上历史。 -- `useAgentSession.ts`:任务中心内部 topics 初始列表请求从 `60` 降到 `21`,保留 `topicsListMayBeTruncatedRef` 作为旧会话不在首屏列表时的 detached 恢复兜底。 -- `AppSidebarConversationShelf.tsx`:hover/focus 预取延迟从 `140ms` 提高到 `900ms`,点击路径仍会取消未触发预取,减少鼠标扫过列表时的隐性 `getSession`。 -- `useWorkspaceInitialSessionNavigation.ts` / `AgentChatWorkspace.tsx`:新增“外部任务打开已启动”去重标记;侧栏/任务中心事件已经触发 `switchTopic` 后,2s 内路由 `initialSessionId` 追平不再重复打开同一会话。 -- `.tmp/agentui-perf-probe.mjs` 临时探针增强:只从侧栏会话 shelf 取目标、记录 invoke command、采集 CDP CPU/heap delta、long task 与 detail 阶段 summary。 - -Playwright 复测摘要: - -- 页面:`http://127.0.0.1:1420/`,Chrome 持久化 profile `.tmp/lime-agentui-e2e-chrome-profile`,DevBridge `3030` 健康检查通过。 -- 旧会话 A `AI网关MVP规划`:`switchStartCount=1`,`runtimeGetSessionStartCount=1`,`runtimeGetSessionDurationMs≈82ms`,`clickToSwitchSuccessMs≈685ms`,`clickToMessageListPaintMs≈626ms`,`longTask=0`。 -- 旧会话 B `PPT大纲规划`:去重后目标会话 `switchStartCount=1`,`runtimeGetSessionStartCount=1`;`agent_runtime_get_session` 最慢约 `157ms`。 -- 切回旧会话 A:目标会话 `switchStartCount=1`,`runtimeGetSessionStartCount=1`,`clickToMessageListPaintMs≈18ms`,`longTask=0`。 -- 控制台:`0 error / 1 warning`;warning 为 `useAgentTopicSnapshot.skipWithoutActiveTopic`,不阻塞主链,但提示后续 topics 截断后仍可继续优化 topic snapshot 噪音。 -- 网络:最慢 `/invoke` 从上一轮 `agent_runtime_get_session≈6.1s` / `agent_runtime_list_sessions≈10.2s`,恢复到本轮 `agent_runtime_get_session≤157ms`、`agent_runtime_list_sessions≤218ms`;上一轮 6s 主要由探针未等待 detail、连续发起多个旧会话请求叠加当时 Rust 编译负载污染,已用直接 curl 与等待 detail 的探针复核。 - -已验证: - -```bash -npx eslint "src/components/AppSidebar.tsx" "src/components/AppSidebar.test.tsx" "src/components/app-sidebar/AppSidebarConversationShelf.tsx" "src/components/agent/chat/hooks/useAgentSession.ts" "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" --max-warnings 0 -npm exec -- vitest run "src/components/AppSidebar.test.tsx" "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" -t "最近对话|窗口重新聚焦|打开已有会话|归档动作|加载话题时应后台预热" -npx eslint "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/workspace/useWorkspaceInitialSessionNavigation.ts" "src/components/agent/chat/index.test.tsx" --max-warnings 0 -npm exec -- vitest run "src/components/agent/chat/index.test.tsx" "src/components/agent/chat/workspace/useWorkspaceInitialSessionNavigation.test.tsx" -t "外层侧边栏通知打开历史会话|初始会话|dedupe|连续打开历史会话|任务中心初始会话标签" -npm run typecheck -node ".tmp/agentui-perf-probe.mjs" > ".tmp/agentui-perf-probe-latest.json" -``` - -结果: - -- AppSidebar / useAsterAgentChat 定向回归:通过,`8` 个测试通过。 -- AgentChatWorkspace / initial session navigation 定向回归:通过,`16` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript:通过。 -- Playwright 性能探针:完成,旧会话切换不再出现同一目标重复 `switchTopic` / 重复 `getSession`;列表请求窗口已降到 `11/21`。 - -下一步: - -1. 修复或降噪 `useAgentTopicSnapshot.skipWithoutActiveTopic`:在 topics 初始窗口被截断时,active session 已由 detail 恢复,不应持续警告。 -2. 新建任务探针当前用性能事件等待会超时,应改成 DOM 空态断言(`home-start-surface` / `青柠一下,灵感即来`)后再纳入数值汇总,避免把探针等待超时误判为产品卡顿。 -3. 如果用户继续反馈“打开后消息正文仍慢”,下一刀不要再扩 AppSidebar;优先进入 `agent_runtime_get_session` 首包/分块返回或 MessageList 真虚拟化。 - -### 2026-04-30:P1 第八刀,新建页旧会话本地打开与探针降噪 - -采集事实: - -- 上一轮 Playwright 探针只剩 `0 error / 1 warning`,warning 来自旧会话 pending shell 阶段:`sessionId` 已切到目标会话,但 topics 还没等 `getSession` detail upsert,`useAgentTopicSnapshot` 误判为 active topic 缺失。 -- 新建任务按钮探针此前仍等待 `session.switch.*` / `messageList.paint` 性能事件;新建首页本身不会触发旧会话切换事件,导致 14s 超时被误算成产品卡顿。 -- 从新建页点击旧会话时,侧栏原先只在 `agentEntry=claw` 时走任务中心本地事件;在 `new-task` 首页会回到路由跳转路径,容易触发页面切换、路由追平和首刀延迟。 - -已完成: - -- `useAsterAgentChat.ts`:`useAgentTopicSnapshot` 在 `isSessionHydrating=true` 时抑制 active topic 暂缺 warning;真实缺失仍会在非 hydrating 阶段继续暴露。 -- `AppSidebar.tsx`:新建任务首页点击已有会话改走 `TASK_CENTER_OPEN_TASK_EVENT`,交给当前 Agent workspace 本地新增/切换标签,不再跳出当前页面做 claw 路由导航。 -- `AppSidebar.test.tsx`:更新新建任务首页点击历史会话的回归,断言发出本地 open event 且不调用 `onNavigate`。 -- `.tmp/agentui-perf-probe.mjs`:新建任务改为等待 `home-start-surface` / `青柠一下,灵感即来` DOM 就绪;会话选择避开已标记 active 的侧栏项,避免把 no-op 点击计入旧会话恢复耗时。 - -Playwright 复测摘要: - -- 页面:`http://127.0.0.1:1420/`,Chrome 持久化 profile `.tmp/lime-agentui-e2e-chrome-profile`,DevBridge `3030` 健康检查通过。 -- 旧会话 B `PPT大纲规划`:`clickToSwitchStartMs≈3ms`,`runtimeGetSessionDurationMs≈71ms`,`clickToSwitchSuccessMs≈81ms`,`switchStartCount=1`,`runtimeGetSessionStartCount=1`,`longTask=0`。 -- 切回旧会话 A `AI网关MVP规划`:`clickToSwitchStartMs≈1ms`,`runtimeGetSessionDurationMs≈108ms`,`clickToSwitchSuccessMs≈113ms`,`switchStartCount=1`,`runtimeGetSessionStartCount=1`,`longTaskMax≈51ms`。 -- 新建任务:`clickToHomeMs≈83ms`,`home-start-surface=true`,`0` 次 `getSession`,`longTask=0`。 -- 控制台:`0 error / 0 warning`;上一轮 `useAgentTopicSnapshot.skipWithoutActiveTopic` 已消失。 -- 网络:最慢有效 `/invoke` 为 `agent_runtime_list_sessions≈413ms`,`agent_runtime_get_session≤113ms`;长连接类 `/events` 在浏览器关闭时出现 `ERR_ABORTED`,为探针关闭上下文产生的非阻塞噪音。 - -已验证: - -```bash -node --check ".tmp/agentui-perf-probe.mjs" -npx eslint "src/components/agent/chat/hooks/useAsterAgentChat.ts" --max-warnings 0 -npm exec -- vitest run "src/components/agent/chat/hooks/useAgentTopicSnapshot.test.tsx" "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" -t "detached 会话缺少活动话题|切换到无本地快照的话题" -npx eslint "src/components/AppSidebar.tsx" "src/components/AppSidebar.test.tsx" "src/components/agent/chat/hooks/useAsterAgentChat.ts" --max-warnings 0 -npm exec -- vitest run "src/components/AppSidebar.test.tsx" "src/components/agent/chat/index.test.tsx" -t "新建任务首页点击已有会话|new-task 首页收到外层侧栏打开历史会话|任务中心内点击已有会话|打开已有会话时若导航已有缓存任务" -npm run typecheck -npm run bridge:health -- --timeout-ms 120000 -node ".tmp/agentui-perf-probe.mjs" > ".tmp/agentui-perf-probe-latest.json" -``` - -结果: - -- Hook 定向回归:通过,`2` 个测试通过。 -- AppSidebar / AgentChatPage 定向回归:通过,`4` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript:通过。 -- Playwright 性能探针:完成,旧会话点击到 switch start 已收敛到 `1-3ms`;新建任务首页首帧收敛到 `~83ms`;控制台 warning 清零。 - -下一步: - -1. 如果用户继续感知“旧会话正文慢”,优先看真实重历史会话的 `messageList.paint` 是否稳定产出;当前小会话 detail 很快,但首个 no-op 样本说明探针还需要进一步区分“已在内存中的会话”与“真实冷打开”。 -2. 对大历史会话继续采 `renderedMessagesCount / threadItemsCount / timelineGroupsCount / longTaskMaxMs`,若 `getSession≤150ms` 但 paint 或 long task 高,下一刀进入 MessageList 虚拟化 / timeline worker。 -3. 当前磁盘空间不足时不跑 `npm run tauri:dev:headless` / `verify:gui-smoke` 这类会触发 Rust 编译的重验证;本轮以已就绪 DevBridge + 浏览器实测覆盖主路径。 - -### 2026-04-30:P1 第九刀,旧会话 pending shell 直接进入会话布局 - -采集事实: - -- 上一轮探针中,旧会话 `switch.success` 与 `agent_runtime_get_session` 已较快返回,但部分样本 `messageList.paintCount=0`,探针等待到超时,体感上等同“打开旧会话后仍停在新建首页 / 空态”。 -- 代码复核发现 `chatLayoutVisibility` 已支持 `isSessionHydrating`,但 `AgentChatWorkspace` 还没有把该状态传入 `shouldShowChatLayout`;同时 `effectiveShowChatPanel` 的 `new-task` 分支也没有把 hydrating 算作会话活动。 -- 这会导致旧会话 pending shell 阶段虽然已进入 session switch 主链,但布局层仍按空白新建页处理,MessageList 无法及时挂载并产生 paint 指标。 - -已完成: - -- `AgentChatWorkspace.tsx`: - - `shouldShowChatLayout(...)` 调用补入 `isSessionHydrating`。 - - `effectiveShowChatPanel` 在 `agentEntry="new-task"` 时把 `isSessionHydrating` 计入会话活动,旧会话恢复的 pending shell 不再被空白首页分支吞掉。 -- `chatLayoutVisibility.ts` / `chatLayoutVisibility.test.ts`:保留第八刀新增的 hydrating 可见性参数与回归,确保旧会话恢复 pending shell 阶段直接进入会话布局。 - -已验证: - -```bash -npx eslint "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/utils/chatLayoutVisibility.ts" "src/components/agent/chat/utils/chatLayoutVisibility.test.ts" "src/components/agent/chat/index.test.tsx" "src/components/AppSidebar.tsx" "src/components/AppSidebar.test.tsx" "src/components/agent/chat/taskCenterDraftTaskEvents.ts" --max-warnings 0 -npm exec -- vitest run "src/components/agent/chat/utils/chatLayoutVisibility.test.ts" "src/components/agent/chat/index.test.tsx" "src/components/AppSidebar.test.tsx" -t "旧会话恢复 pending shell|new-task 首页收到外层侧栏打开历史会话|新建任务首页点击已有会话|任务中心内点击已有会话|空白新建任务首页应保留浏览器式工作区顶栏" -npm run typecheck -``` - -结果: - -- ESLint touched files:通过。 -- AgentUI 布局 / 新建页 / 侧栏打开历史会话定向回归:通过,`5` 个测试通过。 -- TypeScript:通过。 - -Playwright / DevBridge 状态: - -- 下一次真实复测必须继续按仓库规则使用 Chrome 持久化 profile:`.tmp/lime-agentui-e2e-chrome-profile`,不使用 isolated 临时 profile,不传 `--no-sandbox`。 -- 本轮真实 E2E 暂未完成:`npm run bridge:health -- --timeout-ms 5000` 多次失败,`http://127.0.0.1:3030/health` 未监听。 -- 尝试拉起 `npm run tauri:dev:headless` 时,当前机器已有其它 Rust / GUI smoke / cargo test 编译链占用 Cargo lock,输出持续停在 `Blocking waiting for file lock on package cache / artifact directory`;同时磁盘可用空间约 `8.8-9.3GiB`,继续叠加编译会污染旧会话卡顿采样。 -- 已停止本轮自己拉起的 headless 链路,未清理用户已有的长期 Tauri / cargo 校验进程;待 DevBridge 恢复后再复跑真实旧会话多标签性能探针。 - -下一步: - -1. DevBridge 3030 恢复后,复测:新建任务首页 -> 打开旧会话 A -> 打开旧会话 B -> 切回旧会话 A -> 新建空白任务标签。 -2. 采集并对比 `clickToSwitchStartMs`、`runtimeGetSessionDurationMs`、`clickToSwitchSuccessMs`、`messageListPaintCount`、`clickToMessageListPaintMs`、`longTaskMaxMs`。 -3. 如果 `messageList.paintCount` 仍为 `0`,下一刀继续查 `WorkspaceShellScene` / `MessageList` 条件渲染;如果 paint 正常但 `longTaskMaxMs` 高,转入 MessageList 虚拟化或 timeline worker。 - -### 2026-04-30:P1 第十刀,旧会话首帧延后底部运行状态行重计算 - -采集事实: - -- 第九刀修复布局后,旧会话 pending shell 能进入会话布局;下一处首帧风险集中在 `MessageList` 首帧仍会为了最后一条 assistant 的底部运行状态行同步扫描 `threadItems`。 -- 已分页旧会话或历史窗口里,timeline 本体虽然已经延后,但 `buildInputbarRuntimeStatusLineModel` / `buildAgentTaskRuntimeCardModel` 仍可能在首帧扫描并过滤大量历史 `threadItems`,造成 CPU 峰值和短期数组分配。 -- 这些底部完成态状态行不是旧会话首帧正文可见的必要条件;等待 historical timeline idle 后再补上,不影响发送中、等待输入、排队或 active turn 的实时反馈。 - -已完成: - -- `MessageList.tsx`: - - 对旧会话恢复窗口增加 `shouldDeferTailRuntimeStatusLine`。 - - 当旧会话历史 timeline 正在 idle 延后、且没有发送中 / active turn / pending action / queued turn / pending request 时,首帧不再构建底部运行状态行。 - - `messageList.commit/paint` 指标增加 `tailRuntimeStatusDeferred`,后续 E2E 可直接判断首帧是否成功避开这段同步计算。 -- `MessageList.test.tsx`:旧会话消息少但执行过程多的场景,新增断言:首帧不渲染 `inputbar-runtime-status-line`,idle 后再恢复。 -- `inputbarRuntimeStatusLine.ts` / `agentTaskRuntime.ts`:把多处 `[...array].reverse()` 与 `filter(...).find(...)` 改为从尾部循环或单次扫描,减少旧会话打开时的短期数组复制。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/components/MessageList.test.tsx" -t "旧会话消息较少但执行过程很多时也应延后构建 timeline|旧会话首帧应记录可汇总的渲染采样数值|复杂任务完成后应把运行状态" -npm exec -- vitest run "src/components/agent/chat/components/Inputbar/components/InputbarRuntimeStatusLine.test.tsx" "src/components/agent/chat/components/MessageList.test.tsx" -t "旧会话消息较少但执行过程很多时也应延后构建 timeline|复杂任务完成后应把运行状态|InputbarRuntimeStatusLine" -npm exec -- vitest run "src/components/agent/chat/utils/agentTaskRuntime.test.ts" -npx eslint "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" "src/components/agent/chat/utils/agentTaskRuntime.ts" "src/components/agent/chat/utils/inputbarRuntimeStatusLine.ts" --max-warnings 0 -npm run typecheck -npm run bridge:health -- --timeout-ms 5000 -``` - -结果: - -- MessageList 定向回归:通过,`3` 个测试通过。 -- Inputbar / MessageList 组合回归:通过,`4` 个测试通过。 -- Agent task runtime 单测:通过,`4` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript:通过。 -- DevBridge 健康检查:失败,`http://127.0.0.1:3030/health` 仍未监听;因此本轮仍未做真实 Playwright 多旧会话采样。 - -下一步: - -1. DevBridge 恢复后,优先复测旧会话 A/B 切换,确认 `messageList.paint` 中 `tailRuntimeStatusDeferred=true` 的首帧是否降低 `longTaskMaxMs`。 -2. 如果 E2E 仍显示 `longTaskMaxMs` 高,下一刀继续把 historical `threadItems` 的摘要计算改成按 `latestTurnId` 建索引或移入 idle/worker。 -3. 如果 E2E 显示 `runtimeGetSessionDurationMs` 高于渲染耗时,回到后端 `getSession` 分块/缓存,不再继续前端微调。 - -### 2026-04-30:P1 第十一刀,旧会话按可见 turns 精确裁剪 threadItems - -采集事实: - -- 第十刀已把旧会话首帧的底部运行状态行延后,但 `MessageList` 仍会在历史窗口首帧按消息数量粗略截取尾部 `threadItems`。 -- 对“消息少、工具过程多”的旧会话,粗略按 `messageCount * factor` 截取容易把与当前可见消息无关的 turn item 也带入 `buildMessageTurnTimeline` / runtime status 计算,继续造成短期 CPU 与数组分配峰值。 -- 旧会话分页窗口的首帧只需要渲染尾部可见 assistant 关联的 turns;其它历史 turns 可以等待“加载完整历史”或后续展开再参与计算。 - -已完成: - -- `MessageList.tsx`: - - 移除按消息数倍数裁剪 `threadItems` 的粗略常量。 - - 根据当前实际渲染的 assistant 消息数推导旧会话恢复窗口的 `renderedTurns` tail window,并额外保留 `currentTurnId`,避免进行中 turn 被裁掉。 - - 在分页旧会话 / hidden history 场景下构建 `renderedTurnIdSet`,`renderedThreadItems` 只保留这些 turns 对应的 `threadItems`。 -- `MessageList.test.tsx`:新增“已分页旧会话首帧应只把尾部相关 turns 的 threadItems 纳入计算”回归,覆盖 8 个 turns、40 个 threadItems、首帧只渲染 2 条消息的场景;断言首帧只纳入尾部 2 个 turns / 10 个 threadItems。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/components/MessageList.test.tsx" -t "已分页旧会话首帧应只把尾部相关 turns 的 threadItems 纳入计算|旧会话消息较少但执行过程很多时也应延后构建 timeline|已分页旧会话的完成执行过程应先折叠为轻量摘要" -npx eslint "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" --max-warnings 0 -python3 - <<'PY' -# 120s wrapper for npm run typecheck -PY -``` - -结果: - -- MessageList 定向回归:通过,`3` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript:本轮 wrapper 在 `120s` 超时后终止;未看到类型错误输出。当前机器仍有其它 Rust / cargo 编译链与编辑器 tsserver 占用 CPU,先记录为环境性未完成,不继续叠加新的全量 typecheck。 -- DevBridge / Playwright:尚未复测;需先确认 `3030` 恢复,避免在 bridge 未就绪时把前端优化误判为 GUI 卡顿。 - -下一步: - -1. DevBridge 恢复后,复测多旧会话切换并采集 `messageList.commit/paint`,重点看 `threadItemsCount` 是否随可见 turn 数下降,而不是随全量历史增长。 -2. 如果 `getSession≤150ms` 但 `clickToMessageListPaintMs` 或 `longTaskMaxMs` 仍高,下一刀继续把 `buildMessageTurnTimeline` 的历史 mapping / sort 移到 idle 或建立 `turn_id -> items` 索引。 -3. 如果 `runtimeGetSessionDurationMs` 高于渲染耗时,转回后端 `getSession` 分块 / 缓存,不再继续前端微调。 - -### 2026-04-30:P1 第十二刀,旧会话首帧完全跳过 threadItems 扫描 - -采集事实: - -- 第十一刀已经把旧会话恢复窗口的 `threadItems` 从“按消息数粗略截尾”改成“按可见 turns 精确裁剪”,但首帧仍需要遍历全量 `threadItems` 才能筛出尾部 turns。 -- 对工具轨迹特别多的旧会话,哪怕最终只渲染 10 条相关 items,首帧的全量数组扫描仍会造成鼠标 loading、CPU 峰值和短期内存分配。 -- 旧会话首帧的核心目标是先让消息文本和吸顶布局可见;完成态历史 timeline / 底部运行状态行可以继续等 idle 后补齐。 - -已完成: - -- `MessageList.tsx`: - - `shouldDeferHistoricalTimeline` 改为基于原始 `threadItems.length` 与恢复窗口判断,避免为了判断是否延后而先扫描 / 裁剪 `threadItems`。 - - 新增 `shouldDeferThreadItemsScan`:旧会话历史 timeline 尚未 idle-ready、且没有 active turn 时,`renderedThreadItems` 首帧直接返回空数组,不再遍历全量历史 items。 - - `timelineHydrationKey` 改用原始 `threadItems.length + lastItemId`,确保后台 item 变化仍能触发 idle hydrate。 - - `messageList.commit/paint` 指标增加 `threadItemsScanDeferred`,后续 Playwright 能直接看到首帧是否跳过了全量扫描。 -- `MessageList.test.tsx`:更新旧会话窗口测试,首帧断言 `threadItemsScanDeferred=true` 且 `threadItemsCount=0`;idle 后再断言精确裁剪到尾部 2 个 turns / 10 个 `threadItems`。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/components/MessageList.test.tsx" -t "已分页旧会话首帧应只把尾部相关 turns 的 threadItems 纳入计算|旧会话消息较少但执行过程很多时也应延后构建 timeline|已分页旧会话的完成执行过程应先折叠为轻量摘要" -npx eslint "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" --max-warnings 0 -npm run bridge:health -- --timeout-ms 5000 -python3 - <<'PY' -# 180s wrapper for npm run typecheck -PY -``` - -结果: - -- MessageList 定向回归:通过,`3` 个测试通过。 -- ESLint touched files:通过。 -- DevBridge 健康检查:失败,`http://127.0.0.1:3030/health` 未监听;本轮没有进入 Playwright 真实旧会话采样。 -- TypeScript:本轮 wrapper 未超时,但 `tsc --noEmit` 约 `40s` 后以 code `241` 退出且无错误诊断;检查后未发现残留 `tsc` 进程。当前仍有其它 `run-vitest-smart` / Vite 进程占用 CPU,先记录为环境性未闭环,避免继续叠加重校验影响用户本机性能。 - -下一步: - -1. DevBridge 3030 恢复后复测旧会话 A/B 切换,重点读取 `messageList.commit/paint` 的 `threadItemsScanDeferred`、`threadItemsCount`、`clickToMessageListPaintMs` 和 `longTaskMaxMs`。 -2. 若首帧 `threadItemsScanDeferred=true` 后仍卡顿,下一刀优先检查 `StreamingRenderer` / Markdown light render 的长文本成本,而不是继续优化 timeline。 -3. 若 idle 后 timeline hydrate 才出现长任务,则把 `buildMessageTurnTimeline` 的 grouping / sort 继续放到 worker 或分片 idle 队列。 - -### 2026-04-30:P1 第十三刀,旧会话首帧延后 contentParts 细节扫描 + 流式首字立即可见 - -采集事实: - -- DevBridge `3030` 仍未监听,当前无法用 Playwright 复测真实旧会话 A/B 切换;同时本机已有多条 Rust 编译链占用 CPU,继续启动 `tauri:dev:headless` 会污染“卡顿”采样。 -- 第十二刀已经让旧会话首帧跳过全量 `threadItems` 扫描,但 `MessageList` 在渲染每条历史 assistant 时仍会同步 `sanitizeContentPartsForDisplay`、过滤工具/思考片段、计算 inline process coverage。 -- 对已完成的旧会话,这些 `contentParts` 细节不是首帧文本可见的必要条件;可以等 historical timeline idle 后再恢复。 -- 流式纯文本首次挂载时,`StreamingText` 之前以空字符串作为首帧,必须等下一次 `requestAnimationFrame` 才开始吐字;在模型已有首个分片时,这会放大“首字慢”的体感。 - -已完成: - -- `MessageList.tsx`: - - 增加 `shouldDeferHistoricalAssistantMessageDetails`,旧会话恢复窗口、historical timeline 尚未 ready、没有 active turn / sending / action request / toolCalls / thinking 时,首帧不再处理历史 assistant 的 `contentParts` 细节。 - - 增加 `historicalContentPartsDeferredCount` 指标,后续 E2E 可判断是否命中旧会话首帧轻量路径。 - - 保留文本正文优先渲染;idle 后再恢复 contentParts / timeline 细节,避免首帧被旧工具过程拖慢。 -- `MessageList.test.tsx`:新增“旧会话首帧应延后历史助手 contentParts 细节扫描”回归,断言首帧 `data-content-parts=0`、`historicalContentPartsDeferredCount=1`,idle 后指标恢复为 `0`。 -- `StreamingRenderer.tsx`: - - 增加 `STREAMING_TEXT_INITIAL_VISIBLE_CHARS` 和 `resolveInitialStreamingDisplayText`。 - - 流式纯文本首次挂载时立即显示前 `12` 个字符;结构化内容仍保持空首帧,避免把未完整的 A2UI / write_file 协议直接露出。 - - 当流式文本发生非 append 替换时,也立即种下同样的纯文本前缀,减少重置后的空白等待。 -- `StreamingRenderer.test.tsx`:新增“流式纯文本首帧应立即显示前缀”回归,并保留大 backlog 追赶测试。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/components/MessageList.test.tsx" -t "旧会话首帧应延后历史助手 contentParts 细节扫描|已分页旧会话首帧应只把尾部相关 turns 的 threadItems 纳入计算|旧会话消息较少但执行过程很多时也应延后构建 timeline" -npm exec -- vitest run "src/components/agent/chat/components/StreamingRenderer.test.tsx" -t "流式纯文本首帧应立即显示前缀|流式正文积压较多时应快速追上最新目标文本|纯文本内容应短路跳过结构化解析" -npx eslint "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" "src/components/agent/chat/components/StreamingRenderer.tsx" "src/components/agent/chat/components/StreamingRenderer.test.tsx" --max-warnings 0 -npm run bridge:health -- --timeout-ms 5000 -``` - -结果: - -- MessageList 定向回归:通过,`3` 个测试通过。 -- StreamingRenderer 定向回归:通过,`3` 个测试通过。 -- ESLint touched files:通过。 -- DevBridge 健康检查:失败,`http://127.0.0.1:3030/health` 未监听。 -- TypeScript:本轮暂不追加全量 typecheck;当前机器已有多条 Rust 编译链高负载运行,继续叠加全量 TS 校验会影响用户正在反馈的 CPU/鼠标 loading 问题。待编译链空闲后补跑。 - -下一步: - -1. DevBridge 恢复后复测真实旧会话:读取 `threadItemsScanDeferred`、`historicalContentPartsDeferredCount`、`clickToMessageListPaintMs`、`longTaskMaxMs`。 -2. 如果旧会话首帧仍慢,下一刀只看 `MarkdownRenderer` 本体:把 restored history 的短正文也先走纯文本预览 / idle 后 Markdown hydrate,避免 ReactMarkdown 在首帧解析多条历史短回复。 -3. 如果流式仍首字慢,下一步看后端事件到达时间:区分“前端首帧空白”与“runtime 第一段 delta 到达慢”。 - -第十三刀补充: - -- `agentUiPerformanceMetrics.ts`:summary 增加 `historicalContentPartsDeferredMax` 与 `threadItemsScanDeferredCount`,让 Playwright 不只读 raw entries,也能在 session summary 里直接看到旧会话首帧轻量路径命中次数。 -- `agentUiPerformanceMetrics.test.ts`:补充 summary 断言,覆盖 contentParts 延后最大值与 threadItems 扫描延后次数。 -- 追加验证: - -```bash -npm exec -- vitest run "src/lib/agentUiPerformanceMetrics.test.ts" -npx eslint "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" "src/components/agent/chat/components/StreamingRenderer.tsx" "src/components/agent/chat/components/StreamingRenderer.test.tsx" "src/lib/agentUiPerformanceMetrics.ts" "src/lib/agentUiPerformanceMetrics.test.ts" --max-warnings 0 -``` - -结果:性能指标汇总单测通过,ESLint touched files 继续通过。 - -### 2026-04-30:P1 第十四刀,旧会话首帧延后 Markdown hydrate - -采集事实: - -- DevBridge `3030` 仍未监听,真实 Playwright 多旧会话切换暂不可测。 -- 当前机器已有 `tsc --noEmit` 与多条 `rustc` 高 CPU 进程,继续启动 Tauri / GUI smoke 会污染用户反馈的鼠标 loading 与 CPU 飙高采样。 -- 第十三刀已跳过旧会话首帧的 `contentParts` 细节扫描,但短历史 assistant 正文仍会进入 `StreamingRenderer -> MarkdownRenderer -> ReactMarkdown`,即使 `renderMode=light` 也会同步解析多条历史 Markdown。 -- 旧会话首帧的产品目标是“先看到消息文本与布局”,Markdown 标题、列表、代码高亮、表格等可等 idle 后恢复。 - -已完成: - -- `MessageList.tsx`: - - 增加 `MESSAGE_LIST_STRUCTURED_HISTORY_CONTENT_RE` 与 `hasStructuredHistoricalContentHint`,避免把 A2UI / write_file / document 这类结构化协议用纯文本提前露出。 - - 增加 `HistoricalMarkdownHydrationPreview`,旧会话首帧用 `whitespace-pre-wrap` 纯文本直接展示 assistant 正文,不挂载 `StreamingRenderer` / `ReactMarkdown`。 - - 增加 `historicalMarkdownDeferredCount` 指标,记录旧会话首帧被延后的 Markdown hydrate 数量。 - - 当 historical timeline idle-ready 后,自动恢复原有 `StreamingRenderer` / light Markdown 渲染。 -- `MessageList.test.tsx`:更新旧会话首帧回归,断言首帧出现 `message-list-historical-markdown-preview`、不挂载 `streaming-renderer`,idle 后移除 preview 并恢复 renderer。 -- `agentUiPerformanceMetrics.ts` / `.test.ts`:summary 增加 `historicalMarkdownDeferredMax`,方便 Playwright summary 直接读取 Markdown hydrate 延后命中量。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/components/MessageList.test.tsx" -t "旧会话首帧应延后历史助手 contentParts 与 Markdown 细节扫描|已分页旧会话首帧应只把尾部相关 turns 的 threadItems 纳入计算|旧会话消息较少但执行过程很多时也应延后构建 timeline|旧会话里的长助手回复应先展示纯文本预览" -npm exec -- vitest run "src/lib/agentUiPerformanceMetrics.test.ts" -npx eslint "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" "src/lib/agentUiPerformanceMetrics.ts" "src/lib/agentUiPerformanceMetrics.test.ts" --max-warnings 0 -npm run bridge:health -- --timeout-ms 5000 -``` - -结果: - -- MessageList 定向回归:通过,`4` 个测试通过。 -- 性能指标汇总单测:通过,`2` 个测试通过。 -- ESLint touched files:通过。 -- DevBridge 健康检查:失败,`http://127.0.0.1:3030/health` 未监听。 -- TypeScript:本轮未追加全量 typecheck;本机已有其它 `tsc --noEmit` 高 CPU 进程在运行,避免重复启动。 - -下一步: - -1. DevBridge 恢复后复测真实旧会话,读取 `historicalMarkdownDeferredMax`、`historicalContentPartsDeferredMax`、`threadItemsScanDeferredCount`、`clickToMessageListPaintMs`、`longTaskMaxMs`。 -2. 若首帧仍慢,下一刀优先看 `visibleMessages.filter` / `buildMessageTurnGroups` 是否需要基于 sessionId 做更强 memo 或窗口化。 -3. 若首帧已快但 idle 后出现卡顿,把 Markdown hydrate / timeline hydrate 拆成分批 idle,而不是一次性恢复完整历史。 - -### 2026-04-30:P1 第十五刀,旧会话 Markdown idle 分批 hydrate - -采集事实: - -- 第十四刀已经让旧会话首帧不挂载 `ReactMarkdown`,但 historical timeline idle-ready 后,所有短历史 assistant 会在同一轮恢复 `StreamingRenderer / MarkdownRenderer`。 -- 对消息窗口里有多条短 Markdown 回复的旧会话,一次性恢复仍可能在首帧之后造成第二段 CPU 峰值,表现为鼠标短暂 loading 或滚动卡顿。 -- 真实 Playwright 仍不可用:`DevBridge 3030` 未监听;本机同时存在 `rustc` 高 CPU 编译链,继续拉 GUI smoke 会污染性能采样。 - -已完成: - -- `MessageList.tsx`: - - 增加 `MESSAGE_LIST_RESTORED_MARKDOWN_HYDRATION_INITIAL_COUNT / BATCH_SIZE / DELAY_MS`。 - - 将旧会话 Markdown hydrate 从“timeline ready 后全量恢复”改为“先恢复 2 条,再按 idle 每批 +2 条”。 - - 复用 `scheduleMinimumDelayIdleTask` 分片恢复,避免一次性挂载多个 `StreamingRenderer / ReactMarkdown`。 - - `historicalMarkdownDeferredCount` 现在表示尚未 hydrate 的历史 Markdown 数量;ready 后会随批次递减,而不是直接归零。 - - `historicalContentPartsDeferredCount` 也跟随未 hydrate 的消息保持延后,避免 Markdown 未恢复但 contentParts 细节先被扫描。 -- `MessageList.test.tsx`:新增“旧会话 idle 后应分批恢复历史 Markdown hydrate”回归,覆盖 5 条历史 assistant:首帧 `0/5` hydrated,第一次 idle `2/5`,第二次 idle `4/5`,第三次 idle `5/5`。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/components/MessageList.test.tsx" -t "旧会话 idle 后应分批恢复历史 Markdown hydrate|旧会话首帧应延后历史助手 contentParts 与 Markdown 细节扫描|已分页旧会话首帧应只把尾部相关 turns 的 threadItems 纳入计算|旧会话消息较少但执行过程很多时也应延后构建 timeline" -npx eslint "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" --max-warnings 0 -npm run bridge:health -- --timeout-ms 5000 -``` - -结果: - -- MessageList 定向回归:通过,`4` 个测试通过。 -- ESLint touched files:通过。 -- DevBridge 健康检查:失败,`http://127.0.0.1:3030/health` 未监听。 -- TypeScript:本轮未追加全量 typecheck;当前已有外部 `tsc --noEmit` 与 `rustc` 高 CPU 进程,避免重复启动影响用户本机。 - -下一步: - -1. DevBridge 恢复后跑真实 E2E,确认 `historicalMarkdownDeferredMax` 是否命中,且 `longTaskMaxMs` 是否下降。 -2. 若 idle 后仍有峰值,继续把 timeline hydrate 与 Markdown hydrate 分开调度,或给 Markdown hydrate 增加“仅当前视口附近消息优先”。 -3. 若真实卡顿转移到会话切换前,则回到 sidebar/list_sessions 与 getSession 并发争抢治理。 - -### 2026-04-30:P1 第十六刀,旧会话 E2E 长任务指标内建采集 - -采集事实: - -- 旧会话卡顿反馈里,`clickToMessageListPaintMs` 只能说明首屏是否出现,不能说明首屏后是否有第二段主线程峰值。 -- 之前 Playwright 复测依赖临时脚本读取 `PerformanceObserver(longtask)`,不够稳定;真实复测一旦 DevBridge 恢复,应能直接从 `window.__LIME_AGENTUI_PERF__.summary()` 读取 long task 指标。 -- 当前 DevBridge 仍未监听 `3030`,且本机有 `rustc / clang / vite` 高 CPU 进程;本刀只补内建采集与单测,不启动 GUI smoke。 - -已完成: - -- `agentUiPerformanceMetrics.ts`: - - 在浏览器支持 `PerformanceObserver` 且支持 `longtask` entry 时,自动注册 long task observer。 - - observer 会把长任务写入 `agentUi.longTask` phase,并绑定最近一次有 `sessionId` 的会话上下文。 - - summary 增加 `longTaskCount / longTaskMaxMs`,避免 E2E 还要自行维护临时 long task 数组。 - - 保持 WebView / jsdom 不支持 longtask 时静默降级,不阻塞页面。 -- `agentUiPerformanceMetrics.test.ts`:补充 summary 断言,确保 `session.switch.success.durationMs` 不会污染 `longTaskMaxMs`,只统计 `agentUi.longTask.durationMs`。 - -已验证: - -```bash -npm exec -- vitest run "src/lib/agentUiPerformanceMetrics.test.ts" -npx eslint "src/lib/agentUiPerformanceMetrics.ts" "src/lib/agentUiPerformanceMetrics.test.ts" --max-warnings 0 -npx tsc --noEmit --pretty false --target ES2020 --module ESNext --moduleResolution node --skipLibCheck --lib DOM,ES2020 "src/lib/agentUiPerformanceMetrics.ts" -npm run bridge:health -- --timeout-ms 5000 -``` - -结果: - -- 性能指标汇总单测:通过,`2` 个测试通过。 -- ESLint touched metrics files:通过。 -- `agentUiPerformanceMetrics.ts` 聚焦类型检查:通过。 -- DevBridge 健康检查:失败,`http://127.0.0.1:3030/health` 未监听。 -- GUI / Playwright:本刀未执行,原因仍是 `DevBridge 3030` 未就绪且本机已有高 CPU 编译链,贸然启动会污染卡顿采样。 - -下一步: - -1. DevBridge 恢复后,Playwright 复测只需读取 `window.__LIME_AGENTUI_PERF__.summary()`,重点看 `longTaskCount / longTaskMaxMs / historicalMarkdownDeferredMax / threadItemsScanDeferredCount`。 -2. 若 `longTaskMaxMs` 仍高但首屏快,下一刀继续把 historical timeline summary 构建或展开 hydrate 做视口优先 / idle 分批。 -3. 若 long task 主要出现在 `getSession` 返回前后,转后端分页/缓存和 sidebar refresh 优先级治理,不再只做 MessageList 微调。 - -### 2026-04-30:P1 第十七刀,旧会话 threadItems 展开前不扫描 - -采集事实: - -- 第十五刀已经把 Markdown hydrate 改为分批,但 historical timeline ready 后仍会对大 `threadItems` 数组做一次同步过滤与 timeline 构建。 -- 用户反馈的“打开旧对话后鼠标 loading、CPU/内存飙高”更像首屏之后的主线程峰值;如果用户没有展开历史执行过程,立即扫描完整工具轨迹不是首屏必要工作。 -- 当前真实 E2E 仍受 DevBridge `3030` 未就绪阻塞,本刀先把可确定的前端同步扫描从自动 idle 路径移到用户展开路径。 - -已完成: - -- `MessageList.tsx`: - - 增加 `shouldDeferRestoredThreadItemsUntilExpand`,旧会话在没有聚焦 timeline、没有活动回合、没有用户展开历史执行过程时,即使 timeline ready 也继续保持 `renderedThreadItems=[]`。 - - 旧会话仍会用轻量 turn/message 映射渲染“执行过程已折叠”按钮,但按钮文案改为“点击展开后加载执行细节”,避免空 timeline 直接消失。 - - 用户点击折叠按钮后,才解除 `threadItems` 扫描,且继续只按当前渲染窗口相关 turns 过滤,避免全历史全部挂载。 -- `MessageList.test.tsx`: - - 更新已分页旧会话回归:首帧与 idle 后都保持 `threadItemsCount=0 / threadItemsScanDeferred=true`,点击执行过程折叠按钮后才出现 `threadItemsCount=10 / threadItemsScanDeferred=false`。 - - 保留 contentParts / Markdown 分批回归,确认正文 hydrate 不再强制带动工具轨迹扫描。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/components/MessageList.test.tsx" -t "旧会话 idle 后应分批恢复历史 Markdown hydrate|旧会话首帧应延后历史助手 contentParts 与 Markdown 细节扫描|已分页旧会话展开执行过程前不应扫描 threadItems,展开后只纳入尾部相关 turns|旧会话消息较少但执行过程很多时也应延后构建 timeline" -npm exec -- vitest run "src/components/agent/chat/components/MessageList.test.tsx" -t "旧会话|已分页旧会话|历史" -npm exec -- vitest run "src/components/agent/chat/components/MessageList.test.tsx" -npm exec -- vitest run "src/lib/agentUiPerformanceMetrics.test.ts" -npx eslint "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" "src/lib/agentUiPerformanceMetrics.ts" "src/lib/agentUiPerformanceMetrics.test.ts" --max-warnings 0 -npm run bridge:health -- --timeout-ms 5000 -``` - -结果: - -- MessageList 关键旧会话回归:通过,`4` 个测试通过。 -- MessageList 旧会话相关回归:通过,`15` 个测试通过。 -- MessageList 全量组件单测:通过,`91` 个测试通过。 -- 性能指标汇总单测:通过,`2` 个测试通过。 -- ESLint touched files:通过。 -- DevBridge 健康检查:失败,`http://127.0.0.1:3030/health` 未监听。 - -下一步: - -1. DevBridge 恢复后真实复测:如果 `longTaskMaxMs` 仍高,优先看 `buildMessageTurnGroups(renderedMessages)` 与大量 Markdown 视口外 hydrate;如果 `threadItemsScanDeferredCount` 命中且 long task 下降,则本刀有效。 -2. 若用户展开历史执行过程仍卡,下一刀把展开后的 timeline 也做分批/worker 化,而不是在展开瞬间一次性挂完整工具轨迹。 -3. 若真实卡顿已转移到 `getSession` 或 sidebar list 并发,回到后端分页/缓存与 sidebar refresh 优先级治理。 - -### 2026-05-01:P1 第十八刀,DevBridge 事件流断线停止自动重连风暴 - -采集事实: - -- 登录完成后,DevBridge `3030 /health` 一度恢复,旧会话可真实打开。 -- Playwright 真实采样: - - `PPT大纲规划`:`runtimeGetSessionDurationMs≈201ms`、`clickToMessageListPaintMs≈506ms`、`longTaskCount=2`、`longTaskMaxMs≈114ms`、`messages=2`、`threadItems=4`。 - - `AI网关MVP规划`:`runtimeGetSessionDurationMs≈359ms`、`clickToMessageListPaintMs≈507ms`、`longTaskCount=1`、`longTaskMaxMs≈53ms`、`messages=2`、`threadItems=5`。 -- 这两个 recent 样本都不是大历史,无法验证第十七刀的大 `threadItems` 展开前延后收益。 -- 继续点击/加载更多时,DevBridge 再次掉线;页面产生大量 `/events?...` 的 `ERR_CONNECTION_REFUSED`,控制台 error 瞬间上涨到 `175+`。根因是浏览器 `EventSource` 在已打开事件流断线后自动重连,而 `listenViaHttpEvent` 之前选择保留连接。 -- 这类事件流重连风暴会直接放大 CPU、console 噪音与“鼠标 loading”体感,且与消息渲染优化无关,必须先止血。 - -已完成: - -- `src/lib/dev-bridge/http-client.ts`: - - `listenViaHttpEvent` 在事件流已建立后遇到 `onerror` 时,改为关闭 `EventSource`、删除 hub,并停止浏览器自动重连。 - - 保持“不把一次已建立事件流断开误标记为整体桥不可用”,避免单个 SSE 结束影响普通 invoke。 - - 下次调用 `safeListen/listenViaHttpEvent` 时仍可重新建新连接,但不会由同一个 EventSource 在后台无限刷 `/events`。 -- `src/lib/dev-bridge/http-client.test.ts`: - - 更新回归为“已建立事件流断开后应关闭连接,避免自动重连风暴”。 - - 保留“事件流结束不影响后续 invoke”的回归。 - -已验证: - -```bash -npm exec -- vitest run "src/lib/dev-bridge/http-client.test.ts" -npm exec -- vitest run "src/lib/dev-bridge/http-client.test.ts" "src/lib/dev-bridge/safeInvoke.test.ts" -npx eslint "src/lib/dev-bridge/http-client.ts" "src/lib/dev-bridge/http-client.test.ts" --max-warnings 0 -npm run test:contracts -npm run bridge:health -- --timeout-ms 5000 -``` - -结果: - -- DevBridge HTTP / safeInvoke 定向回归:通过,`28` 个测试通过。 -- ESLint touched bridge files:通过。 -- 命令契约:通过。 -- DevBridge 健康检查:最后再次失败,`http://127.0.0.1:3030/health` 未监听;因此本刀代码热更新后的真实浏览器复测未能闭环。 - -下一步: - -1. DevBridge 稳定恢复后,刷新页面重测 `/events` 断线场景,确认 console 不再出现同一个事件的无限 `ERR_CONNECTION_REFUSED`。 -2. 再用 `Slow typing E2E` / `AI Trends Task` 这两个 40 消息样本做真实打开测试,读取 `historicalMarkdownDeferredMax`、`threadItemsScanDeferredCount`、`longTaskMaxMs`。 -3. 如果大历史仍有 long task,下一刀优先看 Markdown 视口外 hydrate 和展开后的 timeline 分批;如果 long task 主要来自 DevBridge 掉线/事件流,则继续治理事件桥生命周期。 - -### 2026-05-01:P1 第十九刀,侧栏会话加载去重与导航后延迟 - -采集事实: - -- DevBridge 稳定时的 Playwright 采样显示,打开 `Slow typing E2E` / `AI Trends Task` 这类旧会话时,`agent_runtime_get_session(historyLimit: 40)` 本身可在约 `172-364ms` 返回,但同一窗口内仍会出现 `agent_runtime_list_sessions(limit 21/31/41)`、`workspace_*` 和 `agent_runtime_update_session` 抢占 invoke 通道。 -- 侧栏搜索 / 加载更多路径会在旧会话点击前后继续触发 recent / archived list reload;在 invoke 单通道或 DevBridge 忙时,会放大“点击后鼠标 loading、CPU/内存飙高”的体感。 -- 搜索弹窗点击历史会话此前没有统一写入 `sidebar.conversation.click`,导致 E2E 只能看最终 paint,难以稳定还原 click-to-paint 链路。 - -已完成: - -- `AppSidebar.tsx`: - - 搜索结果点击历史会话时记录 `sidebar.conversation.click`,补上 `source=sidebar_search / sessionId / workspaceId`。 - - recent / archived 会话列表加载增加 in-flight 去重与 pending reload 合并,避免加载更多或焦点刷新同时发起多次 list invoke。 - - 点击会话后设置 `conversationNavigationDeferUntilRef`,在已有缓存可展示时把侧栏列表刷新延后 `12s`,优先把 invoke 通道留给旧会话 `getSession`。 - - 搜索结果在 `sidebarSessionsLoading` 时禁用并显示 progress 光标,避免用户在 list reload 中重复点击造成并发导航。 -- `AppSidebar.test.tsx`:补充搜索结果点击埋点断言,确保 search 来源的旧会话导航可被 E2E 采样。 - -已验证: - -```bash -npm exec -- vitest run "src/components/AppSidebar.test.tsx" -t "搜索弹窗|搜索结果" -npx eslint "src/components/AppSidebar.tsx" "src/components/AppSidebar.test.tsx" --max-warnings 0 -``` - -结果: - -- AppSidebar 搜索相关回归:通过,`5` 个测试通过。 -- ESLint touched sidebar files:通过。 -- DevBridge / Playwright:中途曾采到 `Slow typing E2E` 打开首屏约 `232ms`、`runtimeGetSessionDurationMs≈172ms`、`longTaskMaxMs≈69ms`;随后 `3030 /health` 再次掉线,无法把本刀做成稳定 E2E 结论。 - -下一步: - -1. DevBridge 恢复后,复测加载更多后点击旧会话,确认点击后 `12s` 内不再出现侧栏 list reload 抢占 `getSession`。 -2. 如果仍看到 `agent_runtime_update_session` 与下一次旧会话切换重叠,继续治理 `AgentChatWorkspace` 的 background recent metadata sync。 -3. 如果 list reload 已延后但首屏仍慢,回到 `useAgentSession.getSession` 和 MessageList 首帧分片继续看 long task。 - -### 2026-05-01:P1 第二十刀,会话切换期间延后 background recent metadata 回填 - -采集事实: - -- 第十九刀后,侧栏 list reload 已经可以延后;但一次 Playwright trace 仍显示在连续打开旧会话时,`AgentChatWorkspace` 的 `agent_runtime_update_session` background 回填可能在约 `12-18s` 后与下一次 `getSession` 撞车。 -- 这类 `recent_preferences / recent_team_selection` 回填不是首屏必须项;它应该服务后续恢复体验,而不能和旧会话打开主链抢 DevBridge invoke 通道。 -- 本轮开始前,当前浏览器页签仍停留在 `http://127.0.0.1:1420/`,但 DevBridge `http://127.0.0.1:3030/health` 不可用;Playwright console 明确为 `ERR_CONNECTION_REFUSED`、`bridge cooldown active`、`workspace_get / agent_runtime_list_sessions / aster_agent_init` 失败。因此本刀先做可验证的前端调度治理,E2E 只记录阻塞原因,不宣布交互可交付。 - -已完成: - -- `AgentChatWorkspace.tsx`: - - 新增 `SESSION_RECENT_METADATA_NAVIGATION_DEFER_MS=20s` 与 `sessionRecentMetadataNavigationDeferUntilRef`。 - - 任意会话切换、子代理会话打开、返回父会话前,先标记 recent metadata background sync 的导航保护窗口。 - - background priority 的 recent metadata flush 若命中导航保护窗口,不再立刻调用 `updateAgentRuntimeSession`,而是按剩余保护时间重新 idle 调度;immediate priority 不受影响。 - - 保留“如果 background flush 触发时已经不是当前 session,则直接 resolve 并跳过更新”的原有保护。 -- `useWorkspaceTopicSwitch.ts`: - - 增加 `onBeforeTopicSwitch` 回调,并确保在项目解析后端查询前发出导航信号。 - - `runTopicSwitch` 直接调用路径也会发出导航信号;`switchTopic` 内部 fast path 不重复发。 -- `useWorkspaceTopicSwitch.test.tsx`:新增 3 个回归,覆盖 current-project fast path、需要项目解析路径、直接 `runTopicSwitch` 路径的导航信号顺序。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/workspace/useWorkspaceTopicSwitch.test.tsx" -npm exec -- vitest run "src/components/AppSidebar.test.tsx" -t "搜索弹窗|搜索结果" "src/components/agent/chat/workspace/useWorkspaceTopicSwitch.test.tsx" -npx eslint "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/workspace/useWorkspaceTopicSwitch.ts" "src/components/agent/chat/workspace/useWorkspaceTopicSwitch.test.tsx" --max-warnings 0 -npm run bridge:health -- --timeout-ms 5000 -``` - -结果: - -- `useWorkspaceTopicSwitch` 定向回归:通过,`3` 个测试通过。 -- AppSidebar 搜索相关回归复跑:通过,`5` 个测试通过;同命令中的 `useWorkspaceTopicSwitch` 因 `-t` 过滤被跳过,已由上一条单独覆盖。 -- ESLint touched workspace files:通过。 -- DevBridge 健康检查:失败,`http://127.0.0.1:3030/health` 未监听。 -- Playwright 当前页:`http://127.0.0.1:1420/`,console 仍是 bridge 断线类错误;当前环境不能给出旧会话真实交互闭环。 -- Playwright 污染态数值:`traceCount=240`,最新 trace 包含 `aster_agent_init / sceneapp_list_catalog / workspace_get / get_provider_ui_state` bridge 失败;`window.__LIME_AGENTUI_PERF__.summary()` 捕获到 `agentRuntime.listSessions(limit=21)` 失败耗时约 `1635ms`,且 bridge 掉线状态下存在最高约 `4935ms` long task,因此这组数值只用于证明环境已污染,不用于判断旧会话优化效果。 - -下一步: - -1. 先恢复 DevBridge,再刷新页面清空 `window.__LIME_AGENTUI_PERF__` 和 `lime_invoke_trace_buffer_v1`,重测 `Slow typing E2E` 与 `AI Trends Task`。 -2. 复测重点看 `agent_runtime_get_session` 前后 `20s` 内是否还出现 `agent_runtime_update_session` / `agent_runtime_list_sessions` 抢占。 -3. 如果 invoke 争抢消失但仍卡,下一刀转向 MessageList 视口外 Markdown hydrate 与 timeline 展开后的分批 / worker 化。 - -### 2026-05-01:P1 第二十一刀,搜索弹窗预取延迟与点击取消 - -采集事实: - -- 第十九刀已经让侧栏 conversation shelf 的 hover 预取延迟触发,但搜索弹窗结果仍在 `focus / pointerenter` 时立即调用 `notifyTaskCenterTaskPrefetch`。 -- 用户在搜索弹窗里快速移动鼠标或准备点击旧会话时,立即预取会先发 `agent_runtime_get_session(historyLimit=40)`;如果随后立刻点击同一会话,预取与切换链路会争抢同一 DevBridge invoke 通道。 -- 旧会话打开主线只需要“点击后尽快切换”;搜索 hover 预取是优化项,不能抢占点击链路。 - -已完成: - -- `AppSidebar.tsx`: - - 搜索结果 hover / focus 改为 `900ms` dwell 后再预取,与 conversation shelf 保持一致。 - - 搜索结果 `blur / pointerleave / click / 关闭弹窗 / 卸载` 会取消待触发预取。 - - 搜索预取事件 source 改为 `sidebar_search`,便于和 conversation shelf E2E 指标区分。 -- `taskCenterDraftTaskEvents.ts`:补充 `sidebar_search` 事件来源类型。 -- `AppSidebar.test.tsx`:新增搜索结果延迟预取、快速点击取消预取并直接导航的回归。 - -已验证: - -```bash -npm exec -- vitest run "src/components/AppSidebar.test.tsx" -t "搜索结果|搜索弹窗|任务中心内悬停已有会话|点击已有会话时不应先触发旧会话预取" -npx eslint "src/components/AppSidebar.tsx" "src/components/AppSidebar.test.tsx" "src/components/agent/chat/taskCenterDraftTaskEvents.ts" --max-warnings 0 -``` - -结果: - -- AppSidebar 预取 / 搜索相关回归:通过,`9` 个测试通过。 -- ESLint touched sidebar/event files:通过。 - -下一步: - -1. DevBridge 稳定后,在搜索弹窗中 hover 旧会话不足 `900ms` 后点击,确认 trace 中不出现点击前 `agent_runtime_get_session` 预取。 -2. 如果用户长停留后预取已完成,再点击同一会话,应走 prefetch 结果而不是再发重复 getSession。 - -### 2026-05-01:P1 第二十二刀,旧会话恢复命令绕过短退避重新探测 DevBridge - -采集事实: - -- DevBridge 短暂恢复后,Playwright 点击 `Slow typing E2E`: - - `sidebar.conversation.click -> session.switch.start` 约 `324ms`。 - - 新缓存快照立即应用,页面先显示最近 `1 / 170` 条消息。 - - deferred hydration 在约 `1.26s` 后发 `agent_runtime_get_session(historyLimit=40)`,但前端 DevBridge client 仍处于 `bridge cooldown active`,导致 `getSession` 直接失败。 - - 该次污染态中 `longTaskMaxMs≈397ms`、`threadItemsScanDeferredCount=7`;由于真实 getSession 失败,这组数值不能用作最终性能结论,但明确暴露了“后端已短暂恢复,前端 cooldown 仍挡住用户主链”的问题。 -- CLI `bridge:health` 曾返回 `status=ok (1398ms)`,说明后端可恢复;但浏览器端在 cooldown 内不会重新探测,用户点击旧会话时仍可能被短退避误伤。 - -已完成: - -- `http-client.ts`: - - 新增 DevBridge cooldown bypass 命令集合。 - - `agent_runtime_get_session / agent_runtime_submit_turn / agent_runtime_create_session / agent_runtime_send_subagent_input` 这类用户主链命令在 cooldown 窗口内允许重新发起 `/health` 探测。 - - 普通后台命令仍保留 cooldown 快速失败,避免 bridge 掉线时继续刷大量后台请求。 -- `http-client.test.ts`:新增“旧会话恢复命令应允许绕过短退避重新探测”的回归。 - -已验证: - -```bash -npm exec -- vitest run "src/lib/dev-bridge/http-client.test.ts" -npm exec -- vitest run "src/lib/dev-bridge/http-client.test.ts" "src/lib/dev-bridge/safeInvoke.test.ts" -npx eslint "src/lib/dev-bridge/http-client.ts" "src/lib/dev-bridge/http-client.test.ts" --max-warnings 0 -``` - -结果: - -- DevBridge HTTP 定向回归:通过,`13` 个测试通过。 -- DevBridge HTTP + safeInvoke 回归:通过,`29` 个测试通过。 -- ESLint touched bridge files:通过。 -- E2E:本刀发现问题时 DevBridge 曾短暂恢复,随后 `3030 /health` 再次超时;因此真实旧会话闭环仍未稳定完成。 - -下一步: - -1. 等 DevBridge 再次稳定后刷新页面重测 `Slow typing E2E`:重点看 `agent_runtime_get_session` 是否能在 cooldown 污染后重新探测并成功。 -2. 若 `getSession` 成功且 trace 中无 `agent_runtime_update_session / agent_runtime_list_sessions` 抢占,再转向剩余前端 long task(当前污染态最高约 `397ms`)。 -3. 若 `getSession` 仍失败但 CLI health 正常,继续检查 browser client health cache 与 cooldown 状态暴露,必要时增加可视化 bridge 状态或手动 reset 入口。 - -### 2026-05-01:P1 第二十三刀,DevBridge 瞬断后的旧会话恢复快速失败与读命令重试 - -采集事实: - -- 复用现有 Playwright Lime 页签,刷新后点击 `Slow typing E2E`: - - `sidebar.conversation.click -> session.switch.start` 约 `60ms`。 - - `click -> cachedSnapshotApplied` 约 `60ms`。 - - `click -> messageList.paint` 约 `1700ms`,首屏先展示缓存窗口 `1 / 170` 条。 - - `longTaskMaxMs` 从上一轮污染态约 `119ms` 降到约 `72ms`。 -- 但 `agent_runtime_get_session(historyLimit=40)` 在浏览器侧被 `net::ERR_ABORTED`,最终按 `60s` 超时失败;后续 `agent_runtime_list_sessions` 与 `agent_runtime_update_session` 也各自挂到约 `60s`。 -- 同一时间用命令行直接 POST DevBridge `agent_runtime_get_session(historyLimit=40)` 可在约 `236ms` 返回,说明不是会话数据必然需要 60s,而是浏览器端在 DevBridge 瞬断 / cooldown / 后台 invoke 叠加后把用户恢复链路拖进长超时。 -- 页面刷新基线还暴露:一次非关键 `get_config` 瞬断会把 HTTP client 标记进 `3s` cooldown,随后 `agent_runtime_list_sessions / workspace_get` 这类首页与侧栏真相命令会 `0-5ms` 快速失败,导致侧栏短暂显示“还没有开始对话”。 - -已完成: - -- `src/lib/dev-bridge/http-client.ts`: - - `agent_runtime_get_session / agent_runtime_list_sessions` 从泛化 `agent_runtime_* = 60s` 收敛为 `8s` 读超时,并对连接类失败做一次强制 `/health` 探测后重试。 - - `agent_runtime_update_session` 收敛为 `5s` 后台 patch 超时,避免 recent metadata 回填占住 DevBridge 通道一分钟。 - - `agent_runtime_create_session` 单独保留 `15s` 用户主链窗口;`agent_runtime_submit_turn` 等真正长链路仍保留 `60s`。 - - `agent_runtime_list_sessions` 与 `workspace_list / workspace_get_default / workspace_get / workspace_ensure_ready` 允许绕过短退避重新探测,避免一次瞬断把首页和侧栏恢复命令挡在 cooldown 里。 -- `src/components/AppSidebar.tsx`:旧会话点击后,侧栏 recent / archived 后台刷新保护窗口从 `12s` 延长到 `30s`,降低恢复期间 list 与 getSession 抢通道概率。 -- `src/components/agent/chat/AgentChatWorkspace.tsx`:recent metadata 后台回填导航保护窗口从 `20s` 延长到 `45s`,避免 `agent_runtime_update_session` 在旧会话恢复尚未稳定时启动。 -- `src/lib/dev-bridge/http-client.test.ts`:补充读命令短超时、读命令强制健康探测重试、首页 / 侧栏命令绕过 cooldown、后台 patch 快速超时回归。 - -已验证: - -```bash -npm exec -- vitest run "src/lib/dev-bridge/http-client.test.ts" -npm exec -- vitest run "src/lib/dev-bridge/http-client.test.ts" "src/lib/dev-bridge/safeInvoke.test.ts" -npm exec -- vitest run "src/components/AppSidebar.test.tsx" -t "搜索结果|搜索弹窗|任务中心内悬停已有会话|点击已有会话时不应先触发旧会话预取" "src/components/agent/chat/workspace/useWorkspaceTopicSwitch.test.tsx" -npm exec -- vitest run "src/components/agent/chat/workspace/useWorkspaceTopicSwitch.test.tsx" -npx eslint "src/lib/dev-bridge/http-client.ts" "src/lib/dev-bridge/http-client.test.ts" "src/components/AppSidebar.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx" --max-warnings 0 -``` - -结果: - -- DevBridge HTTP 定向回归:通过,`17` 个测试通过。 -- DevBridge HTTP + safeInvoke 回归:通过,`33` 个测试通过。 -- AppSidebar 预取 / 搜索相关回归:通过,`9` 个测试通过。 -- `useWorkspaceTopicSwitch` 回归:通过,`3` 个测试通过。 -- ESLint touched files:通过。 -- Playwright 交互复测:当前浏览器页签可复用,但 DevBridge 在 Rust/Tauri rebuild 期间未监听 `3030`;`bridge:health --timeout-ms 10000` 超时。已记录为环境阻塞,不能把本轮 E2E 闭环宣称为完全通过。 - -下一步: - -1. 等 Tauri rebuild 完成、`bridge:health` 稳定后,再刷新页签清空 `window.__LIME_AGENTUI_PERF__` 与 invoke trace,重复点击 `Slow typing E2E`。 -2. 复测重点:`agent_runtime_get_session` 若再次瞬断,应在约 `8s` 内失败并重试,而不是挂到 `60s`;侧栏 `agent_runtime_list_sessions` 与 recent metadata `agent_runtime_update_session` 不应在点击后 `30-45s` 内抢通道。 -3. 若 DevBridge 稳定时 `getSession(historyLimit=40)` 仍超过 `8s`,下一刀应查 Rust 侧 `agent_runtime_get_session` 的 DB 查询、items/messages 组装与序列化耗时。 - -### 2026-05-01:P1 第二十四刀,旧会话 hydration 超时不再立即重试并延后非关键后台抢占 - -采集事实: - -- 复用现有 Playwright Lime 页签点击 `Slow typing E2E` 后,旧会话首屏已经能在缓存窗口先显示: - - `click -> switch.start` 约 `89ms`。 - - `click -> cachedSnapshotApplied` 约 `89ms`。 - - `click -> messageList.paint` 约 `1807ms`。 - - `fetchDetailStartCount=1`、`runtimeGetSessionStartCount=1`。 -- 同轮 trace 中 `agent_runtime_get_session(historyLimit=40)` 在浏览器侧约 `8004ms` 超时;之前的立即重试会继续抢占 DevBridge,使旧会话恢复、侧栏刷新和后续操作一起变慢。 -- `get_or_create_default_project` 曾在短退避或 mock fallback 下返回空对象,触发 `normalizeProject(undefined)` 类重复错误;这类错误不阻塞主链,但会污染恢复期间 CPU 和日志。 - -已完成: - -- `useAgentSession.ts` / `agentSessionDetailHydrationError.ts`: - - 将旧会话 deferred hydration 错误分为 `timeout / abort / bridge cooldown / bridge health / connection / other`。 - - 对 `timeout after 8000ms` 与 abort 类错误不再立即重试,只记录 `session.switch.fetchDetail.retrySkipped`。 - - 只对 bridge health / cooldown / 硬连接失败保留最多 `1` 次、`15s` 后的低优先级重试。 -- `http-client.ts` / `mockPriorityCommands.ts` / `tauri-mock/core.ts`: - - `get_or_create_default_project` 加入 cooldown bypass 与 bridge truth command 集合。 - - 浏览器 bridge 失败时不再把该命令落到空 mock;默认 mock 返回完整可 normalize 的 workspace 对象。 -- `ProjectSelector.tsx`:被动展示 + `deferProjectListLoad` 时,项目摘要请求延迟到 `12s idle` 后触发,减少旧会话切换瞬间的 `workspace_get/default/list` 抢占。 -- `AgentChatWorkspace.tsx`:旧会话直达时 topics/listSessions 后台加载延迟从 `12s` 提高到 `45s`。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentSessionDetailHydrationError.test.ts" "src/lib/dev-bridge/http-client.test.ts" "src/lib/dev-bridge/safeInvoke.test.ts" "src/lib/dev-bridge/mockPriorityCommands.test.ts" "src/lib/tauri-mock/core.test.ts" -npm exec -- vitest run "src/components/projects/ProjectSelector.ui.test.tsx" "src/components/agent/chat/components/ChatNavbar.test.tsx" "src/lib/dev-bridge/http-client.test.ts" "src/lib/dev-bridge/mockPriorityCommands.test.ts" -npm exec -- vitest run "src/components/agent/chat/index.test.tsx" "src/components/projects/ProjectSelector.ui.test.tsx" "src/components/agent/chat/components/ChatNavbar.test.tsx" -npm run test:contracts -``` - -结果: - -- hydration 错误分类 / DevBridge / mock 定向回归:通过。 -- ProjectSelector / AgentChatWorkspace 相关 UI 回归:通过。 -- 契约检查:通过。 -- E2E 污染态结论:浏览器侧 `getSession` 仍会 timeout,但已从多次重试收敛为单次失败并跳过即时 retry;下一刀需要解释“CLI 同命令快、浏览器页面内慢”的差异。 - -下一步: - -1. 不再继续盲目优化 SQL;先验证浏览器同源连接池是否被 DevBridge SSE 长连接占满。 -2. 如果页面内直接 `fetch('/invoke', agent_runtime_get_session)` 仍明显慢于 Node/CLI,优先收敛 `/events` 连接数。 - -### 2026-05-01:P1 第二十五刀,DevBridge SSE 事件流 multiplex,释放浏览器 invoke 连接槽 - -采集事实: - -- timeout 污染态中,CLI/Node 直连同一 `agent_runtime_get_session(historyLimit=40)` 可在约 `222-1196ms` 返回;浏览器页面内 `fetch('http://127.0.0.1:3030/invoke')` 曾出现 `12s/20s` timeout。 -- Playwright network 曾多次看到 `GET /events?event=lime%3A%2F%2Fcreation_task_submitted => 200 OK` 常驻,以及大量 `/invoke => net::ERR_ABORTED`。 -- 这说明主要瓶颈不是 Rust handler 固定慢,而是浏览器同源 HTTP/1.1 连接槽容易被多个 EventSource/SSE 长连接占住,导致 POST `/invoke` 排队超时。 - -已完成: - -- `src-tauri/src/dev_bridge.rs`: - - `/events` 保留兼容 `?event=...`,新增 `?events=[...]` multiplex 查询。 - - 单条 SSE 连接可同时监听多个 Tauri event,并在每条消息中继续携带 `{ event, payload }`。 - - 仍使用 `app_handle.listen(...)` 只监听 AppHandle 目标,避免退回 `listen_any` 后再次出现逐 token 重复吐字。 - - `DevBridgeEventListenerGuard` 改为持有多个 `EventId`,连接关闭时成组释放监听。 -- `src/lib/dev-bridge/http-client.ts`: - - 前端 HTTP event bridge 从“每个事件一条 EventSource”收敛为“当前页面一条 multiplex EventSource”。 - - 多个 `safeListen(...)` 并发注册时复用同一个 in-flight 连接初始化,按事件名分发 payload。 - - 事件流已打开后断开仍会关闭连接并停止浏览器自动重连风暴,不把整个 bridge 误标记为 unavailable。 -- `src/lib/dev-bridge/http-client.test.ts` / `src-tauri/src/dev_bridge.rs`: - - 新增多事件共用一条 SSE 连接的前端回归。 - - 新增 Rust 查询解析回归,覆盖单事件、JSON array multiplex 与逗号分隔调试格式。 - -已验证: - -```bash -npm exec -- vitest run "src/lib/dev-bridge/http-client.test.ts" "src/lib/dev-bridge/safeInvoke.test.ts" "src/lib/dev-bridge/mockPriorityCommands.test.ts" -npx eslint "src/lib/dev-bridge/http-client.ts" "src/lib/dev-bridge/http-client.test.ts" -cargo test --manifest-path "src-tauri/Cargo.toml" dev_bridge::tests::parses_ -npm run test:contracts -git diff --check -- "src/lib/dev-bridge/http-client.ts" "src/lib/dev-bridge/http-client.test.ts" "src-tauri/src/dev_bridge.rs" -npm run bridge:health -- --timeout-ms 10000 -``` - -结果: - -- DevBridge HTTP / safeInvoke / mockPriority 定向回归:通过,`40` 个测试通过。 -- Rust DevBridge event query 解析回归:通过,`2` 个测试通过。 -- ESLint touched bridge files:通过。 -- 命令契约检查:通过。 -- diff 空白检查:通过。 -- DevBridge health:`41ms` 就绪。 - -Playwright E2E 复测(复用现有 Lime 页签,点击 `Slow typing E2E`): - -- `click -> session.switch.start`: `102ms`。 -- `click -> cachedSnapshotApplied`: `103ms`。 -- 首次可见 `messageList.paint`: 约 `216ms`(缓存窗口先显示最近消息)。 -- deferred hydration `fetchDetail.start`: `1305ms`。 -- `agent_runtime_get_session(historyLimit=40)`: 成功,`471ms`,`messages=40 / total=170`。 -- `click -> session.switch.success`: `1779ms`。 -- `runtimeGetSessionErrorCount=0`,`fetchDetailErrorCount=0`,invoke error buffer 为空。 -- `longTaskCount=1`,`longTaskMaxMs=129ms`,`maxUsedJSHeapSize≈499MB`。 -- 页面内直接 `fetch('/invoke', agent_runtime_get_session historyLimit=40)`:成功,`946ms`,`messages=40 / total=170`。 -- 控制台 error:`2` 条,均为 `user.limeai.run ... /client/skills 401`,属于云端目录鉴权噪音,非本地旧会话恢复阻塞。 - -下一步: - -1. 继续把 “summary 中 clickToMessageListPaintMs 取最后一次 paint” 与“用户首屏已在约 216ms 出现”区分开,补一个首屏 paint 指标,避免后续误判。 -2. 针对 `longTaskMaxMs≈129ms` 与 `JSHeap≈499MB`,下一刀优先看 MessageList 首屏 restored-window 的 markdown / turn timeline 同步计算和 sidebar 常驻列表渲染,而不是继续加大 getSession 超时。 -3. 多开旧会话 / 新建对话后再复测 EventSource 数量,确认内部 tab 增多时仍不会回到每个事件一条长连接。 - -### 2026-05-01:P1 第二十六刀,补齐首屏 paint 指标避免误判旧会话体感 - -采集事实: - -- 第二十五刀 Playwright 复测中,旧会话实际首屏缓存窗口约 `216ms` 可见,但 `summary.clickToMessageListPaintMs` 取最后一次 `messageList.paint`,显示为约 `2704ms`。 -- 该字段容易把“首屏可见”与“hydration 后最终稳定 paint”混为一谈,后续分析会误判体感慢点。 - -已完成: - -- `agentUiPerformanceMetrics.ts`:新增 `clickToFirstMessageListPaintMs`,保留原 `clickToMessageListPaintMs` 作为最后一次 paint 兼容字段。 -- `agentUiPerformanceMetrics.test.ts`:补两次 `messageList.paint` 的回归,确保 first paint 小于等于 final paint,且 final message 指标仍来自最后一次 paint。 - -已验证: - -```bash -npm exec -- vitest run "src/lib/agentUiPerformanceMetrics.test.ts" -npm exec -- vitest run "src/lib/dev-bridge/http-client.test.ts" "src/lib/dev-bridge/safeInvoke.test.ts" "src/lib/dev-bridge/mockPriorityCommands.test.ts" "src/lib/agentUiPerformanceMetrics.test.ts" -npx eslint "src/lib/agentUiPerformanceMetrics.ts" "src/lib/agentUiPerformanceMetrics.test.ts" -git diff --check -- "src/lib/dev-bridge/http-client.ts" "src/lib/dev-bridge/http-client.test.ts" "src-tauri/src/dev_bridge.rs" "src/lib/agentUiPerformanceMetrics.ts" "src/lib/agentUiPerformanceMetrics.test.ts" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- AgentUI perf metrics 定向回归:通过,`2` 个测试通过。 -- DevBridge + AgentUI metrics 组合回归:通过,`42` 个测试通过。 -- ESLint touched metrics files:通过。 -- diff 空白检查:通过。 - -下一步: - -1. 后续 Playwright 汇报同时看 `clickToFirstMessageListPaintMs` 与 `clickToMessageListPaintMs`,前者代表用户首屏,后者代表最终稳定 paint。 -2. 若首屏仍偶发超过 `500ms`,优先查 sidebar click 期间 long task;若 final paint 慢但首屏快,优先查 hydration 后 MessageList timeline / markdown 懒加载。 - -### 2026-05-01:P1 第二十七刀,多 tab / 新建 / 两个历史对话复测 multiplex 效果 - -采集事实: - -- 复用现有 Playwright Lime 页签,注入 EventSource 统计后执行:`new-task-1 -> open-history(Slow typing E2E) -> open-history(配置 Lime API Key...) -> new-task-2`。 -- 最终活跃 EventSource 数:`1`,最终 URL 为 multiplex `/events?events=[...]`,说明第二十五刀已避免“每个事件一条 SSE 长连接”回流。 -- `agent_runtime_get_session(historyLimit=40)` 三次成功耗时约 `670ms / 299ms / 234ms`,invoke trace 无 error。 -- `Slow typing E2E`:`clickToFirstMessageListPaintMs≈95ms`、`runtimeGetSessionDurationMs≈235ms`、`longTaskMaxMs≈58ms`。 -- 第二个历史会话仍出现一次 `longTaskMaxMs≈228ms`,但不是 DevBridge 连接槽阻塞;下一步应继续看 MessageList / sidebar 渲染主线程负载。 - -结论: - -- 多 tab 与两个历史对话已能打开,不再因为 EventSource 数量导致 `/invoke` 连接槽被占满。 -- 剩余体感慢点从“网络/bridge 排队”转向“局部主线程 long task + 后端模型首字”。 - -### 2026-05-01:P0 第二十八刀,修复新建任务 createSession 失败后的永久创建锁 - -采集事实: - -- Playwright 中复现:DevBridge 曾在 Tauri rebuild 瞬间不可用,第一次 `agent_runtime_create_session` 失败后,用户继续点击发送只反复出现: - - `AgentChatPage.taskCenter.draftTab.materialize.start` - - 不再出现 `useAgentSession.createFreshSession.start` - - invoke trace 为空,textarea 保留原文,页面看起来“点击无效 / 卡住”。 -- 源码定位到 `useAgentSession.ts`:`createFreshSessionPromiseRef.current` 保存的是 `trackedCreationPromise`,但 `finally` 中比较的是原始 `creationPromise`,因此无论成功还是失败都不会清空 ref;如果首次失败返回 `null`,后续新建任务会永久复用这个已失败 promise。 - -已完成: - -- `src/components/agent/chat/hooks/useAgentSession.ts`:创建锁释放改为比较当前保存的 `trackedCreationPromise`,确保成功 / 失败后都能清空 `createFreshSessionPromiseRef`。 -- `src/components/agent/chat/hooks/useAsterAgentChat.test.tsx`:新增“新建任务失败后应释放创建锁,允许恢复桥接后再次新建”回归;覆盖首次 bridge error、第二次恢复成功。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" -t "新建任务失败后应释放创建锁|从旧会话新建任务时应立即清空当前消息" -npx eslint "src/components/agent/chat/hooks/useAgentSession.ts" "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" -``` - -结果: - -- 定向回归通过:`2` 个测试通过。 -- ESLint touched send/session files:通过。 - -Playwright E2E 复测(刷新后新建任务发送短 prompt): - -- `agent_runtime_create_session`: 成功,`168ms`。 -- `AgentStream.listenerBound`: 点击后约 `500ms`。 -- `agent_runtime_submit_turn`: 成功,`623ms`。 -- `AgentStream.submitAccepted`: 点击后约 `1124ms`。 -- `AgentStream.firstEvent/runtime_status`: 点击后约 `1257ms`。 -- `AgentStream.firstTextPaint`: 点击后约 `10246ms`,页面最终只输出一次“好”,未复现重复吐字。 -- invoke error buffer:空;long task:`0`。 - -结论: - -- “新建任务点击无效 / 不能恢复 / 只能 materialize.start”已修复。 -- 前端发送链路在 `~1.1s` 内完成提交和 runtime status;首字剩余 `~9s` 主要落在模型侧首 token,而非按钮、createSession 或 listener 绑定。 - -### 2026-05-01:P1 第二十九刀,首字路径裁掉默认占位记忆并启用通用紧凑 Prompt - -采集事实: - -- 首字 E2E 里 `turn_config.system_prompt` 混入默认项目记忆占位:`默认主角 / 待补充角色设定 / 待补充世界观背景与规则 / 第一章:待补充章节内容`。 -- 这些占位内容不会帮助回答,但会污染 prompt、增加 token 与模型路由成本。 -- 通用对话默认 Browser Assist 全量协议使首轮 system prompt 约 `4.4K` 字符;对“请只回复一个字”这类直接回答任务过重。 - -已完成: - -- `src/lib/workspace/projectPrompt.ts`:过滤默认占位项目记忆;只有角色、世界观、大纲存在真实内容时才注入 `## 项目背景`。 -- `src/lib/workspace/projectPrompt.test.ts`:新增占位记忆不注入、真实记忆保留且过滤占位字段的回归。 -- `src/components/agent/chat/utils/generalAgentPrompt.ts`:新增 `compact` prompt 变体,保留核心边界、WebSearch / Browser Assist / `lime_site_run` 约束,但移除长篇重复协议。 -- `src/components/agent/chat/AgentChatWorkspace.tsx`:通用对话在默认轻量能力态(未开启 webSearch / thinking / task / subagent,且无 contentId)使用 compact prompt;重型能力或工作区上下文继续使用完整 prompt。 -- `src/components/agent/chat/utils/generalAgentPrompt.test.ts`:新增 compact prompt 回归,确保体积下降且核心边界保留。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" "src/components/agent/chat/utils/generalAgentPrompt.test.ts" "src/lib/workspace/projectPrompt.test.ts" -t "新建任务失败后应释放创建锁|从旧会话新建任务时应立即清空当前消息|generalAgentPrompt|generateProjectMemoryPrompt" -npm exec -- vitest run "src/components/agent/chat/utils/generalAgentPrompt.test.ts" "src/lib/workspace/projectPrompt.test.ts" -npx eslint "src/components/agent/chat/hooks/useAgentSession.ts" "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" "src/components/agent/chat/utils/generalAgentPrompt.ts" "src/components/agent/chat/utils/generalAgentPrompt.test.ts" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/lib/workspace/projectPrompt.ts" "src/lib/workspace/projectPrompt.test.ts" -npm exec -- tsc --noEmit --pretty false --project tsconfig.json --incremental false -git diff --check -- "src/components/agent/chat/hooks/useAgentSession.ts" "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" "src/components/agent/chat/utils/generalAgentPrompt.ts" "src/components/agent/chat/utils/generalAgentPrompt.test.ts" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/lib/workspace/projectPrompt.ts" "src/lib/workspace/projectPrompt.test.ts" -``` - -结果: - -- 定向 vitest:通过,`12` 个匹配测试通过。 -- prompt / projectPrompt 回归:通过,`10` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit`:通过。 -- diff 空白检查:通过。 - -Playwright E2E 复测: - -- 占位记忆过滤后:`systemPromptHasPlaceholderMemory=false`,首次 `firstTextPaint≈4849ms`,`agent_runtime_create_session≈114ms`,`agent_runtime_submit_turn≈569ms`。 -- compact prompt 启用后:`systemPromptLength=938`(从约 `4431` 字符降到 `938`),`systemPromptHasPlaceholderMemory=false`。 -- compact prompt 同轮:`createSession≈97ms`,`listenerBound≈401ms`,`submitAccepted≈931ms`,`firstEvent≈1096ms`,`firstTextPaint≈5425ms`,long task `0`,invoke error buffer 空。 -- 旧会话再复测 `Slow typing E2E`:`clickToFirstMessageListPaintMs≈79ms`,`runtimeGetSessionDurationMs≈298ms`,`clickToSwitchSuccessMs≈1541ms`,long task `0`,invoke error buffer 空。 - -结论: - -- 新建任务前端发送链路已恢复,首屏 runtime status 能在约 `1.1s` 出现。 -- 首字真实文本仍受当前 `gpt-5.5` 模型首 token 影响,当前实测约 `4.8-5.4s`;如需继续压到 `2s` 内,下一刀应做“低延迟模型 / DeepSeek 快速模式”与 UI 模型选择的自动化对比,而不是继续在 React 侧盲改。 - -### 2026-05-01:P1 第三十刀,首字快速响应路由落地 - -采集事实: - -- 上一轮 Playwright 对比显示,前端发送链路已在约 `0.1s` 收到 runtime status,慢点主要在模型首 token。 -- `lime-hub / gpt-5.5` 首字约 `4.1s`,`deepseek / deepseek-chat` 首字约 `1.6s`;同样 compact prompt 下均未复现重复吐字。 -- 因此本刀不继续盲改 React 渲染,而是在“首轮轻量普通对话”里做可回退、可观测的低延迟模型路由。 - -已完成: - -- `src/components/agent/chat/utils/fastResponseModel.ts`:新增快速响应 resolver。仅当满足以下条件时自动生效:mappedTheme 为 general 的首轮轻量对话、无图片、无 contentId、无 webSearch / thinking / task / subagent、无团队/角色/上下文/技能/显式模型覆盖、当前模型为已知慢首字的 `lime-hub / gpt-5.5|gpt-5.4`,且已配置 DeepSeek provider。 -- `src/components/agent/chat/workspace/useWorkspaceSendActions.ts`:发送前注入 `providerOverride=deepseek`、`modelOverride=deepseek-chat`,并把 `harness.fast_response_routing` 写入 metadata,便于后续 E2E 从 turn_config/日志追踪。 -- `src/components/agent/chat/hooks/handleSendTypes.ts`:允许 Workspace send options 携带 `assistantDraft`,让快速响应在等待阶段显示“快速响应已启用/处理中”,不是隐式降级。 -- `src/components/agent/chat/AgentChatWorkspace.tsx`:仅在空白普通对话且当前为 `lime-hub / gpt-5.5|gpt-5.4` 时预热配置 provider 列表,避免旧会话恢复路径额外争抢 provider 加载。 -- `src/components/agent/chat/utils/fastResponseModel.test.ts`、`src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx`:补 resolver 与发送链集成回归。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/utils/fastResponseModel.test.ts" -npm exec -- vitest run "src/components/agent/chat/utils/fastResponseModel.test.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" -t "快速响应|普通发送不应把当前工作区模型当成 modelOverride|mappedTheme|自定义模型" -npx eslint "src/components/agent/chat/utils/fastResponseModel.ts" "src/components/agent/chat/utils/fastResponseModel.test.ts" "src/components/agent/chat/hooks/handleSendTypes.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx" -npm exec -- tsc --noEmit --pretty false --project tsconfig.json --incremental false -``` - -结果: - -- 快速响应 resolver 单测:通过,`7` 个测试通过。 -- 发送链定向回归:通过,`6` 个匹配测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit`:通过。 - -下一步: - -1. Playwright 复测真实新建对话,确认 `turn_config.provider_preference=deepseek`、`turn_config.model_preference=deepseek-chat`,并重新采集 `listenerBound / submitAccepted / firstEvent / firstTextDelta / firstTextPaint`。 -2. 若首字降到约 `1.6s`,保留当前“首轮轻量普通对话”范围;若仍慢,继续从 DevBridge trace 与 provider 返回事件排队排查。 -3. 后续再补可配置 UI 开关,把 `lime:agent-fast-response-mode=off` 暴露到设置或模型胶囊菜单。 - -Playwright E2E 复测: - -- 复用现有 Lime 页签,先临时把当前工作区偏好切到 `lime-hub / gpt-5.5` 以触发快速响应,测试后已恢复到原始 `deepseek / deepseek-v4-flash` 偏好。 -- 第一次复测发现 DeepSeek provider 的 `custom_models` 只有 `deepseek-v4-pro / deepseek-v4-flash`,按自定义列表选择 `deepseek-v4-flash` 后虽然成功路由,但输出出现“已完成思考 / 我们被要求...”推理说明泄漏,且 `firstTextPaint≈4.6s`,不符合“只输出好”的流式体验。 -- 已调整 resolver:DeepSeek 快速响应固定使用非推理 `deepseek-chat`,不跟随自定义 flash/pro 列表,避免 reasoning UI 泄漏与排版回归。 -- 最终复测 `turn_config.provider_preference=deepseek`、`turn_config.model_preference=deepseek-chat`,`harness.fast_response_routing` 已写入 metadata。 -- 最终复测数据:`agent_runtime_create_session=96ms`,`agent_runtime_submit_turn=396ms`,`listenerBound=12ms`,`submitAccepted=410ms`,`firstEvent=652ms`,`firstRuntimeStatus=653ms`,`firstTextDelta=2962ms`,`firstTextPaint=2962ms`(从 requestStarted 计),脚本侧 click-to-first-paint 约 `4019ms`。 -- 可见输出只剩一个“好”,未复现重复吐字;invoke error buffer 为 `0`;测试期间无新增控制台 error,刷新基线仍有 `user.limeai.run /client/skills 401` 鉴权噪音。 - -结论: - -- 快速响应路由已经按真实 turn_config 生效,并规避了 `deepseek-v4-flash` 的思考文本泄漏。 -- 首字较 `lime-hub / gpt-5.5` 的 `~5.4s` 有改善到 `~3.0s`(runtime 口径),但未稳定达到早前单独 DeepSeek 测试的 `~1.6s`;下一刀如果继续压首字,优先补“新建空白会话发送前预建 session / 减少 click->listenerBound 约 1s”的数据点,而不是再换模型。 - -补充验证: - -```bash -npm run verify:gui-smoke -``` - -结果:通过。已复用现有 headless Tauri / DevBridge,覆盖 workspace ready、browser runtime、site adapters、service skill entry、runtime tool surface 与页面级 tool surface smoke。 - -### 2026-05-01:P1 第三十一刀,后端直发事件去重,收敛重复吐字风险 - -采集事实: - -- 流式事件在 `record_runtime_stream_event` 中会对 `text_delta` / `runtime_status` 等低延迟事件先直发给前端。 -- 同一事件随后又会从 `stream_reply_once` 的统一 `app.emit` 路径再次发送,形成同一 `text_delta` 被前端处理两次的高风险路径。 -- `ItemStarted / ItemUpdated / ItemCompleted` 已由 `AgentTimelineRecorder` 持久化并发出等价 item 事件,也不应再由统一 emit 重复补发。 -- `Warning / Error / ArtifactSnapshot / ContextCompaction*` 会投影为不同 item 或保留原始语义,不能粗暴吞掉原始事件。 - -已完成: - -- `src-tauri/src/commands/aster_agent_cmd/reply_runtime.rs`:`stream_reply_once` 的 `on_event` 回调改为返回 `bool`,表示当前事件是否已由更低层发送;已发送时跳过统一 `app.emit`。 -- `src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs`:`record_runtime_stream_event` 返回已发送状态;直接直发事件返回 `true`,timeline-owned item 事件在 recorder 成功后也返回 `true`。 -- `src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs`:新增 `timeline_recorder_emits_equivalent_runtime_event`,只对 runtime item 三类事件去重;warning/error/artifact 等继续保留原始 emit。 -- `src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs`:补充 warning 场景回归,防止把 timeline item 投影和原始 warning 语义混为一类。 - -已验证: - -```bash -rustfmt --edition 2021 --check "src-tauri/src/commands/aster_agent_cmd/reply_runtime.rs" "src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs" -npm exec -- vitest run "src/components/agent/chat/hooks/agentChatHistory.test.ts" -t "重复吐字|累计快照" -cargo test --manifest-path "src-tauri/Cargo.toml" -p lime runtime_stream_ --no-fail-fast -``` - -结果: - -- Rust touched files 格式检查:通过。 -- 前端重复吐字/累计快照回归:通过,`2` 个匹配测试通过。 -- Rust runtime stream 定向测试:通过,`4` 个匹配测试通过;`1131` 个过滤。 - -结论: - -- 后端低延迟直发事件不再被统一 emit 二次发送,重复吐字主风险路径已收敛。 -- 保留 warning/error/artifact 原始语义,不因去重破坏前端错误、告警或 artifact 处理。 - -### 2026-05-01:P1 第三十二刀,快速响应专用短 Prompt 与真实 E2E 复测 - -采集事实: - -- 后端去重后,真实 E2E 新建对话输出只出现一次“好”,未再复现重复吐字。 -- 同一轮采集显示前端链路已很快:`listenerBound≈121ms`、`submitAccepted≈253ms`、`firstRuntimeStatus≈287ms`。 -- 首字仍慢在模型首 token:快速响应路由命中 `deepseek / deepseek-chat` 后,普通 compact prompt 下 `firstTextPaint≈4665ms`。 -- 该请求仍携带通用 compact prompt、Browser Assist 协议和 harness 说明;对“只回答一个字”这类轻量首轮对话仍偏重。 - -已完成: - -- `src/components/agent/chat/utils/fastResponseModel.ts`:新增 `buildAgentFastResponseSystemPrompt`,为快速响应路由生成约 `163` 字符的短系统提示词,强调直接回答、严格遵守单字/格式要求、不输出思维链、不主动联网/工具/落盘。 -- `src/components/agent/chat/hooks/agentChatShared.ts`、`src/components/agent/chat/hooks/handleSendTypes.ts`、`src/components/agent/chat/hooks/agentStreamUserInputSendPreparation.ts`:新增单次发送级 `systemPromptOverride`,避免把全局通用 prompt 改短,保证只影响快速响应命中的轻量首轮。 -- `src/components/agent/chat/workspace/useWorkspaceSendActions.ts`:快速响应命中时同时注入 `providerOverride`、`modelOverride`、`harness.fast_response_routing`、assistant draft 和短 prompt override。 -- `src/components/agent/chat/utils/fastResponseModel.test.ts`、`src/components/agent/chat/hooks/agentStreamUserInputSendPreparation.test.ts`、`src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx`:补齐短 prompt、单次 prompt override、发送链注入回归。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/utils/fastResponseModel.test.ts" "src/components/agent/chat/hooks/agentStreamUserInputSendPreparation.test.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" -npx eslint "src/components/agent/chat/utils/fastResponseModel.ts" "src/components/agent/chat/utils/fastResponseModel.test.ts" "src/components/agent/chat/hooks/agentChatShared.ts" "src/components/agent/chat/hooks/handleSendTypes.ts" "src/components/agent/chat/hooks/agentStreamUserInputSendPreparation.ts" "src/components/agent/chat/hooks/agentStreamUserInputSendPreparation.test.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" -npm exec -- tsc --noEmit --pretty false --project tsconfig.json --incremental false -git diff --check -- "src/components/agent/chat/utils/fastResponseModel.ts" "src/components/agent/chat/utils/fastResponseModel.test.ts" "src/components/agent/chat/hooks/agentChatShared.ts" "src/components/agent/chat/hooks/handleSendTypes.ts" "src/components/agent/chat/hooks/agentStreamUserInputSendPreparation.ts" "src/components/agent/chat/hooks/agentStreamUserInputSendPreparation.test.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" "src-tauri/src/commands/aster_agent_cmd/reply_runtime.rs" "src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs" -npm run bridge:health -- --timeout-ms 120000 -npm run verify:gui-smoke -``` - -结果: - -- 定向 vitest:通过,`134` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit`:通过。 -- diff 空白检查:通过。 -- DevBridge 健康检查:通过,`72ms` 就绪。 -- GUI smoke:通过,覆盖 workspace ready、browser runtime、site adapters、service skill entry、runtime tool surface 与页面级 tool surface。 - -Playwright E2E 复测: - -- 复用现有 `http://127.0.0.1:1420/` Lime 页签,设置 `lime:agent-debug=1`、`lime:agent-fast-response-mode=auto`、`lime:onboarding-completed=true`。 -- 新建首轮轻量对话,输入 `只回答一个字:好 `。 -- 网络请求确认 `turn_config.provider_preference=deepseek`、`turn_config.model_preference=deepseek-chat`。 -- 网络请求确认 `turn_config.system_prompt` 已切为快速响应短 prompt,内容以“你是 Lime 的快速响应助手”开头,不再携带 Browser Assist 长协议。 -- 采集结果:`listenerBound≈7ms`、`submitAccepted≈215ms`、`firstEvent≈336ms`、`firstRuntimeStatus≈337ms`、`firstTextDelta≈3645ms`、`firstTextPaint≈3646ms`。 -- 可见输出只出现一次“好”;`textRenderFlush` 仅一次,`accumulatedChars=1`、`backlogChars=1`。 -- 控制台 error/warning:本轮复测后 `0`。 - -结论: - -- 重复吐字风险已从后端 emit 层和前端累计文本层双向验证。 -- 快速响应短 prompt 把同环境首字从 `~4.7s` 压到 `~3.6s`,前端提交链路稳定在 `~0.3s` 内,剩余主要是 DeepSeek provider 首 token 波动。 -- 下一步若继续追 `2s` 内首字,不应再盲改 React;优先做 provider/model A/B(例如可控地评估非推理低延迟模型)和“首 token 到达前的可感知 UI”优化。 - -### 2026-05-01:P1 第三十三刀,DeepSeek 推理模型首轮降级与 E2E 反证 - -采集事实: - -- 复用现有 `http://127.0.0.1:1420/` Lime 页签,刷新后控制台基线为 `0` error / `0` warning。 -- 连续 4 轮新建首轮轻量对话(`只回答一个字:好 E2E-*`)显示前端链路仍快:`listenerBound=33-56ms`、`submitAccepted=160-298ms`、`firstRuntimeStatus=196-352ms`、`firstTextPaint=1581-4073ms`。 -- 但当当前模型是 `deepseek-v4-flash` 时,快速响应短 prompt 没有命中,真实请求仍为 `provider=deepseek`、`model=deepseek-v4-flash`、通用长 prompt。 -- 该路径复现了用户反馈的排版/吐字问题:可见“已完成思考 / 我们被要求...”推理文本,且 1 轮输出成 `好 E2E-*`,没有严格遵守单字输出。 -- 补丁首版后再次测到当前模型变为 `deepseek-reasoner` 时,仍未命中快速响应;原因是页面只在 `lime-hub / gpt-5.x` 预加载快速响应 Provider,DeepSeek 当前 Provider 场景会因为 Provider 列表尚未加载而走 `fast-provider-unavailable`。 - -已完成: - -- `src/components/agent/chat/utils/fastResponseModel.ts`:把快速响应触发条件从“只识别 lime-hub 慢首字模型”扩展为“lime-hub gpt-5.x 或 DeepSeek 推理/flash/pro/r1 类模型”。 -- `src/components/agent/chat/utils/fastResponseModel.ts`:当前 Provider 已经是 DeepSeek 时,不再依赖 Provider 列表预加载;直接使用当前 `providerType` 作为本轮 `providerOverride`,并把模型降级到非推理 `deepseek-chat`。 -- `src/components/agent/chat/AgentChatWorkspace.tsx`:Provider 预加载条件改为复用同一个快速响应候选判断,避免 UI 层与发送层判断漂移。 -- `src/components/agent/chat/utils/fastResponseModel.test.ts`:新增 DeepSeek `deepseek-v4-flash`、`deepseek-reasoner` 与无需 Provider 列表的降级回归。 -- `src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx`:新增发送链回归,覆盖 DeepSeek 推理模型不等待 Provider 列表也能注入 `providerOverride=deepseek`、`modelOverride=deepseek-chat` 和快速响应短 prompt。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/utils/fastResponseModel.test.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" -npx eslint "src/components/agent/chat/utils/fastResponseModel.ts" "src/components/agent/chat/utils/fastResponseModel.test.ts" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" -git diff --check -- "src/components/agent/chat/utils/fastResponseModel.ts" "src/components/agent/chat/utils/fastResponseModel.test.ts" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" -``` - -结果: - -- 定向 vitest:通过,`133` 个测试通过。 -- ESLint touched files:通过。 -- diff 空白检查:通过。 - -补充验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/utils/fastResponseModel.test.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" -npx eslint "src/components/agent/chat/utils/fastResponseModel.ts" "src/components/agent/chat/utils/fastResponseModel.test.ts" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" -npm exec -- tsc --noEmit --pretty false --project tsconfig.json --incremental false -npm run bridge:health -- --timeout-ms 120000 -npm run verify:gui-smoke -npm run verify:local -``` - -结果: - -- 定向 vitest:通过,`133` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit`:通过。 -- DevBridge 健康检查:通过,首轮约 `26ms`,后续约 `2ms`。 -- GUI smoke:通过,覆盖 workspace ready、browser runtime、site adapters、service skill entry、runtime tool surface 与页面级 tool surface。 -- 完整 `npm run verify:local`:通过;包含 app version、lint、typecheck、vitest smart、contracts、Rust cargo test 与 GUI smoke。既有 warning 未阻塞:`runtime_evidence_pack_service.rs` unused imports、`modality_runtime_contracts.rs` dead_code、update 测试里的 signature mismatch / 404 diagnostic 文案。 - -Playwright E2E 修复后复测: - -- 复用现有 `http://127.0.0.1:1420/` Lime 页签,设置 `lime:agent-debug=1`、`lime:agent-fast-response-mode=auto`、`lime:onboarding-completed=true`。 -- 当前 UI 仍显示 `deepseek-v4-flash` 属于预期;本轮只做单次发送降级,不修改全局模型选择。 -- 连续 2 轮输入 `只回答一个字:好 E2E-DEEPSEEK-DOWNGRADE-*`,请求体均确认 `turn_config.provider_preference=deepseek`、`turn_config.model_preference=deepseek-chat`。 -- 请求体均确认 `turn_config.system_prompt` 已切为快速响应短 prompt,开头为“你是 Lime 的快速响应助手”;`harness.fast_response_routing` 已写入 metadata。 -- Run 1:`listenerBound=24ms`、`submitAccepted=130ms`、`firstEvent=151ms`、`firstRuntimeStatus=151ms`、`firstTextDelta=1656ms`、`firstTextPaint=1657ms`、`flushCount=1`。 -- Run 2:`listenerBound=16ms`、`submitAccepted=95ms`、`firstEvent=114ms`、`firstRuntimeStatus=114ms`、`firstTextDelta=829ms`、`firstTextPaint=830ms`、`flushCount=1`。 -- 两轮可见输出都只包含“好”,未出现“已完成思考 / 我们被 / 推理”等思考文本或 marker 回显;控制台 error/warning 为 `0`。 - -结论: - -- DeepSeek 推理/Flash 模型轻量首轮现在会自动走单次发送降级:`deepseek-v4-flash|reasoner -> deepseek-chat`,同时套用短 prompt。 -- 真实 E2E 已证明修复后不再泄漏思考文本、不再重复吐字,首字从此前 `1.5-5s` 波动收敛到 `0.83s / 1.66s` 两轮。 -- 完整 `npm run verify:local` 已通过,本刀达到 GUI 主路径可交付门槛。 -- 下一刀继续压旧会话恢复卡顿:优先采集会话打开 CPU/内存峰值与 `MessageList` timeline 主线程计算,不再在本刀内扩大快速响应逻辑范围。 - -### 2026-05-01:P1 第三十四刀,旧会话 MessageList 同步计算细分采集 - -采集事实: - -- 第三十三刀后,首字快速响应主链已收口;剩余用户体感慢点回到旧会话打开后的 CPU / 内存峰值与局部主线程 long task。 -- 现有 `agentUiPerformanceMetrics` 已能看到 `clickToFirstMessageListPaintMs`、`longTaskMaxMs`、JS heap 与是否延后 timeline / Markdown,但还不能区分 MessageList 内部是 `threadItems` 扫描、timeline 构建、消息分组还是 render group 拼装在耗时。 -- DevBridge 当前未就绪:`npm run bridge:health -- --timeout-ms 120000` 超时,`3030` 未监听;本机同时有 Tauri/Rust watch 编译链高 CPU,真实 Playwright 采样会被污染,本刀先补内建细分采集,不扩大 UI 行为。 - -已完成: - -- `src/components/agent/chat/components/MessageList.tsx`:新增 `measureMessageListComputation`,在不引入渲染副作用的前提下记录同步计算耗时。 -- `MessageList` 旧会话 metric context 新增: - - `messageListThreadItemsScanMs` - - `messageListTimelineBuildMs` - - `messageListGroupBuildMs` - - `messageListRenderGroupsMs` - - `messageListHistoricalMarkdownTargetScanMs` - - `messageListHistoricalContentPartsScanMs` - - `messageListComputeMs` -- `src/lib/agentUiPerformanceMetrics.ts`:summary 新增对应 max 字段,Playwright 可直接通过 `window.__LIME_AGENTUI_PERF__.summary()` 判断下一刀该打哪个热点,而不是只看 long task 总值。 -- `src/components/agent/chat/components/MessageList.test.tsx`、`src/lib/agentUiPerformanceMetrics.test.ts`:补旧会话 commit metric 与 summary 聚合回归。 - -已验证: - -```bash -npm exec -- vitest run "src/lib/agentUiPerformanceMetrics.test.ts" "src/components/agent/chat/components/MessageList.test.tsx" -t "agentUiPerformanceMetrics|旧会话首帧应延后历史助手 contentParts" -npm exec -- vitest run "src/components/agent/chat/components/MessageList.test.tsx" -t "旧会话|已分页旧会话|历史" -npx eslint "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" "src/lib/agentUiPerformanceMetrics.ts" "src/lib/agentUiPerformanceMetrics.test.ts" --max-warnings 0 -git diff --check -- "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" "src/lib/agentUiPerformanceMetrics.ts" "src/lib/agentUiPerformanceMetrics.test.ts" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- 定向性能汇总与旧会话 contentParts 回归:通过,`3` 个测试通过。 -- MessageList 旧会话 / 已分页旧会话 / 历史回归:通过,`15` 个测试通过。 -- ESLint touched files:通过。 -- diff 空白检查:通过。 - -暂未完成验证: - -- TypeScript 全量 `tsc --noEmit`:已启动但超过数分钟无输出;本机同时存在多路 `rustc` / Tauri watch 编译高 CPU,为避免继续污染用户反馈的 CPU 飙高场景,已停止本轮发起的 typecheck。上一刀完整 `npm run verify:local` 已通过;本刀后续在 DevBridge 稳定时补一次统一验证。 -- Playwright 旧会话真实采样:当前 DevBridge `3030` 未就绪,不能给出可信 E2E 数值。 - -下一步: - -1. 等 DevBridge 恢复后,用 Playwright 连续打开 2-3 个旧会话,读取 `window.__LIME_AGENTUI_PERF__.summary()` 中新增的 MessageList 细分 max 字段。 -2. 若 `messageListTimelineBuildMaxMs` 或 `messageListThreadItemsScanMaxMs` 占主因,再继续把 timeline 构建移动到展开后或 Worker;若 `messageListRenderGroupsMaxMs` 占主因,优先看历史消息窗口和 DOM 虚拟化。 -3. 若细分项都低但 `longTaskMaxMs / maxUsedJSHeapSize` 仍高,下一刀转向常驻 sidebar/tab DOM 数量和 DevBridge/Rust watch 环境干扰,而不是继续改 MessageList。 - -### 2026-05-01:P1 第三十五刀,首页回车首帧会话壳去阻塞 - -采集事实: - -- 复用现有 `http://127.0.0.1:1420/` Lime 页签,不新启违规 Playwright 浏览器。 -- 修复前在 DevBridge 未就绪场景下复现:输入后按 Enter,`homeInputToPendingShellMs=11ms` 只是状态已入队,真实用户输入文本约 `1331ms` 才可见;同一请求出现 `542ms / 556ms` long task,`homeInputToSendDispatchMs=458ms`,体感会出现鼠标 busy。 -- 复现时还看到输入框内容变化后会触发空白首页后台 `ensureSession()` 预热;这会在用户尚未发送时就创建/恢复会话,容易和 Enter 后的发送链路、侧边栏 list、DevBridge invoke 抢主线程与桥接通道。 - -已完成: - -- `src/components/agent/chat/AgentChatWorkspace.tsx`:移除空白首页输入后的自动 `ensureSession()` 预热;输入文字不再提前创建会话,避免未发送就触发 CPU / 内存峰值与空会话副作用。 -- `src/components/agent/chat/AgentChatWorkspace.tsx`:首页首发改为先写入轻量 `homePendingPreviewMessages`,立即渲染用户消息 + “正在进入对话”助手占位;真实 `handleSend` 延后到下一次 paint 后再派发。 -- `src/components/agent/chat/AgentChatWorkspace.tsx`:非草稿首页首发、以及已为空的草稿发送,不再调用重型 `clearMessages()`,避免在空白态重复 `applySessionSnapshot`、清 transient storage 与 reset streaming refs。 -- `src/lib/agentUiPerformanceMetrics.ts`:新增 `homeInput.pendingPreviewPaint` 与 `homeInputToPendingPreviewPaintMs`,Playwright 可直接区分“状态入队”与“用户可见预览已绘制”。 -- `src/components/agent/chat/index.test.tsx`:把旧的“输入即后台预热会话”回归改为“不应后台创建会话”,并新增“发送后立即展示轻量对话预览”回归。 - -Playwright E2E 修复后复测: - -- 输入后停留 `500ms`,`window.__LIME_AGENTUI_PERF__.entries()` 仍为空,证明单纯输入不再触发会话创建/发送相关预热。 -- 按 Enter 后:`homeInputToPendingShellMs=0ms`、`homeInputToPendingPreviewPaintMs=63ms`、`homeInputToSendDispatchMs=64ms`。 -- 用户输入文本可见约 `110ms`;首页空态已退出,进入对话流预览。 -- 本轮请求 `longTaskMaxMs` 从修复前约 `556ms` 降到 `59ms`;同页 heap 未再出现 Enter 后瞬时大幅攀升。 -- 真实后端随后继续处理;本刀目标是“毫秒级先到达对话页面/壳”,不改变后端首 token 质量链。 - -已验证: - -```bash -npx eslint "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/index.test.tsx" "src/lib/agentUiPerformanceMetrics.ts" "src/lib/agentUiPerformanceMetrics.test.ts" --max-warnings 0 -npm exec -- vitest run "src/lib/agentUiPerformanceMetrics.test.ts" "src/components/agent/chat/index.test.tsx" -t "首页输入|空白新建任务|草稿标签输入后应预热创建会话" --hookTimeout 180000 --testTimeout 120000 -npm run typecheck -- --pretty false -npm run bridge:health -- --timeout-ms 120000 -npm run verify:gui-smoke -git diff --check -- "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/index.test.tsx" "src/lib/agentUiPerformanceMetrics.ts" "src/lib/agentUiPerformanceMetrics.test.ts" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- ESLint touched files:通过。 -- 定向 vitest:通过,`7` 个测试通过,`101` 个测试按过滤条件跳过。 -- TypeScript `tsc --noEmit`:通过。 -- DevBridge 健康检查:通过,`1710ms` 就绪。 -- GUI smoke:通过,覆盖 workspace ready、browser runtime、site adapters、service skill entry、runtime tool surface 与页面级 tool surface。 -- diff 空白检查:通过。 - -下一步: - -1. 若仍觉得 Enter 后模型首字慢,继续看 `AgentStream.firstTextDelta / firstTextPaint`,不要再把“先进入对话页”与“后端首 token”混成同一个问题。 -2. 若首页打开后内存基线仍高,下一刀应从常驻 tab/sidebar DOM、历史对话列表与 keep-alive 页面裁剪入手。 - -### 2026-05-01:P1 第三十六刀,首页首发流式首字链路拆段与跳过旧会话恢复 - -采集事实: - -- 复用现有 `http://127.0.0.1:1420/` Lime 页签,不新启违规 Playwright 浏览器;先清空 `window.__LIME_AGENTUI_PERF__`,再从首页输入框发起真实首轮请求。 -- 复测样本 1:`homeInputToPendingPreviewPaintMs=49ms`、`homeInputToSubmitAcceptedMs=303ms`、`homeInputToFirstEventMs=331ms`、`homeInputToFirstTextPaintMs=2040ms`、`streamEnsureSessionDurationMs=91ms`、`streamSubmitInvokeDurationMs=119ms`、`firstEventToFirstTextDeltaMs=1674ms`、`longTaskCount=0`。 -- 复测样本 2:`homeInputToPendingPreviewPaintMs=17ms`、`homeInputToSubmitAcceptedMs=176ms`、`homeInputToFirstEventMs=199ms`、`homeInputToFirstTextPaintMs=2100ms`、`streamEnsureSessionDurationMs=35ms`、`streamSubmitInvokeDurationMs=86ms`、`firstEventToFirstTextDeltaMs=1879ms`、`longTaskCount=0`。 -- 结论:当前前端从 Enter 到会话壳 / 状态事件已经稳定在几十到两百毫秒;仍然约 `1.7-1.9s` 的等待主要发生在后端/Provider 从首个 `runtime_status` 到首个 `text_delta` 的阶段,不再是首页切壳、MessageList 或主线程 long task。 - -已完成: - -- `src/components/agent/chat/hooks/agentStreamPerformanceMetrics.ts`:新增首页首发 trace 元数据,允许后续 stream 阶段继续按草稿请求维度汇总,而不是被真实 sessionId 打散。 -- `src/components/agent/chat/AgentChatWorkspace.tsx`:首页首发派发时写入 trace,并设置 `skipSessionRestore: true`;新对话首发不再先恢复上一次会话,避免误入旧会话 hydration 与历史消息拉取。 -- `src/components/agent/chat/hooks/useAgentSession.ts` 与 stream 发送链路:`ensureSession` 支持按请求跳过 restore candidate;普通恢复路径不变,仅首页新对话首发显式走创建新会话。 -- `src/components/agent/chat/hooks/agentStreamSubmitContext.ts`、`agentStreamSubmitExecution.ts`、`agentStreamTurnEventBinding.ts`、`agentStreamRuntimeHandler.ts`:新增 `agentStream.ensureSession.*`、`request.start`、`listenerBound`、`submitDispatched`、`submitAccepted`、`firstEvent`、`firstRuntimeStatus`、`firstTextDelta`、`firstTextRenderFlush`、`firstTextPaint` 采集。 -- `src/lib/agentUiPerformanceMetrics.ts`:summary 新增 `homeInputToFirstEventMs`、`homeInputToFirstRuntimeStatusMs`、`homeInputToFirstTextDeltaMs`、`homeInputToFirstTextPaintMs`、`streamEnsureSessionDurationMs`、`streamSubmitInvokeDurationMs` 等字段,Playwright 可直接读出前端、桥接、后端首 token 分段。 - -已验证: - -```bash -npx eslint "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/hooks/agentStreamPerformanceMetrics.ts" "src/components/agent/chat/hooks/agentStreamPreparedSendEnv.ts" "src/components/agent/chat/hooks/useAgentStream.ts" "src/components/agent/chat/hooks/agentStreamUserInputSendPreparation.ts" "src/components/agent/chat/hooks/agentStreamUserInputSubmission.ts" "src/components/agent/chat/hooks/agentStreamSubmissionLifecycle.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "src/components/agent/chat/hooks/useAgentSession.ts" "src/components/agent/chat/hooks/handleSendTypes.ts" "src/components/agent/chat/hooks/agentChatShared.ts" "src/lib/agentUiPerformanceMetrics.ts" "src/lib/agentUiPerformanceMetrics.test.ts" --max-warnings 0 -npm run typecheck -- --pretty false -npm exec -- vitest run "src/lib/agentUiPerformanceMetrics.test.ts" "src/components/agent/chat/index.test.tsx" "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" -t "agentUiPerformanceMetrics|空白新建任务|首页输入|sendMessage 后在首个流事件前应先注入本地回合占位" --hookTimeout 180000 --testTimeout 120000 -npm run bridge:health -- --timeout-ms 120000 -npm run verify:gui-smoke -``` - -结果: - -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit`:通过。 -- 定向 vitest:通过,`9` 个测试通过。 -- DevBridge 健康检查:通过,`21ms` 就绪。 -- GUI smoke:通过,覆盖 workspace ready、browser runtime、site adapters、service skill entry、runtime tool surface 与页面级 tool surface。 -- Playwright 真实 GUI:两次首页新建对话首发均可快速进入对话壳;控制台 error 为 `0`;本轮链路没有 long task。 - -下一步: - -1. 若要继续压缩真实首字,需要转向后端 runtime/provider:记录 submitOp 到 provider request、provider first byte、provider first text delta 的服务端分段。 -2. 前端侧可继续做感知优化:把 `firstEventToFirstTextDeltaMs > 1000` 时的运行态文案改成更明确的“模型正在生成首字”,但不要伪造模型文本。 -3. 若同一页面连续打开多个标签后仍卡顿,下一刀回到 tab/sidebar keep-alive DOM 裁剪与历史标签卸载策略。 - -### 2026-05-05:P3 前置,AgentUI 对话投影计划落库 - -已完成: - -- 新增 [conversation-projection-architecture.md](../roadmap/agentui/conversation-projection-architecture.md),声明对话层只做 UI projection,不新增 runtime / artifact / evidence 事实源。 -- 新增 [conversation-projection-implementation-plan.md](../roadmap/agentui/conversation-projection-implementation-plan.md),把后续结构瘦身拆成: - - Phase 0:对话事实源盘点 - - Phase 1:Projection Store 边界 - - Phase 2:Session lifecycle / hydration 拆分 - - Phase 3:Stream submission / queue / event reducer 拆分 - - Phase 4:Message render projection - - Phase 5:Workspace shell 瘦身 - - Phase 6:性能与治理守卫 -- 新增 [conversation-projection-acceptance.md](../roadmap/agentui/conversation-projection-acceptance.md),固定首页输入、新建对话、打开两个历史会话、大历史 MessageList、流式输出、Artifact 恢复的验收场景。 -- 更新 [AgentUI README](../roadmap/agentui/README.md) 和 [AgentUI 实施路线图](../roadmap/agentui/lime-agentui-implementation-roadmap.md),把 projection plan 纳入 current planning source。 - -主线收益: - -- 后续不再以“继续拆大文件”作为默认目标,而是按 `fact source -> projection store -> controllers -> selectors -> UI` 收敛。 -- P0/P1 已做的性能采集可以继续用于 Phase 2 / Phase 4 验收,避免架构瘦身和性能排查脱节。 -- 与 `docs/roadmap/warp` 对齐,避免 AgentUI 再长出第二套 runtime / artifact / evidence 事实源。 - -下一刀: - -1. 执行 Phase 0,对 `sessionId/threadId/turnId/taskId`、`messages/threadItems/threadTurns`、`thread_read`、`queuedTurns/pendingActions`、`artifact_snapshot`、`sessionHistoryWindow`、stream trace、MessageList render window 建 fact map。 -2. 从低风险 slice 开始 Phase 1,优先选择 `stream diagnostics` 或 `message render window` 接入最小 Projection Store。 -3. 补 selector 测试,证明无关切片更新不会触发 MessageList / Workspace 重渲染。 - -### 2026-05-05:P3 第一刀,Phase 0 fact map 与最小 Projection Store - -已完成: - -- 新增 [conversation-projection-fact-map.md](../roadmap/agentui/conversation-projection-fact-map.md),把对话状态按 runtime identity、session/history、messages/thread projection、stream/queue/actions、artifact/evidence 分组,标明 owner、writer、readers、persistence、runtime fact source、projection-only 与 `current` 分类。 -- 新增 `src/components/agent/chat/projection/conversationProjectionStore.ts`: - - 定义 `Conversation Projection Store` 的最小 state shape。 - - 先落 `diagnostics.streamDiagnostics` slice。 - - 保留 `session / stream / queue / render` slice 占位,但只保存版本,不写 runtime 事实。 - - 提供 `selectConversationStreamDiagnostics` 与 `selectLatestConversationStreamDiagnostic` selector。 -- `recordAgentStreamPerformanceMetric` 同步写入原有 `agentUiPerformanceMetrics` 与新的 projection store。 -- 新增 projection store 与 stream diagnostics 回归,证明 diagnostics 更新不会改变其它 slice 引用。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/projection/conversationProjectionStore.test.ts" "src/components/agent/chat/hooks/agentStreamPerformanceMetrics.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitDraft.test.ts" -npx eslint "src/components/agent/chat/projection/conversationProjectionStore.ts" "src/components/agent/chat/projection/conversationProjectionStore.test.ts" "src/components/agent/chat/hooks/agentStreamPerformanceMetrics.ts" "src/components/agent/chat/hooks/agentStreamPerformanceMetrics.test.ts" --max-warnings 0 -git diff --check -- "docs/roadmap/agentui/conversation-projection-fact-map.md" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/roadmap/agentui/README.md" "docs/exec-plans/agentui-implementation-progress.md" "src/components/agent/chat/projection/conversationProjectionStore.ts" "src/components/agent/chat/projection/conversationProjectionStore.test.ts" "src/components/agent/chat/hooks/agentStreamPerformanceMetrics.ts" "src/components/agent/chat/hooks/agentStreamPerformanceMetrics.test.ts" -rg "conversation-projection-fact-map|conversationProjectionStore|recordConversationStreamDiagnostic|selectLatestConversationStreamDiagnostic" "docs" "src/components/agent/chat" -``` - -结果: - -- Projection Store / stream diagnostics 定向回归:通过,`9` 个测试通过。 -- ESLint touched files:通过。 -- diff 空白检查:通过。 -- 引用检查:通过。 - -暂未完成验证: - -- TypeScript 全量 `npm run typecheck -- --pretty false` 本轮运行超过约 1 分钟仍无输出;为避免继续占用本机 CPU,已停止本轮发起的 `tsc --noEmit --pretty false` 进程。新增代码为窄边界 TS 文件,已由定向 vitest 与 ESLint 覆盖;下一轮接入 `messageRenderWindow` 前补跑统一 typecheck。 - -主线收益: - -- Phase 0 不再只是计划,已有可维护的 fact map。 -- Phase 1 有了第一个低风险 current slice,后续可按同一模式迁 `messageRenderWindow`。 -- 当前实现只新增 UI projection,不新增 Tauri command、不改 runtime event、不改 artifact/evidence 事实源。 - -下一刀: - -1. 用现有 E2E 性能指标确认 MessageList 是否仍是热点。 -2. 若热点成立,接入 Phase 4 的最小 `messageRenderWindow` selector,而不是继续让 `MessageList` 内部同步推导窗口。 -3. 若热点转向后端首字,则先补 runtime/provider 服务端分段,不扩大前端 projection。 - -### 2026-05-05:P3 第二刀,MessageList render window 投影外移 - -已完成: - -- 新增 `src/components/agent/chat/projection/messageRenderWindowProjection.ts`: - - `filterVisibleConversationMessages` - - `resolveConversationMessageRenderWindowSettings` - - `resolveInitialConversationRenderedMessageCount` - - `buildConversationMessageRenderWindowProjection` -- `MessageList.tsx` 改为消费 `messageRenderWindowProjection` 输出的: - - `visibleMessages` - - `renderedMessages` - - `hiddenHistoryCount` - - `shouldAutoHydrateHiddenHistory` - - 渐进渲染阈值、首帧数量、批量数量与 idle delay -- 新增 `messageRenderWindowProjection.test.ts` 覆盖: - - 空白 user 消息过滤 - - 普通会话尾部窗口 - - 旧会话更小首帧与禁止自动补齐 - - 发送中不裁剪 - -主线收益: - -- `MessageList` 不再直接散落“可见消息过滤 + 渐进渲染窗口 + 旧会话隐藏历史”推导,后续可以继续把 `renderedTurns / renderedThreadItems / timelineByMessageId` 外移。 -- 这是 Phase 4 的最小入口,不改变 runtime event、session detail、artifact/evidence 事实源,也不引入第二套 message 数据源。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/projection/messageRenderWindowProjection.test.ts" "src/components/agent/chat/projection/conversationProjectionStore.test.ts" "src/components/agent/chat/hooks/agentStreamPerformanceMetrics.test.ts" "src/components/agent/chat/components/MessageList.test.tsx" -t "messageRenderWindowProjection|conversationProjectionStore|agentStreamPerformanceMetrics|旧会话首帧|已分页旧会话|历史" -npx eslint "src/components/agent/chat/projection/conversationProjectionStore.ts" "src/components/agent/chat/projection/conversationProjectionStore.test.ts" "src/components/agent/chat/projection/messageRenderWindowProjection.ts" "src/components/agent/chat/projection/messageRenderWindowProjection.test.ts" "src/components/agent/chat/hooks/agentStreamPerformanceMetrics.ts" "src/components/agent/chat/hooks/agentStreamPerformanceMetrics.test.ts" "src/components/agent/chat/components/MessageList.tsx" --max-warnings 0 -git diff --check -- "src/components/agent/chat/projection" "src/components/agent/chat/hooks/agentStreamPerformanceMetrics.ts" "src/components/agent/chat/hooks/agentStreamPerformanceMetrics.test.ts" "src/components/agent/chat/components/MessageList.tsx" "docs/roadmap/agentui" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Projection / MessageList 定向回归:通过,`19` 个测试通过。 -- ESLint touched files:通过。 -- diff 空白检查:通过。 -- 完整 MessageList 回归:通过,`97` 个测试通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -下一刀: - -1. 补跑完整 `MessageList.test.tsx` 与 TypeScript。 -2. 如果通过,继续把 `renderedTurns / renderedThreadItems` 提取为 `threadTimelineWindowProjection`,并用 `messageListThreadItemsScanMs` / `messageListTimelineBuildMs` 判断收益。 -3. 如果 TypeScript 或完整 MessageList 回归暴露旧行为差异,先修 projection selector,不继续扩展。 - -### 2026-05-05:P3 第三刀,Thread timeline window 投影外移 - -已完成: - -- 新增 `src/components/agent/chat/projection/threadTimelineWindowProjection.ts`: - - `resolveConversationRenderedTurns` - - `resolveConversationRenderedTurnIdSet` - - `filterConversationThreadItemsForRenderedTurns` - - `buildConversationThreadTimelineWindowProjection` -- `MessageList.tsx` 改为从 projection 层获取: - - `renderedTurns` - - `renderedTurnIdSet` - - `renderedThreadItems` -- 新增 `threadTimelineWindowProjection.test.ts` 覆盖: - - 无隐藏历史时保留全部 turns / threadItems - - 旧会话按可见 assistant 数裁剪尾部 turns - - 当前 turn 不在尾部窗口时额外保留 - - 按 rendered turn 精确裁剪 threadItems - - 延迟扫描时返回空 threadItems - -主线收益: - -- `MessageList` 的旧会话历史窗口逻辑进一步收敛到 projection 层。 -- 后续可以继续把 `timelineByMessageId / messageGroups / renderGroups` 外移,并用现有 `messageListTimelineBuildMs / messageListRenderGroupsMs` 指标判断是否值得 worker 化。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/projection/threadTimelineWindowProjection.test.ts" "src/components/agent/chat/projection/messageRenderWindowProjection.test.ts" "src/components/agent/chat/components/MessageList.test.tsx" -npx eslint "src/components/agent/chat/projection/threadTimelineWindowProjection.ts" "src/components/agent/chat/projection/threadTimelineWindowProjection.test.ts" "src/components/agent/chat/projection/messageRenderWindowProjection.ts" "src/components/agent/chat/projection/messageRenderWindowProjection.test.ts" "src/components/agent/chat/components/MessageList.tsx" --max-warnings 0 -git diff --check -- "src/components/agent/chat/projection" "src/components/agent/chat/components/MessageList.tsx" -``` - -结果: - -- Thread / Message render projection + MessageList 回归:通过,`102` 个测试通过。 -- ESLint touched files:通过。 -- diff 空白检查:通过。 - -下一刀: - -1. 补跑 TypeScript。 -2. 继续外移 `timelineByMessageId / messageGroups / renderGroups` 为 `messageTimelineRenderProjection`。 -3. 再评估是否需要把 `buildMessageTurnTimeline` 移入 idle / worker。 - -### 2026-05-05:P3 第四刀,Message timeline render 投影外移 - -已完成: - -- 新增 `src/components/agent/chat/projection/messageTimelineRenderProjection.ts`: - - `buildTimelineByMessageIdProjection` - - `resolveLastAssistantMessage` - - `buildCurrentTurnTimelineProjection` - - `buildMessageGroupsProjection` - - `buildMessageRenderGroupsProjection` -- `MessageList.tsx` 改为从 projection 层获取: - - `timelineByMessageId` - - `lastAssistantMessage` - - `currentTurnTimeline` - - `messageGroups` - - `renderGroups` -- 保留原有 `measureMessageListComputation` 分段,`messageListTimelineBuildMs / messageListRenderGroupsMs` 等指标仍可用于判断下一刀是否需要 worker 化。 - -主线收益: - -- `MessageList` 中“数据投影”和“React 渲染”边界更清晰。 -- Phase 4 的主要同步投影已形成独立纯函数层,后续性能优化可以优先移动 projection,而不是继续在组件内部堆判断。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/projection/messageTimelineRenderProjection.test.ts" "src/components/agent/chat/projection/threadTimelineWindowProjection.test.ts" "src/components/agent/chat/components/MessageList.test.tsx" -npx eslint "src/components/agent/chat/projection/messageTimelineRenderProjection.ts" "src/components/agent/chat/projection/messageTimelineRenderProjection.test.ts" "src/components/agent/chat/projection/threadTimelineWindowProjection.ts" "src/components/agent/chat/projection/threadTimelineWindowProjection.test.ts" "src/components/agent/chat/components/MessageList.tsx" --max-warnings 0 -git diff --check -- "src/components/agent/chat/projection" "src/components/agent/chat/components/MessageList.tsx" -``` - -结果: - -- Message timeline projection / thread window projection / MessageList 回归:通过,`102` 个测试通过。 -- ESLint touched files:通过。 -- diff 空白检查:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -暂未完成验证: - -- Playwright MCP 当前无法进入复用页签:MCP Chrome profile 被占用,工具提示需 `--isolated`,但仓库规则禁止为本地续测新开 isolated profile。 -- `npm run verify:gui-smoke` 已尝试;第一次被既有脏改阻塞,随后阻塞文件已恢复到可编译状态并通过 TypeScript。第二次 smoke 触发独立 Cargo target 全量重编,约 `8` 分钟推进到 `836/1098` 后进程退出并停止 headless Tauri,未得到最终 GUI smoke 结论;已确认未留下本轮 `verify-gui-smoke` / 临时 target 编译进程。 - -下一刀: - -1. DevBridge / headless Tauri 稳定后,先复跑 `npm run verify:gui-smoke`。 -2. 再做真实 E2E,读取 `messageListTimelineBuildMs / messageListRenderGroupsMs / longTaskMaxMs`,决定是否 worker 化。 - -### 2026-05-05:P3 第五刀,历史消息 hydration 投影外移 - -已完成: - -- 新增 `src/components/agent/chat/projection/historicalMessageHydrationProjection.ts`: - - `hasStructuredHistoricalContentHint` - - `isHistoricalAssistantMessageHydrationCandidate` - - `buildHistoricalMarkdownHydrationTargets` - - `buildHistoricalMarkdownHydrationIndexByMessageId` - - `shouldDeferHistoricalAssistantMessageDetails` - - `countDeferredHistoricalContentParts` - - `countDeferredHistoricalMarkdown` -- `MessageList.tsx` 改为从 projection 层获取旧会话历史 markdown hydration 目标、hydration index、消息细节延迟判断、延迟 contentParts 计数和延迟 markdown 数量。 -- 新增 `historicalMessageHydrationProjection.test.ts`,覆盖结构化历史内容识别、旧会话 assistant hydration 候选、目标筛选、hydration 计数和延迟统计。 - -主线收益: - -- Phase 4 中仍留在 `MessageList` 内的历史消息 hydration 扫描被移到纯 projection,后续如果 E2E 证明 `messageListHistoricalMarkdownTargetScanMs` 或 `messageListHistoricalContentPartsScanMs` 仍高,可以直接对 projection 做 idle / worker 化。 -- `MessageList` 继续向“只编排状态与渲染”收敛,不新增 runtime、artifact 或 evidence 事实源。 -- 结构化历史内容识别成为可单测 selector,不再散落在组件内部。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/projection/historicalMessageHydrationProjection.test.ts" "src/components/agent/chat/projection/messageTimelineRenderProjection.test.ts" "src/components/agent/chat/components/MessageList.test.tsx" -npx eslint "src/components/agent/chat/projection/historicalMessageHydrationProjection.ts" "src/components/agent/chat/projection/historicalMessageHydrationProjection.test.ts" "src/components/agent/chat/components/MessageList.tsx" --max-warnings 0 -git diff --check -- "src/components/agent/chat/projection/historicalMessageHydrationProjection.ts" "src/components/agent/chat/projection/historicalMessageHydrationProjection.test.ts" "src/components/agent/chat/components/MessageList.tsx" -npm run typecheck -- --pretty false -``` - -结果: - -- Historical hydration projection / Message timeline projection / MessageList 回归:通过,`102` 个测试通过。 -- ESLint touched files:通过。 -- diff 空白检查:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -GUI / E2E 状态: - -- `npm run verify:gui-smoke` 已尝试,但脚本检测到 sqlite 构建缓存损坏并切换到新的独立 Cargo target `/var/folders/.../lime-gui-smoke-target-rebuild-1777945025159-2866`,开始 `1098` 个 crate 的全量重编;为避免继续造成 CPU/鼠标繁忙,已在约 `113/1098` 时停止本轮 smoke。 -- 停止 headless Tauri 后,`npm run bridge:health -- --timeout-ms 30000` 返回 `3030` 未就绪;当前仍不把 GUI smoke 记为通过。 -- Playwright MCP 仍因既有 Chrome profile 占用无法进入复用页签,工具提示要求 `--isolated`,但仓库规则禁止本地续测使用 isolated profile,因此本轮未绕规则新开浏览器。 - -下一刀: - -1. 等 DevBridge / Playwright profile 恢复后,先按验收路径采集 `messageListHistoricalMarkdownTargetScanMs / messageListHistoricalContentPartsScanMs / messageListTimelineBuildMs / messageListRenderGroupsMs / longTaskMaxMs`。 -2. 如果历史 hydration 或 timeline projection 仍是热点,再把对应 projection 放到 idle / worker;否则不要盲目 worker 化。 -3. 若继续结构主线,进入 Phase 2,把 `useAgentSession` 的 lifecycle / hydration controller 拆成可单测模块,减少旧会话恢复链路继续堆在 hook 内。 - -### 2026-05-05:P3 第六刀,Session hydration controller 最小化 - -已完成: - -- 新增 `src/components/agent/chat/hooks/sessionHydrationController.ts`: - - `SESSION_DETAIL_HISTORY_LIMIT` - - `normalizeSessionDetailHistoryLimit` - - `buildSessionDetailHydrationOptions` - - `buildSessionDetailPrefetchKey` - - `buildSessionDetailPrefetchSignature` - - `isCurrentSessionHydrationRequest` -- `useAgentSession.ts` 中旧会话详情、prefetch、静默 turn 恢复、missing-from-topics 校验的 `runtime.getSession` 统一通过 `buildSessionDetailHydrationOptions()` 构造请求参数。 -- `useAgentSession.ts` 中 switch finalize、deferred hydrate catch、metadata sync、load full history、silent recovery、missing session verify 的 stale/session guard 改为 `isCurrentSessionHydrationRequest()`。 -- 新增 `sessionHydrationController.test.ts`,固定 `historyLimit: 40`、`resumeSessionStartHooks` 合并、prefetch key/signature 和过期 hydrate 丢弃逻辑。 - -主线收益: - -- Phase 2 开始从 `useAgentSession` 抽出可单测 controller,先把最容易回归成“无 limit getSession / 过期结果覆盖当前 tab”的逻辑收敛到单一入口。 -- 不改变 runtime 协议、不新增 Tauri command、不改变对外 hook shape;本刀只降低旧会话恢复链路的重复与排查成本。 -- 后续拆 `sessionLifecycleController / topicListController` 时,可以继续复用同一 stale guard,而不是在 hook 内复制判断。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/sessionHydrationController.test.ts" "src/components/agent/chat/projection/historicalMessageHydrationProjection.test.ts" "src/components/agent/chat/components/MessageList.test.tsx" -npx eslint "src/components/agent/chat/hooks/sessionHydrationController.ts" "src/components/agent/chat/hooks/sessionHydrationController.test.ts" "src/components/agent/chat/hooks/useAgentSession.ts" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/components/agent/chat/hooks/sessionHydrationController.ts" "src/components/agent/chat/hooks/sessionHydrationController.test.ts" "src/components/agent/chat/hooks/useAgentSession.ts" "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/projection" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Session hydration controller / historical hydration projection / MessageList 回归:通过,`102` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- diff 空白检查:通过。 - -GUI / E2E 状态: - -- 本刀未复跑 `verify:gui-smoke`,原因仍是上一轮已确认 smoke 会因 sqlite 构建缓存损坏切到独立 Cargo target 并触发全量重编,容易复现用户反馈的 CPU/鼠标繁忙。 -- Playwright MCP 仍需等待既有 profile 释放;不使用 isolated profile 绕过仓库规则。 - -下一刀: - -1. 继续 Phase 2:抽 `sessionDetailFetchController`,把 `loadRuntimeSessionDetail` 的 prefetch 命中、fetch start/success/error metrics 和 retry 决策从 hook 中移出。 -2. 或等待 GUI 环境恢复后,先采集旧会话 A/B 打开和切换指标,再决定是否优先 worker 化 MessageList projection。 - -### 2026-05-05:P3 第七刀,Session detail fetch controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/sessionDetailFetchController.ts`: - - `createSessionDetailPrefetchRegistry` - - `loadSessionDetailWithPrefetch` - - `SessionDetailFetchEvent` - - `SessionDetailFetchMode` -- `useAgentSession.ts` 中 `loadRuntimeSessionDetail` 改为委托 `loadSessionDetailWithPrefetch`: - - 保留 `session.switch.fetchDetail.start / prefetch / success / error` 性能指标。 - - 保留 `switchTopic.fetchDetail.*` AgentDebug 日志。 - - prefetch 命中、prefetch fallback、resume 跳过 prefetch、registry 只删除当前 promise 进入 controller 单测。 -- `sessionDetailPrefetchRegistry` 从裸 `Map` 改为 controller registry,避免 future prefetch 清理误删较新 promise。 - -主线收益: - -- Phase 2 继续把 `useAgentSession` 从“状态 + 请求 + metrics + retry + registry”巨石里拆开;本刀先收敛 detail fetch 和 prefetch 复用,不改变 UI 行为。 -- 旧会话打开时最关键的 detail fetch 分段现在有单独 controller 测试,后续要做取消、优先级或批量请求时不用再直接改 hook 主体。 -- 继续保持 `historyLimit: 40` 由 `sessionHydrationController` 单一入口提供,避免 prefetch / switch / recovery 重新分叉。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/sessionDetailFetchController.test.ts" "src/components/agent/chat/hooks/sessionHydrationController.test.ts" "src/components/agent/chat/projection/historicalMessageHydrationProjection.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" -t "预取|stale 快照" --hookTimeout 180000 --testTimeout 120000 -npx eslint "src/components/agent/chat/hooks/sessionDetailFetchController.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.test.ts" "src/components/agent/chat/hooks/sessionHydrationController.ts" "src/components/agent/chat/hooks/sessionHydrationController.test.ts" "src/components/agent/chat/hooks/useAgentSession.ts" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/components/agent/chat/hooks/sessionDetailFetchController.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.test.ts" "src/components/agent/chat/hooks/sessionHydrationController.ts" "src/components/agent/chat/hooks/sessionHydrationController.test.ts" "src/components/agent/chat/hooks/useAgentSession.ts" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Fetch / hydration controller / historical hydration projection:通过,`13` 个测试通过。 -- `useAsterAgentChat` 旧会话预取和 stale 快照定向:通过,`3` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- diff 空白检查:通过。 - -GUI / E2E 状态: - -- 本刀仍未复跑 `verify:gui-smoke`,理由同上一刀:当前 smoke 会触发独立 Rust target 全量重编,容易造成 CPU 和鼠标繁忙;本刀是纯前端 controller 抽取,先用 hook / controller 单测覆盖行为。 -- Playwright MCP 仍等待 profile 释放;不使用 isolated profile 绕过仓库规则。 - -下一刀: - -1. 继续 Phase 2:抽 `sessionHydrationRetryController`,把 deferred hydrate retry / transient skip / error fallback 从 `switchTopic` 内联函数里移出。 -2. 或恢复 GUI 环境后先做旧会话 A/B 打开与切换采样,确认是否还需要优先处理 MessageList worker 化。 - -### 2026-05-05:P3 第八刀,Deferred hydration retry controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/sessionHydrationRetryController.ts`: - - `resolveDeferredSessionHydrationErrorAction` - - `DeferredSessionHydrationErrorAction` - - `DeferredSessionHydrationRetryContext` - - `DeferredSessionHydrationSkipContext` -- `useAgentSession.ts` 中 deferred cached topic hydrate 的 catch 分支改为委托 retry controller: - - retryable transient 且未达上限:返回 `retry`,继续写 `session.switch.fetchDetail.retryScheduled` 并调度 idle retry。 - - transient 且不再重试:返回 `skip`,保留缓存快照并写 `session.switch.fetchDetail.retrySkipped`。 - - fatal unknown:返回 `fail`,继续走 `handleSwitchTopicError(..., preserveCurrentSnapshot: true)`。 -- 新增 `sessionHydrationRetryController.test.ts`,覆盖 bridge health retry、connection retry 达上限跳过、timeout 直接跳过、unknown fatal fallback。 - -主线收益: - -- Phase 2 继续把 `switchTopic` 的旧会话恢复分支从“请求 + stale guard + retry 分类 + metrics + 调度”拆开;本刀只抽 retry 决策,不改变调度行为。 -- deferred hydrate 的错误处理有纯函数测试,后续如果要调整 retry 次数、退避策略或按错误类型降级,不需要在 `useAgentSession` 巨石里改条件。 -- 继续保护旧会话打开体验:短暂 bridge / network 问题只保留 cached snapshot,不把用户已经看到的旧会话清空。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/sessionHydrationRetryController.test.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.test.ts" "src/components/agent/chat/hooks/sessionHydrationController.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" -t "stale 快照|预取" --hookTimeout 180000 --testTimeout 120000 -npx eslint "src/components/agent/chat/hooks/sessionHydrationRetryController.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.test.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.test.ts" "src/components/agent/chat/hooks/useAgentSession.ts" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/components/agent/chat/hooks/sessionHydrationRetryController.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.test.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.test.ts" "src/components/agent/chat/hooks/sessionHydrationController.ts" "src/components/agent/chat/hooks/sessionHydrationController.test.ts" "src/components/agent/chat/hooks/useAgentSession.ts" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Retry / fetch / hydration controller:通过,`12` 个测试通过。 -- `useAsterAgentChat` 旧会话预取和 stale 快照定向:通过,`3` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- diff 空白检查:通过。 - -GUI / E2E 状态: - -- 本刀未复跑 `verify:gui-smoke`,原因同前:当前 smoke 会切到独立 Rust target 全量重编,容易造成 CPU 和鼠标繁忙;本刀是纯前端 controller 抽取,先用定向行为测试收口。 -- Playwright MCP 仍等待 profile 释放;不使用 isolated profile 绕过仓库规则。 - -下一刀: - -1. 继续 Phase 2:抽 `sessionSwitchSnapshotController`,把 cached snapshot apply、pending shell、localSnapshotOverride 判断从 `switchTopic` 主体中移出。 -2. 或恢复 GUI 环境后先采集旧会话 A/B 打开和切换指标,决定是否进入 MessageList projection idle / worker 化。 - -### 2026-05-05:P3 第九刀,Session switch snapshot controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/sessionSwitchSnapshotController.ts`: - - `shouldLoadCachedTopicSnapshot` - - `shouldApplyCachedTopicSnapshot` - - `shouldRefreshCachedSnapshotImmediately` - - `shouldApplyPendingSessionShell` - - `buildSessionSwitchStartMetricContext` - - `buildSessionSwitchDeferHydrationMetricContext` - - `buildPendingSessionShellMetricContext` - - `buildSessionSwitchLocalSnapshotOverride` -- `useAgentSession.ts` 中 `switchTopic` 的 cached snapshot 加载/应用、stale/running 立即刷新、defer metric、pending shell metric、`localSnapshotOverride` 引用判定改为委托 controller。 -- 新增 `sessionSwitchSnapshotController.test.ts`,覆盖当前会话不重复加载 snapshot、stale/running/waiting 立即刷新、无 snapshot 时应用 pending shell、指标上下文和 local snapshot 引用匹配。 - -主线收益: - -- Phase 2 继续瘦 `switchTopic`:snapshot 相关判断不再与 detail fetch、retry、metadata sync 混在同一个长函数里。 -- `localSnapshotOverride` 的引用匹配规则有单测保护,避免后续改动误把 stale cached snapshot 与当前 UI 状态错配,导致旧会话恢复覆盖当前 tab。 -- pending shell 的触发条件可单测,继续保护“打开无缓存旧会话先显示壳,不等 getSession 完成”的体验。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/sessionSwitchSnapshotController.test.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.test.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.test.ts" "src/components/agent/chat/hooks/sessionHydrationController.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" -t "stale 快照|预取|pendingShell|pending shell|空白" --hookTimeout 180000 --testTimeout 120000 -npx eslint "src/components/agent/chat/hooks/sessionSwitchSnapshotController.ts" "src/components/agent/chat/hooks/sessionSwitchSnapshotController.test.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.ts" "src/components/agent/chat/hooks/sessionHydrationController.ts" "src/components/agent/chat/hooks/useAgentSession.ts" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/components/agent/chat/hooks/sessionSwitchSnapshotController.ts" "src/components/agent/chat/hooks/sessionSwitchSnapshotController.test.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.test.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.test.ts" "src/components/agent/chat/hooks/sessionHydrationController.ts" "src/components/agent/chat/hooks/sessionHydrationController.test.ts" "src/components/agent/chat/hooks/useAgentSession.ts" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Snapshot / retry / fetch / hydration controller:通过,`17` 个测试通过。 -- `useAsterAgentChat` 旧会话预取、stale 快照和相关空白消息定向:通过,`7` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- diff 空白检查:通过。 - -GUI / E2E 状态: - -- 本刀未复跑 `verify:gui-smoke`,原因同前:当前 smoke 会切到独立 Rust target 全量重编,容易造成 CPU 和鼠标繁忙;本刀是纯前端 controller 抽取,先用定向行为测试收口。 -- Playwright MCP 仍等待 profile 释放;不使用 isolated profile 绕过仓库规则。 - -下一刀: - -1. 继续 Phase 2:抽 `sessionMetadataSyncController`,把 finalize 后的 accessMode / provider / executionStrategy fallback patch 与低优先级 sync 决策从 `finalizeResolvedTopicDetail` 中移出。 -2. 或恢复 GUI 环境后先采集旧会话 A/B 打开和切换指标,决定是否进入 MessageList projection idle / worker 化。 - -### 2026-05-05:P3 第十刀,Session metadata sync controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/sessionMetadataSyncController.ts`: - - `buildSessionMetadataSyncPlan` - - `buildSessionSwitchSuccessMetricContext` - - `resolveSessionExecutionStrategySource` - - `executeSessionMetadataSync` -- `useAgentSession.ts` 中 `finalizeResolvedTopicDetail` 的 metadata fallback 决策改为委托 controller: - - accessMode 来源解析与是否本地持久化。 - - provider/model fallback patch。 - - executionStrategy fallback patch。 - - switch success metric 的 source 字段。 - - 优先 `updateSessionMetadata`,缺少批量命令时回退到 `setSessionAccessMode / setSessionProviderSelection / setSessionExecutionStrategy`。 -- 新增 `sessionMetadataSyncController.test.ts`,覆盖 runtime source 不回填、session storage fallback patch、workspace default patch、metric context、批量 sync、分散 sync fallback。 - -主线收益: - -- Phase 2 继续瘦 `finalizeResolvedTopicDetail`:会话详情应用、成功指标、metadata fallback、低优先级 sync 不再全部堆在一个长函数里。 -- P1 里提出的“三个迁移回填 invoke 合并或去重”现在有了明确 controller 边界;当前仍优先使用已有 `updateSessionMetadata` 批量命令,fallback 分散命令只在批量命令不存在时使用。 -- 模型、权限、执行策略恢复来源有单测保护,降低旧会话切换后选择器错恢复的风险。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/sessionMetadataSyncController.test.ts" "src/components/agent/chat/hooks/sessionSwitchSnapshotController.test.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.test.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.test.ts" "src/components/agent/chat/hooks/sessionHydrationController.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" -t "模型|权限|执行策略|metadata|stale 快照|预取" --hookTimeout 180000 --testTimeout 120000 -npx eslint "src/components/agent/chat/hooks/sessionMetadataSyncController.ts" "src/components/agent/chat/hooks/sessionMetadataSyncController.test.ts" "src/components/agent/chat/hooks/sessionSwitchSnapshotController.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.ts" "src/components/agent/chat/hooks/sessionHydrationController.ts" "src/components/agent/chat/hooks/useAgentSession.ts" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/components/agent/chat/hooks/sessionMetadataSyncController.ts" "src/components/agent/chat/hooks/sessionMetadataSyncController.test.ts" "src/components/agent/chat/hooks/sessionSwitchSnapshotController.ts" "src/components/agent/chat/hooks/sessionSwitchSnapshotController.test.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.test.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.test.ts" "src/components/agent/chat/hooks/sessionHydrationController.ts" "src/components/agent/chat/hooks/sessionHydrationController.test.ts" "src/components/agent/chat/hooks/useAgentSession.ts" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Metadata / snapshot / retry / fetch / hydration controller:通过,`23` 个测试通过。 -- `useAsterAgentChat` 模型、权限、metadata、stale 快照、预取定向:通过,`25` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- diff 空白检查:通过。 - -GUI / E2E 状态: - -- 本刀未复跑 `verify:gui-smoke`,原因同前:当前 smoke 会切到独立 Rust target 全量重编,容易造成 CPU 和鼠标繁忙;本刀是纯前端 controller 抽取,先用定向行为测试收口。 -- Playwright MCP 仍等待 profile 释放;不使用 isolated profile 绕过仓库规则。 - -下一刀: - -1. 继续 Phase 2:抽 `sessionFinalizeController`,把 workspace mismatch、runtime/topic/shadow source 汇总和 apply detail plan 从 `finalizeResolvedTopicDetail` 中继续移出。 -2. 或恢复 GUI 环境后先采集旧会话 A/B 打开和切换指标,决定是否进入 MessageList projection idle / worker 化。 - -### 2026-05-05:P3 第十一刀,Session finalize controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/sessionFinalizeController.ts`: - - `resolveSessionKnownWorkspaceId` - - `isCrossWorkspaceSessionDetail` - - `buildCrossWorkspaceSessionRestoreContext` - - `buildSessionWorkspaceRestorePlan` - - `resolveShadowSessionExecutionStrategyFallback` - - `resolveSessionExecutionStrategyOverride` -- `useAgentSession.ts` 中 `finalizeResolvedTopicDetail` 的跨 workspace restore guard、runtime/topic/shadow workspace 汇总、shadow execution strategy fallback 与最终 `executionStrategyOverride` 改为委托 controller。 -- 新增 `sessionFinalizeController.test.ts`,覆盖 workspace 优先级、跨 workspace 拒绝条件、拒绝日志上下文、shadow execution strategy fallback 与最终执行策略优先级。 - -主线收益: - -- Phase 2 继续瘦 `finalizeResolvedTopicDetail`:会话详情应用前的 restore guard 与执行策略恢复规则不再和 UI state apply、metadata sync、topic upsert 混在一起。 -- 旧会话恢复的 workspace 保护有单测覆盖,降低多 tab / 多 workspace 切换时旧会话错误覆盖当前工作区的风险。 -- 执行策略恢复的 `runtime -> topic -> shadow -> react` 优先级有独立测试,后续排查首字慢或策略错恢复时可以直接定位到 finalize controller。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/sessionFinalizeController.test.ts" "src/components/agent/chat/hooks/sessionMetadataSyncController.test.ts" "src/components/agent/chat/hooks/sessionSwitchSnapshotController.test.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.test.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.test.ts" "src/components/agent/chat/hooks/sessionHydrationController.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" -t "模型|权限|执行策略|metadata|stale 快照|预取|workspace|跨工作区" --hookTimeout 180000 --testTimeout 120000 -npx eslint "src/components/agent/chat/hooks/sessionFinalizeController.ts" "src/components/agent/chat/hooks/sessionFinalizeController.test.ts" "src/components/agent/chat/hooks/sessionMetadataSyncController.ts" "src/components/agent/chat/hooks/sessionSwitchSnapshotController.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.ts" "src/components/agent/chat/hooks/sessionHydrationController.ts" "src/components/agent/chat/hooks/useAgentSession.ts" --max-warnings 0 -npm run typecheck -- --pretty false -``` - -结果: - -- Finalize / metadata / snapshot / retry / fetch / hydration controller:通过,`28` 个测试通过。 -- `useAsterAgentChat` 模型、权限、metadata、stale 快照、预取、workspace 定向:通过,`29` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -GUI / E2E 状态: - -- 本刀未复跑 `verify:gui-smoke`,原因同前:当前 smoke 会切到独立 Rust target 全量重编,容易造成 CPU 和鼠标繁忙;本刀是纯前端 controller 抽取,先用定向行为测试收口。 -- Playwright MCP 仍等待 profile 释放;不使用 isolated profile 绕过仓库规则。 - -下一刀: - -1. 继续 Phase 2:抽 `sessionPostFinalizePersistenceController` 或 `sessionFinalizeMetadataScheduler`,把 workspace 保存、topic workspace upsert、provider preference apply、metadata idle scheduler 从 `finalizeResolvedTopicDetail` 主体继续移出。 -2. 恢复 GUI 环境后按 `conversation-projection-acceptance.md` 采集旧会话 A/B 打开、切换与首字指标,决定是否进入 MessageList idle / worker 化。 - -### 2026-05-05:P3 第十二刀,Session metadata sync scheduler - -已完成: - -- 新增 `src/components/agent/chat/hooks/sessionMetadataSyncScheduler.ts`: - - `buildSessionMetadataSyncBrowserSkipEvent` - - `buildSessionMetadataSyncStaleSkipEvent` - - `scheduleSessionMetadataSync` -- `useAgentSession.ts` 中 `finalizeResolvedTopicDetail` 的 metadata idle 调度改为委托 scheduler: - - 浏览器桥接下跳过低优先级 runtime invoke。 - - 调度前取消上一条 pending metadata sync。 - - idle 执行时统一 stale request/session guard。 - - 成功后回写 provider preference / execution strategy 同步标记。 - - 失败时保留现有 warn 行为。 -- 新增 `sessionMetadataSyncScheduler.test.ts`,覆盖无 patch 不调度、无 invoke 跳过、取消旧调度、按 idle 参数调度、stale 跳过与失败回调。 - -主线收益: - -- Phase 2 继续瘦 `finalizeResolvedTopicDetail`:metadata patch 的“是否调度、何时调度、如何判过期、如何执行”不再内联在会话详情应用主链里。 -- P1 的“三个回填 invoke 占用 invoke 通道”现在被明确约束在低优先级 scheduler 边界内;后续如果继续合并、降频或批处理,只需要改 scheduler/controller,不再穿透 hook 主体。 -- 旧会话切换时 metadata sync 的 stale guard 有单测保护,避免 A/B 历史会话快速切换后旧调度写回当前会话。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/sessionMetadataSyncScheduler.test.ts" "src/components/agent/chat/hooks/sessionMetadataSyncController.test.ts" "src/components/agent/chat/hooks/sessionFinalizeController.test.ts" "src/components/agent/chat/hooks/sessionSwitchSnapshotController.test.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.test.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.test.ts" "src/components/agent/chat/hooks/sessionHydrationController.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" -t "模型|权限|执行策略|metadata|stale 快照|预取|workspace|跨工作区" --hookTimeout 180000 --testTimeout 120000 -npx eslint "src/components/agent/chat/hooks/sessionMetadataSyncScheduler.ts" "src/components/agent/chat/hooks/sessionMetadataSyncScheduler.test.ts" "src/components/agent/chat/hooks/sessionMetadataSyncController.ts" "src/components/agent/chat/hooks/sessionFinalizeController.ts" "src/components/agent/chat/hooks/sessionSwitchSnapshotController.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.ts" "src/components/agent/chat/hooks/sessionHydrationController.ts" "src/components/agent/chat/hooks/useAgentSession.ts" --max-warnings 0 -npm run typecheck -- --pretty false -``` - -结果: - -- Scheduler / finalize / metadata / snapshot / retry / fetch / hydration controller:通过,`33` 个测试通过。 -- `useAsterAgentChat` 模型、权限、metadata、stale 快照、预取、workspace 定向:通过,`29` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -GUI / E2E 状态: - -- 本刀未复跑 `verify:gui-smoke`,原因同前:当前 smoke 会切到独立 Rust target 全量重编,容易造成 CPU 和鼠标繁忙;本刀是纯前端 scheduler/controller 抽取,先用定向行为测试收口。 -- Playwright MCP 仍等待 profile 释放;不使用 isolated profile 绕过仓库规则。 - -下一刀: - -1. 继续 Phase 2:抽 `sessionPostFinalizePersistenceController`,把 workspace 保存、topic workspace upsert、provider preference apply 从 `finalizeResolvedTopicDetail` 主体继续移出。 -2. 恢复 GUI 环境后按 `conversation-projection-acceptance.md` 采集旧会话 A/B 打开、切换与首字指标,决定是否进入 MessageList idle / worker 化。 - -### 2026-05-05:P3 第十三刀,Session post-finalize persistence controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/sessionPostFinalizePersistenceController.ts`: - - `resolveSessionDetailTopicWorkspaceId` - - `resolvePersistedSessionWorkspaceId` - - `buildSessionPostFinalizePersistencePlan` -- `useAgentSession.ts` 中 `finalizeResolvedTopicDetail` 的 post-finalize 后处理决策改为委托 controller: - - `mapSessionDetailToTopic` 使用的 topic workspace 来源。 - - `agent_session_workspace` 映射持久化 workspace 来源。 - - runtime workspace 回写 topic 字段的条件和值。 - - provider preference apply 的目标 preference。 -- 新增 `sessionPostFinalizePersistenceController.test.ts`,覆盖 topic workspace 优先级、持久化 workspace 来源和完整 post-finalize plan。 - -主线收益: - -- Phase 2 继续瘦 `finalizeResolvedTopicDetail`:会话详情 apply 后的 workspace / provider 后处理不再散落在 hook 主体里。 -- workspace 相关恢复规则进一步可单测,降低旧会话恢复慢问题排查时“到底是 runtime workspace、topic snapshot 还是 shadow cache 生效”的定位成本。 -- provider preference apply 的决策进入同一个 post-finalize plan,为后续继续拆 `finalizeResolvedTopicDetail` 或把 post-apply side effects 降优先级打基础。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/sessionPostFinalizePersistenceController.test.ts" "src/components/agent/chat/hooks/sessionMetadataSyncScheduler.test.ts" "src/components/agent/chat/hooks/sessionMetadataSyncController.test.ts" "src/components/agent/chat/hooks/sessionFinalizeController.test.ts" "src/components/agent/chat/hooks/sessionSwitchSnapshotController.test.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.test.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.test.ts" "src/components/agent/chat/hooks/sessionHydrationController.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" -t "模型|权限|执行策略|metadata|stale 快照|预取|workspace|跨工作区" --hookTimeout 180000 --testTimeout 120000 -npx eslint "src/components/agent/chat/hooks/sessionPostFinalizePersistenceController.ts" "src/components/agent/chat/hooks/sessionPostFinalizePersistenceController.test.ts" "src/components/agent/chat/hooks/sessionMetadataSyncScheduler.ts" "src/components/agent/chat/hooks/sessionMetadataSyncScheduler.test.ts" "src/components/agent/chat/hooks/sessionMetadataSyncController.ts" "src/components/agent/chat/hooks/sessionFinalizeController.ts" "src/components/agent/chat/hooks/sessionSwitchSnapshotController.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.ts" "src/components/agent/chat/hooks/sessionHydrationController.ts" "src/components/agent/chat/hooks/useAgentSession.ts" --max-warnings 0 -npm run typecheck -- --pretty false -``` - -结果: - -- Post-finalize / scheduler / finalize / metadata / snapshot / retry / fetch / hydration controller:通过,`36` 个测试通过。 -- `useAsterAgentChat` 模型、权限、metadata、stale 快照、预取、workspace 定向:通过,`29` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -GUI / E2E 状态: - -- 本刀未复跑 `verify:gui-smoke`,原因同前:当前 smoke 会切到独立 Rust target 全量重编,容易造成 CPU 和鼠标繁忙;本刀是纯前端 controller 抽取,先用定向行为测试收口。 -- Playwright MCP 仍等待 profile 释放;不使用 isolated profile 绕过仓库规则。 - -下一刀: - -1. 继续 Phase 2:抽 `sessionSwitchErrorController`,把 session not found、preserve current snapshot、toast/error metric 等错误恢复判断从 `useAgentSession` 中移出。 -2. 或抽 `sessionHistoryPaginationController`,把完整历史分页窗口计算、stale guard 与 merge 计划从主 hook 中移出。 - -### 2026-05-05:P3 第十四刀,Session switch error controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/sessionSwitchErrorController.ts`: - - `buildSessionSwitchErrorLogContext` - - `buildSessionSwitchErrorToastMessage` - - `resolveSessionSwitchErrorAction` -- `useAgentSession.ts` 中 `handleSwitchTopicError` 的错误恢复分支改为委托 controller: - - session not found:清空当前快照、刷新 topics、不弹 toast。 - - 普通错误:默认清空当前快照并弹 toast。 - - `preserveCurrentSnapshot`:保留当前快照,只弹 toast。 -- 新增 `sessionSwitchErrorController.test.ts`,覆盖 session not found、普通错误、保留快照错误和非 `Error` 文案。 - -主线收益: - -- Phase 2 继续瘦 `useAgentSession`:旧会话切换失败的恢复策略不再散落在 hook 主体里。 -- `preserveCurrentSnapshot` 的行为有单测保护,避免 deferred hydration 失败时误清空当前缓存快照,造成旧会话 UI 闪空或用户误以为卡死。 -- session not found 的清理与 topics 刷新路径可单测,后续排查旧会话恢复失败时能直接定位到错误 controller。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/sessionSwitchErrorController.test.ts" "src/components/agent/chat/hooks/sessionPostFinalizePersistenceController.test.ts" "src/components/agent/chat/hooks/sessionMetadataSyncScheduler.test.ts" "src/components/agent/chat/hooks/sessionMetadataSyncController.test.ts" "src/components/agent/chat/hooks/sessionFinalizeController.test.ts" "src/components/agent/chat/hooks/sessionSwitchSnapshotController.test.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.test.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.test.ts" "src/components/agent/chat/hooks/sessionHydrationController.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" -t "模型|权限|执行策略|metadata|stale 快照|预取|workspace|跨工作区|错误|not found|not found" --hookTimeout 180000 --testTimeout 120000 -``` - -结果: - -- Switch error / post-finalize / scheduler / finalize / metadata / snapshot / retry / fetch / hydration controller:通过,`40` 个测试通过。 -- `useAsterAgentChat` 模型、权限、metadata、stale 快照、预取、workspace、错误定向:通过,`30` 个测试通过。 - -GUI / E2E 状态: - -- 本刀暂未复跑 `verify:gui-smoke`,原因同前:当前 smoke 会切到独立 Rust target 全量重编,容易造成 CPU 和鼠标繁忙;本刀是纯前端 controller 抽取,先用定向行为测试收口。 -- Playwright MCP 仍等待 profile 释放;不使用 isolated profile 绕过仓库规则。 - -下一刀: - -1. 继续 Phase 2:抽 `sessionHistoryPaginationController`,把完整历史分页窗口计算、分页 options、stale guard、merge 计划从 `useAgentSession` 主体中移出。 -2. 恢复 GUI 环境后按 `conversation-projection-acceptance.md` 采集旧会话 A/B 打开、切换与首字指标。 - -### 2026-05-05:P3 第十五刀,Session history pagination controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/sessionHistoryPaginationController.ts`: - - `normalizePositiveInteger` - - `normalizeNonNegativeInteger` - - `resolveDetailHistoryLoadedMessages` - - `resolveSessionHistoryWindowFromDetail` - - `buildSessionHistoryPageRequestPlan` - - `buildSessionHistoryPageResultPlan` -- `useAgentSession.ts` 中 `resolveSessionHistoryWindow` 与 `loadFullSessionHistory` 的分页窗口计算改为委托 controller: - - 首次 detail 截断窗口计算。 - - “加载更早历史”的 `historyLimit / historyOffset / historyBeforeMessageId` 请求参数。 - - loading window 状态。 - - 分页返回后的 `loadedMessages / totalMessages / cursor` 下一轮窗口。 -- 新增 `sessionHistoryPaginationController.test.ts`,覆盖整数归一化、detail loaded count、截断窗口、重复 loading 防护、分页请求计划与分页结果计划。 - -主线收益: - -- Phase 2 继续瘦 `useAgentSession`:完整历史分页不再在主 hook 内手写多段窗口计算。 -- P2 “`loadFullSessionHistory` 用全量拉取改分页”的主线现在有独立 controller 和回归保护,避免后续误退回无分页或重复触发。 -- 旧会话打开慢的排查边界更清晰:首帧 detail hydrate、分页请求参数、分页 merge 可以分别测,不再必须挂载完整 workspace 才能验证窗口算法。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/sessionHistoryPaginationController.test.ts" "src/components/agent/chat/hooks/sessionSwitchErrorController.test.ts" "src/components/agent/chat/hooks/sessionPostFinalizePersistenceController.test.ts" "src/components/agent/chat/hooks/sessionMetadataSyncScheduler.test.ts" "src/components/agent/chat/hooks/sessionMetadataSyncController.test.ts" "src/components/agent/chat/hooks/sessionFinalizeController.test.ts" "src/components/agent/chat/hooks/sessionSwitchSnapshotController.test.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.test.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.test.ts" "src/components/agent/chat/hooks/sessionHydrationController.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" -t "加载更早历史" --hookTimeout 180000 --testTimeout 120000 -npx eslint "src/components/agent/chat/hooks/sessionHistoryPaginationController.ts" "src/components/agent/chat/hooks/sessionHistoryPaginationController.test.ts" "src/components/agent/chat/hooks/sessionSwitchErrorController.ts" "src/components/agent/chat/hooks/sessionSwitchErrorController.test.ts" "src/components/agent/chat/hooks/useAgentSession.ts" --max-warnings 0 -npm run typecheck -- --pretty false -``` - -结果: - -- History pagination / switch error / post-finalize / scheduler / finalize / metadata / snapshot / retry / fetch / hydration controller:通过,`46` 个测试通过。 -- `useAsterAgentChat` 完整历史分页定向:通过,`1` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -GUI / E2E 状态: - -- 本刀未复跑 `verify:gui-smoke`,原因同前:当前 smoke 会切到独立 Rust target 全量重编,容易造成 CPU 和鼠标繁忙;本刀是纯前端 controller 抽取,先用定向行为测试收口。 -- Playwright MCP 仍等待 profile 释放;不使用 isolated profile 绕过仓库规则。 - -下一刀: - -1. 继续 Phase 2:抽 `sessionHistoryMergeController`,把完整历史分页返回后的 messages / turns / items merge 计划从 `loadFullSessionHistory` 中移出。 -2. 或进入 Phase 3:抽 `streamSubmissionController`,把首字链路的 ensure / listener / submit 分段进一步收口。 - -### 2026-05-05:P3 第十六刀,Session history merge controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/sessionHistoryMergeController.ts`: - - `buildSessionHistoryMergePlan` -- `useAgentSession.ts` 中 `loadFullSessionHistory` 的分页返回 merge 改为委托 controller: - - detail messages -> UI messages hydrate。 - - incoming messages 与本地 messages 合并。 - - detail turns 与本地 turns 合并。 - - detail items 经过 legacy normalization、merge、conversation filter。 - - 根据合并后的 turns 恢复 `currentTurnId`。 -- 新增 `sessionHistoryMergeController.test.ts`,覆盖分页 detail 的 messages / turns / threadItems 合并,以及无 incoming turns 时保留当前 turnId。 - -主线收益: - -- Phase 2 中 `loadFullSessionHistory` 的分页请求、分页窗口、分页 merge 已拆成独立 controller;完整历史加载不再把请求参数、窗口状态、消息合并全部堆在 hook 主体中。 -- P2 的“Cursor 分页 + 防止全量拉取”现在有分页窗口和 merge 两层单测保护,后续若旧会话加载仍慢,可以明确区分慢在 runtime page fetch、hydrate/merge,还是 MessageList render。 -- `threadItems` 的 legacy normalization 和 conversation filter 被收进 merge controller,减少后续修分页时漏掉工具过程过滤的风险。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/sessionHistoryMergeController.test.ts" "src/components/agent/chat/hooks/sessionHistoryPaginationController.test.ts" "src/components/agent/chat/hooks/sessionSwitchErrorController.test.ts" "src/components/agent/chat/hooks/sessionPostFinalizePersistenceController.test.ts" "src/components/agent/chat/hooks/sessionMetadataSyncScheduler.test.ts" "src/components/agent/chat/hooks/sessionMetadataSyncController.test.ts" "src/components/agent/chat/hooks/sessionFinalizeController.test.ts" "src/components/agent/chat/hooks/sessionSwitchSnapshotController.test.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.test.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.test.ts" "src/components/agent/chat/hooks/sessionHydrationController.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" -t "加载更早历史" --hookTimeout 180000 --testTimeout 120000 -npx eslint "src/components/agent/chat/hooks/sessionHistoryMergeController.ts" "src/components/agent/chat/hooks/sessionHistoryMergeController.test.ts" "src/components/agent/chat/hooks/sessionHistoryPaginationController.ts" "src/components/agent/chat/hooks/sessionHistoryPaginationController.test.ts" "src/components/agent/chat/hooks/sessionSwitchErrorController.ts" "src/components/agent/chat/hooks/sessionSwitchErrorController.test.ts" "src/components/agent/chat/hooks/useAgentSession.ts" --max-warnings 0 -npm run typecheck -- --pretty false -``` - -结果: - -- History merge / pagination / switch error / post-finalize / scheduler / finalize / metadata / snapshot / retry / fetch / hydration controller:通过,`48` 个测试通过。 -- `useAsterAgentChat` 完整历史分页定向:通过,`1` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -GUI / E2E 状态: - -- 本刀未复跑 `verify:gui-smoke`,原因同前:当前 smoke 会切到独立 Rust target 全量重编,容易造成 CPU 和鼠标繁忙;本刀是纯前端 controller 抽取,先用定向行为测试收口。 -- Playwright MCP 仍等待 profile 释放;不使用 isolated profile 绕过仓库规则。 - -下一刀: - -1. 进入 Phase 3:抽 `streamSubmissionController`,把首页/对话发送首字链路的 ensure session、listener readiness、submit invoke 分段继续收口。 -2. 恢复 GUI 环境后按 `conversation-projection-acceptance.md` 采集旧会话 A/B 打开、切换与首字指标。 - -### 2026-05-05:P3 第十七刀,Agent stream submission controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamSubmissionController.ts`: - - `resolveAgentStreamSubmitErrorMessage` - - `buildAgentStreamSubmitDispatchedContext` - - `buildAgentStreamSubmitAcceptedContext` - - `buildAgentStreamSubmitFailedContext` - - `buildAgentStreamSubmitFailedLogContext` -- `agentStreamSubmitExecution.ts` 中 submit dispatched / accepted / failed 的 metric/log context 改为委托 controller: - - listener bound 到 submit dispatched 的 delta。 - - request start 到 dispatched / accepted / failed 的 elapsed。 - - submit invoke 耗时。 - - metric error message 与 debug 原始 error 分离。 -- 新增 `agentStreamSubmissionController.test.ts`,覆盖 dispatched、accepted、failed metric context 与 failed debug context。 - -主线收益: - -- Phase 3 开始把首字链路拆成可测试边界:提交阶段耗时不再内联在 `executeAgentStreamSubmit` 主体里。 -- `executeAgentStreamSubmit` 继续保持 current runtime 协议,只串接 ensure session、listener binding 和 runtime `submitOp`;submit 分段指标由 controller 统一生成,方便后续 E2E 对比 `ensureSession / listenerBound / submitDispatched / submitAccepted / firstEvent / firstText`。 -- failed metric 与 debug log 的 error 形态被单测固定,避免为了日志可读性破坏 performance summary 的 JSON 友好字段。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/sessionHistoryMergeController.test.ts" "src/components/agent/chat/hooks/sessionHistoryPaginationController.test.ts" "src/components/agent/chat/hooks/sessionSwitchErrorController.test.ts" "src/components/agent/chat/hooks/sessionPostFinalizePersistenceController.test.ts" "src/components/agent/chat/hooks/sessionMetadataSyncScheduler.test.ts" "src/components/agent/chat/hooks/sessionMetadataSyncController.test.ts" "src/components/agent/chat/hooks/sessionFinalizeController.test.ts" "src/components/agent/chat/hooks/sessionSwitchSnapshotController.test.ts" "src/components/agent/chat/hooks/sessionHydrationRetryController.test.ts" "src/components/agent/chat/hooks/sessionDetailFetchController.test.ts" "src/components/agent/chat/hooks/sessionHydrationController.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamSubmissionController.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.ts" "src/components/agent/chat/hooks/sessionHistoryMergeController.ts" "src/components/agent/chat/hooks/sessionHistoryMergeController.test.ts" "src/components/agent/chat/hooks/useAgentSession.ts" --max-warnings 0 -npm run typecheck -- --pretty false -``` - -结果: - -- Agent stream submission / submit execution / submit context / turn event binding:通过,`13` 个测试通过。 -- Session controller 回归:通过,`48` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -GUI / E2E 状态: - -- 本刀未复跑 `verify:gui-smoke`,原因同前:当前 smoke 会切到独立 Rust target 全量重编,容易造成 CPU 和鼠标繁忙;本刀是纯前端 controller 抽取,先用定向行为测试收口。 -- Playwright MCP 仍等待 profile 释放;不使用 isolated profile 绕过仓库规则。 - -下一刀: - -1. 继续 Phase 3:抽 `agentStreamSubmitOpController`,把 runtime `submitOp` 的参数组装从 `agentStreamSubmitExecution` 中移出。 -2. 或抽 `agentStreamListenerReadinessController`,把 listener bound / first event timeout / silent recovery guard 继续拆成可测试 controller。 - -### 2026-05-05:P3 第十八刀,Agent stream submit op controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamSubmitOpController.ts`: - - `buildAgentStreamSubmitOp` -- `agentStreamSubmitExecution.ts` 中 runtime `submitOp` payload 组装改为委托 controller: - - `activeSessionId -> sessionId`。 - - `submitWorkspaceId -> workspaceId`。 - - `requestTurnId -> turnId`。 - - 统一固定 `queueIfBusy: true`,避免 stream submit 主链到处重复声明 busy queue 语义。 -- 新增 `agentStreamSubmitOpController.test.ts`,覆盖首页首发快路径 payload 与底层 `buildUserInputSubmitOp` payload 等价性。 - -主线收益: - -- Phase 3 继续瘦 `executeAgentStreamSubmit`:执行函数现在更接近 `ensure session -> bind listener -> dispatch submit -> record result`,不再同时承担 runtime payload 拼装职责。 -- 首页输入回车后的首字链路更容易分段排查:后续若 `submitInvokeMs` 异常,可直接区分是 submit lifecycle、payload compaction 还是 runtime bridge 慢。 -- `queueIfBusy` 的当前 stream 语义进入单测保护,避免后续修队列/首字时误把 busy 会话变成阻塞式提交。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/utils/buildUserInputSubmitOp.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamSubmitOpController.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.ts" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/components/agent/chat/hooks/agentStreamSubmitOpController.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.ts" -``` - -结果: - -- Agent stream submit op / submit execution / user input builder:通过,`7` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- Diff whitespace check:通过。 - -GUI / E2E 状态: - -- 本刀未复跑 `verify:gui-smoke`。本刀是纯前端 controller 抽取,不改 UI 壳、Bridge、Tauri command 或 runtime event protocol;同时继续避免触发会污染 CPU / 鼠标繁忙现象判断的独立 Rust rebuild。 -- 真实 Playwright E2E 仍按既有规则等待稳定 Lime 页签 / DevBridge 环境,不使用 isolated profile 绕过仓库约束。 - -下一刀: - -1. 继续 Phase 3:抽 `agentStreamListenerReadinessController`,把 listener bound、first event guard、silent recovery 前置条件继续从 submit execution / turn event binding 中拆出。 -2. 或抽 `agentStreamSubmitLifecycleController`,把 dispatched / accepted / failed 记录与 runtime submit invoke 包装成一个可测 lifecycle plan,为 TTFT 阶段日志做更细分的单元边界。 - -### 2026-05-05:P3 第十九刀,Agent stream listener readiness controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamListenerReadinessController.ts`: - - `extractAgentStreamRuntimeEventType` - - `buildAgentStreamListenerBoundContext` - - `buildAgentStreamFirstEventContext` - - `buildAgentStreamFirstEventDeferredContext` - - `shouldDeferAgentStreamFirstEventTimeout` - - `shouldScheduleAgentStreamInactivityWatchdog` - - `shouldIgnoreAgentStreamInactivityResult` -- `agentStreamTurnEventBinding.ts` 中 listener / first event / inactivity guard 改为委托 controller: - - listener bound metric/log context。 - - recognized / unknown first event metric/log context。 - - submit 已派发但首包暂未到达时的 deferred context。 - - inactivity watchdog 是否调度、过期结果是否丢弃的判断。 -- 新增 `agentStreamListenerReadinessController.test.ts`,覆盖 runtime event type 提取、listener bound context、first event context、first event deferred context、first event timeout defer guard、inactivity watchdog guard。 - -主线收益: - -- Phase 3 的 TTFT readiness 分段进入独立单测边界;首字慢现在能更清楚区分 listener 未绑定、submit 已派发但 runtime 无首包、首包后长时间静默等阶段。 -- `agentStreamTurnEventBinding` 继续瘦身,事件绑定主函数不再内联所有 metric context 与 watchdog guard 判断。 -- 未识别但结构合法 runtime event 的首包活跃态继续被测试保护,避免后续 runtime projection/bootstrap 事件导致 UI 误失败。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamListenerReadinessController.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.ts" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/components/agent/chat/hooks/agentStreamListenerReadinessController.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.ts" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Listener readiness controller / turn event binding:通过,`11` 个测试通过。 -- Agent stream readiness / submit / context 回归:通过,`20` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- Diff whitespace check:通过。 - -GUI / E2E 状态: - -- 本刀暂未复跑 `verify:gui-smoke`。本刀仍是纯前端 stream controller 抽取,不改 Tauri command、Bridge、runtime event protocol 或用户可见 UI;继续避免因独立 Rust rebuild 干扰 CPU / 鼠标繁忙问题判断。 - -下一刀: - -1. 继续 Phase 3:抽 `agentStreamSubmitLifecycleController`,把 submit dispatched / accepted / failed metric 记录与 runtime `submitOp` invoke 包装成可测生命周期边界。 -2. 或抽 `agentStreamRequestStartController`,把 request start metric 与 activity log payload 从 `agentStreamTurnEventBinding` 中移出,进一步降低事件绑定主函数职责。 - -### 2026-05-05:P3 第二十刀,Agent stream submit lifecycle controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.ts`: - - `runAgentStreamSubmitLifecycle` -- `agentStreamSubmitExecution.ts` 中 submit dispatched / accepted / failed 的记录和 `runtime.submitOp` invoke 包装改为委托 controller: - - submit dispatched 时写入 `requestState.submissionDispatchedAt`。 - - submit accepted 时记录 `submitInvokeMs`。 - - submit failed 时 metric 记录可 JSON 化错误文案,debug log 保留原始 error,并继续抛出原始错误。 -- 新增 `agentStreamSubmitLifecycleController.test.ts`,覆盖成功和失败两条生命周期,固定 metric/log 顺序与 requestState 更新时间。 - -主线收益: - -- Phase 3 的 submit invoke 生命周期进入独立单测边界,`executeAgentStreamSubmit` 进一步收敛为 ensure session、bind listener、构造 submit op、交给 lifecycle 执行。 -- 首页输入回车后若首字慢,可以更明确地区分:listener bound 慢、submit invoke 慢、runtime 首包慢,还是后续 render 慢。 -- submit 失败链路保留原始错误抛出,不改变现有错误传播语义,同时确保性能 metric 的 error 字段继续适合汇总分析。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.ts" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.ts" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Submit lifecycle / submission context / submit execution / submit op:通过,`9` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`22` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- Diff whitespace check:通过。 - -GUI / E2E 状态: - -- 本刀暂未复跑 `verify:gui-smoke`。本刀仍是纯前端 stream controller 抽取,不改 Tauri command、Bridge、runtime event protocol 或用户可见 UI;继续避免因独立 Rust rebuild 干扰 CPU / 鼠标繁忙问题判断。 - -下一刀: - -1. 继续 Phase 3:抽 `agentStreamRequestStartController`,把 request start metric 与 activity log payload 从 `agentStreamTurnEventBinding` 中移出。 -2. 或抽更细的 `agentStreamUnknownEventController`,把未知 runtime event 活跃态、告警去重与 watchdog 调度从事件绑定主函数中移出。 - -### 2026-05-05:P3 第二十一刀,Agent stream request start controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamRequestStartController.ts`: - - `buildAgentStreamRequestStartMetricContext` - - `buildAgentStreamRequestStartActivityLog` - - `startAgentStreamRequest` -- `agentStreamTurnEventBinding.ts` 中 request start 阶段改为委托 controller: - - 统一写入 `requestState.requestStartedAt`。 - - 统一记录 `agentStream.request.start` metric。 - - 统一创建 activity log,并写回 `requestState.requestLogId`。 -- 新增 `agentStreamRequestStartController.test.ts`,覆盖 metric context、activity log payload、requestState 写入和 metric/activity 依赖调用。 - -主线收益: - -- Phase 3 的首字链路起点进入独立单测边界;request start、listener bound、submit lifecycle、first event readiness 已分别有 controller。 -- `agentStreamTurnEventBinding` 不再直接拼 activity log payload,后续排查首页输入回车慢时可以稳定比较 request start 到 listener / submit / first event 的阶段日志。 -- activity log 的 provider 映射、队列标记、auto continue 元数据继续保持原语义,并由单测固定。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamRequestStartController.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.ts" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/components/agent/chat/hooks/agentStreamRequestStartController.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.ts" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Request start controller / turn event binding:通过,`9` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`25` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- Diff whitespace check:通过。 - -GUI / E2E 状态: - -- 本刀暂未复跑 `verify:gui-smoke`。本刀仍是纯前端 stream controller 抽取,不改 Tauri command、Bridge、runtime event protocol 或用户可见 UI;继续避免因独立 Rust rebuild 干扰 CPU / 鼠标繁忙问题判断。 - -下一刀: - -1. 继续 Phase 3:抽 `agentStreamUnknownEventController`,把未知 runtime event 活跃态、告警去重与首包标记策略移出。 -2. 或抽 `agentStreamInactivityController`,把首包超时、silent recovery、inactivity timeout 的调度与恢复策略进一步收口。 - -### 2026-05-05:P3 第二十二刀,Agent stream unknown event controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamUnknownEventController.ts`: - - `buildAgentStreamUnknownEventWarningMessage` - - `resolveAgentStreamUnknownEventPlan` - - `rememberAgentStreamUnknownEventWarning` -- `agentStreamTurnEventBinding.ts` 中未知 runtime event 分支改为委托 controller: - - 无结构化 `type` 时继续忽略。 - - 有 `type` 但 `parseAgentEvent` 不识别时继续标记首包、激活流、调度 inactivity watchdog。 - - 告警文案与去重状态由 controller 统一生成与记录。 -- 新增 `agentStreamUnknownEventController.test.ts`,覆盖告警文案、空 event type、首次未知事件计划、重复未知事件去重与告警状态记录。 - -主线收益: - -- Phase 3 继续瘦 `agentStreamTurnEventBinding`:未知 runtime event 的活跃态保留策略不再内联在事件绑定主函数中。 -- runtime projection/bootstrap 这类未来扩展事件即使暂未被 parser 识别,也能继续保留首包活跃态,避免 UI 误判首包超时失败。 -- 告警去重进入单测保护,避免 provider 高频心跳或 runtime projection 事件刷屏并干扰首字慢日志分析。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamUnknownEventController.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.ts" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/components/agent/chat/hooks/agentStreamUnknownEventController.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.ts" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Unknown event controller / turn event binding:通过,`10` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`29` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- Diff whitespace check:通过。 - -GUI / E2E 状态: - -- 本刀暂未复跑 `verify:gui-smoke`。本刀仍是纯前端 stream controller 抽取,不改 Tauri command、Bridge、runtime event protocol 或用户可见 UI;继续避免因独立 Rust rebuild 干扰 CPU / 鼠标繁忙问题判断。 - -下一刀: - -1. 继续 Phase 3:抽 `agentStreamInactivityController`,把首包超时、silent recovery、inactivity timeout 的调度与恢复策略进一步收口。 -2. 完成 Phase 3 controller 主链后,回到真实 E2E 指标采集,验证首页输入回车到 first status / first text 的阶段耗时。 - -### 2026-05-05:P3 第二十三刀,Agent stream inactivity controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamInactivityController.ts`: - - `AGENT_STREAM_FIRST_EVENT_TIMEOUT_MESSAGE` - - `AGENT_STREAM_INACTIVITY_TIMEOUT_MESSAGE` - - `buildAgentStreamFirstEventSilentRecoveryWarning` - - `buildAgentStreamFirstEventDeferredWarning` - - `buildAgentStreamInactivitySilentRecoveryWarning` - - `resolveAgentStreamFirstEventTimeoutAction` - - `resolveAgentStreamInactivityTimeoutAction` -- `agentStreamTurnEventBinding.ts` 中首包超时和 inactivity timeout 恢复策略改为委托 controller: - - 首包超时后按 `ignore / recover / defer / fail` 执行动作。 - - inactivity timeout 后按 `ignore / recover / fail` 执行动作。 - - silent recovery 与 deferred warning 文案统一从 controller 生成。 - - 用户可见失败文案统一从 controller 常量读取。 -- 新增 `agentStreamInactivityController.test.ts`,覆盖用户文案、warning 文案、首包超时动作决策与 inactivity timeout 动作决策。 - -主线收益: - -- Phase 3 的首字慢异常恢复链路进一步可测试:首包无事件、后台已恢复、提交已派发但首包暂未到达、首包后长时间静默都进入明确 action plan。 -- `agentStreamTurnEventBinding` 不再内联 silent recovery / timeout 文案与动作优先级,后续调整 TTFT 阈值或恢复策略时风险更小。 -- 首包 deferred 与 inactivity synthetic error 的用户文案保持原语义,避免本轮结构拆分改变用户可见行为。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamInactivityController.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.ts" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/components/agent/chat/hooks/agentStreamInactivityController.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.ts" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Inactivity controller / turn event binding:通过,`10` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`33` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- Diff whitespace check:通过。 - -GUI / E2E 状态: - -- 本刀暂未复跑 `verify:gui-smoke`。本刀仍是纯前端 stream controller 抽取,不改 Tauri command、Bridge、runtime event protocol 或用户可见 UI;继续避免因独立 Rust rebuild 干扰 CPU / 鼠标繁忙问题判断。 - -下一刀: - -1. Phase 3 controller 主链完成后,回到真实 E2E 指标采集,验证首页输入回车到 first status / first text 的阶段耗时。 -2. 若 E2E 仍显示首字慢在事件处理后段,再进入 `streamEventReducer` 拆分;若慢在 render,再进入 Phase 4 render projection。 - -### 2026-05-05:P3 E2E 指标采集准备与阻塞记录 - -已完成: - -- 确认现有前端壳与 DevBridge 已就绪,未启动新的 GUI / Rust 进程: - -```bash -curl -fsS "http://127.0.0.1:1420/" -npm run bridge:health -- --timeout-ms 120000 -``` - -结果: - -- 前端 `http://127.0.0.1:1420/` 可访问。 -- DevBridge `http://127.0.0.1:3030/health` 就绪,`status=ok`,健康检查耗时 `33ms`。 - -阻塞: - -- Playwright MCP 当前无法接管浏览器,报错为 profile 已被 `/Users/coso/Library/Caches/ms-playwright/mcp-chrome-348597d` 占用;按仓库规则未使用 `--isolated` 绕过。 -- 已检查 Chrome 现有页签,存在 `http://127.0.0.1:1420/` 的 `Lime` 页签。 -- AppleScript 可读取 Chrome 页签 URL / title,但 Chrome 未开启“允许 Apple 事件中的 JavaScript”,无法执行 `window.__LIME_AGENTUI_PERF__?.summary()` 采集页面指标。 -- 未结束或清理现有 MCP / Chrome 进程,避免破坏用户或其他 agent 的浏览器会话。 - -下一次续测条件: - -1. 关闭占用 `mcp-chrome-348597d` 的旧 Playwright MCP 会话,或由用户确认允许清理这些 MCP 进程。 -2. 或在现有 Chrome 中开启 `查看 -> 开发者 -> 允许 Apple 事件中的 JavaScript`,允许只读执行 `window.__LIME_AGENTUI_PERF__?.summary()`。 -3. 恢复后按 `docs/roadmap/agentui/conversation-projection-acceptance.md` 采集:首页短 prompt -> conversation shell -> first runtime status -> first text delta/paint。 - -### 2026-05-05:P3 第二十四刀,Agent stream runtime metrics controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.ts`: - - `shouldRecordAgentStreamFirstRuntimeStatus` - - `shouldRecordAgentStreamFirstTextDelta` - - `buildAgentStreamFirstRuntimeStatusMetricContext` - - `buildAgentStreamFirstTextDeltaMetricContext` -- `agentStreamRuntimeHandler.ts` 中 first runtime status / first text delta 指标记录改为委托 controller: - - first runtime status 的 elapsed、first event delta、phase、title、session 统一生成。 - - first text delta 的 delta chars、elapsed、first event delta、first runtime status delta、session 统一生成。 - - 一次性记录判断进入单测,避免重复 text delta 或重复 runtime status 污染 TTFT 指标。 -- 新增 `agentStreamRuntimeMetricsController.test.ts`,覆盖 first status/text delta 是否记录、指标上下文和缺失前置阶段时的 null delta。 - -主线收益: - -- Phase 3 的首字链路后段继续可测试:`request start -> listener -> submit -> first event -> first runtime status -> first text delta` 的指标上下文已基本从主函数中拆出。 -- 后续 E2E 恢复后,`window.__LIME_AGENTUI_PERF__` 的阶段指标更容易对应到 controller 单测,便于判断慢点在 runtime bridge、provider 首包、事件处理还是 render。 -- `agentStreamRuntimeHandler` 开始为 `streamEventReducer` 拆分做前置减法,先抽指标与判断,不一次性重写大 switch,降低回归风险。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.ts" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Runtime metrics controller / runtime handler:通过,`15` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`48` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- Diff whitespace check:通过。 - -GUI / E2E 状态: - -- 本刀仍未做真实页面交互。阻塞同前:Playwright MCP profile 被占用,且 Chrome 未开启 AppleScript JS 执行能力。 -- 前端与 DevBridge 健康态已在上一条记录确认;未启动新的 GUI / Rust 进程。 - -下一刀: - -1. 恢复 E2E 后采集 `firstRuntimeStatus / firstTextDelta / firstTextPaint` 指标,确认慢点是否仍在事件处理后段。 -2. 若仍无法恢复 E2E,就继续小步拆 `agentStreamRuntimeHandler` 中 text delta flush / runtime status apply 的 reducer 边界。 - -### 2026-05-05:P3 第二十五刀,Agent stream runtime status controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamRuntimeStatusController.ts`: - - `buildAgentStreamNormalizedRuntimeStatus` - - `buildAgentStreamRuntimeStatusApplyPlan` - - `selectAgentStreamRuntimeSummaryItem` - - `buildAgentStreamRuntimeSummaryItemUpdate` -- `agentStreamRuntimeHandler.ts` 中 `runtime_status` apply 逻辑改为委托 controller: - - runtime status title 归一化。 - - runtime summary 文案生成。 - - pending summary item 优先选择。 - - pending item 存在但不是 `turn_summary` 时保持原行为,不回退其他 summary。 - - 无 pending item 时选择同 session 最新 in-progress summary。 -- 新增 `agentStreamRuntimeStatusController.test.ts`,覆盖 status apply plan、pending summary 优先级、pending 非 summary 不回退、fallback 最新 summary 与 summary item 更新。 - -主线收益: - -- Phase 3 继续为 `streamEventReducer` 拆分做前置减法:`runtime_status` 的状态归一化与 thread summary 更新策略不再内联在 `agentStreamRuntimeHandler` 大 switch 中。 -- 首字前状态展示路径更可测,后续 E2E 若显示 first runtime status 已到但 UI 状态慢,可直接定位到 status apply / render,而不是混在事件处理主函数里。 -- 保留 pending 非 summary 不回退的旧行为,避免结构拆分顺手改变 runtime summary 选择语义。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.ts" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Runtime status controller / runtime handler:通过,`16` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`53` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- Diff whitespace check:通过。 - -GUI / E2E 状态: - -- 本刀仍未做真实页面交互。阻塞同前:Playwright MCP profile 被占用,且 Chrome 未开启 AppleScript JS 执行能力。 -- 未启动新的 GUI / Rust 进程,不干扰用户当前浏览器会话。 - -下一刀: - -1. 恢复 E2E 后采集 `firstRuntimeStatus / firstTextDelta / firstTextPaint` 指标,确认首字慢是否仍在事件处理后段。 -2. 若 E2E 仍无法恢复,继续拆 `agentStreamRuntimeHandler` 中 text delta flush 或 final_done reconcile 的 reducer 边界。 - -### 2026-05-05:P3 第二十六刀,Agent stream text delta controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamTextDeltaController.ts`: - - `buildAgentStreamTextDeltaApplyPlan` -- `agentStreamRuntimeHandler.ts` 中 `text_delta` apply 前半段改为委托 controller: - - text delta buffer 计数。 - - 首个 text delta 的时间戳和 metric context。 - - accumulated content 的 overlap append 计划。 - - observer 仍收到原始 delta 和合并后的 accumulated content。 - - typewriter sound 与 text render flush 调度保持原位置,不改变渲染节流行为。 -- 新增 `agentStreamTextDeltaController.test.ts`,覆盖首个 text delta 指标、非首个 delta 不重复记录、overlap detection 防重复吐字。 - -主线收益: - -- Phase 3 继续为 `streamEventReducer` 拆分做前置减法:`text_delta` 的 buffer / first delta metric / overlap append 逻辑不再内联在 runtime handler 大 switch 中。 -- 重复吐字问题的关键防线进入独立 controller 单测,后续调整流式 flush 或 final_done reconcile 时更不容易破坏。 -- 首字链路的 first text delta metric 与实际 accumulated content 更新绑定在同一个 apply plan,便于后续 E2E 对齐 `firstTextDelta` 与 `firstTextPaint`。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamTextDeltaController.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.ts" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/components/agent/chat/hooks/agentStreamTextDeltaController.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Text delta controller / runtime handler:通过,`14` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`56` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- Diff whitespace check:通过。 - -GUI / E2E 状态: - -- 本刀仍未做真实页面交互。阻塞同前:Playwright MCP profile 被占用,且 Chrome 未开启 AppleScript JS 执行能力。 -- 未启动新的 GUI / Rust 进程,不干扰用户当前浏览器会话。 - -下一刀: - -1. 恢复 E2E 后采集 `firstTextDelta / firstTextPaint` 指标,确认首字慢是否仍在 text render flush。 -2. 若 E2E 仍无法恢复,继续拆 text render flush 或 final_done reconcile 的 reducer 边界。 - -### 2026-05-05:P3 第二十七刀,Agent stream text render flush controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamTextRenderFlushController.ts`: - - `resolveAgentStreamPendingRenderedTextDelta` - - `shouldFlushAgentStreamVisibleFirstText` - - `shouldScheduleAgentStreamTextRenderTimer` - - `buildAgentStreamTextRenderFlushPlan` - - `buildAgentStreamFirstTextPaintContext` -- `agentStreamRuntimeHandler.ts` 中 `flushPendingTextRender / scheduleTextRenderFlush` 改为委托 controller: - - 首个可见文本继续立即 flush,不等待 32ms timer。 - - 后续 text render flush 继续保持 `TEXT_DELTA_RENDER_FLUSH_MS=32` 节流。 - - first text render flush、first text paint、backlog、flush count、debug dedupe key 由 plan 统一计算。 - - `requestState.renderedContent / textDeltaFlushCount / lastTextRenderFlushAt / maxTextDeltaBacklogChars / firstTextPaintScheduled` 仍在 handler 中作为副作用写回。 -- 新增 `agentStreamTextRenderFlushController.test.ts`,覆盖待渲染 delta 解析、首字立即 flush 判定、timer 调度、首个 render flush plan、非首 flush 不重复 first metric、first paint metric context。 - -主线收益: - -- Phase 3 继续为 `streamEventReducer` 拆分做前置减法:文本可见渲染 flush 的决策、指标和日志上下文不再内联在 `agentStreamRuntimeHandler` 大函数中。 -- 首字链路后半段现在可单独测试:`firstTextDelta -> firstTextRenderFlush -> firstTextPaint` 的延迟可以从 controller plan 与 E2E 指标对齐分析。 -- 保留“首个可见文本立即 flush、后续 32ms 节流”的当前性能语义,不引入 UI 协议变化或新队列。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.ts" --max-warnings 0 -npm run typecheck -- --pretty false -``` - -结果: - -- Text render flush controller / runtime handler:通过,`16` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`61` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -GUI / E2E 状态: - -- 本刀未做真实页面交互。它是纯前端 stream controller 抽取,不改 Tauri command、Bridge、runtime event protocol 或用户可见 UI。 -- 仍避免启动新的 GUI / Rust 进程,防止干扰用户正在观察的 CPU / 鼠标繁忙问题。 - -下一刀: - -1. 先补本刀 `git diff --check` 后收口;随后恢复 E2E 后采集 `firstTextDelta / firstTextRenderFlush / firstTextPaint / textDeltaFlushCount / maxTextDeltaBacklogChars`。 -2. 若 E2E 仍显示慢在事件处理后段,继续拆 `final_done` reconcile / completion reducer;若慢在 render,则进入 Phase 4 render projection 或 Markdown hydrate 分批。 - -### 2026-05-05:P3 第二十八刀,Agent stream completion controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamCompletionController.ts`: - - `isAgentStreamEmptyFinalReplyError` - - `shouldFailAgentStreamMissingFinalReply` - - `resolveAgentStreamGracefulCompletionContent` - - `reconcileAgentStreamFinalContentParts` - - 空最终回复错误文案常量。 -- `agentStreamRuntimeHandler.ts` 中 `final_done` 与 empty-final-error 降级分支改为委托 completion controller: - - 空最终回复失败判定不再在 `final_done` 分支内联计算。 - - graceful completion 内容继续先剥离 assistant protocol residue,再按原逻辑回退 raw / fallback。 - - 最终 `contentParts` reconcile 继续保留过程 part、按 `surfaceThinkingDeltas` 过滤 thinking,并在最终文本变化时重建 text part。 -- 新增 `agentStreamCompletionController.test.ts`,覆盖 empty-final-error 识别、空回复失败判定、meaningful completion signal 降级、协议残留 fallback、最终 contentParts reconcile 与 thinking 过滤。 - -主线收益: - -- Phase 3 继续收窄 `agentStreamRuntimeHandler` 大 switch:完成态的纯判断和最终消息内容计划已进入独立 controller,后续再拆副作用 action 时不需要同时搬协议残留和 contentParts 细节。 -- 重复吐字 / 排版问题的完成态防线更清晰:`text_delta` 负责 overlap append,`text render flush` 负责可见增量,`completion` 负责最终文本与 contentParts 对齐。 -- 保留现有行为,不改变 runtime event protocol、toast 文案或用户可见 UI。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamCompletionController.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" --max-warnings 0 -npm run typecheck -- --pretty false -``` - -结果: - -- Completion controller / runtime handler:通过,`16` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`66` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -GUI / E2E 状态: - -- 本刀未做真实页面交互。它仍是纯前端 stream controller 抽取,不改 Tauri command、Bridge、runtime event protocol 或用户可见 UI。 -- 未启动新的 GUI / Rust 进程,避免干扰用户当前 CPU / 鼠标繁忙观察。 - -下一刀: - -1. 补本刀 `git diff --check` 后,优先恢复 E2E 指标采集,确认首页 Enter 到 `firstRuntimeStatus / firstTextDelta / firstTextPaint` 的真实分段。 -2. 若仍无法 E2E,就把 completion/error 的副作用路径包装成更薄的 reducer action,或开始拆 `agentStreamRuntimeHandler` 的 tool event apply 边界。 - -### 2026-05-05:P3 第二十九刀,Agent stream tool completion signal controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.ts`: - - `hasMeaningfulAgentStreamToolCompletionSignal` - - 内部统一把 normalized tool result 转为 record。 - - 复用站点保存信号、图片任务预览、通用任务预览与 artifact 预览作为 meaningful completion signal 判断来源。 -- `agentStreamRuntimeHandler.ts` 的 `tool_end` 分支改为委托 tool completion signal controller: - - handler 不再直接依赖 `siteToolResultSummary` 与 `taskPreviewFromToolResult` 的多种预览构造函数。 - - 仍只在 tool result 真实可展示/可恢复时设置 `requestState.hasMeaningfulCompletionSignal`。 -- 新增 `agentStreamToolCompletionSignalController.test.ts`,覆盖站点保存 metadata、图片任务 metadata 与普通空结果。 - -主线收益: - -- Phase 3 继续压缩 `agentStreamRuntimeHandler` 的横向依赖:tool result 是否能支撑“无最终文本但过程有产物”的完成语义进入独立 controller。 -- completion controller 与 tool completion signal controller 分工更清楚:前者处理最终内容/协议残留,后者处理工具产物是否构成可降级完成信号。 -- 后续排查“模型未输出最终答复但 UI 是否应显示失败”时,可以单测 tool result 信号,不需要跑完整 stream handler。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" --max-warnings 0 -npm run typecheck -- --pretty false -npm run bridge:health -- --timeout-ms 120000 -``` - -结果: - -- Tool completion signal / completion / runtime handler:通过,`19` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`69` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- DevBridge health:通过,`77ms` 就绪。 - -GUI / E2E 状态: - -- 已尝试进入 Playwright MCP 续测,但当前 MCP Chrome profile 仍被占用:`Browser is already in use for /Users/coso/Library/Caches/ms-playwright/mcp-chrome-348597d, use --isolated to run multiple instances of the same browser`。 -- 按 `docs/aiprompts/playwright-e2e.md` 约束,本轮没有使用 `--isolated`,也没有 kill/清理现有 Chrome 或 MCP 进程。 - -下一刀: - -1. 等 Playwright MCP profile 可复用后,优先采集首页 Enter 到 `firstRuntimeStatus / firstTextDelta / firstTextPaint` 的真实分段。 -2. 如果仍无法 E2E,继续把 `agentStreamRuntimeHandler` 的 error/final completion 副作用或 tool event apply 拆成更小 action plan。 - -### 2026-05-05:P3 第三十刀,Agent stream error controller - -已完成: - -- 进入 Playwright MCP 前先执行 `npm run bridge:health -- --timeout-ms 120000`,DevBridge `111ms` 就绪。 -- 再次尝试复用 Playwright MCP 当前浏览器会话,仍被 MCP Chrome profile lock 阻塞:`Browser is already in use for /Users/coso/Library/Caches/ms-playwright/mcp-chrome-348597d, use --isolated to run multiple instances of the same browser`。 -- 按续遵守 `docs/aiprompts/playwright-e2e.md`:没有使用 `--isolated`,没有 kill/清理现有 Chrome 或 MCP 进程。 -- 新增 `src/components/agent/chat/hooks/agentStreamErrorController.ts`: - - `buildAgentStreamErrorToastPlan` - - `buildAgentStreamFailedAssistantMessagePatch` -- `agentStreamRuntimeHandler.ts` 的 missing final failure 与普通 error 分支改为委托 error controller: - - rate limit / 429 toast level 与文案不再在 handler 内联判断。 - - 失败 assistant 消息的 `content / runtimeStatus / isThinking / usage` patch 不再在 handler 重复组装。 - - `markFailedTimelineState` 仍保留在 handler 内,继续负责 thread turn / item 的副作用写回。 -- 新增 `agentStreamErrorController.test.ts`,覆盖 rate limit warning、普通 error toast、保留局部输出的失败消息 patch、无局部输出时回退 previous content 与 usage 带回。 - -主线收益: - -- Phase 3 继续压缩 `agentStreamRuntimeHandler` 的 error 分支:展示决策和失败消息 patch 进入纯 controller,handler 只保留必要副作用顺序。 -- 首字/流式链路出错时更容易定位:runtime event、completion fallback、tool completion signal、error presentation 已分别可单测。 -- 保留现有 UI 文案与失败状态语义,不改变 runtime event protocol、Tauri command 或 Bridge。 - -已验证: - -```bash -npm run bridge:health -- --timeout-ms 120000 -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamErrorController.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" --max-warnings 0 -npm run typecheck -- --pretty false -``` - -结果: - -- Error controller / runtime handler:通过,`15` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`73` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- DevBridge health:通过,`111ms` 就绪。 - -GUI / E2E 状态: - -- 真实页面交互仍未完成,停留在 MCP profile lock 阶段;当前没有可报告的页面 URL / 控制台 error 增量 / 首页 Enter 指标。 -- 本刀是纯前端 stream controller 抽取,不改 GUI 壳、Tauri command、Bridge、mock 或用户可见 UI;因此未启动 `verify:gui-smoke`,避免 Rust rebuild 干扰 CPU / 鼠标繁忙观察。 - -下一刀: - -1. 等 Playwright MCP profile 可复用后,优先恢复 E2E 采集首页 Enter 到 `firstRuntimeStatus / firstTextDelta / firstTextPaint` 的真实分段。 -2. 若 E2E 继续不可用,继续拆 `agentStreamRuntimeHandler` 中 warning / queued draft / thread item 高频事件的纯 action plan,而不是扩大到 GUI 重构。 - -### 2026-05-05:P3 第三十一刀,Agent stream warning controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamWarningController.ts`: - - `buildAgentStreamWarningPlan` - - 统一 workspace auto-created warning 忽略、warning key 生成、已提示去重、shouldToast 判断与 toast level/message plan。 -- `agentStreamRuntimeHandler.ts` 的 `warning` 分支改为委托 warning controller: - - handler 不再直接依赖 `WORKSPACE_PATH_AUTO_CREATED_WARNING_CODE` 与 `resolveRuntimeWarningToastPresentation`。 - - handler 只保留 `warnedKeysRef` 写入与 `toast.info/error/warning` 副作用。 - - 保留现有语义:不需要 toast 的 warning 仍会标记 warned,避免后续重复处理。 -- 新增 `agentStreamWarningController.test.ts`,覆盖 workspace auto-created 忽略、重复 warning 不 toast、普通 warning toast plan、不 toast warning 仍标记 warned。 - -主线收益: - -- Phase 3 继续压缩 `agentStreamRuntimeHandler` 的低频分支:warning 事件的忽略/去重/展示决策进入纯 controller。 -- 当前 stream handler 中首字、运行态、文本增量、渲染 flush、完成态、tool completion signal、error、warning 都已有独立可测边界。 -- 保留现有 UI 文案与 warning 去重语义,不改变 runtime event protocol、Tauri command 或 Bridge。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamWarningController.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" --max-warnings 0 -npm run typecheck -- --pretty false -``` - -结果: - -- Warning controller / runtime handler:通过,`15` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`77` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -GUI / E2E 状态: - -- 本刀未重新进入 Playwright;上一刀已经确认 MCP profile lock 阻塞仍在。 -- 本刀是纯前端 stream controller 抽取,不改 GUI 壳、Tauri command、Bridge、mock 或用户可见 UI;继续不启动 `verify:gui-smoke`,避免 Rust rebuild 干扰用户观察 CPU / 鼠标繁忙。 - -下一刀: - -1. Playwright MCP 可复用后,优先恢复 E2E 指标采集。 -2. 若继续做代码小刀,优先拆 queued draft / thread item 高频事件的 action plan,或开始把 `handleToolStartEvent / handleToolEndEvent` 周边状态写回收敛成更薄边界。 - -### 2026-05-05:P3 最终收口,stream controller 阶段验证边界 - -收口结论: - -- 本阶段 Phase 3 代码侧已完成一组可测 controller 拆分:submit、listener readiness、request start、unknown event、inactivity、runtime metrics、runtime status、text delta、text render flush、completion、tool completion signal、error、warning。 -- `agentStreamRuntimeHandler.ts` 仍保留必要 UI / thread / toast 副作用顺序,但首字链路、重复吐字防线、完成态降级、错误与 warning 展示决策都已从大 switch 中移出。 -- 最后一次尝试 Playwright MCP 仍失败于 profile lock:`Browser is already in use for /Users/coso/Library/Caches/ms-playwright/mcp-chrome-348597d, use --isolated to run multiple instances of the same browser`。 -- 按续遵守 GUI 续测约束:没有使用 `--isolated`,没有 kill / 清理用户当前 Chrome 或 MCP 进程。 - -最终验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -``` - -结果: - -- Agent stream Phase 3 定向回归最终复跑:通过,`19` 个测试文件、`77` 个测试通过。 -- 本阶段最近一次静态验证已通过:ESLint touched files、TypeScript `tsc --noEmit --pretty false`、`git diff --check`。 - -未完成边界: - -- 真实 GUI / Playwright E2E 仍未完成;缺少首页 Enter 到 `firstRuntimeStatus / firstTextDelta / firstTextPaint` 的最终实测数据。 -- 因此本阶段只能判定“stream controller 代码拆分与定向回归完成”,不能判定“GUI 体感性能已最终交付”。 - -下一步最短路径: - -1. 释放或复用 Playwright MCP profile 后,立即采集首页 Enter / 旧会话打开的真实性能 summary。 -2. 若 `firstTextPaint` 已快但仍卡,转向 render / Markdown hydrate;若 `firstTextDelta` 慢,转 provider / runtime;若 `submitAccepted` 前慢,回查 session ensure / listener bind。 - -### 2026-05-05:P3 第三十二刀,Agent stream queue controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamQueueController.ts`: - - `buildAgentStreamQueuedDraftMessagePatch` - - `shouldWatchAgentStreamQueuedDraftCleanup` - - `shouldWatchAgentStreamQueuedDraftCleanupForCleared` -- `agentStreamRuntimeHandler.ts` 的 queued draft / queue removed / queue cleared 分支改为委托 queue controller: - - queued draft 的 `isThinking=false` 与 queued runtime status patch 不再在 handler 内联组装。 - - queue removed / cleared 后是否继续观察当前 queued draft 的判断不再散落在 switch case 中。 - - handler 仍保留 `requestState.queuedTurnId`、queued turn store、draft cleanup timer 等副作用顺序。 -- 新增 `agentStreamQueueController.test.ts`,覆盖 queued message text 优先、content fallback、单个 removed 与 cleared 覆盖当前 draft 的判断。 - -主线收益: - -- Phase 3 继续压缩 `agentStreamRuntimeHandler` 的 queue 分支:排队态展示与 cleanup watch 判定进入纯 controller。 -- 首页 Enter / 多 tab / busy 会话场景依赖 `queueIfBusy` 与 queued draft 展示;该语义现在有独立单测保护,后续排查“新建/旧会话切换后无法继续输入”时更好定位。 -- 保留现有 queue 行为,不改变 runtime event protocol、Tauri command、Bridge 或用户可见文案。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamQueueController.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" --max-warnings 0 -npm run typecheck -- --pretty false -``` - -结果: - -- Queue controller / runtime handler:通过,`15` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`20` 个测试文件、`81` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -GUI / E2E 状态: - -- 本刀未进入 Playwright;此前已经确认 MCP profile lock 阻塞仍在。 -- 本刀仍是纯前端 stream controller 抽取,不改 GUI 壳、Tauri command、Bridge、mock 或用户可见 UI;继续不启动 `verify:gui-smoke`,避免 Rust rebuild 干扰用户观察 CPU / 鼠标繁忙。 - -下一刀: - -1. Playwright MCP 可复用后,优先恢复真实 E2E 指标采集。 -2. 如果继续代码拆分,下一刀只看 thread item 高频事件的 action plan,不再扩大到无关 UI 重构。 - -### 2026-05-05:P3 第三十三刀,Agent stream thread item controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamThreadItemController.ts`: - - `shouldDeferAgentStreamThreadItemUpdate` - - `buildAgentStreamTurnStartedPendingItemUpdate` -- `agentStreamRuntimeHandler.ts` 的 `turn_started` 与 `item_updated` 分支改为委托 thread item controller: - - in-progress `reasoning / agent_message` 高频更新延后判断不再内联在 handler。 - - `turn_started` 时 pending item 绑定真实 `thread_id / turn_id / updated_at` 的 patch 不再内联组装。 - - handler 仍保留 `setThreadItems`、remove/upsert 顺序与其它 runtime 副作用。 -- 新增 `agentStreamThreadItemController.test.ts`,覆盖 reasoning / agent_message 延后、非文本/已完成 item 不延后、pending item 绑定真实 turn、无 pending item 返回空。 - -主线收益: - -- Phase 3 继续压缩 `agentStreamRuntimeHandler` 的 thread item 分支:高频更新策略与 turn_started pending patch 进入纯 controller。 -- 旧会话恢复与流式过程中 thread item 数量大时,最容易产生同步计算和状态写入压力;这条延后策略现在有独立单测保护。 -- 保留现有行为,不改变 runtime event protocol、Tauri command、Bridge 或用户可见 UI。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamThreadItemController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamThreadItemController.test.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamThreadItemController.ts" "src/components/agent/chat/hooks/agentStreamThreadItemController.test.ts" "src/components/agent/chat/hooks/agentStreamQueueController.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" --max-warnings 0 -npm run typecheck -- --pretty false -``` - -结果: - -- Thread item controller / runtime handler:通过,`15` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`21` 个测试文件、`85` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -GUI / E2E 状态: - -- 本刀未进入 Playwright;此前已经确认 MCP profile lock 阻塞仍在。 -- 本刀仍是纯前端 stream controller 抽取,不改 GUI 壳、Tauri command、Bridge、mock 或用户可见 UI;继续不启动 `verify:gui-smoke`,避免 Rust rebuild 干扰用户观察 CPU / 鼠标繁忙。 - -下一刀: - -1. Playwright MCP 可复用后,优先恢复真实 E2E 指标采集。 -2. 如果继续代码拆分,只看 tool / artifact / action event apply 的薄 action plan,避免偏离主线。 - -### 2026-05-05:P3 第三十四刀,Agent stream tool event controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamToolEventController.ts`: - - `buildAgentStreamToolEndPreApplyPlan` - - 统一 `tool_end` 前置的 `normalizeIncomingToolResult`、`toolNameByToolId` lookup 与 meaningful completion signal 判断。 -- `agentStreamRuntimeHandler.ts` 的 `tool_end` 分支改为委托 tool event controller: - - handler 不再直接依赖 `normalizeIncomingToolResult` 与 `hasMeaningfulAgentStreamToolCompletionSignal`。 - - handler 仍只在 plan 标记 `hasMeaningfulCompletionSignal` 时写回 `requestState.hasMeaningfulCompletionSignal`。 - - `handleToolEndEvent` 的原始副作用路径保持不变,避免改变工具结果展示、文件写入和消息更新顺序。 -- 新增 `agentStreamToolEventController.test.ts`,覆盖 tool name lookup、Lime metadata block 归一化、图片任务 meaningful completion 与普通 result 不标记。 - -主线收益: - -- Phase 3 继续压缩 `agentStreamRuntimeHandler` 的 tool_end 分支:工具完成前置判断进入纯 controller。 -- “有工具产物但模型未输出最终文本”这条降级完成语义现在由 tool completion signal 与 tool event pre-apply plan 共同保护。 -- 保留现有行为,不改变 runtime event protocol、Tauri command、Bridge、文件写入或用户可见 UI。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamToolEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamToolEventController.test.ts" "src/components/agent/chat/hooks/agentStreamThreadItemController.test.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamToolEventController.ts" "src/components/agent/chat/hooks/agentStreamToolEventController.test.ts" "src/components/agent/chat/hooks/agentStreamThreadItemController.ts" "src/components/agent/chat/hooks/agentStreamThreadItemController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" --max-warnings 0 -npm run typecheck -- --pretty false -``` - -结果: - -- Tool event controller / runtime handler:通过,`14` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`22` 个测试文件、`88` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -GUI / E2E 状态: - -- 本刀未进入 Playwright;此前已经确认 MCP profile lock 阻塞仍在。 -- 本刀仍是纯前端 stream controller 抽取,不改 GUI 壳、Tauri command、Bridge、mock 或用户可见 UI;继续不启动 `verify:gui-smoke`,避免 Rust rebuild 干扰用户观察 CPU / 鼠标繁忙。 - -下一刀: - -1. Playwright MCP 可复用后,优先恢复真实 E2E 指标采集。 -2. 如果继续代码拆分,只看 artifact / action event apply 的薄 action plan,避免偏离主线。 - -### 2026-05-05:P3 第三十五刀,Agent stream artifact/action controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamArtifactActionController.ts`: - - `buildAgentStreamArtifactSnapshotPreApplyPlan` - - `buildAgentStreamActionRequiredPreApplyPlan` -- `agentStreamRuntimeHandler.ts` 的 `artifact_snapshot / action_required` 分支改为委托 artifact/action controller: - - `artifact_snapshot` 前置的 activate stream、清 optimistic item、meaningful completion signal 标记进入 plan。 - - `action_required` 前置的 activate stream、清 optimistic item 进入 plan。 - - `handleArtifactSnapshotEvent / handleActionRequiredEvent` 的原始副作用路径保持不变。 -- 新增 `agentStreamArtifactActionController.test.ts`,覆盖 artifact snapshot 前置计划、空 artifact 仍保持完成信号语义、action required 前置计划。 - -主线收益: - -- Phase 3 继续压缩 `agentStreamRuntimeHandler` 的 artifact/action 分支:事件前置副作用决策进入纯 controller。 -- artifact snapshot 仍作为 meaningful completion signal,保护“有产物但模型未输出最终文本”的降级完成语义。 -- 保留现有行为,不改变 runtime event protocol、Tauri command、Bridge、文件写入、权限确认或用户可见 UI。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamArtifactActionController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamArtifactActionController.test.ts" "src/components/agent/chat/hooks/agentStreamToolEventController.test.ts" "src/components/agent/chat/hooks/agentStreamThreadItemController.test.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamArtifactActionController.ts" "src/components/agent/chat/hooks/agentStreamArtifactActionController.test.ts" "src/components/agent/chat/hooks/agentStreamToolEventController.ts" "src/components/agent/chat/hooks/agentStreamToolEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" --max-warnings 0 -npm run typecheck -- --pretty false -``` - -结果: - -- Artifact/action controller / runtime handler:通过,`14` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`23` 个测试文件、`91` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -GUI / E2E 状态: - -- 本刀未进入 Playwright;此前已经确认 MCP profile lock 阻塞仍在。 -- 本刀仍是纯前端 stream controller 抽取,不改 GUI 壳、Tauri command、Bridge、mock 或用户可见 UI;继续不启动 `verify:gui-smoke`,避免 Rust rebuild 干扰用户观察 CPU / 鼠标繁忙。 - -下一刀: - -1. Playwright MCP 可复用后,优先恢复真实 E2E 指标采集。 -2. 如果继续代码拆分,只看 context trace / turn context / model change event apply 的薄 action plan,避免偏离主线。 - -### 2026-05-05:P3 第三十六刀,Agent stream runtime context controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamRuntimeContextController.ts`: - - `buildAgentStreamContextTracePreApplyPlan` - - `buildAgentStreamTurnContextPreApplyPlan` - - `buildAgentStreamModelChangePreApplyPlan` - - `applyAgentStreamTurnContextExecutionRuntime` - - `applyAgentStreamModelChangeExecutionRuntime` -- `agentStreamRuntimeHandler.ts` 的 `context_trace / turn_context / model_change` 分支改为委托 runtime context controller: - - `context_trace` 前置 activate stream / clear optimistic item 进入 plan。 - - `turn_context / model_change` 前置 activate stream 进入 plan。 - - execution runtime apply 通过 controller wrapper 进入 handler,原有 apply 语义不变。 - - `handleContextTraceEvent` 与 `setExecutionRuntime` 副作用顺序保持不变。 -- 新增 `agentStreamRuntimeContextController.test.ts`,覆盖 context trace latest stage、turn context runtime apply、model change runtime apply 与当前 turn 状态保留。 - -主线收益: - -- Phase 3 继续压缩 `agentStreamRuntimeHandler` 的 context/runtime 分支:上下文轨迹与 execution runtime 更新前置决策进入纯 controller。 -- 首字链路中 `turn_context / model_change` 到达后,runtime 恢复状态仍受现有 utility 保护,同时可通过 controller 单测定位。 -- 保留现有行为,不改变 runtime event protocol、Tauri command、Bridge、execution runtime 结构或用户可见 UI。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamRuntimeContextController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamRuntimeContextController.test.ts" "src/components/agent/chat/hooks/agentStreamArtifactActionController.test.ts" "src/components/agent/chat/hooks/agentStreamToolEventController.test.ts" "src/components/agent/chat/hooks/agentStreamThreadItemController.test.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamRuntimeContextController.ts" "src/components/agent/chat/hooks/agentStreamRuntimeContextController.test.ts" "src/components/agent/chat/hooks/agentStreamArtifactActionController.ts" "src/components/agent/chat/hooks/agentStreamArtifactActionController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" --max-warnings 0 -npm run typecheck -- --pretty false -``` - -结果: - -- Runtime context controller / runtime handler:通过,`14` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`24` 个测试文件、`94` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -GUI / E2E 状态: - -- 本刀未进入 Playwright;此前已经确认 MCP profile lock 阻塞仍在。 -- 本刀仍是纯前端 stream controller 抽取,不改 GUI 壳、Tauri command、Bridge、mock 或用户可见 UI;继续不启动 `verify:gui-smoke`,避免 Rust rebuild 干扰用户观察 CPU / 鼠标繁忙。 - -下一刀: - -1. Playwright MCP 可复用后,优先恢复真实 E2E 指标采集。 -2. 如果继续代码拆分,只看 thinking delta 或 final side-effect action 的薄 action plan,避免偏离主线。 - -### 2026-05-05:P3 第三十七刀,Agent stream thinking delta controller - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamThinkingDeltaController.ts`: - - `buildAgentStreamThinkingDeltaPreApplyPlan` - - `buildAgentStreamThinkingDeltaMessagePatch` -- `agentStreamRuntimeHandler.ts` 的 `thinking_delta` 分支改为委托 thinking delta controller: - - 前置 activate stream 与 `surfaceThinkingDeltas` guard 进入 plan。 - - thinkingContent 的 overlap append 与 contentParts thinking append 进入消息 patch。 - - handler 仍保留 `setMessages` 副作用与 assistant message id 过滤顺序。 -- 新增 `agentStreamThinkingDeltaController.test.ts`,覆盖 surface guard、overlap append、contentParts 追加和无 contentParts 时的默认追加。 - -主线收益: - -- Phase 3 继续压缩 `agentStreamRuntimeHandler` 的 thinking 分支:思考流的显示开关与消息 patch 进入纯 controller。 -- 重复吐字防线从 text delta 扩展到 thinking delta,thinkingContent 的 overlap append 现在有独立单测保护。 -- 保留现有行为,不改变 runtime event protocol、Tauri command、Bridge、thinking 展示开关或用户可见 UI。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeContextController.test.ts" "src/components/agent/chat/hooks/agentStreamArtifactActionController.test.ts" "src/components/agent/chat/hooks/agentStreamToolEventController.test.ts" "src/components/agent/chat/hooks/agentStreamThreadItemController.test.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeContextController.ts" "src/components/agent/chat/hooks/agentStreamRuntimeContextController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" --max-warnings 0 -npm run typecheck -- --pretty false -``` - -结果: - -- Thinking delta controller / runtime handler:通过,`14` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`25` 个测试文件、`97` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -GUI / E2E 状态: - -- 本刀未进入 Playwright;此前已经确认 MCP profile lock 阻塞仍在。 -- 本刀仍是纯前端 stream controller 抽取,不改 GUI 壳、Tauri command、Bridge、mock 或用户可见 UI;继续不启动 `verify:gui-smoke`,避免 Rust rebuild 干扰用户观察 CPU / 鼠标繁忙。 - -下一刀: - -1. Playwright MCP 可复用后,优先恢复真实 E2E 指标采集。 -2. 如果继续代码拆分,只看 final side-effect action 的薄 action plan,避免偏离主线。 - -### 2026-05-05:P3 第三十八刀,Agent stream completion assistant patch 收口 - -已完成: - -- 扩展 `src/components/agent/chat/hooks/agentStreamCompletionController.ts`: - - 新增 `buildAgentStreamCompletedAssistantMessagePatch`,统一完成态 assistant 消息的 `content / contentParts / usage / runtimeStatus / isThinking` patch。 - - 复用 `reconcileAgentStreamFinalContentParts`,保持协议残留清理、thinking part 过滤与最终 text part 重建语义不变。 -- `agentStreamRuntimeHandler.ts` 的 `final_done` 与 empty-final graceful completion 分支改为委托 completion controller 生成 assistant message patch: - - handler 仍只保留队列清理、request log、observer complete、listener dispose 等副作用编排。 - - 完成态消息 patch 不再在 handler 内联拼装,降低流式完成分支与重复吐字 / 排版回归的耦合。 -- `agentStreamCompletionController.test.ts` 新增完成态 assistant patch 回归,覆盖 usage 带回和最终文本重建。 -- 验证门禁顺手收口 `src/lib/activeContentTarget.ts` 的输入类型: - - `setActiveContentTarget` 允许接收任意 canvas type 字符串,再通过既有 `normalizeThemeCanvasType` 收敛到 `document / video / null`。 - - 这只解除 `DesignCanvasState.type === "design"` 对 workspace typecheck 的阻塞,不扩大 active content target 的 current 事实源范围。 - -主线收益: - -- Phase 3 继续压缩 `agentStreamRuntimeHandler` 的完成分支:完成态 assistant 消息归一进入纯 controller,后续排查 final_done 只需区分“消息 patch”与“副作用编排”。 -- 重复吐字 / 输出排版的最终态防线继续集中在 completion controller 单测中,避免 final_done 二次 append 或 thinking part 意外混入正文。 -- 保留现有行为,不改变 runtime event protocol、Tauri command、Bridge、mock、active target 持久化格式或用户可见 UI。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeContextController.test.ts" "src/components/agent/chat/hooks/agentStreamArtifactActionController.test.ts" "src/components/agent/chat/hooks/agentStreamToolEventController.test.ts" "src/components/agent/chat/hooks/agentStreamThreadItemController.test.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/lib/activeContentTarget.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" --max-warnings 0 -npm run typecheck -- --pretty false -``` - -结果: - -- Agent stream Phase 3 定向回归:通过,`25` 个测试文件、`98` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -GUI / E2E 状态: - -- 本刀未进入 Playwright;此前已经确认 MCP profile lock 阻塞仍在,且不能使用 `--isolated` 或 kill 用户 Chrome/MCP。 -- 本刀仍是纯前端 stream controller 与类型门禁收口,不改 GUI 壳、Tauri command、Bridge、mock 或用户可见 UI;继续不启动 `verify:gui-smoke`,避免 Rust rebuild 干扰用户观察 CPU / 鼠标繁忙。 - -下一刀: - -1. Playwright MCP 可复用后,优先恢复首页首发、旧会话打开、首 token 的真实性能采集。 -2. 如果继续代码拆分,只看 `final_done` 日志 / 队列清理 / listener dispose 的 side-effect plan;若 E2E 指标显示慢在 render,则转回 Phase 4 render projection。 - -### 2026-05-05:P3 第三十九刀,Agent stream final side-effect plan 收口 - -已完成: - -- 继续扩展 `src/components/agent/chat/hooks/agentStreamCompletionController.ts`: - - 新增 `buildAgentStreamFinalDonePlan`,统一 `final_done` 的空最终回复失败判断、最终内容解析、queued turn 清理 ID 与 request log payload。 - - 新增 `buildAgentStreamEmptyFinalErrorPlan`,统一 empty-final error 在“无真实产物信号 -> 失败”和“已有真实产物信号 -> 软完成”之间的决策。 -- `agentStreamRuntimeHandler.ts` 的完成分支继续变薄: - - `final_done` 不再内联判断 `shouldFailAgentStreamMissingFinalReply`,只消费 completion plan 后执行副作用。 - - empty-final error 不再内联 queued turn / request log / graceful content 组装,软完成与失败分叉由 controller 决定。 -- `agentStreamCompletionController.test.ts` 新增 side-effect plan 回归,覆盖: - - `final_done` 协议残留清理后的完成计划。 - - 缺少最终回复的失败计划和 usage 保留。 - - empty-final error 在无产物信号与有产物信号两种情况下的分叉。 - -主线收益: - -- Phase 3 的 `final_done` 链路进一步拆成“纯决策 plan + handler 副作用执行”,首字 / 流式完成慢点排查时可以把 completion 语义与 React state / listener cleanup 分开看。 -- “空 final_done / 工具有产物但无最终文本 / 协议残留清理”继续收敛到同一个 current controller,避免重复吐字、排版错乱或空回复误报在 handler 中回流。 -- 保留现有行为,不改变 runtime event protocol、Tauri command、Bridge、mock、GUI 壳或用户可见 UI。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeContextController.test.ts" "src/components/agent/chat/hooks/agentStreamArtifactActionController.test.ts" "src/components/agent/chat/hooks/agentStreamToolEventController.test.ts" "src/components/agent/chat/hooks/agentStreamThreadItemController.test.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/lib/activeContentTarget.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" --max-warnings 0 -npm run typecheck -- --pretty false -``` - -结果: - -- Completion controller / runtime handler:通过,`2` 个测试文件、`20` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`25` 个测试文件、`101` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 - -GUI / E2E 状态: - -- 本刀未进入 Playwright;此前已经确认 MCP profile lock 阻塞仍在,且不能使用 `--isolated` 或 kill 用户 Chrome/MCP。 -- 本刀仍是纯前端 stream controller 收口,不改 GUI 壳、Tauri command、Bridge、mock 或用户可见 UI;继续不启动 `verify:gui-smoke`,避免 Rust rebuild 干扰用户观察 CPU / 鼠标繁忙。 - -下一刀: - -1. Playwright MCP 可复用后,优先恢复首页首发、旧会话打开、首 token 的真实性能采集。 -2. 如果继续代码拆分,只看 `error` 分支失败完成 side-effect plan;若 E2E 指标显示慢在 render,则转回 Phase 4 render projection。 - -### 2026-05-05:P3 第四十刀,Agent stream error failure side-effect plan 收口 - -已完成: - -- 继续扩展 `src/components/agent/chat/hooks/agentStreamErrorController.ts`: - - 新增 `buildAgentStreamErrorFailurePlan`,统一普通 runtime error 的错误文案、queued turn 清理 ID、request log payload 与 toast plan。 - - 复用既有 `buildAgentStreamErrorToastPlan`,保持 rate limit -> warning toast、普通错误 -> runtime error toast 的展示语义不变。 -- `agentStreamRuntimeHandler.ts` 的普通 `error` 分支继续变薄: - - handler 不再内联 `queuedTurnId ? [queuedTurnId] : []`、`chat_request_error` payload 或 toast plan 组装。 - - handler 只消费 error failure plan 后执行 timeline 标失败、队列清理、request log、observer、toast、assistant message patch 与 listener dispose。 -- `agentStreamErrorController.test.ts` 新增失败 side-effect plan 回归,覆盖普通错误和 rate limit toast 降级。 - -主线收益: - -- Phase 3 的普通错误链路继续收敛到 current controller:error 分支的“失败语义决策”和 handler 的“副作用执行”分离,后续排查首 token / 流式中断时更容易定位慢点或错态来源。 -- `agentStreamRuntimeHandler` 中普通 error 分支不再重复拼 queued turn、request log 与 toast,减少后续修空 final / rate limit / provider error 时互相踩语义的风险。 -- 保留现有行为,不改变 runtime event protocol、Tauri command、Bridge、mock、GUI 壳或用户可见 UI。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeContextController.test.ts" "src/components/agent/chat/hooks/agentStreamArtifactActionController.test.ts" "src/components/agent/chat/hooks/agentStreamToolEventController.test.ts" "src/components/agent/chat/hooks/agentStreamThreadItemController.test.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/lib/activeContentTarget.ts" "src/components/agent/chat/hooks/agentStreamErrorController.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/lib/activeContentTarget.ts" "src/components/agent/chat/hooks/agentStreamErrorController.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Error controller / runtime handler:通过,`2` 个测试文件、`17` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`25` 个测试文件、`103` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- Diff whitespace check:通过。 - -GUI / E2E 状态: - -- 本刀未进入 Playwright;此前已经确认 MCP profile lock 阻塞仍在,且不能使用 `--isolated` 或 kill 用户 Chrome/MCP。 -- 本刀仍是纯前端 stream controller 收口,不改 GUI 壳、Tauri command、Bridge、mock 或用户可见 UI;继续不启动 `verify:gui-smoke`,避免 Rust rebuild 干扰用户观察 CPU / 鼠标繁忙。 - -下一刀: - -1. Playwright MCP 可复用后,优先恢复首页首发、旧会话打开、首 token 的真实性能采集。 -2. 如果继续代码拆分,只看 `warning` toast 执行 plan 或 `markFailedTimelineState` 的 timeline failure plan;若 E2E 指标显示慢在 render,则转回 Phase 4 render projection。 - -### 2026-05-05:P3 第四十一刀,Agent stream failed timeline plan 收口 - -已完成: - -- 继续扩展 `src/components/agent/chat/hooks/agentStreamErrorController.ts`: - - 新增 `selectAgentStreamFailedTimelineTurn`,统一 pending turn 优先、当前会话最后一个 running turn 回退的选择策略。 - - 新增 `buildAgentStreamFailedTimelineTurnUpdate`,统一 running turn 失败态 patch。 - - 新增 `buildAgentStreamFailedTimelineItemUpdate`,统一 pending `turn_summary` 失败态 patch 和失败 runtime summary 文案。 -- `agentStreamRuntimeHandler.ts` 的 `markFailedTimelineState` 继续变薄: - - handler 不再内联查找 running turn。 - - handler 不再内联构造 failed runtime status summary。 - - handler 只负责把 controller 产出的 turn / item update 写回 `upsertThreadTurnState` / `upsertThreadItemState`。 -- `agentStreamErrorController.test.ts` 新增 failed timeline plan 回归,覆盖: - - pending turn 优先。 - - pending turn 缺失时回退当前 session 最后一个 running turn。 - - `turn_summary` 失败 patch 保留已有 `completed_at`。 - - pending item 缺失或不是 `turn_summary` 时跳过更新。 - -主线收益: - -- Phase 3 的错误 timeline 更新继续收敛到 current error controller,stream handler 不再同时承担失败语义、timeline 查找与状态 patch 组装。 -- 后续排查“流式错误后 timeline 卡在 running / summary 文案不一致 / 错 turn 被标失败”时,可以直接测 controller,不必挂载完整 workspace。 -- 保留现有行为,不改变 runtime event protocol、Tauri command、Bridge、mock、GUI 壳或用户可见 UI。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeContextController.test.ts" "src/components/agent/chat/hooks/agentStreamArtifactActionController.test.ts" "src/components/agent/chat/hooks/agentStreamToolEventController.test.ts" "src/components/agent/chat/hooks/agentStreamThreadItemController.test.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/lib/activeContentTarget.ts" "src/components/agent/chat/hooks/agentStreamErrorController.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/lib/activeContentTarget.ts" "src/components/agent/chat/hooks/agentStreamErrorController.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Error controller / runtime handler:通过,`2` 个测试文件、`21` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`25` 个测试文件、`107` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- Diff whitespace check:通过。 - -GUI / E2E 状态: - -- 本刀未进入 Playwright;此前已经确认 MCP profile lock 阻塞仍在,且不能使用 `--isolated` 或 kill 用户 Chrome/MCP。 -- 本刀仍是纯前端 stream controller 收口,不改 GUI 壳、Tauri command、Bridge、mock 或用户可见 UI;继续不启动 `verify:gui-smoke`,避免 Rust rebuild 干扰用户观察 CPU / 鼠标繁忙。 - -下一刀: - -1. Playwright MCP 可复用后,优先恢复首页首发、旧会话打开、首 token 的真实性能采集。 -2. 如果继续代码拆分,只看 `warning` toast 执行 plan;若 E2E 指标显示慢在 render,则转回 Phase 4 render projection。 - -### 2026-05-05:P3 第四十二刀,Agent stream warning toast action 收口 - -已完成: - -- 继续扩展 `src/components/agent/chat/hooks/agentStreamWarningController.ts`: - - 新增 `buildAgentStreamWarningToastAction`,把 warning plan 的 toast payload 归一为可执行 action。 - - 新增 `applyAgentStreamWarningToastAction`,统一 `info / warning / error` dispatcher 调用。 -- `agentStreamRuntimeHandler.ts` 的 `warning` 分支继续变薄: - - handler 不再内联 `switch (warningPlan.toast.level)`。 - - handler 只负责 warned key 标记,然后把 toast action 交给 warning controller 执行。 -- `agentStreamWarningController.test.ts` 新增 warning toast action 回归,覆盖 action 构造、null toast 跳过、不同 level 调用对应 dispatcher。 - -主线收益: - -- Phase 3 的 warning 展示行为继续收敛到 current warning controller,handler 不再承担 toast level 分发细节。 -- 后续排查 warning 重复提示、误提示或提示等级不一致时,可以直接测 warning controller,不必进入完整 stream runtime handler。 -- 保留现有行为,不改变 runtime event protocol、Tauri command、Bridge、mock、GUI 壳或用户可见 UI。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeContextController.test.ts" "src/components/agent/chat/hooks/agentStreamArtifactActionController.test.ts" "src/components/agent/chat/hooks/agentStreamToolEventController.test.ts" "src/components/agent/chat/hooks/agentStreamThreadItemController.test.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/lib/activeContentTarget.ts" "src/components/agent/chat/hooks/agentStreamWarningController.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "src/components/agent/chat/workspace/knowledge/useWorkspaceKnowledgeRuntime.ts" "src/features/knowledge/KnowledgePage.tsx" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/lib/activeContentTarget.ts" "src/components/agent/chat/hooks/agentStreamWarningController.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "src/components/agent/chat/workspace/knowledge/useWorkspaceKnowledgeRuntime.ts" "src/features/knowledge/KnowledgePage.tsx" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Warning controller / runtime handler:通过,`2` 个测试文件、`17` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`25` 个测试文件、`109` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- Diff whitespace check:通过。 - -附带门禁修复: - -- `src/components/agent/chat/workspace/knowledge/useWorkspaceKnowledgeRuntime.ts`:为 `knowledgePackOptions` 显式标注 `InputbarKnowledgePackOption[]`,避免 initial selection fallback 的可选 `status` 被数组推断收窄成必填 string。 -- `src/features/knowledge/KnowledgePage.tsx`:移除过期 `getPackTypeLabel` import,保持当前 `getUserFacingPackTypeLabel` 展示路径。 - -GUI / E2E 状态: - -- 本刀未进入 Playwright;此前已经确认 MCP profile lock 阻塞仍在,且不能使用 `--isolated` 或 kill 用户 Chrome/MCP。 -- 本刀仍是纯前端 stream controller 收口,不改 GUI 壳、Tauri command、Bridge、mock 或用户可见 UI;继续不启动 `verify:gui-smoke`,避免 Rust rebuild 干扰用户观察 CPU / 鼠标繁忙。 - -下一刀: - -1. Playwright MCP 可复用后,优先恢复首页首发、旧会话打开、首 token 的真实性能采集。 -2. 如果继续代码拆分,先盘点 `agentStreamRuntimeHandler` 剩余内部 helper,优先只拆仍影响首字 / 流式错态排查的 current controller plan。 - -### 2026-05-05:P3 第四十三刀,Agent stream error toast action 收口 - -已完成: - -- 继续扩展 `src/components/agent/chat/hooks/agentStreamErrorController.ts`: - - 新增 `applyAgentStreamErrorToastPlan`,统一普通 runtime error 的 `warning / error` toast dispatcher 调用。 -- `agentStreamRuntimeHandler.ts` 的普通 `error` 分支继续变薄: - - handler 不再内联 `if (toastPlan.level === "warning")` 判断。 - - handler 只消费 `errorFailurePlan.toast` 并交给 error controller 执行。 -- `agentStreamErrorController.test.ts` 新增 error toast dispatcher 回归,覆盖 rate limit warning 与普通 error 两条分发路径。 - -主线收益: - -- Phase 3 的普通 runtime error 展示行为继续收敛到 current error controller,handler 不再承担 toast level 分发细节。 -- 后续排查 provider error、rate limit、空 final error 的展示差异时,可以直接测 error / completion controller,而不是进入完整 stream handler。 -- 保留现有行为,不改变 runtime event protocol、Tauri command、Bridge、mock、GUI 壳或用户可见 UI。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeContextController.test.ts" "src/components/agent/chat/hooks/agentStreamArtifactActionController.test.ts" "src/components/agent/chat/hooks/agentStreamToolEventController.test.ts" "src/components/agent/chat/hooks/agentStreamThreadItemController.test.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/lib/activeContentTarget.ts" "src/components/agent/chat/hooks/agentStreamWarningController.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "src/components/agent/chat/workspace/knowledge/useWorkspaceKnowledgeRuntime.ts" "src/features/knowledge/KnowledgePage.tsx" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/lib/activeContentTarget.ts" "src/components/agent/chat/hooks/agentStreamWarningController.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "src/components/agent/chat/workspace/knowledge/useWorkspaceKnowledgeRuntime.ts" "src/features/knowledge/KnowledgePage.tsx" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Error controller / runtime handler:通过,`2` 个测试文件、`22` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`25` 个测试文件、`110` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- Diff whitespace check:通过。 - -GUI / E2E 状态: - -- 本刀未进入 Playwright;此前已经确认 MCP profile lock 阻塞仍在,且不能使用 `--isolated` 或 kill 用户 Chrome/MCP。 -- 本刀仍是纯前端 stream controller 收口,不改 GUI 壳、Tauri command、Bridge、mock 或用户可见 UI;继续不启动 `verify:gui-smoke`,避免 Rust rebuild 干扰用户观察 CPU / 鼠标繁忙。 - -下一刀: - -1. Playwright MCP 可复用后,优先恢复首页首发、旧会话打开、首 token 的真实性能采集。 -2. 如果继续代码拆分,先盘点 `agentStreamRuntimeHandler` 剩余内部 helper,优先只拆仍影响首字 / 流式错态排查的 current controller plan。 - -### 2026-05-05:P3 第四十四刀,Agent stream missing final failure plan 收口 - -已完成: - -- 继续扩展 `src/components/agent/chat/hooks/agentStreamCompletionController.ts`: - - 导出 `AgentStreamMissingFinalReplyPlan`。 - - 新增 `buildAgentStreamMissingFinalReplyFailurePlan`,统一 missing final reply failure 的 `errorMessage / queuedTurnIds / requestLogPayload / toastMessage / usage`。 - - `buildAgentStreamFinalDonePlan` 与 `buildAgentStreamEmptyFinalErrorPlan` 的失败分支改为复用 missing final failure plan。 -- `agentStreamRuntimeHandler.ts` 的 `finalizeMissingFinalReplyFailure` 继续变薄: - - 不再内联 `queuedTurnId ? [queuedTurnId] : []`。 - - 不再内联 `chat_request_error` payload。 - - 不再直接引用空最终回复 toast 常量,只消费 completion controller 产出的 toast message。 -- `agentStreamCompletionController.test.ts` 新增 missing final failure plan 回归,覆盖 queued turn 清理、request log payload、toast message 与 usage 保留。 - -主线收益: - -- Phase 3 的空最终回复失败路径继续收敛到 current completion controller;`final_done` 与 empty-final error 的失败副作用参数现在走同一个计划。 -- 后续排查“模型无最终文本 / 工具有产物但无 summary / 空 final 误报失败”时,可以直接测 completion controller,不必进入完整 stream handler。 -- 保留现有行为,不改变 runtime event protocol、Tauri command、Bridge、mock、GUI 壳或用户可见 UI。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeContextController.test.ts" "src/components/agent/chat/hooks/agentStreamArtifactActionController.test.ts" "src/components/agent/chat/hooks/agentStreamToolEventController.test.ts" "src/components/agent/chat/hooks/agentStreamThreadItemController.test.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/lib/activeContentTarget.ts" "src/components/agent/chat/hooks/agentStreamWarningController.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "src/components/agent/chat/workspace/knowledge/useWorkspaceKnowledgeRuntime.ts" "src/features/knowledge/KnowledgePage.tsx" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/lib/activeContentTarget.ts" "src/components/agent/chat/hooks/agentStreamWarningController.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "src/components/agent/chat/workspace/knowledge/useWorkspaceKnowledgeRuntime.ts" "src/features/knowledge/KnowledgePage.tsx" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Completion controller / runtime handler:通过,`2` 个测试文件、`21` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`25` 个测试文件、`111` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- Diff whitespace check:通过。 - -GUI / E2E 状态: - -- 本刀未进入 Playwright;此前已经确认 MCP profile lock 阻塞仍在,且不能使用 `--isolated` 或 kill 用户 Chrome/MCP。 -- 本刀仍是纯前端 stream controller 收口,不改 GUI 壳、Tauri command、Bridge、mock 或用户可见 UI;继续不启动 `verify:gui-smoke`,避免 Rust rebuild 干扰用户观察 CPU / 鼠标繁忙。 - -下一刀: - -1. Playwright MCP 可复用后,优先恢复首页首发、旧会话打开、首 token 的真实性能采集。 -2. 如果继续代码拆分,优先盘点 `markQueuedDraftState` 是否还能以 queued draft controller plan 形式收口。 - -### 2026-05-05:P3 第四十五刀,Agent stream queued draft state plan 收口 - -已完成: - -- 继续扩展 `src/components/agent/chat/hooks/agentStreamQueueController.ts`: - - 新增 `buildAgentStreamQueuedDraftStatePlan`,统一 queued draft 进入排队态时的 message patch、active stream 清理、optimistic item / turn 清理与 sending 状态计划。 - - 继续复用 `buildAgentStreamQueuedDraftMessagePatch` 生成排队 runtime status。 -- `agentStreamRuntimeHandler.ts` 的 `markQueuedDraftState` 继续变薄: - - handler 不再内联 queued draft 的 `clearActiveStreamIfMatch / clearOptimisticItem / clearOptimisticTurn / setIsSending(false)` 决策。 - - handler 只消费 queue controller 产出的状态计划并执行副作用。 -- `agentStreamQueueController.test.ts` 新增 queued draft state plan 回归,覆盖 message patch 和四个状态副作用开关。 - -主线收益: - -- Phase 3 的排队态转换继续收敛到 current queue controller;首页首发或旧会话中遇到 busy queue 时,queued draft 状态语义可独立测试。 -- 后续排查“点击发送后卡在 loading / optimistic 消息残留 / queued draft 没有变为排队态”时,可以直接测 queue controller,不必进入完整 stream handler。 -- 保留现有行为,不改变 runtime event protocol、Tauri command、Bridge、mock、GUI 壳或用户可见 UI。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeContextController.test.ts" "src/components/agent/chat/hooks/agentStreamArtifactActionController.test.ts" "src/components/agent/chat/hooks/agentStreamToolEventController.test.ts" "src/components/agent/chat/hooks/agentStreamThreadItemController.test.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/lib/activeContentTarget.ts" "src/components/agent/chat/hooks/agentStreamQueueController.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "src/components/agent/chat/workspace/knowledge/useWorkspaceKnowledgeRuntime.ts" "src/features/knowledge/KnowledgePage.tsx" --max-warnings 0 -npm run typecheck -- --pretty false -git diff --check -- "src/lib/activeContentTarget.ts" "src/components/agent/chat/hooks/agentStreamQueueController.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "src/components/agent/chat/workspace/knowledge/useWorkspaceKnowledgeRuntime.ts" "src/features/knowledge/KnowledgePage.tsx" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Queue controller / runtime handler:通过,`2` 个测试文件、`16` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`25` 个测试文件、`112` 个测试通过。 -- ESLint touched files:通过。 -- TypeScript `tsc --noEmit --pretty false`:通过。 -- Diff whitespace check:通过。 - -GUI / E2E 状态: - -- 本刀未进入 Playwright;此前已经确认 MCP profile lock 阻塞仍在,且不能使用 `--isolated` 或 kill 用户 Chrome/MCP。 -- 本刀仍是纯前端 stream controller 收口,不改 GUI 壳、Tauri command、Bridge、mock 或用户可见 UI;继续不启动 `verify:gui-smoke`,避免 Rust rebuild 干扰用户观察 CPU / 鼠标繁忙。 - -下一刀: - -1. Playwright MCP 可复用后,优先恢复首页首发、旧会话打开、首 token 的真实性能采集。 -2. 如果继续代码拆分,优先盘点 `finishRequestLog` 或 timer cleanup helper 是否还有可测 controller plan。 - -### 2026-05-05:P3 第四十六刀,Agent stream request log finish plan 收口 - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamRequestLogController.ts`: - - 新增 `buildAgentStreamRequestLogFinishPlan`,统一 request log finish 的重复完成 guard、`duration` 计算与 `activityLogger.updateLog` payload 组装。 - - 明确 `shouldUpdate / nextRequestFinished / logId / updatePayload`,让 request log 完成语义可单测。 -- `agentStreamRuntimeHandler.ts` 的 `finishRequestLog` 继续变薄: - - handler 不再内联 `requestLogId`、`requestFinished` 与 `Date.now() - requestStartedAt` 决策。 - - handler 只消费 request log controller 产出的计划,并执行 `activityLogger.updateLog` 副作用。 -- 新增 `agentStreamRequestLogController.test.ts`,覆盖无 log id、已完成去重、success duration、error payload 四类分支。 - -主线收益: - -- Phase 3 的 request log 完成链路继续收敛到 current controller;首字/流式排查时能把“完成态记录是否重复更新”和 runtime event 处理分开测。 -- 后续排查 request log duration 异常、重复完成、错误完成状态不一致时,可以直接测 request log controller,不必进入完整 stream handler。 -- 保留现有行为,不改变 runtime event protocol、Tauri command、Bridge、mock、GUI 壳或用户可见 UI。 - -已验证: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamRequestLogController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamRequestLogController.test.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeContextController.test.ts" "src/components/agent/chat/hooks/agentStreamArtifactActionController.test.ts" "src/components/agent/chat/hooks/agentStreamToolEventController.test.ts" "src/components/agent/chat/hooks/agentStreamThreadItemController.test.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamRequestLogController.ts" "src/components/agent/chat/hooks/agentStreamRequestLogController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" --max-warnings 0 -npm exec -- tsc --noEmit --pretty false --skipLibCheck --target ES2020 --module ESNext --moduleResolution bundler --jsx react-jsx --lib DOM,ES2020 "src/components/agent/chat/hooks/agentStreamRequestLogController.ts" "src/components/agent/chat/hooks/agentStreamRequestLogController.test.ts" -git diff --check -- "src/components/agent/chat/hooks/agentStreamRequestLogController.ts" "src/components/agent/chat/hooks/agentStreamRequestLogController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" -``` - -结果: - -- Request log controller / runtime handler:通过,`2` 个测试文件、`15` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`26` 个测试文件、`116` 个测试通过。 -- ESLint touched files:通过。 -- Targeted TypeScript check:通过。 -- Diff whitespace check:通过。 - -未完成验证: - -- 全量 `npm run typecheck -- --pretty false` 本轮运行超过 `10` 分钟仍无输出;为避免继续占用本机 CPU,已终止本轮自行启动的 `tsc` 进程。上一刀全量 typecheck 有通过记录,本刀额外补了 touched file 的 targeted TypeScript check。 -- 本刀未进入 Playwright;仍按既有规则不使用 `--isolated`,也不 kill 用户 Chrome/MCP。当前改动是纯前端 stream controller 收口,不改 GUI 壳、Tauri command、Bridge、mock 或用户可见 UI。 - -下一刀: - -1. Playwright MCP 可复用后,优先恢复首页首发、旧会话打开、首 token 的真实性能采集。 -2. 如果继续代码拆分,只看 timer cleanup helper;不要再扩大到无关 GUI / Bridge 面。 - -### 2026-05-05:P3 第四十七刀,Agent stream timer schedule plan 收口 - -已完成: - -- 新增 `src/components/agent/chat/hooks/agentStreamTimerController.ts`: - - 新增 `buildAgentStreamTimerClearPlan`,统一 timer clear 的状态计划。 - - 新增 `buildAgentStreamTextRenderTimerSchedulePlan`,统一首个可见文本立即 flush、已有 pending timer 跳过、后续 32ms 低频 flush 的调度决策。 - - 新增 `buildAgentStreamQueuedDraftCleanupTimerSchedulePlan` 与 `buildAgentStreamQueuedDraftCleanupTimerFirePlan`,统一 queued draft cleanup 的旧 timer 清理、1800ms grace 调度与触发时 cleanup guard。 -- `agentStreamRuntimeHandler.ts` 的 timer helper 继续变薄: - - `clearQueuedDraftCleanupTimer` / `clearPendingTextRenderTimer` 不再内联是否清理的判断。 - - `scheduleTextRenderFlush` 不再内联首个可见文本 flush 与 pending timer guard。 - - `scheduleQueuedDraftCleanup` 不再内联 queued draft cleanup 的 schedule/fire guard。 -- 新增 `agentStreamTimerController.test.ts`,覆盖 timer clear、text render flush_now/skip/schedule、queued cleanup schedule/fire 分支。 - -主线收益: - -- Phase 3 的 text render timer 与 queued draft cleanup timer 决策继续收敛到 current controller;首字慢或 queued draft 卡住时可以直接区分“调度策略”与 handler 副作用执行。 -- 后续排查“首字为什么等 32ms / 为什么排队草稿 1800ms 后消失或残留”时,可以直接测 timer controller,不必进入完整 stream handler。 -- 保留现有行为,不改变 runtime event protocol、Tauri command、Bridge、mock、GUI 壳或用户可见 UI。 - -待验证: - -- 先跑 timer controller / runtime handler 定向回归。 -- 再跑 Phase 3 stream controller 定向回归、ESLint、targeted TypeScript check 与 diff whitespace check。 - -验证结果: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamTimerController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamTimerController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestLogController.test.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeContextController.test.ts" "src/components/agent/chat/hooks/agentStreamArtifactActionController.test.ts" "src/components/agent/chat/hooks/agentStreamToolEventController.test.ts" "src/components/agent/chat/hooks/agentStreamThreadItemController.test.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamTimerController.ts" "src/components/agent/chat/hooks/agentStreamTimerController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestLogController.ts" "src/components/agent/chat/hooks/agentStreamRequestLogController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" --max-warnings 0 -npm exec -- tsc --noEmit --pretty false --skipLibCheck --target ES2020 --module ESNext --moduleResolution bundler --jsx react-jsx --lib DOM,ES2020 "src/components/agent/chat/hooks/agentStreamTimerController.ts" "src/components/agent/chat/hooks/agentStreamTimerController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestLogController.ts" "src/components/agent/chat/hooks/agentStreamRequestLogController.test.ts" -git diff --check -- "src/components/agent/chat/hooks/agentStreamTimerController.ts" "src/components/agent/chat/hooks/agentStreamTimerController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestLogController.ts" "src/components/agent/chat/hooks/agentStreamRequestLogController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Timer controller / runtime handler:通过,`2` 个测试文件、`17` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`27` 个测试文件、`122` 个测试通过。 -- ESLint touched files:通过。 -- Targeted TypeScript check:通过。 -- Diff whitespace check:通过。 - -未完成验证: - -- 本刀仍未进入 Playwright;这是纯前端 stream controller 收口,不改变 GUI 可见行为,也不碰 Tauri command / Bridge / mock。 -- 全量 `npm run typecheck` 上一刀已记录超时风险;本刀继续使用 touched file targeted TypeScript check,避免再次长时间占用 CPU。 - -下一刀: - -1. 优先恢复 Playwright MCP 真实性能采集,覆盖首页首发、旧会话打开和首 token 分段。 -2. 若仍需要代码收口,只看 missing final / failed timeline helper 的执行层;不继续扩散到无关 Workspace 或 Bridge 面。 - -### 2026-05-05:P3 第四十八刀,Missing final / failed timeline 执行层计划收口 - -已完成: - -- 继续扩展 `src/components/agent/chat/hooks/agentStreamCompletionController.ts`: - - 新增 `buildAgentStreamMissingFinalReplyFailureSideEffectPlan`,统一 missing final failure 的 pending text timer 清理、failed timeline 标记、queued turn 清理、request log、observer error、toast、active stream 与 listener dispose 执行计划。 -- 继续扩展 `src/components/agent/chat/hooks/agentStreamErrorController.ts`: - - 新增 `buildAgentStreamFailedTimelineStatePlan`,统一 failed timeline 更新所需的 session、pending turn/item、error 与 failedAt 参数。 -- `agentStreamRuntimeHandler.ts` 的失败路径 helper 继续变薄: - - `finalizeMissingFinalReplyFailure` 不再直接读取 failure plan 的全部字段来拼执行语义,而是消费 completion controller 产出的 side-effect plan。 - - `markFailedTimelineState` 不再内联 failed timeline 参数组装,而是消费 error controller 产出的 state plan。 -- 补充 controller 单测: - - `agentStreamCompletionController.test.ts` 覆盖 missing final failure side-effect plan。 - - `agentStreamErrorController.test.ts` 覆盖 failed timeline state plan。 - -主线收益: - -- Phase 3 的失败完成路径继续收敛到 current controller;空 final、普通 error、timeline failed state 的执行参数不再散落在 runtime handler 内。 -- 后续排查“空 final 误报失败 / failed timeline 未落态 / request log 和 toast 不一致”时,可以直接测 completion/error controller,不必进入完整 stream handler。 -- 保留现有行为,不改变 runtime event protocol、Tauri command、Bridge、mock、GUI 壳或用户可见 UI。 - -待验证: - -- 先跑 completion/error controller 与 runtime handler 定向回归。 -- 再跑 Phase 3 stream controller 定向回归、ESLint、targeted TypeScript check 与 diff whitespace check。 - -验证结果: - -```bash -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" -npm exec -- vitest run "src/components/agent/chat/hooks/agentStreamTimerController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestLogController.test.ts" "src/components/agent/chat/hooks/agentStreamThinkingDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeContextController.test.ts" "src/components/agent/chat/hooks/agentStreamArtifactActionController.test.ts" "src/components/agent/chat/hooks/agentStreamToolEventController.test.ts" "src/components/agent/chat/hooks/agentStreamThreadItemController.test.ts" "src/components/agent/chat/hooks/agentStreamQueueController.test.ts" "src/components/agent/chat/hooks/agentStreamWarningController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamToolCompletionSignalController.test.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamTextRenderFlushController.test.ts" "src/components/agent/chat/hooks/agentStreamTextDeltaController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeStatusController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeMetricsController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" "src/components/agent/chat/hooks/agentStreamInactivityController.test.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamUnknownEventController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestStartController.test.ts" "src/components/agent/chat/hooks/agentStreamListenerReadinessController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitLifecycleController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmissionController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitOpController.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitContext.test.ts" -npx eslint "src/components/agent/chat/hooks/agentStreamCompletionController.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "src/components/agent/chat/hooks/agentStreamTimerController.ts" "src/components/agent/chat/hooks/agentStreamTimerController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestLogController.ts" "src/components/agent/chat/hooks/agentStreamRequestLogController.test.ts" --max-warnings 0 -npm exec -- tsc --project "/tmp/lime-agentstream-targeted-tsconfig.json" -git diff --check -- "src/components/agent/chat/hooks/agentStreamCompletionController.ts" "src/components/agent/chat/hooks/agentStreamCompletionController.test.ts" "src/components/agent/chat/hooks/agentStreamErrorController.ts" "src/components/agent/chat/hooks/agentStreamErrorController.test.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "src/components/agent/chat/hooks/agentStreamTimerController.ts" "src/components/agent/chat/hooks/agentStreamTimerController.test.ts" "src/components/agent/chat/hooks/agentStreamRequestLogController.ts" "src/components/agent/chat/hooks/agentStreamRequestLogController.test.ts" "docs/roadmap/agentui/conversation-projection-implementation-plan.md" "docs/exec-plans/agentui-implementation-progress.md" -``` - -结果: - -- Completion / error controller / runtime handler:通过,`3` 个测试文件、`34` 个测试通过。 -- Agent stream Phase 3 定向回归:通过,`27` 个测试文件、`124` 个测试通过。 -- ESLint touched files:通过。 -- Targeted TypeScript check:通过;使用 `/tmp/lime-agentstream-targeted-tsconfig.json` 继承仓库 `tsconfig.json` 并额外包含 `src/vite-env.d.ts`,避免 CLI 单文件检查丢失 `@/*` 与 `ImportMeta.env` 类型。 -- Diff whitespace check:通过。 - -未完成验证: - -- 本刀未进入 Playwright;这是纯前端 stream controller 收口,不改变 GUI 可见行为,也不碰 Tauri command / Bridge / mock。 -- 全量 `npm run typecheck` 本轮未重跑;上一刀已记录长时间无输出风险,本刀用贴边界 targeted TypeScript check 验证 touched controller。 - -下一刀: - -1. 优先恢复 Playwright MCP 真实性能采集,覆盖首页首发、旧会话打开和首 token 分段。 -2. 若继续代码收口,先盘点 `agentStreamRuntimeHandler.ts` 剩余 helper 是否真的阻塞 Phase 3;否则进入 E2E 或 Phase 4 render projection 验收。 diff --git a/docs/exec-plans/ai-layered-design-implementation-plan.md b/docs/exec-plans/ai-layered-design-implementation-plan.md deleted file mode 100644 index 4779b4d86..000000000 --- a/docs/exec-plans/ai-layered-design-implementation-plan.md +++ /dev/null @@ -1,531 +0,0 @@ -# AI 图层化设计实现执行计划 - -> 状态:P4I 原生工程目录远程资产持久化缓存已完成,P4J 扁平图拆层协议首刀已完成,P4K 扁平图 draft `canvas:design` artifact bridge 已完成,P4L 上传扁平图本地 draft adapter 已完成,P4M DesignCanvas 候选层切换首刀已完成,P4N 上传扁平图本地 heuristic seed 首刀已完成;上传图片现在已能直接归一为 extraction draft,并生成可切换的本地裁片候选层进入 current `DesignCanvas`;定向单测、ESLint、定向 TypeScript 与 GUI smoke 已通过 -> 创建时间:2026-05-05 -> 路线图来源:`docs/roadmap/ai-layered-design/README.md` -> 当前目标:围绕 `LayeredDesignDocument` current 事实源完成生成、编辑、任务回写、工程目录保存、恢复、PSD-like 专业层栈投影,以及扁平图拆层 draft/候选层切换与本地 heuristic seed 首刀;下一步进入拆层确认页接线、真实 analyzer adapter,或真 PSD writer、复杂 matting / mask refine。 - -## 主目标 - -把 Lime 的 AI 图片生成从“返回一张扁平 PNG”升级为“生成、保存、重新打开并继续编辑的设计工程”: - -```text -用户目标 / @海报 / @配图 - -> Layer Planner - -> Asset Generator - -> LayeredDesignDocument - -> Design Canvas Editor - -> Exporter / Artifact / Evidence -``` - -固定事实源: - -**AI 图层化设计的 current 事实源是 `LayeredDesignDocument`;Canvas Editor、导出、单层重生成和后续拆层都必须读写这份文档。现有 `DocumentCanvas` / `ImageTaskViewer` / `TeamWorkspaceCanvas` 只作为 UI 和交互基础参考,不反向定义设计协议。** - -## 已完成阶段范围 - -已完成: - -1. 新增执行计划并回挂 `docs/exec-plans/README.md`。 -2. 新增 `src/lib/layered-design/` 的 P1 最小协议。 -3. 用纯函数保证图层排序、默认值归一化、单层资产替换和 transform 更新不变量。 -4. 补定向单测,证明预览 PNG 只是导出投影,不是设计事实源。 -5. 新增 `DesignCanvas` 最小可见 UI,并把 `canvas:design` Artifact 打开链路接入 Workspace Canvas。 -6. 新增本地 Layer Planner seed:从 prompt 生成可编辑图层计划,不调用图片模型。 -7. 新增 `LayeredDesignDocument -> canvas:design Artifact` bridge,让 prompt seed 能进入当前 Artifact / Canvas 主链。 -8. 新增 provider-agnostic 资产生成 seam:从图片图层创建生成请求,并把 provider 输出写回目标图层。 -9. 新增 `LayeredDesignAssetGenerationRequest -> create_image_generation_task_artifact` adapter,复用现有图片任务主链。 -10. 在 `DesignCanvas` 增加“生成全部图片层 / 重生成当前层”入口,提交任务后回写 `LayeredDesignDocument.editHistory`。 -11. 从 `LayeredDesignDocument.editHistory` 恢复已提交图片任务,并通过现有 `get_media_task_artifact` 刷新成功结果回写目标图层。 -12. 借鉴 Codex `imagegen` 的模型能力约束与透明图层 chroma-key 后处理策略,扩展为主流图片模型族 registry 并沉到 `runtimeContract.layered_design`,不新增 Python CLI 旁路。 -13. 新增 `LayeredDesignDocument` 导出投影:`design.json`、`export-manifest.json`、`preview.svg`、`preview.png` 与内嵌 data URL assets 下载入口。 -14. 新增 DEV-only `/design-canvas-smoke` 页面与 `smoke:design-canvas`,真实页面已验证 `canvas:design -> DesignCanvas -> 图层选择/移动/显隐` 主路径。 -15. 完整 `npm run verify:gui-smoke` 已通过,证明默认 GUI 壳、DevBridge、workspace、browser runtime、runtime tool surface、knowledge GUI 与 design canvas smoke 在同一轮可跑通。 -16. 新增无依赖 ZIP 工程包导出:单个 `.layered-design.zip` 包含 `design.json`、`export-manifest.json`、`preview.svg`、`preview.png` 与 `assets/` 内嵌资产。 -17. 修复图片任务 artifact 对自定义 `runtime_contract.layered_design` 的透传,并让 media task worker 消费 `chroma_key_postprocess`:生成提示词追加 chroma-key 背景约束,结果图与最终 task result 写入 `postprocess` seam,前端写回资产时保留该状态。 -18. 在 media task worker 内实现 data URL PNG 的 `chroma-key -> alpha` 像素级后处理:支持 `data:image/png;base64` 输出透明 PNG,远程 URL 保留原图并标记 `skipped_unsupported_source`,不让后处理失败中断图片任务。 -19. 在 media task worker 内补齐 http/https 远程 URL PNG 下载后处理:provider 返回远程图片时可受控下载、抠绿、回写透明 PNG data URL,并保留 `input_source: remote_url` 元数据。 -20. 新增原生项目工程目录落盘:`DesignCanvas` 绑定项目根目录时通过 Tauri current 命令写入 `.lime/layered-designs/.layered-design/`,包含 `design.json / export-manifest.json / preview.svg / preview.png / assets/`;未绑定项目时仍回退浏览器 ZIP 下载。 -21. 新增原生项目工程目录读回:`DesignCanvas` 绑定项目根目录时可调用 `read_layered_design_project_export` 打开最近保存的 `.layered-design` 工程,读回 `design.json` 后归一为 `LayeredDesignDocument` 并继续编辑。 -22. 新增 PSD-like 专业导出投影:`psd-like-manifest.json` 记录 back-to-front 图层栈、editable text、raster image、vector shape 与 group reference,随 ZIP 和原生工程目录一起导出,但明确 `compatibility.truePsd=false`。 -23. 新增扁平图拆层协议首刀:`LayeredDesignDocument.extraction` 现在可记录 `source_image`、候选层、置信度、clean plate 状态,并通过纯函数把“已选候选层”同步为正式 `layers`,低置信度候选默认不进入正式图层。 -24. 新增扁平图 draft Artifact bridge:`createLayeredDesignArtifactFromExtraction` 现在可把拆层 draft 直接包装成 `canvas:design` Artifact,并沿 current Canvas 打开链路进入 `DesignCanvasState`。 -25. 新增上传扁平图本地 draft adapter:`createLayeredDesignFlatImageDraftDocument` / `createLayeredDesignArtifactFromFlatImage` 现在可把单张上传图片直接归一为 extraction draft,即使还没有真实 analyzer 结果,也能通过 current 主链进入 `DesignCanvas`。 -26. 新增 `DesignCanvas` 扁平图入口与候选层切换首刀:工具栏可直接上传扁平图创建 draft,属性栏可切换 `extraction.candidates`,只把选中的候选层 materialize 到正式图层栈。 -27. 新增上传扁平图本地 heuristic seed 首刀:上传本地图后会先生成主体 / 标题文字 / Logo / 边角碎片裁片候选,并继续通过 `LayeredDesignDocument.extraction` 与 current `DesignCanvas` 进入编辑;未接 OCR / matting / clean plate 真执行前,不新增第二套确认页或拆层协议。 - -仍未做: - -1. 不新增 provider adapter、旧 poster 命令或平行主链;P4F/P4G 只新增 current 工程目录保存/读取命令。 -2. 不直接调用 `gpt-image-2` / Gemini / Flux;当前只规范 request contract 与现有 media task artifact 写回。 -3. 不引入 Fabric 运行时。 -4. 不实现真 PSD writer、PSD 文件打开验证、mask、inpaint、OCR 或拆层模型执行;当前只完成扁平图拆层协议首刀、候选层 materialize 纯函数和本地 heuristic 裁片 seed。 -5. 不宣称原生工程目录落盘、PSD-like manifest 或 `LayeredDesignDocument.extraction` 已经等同于真 PSD、mask、inpaint、OCR 或完整扁平图拆层产品流;这些仍在后续 P4/P5。 -6. 不宣称已完成复杂 matting、mask refine、文字/Logo 自动拆层、拆层确认页接线或 provider 级 clean plate 生成;当前只是把后续执行结果所需的 current 事实源协议、本地 heuristic 候选层与 current Canvas 接线先落稳。 - -## 阶段计划 - -### P0:文档与边界 - -状态:已完成 proposal 文档,进入 implementation 跟踪。 - -产物: - -1. `docs/research/ai-layered-design/` -2. `docs/roadmap/ai-layered-design/` -3. `docs/roadmap/creaoai/` 与 AI 图层化设计边界说明 - -完成标准: - -1. 文档说明为什么不先训练模型。 -2. 文档固定 `LayeredDesignDocument` 是 current 事实源。 -3. 文档说明 Lovart 类“可调整图层”来自工程编排,不是单个生图模型。 - -### P1:LayeredDesignDocument 最小协议 - -状态:已完成 P1 第一刀。 - -产物: - -1. `src/lib/layered-design/types.ts` -2. `src/lib/layered-design/document.ts` -3. `src/lib/layered-design/index.ts` -4. `src/lib/layered-design/document.test.ts` - -完成标准: - -1. 创建文档时按 `zIndex` 稳定排序。 -2. 普通文案默认是 `TextLayer`,不是烘焙图片。 -3. 单层替换 asset 不改变 layer id、transform、zIndex、visible、locked。 -4. normalize 能填充 `visible`、`locked`、`opacity`、`rotation` 等缺省值。 -5. preview 只作为导出投影,不进入 `layers[]`。 - -### P2:Design Canvas Editor - -状态:已完成最小可见 UI 与 Artifact 接入口。 - -计划: - -1. 在现有 Workspace / CanvasWorkbench 壳层下新增 `DesignCanvas`。 -2. 第一版用 DOM/CSS absolute layers 支持选择、拖动、缩放、隐藏、锁定和 zIndex。 -3. 图层栏和属性栏只读写 `LayeredDesignDocument`。 -4. Fabric 只作为后续更复杂选择框、旋转和导出的候选实现,不作为首刀依赖。 -5. 旧 `canvas:poster / canvas:music / canvas:novel / canvas:script` 不再归一到现役画布;需要图层化图片设计时必须使用 `canvas:design`。 - -### P3:原生分层生成与单层重生成 - -状态:P3G 已完成本地 seed、Artifact bridge、provider-agnostic 资产生成 seam、现有 image task artifact API adapter、`DesignCanvas` 生成入口、任务结果刷新写回,以及 OpenAI / Gemini Imagen / Flux / Stable Diffusion / Ideogram / Recraft / Seedream / CogView / Midjourney 等主流模型族能力 request contract;P4A 收口时已补完整 GUI smoke。 - -计划: - -1. Layer Planner 输出 5-8 个可编辑层。 -2. Prompt seed 生成 `canvas:design` Artifact,直接进入 `DesignCanvas`。 -3. Asset Generator 通过 provider capability seam 调用图片模型。 -4. 每个 ImageLayer 绑定 asset、prompt、provider、modelId。 -5. 单层重生成只替换该层 asset,并写入 edit history。 - -### P4:扁平图拆层与专业导出 - -状态:P4A 设计工程导出首刀已完成,P4B 浏览器 ZIP 工程包已完成,P4C media task worker 后处理 seam 已完成,P4D data URL PNG 像素级 chroma-key 后处理已完成,P4E http/https 远程 URL PNG 后处理已完成,P4F 原生工程目录落盘已完成,P4G 工程目录再打开/恢复已完成,P4H PSD-like 专业导出投影首刀已完成,P4I 原生工程目录远程资产持久化缓存已完成,P4J 扁平图拆层协议首刀已完成,P4K 扁平图 draft `canvas:design` artifact bridge 已完成,P4L 上传扁平图本地 draft adapter 已完成,P4M DesignCanvas 候选层切换首刀已完成,P4N 上传扁平图本地 heuristic seed 首刀已完成;真 PSD writer、复杂 matting / mask refine 与拆层执行链路仍未开始。 - -计划: - -1. 上传扁平图后识别主体、文字、Logo、背景候选层。 -2. 通过 mask / matting / clean plate 建立可编辑文档。 -3. 先稳定导出 PNG + JSON + assets,再试点 PSD-like 投影。 -4. P4A 当前只做浏览器下载投影,不新增 Tauri 二进制写文件命令。 -5. P4B 先用前端无依赖 ZIP 打包形成可交换工程包,仍不新增 Tauri 写文件命令。 -6. P4C 先把 `chroma_key_postprocess` 从 `runtimeContract` 贯穿到 media task worker 和结果元数据;真实像素处理单独作为下一刀。 -7. P4D 先在 media task worker 内处理 `data:image/png;base64`,把 chroma-key 背景像素 alpha 置 0;远程 URL 与复杂抠图留给后续缓存 / matting 阶段。 -8. P4E 继续在 media task worker 内处理 provider 返回的 http/https PNG URL,下载只在任务执行期发生,并受大小上限约束;持久化缓存与工程目录落盘仍单独推进。 -9. P4F 把当前浏览器 ZIP 下载推进为 Tauri current 命令 `save_layered_design_project_export`:只写项目根目录下 `.lime/layered-designs/.layered-design/`,继续消费 `LayeredDesignDocument` 导出投影,不新增 provider adapter 或旧 poster 协议。 -10. P4G 在同一条 current 工程目录链路补 `read_layered_design_project_export`:只读 `.lime/layered-designs/.layered-design/design.json`,恢复 `LayeredDesignDocument` 到 `DesignCanvas`,不读取或定义新的设计事实源。 -11. P4H 先定义 `psd-like-manifest.json` 专业层栈投影并随 ZIP / 原生工程目录导出;它只做 `LayeredDesignDocument` 的可交换投影,不写真 `.psd`,不做 OCR / matting / mask。 -12. P4I 继续收口 current 工程目录保存/读取链路:保存时把 manifest 中的远程图片引用持久化到 `assets/`,读回时优先从缓存文件水合回 `design.json`,但不把 ZIP 浏览器导出扩展成第二套下载协议。 -13. P4J 先不接模型,只把扁平图拆层需要的 current 协议落到 `LayeredDesignDocument`:记录 `source_image`、候选层、置信度、clean plate 状态,并用纯函数保证“只有已选候选层才 materialize 为正式 layers”,为后续拆层确认页和本地/远程 analyzer adapter 铺路。 -14. P4K 在不新增命令和 UI 主入口的前提下,把扁平图拆层 draft 接回 current `canvas:design` Artifact 链:新增 `createLayeredDesignArtifactFromExtraction`,保证拆层 draft 可以像 prompt seed 一样进入 `DesignCanvasState`,继续复用现有 Canvas 主路径。 -15. P4L 继续收口“上传扁平图”的本地入口:新增 `createLayeredDesignFlatImageDraftDocument` 和 `createLayeredDesignArtifactFromFlatImage`,让单张图片在没有 analyzer / OCR / mask 时也能先生成 extraction draft,后续只需替换 candidates/cleanPlate seed,不需要重开第二条 Canvas 接线。 -16. P4M 先不做独立拆层确认页,直接在 current `DesignCanvas` 落一刀最小确认态:上传扁平图后可在属性栏切换候选层,保持 `extraction.candidates` 与正式 `layers` 的边界一致,为后续专门确认页先验证状态机。 -17. P4N 继续在同一条 current 上传链上补本地 heuristic seed:先用浏览器本地裁片生成主体 / 标题文字 / Logo / 边角碎片候选,继续写回 `LayeredDesignDocument.extraction.candidates`,不伪装成 OCR / matting / clean plate,不新增独立确认页或新的 Artifact 类型。 - -## 已完成的不变量 - -当前已证明: - -1. `LayeredDesignDocument` 类型是唯一 current 设计事实源。 -2. `GeneratedDesignAsset` 只是资产记录,只有被 layer 引用才进入图层栏语义。 -3. `DesignPreviewProjection` 只是当前导出预览的投影,编辑会把它标记为 stale。 -4. 所有编辑函数保持不可变更新,避免 Canvas 状态绕过文档。 -5. Prompt seed 里的普通文案保持 `TextLayer`,不被烘焙成图片。 -6. Prompt seed 里的图片资产只是 `plannedOnly` 占位,不隐式调用 provider。 -7. `canvas:design` 是图层化设计唯一 current Artifact 类型;旧 `canvas:poster` 不再参与归一。 -8. 资产生成 seam 只选择图片 / effect 图层,跳过 `TextLayer`,并允许单层重生成重新进入 provider seam。 -9. 图层生成任务复用现有 `create_image_generation_task_artifact`,通过 `slotId / targetOutputId / targetOutputRefId / anchorHint` 保留 document/layer/asset 关联,不新增旧 poster 协议。 -10. Canvas UI 提交任务后必须回写 `LayeredDesignDocument.editHistory`;如果任务输出已经包含图片结果,立即写回目标图片层 asset,文字层保持可编辑。 -11. `asset_generation_requested` 必须记录 `taskId / taskPath / taskStatus`,后续打开同一设计工程时可恢复等待写回的图片任务。 -12. 主流图片模型族必须通过统一 capability registry 判断尺寸策略、透明策略、编辑/mask/reference 能力;未知模型走 `generic + provider_passthrough`,不阻塞任务创建。 -13. `gpt-image-2 / gpt-images-2` 图层任务必须归一到 16 倍数尺寸与合法像素范围;透明图层只记录 `chroma_key_postprocess` 策略,不把 Python CLI 变成 Lime current 主链。 -14. 导出结果是 `LayeredDesignDocument` 的投影:`design.json` 会标记 `status: exported`,`preview.svg / preview.png` 只作为当前画布快照,不反向替代图层事实源。 -15. 内嵌 data URL assets 可随导出下载;远程 assets 在 manifest 中保留 `originalSrc` 引用,不伪装成本地已落盘文件。 -16. ZIP 工程包只是导出容器:`assets/` 只收纳内嵌 data URL 资产,远程资产继续只在 manifest 中保留引用,避免把不可控远程资源伪装成本地工程文件。 -17. 图片任务 artifact 必须保留调用方传入的 `runtime_contract.layered_design` 扩展字段,同时继续保留标准 `image_generation` executor / policy / routing 合同;不能用默认 runtime contract 覆盖设计图层扩展。 -18. `chroma_key_postprocess` 的 worker 合同必须先保持可追踪:生成请求提示词明确 chroma-key 背景,`result.postprocess` 和 `images[].postprocess` 持续写入同一套后处理元数据,前端写回 `GeneratedDesignAsset.params.postprocess` 不得丢失状态。 -19. `chroma_key_postprocess` 的首个真实像素处理器必须至少消费 `data:image/png;base64`:成功时替换 `images[].url` 为透明 PNG data URL,并写入 `status: succeeded / removed_pixel_count / total_pixel_count / transparent`。 -20. http/https 远程 URL 后处理必须受控:只允许下载任务结果 URL,限制最大图片体积,成功后仍回写透明 PNG data URL;失败只写 `postprocess.status: failed/skipped_unsupported_source`,不得让图片任务整体失败,也不得伪装为已透明化。 -21. 原生工程目录落盘必须只保存导出投影:Tauri 侧负责路径约束、目录创建、UTF-8 / base64 文件写入和目录穿越防护;`preview.png` 与 `assets/` 仍是投影文件,不能反向替代 `LayeredDesignDocument`。 -22. 工程目录读回必须只恢复 `design.json` 中的 `LayeredDesignDocument`:Tauri 侧负责约束目录必须位于 `.lime/layered-designs/`,前端负责 `normalizeLayeredDesignDocument` 后回写 `DesignCanvas`,manifest / preview / assets 只作为旁路投影元数据。 -23. PSD-like manifest 必须是导出投影而非新事实源:`source.factSource` 必须指向 `LayeredDesignDocument`,`compatibility.truePsd=false`,图层顺序固定为 `back_to_front`,不得引入 `poster_generate / canvas:poster / ImageTaskViewer`。 -24. 原生工程目录保存命令可以在不新增协议面的前提下,把 `export-manifest.json` 中 `http/https` 远程图片引用持久化缓存到 `assets/`;读回时优先从缓存文件水合 `design.json` 返回给前端,避免重新打开工程时仍依赖远程 URL 在线可达。 -25. 扁平图拆层候选必须作为 `LayeredDesignDocument.extraction.candidates` 单独记录;候选层在用户确认前不能静默混入正式 `layers`。 -26. 低置信度拆层候选默认不选中;即使候选附带 mask / RGBA 资产,也只能在 `selected=true` 后才 materialize 到 `DesignCanvas` 图层栈。 -27. clean plate 失败不能阻断进入可编辑工程;背景层必须可回退到 `source_image`,同时在 extraction 元数据里保留失败状态和说明。 -28. 扁平图拆层 draft 一旦进入 current Artifact 主链,仍必须继续使用 `canvas:design`;不为拆层草稿新增 `canvas:image`、`canvas:poster` 或平行 viewer 协议。 -29. 上传扁平图的本地 draft adapter 只能做归一化和最小默认值推导;它不能伪装成真实 analyzer、OCR、matting 或 clean plate 结果,也不能偷偷扩成新的事实源 schema。 -30. `DesignCanvas` 内的候选层切换只能修改 `extraction.candidates.selected` 并同步 materialize 结果;未选候选不能因为画布交互而静默出现在正式 `layers`。 -31. 上传扁平图的本地 heuristic seed 只能产出基于原图的裁片候选;它可以帮助 current 画布先验证候选层状态机,但不能伪装成真实 mask、透明抠图、OCR 文字层或 clean plate 成果。 - -## 验证策略 - -当前改动横跨 TypeScript 协议、Artifact adapter、Workspace Canvas UI、Tauri 命令、DevBridge、mock 与治理 catalog;每一刀按实际触达边界选择最小可证明交付的校验集合。 - -最低校验: - -```bash -npm exec -- vitest run "src/lib/layered-design/document.test.ts" "src/lib/layered-design/planner.test.ts" "src/lib/layered-design/artifact.test.ts" "src/lib/layered-design/generation.test.ts" "src/lib/layered-design/imageModelCapabilities.test.ts" "src/lib/layered-design/imageTasks.test.ts" "src/components/workspace/design/DesignCanvas.test.tsx" "src/components/artifact/canvasAdapterUtils.test.ts" "src/components/artifact/ArtifactRenderer.ui.test.tsx" -npm exec -- eslint "src/lib/layered-design/**/*.ts" "src/components/artifact/canvasAdapterUtils.ts" "src/components/artifact/canvasAdapterUtils.test.ts" --max-warnings 0 -npm exec -- tsc -p "/tmp/lime-layered-design-tsconfig.json" --noEmit -npm run smoke:design-canvas -- --timeout-ms 240000 --interval-ms 1000 -``` - -GUI 主路径当前已补齐的 smoke 门槛: - -```bash -npm run smoke:design-canvas -- --timeout-ms 240000 --interval-ms 1000 -npm run verify:gui-smoke -- --reuse-running --timeout-ms 600000 --interval-ms 1000 -``` - -后续若继续改 Workspace / Design Canvas / DevBridge 主路径,应继续把 `npm run verify:gui-smoke` 纳入收口门槛;若只是纯函数或局部 UI 小改,可先跑定向 Vitest、ESLint 和 TypeScript 后再按风险升级。 - -后续进入 Tauri 命令 / provider / mock 时再追加: - -```bash -npm run test:contracts -npm run governance:legacy-report -``` - -## 进度日志 - -### 2026-05-05 - -- 已创建本执行计划,承接 `docs/roadmap/ai-layered-design/`。 -- 当前阶段固定为 P1 第一刀:先落 `LayeredDesignDocument` 协议和纯函数测试。 -- 本轮不接 GUI、provider、Tauri 命令或 Fabric,避免在事实源未稳定前扩展平行实现。 -- 已新增 `src/lib/layered-design/types.ts`、`src/lib/layered-design/document.ts`、`src/lib/layered-design/index.ts` 与 `src/lib/layered-design/document.test.ts`。 -- 已实现 `LayeredDesignDocument`、`DesignCanvas`、`DesignLayer`、`GeneratedDesignAsset`、`LayerEditRecord`、创建 / normalize / 排序 / 单层资产替换 / transform 更新等 P1 最小协议。 -- 已通过 `npm exec -- vitest run "src/lib/layered-design/document.test.ts"`,5 个定向测试覆盖 zIndex 排序、TextLayer、单层替换不变量、默认值归一化和 preview 投影语义。 -- 已通过 `npm exec -- eslint "src/lib/layered-design/**/*.ts" --max-warnings 0` 与定向 `tsc`,确认本轮新增协议文件静态检查通过。 -- 已执行 `npm run typecheck`,当前失败来自未跟随本轮修改的未跟踪文件 `src/components/agent/chat/hooks/agentStreamRuntimeContextController.test.ts`:测试构造的 `output_schema_runtime` 缺少 `source` 与 `strategy` 字段;本轮未修改该区域,未纳入本阶段修复范围。 - -### 2026-05-05 P2 最小 Canvas UI - -- 已新增 `src/components/workspace/design/DesignCanvas.tsx` 与 `src/components/workspace/design/types.ts`,提供图层栏、画布预览、属性栏、选择、移动、显隐、锁定、zIndex 调整和 zoom 控制。 -- 已把 `CanvasStateUnion` 扩展为 `document / video / design`,并在 `CanvasFactory` 与 `workbenchCanvas` current 网关接入 `DesignCanvas`。 -- 已新增 `canvas:design` Artifact 类型和 `.json` 默认扩展名;Artifact adapter 可从 `LayeredDesignDocument` JSON 创建 design canvas state,并把 design canvas state 序列化回同一文档 JSON。 -- 已清理旧 Canvas 类型别名:`canvas:poster / canvas:music / canvas:novel / canvas:script` 不再归一到 `canvas:document / canvas:video`,避免旧专用主题继续伪装成新设计工程主线。 -- 已同步 `src/components/artifact/README.md`,明确旧 Canvas 别名不再是 compat 主链;图层化图片设计必须走 `canvas:design + LayeredDesignDocument`。 -- 已补 `src/components/workspace/design/DesignCanvas.test.tsx`、`src/components/artifact/canvasAdapterUtils.test.ts` 与 `canvasUtils` 回归,锁定 UI 操作必须回写文档而不是只改 DOM。 -- 已修正 `ArtifactRenderer` 的 Canvas 分发顺序:Canvas 类型先委托给 `CanvasAdapter`,不再要求先注册轻量 renderer;`canvas:design` 因此能从 Artifact 直接打开 `DesignCanvas`。 -- 已补 `src/components/artifact/ArtifactRenderer.ui.test.tsx` 回归,覆盖 `canvas:design` 从 Artifact 直接渲染到图层设计画布。 -- 已同步 `ArtifactToolbar` MIME:`canvas:design` 导出内容按 `application/json` 处理。 -- 已补 `src/components/agent/chat/workspace/generalWorkbenchHelpers.test.ts`,覆盖 design canvas 的空态判断和 `LayeredDesignDocument` JSON 同步。 -- 已通过 `npm exec -- vitest run "src/lib/layered-design/document.test.ts" "src/components/workspace/design/DesignCanvas.test.tsx" "src/components/artifact/canvasAdapterUtils.test.ts" "src/components/workspace/canvas/canvasUtils.test.ts"`。 -- 已通过 `npm exec -- vitest run "src/lib/artifact/parser.test.ts" "src/lib/artifact/registry.test.ts" "src/components/artifact/ArtifactRenderer.test.ts" "src/components/artifact/ArtifactToolbar.test.ts"`。 -- 已通过 `npm exec -- vitest run "src/components/artifact/ArtifactRenderer.ui.test.tsx" "src/components/artifact/canvasAdapterUtils.test.ts" "src/components/workspace/design/DesignCanvas.test.tsx"`。 -- 已通过 `npm exec -- vitest run "src/components/artifact/ArtifactToolbar.test.ts" "src/components/agent/chat/workspace/generalWorkbenchHelpers.test.ts" "src/components/artifact/ArtifactRenderer.ui.test.tsx"`。 -- 已通过 `npm exec -- eslint "src/lib/layered-design/**/*.ts" "src/components/workspace/design/**/*.{ts,tsx}" "src/components/workspace/canvas/canvasUtils.ts" "src/components/workspace/canvas/canvasUtils.test.ts" "src/components/workspace/canvas/CanvasFactory.tsx" "src/components/artifact/canvasAdapterUtils.ts" "src/components/artifact/canvasAdapterUtils.test.ts" "src/lib/artifact/types.ts" "src/lib/artifact/parser.ts" "src/components/artifact/ArtifactRenderer.test.ts" "src/components/artifact/ArtifactToolbar.test.ts" "src/components/agent/chat/workspace/generalWorkbenchHelpers.ts" --max-warnings 0`。 -- 已通过增量 ESLint:`npm exec -- eslint "src/components/artifact/ArtifactToolbar.tsx" "src/components/artifact/ArtifactToolbar.test.ts" "src/components/agent/chat/workspace/generalWorkbenchHelpers.ts" "src/components/agent/chat/workspace/generalWorkbenchHelpers.test.ts" "src/components/artifact/ArtifactRenderer.tsx" "src/components/artifact/ArtifactRenderer.ui.test.tsx" --max-warnings 0`。 -- 已通过定向 TypeScript 检查:`npm exec -- tsc -p "/tmp/lime-layered-design-tsconfig.json" --noEmit`,范围包含 `src/vite-env.d.ts`、layered-design、DesignCanvas、CanvasFactory、CanvasAdapter、ArtifactRenderer、artifact 类型/解析和 Workbench 同步 helper。 -- 已通过 `git diff --check` 相关文件检查。 -- 已尝试 `npm run typecheck`,120 秒内未完成并被中止;本轮定向测试和 ESLint 已覆盖新增边界,完整 typecheck 需要等当前工作区并发校验任务收口后补跑。 - -### 2026-05-05 P3A 本地 Layer Planner seed 与 Artifact bridge - -- 已新增 `src/lib/layered-design/planner.test.ts`,锁定 prompt seed 会生成背景、主体、氛围特效、主标题、副标题、CTA 底和 CTA 文案等 7 个可编辑层。 -- 已确认 prompt seed 中普通文案保持 `TextLayer`,图片资产仅为 `plannedOnly` 占位,`src` 为空且不写 `provider / modelId`,不会假装已经调用 `gpt-image-2`、Gemini 或其他模型。 -- 已新增 `src/lib/layered-design/artifact.ts`,提供 `createLayeredDesignArtifact` 与 `createLayeredDesignArtifactFromPrompt`,统一生成 `canvas:design` Artifact。 -- 已通过 `createLayeredDesignArtifactFromPrompt -> createCanvasStateFromArtifact -> DesignCanvasState` 回归,证明 prompt seed 能进入当前 Artifact / Canvas 主链。 -- 已从 `src/lib/layered-design/index.ts` 导出 planner 与 artifact bridge,后续主链入口不需要绕到旧 poster / image viewer。 -- 已通过 `npm exec -- vitest run "src/lib/layered-design/document.test.ts" "src/lib/layered-design/planner.test.ts" "src/lib/layered-design/artifact.test.ts" "src/components/artifact/canvasAdapterUtils.test.ts"`,共 13 个定向测试。 -- 已通过 `npm exec -- eslint "src/lib/layered-design/**/*.ts" "src/components/artifact/canvasAdapterUtils.ts" "src/components/artifact/canvasAdapterUtils.test.ts" --max-warnings 0`。 -- 已通过定向 TypeScript 检查:`npm exec -- tsc -p "/tmp/lime-layered-design-tsconfig.json" --noEmit`。 -- 当前仍未跑 `npm run verify:gui-smoke`,因此 GUI 主路径还不能宣称完整可交付。 - -### 2026-05-05 P3B provider-agnostic 资产生成 seam - -- 已新增 `src/lib/layered-design/generation.ts`,提供 `createLayeredDesignAssetGenerationPlan`、`createSingleLayerAssetGenerationRequest` 与 `applyLayeredDesignGeneratedAsset`。 -- 资产生成计划只选择 `ImageLayer / EffectLayer`,跳过 `TextLayer`,确保普通文案继续留在可编辑图层而不是被送进生图模型。 -- 默认生成计划只请求空 `src` 或 `plannedOnly` 资产;单层重生成请求允许已生成资产再次进入 provider seam。 -- 写入 provider 输出时只替换目标图片层的 asset,并把该层标记为 `source: "generated"`;其他图层和文字层保持不变。 -- 该 seam 不调用 `gpt-image-2`、Gemini 或本地模型,只定义 current 文档如何对接后续 provider adapter。 -- 已通过 `npm exec -- vitest run "src/lib/layered-design/document.test.ts" "src/lib/layered-design/planner.test.ts" "src/lib/layered-design/artifact.test.ts" "src/lib/layered-design/generation.test.ts" "src/components/artifact/canvasAdapterUtils.test.ts"`,共 17 个定向测试。 -- 已通过 `npm exec -- eslint "src/lib/layered-design/**/*.ts" "src/components/artifact/canvasAdapterUtils.ts" "src/components/artifact/canvasAdapterUtils.test.ts" --max-warnings 0`。 -- 已通过定向 TypeScript 检查:`npm exec -- tsc -p "/tmp/lime-layered-design-tsconfig.json" --noEmit`。 -- 下一刀应接真实 provider adapter 或 UI 单层重生成入口,不能回到旧 `poster_generate / ImageTaskViewer`。 - -### 2026-05-05 P3C image task adapter - -- 已新增 `src/lib/layered-design/imageTasks.ts`,把 `LayeredDesignAssetGenerationRequest` 映射到现有 `createImageGenerationTaskArtifact` 前端 API。 -- 映射后的图片任务使用 `entrySource: "layered_design_canvas"`、`modalityContractKey: "image_generation"`、`routingSlot: "image_generation_model"`,不新增 Tauri 命令、不新增 mock、不回到旧 poster 协议。 -- 图层关联通过现有字段持久化:`slotId=layerId`、`targetOutputId=assetId`、`targetOutputRefId=generationRequest.id`、`anchorHint=layered-design::`。 -- 已新增 `createGeneratedDesignAssetFromImageTaskOutput`,能从成功的 image task result 创建 `GeneratedDesignAsset`,并保留 `provider / model / taskId / taskPath / layerId / documentId`。 -- 已新增 `applyLayeredDesignImageTaskOutput`,可把成功任务输出写回目标图层;文字层仍保持 `TextLayer` 可编辑。 -- 已补 `src/lib/layered-design/imageTasks.test.ts`,覆盖请求映射、批量提交、任务输出转 asset、任务输出写回文档,并断言不出现 `poster_generate / canvas:poster`。 -- 已通过 `npm exec -- vitest run "src/lib/layered-design/document.test.ts" "src/lib/layered-design/planner.test.ts" "src/lib/layered-design/artifact.test.ts" "src/lib/layered-design/generation.test.ts" "src/lib/layered-design/imageTasks.test.ts" "src/components/artifact/canvasAdapterUtils.test.ts"`,共 21 个定向测试。 -- 已通过 `npm exec -- eslint "src/lib/layered-design/**/*.ts" "src/components/artifact/canvasAdapterUtils.ts" "src/components/artifact/canvasAdapterUtils.test.ts" --max-warnings 0`。 -- 已通过定向 TypeScript 检查:`npm exec -- tsc -p "/tmp/lime-layered-design-tsconfig.json" --noEmit`。 -- 当前仍未跑 `npm run test:contracts` 与 `npm run verify:gui-smoke`;本轮没有新增命令面,但下一轮接 UI 或真实轮询后必须补 GUI 主路径验证。 - -### 2026-05-05 P3D DesignCanvas 图层生成入口 - -- 已在 `src/components/workspace/design/DesignCanvas.tsx` 增加“生成全部图片层”和“重生成当前层”入口,页面类型属于宽工作台,按钮沿用深色主按钮 + 白底描边次按钮层级。 -- `DesignCanvas` 生成入口只调用 `createLayeredDesignImageTaskArtifacts` current adapter;没有接 `poster_generate`、`canvas:poster` 或 `ImageTaskViewer`。 -- 提交任务后通过 `recordLayeredDesignImageTaskSubmissions` 回写 `LayeredDesignDocument.editHistory`,保证 UI 操作不只停在 DOM 状态。 -- 如果任务输出已经包含图片结果,`DesignCanvas` 会立刻用 `applyLayeredDesignImageTaskOutput` 写回目标图片层 asset;文字层继续保持 `TextLayer`。 -- `CanvasFactory` 已向 design canvas 透传 `projectRootPath / projectId / contentId`,`useWorkspaceCanvasSceneRuntime` 使用当前 workspace root 作为图片任务根目录。 -- 已补 `src/components/workspace/design/DesignCanvas.test.tsx` 回归,覆盖全部生成、单层重生成、任务请求字段、edit history 回写、任务结果写回图层和旧 poster 文本不回流。 -- 已通过 `npm exec -- vitest run "src/lib/layered-design/document.test.ts" "src/lib/layered-design/planner.test.ts" "src/lib/layered-design/artifact.test.ts" "src/lib/layered-design/generation.test.ts" "src/lib/layered-design/imageTasks.test.ts" "src/components/workspace/design/DesignCanvas.test.tsx" "src/components/artifact/canvasAdapterUtils.test.ts" "src/components/artifact/ArtifactRenderer.ui.test.tsx"`,共 34 个定向测试。 -- 已通过 `npm exec -- eslint "src/lib/layered-design/**/*.ts" "src/components/workspace/design/**/*.{ts,tsx}" "src/components/workspace/canvas/CanvasFactory.tsx" "src/components/agent/chat/workspace/useWorkspaceCanvasSceneRuntime.tsx" --max-warnings 0`。 -- 已通过定向 TypeScript 检查:`npm exec -- tsc -p "/tmp/lime-layered-design-tsconfig.json" --noEmit`。 -- 当前仍未跑 `npm run verify:gui-smoke`;下一刀应补任务轮询 / 结果自动写回后跑 GUI 主路径验证。 - -### 2026-05-05 P3E 图层任务恢复与刷新写回 - -- 已扩展 `LayerEditRecord`,让 `asset_generation_requested` 记录 `taskId / taskPath / taskStatus`,避免任务提交后只能依赖当前 React 内存状态。 -- 已新增 `listPendingLayeredDesignImageTasks`,从 `LayeredDesignDocument.editHistory` 恢复仍等待写回的图片任务;如果同一图层已有后续 `asset_replaced`,旧任务会被视为已关闭。 -- 已新增 `refreshLayeredDesignImageTaskResults`,复用现有 `getMediaTaskArtifact` / `get_media_task_artifact` 刷新图片任务结果,成功时只替换目标图片层 asset。 -- 已在 `DesignCanvas` 增加“刷新生成结果”入口;页面仍属于宽工作台,主生成按钮与刷新按钮保持深色主按钮 + 白底描边次按钮层级,不引入新的视觉体系。 -- 已补 `src/lib/layered-design/imageTasks.test.ts` 与 `src/components/workspace/design/DesignCanvas.test.tsx` 回归,覆盖 pending 任务恢复、刷新调用、成功结果写回和文字层保持可编辑。 -- 已通过 `npm exec -- vitest run "src/lib/layered-design/imageTasks.test.ts" "src/components/workspace/design/DesignCanvas.test.tsx"`,共 13 个定向测试。 -- 当前仍未跑 `npm run verify:gui-smoke`,GUI 主路径还不能宣称完整可交付。 - -### 2026-05-05 P3F 借鉴 Codex imagegen 的模型能力约束 - -- 已只读分析 `/Users/coso/Documents/dev/rust/codex/codex-rs/skills/src/assets/samples/imagegen/`,确认适合借鉴的是模型能力约束、透明图层后处理策略和多资产生成纪律,不适合直接引入 Python CLI 旁路。 -- 已新增 `src/lib/layered-design/imageModelCapabilities.ts`,把 `gpt-image-2 / gpt-images-2` 的 16 倍数、最大边、像素范围、长短边比例和透明背景限制沉到纯函数。 -- `createLayeredDesignImageTaskRequest` 现在会在指定 `gpt-image-2 / gpt-images-2` 时归一任务尺寸,并把原始尺寸、任务尺寸、alpha 策略写入 `runtimeContract.layered_design`。 -- 透明图层当前只记录 `chroma_key_postprocess` 策略和默认 key color,不直接把 Codex `scripts/image_gen.py` 或 chroma-key prompt 接成产品主链;后续应在 media task worker 内做本地 post-process。 -- 已补 `src/lib/layered-design/imageModelCapabilities.test.ts` 与 `src/lib/layered-design/imageTasks.test.ts` 回归,证明 request contract 仍是 `image_generation`,没有新增旧 `poster_generate / canvas:poster` 协议。 -- 已通过 `npm exec -- vitest run "src/lib/layered-design/imageModelCapabilities.test.ts" "src/lib/layered-design/imageTasks.test.ts"`,共 11 个定向测试。 - -### 2026-05-05 P3G 主流图片模型族 capability registry - -- 已把上一刀的 `gpt-image-2` 单点判断扩展为主流模型族 registry:`openai-gpt-image-2`、`openai-gpt-image`、`openai-dalle`、`google-imagen`、`flux`、`stable-diffusion`、`ideogram`、`recraft`、`seedream`、`cogview`、`midjourney` 与 `generic`。 -- `LayeredDesignImageModelCapability` 现在记录 `sizePolicy`、`allowedSizes`、`supportsNativeTransparency`、`supportsImageEdit`、`supportsMask`、`supportsReferenceImages` 等能力;未知模型走 `generic + provider_passthrough`,不阻塞现有 provider routing。 -- 尺寸策略已收敛为四类:`flexible_pixels`、`allowed_sizes`、`multiple_pixels`、`provider_passthrough`;OpenAI legacy / DALL-E 会选最接近允许尺寸,Stable Diffusion 会按 64 倍数归一,Flux 会按最大像素做保守缩放。 -- `createLayeredDesignImageTaskRequest` 继续只复用现有 `create_image_generation_task_artifact`,但会把模型族、provider、size policy、透明策略和编辑/mask/reference 能力写入 `runtimeContract.layered_design`。 -- 已补 `src/lib/layered-design/imageModelCapabilities.test.ts`,覆盖 `gpt-image-1.5`、`flux-pro`、`stable-diffusion-xl`、`seedream-4.0` 等非 gpt-image-2 模型族,避免当前主线绑定单一模型。 -- 已通过 `npm exec -- vitest run "src/lib/layered-design/imageModelCapabilities.test.ts" "src/lib/layered-design/imageTasks.test.ts"`,共 12 个定向测试。 -- 已修正 `LayeredDesignImageRuntimeContract` 类型,让它可直接写入现有图片任务 `runtimeContract: Record`,不新增任务协议或桥接命令。 -- 已通过 P3G 汇总回归:`npm exec -- vitest run "src/lib/layered-design/document.test.ts" "src/lib/layered-design/planner.test.ts" "src/lib/layered-design/artifact.test.ts" "src/lib/layered-design/generation.test.ts" "src/lib/layered-design/imageModelCapabilities.test.ts" "src/lib/layered-design/imageTasks.test.ts" "src/components/workspace/design/DesignCanvas.test.tsx" "src/components/artifact/canvasAdapterUtils.test.ts" "src/components/artifact/ArtifactRenderer.ui.test.tsx"`,共 43 个定向测试。 -- 已通过 P3G 定向 ESLint:`npm exec -- eslint "src/lib/layered-design/**/*.ts" "src/components/workspace/design/**/*.{ts,tsx}" "src/components/workspace/canvas/CanvasFactory.tsx" "src/components/agent/chat/workspace/useWorkspaceCanvasSceneRuntime.tsx" --max-warnings 0`。 -- 已通过定向 TypeScript 检查:`npm exec -- tsc -p "/tmp/lime-layered-design-tsconfig.json" --noEmit`。 -- 已再次尝试 `npm run verify:gui-smoke -- --timeout-ms 600000 --interval-ms 1000`;本轮未走到新增 `smoke:design-canvas`,而是在既有 `smoke:agent-runtime-tool-surface-page` 超时。随后单独复跑该旧 smoke,失败点为 `launch_browser_session` 多次 DevBridge 响应超时;该失败归类为既有 browser runtime / 本地端口状态问题,不来自 `canvas:design`。 - -### 2026-05-05 P3H / P4A Design Canvas 专属 smoke 与导出首刀 - -- 已新增 `src/pages/design-canvas-smoke.tsx`,DEV-only 挂载 `/design-canvas-smoke`,从 `createLayeredDesignArtifactFromPrompt -> createCanvasStateFromArtifact -> CanvasFactory` 进入真实 `canvas:design` 页面。 -- 已新增 `scripts/design-canvas-smoke.mjs` 与 `package.json` 脚本 `smoke:design-canvas`,验证 `canvas:design`、`LayeredDesignDocument`、图层栏、属性栏、生成/刷新/单层重生成/导出入口,以及图层选择、右移、隐藏、显示交互。 -- 已修正 `scripts/design-canvas-smoke.mjs`:优先使用系统 Chrome channel,缺失时回退 Playwright Chromium;图层与属性按钮定位改为精确 accessible name,避免与图层列表“显示/隐藏”元信息冲突。 -- 已新增 `src/lib/layered-design/export.ts`,把 `LayeredDesignDocument` 投影为 `design.json`、`export-manifest.json`、`preview.svg`、`preview.png` 和可下载内嵌 data URL assets,不新增 Tauri 命令。 -- `export-manifest.json` 会区分 `file / reference / missing`:内嵌 data URL assets 可下载成文件,远程 assets 保留 `originalSrc` 引用,避免伪装成本地 assets 已落盘。 -- `DesignCanvas` 顶部工具栏已把旧占位“PNG 导出待接入”替换为“导出设计工程”,点击后下载设计 JSON、manifest、SVG、PNG 和内嵌 assets;PNG 由当前 SVG 投影转换而来,仍不是事实源。 -- 已补 `src/lib/layered-design/export.test.ts` 与 `src/components/workspace/design/DesignCanvas.test.tsx` 回归,覆盖导出包结构、SVG 可见图层投影、文本转义、远程 assets 引用、UI 导出入口。 -- 已通过汇总回归:`npm exec -- vitest run "src/lib/layered-design/document.test.ts" "src/lib/layered-design/planner.test.ts" "src/lib/layered-design/artifact.test.ts" "src/lib/layered-design/generation.test.ts" "src/lib/layered-design/imageModelCapabilities.test.ts" "src/lib/layered-design/imageTasks.test.ts" "src/lib/layered-design/export.test.ts" "src/components/workspace/design/DesignCanvas.test.tsx" "src/components/artifact/canvasAdapterUtils.test.ts" "src/components/artifact/ArtifactRenderer.ui.test.tsx"`,共 47 个测试。 -- 已通过定向 ESLint:`npm exec -- eslint "src/lib/layered-design/**/*.ts" "src/components/workspace/design/**/*.{ts,tsx}" "scripts/design-canvas-smoke.mjs" --max-warnings 0`。 -- 已通过定向 TypeScript 检查:`npm exec -- tsc -p "/tmp/lime-layered-design-tsconfig.json" --noEmit`。该临时 tsconfig 为规避既有 `src/lib/sceneapp/product.ts` 对 ES2022 `Array.prototype.at` 的依赖,显式使用 `lib: ["ES2022", "DOM", "DOM.Iterable"]`。 -- 已通过专属 GUI smoke:`npm run smoke:design-canvas -- --timeout-ms 240000 --interval-ms 1000`,真实页面验证通过,项目为默认 workspace `849e36ff-8f64-45ed-ba51-aab6b8e182e4`。 -- 截至 2026-05-05 该刀收口前,完整 `verify:gui-smoke` 尚未通过;后续 2026-05-06 记录已完成仓库级 smoke 收口。 - -### 2026-05-06 P4A GUI smoke 收口 - -- 已修正 `scripts/agent-runtime-tool-surface-page-smoke.mjs` 的托管 Chrome 会话恢复逻辑:当 `browser_execute_action` 遇到 `CDP 调试端口不可用`、`没有可用的 Chrome 会话` 或 `未找到 profile_key=` 时,限次重启同一 smoke profile 后继续当前检查,避免本地 Chrome profile 抖动误报为产品失败。 -- 已通过 `npm exec -- eslint "scripts/agent-runtime-tool-surface-page-smoke.mjs" --max-warnings 0`。 -- 已通过单独旧 smoke 复测:`npm run smoke:agent-runtime-tool-surface-page -- --timeout-ms 180000 --interval-ms 1000`。 -- 已通过完整 GUI smoke:`npm run verify:gui-smoke -- --reuse-running --timeout-ms 600000 --interval-ms 1000`。 -- 本轮完整 GUI smoke 覆盖 `workspace-ready`、`browser-runtime`、`site-adapters`、`agent-service-skill-entry`、`agent-runtime-tool-surface`、`agent-runtime-tool-surface-page`、`knowledge-gui` 与新增 `design-canvas`;其中 `smoke:design-canvas` 真实验证 `canvas:design`、`LayeredDesignDocument`、图层栏、属性栏、生成/刷新/单层重生成/导出入口,以及图层选择、右移、隐藏、显示。 -- 当前结论:`canvas:design` 已达到 Lime GUI 最小可交付门槛;尚未完成的是原生工程目录落盘、media task worker 后处理 seam、PSD-like 投影与扁平图拆层。 - -### 2026-05-06 P4B ZIP 工程包导出 - -- 已新增 `src/lib/layered-design/zip.ts`,实现无依赖 stored ZIP writer;该工具只负责 ZIP 容器,不懂 `LayeredDesignDocument` 语义,避免把打包细节塞进设计协议。 -- 已扩展 `src/lib/layered-design/export.ts`:`createLayeredDesignExportZipFile` 会把 `design.json`、`export-manifest.json`、`preview.svg`、调用方生成的 `preview.png` 和内嵌 data URL assets 打进单个 `.layered-design.zip`。 -- `DesignCanvas` 的“导出设计工程”入口已从散落下载多个文件改为下载单个 ZIP;包内 `assets/` 只包含内嵌 data URL assets,远程 assets 仍只在 manifest 中保留 `originalSrc` 引用。 -- 已补 `src/lib/layered-design/export.test.ts`,读取 ZIP local headers 校验包内路径为 `design.json / export-manifest.json / preview.svg / preview.png / assets/...`,并断言不回流 `poster_generate / canvas:poster`。 -- 已补 `src/components/workspace/design/DesignCanvas.test.tsx`,验证导出入口只触发一次 ZIP 下载,而不是多个散文件下载。 -- 已通过 `npm exec -- vitest run "src/lib/layered-design/export.test.ts" "src/components/workspace/design/DesignCanvas.test.tsx"`,共 12 个测试。 -- 已通过 `npm exec -- eslint "src/lib/layered-design/export.ts" "src/lib/layered-design/zip.ts" "src/lib/layered-design/export.test.ts" "src/components/workspace/design/DesignCanvas.tsx" "src/components/workspace/design/DesignCanvas.test.tsx" --max-warnings 0`。 -- 已通过 `npm exec -- tsc -p "/tmp/lime-layered-design-tsconfig.json" --noEmit`。 -- 已尝试 `npm run smoke:design-canvas -- --timeout-ms 240000 --interval-ms 1000`,但本地 DevBridge 未监听 `3030`,停在 `stage=wait-health` 后失败;随后 `npm run bridge:health -- --timeout-ms 10000` 也确认 `fetch failed`。本轮曾尝试启动 `npm run tauri:dev:headless`,但被已有 Cargo artifact lock 阻塞,已终止本轮启动进程,未处理其他已有 Rust / dev 进程。 -- 当前结论:浏览器侧已经具备单文件设计工程包代码路径与组件级回归;GUI smoke 需要等本地 DevBridge 恢复后补跑。下一刀应接 media task worker 的 `chroma_key_postprocess` seam,而不是继续扩展导出 UI。 - -### 2026-05-06 P4C media task chroma-key 后处理 seam - -- 已修复 `src-tauri/src/commands/media_task_cmd.rs`:`create_image_generation_task_artifact_inner` 现在会把请求中的 `runtime_contract` 合并进标准 `image_generation_runtime_contract()`,保留 `layered_design` 扩展,同时不允许覆盖标准 `contract_key / executor_binding / policy / routing` 主合同。 -- 已扩展 `src-tauri/crates/media-runtime/src/lib.rs`:图片 worker 会从 `payload.runtime_contract.layered_design.alpha` 读取 `chroma_key_postprocess`,给每个请求 slot prompt 追加 chroma-key 背景约束,并在 `result.postprocess` 与 `images[].postprocess` 写入 `pending_chroma_key_processor` seam。 -- 已扩展 `src/lib/layered-design/imageTasks.ts`:`GeneratedDesignAsset.params.postprocess` 会保留 worker 写回的后处理状态,后续像素级处理器可以按 `taskId / documentId / layerId / originalAssetId` 找回上下文。 -- 已补 `src-tauri/src/commands/media_task_cmd.rs` 回归,证明图片任务 artifact 同时保留标准 executor binding 和 `layered_design.alpha.strategy = chroma_key_postprocess`。 -- 已补 `src-tauri/crates/media-runtime/src/lib.rs` 回归,证明 worker 能消费 layered-design alpha contract、追加 chroma-key prompt hint,并写出 `pending_chroma_key_processor` 结果 seam。 -- 已补 `src/lib/layered-design/imageTasks.test.ts` 回归,证明前端写回资产时不会丢失 worker postprocess metadata。 -- 已通过 `npm exec -- vitest run "src/lib/layered-design/imageTasks.test.ts" "src/lib/layered-design/imageModelCapabilities.test.ts"`,共 13 个测试。 -- 已通过 `npm exec -- eslint "src/lib/layered-design/imageTasks.ts" "src/lib/layered-design/imageTasks.test.ts" --max-warnings 0`。 -- 已通过 `npm exec -- tsc -p "/tmp/lime-layered-design-tsconfig.json" --noEmit`。 -- 已通过 `CARGO_TARGET_DIR="/tmp/lime-p4c-media-runtime-target" cargo test --manifest-path "src-tauri/Cargo.toml" -p lime-media-runtime prepare_image_task_input_should_consume_layered_design_chroma_key_postprocess_contract`。 -- 已通过 `CARGO_TARGET_DIR="/tmp/lime-p4c-app-target" cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib create_image_generation_task_artifact_inner_should_preserve_layered_design_runtime_contract --no-default-features`。 -- 已通过命令契约门禁:`npm run test:contracts`。 -- 当前结论:`chroma_key_postprocess` 已从 LayeredDesignDocument 图层任务 contract 贯穿到标准 image task artifact、worker 请求与结果回写;下一刀才做真实像素级 key color -> alpha 处理或原生工程目录落盘。 - -### 2026-05-06 P4D data URL PNG chroma-key 像素级后处理 - -- 已为 `lime-media-runtime` 增加最小依赖 `base64` 与 `image`,只用于 worker 内 PNG data URL 解码、像素遍历和透明 PNG 编码;没有新增 provider adapter、Tauri 命令或 Python/CLI 旁路。 -- 已扩展 `src-tauri/crates/media-runtime/src/lib.rs`:当图片服务返回 `data:image/png;base64` 且任务带 `runtime_contract.layered_design.alpha.strategy = chroma_key_postprocess` 时,worker 会按 `chroma_key_color` 计算颜色距离,把命中像素 alpha 置 0,并用新的透明 PNG data URL 替换 `images[].url`。 -- `images[].postprocess` 现在会写入 `status: succeeded`、`removed_pixel_count`、`total_pixel_count`、`output_mime: image/png`、`transparent: true`;最终 `result.postprocess` 会聚合 `processed / succeeded / skipped / failed` 计数。 -- 远程 URL 或非 PNG data URL 不会让图片任务失败;worker 保留原始 `url`,并写入 `status: skipped_unsupported_source` 与原因,避免把不可处理资产伪装成透明图层。 -- 已更新 `src/lib/layered-design/imageTasks.test.ts`,验证前端资产写回会保留 worker 的 `succeeded` 后处理元数据与像素统计。 -- 已通过前端定向回归:`npm exec -- vitest run "src/lib/layered-design/imageTasks.test.ts" "src/lib/layered-design/imageModelCapabilities.test.ts"`,共 13 个测试。 -- 已通过前端定向 ESLint:`npm exec -- eslint "src/lib/layered-design/imageTasks.ts" "src/lib/layered-design/imageTasks.test.ts" --max-warnings 0`。 -- 已通过定向 TypeScript 检查:`npm exec -- tsc -p "/tmp/lime-layered-design-tsconfig.json" --noEmit`。 -- 已通过 Rust 定向回归:`CARGO_TARGET_DIR="/tmp/lime-p4d-media-runtime-target" cargo test --manifest-path "src-tauri/Cargo.toml" -p lime-media-runtime chroma_key`。 -- 已通过 Rust crate 回归:`CARGO_TARGET_DIR="/tmp/lime-p4d-media-runtime-target" cargo test --manifest-path "src-tauri/Cargo.toml" -p lime-media-runtime`,共 17 个测试。 -- 已通过 diff 卫生检查:`git diff --check -- "src-tauri/Cargo.lock" "src-tauri/crates/media-runtime/Cargo.toml" "src-tauri/crates/media-runtime/src/lib.rs" "src/lib/layered-design/imageTasks.ts" "src/lib/layered-design/imageTasks.test.ts" "docs/exec-plans/ai-layered-design-implementation-plan.md"`。 -- 当前结论:`LayeredDesignDocument -> image task artifact -> media-runtime -> GeneratedDesignAsset.params.postprocess` 已具备首个真实透明图层生成闭环;后续仍需远程资产缓存后处理、复杂 matting / mask refine、PSD-like 投影和扁平图拆层。 - -### 2026-05-06 P4E 远程 URL PNG chroma-key 后处理 - -- 已继续扩展 `src-tauri/crates/media-runtime/src/lib.rs`:当 provider 返回 `http/https` 图片 URL 且任务带 `chroma_key_postprocess` 时,worker 会在任务执行期受控下载该 URL,再复用同一套 PNG 像素处理器输出透明 PNG data URL。 -- 远程下载只允许 `http/https`,并设置 `IMAGE_TASK_POSTPROCESS_MAX_IMAGE_BYTES = 20 MiB` 上限;非 URL、非支持 scheme、下载失败、状态非成功或超限都只写后处理 `failed/skipped_unsupported_source`,不让图片任务整体失败。 -- `images[].postprocess.input_source` 现在可区分 `data_url` 与 `remote_url`;远程 URL 成功时 `images[].url` 会从原始 URL 替换为 `data:image/png;base64,...`,继续保留 `removed_pixel_count / total_pixel_count / transparent`。 -- 已补 Rust 集成回归 `execute_image_generation_task_should_postprocess_remote_chroma_key_url`,用本地 Axum 同时模拟图片生成接口和远程 PNG 资源,验证 worker 最终写回透明 data URL 且绿色像素 alpha=0、红色像素 alpha=255。 -- 已通过 Rust 定向回归:`CARGO_TARGET_DIR="/tmp/lime-p4e-media-runtime-target" cargo test --manifest-path "src-tauri/Cargo.toml" -p lime-media-runtime chroma_key`,共 3 个测试。 -- 已通过 Rust crate 回归:`CARGO_TARGET_DIR="/tmp/lime-p4e-media-runtime-target" cargo test --manifest-path "src-tauri/Cargo.toml" -p lime-media-runtime`,共 18 个测试。 -- 已通过 diff 卫生检查:`git diff --check -- "src-tauri/Cargo.lock" "src-tauri/crates/media-runtime/Cargo.toml" "src-tauri/crates/media-runtime/src/lib.rs" "src/lib/layered-design/imageTasks.ts" "src/lib/layered-design/imageTasks.test.ts" "docs/exec-plans/ai-layered-design-implementation-plan.md"`。 -- 当前结论:`chroma_key_postprocess` 已覆盖 provider 返回 `b64_json -> data URL` 与 `url -> http/https PNG` 两类主流图片结果;后续仍需持久化资产缓存、原生工程目录落盘、PSD-like 投影、复杂 matting / mask refine 与扁平图拆层。 - -### 2026-05-06 P4F 原生工程目录落盘 - -- 已新增 `src/lib/api/layeredDesignProject.ts`,前端只通过 API 网关调用 current Tauri 命令 `save_layered_design_project_export`,没有在 `DesignCanvas` 里散落裸 `invoke`。 -- 已扩展 `src/lib/layered-design/export.ts`:在 ZIP 投影之外新增 `createLayeredDesignProjectExportFiles`,把同一份 `LayeredDesignDocument` 导出投影拆成可由 Tauri 写入的 `design.json / export-manifest.json / preview.svg / preview.png / assets/*` 文件列表。 -- 已新增 `src-tauri/src/commands/layered_design_cmd.rs`:只把导出文件写入项目根目录下 `.lime/layered-designs/.layered-design/`,并校验项目根目录必须是绝对路径、导出相对路径不得目录穿越、文件内容仅支持 `utf8 / base64`。 -- 已同步命令四侧:Rust `runner.rs` 注册、DevBridge dispatcher、`agentCommandCatalog.fileBrowserCommands`、`mockPriorityCommands` 与 `defaultMocks`;并在 `docs/aiprompts/commands.md` 记录该命令仍属于 `LayeredDesignDocument -> canvas:design` 主链。 -- `DesignCanvas` 现在在绑定 `projectRootPath` 时默认保存到项目工程目录;只有未绑定工作区时才回退浏览器 `.layered-design.zip` 下载,避免把浏览器下载误称为原生落盘。 -- 已补 `src/lib/layered-design/export.test.ts`、`src/components/workspace/design/DesignCanvas.test.tsx`、`src/lib/tauri-mock/core.test.ts` 与 `src/lib/dev-bridge/mockPriorityCommands.test.ts` 回归,覆盖 Tauri 文件列表、项目目录保存、不触发浏览器下载、mock 命令可用。 -- 已通过前端定向回归:`npm exec -- vitest run "src/lib/layered-design/export.test.ts" "src/components/workspace/design/DesignCanvas.test.tsx"`,共 14 个测试。 -- 已通过 mock / bridge 定向回归:`npm exec -- vitest run "src/lib/tauri-mock/core.test.ts" "src/lib/dev-bridge/mockPriorityCommands.test.ts"`,共 26 个测试。 -- 已通过定向 ESLint:`npm exec -- eslint "src/lib/api/layeredDesignProject.ts" "src/lib/layered-design/export.ts" "src/lib/layered-design/export.test.ts" "src/components/workspace/design/DesignCanvas.tsx" "src/components/workspace/design/DesignCanvas.test.tsx" "src/components/workspace/design/types.ts" "src/lib/dev-bridge/mockPriorityCommands.ts" "src/lib/tauri-mock/core.ts" --max-warnings 0`。 -- 已通过定向 TypeScript 检查:`npm exec -- tsc -p "/tmp/lime-layered-design-tsconfig.json" --noEmit`。 -- 已通过 Rust 定向回归:`CARGO_BUILD_JOBS=1 CARGO_TARGET_DIR="/Users/coso/Library/Caches/lime-p4f-layered-design-target" cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib save_layered_design_project_export --no-default-features`,共 2 个测试。 -- 已通过命令契约门禁:`npm run test:contracts`。 -- 已通过专属 GUI smoke:`npm run smoke:design-canvas -- --timeout-ms 240000 --interval-ms 1000`,真实页面验证 `canvas:design`、图层交互和导出入口仍可打开。 -- 已通过完整 GUI smoke:`npm run verify:gui-smoke -- --reuse-running --timeout-ms 600000 --interval-ms 1000`。 -- 已通过 diff 卫生检查:`git diff --check -- "src/lib/api/layeredDesignProject.ts" "src/lib/layered-design/export.ts" "src/lib/layered-design/export.test.ts" "src/components/workspace/design/DesignCanvas.tsx" "src/components/workspace/design/DesignCanvas.test.tsx" "src/components/workspace/design/types.ts" "src-tauri/src/commands/layered_design_cmd.rs" "src-tauri/src/commands/mod.rs" "src-tauri/src/app/runner.rs" "src-tauri/src/dev_bridge/dispatcher/files.rs" "src/lib/dev-bridge/mockPriorityCommands.ts" "src/lib/tauri-mock/core.ts" "src/lib/governance/agentCommandCatalog.json" "docs/aiprompts/commands.md"`。 -- 当前结论:P4F 的 current 代码路径、命令契约、Rust 写盘内核和 GUI 主路径均已验证通过;后续可进入 PSD-like 投影或扁平图拆层,不需要回到旧 poster / ImageTaskViewer 链路。 - -### 2026-05-06 P4G 工程目录再打开 / 恢复 - -- 已扩展 current API 网关 `src/lib/api/layeredDesignProject.ts`:新增 `readLayeredDesignProjectExport`,继续通过 `safeInvoke` 调用 `read_layered_design_project_export`,页面层没有散落裸 `invoke`。 -- 已扩展 `src-tauri/src/commands/layered_design_cmd.rs`:新增只读请求/输出结构和 `read_layered_design_project_export_inner`,支持显式相对目录或自动选择最近保存的 `.lime/layered-designs/*.layered-design/`,只读取 `design.json` 与可选 `export-manifest.json`。 -- 读取命令会校验 `projectRootPath` 必须是绝对路径、指定导出目录必须位于 `.lime/layered-designs/` 下;非导出目录或缺少 `design.json` 会失败,不会把普通目录误当设计工程。 -- 已同步命令四侧:Rust `runner.rs` 注册、DevBridge dispatcher、`agentCommandCatalog.fileBrowserCommands`、`mockPriorityCommands` 与 `defaultMocks`;`docs/aiprompts/commands.md` 已记录保存/读取同属 `LayeredDesignDocument -> canvas:design` current 工程目录链路。 -- `DesignCanvas` 新增“打开最近工程”入口:绑定 `projectRootPath` 后读取最近工程,`JSON.parse(designJson)` 后通过 `normalizeLayeredDesignDocument` 恢复文档,并自动选中恢复文档中最高 zIndex 图层,继续沿同一个编辑器状态工作。 -- 已补 `src/components/workspace/design/DesignCanvas.test.tsx` 回归,覆盖“打开最近工程”后恢复 `LayeredDesignDocument`、继续编辑状态和旧 `poster_generate / canvas:poster / ImageTaskViewer` 不回流。 -- 已补 `src/lib/tauri-mock/core.test.ts` 与 `src/lib/dev-bridge/mockPriorityCommands.test.ts` 回归,覆盖保存/读取 mock 闭环和浏览器模式 mock 优先命令集合;`scripts/design-canvas-smoke.mjs` 也检查“打开最近工程”入口存在。 -- 已通过前端定向回归:`npm exec -- vitest run "src/lib/layered-design/export.test.ts" "src/components/workspace/design/DesignCanvas.test.tsx" "src/lib/tauri-mock/core.test.ts" "src/lib/dev-bridge/mockPriorityCommands.test.ts"`,共 43 个测试。 -- 已通过定向 ESLint:`npm exec -- eslint "src/lib/api/layeredDesignProject.ts" "src/components/workspace/design/DesignCanvas.tsx" "src/components/workspace/design/DesignCanvas.test.tsx" "src/components/workspace/design/types.ts" "src/lib/dev-bridge/mockPriorityCommands.ts" "src/lib/dev-bridge/mockPriorityCommands.test.ts" "src/lib/tauri-mock/core.ts" "src/lib/tauri-mock/core.test.ts" "scripts/design-canvas-smoke.mjs" --max-warnings 0`。 -- 已通过定向 TypeScript 检查:重建 `/tmp/lime-layered-design-tsconfig.json` 后执行 `npm exec -- tsc -p "/tmp/lime-layered-design-tsconfig.json" --noEmit`。 -- 已通过 Rust 定向回归:`CARGO_BUILD_JOBS=1 CARGO_TARGET_DIR="/Users/coso/Library/Caches/lime-p4g-layered-design-target" cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib layered_design_project_export --no-default-features`,共 4 个测试。 -- 已通过命令契约门禁:`npm run test:contracts`。 -- 已通过专属 GUI smoke:`npm run smoke:design-canvas -- --timeout-ms 240000 --interval-ms 1000`,真实页面验证 `canvas:design`、图层交互、导出入口和“打开最近工程”入口仍可打开。 -- 已通过完整 GUI smoke:`npm run verify:gui-smoke -- --reuse-running --timeout-ms 600000 --interval-ms 1000`。 -- 已通过 diff 卫生检查:`git diff --check` 覆盖 tracked 主线文件;未跟踪的新文件 `src-tauri/src/commands/layered_design_cmd.rs` 与 `src/lib/api/layeredDesignProject.ts` 已额外检查尾随空白和文件末尾换行。 -- 当前结论:P4G 已补上 `生成/编辑 -> 保存项目工程目录 -> 重新打开 -> 继续编辑` 的最小 current 闭环;仍未完成的是持久化远程资产缓存、PSD-like 投影、复杂 matting / mask refine 与扁平图拆层。 - -### 2026-05-06 P4H PSD-like 专业导出投影 - -- 已扩展 `src/lib/layered-design/export.ts`:新增 `createLayeredDesignPsdLikeManifest` 与 `LAYERED_DESIGN_PSD_LIKE_EXPORT_SCHEMA_VERSION`,把 `LayeredDesignDocument` 投影为 `psd-like-layer-stack`。 -- `psd-like-manifest.json` 会记录 `source.factSource=LayeredDesignDocument`、`compatibility.truePsd=false`、`layerOrder=back_to_front`,并把 image / effect、text、shape、group 分别投影为 raster image、editable text、vector shape 与 group reference。 -- ZIP 工程包与 Tauri 工程目录文件列表现在都会包含 `design.json / export-manifest.json / psd-like-manifest.json / preview.svg / preview.png / assets/`;远程 assets 继续只保留 `source=reference` 与 `originalSrc`,不伪装成已缓存文件。 -- `DesignCanvas` 导出文案已同步说明 `psd-like-manifest.json`,用户仍从同一个“导出设计工程”入口进入,不新增旧 poster、provider adapter 或平行主链。 -- 已补 `src/lib/layered-design/export.test.ts` 回归,覆盖 PSD-like manifest 的事实源、兼容性声明、图层顺序、图层角色、远程 asset 引用和旧链路禁词。 -- 已补 `src/components/workspace/design/DesignCanvas.test.tsx` 回归,覆盖导出入口文案和 Tauri 保存文件列表包含 `psd-like-manifest.json`。 -- 已通过前端定向回归:`npm exec -- vitest run "src/lib/layered-design/export.test.ts" "src/components/workspace/design/DesignCanvas.test.tsx"`,共 16 个测试。 -- 已通过定向 ESLint:`npm exec -- eslint "src/lib/layered-design/export.ts" "src/lib/layered-design/export.test.ts" "src/components/workspace/design/DesignCanvas.tsx" "src/components/workspace/design/DesignCanvas.test.tsx" --max-warnings 0`。 -- 已通过定向 TypeScript 检查:`npm exec -- tsc -p "/tmp/lime-layered-design-tsconfig.json" --noEmit`。 -- 已通过专属 GUI smoke:`npm run smoke:design-canvas -- --timeout-ms 240000 --interval-ms 1000`。 -- 已通过完整 GUI smoke:`npm run verify:gui-smoke -- --reuse-running --timeout-ms 600000 --interval-ms 1000`。 -- 当前结论:P4H 完成的是专业层栈 manifest 投影,不是真 PSD writer;仍未完成的是持久化远程资产缓存、真 PSD 文件导出 / 打开验证、复杂 matting / mask refine、OCR 与扁平图拆层。 - -### 2026-05-06 P4I 原生工程目录远程资产持久化缓存 - -- 已继续扩展 `src-tauri/src/commands/layered_design_cmd.rs`,但没有新增命令名:`save_layered_design_project_export` 现在会解析 `export-manifest.json` 中 `source=reference + originalSrc=http/https` 的远程图片资产,并在保存工程目录时尝试持久化到 `assets/`。 -- 远程缓存成功后,命令会把 `export-manifest.json` 与 `psd-like-manifest.json` 中对应资产从 `reference` 更新为 `file`,同时继续保留 `originalSrc`,确保导出 projection 明确说明“这是缓存副本,不是新的事实源 URL”。 -- `design.json` 磁盘文件仍保持原始导出投影,不在保存阶段偷偷改成第二套协议;重新打开时由 `read_layered_design_project_export` 优先读取 manifest 指向的缓存文件,把对应 asset 水合回 data URL,再返回给前端 `DesignCanvas`。 -- 这刀的直接收益是:远程图片图层在“保存项目工程目录 -> 重新打开 -> 继续编辑”链路里不再完全依赖远程 URL 在线可达;即使原始 provider URL 后续失效,只要缓存文件仍在,本地工程仍能继续打开编辑。 -- 本轮不扩浏览器 ZIP 下载的远程缓存;ZIP 仍保持“嵌入 data URL 资产直接打包,远程资产保留引用”。这样避免为了浏览器侧旁路再引入第二套下载/权限模型。 - -### 2026-05-06 P4J 扁平图拆层协议首刀 - -- 已在 `src/lib/layered-design/types.ts` 给 `LayeredDesignDocument` 增加兼容扩展字段 `extraction`,并补 `GeneratedDesignAsset.kind = "source_image"`,让扁平图来源资产、候选层、置信度和 clean plate 状态都能稳定回挂到 current 事实源,而不是另起一套拆层中间协议。 -- 已在 `src/lib/layered-design/document.ts` 增加 extraction normalization:候选层会被强制标记 `source: "extracted"`,低置信度自动补 `low_confidence`,并把 extraction 附带的 `clean_plate` / 候选资产吸收到顶层 `assets`,避免后续 UI 或导出在事实源内读到“候选引用了不存在的资产”。 -- 已新增 `src/lib/layered-design/extraction.ts` 纯函数,提供 `createLayeredDesignExtractionDocument` 和 `updateLayeredDesignExtractionSelection`:前者把扁平图、候选层、clean plate 结果归一为 draft 文档,后者只把 `selected=true` 的候选 materialize 到正式 `layers`,未选候选继续只存在于 `extraction.candidates`。 -- clean plate 成功时,背景层默认引用 `clean_plate`;clean plate 失败时,背景层自动回退到 `source_image`,同时保留 `extraction.cleanPlate.status/message`,确保“可继续编辑”和“风险显式暴露”同时成立。 -- 本轮仍不接 OCR / SAM / matting / inpaint 真执行,也不接拆层确认页;这刀只把后续拆层执行链路需要的协议和不变量先钉死在 current 主链上。 -- 已验证: - - `npm exec -- vitest run "src/lib/layered-design/document.test.ts" "src/lib/layered-design/extraction.test.ts"` - - `npm exec -- eslint "src/lib/layered-design/types.ts" "src/lib/layered-design/document.ts" "src/lib/layered-design/extraction.ts" "src/lib/layered-design/extraction.test.ts" --max-warnings 0` - - `npm exec -- tsc -p "/tmp/lime-layered-design-extraction-tsconfig.json" --noEmit` - -### 2026-05-06 P4K 扁平图 draft `canvas:design` Artifact bridge - -- 已在 `src/lib/layered-design/artifact.ts` 新增 `createLayeredDesignArtifactFromExtraction`,把扁平图拆层 draft 的创建和 Artifact 包装放在同一条 current helper 链里,避免后续上传/拆层入口再临时拼装 `canvas:design` JSON。 -- 这个 bridge 明确把拆层 draft 归类为 `meta.source = "layered-design-extraction"`,继续沿用现有 `canvas:design`、`platform: layered-design` 和 `designId` 语义,不新增拆层专用 Artifact type,也不回流旧 `canvas:poster` / `ImageTaskViewer` 路线。 -- `src/lib/layered-design/artifact.test.ts` 已补回归:扁平图 draft 打开到 `DesignCanvasState` 后,只会 materialize 已选/高置信度候选层;低置信度碎片候选仍只留在 `document.extraction.candidates`,保持确认前后边界一致。 -- 这刀的直接收益是:后续不管拆层结果来自本地 analyzer、远程任务还是 mock,都能先归一为 `LayeredDesignDocument`,再复用现有 Artifact/Canvas 主链进入编辑,不需要为拆层入口再开第二套 Viewer/Workspace 路径。 -- 已验证: - - `npm exec -- vitest run "src/lib/layered-design/document.test.ts" "src/lib/layered-design/extraction.test.ts" "src/lib/layered-design/artifact.test.ts"` - - `npm exec -- eslint "src/lib/layered-design/types.ts" "src/lib/layered-design/document.ts" "src/lib/layered-design/extraction.ts" "src/lib/layered-design/artifact.ts" "src/lib/layered-design/extraction.test.ts" "src/lib/layered-design/artifact.test.ts" --max-warnings 0` - - `npm exec -- tsc -p "/tmp/lime-layered-design-extraction-tsconfig.json" --noEmit` - -### 2026-05-06 P4L 上传扁平图本地 draft adapter - -- 已新增 `src/lib/layered-design/flatImage.ts`,提供 `createLayeredDesignFlatImageDraftDocument`:输入只需要上传图片的 `src/width/height` 与可选 `fileName`,就能自动推导 `document id/title`、`source_image asset`、canvas 尺寸,并产出一个最小 extraction draft。 -- 这个 adapter 复用了前一刀的 extraction 协议,而不是新开一套“上传图片草稿” schema:即使当前还没有 analyzer / OCR / clean plate 结果,也仍然先生成 `LayeredDesignDocument.extraction`,背景层默认回指原始 `source_image`。 -- 已在 `src/lib/layered-design/artifact.ts` 新增 `createLayeredDesignArtifactFromFlatImage`,让单张上传图片可以直接落成 current `canvas:design` Artifact;它继续复用 `layered-design-extraction` 元数据来源,不额外扩 metadata 面。 -- `src/lib/layered-design/flatImage.test.ts` 证明两点:一是纯上传图可以直接进入“只有背景层”的最小 draft;二是同一个 adapter 可以在有本地候选 seed 时只 materialize 高置信度候选层,把低置信度碎片继续留在 `extraction.candidates`。 -- `src/lib/layered-design/artifact.test.ts` 已补回归,证明 `createLayeredDesignArtifactFromFlatImage` 产出的 Artifact 可以直接进入 `DesignCanvasState`,不需要额外 JSON 拼装或第二条 Workspace 接线。 -- 这刀的直接收益是:后续“上传扁平图”入口只要先拿到图片 bytes / data URL / 远程 URL 与尺寸,就已经能稳定走到 current `canvas:design` 主链;未来接 analyzer 结果时只是在同一份 extraction draft 上补 candidates/cleanPlate,不用重写打开链路。 -- 已验证: - - `npm exec -- vitest run "src/lib/layered-design/document.test.ts" "src/lib/layered-design/extraction.test.ts" "src/lib/layered-design/flatImage.test.ts" "src/lib/layered-design/artifact.test.ts"` - - `npm exec -- eslint "src/lib/layered-design/types.ts" "src/lib/layered-design/document.ts" "src/lib/layered-design/extraction.ts" "src/lib/layered-design/flatImage.ts" "src/lib/layered-design/artifact.ts" "src/lib/layered-design/extraction.test.ts" "src/lib/layered-design/flatImage.test.ts" "src/lib/layered-design/artifact.test.ts" --max-warnings 0` - - `npm exec -- tsc -p "/tmp/lime-layered-design-flat-image-tsconfig.json" --noEmit` - -### 2026-05-06 P4M DesignCanvas 候选层切换首刀 - -- 已在 `src/components/workspace/design/DesignCanvas.tsx` 新增两个 current UI 动作:工具栏的“上传扁平图”,以及属性栏里的“拆层候选”卡片。前者直接读取本地图片文件并落成 extraction draft,后者允许在同一个 `DesignCanvas` 内切换 `extraction.candidates.selected`。 -- 这一刀没有新建独立拆层确认页,而是先把确认态压进现有 `DesignCanvas`,验证 `LayeredDesignDocument.extraction -> selected candidates -> layers` 这个最小状态机能否在 current 主路径内跑通。 -- UI 语义保持和协议一致:低置信度候选仍会显示“低置信度”,但在用户点击前不会 materialize 到正式图层;点击后只改 `candidate.selected`,再由纯函数同步图层栈,不直接手改 `layers`。 -- 这刀的直接收益是:上传扁平图后,用户已经可以在 current 画布里完成“原图进入编辑 -> 补选候选层 -> 成为正式图层”的最小操作,而不需要等待独立确认页或真实 analyzer 才能继续主链验证。 -- 已验证: - - `npm exec -- vitest run "src/components/workspace/design/DesignCanvas.test.tsx" "src/lib/layered-design/document.test.ts" "src/lib/layered-design/extraction.test.ts" "src/lib/layered-design/flatImage.test.ts" "src/lib/layered-design/artifact.test.ts"` - - `npm exec -- eslint "src/components/workspace/design/DesignCanvas.tsx" "src/components/workspace/design/DesignCanvas.test.tsx" "src/lib/layered-design/flatImage.ts" "src/lib/layered-design/flatImage.test.ts" "src/lib/layered-design/artifact.ts" "src/lib/layered-design/artifact.test.ts" --max-warnings 0` - - `npm run verify:gui-smoke -- --timeout-ms 600000 --interval-ms 1000`(已通过) - -### 2026-05-06 P4N 上传扁平图本地 heuristic seed 首刀 - -- 已新增 `src/lib/layered-design/flatImageHeuristics.ts`,在浏览器本地对上传图片生成最小裁片候选:主体、标题文字、Logo 与边角碎片都继续回挂到 `LayeredDesignDocument.extraction.candidates`,不新增新的拆层 schema。 -- `DesignCanvas` 的上传入口现在会优先尝试本地 heuristic seed:成功时直接带着裁片候选进入 current `canvas:design -> DesignCanvas` 主链;失败时回退为“只有背景层”的 draft,不阻断上传到 current 画布。 -- 这刀仍然显式标注 clean plate 未执行,且只让高于阈值的主体 / 标题裁片默认进入正式图层;Logo 和碎片继续作为低置信度候选等待用户确认,避免把启发式裁片伪装成真实拆层结果。 -- 这刀的直接收益是:`上传扁平图 -> extraction draft -> 候选层切换 -> 正式图层` 现在不再依赖手工伪造 seed 或未来 analyzer 才能演示,current `DesignCanvas` 已经能直接承接一条最小但真实的候选层闭环。 -- 已验证: - - `npm exec -- vitest run "src/components/workspace/design/DesignCanvas.test.tsx" "src/lib/layered-design/document.test.ts" "src/lib/layered-design/extraction.test.ts" "src/lib/layered-design/flatImage.test.ts" "src/lib/layered-design/artifact.test.ts"` - - `npm exec -- eslint "src/components/workspace/design/DesignCanvas.tsx" "src/components/workspace/design/DesignCanvas.test.tsx" "src/lib/layered-design/flatImage.ts" "src/lib/layered-design/flatImage.test.ts" "src/lib/layered-design/flatImageHeuristics.ts" "src/lib/layered-design/artifact.ts" "src/lib/layered-design/artifact.test.ts" "src/lib/layered-design/index.ts" --max-warnings 0` - - `npm exec -- tsc -p "/tmp/lime-layered-design-tsconfig.json" --noEmit` - - `npm run verify:gui-smoke -- --timeout-ms 600000 --interval-ms 1000` diff --git a/docs/exec-plans/at-command-local-execution-alignment-plan.md b/docs/exec-plans/at-command-local-execution-alignment-plan.md deleted file mode 100644 index 97f850e0e..000000000 --- a/docs/exec-plans/at-command-local-execution-alignment-plan.md +++ /dev/null @@ -1,218 +0,0 @@ -# `@` 命令本地执行面纠偏计划 - -## 摘要 - -本计划用于把 Lime 客户端仓库中关于 `@` 命令、产品型 `/scene`、`ServiceSkill` 的 current 文档收口到同一个正确前提: - -- `limecore` 只负责目录控制、发布治理与配置同步 -- `lime` 客户端负责全部执行 -- 不存在服务端代跑 `@` 命令、`/scene` 或 `service skill` 的 current 主链 - -这份计划只覆盖客户端仓库的文档与后续本地实现收口,同时定义服务端文档完成后的跨仓校验要求。 - -## 背景 - -最近两仓围绕 Ribbi 风格统一调用面的分析,暴露出一个持续回流的错误前提: - -1. 一部分文档把 `limecore` 写成了命令执行面 -2. 一部分文档把 `scene runtime`、`run / poll`、`cloud_required` 继续当成 current 产品模型 -3. 这会误导后续实现,把目录控制面继续扩成运行时 - -用户已明确产品边界: - -1. 云端不会执行任何东西 -2. `limecore` 只承担 `client/bootstrap`、`client/skills`、`client/service-skills` 这类目录与配置事实源 -3. Lime 客户端是唯一执行面 - -因此,客户端 current 文档必须先于代码实现完成纠偏,否则新增 `@` 命令会继续叠加在错误边界上。 - -## 正确边界 - -### `current` - -- `SkillCatalog.entries` 作为 `@ / / / skill` 的统一目录协议 -- `serviceSkillCatalog` 作为完整服务型技能目录 -- seeded / fallback 作为客户端韧性兜底 -- `request_metadata.harness.*` 作为本地运行时路由提示 -- Agent、tool、browser、workspace、task、viewer 全部留在本地执行 - -### `deprecated` - -- `cloud_required` -- `executionLocation = cloud_required` -- `OEM Scene Runtime run / poll` -- `lime_run_service_skill` 被解释成服务端执行入口 -- `cloud-video-dubbing` 这类带云语义的历史命名 - -### `dead` - -- 服务端代跑 `@` 命令 -- 服务端代跑 `/scene` -- 服务端代跑 `service skill` -- 任何把目录命中直接翻译成云端 run 的 current 叙事 - -## 本轮文档改动 - -需要优先收口以下客户端 current 文档: - -1. `docs/aiprompts/commands.md` -2. `docs/aiprompts/command-runtime.md` -3. `docs/aiprompts/limecore-collaboration-entry.md` -4. `docs/roadmap/lime-service-skill-cloud-config-prd.md` - -改动原则: - -1. 删除或改写 `run / poll`、`cloud_required`、`scene runtime` 的 current 叙事 -2. 如果现有实现或历史 ID 仍沿用旧命名,文档里要明确它只是历史命名,不代表当前边界 -3. 不新发明第二套术语,统一收敛到“目录控制面 + 本地执行面” - -## 后续实现顺序 - -### Phase 1:文档先行 - -- 先把 current 文档纠偏 -- 在实现前统一团队和 AI 的事实源 - -### Phase 2:客户端代码收口 - -后续只在本仓库推进以下本地实现检查: - -- `src/components/agent/chat/workspace/useWorkspaceSendActions.ts` -- `src/components/agent/chat/workspace/serviceSkillSceneLaunch.ts` -- `src/components/agent/chat/service-skills/*` -- `src/components/agent/chat/workspace/useWorkspaceServiceSkillEntryActions.ts` -- `src/lib/base-setup/seededCommandPackage.ts` -- `src/lib/base-setup/seededServiceSkillPackage.ts` -- `src/components/settings-v2/system/automation/serviceSkillContext.ts` - -目标: - -- 去掉任何 current 主链中的云端 run / poll 假设 -- 保留目录命中与 metadata 注入 -- 把 `@配音`、`/scene-key`、service skill launch 全部收回本地执行链 - -### Phase 3:服务端完成后的联调校验 - -服务端会由另一个进程按 `limecore/docs/exec-plans/at-command-control-plane-only.md` 推进。客户端这边在服务端文档完成后,需要补一次跨仓一致性校验。 - -## 校验要求 - -### 客户端本地校验 - -至少重新检查: - -- `@配音` -- `/scene-key` -- `@浏览器` -- `@搜索` -- `@发布` -- `@渠道预览` - -校验点: - -1. 在线目录可命中 -2. seeded / fallback 不失能 -3. current 文档不再暗示云执行 -4. 轻卡、timeline、viewer 仍以本地运行态为真相 - -### 跨仓校验 - -服务端文档完成后,再做一次双仓扫描: - -- `cloud_required` -- `云执行` -- `run / poll` -- `scene runtime` -- `not_executable_in_cloud` - -扫描结果必须区分为: - -1. 已移除 -2. 仅保留在历史参考 -3. 仍误留在 current,需要继续收口 - -## 当前状态 - -- 2026-04-21:创建本计划,作为客户端纠偏的 current 执行入口 -- 2026-04-21:与用户确认真实产品边界为“云端不执行,只做目录控制” -- 2026-04-21:本轮优先目标固定为“先改文档事实源,再进入客户端实现收口” -- 2026-04-21:已完成 current 文档纠偏,统一改写为“云端只做目录控制,客户端负责执行” -- 2026-04-21:已继续同步质量事实源;`quality-workflow` 中的 `@配音 / /scene-key` 校验口径已从 `OEM run/timeline` 收回到本地 `service-scene` 直驱执行与 `ServiceSkill / tool timeline` -- 2026-04-21:已继续收口 Rust `service_scene_launch` current 默认值;后端当前默认按 `local_service_skill` 解析,并只把 `cloud_scene` 当 compat alias 读取 -- 2026-04-21:已完成客户端 current 主链收口,`/scene` 非站点技能与 `@配音` 不再依赖 OEM run / poll,而是统一生成本地 `composeServiceSkillPrompt(...)` 并通过工作区/Agent 本地执行 -- 2026-04-21:已完成 service skill 首页、@ 提及面板、设置自动化文案的执行语义纠偏;`cloud_required` 当前只作为兼容目录标记展示,不再表示云端执行 -- 2026-04-21:已继续收口 automation 设置页 current 展示;任务列表、详情弹窗和运行摘要里的 `cloud_required` 现在会显式显示为“客户端执行 + 旧目录兼容”,不再把 compat 标记伪装成当前执行真相 -- 2026-04-21:已完成技能工作台 current surface 的旧云运行状态收口,`ServiceSkillHomeItem` 与技能页展示不再消费 `cloudStatus` -- 2026-04-21:已删除零入口 compat 残留 `src/components/agent/chat/service-skills/cloudRunStorage.ts` 与 `src/lib/api/serviceSkillRuns.ts`,避免旧云 run 语义继续回流 -- 2026-04-21:已进一步把 current seeded package 主动产出的 `cloud_scene / cloud-scene-instant` 收掉;当前只保留历史 seeded id(如 `cloud-video-dubbing`)与 compat projection/sceneapp 中的旧命名,避免 current 目录事实源继续给云执行语义续命 -- 2026-04-21:已继续收口 sceneapp current 主链;Tauri / mock sceneapp planner 产出的 `service_scene_launch.kind` 与 `execution_kind` 已统一改为 `local_service_skill`,并补 `execution_location = client_default` -- 2026-04-21:已移除 current seeded sceneapp 中额外的 `cloud_session` 启动前置,避免 sceneapp detail/runtime 继续把“云端运行时”误当成当前执行门槛 -- 2026-04-21:已继续收口 sceneapp 恢复链内部命名;run summary / entry action / resume helper 中的 `cloud_scene_runtime_ref`、`cloudSceneRuntimeRef`、`open_cloud_scene_session` 已统一改成 `service_scene` 语义,并保留 Rust 侧 alias 兼容旧字段 -- 2026-04-21:已完成最小交付校验,`npm run test:contracts`、定向 Vitest、`npm run verify:local`、`npm run governance:legacy-report` 全部通过 -- 2026-04-21:已补充 sceneapp 定向校验;`npm run verify:gui-smoke` 与 sceneapp 定向 Vitest 已通过,Rust service-scene 新用例改名后需按当前测试名单独补测 -- 2026-04-21:已继续收口 sceneapp current planner/action 命名;当前 Tauri/mock planner 改为产出 `open_service_scene_session`,旧 `launch_cloud_scene` 仅保留为 compat 反序列化输入 -- 2026-04-21:已把 seeded `voice-runtime` 从 `cloud_managed` current 模型收回到本地即时类型;当前种子目录不再把它描述成“云托管场景” -- 2026-04-21:已继续收口 sceneapp runtime context;`cloud_session_ready` 不再参与 current readiness / tool refs 注入,只再保留为 compat 输入字段,避免 current planning 再把“云会话”带回执行语义 -- 2026-04-21:已继续收口 sceneapp seeded/mock 原始目录展示;current `capabilityRefs`、`infraProfile` 与 composition step binding 不再主动写出 `cloud_scene / cloud_runtime`,旧 `cloud_scene` 只再保留在 service-scene adapter 锚点与 compat 输入 -- 2026-04-21:已继续收口 sceneapp current entry binding;seeded/mock 里的 `story-video-suite`、`voice-runtime` 当前入口已改成 `agent_turn`,Rust/mock planner 会按 service-scene 特征继续产出 `open_service_scene_session` -- 2026-04-21:已继续收口 Rust sceneapp 内部命名;`CloudManaged / CloudScene / CloudSession / cloud_session_ready` 当前已改成内部 compat 语义名,并通过 serde 继续兼容旧外部值,避免 current 内部建模继续被旧云执行命名污染 -- 2026-04-22:已补通过 Rust sceneapp 定向 lib 测试:`should_build_service_scene_adapter_plan_for_hybrid_sceneapp`、`build_sceneapp_scorecard_from_runs_should_keep_stable_scene`、`should_promote_selected_memory_entries_into_reference_items` -- 2026-04-21:已补跑本轮相关前端定向回归;`useWorkspaceSendActions`、`sceneapp` API/目录/展示与 SceneApps 页面共 8 个 Vitest 文件、154 条用例通过 -- 2026-04-21:已补跑 `npm run governance:legacy-report`,结果为 `边界违规 0 / 分类漂移候选 0` -- 2026-04-21:已继续收口 sceneapp 展示层 current 边界;`presentation/product` 与 SceneApps 页面测试夹具默认改成 `agent_turn`,展示层不再主动持有 `cloud_scene` current 标签 -- 2026-04-22:已继续收口 `serviceSkills / skillCatalog` 类型边界;public `ServiceSkillItem / ServiceSkillCatalog / SkillCatalogExecutionKind` 默认只暴露 current 值,`cloud_scene / cloud_required` 改为显式 compat 类型或原始输入解析层处理 -- 2026-04-22:已同步更新聊天入口与技能页相关测试夹具;`service_scene_launch.kind` 当前统一改成 `local_service_skill`,服务技能 fixture 默认改成 `agent_turn + client_default` -- 2026-04-22:已补跑服务技能 / 技能目录 / 聊天入口定向回归共 11 个 Vitest 文件、206 条用例通过;随后补跑 `sceneapp` API/目录/launch 3 个 Vitest 文件、13 条用例通过 -- 2026-04-22:已再次补跑 `npm run governance:legacy-report`,结果仍为 `边界违规 0 / 分类漂移候选 0` -- 2026-04-22:已把 service skill 执行位置展示语义收回 `src/lib/api/serviceSkills.ts` 单一事实源;prompt composer 当前只写“客户端执行”,automation 设置页继续通过 compat helper 单独补 `旧目录兼容` 徽标,避免旧云目录标记继续混入 current prompt 文案 -- 2026-04-22:已继续收口 mock sceneapp planner 内部判断;legacy `cloudSessionReady` 输入不再把 planner 拉回 `cloud_scene` 分支,mock adapter 当前会先正规化到 `agent_turn` 后再决定是否打开 `service_scene` 会话 -- 2026-04-22:已继续收口前端 `sceneapp runtime context` 内部命名;当前默认改用 `directorySessionReadyCompat` 承载 compat 会话位,`sceneapp API` 调 Tauri 前会统一回写为 `cloudSessionReady` wire alias,mock readiness 也与 Rust 一样对 `cloud_session` 保持 compat no-op -- 2026-04-22:已继续收口 SceneApps 页面 current 筛选面;目录页不再主动提供 `cloud_managed` 旧类型筛选,旧 page params / 最近访问里的 `typeFilter=cloud_managed` 现在会在 `navigation` 归一化阶段被丢弃,避免 current 页面状态继续把 compat 类型写回路由与本地存储 -- 2026-04-22:已继续收口 sceneapp 展示 compat helper;`presentation/product` 当前统一通过显式 helper 解析 `cloud_managed / cloud_runtime`,workbench 统计与基础设施摘要不再各自直接消费旧云命名,compat 展示只保留在单一 helper 边界 -- 2026-04-22:已继续收口 `sceneapp API` 的旧 planner 假门槛;当前网关会过滤 `launchRequirements / readiness.unmetRequirements` 里的 `cloud_session`,并把 context overlay 中的 `toolRefs.cloud_scene -> agent_turn`、`toolRefs.cloud_session -> 丢弃`,避免旧 planner 再把“云会话阻塞”显影到 current 详情页 -- 2026-04-22:已继续收口 `sceneapp API` 的 compat 类型投影;旧目录 `sceneappType = cloud_managed` 当前会按绑定族与基础设施信号正规化为 `local_instant / local_durable / browser_grounded / hybrid`,不再把 compat 类型直接暴露给 current 前台对象 -- 2026-04-22:已继续收口 current 测试夹具默认值;`workspace sceneapp launch`、`workspace sceneapp entry actions` 与 `automation` 的默认 SceneApp plan/descriptor 夹具已改成 `agent_turn` / 本地能力摘要,只再保留显式 compat 用例验证旧 `cloud_scene` 输入的正规化 -- 2026-04-22:已继续清理 sceneapp 深层 current 测试夹具;`product` 与 `SceneAppsPage` 默认目录样板不再把 `cloud_runtime` 当作普通 `infraProfile` 基线,旧云基础设施词现在只保留给显式 compat 断言 -- 2026-04-22:已继续收口 SceneApps 详情页 current 启动主链;详情页 launch 现在会优先复用当前 preview planning,`workspace_entry` 做法会继续导航到 `agent` 主链,`automation_job` 会先打开标准自动化弹窗再异步补工作区列表,避免 current UI 因重复 planning 或等待工作区列表而停在 sceneapps 自身 -- 2026-04-22:已为 sceneapp launch runtime 补 unmount 保护;页面切走或测试回收后不再回流异步 `setState`,避免 current 导航链在离开 SceneApps 页后继续触发收尾更新 -- 2026-04-22:已补跑 `SceneAppsPage / navigation / presentation / product / launch` 共 5 个 Vitest 文件、58 条用例,通过;`npm run governance:legacy-report` 与 `npm run verify:gui-smoke` 也已通过 -- 2026-04-22:`npm run verify:local` 在 smart 批次 `src/components/agent/chat/workspace/serviceSkillSceneLaunch.test.ts` 因 `@/lib/api/serviceSkills` mock 未同步导出 `resolveServiceSkillExecutionLocationPresentation` 失败;该阻塞位于另一条 service-skill 线,不属于本轮 sceneapp 启动实现回归 -- 2026-04-21:Rust 定向测试 `cargo test should_build_service_scene_adapter_plan_for_hybrid_sceneapp` 因工作区存在多路并发 `cargo test` 抢占 `target`/artifact lock,未拿到最终结果;本轮不把它记为已通过,后续需在较干净的 Rust 构建窗口补测 -- 2026-04-21:已尝试用独立 `CARGO_TARGET_DIR=/tmp/lime-target-codex-sceneapp` 复测 Rust service-scene 新用例,但首次编译 `aster`/`lime` 依赖链耗时过长,本轮仍未拿到最终结果;为避免持续占用机器资源,已主动停止该测试进程,后续需在更稳定的 Rust 构建窗口补跑 - -## 本轮实现结果 - -### 已完成 - -- `/scene` 非站点技能:改为构造 `kind = local_service_skill` 的 request metadata,并生成本地 prompt;不再向 current 主链注入 `oem_runtime` 或云端 session 语义 -- `@配音`:保留用户可见原文,但底层 dispatch 改为 `composeServiceSkillPrompt(...)` 生成的本地 prompt;metadata 同步切换到 `local_service_skill` -- service skill 入口点击:删除 current 对 `createServiceSkillRun` / `getServiceSkillRun` / run-poll 的依赖,统一进入本地工作区准备态 -- 首页与提及展示:`runnerLabel`、`runnerDescription`、`actionLabel`、`outputDestination` 改为本地执行叙事;legacy `cloud_required` 只按兼容目录标记处理 -- automation 设置页展示:`service skill` 任务列表、详情弹窗与运行摘要当前都会补显 `旧目录兼容` 徽标与说明文案;即使 run metadata 已被正规化为 `client_default`,只要来源 job 仍带旧目录标记,也不会在 current 展示层把 compat 信息洗掉 -- Rust `service_scene_launch` 解析:当前默认 `kind` 已切到 `local_service_skill`,并允许 `cloud_scene` 只作为 compat alias 继续读取;`aster_agent_cmd` 定向测试样例也已同步改成 current 命名 -- Rust `prompt_context / lime_run_service_skill`:当前系统提示已改成“本地 service-scene 直驱执行”,`lime_run_service_skill` 只再作为 compat 护栏保留,不再发 OEM `/runs` 请求 -- seeded 目录:保留历史 id 以避免目录断裂,但 `@配音` 的 command binding 已切到 `agent_turn`,技能标题/摘要已改成当前本地执行语义 -- sceneapp planner:Tauri 与 mock 当前改为产出 `open_service_scene_session`;旧 `launch_cloud_scene` 只作为 compat 反序列化输入保留,避免历史 planner / fixture 直接失效 -- sceneapp seeded / fallback:当前目录不再额外声明 `cloud_session` 启动前置;sceneapp detail 展示会继续聚焦“目录控制面 + 客户端执行”,不再把云端运行时写成 current 门槛 -- sceneapp seeded voice-runtime:当前目录模型已改成 `local_instant` + 本地执行文案;旧 `cloud_managed` 只再保留给 compat 目录输入与展示兜底 -- sceneapp runtime context:当前 context compiler 不再把 `cloud_session` 注入 tool refs,且 runtime readiness 对 `cloud_session` 只按 compat no-op 处理;这样历史字段还能读,但不会再影响 current 启动判断 -- sceneapp 恢复链:当前做法复盘和继续执行链已统一改为 `service_scene` 命名;旧 `cloud_scene_runtime_ref` 只再作为 Rust 反序列化 alias 保留,避免历史 run summary 数据读取失败 -- mention / sceneapp 内部命名:聊天发送边界里的 usage slot 提取已统一改成 `service_scene` 语义,sceneapp current seeded/mock 目录的展示能力摘要也已改成 `agent_turn` / 本地工作区表述,避免 current 实现继续把内部变量写成“云场景” -- sceneapp current service-scene 入口:当前 seeded/mock 目录不再依赖 `entryBindings.bindingFamily = cloud_scene` 才能走本地场景执行;planner 会在 `agent_turn` current 目录下按 linked service skill / scene key 继续产出 `open_service_scene_session` -- sceneapp 展示层:`presentation/product` 与 SceneApps 页面当前测试夹具、组合步骤、入口绑定和执行摘要默认都已切到 `agent_turn`;`cloud_scene` 不再作为 current UI 文案映射保留在展示层 -- `serviceSkills / skillCatalog` 类型面:公开 catalog/item/execution 类型当前只暴露 `agent_turn / client_default` 等 current 值;`cloud_scene / cloud_required` 仅再保留为 compat 输入类型与解析层归一化逻辑,避免前台 current consumer 继续把旧云执行名当作常规值处理 -- 聊天入口测试夹具:`workspaceEntry / AppPageContent / slash preflight / scene launch / send actions / EmptyState` 等 current fixture 已同步改成 `local_service_skill` 与 `agent_turn` 语义,避免测试继续给旧云执行命名续命 - -### 仍保留为 compat / 历史锚点 - -- `cloud-video-dubbing` -- `cloud_scene` -- `executionLocation = cloud_required` -- `launch_cloud_scene` / `open_cloud_scene_session` - -这些字段当前仍存在于历史 skill id、compat projection、sceneapp 规划与测试中,用于兼容历史目录和旧数据,不再代表 current 执行边界;其中 current seeded package 已不再主动产出 `cloud_scene / cloud-scene-instant`,sceneapp current planner 也不再主动写出 `service_scene_launch.kind = cloud_scene`。 - -## 下一步 - -- 等服务端进程完成 `limecore` 文档与目录控制面实现后,按本计划里的“跨仓校验”重新扫描双仓术语一致性 -- 如果后续要继续做减法,优先清理 `sceneapp` 与 compat projection 中仍残留的 `cloud_scene` 历史命名,但这不阻塞当前客户端本地执行主链交付 diff --git a/docs/exec-plans/chrome-web-store-publish-plan.md b/docs/exec-plans/chrome-web-store-publish-plan.md deleted file mode 100644 index 2b19027b6..000000000 --- a/docs/exec-plans/chrome-web-store-publish-plan.md +++ /dev/null @@ -1,57 +0,0 @@ -# Chrome Web Store 发布计划 - -## 目标 - -将 `extensions/lime-chrome` 以当前可发布版本提交到 Chrome Web Store,并沉淀可复用的上架材料,避免后续版本更新再次依赖口头说明。 - -## 当前状态 - -- 已确认扩展目录:`extensions/lime-chrome` -- 已确认扩展版本:`0.4.0` -- 已生成上传包:`tmp/lime-chrome-0.4.0.zip` -- 已确认上传包 SHA-256:`059b6c17a8fea130d78709cd85e3cc16e687438da4ab4aab6bd0ed898bd3818b` -- 已发现安装页内预留商店链接:`https://chromewebstore.google.com/detail/lime-chrome/cpidmllglbedhpombjibeoalnafofipo` -- 公开链接当前未返回可见上架页,需在开发者后台确认该条目是草稿、私有条目还是无效占位 - -## 已完成 - -1. 检查扩展结构、`manifest.json`、README 与现有仓库脚本,确认仓库内没有现成的 Chrome 商店发布自动化 -2. 识别审核敏感权限与行为: - - `debugger` - - `clipboardRead` - - `notifications` - - `host_permissions: ` -3. 生成待上传 zip 产物,并记录哈希便于核对 -4. 补齐仓库内可复用的发布文案与隐私政策工件 -5. 生成首批 Chrome 商店截图草稿素材 - -## 阻塞项 - -1. 真正发布到 Chrome Web Store 需要进入 Google 开发者后台,属于高风险外部发布动作,必须先得到用户明确确认 -2. 若开发者后台尚未保存截图、分类、数据使用问卷或发布地区信息,仍需在后台继续补齐 -3. 若当前商店条目与安装页中的扩展 ID 不一致,需要在后台确认是否继续沿用旧条目或新建条目 -4. 隐私政策需要一个公网可访问 URL;当前仓库内文件已就绪,但尚未推送到公开可访问位置 - -## 下一步 - -1. 进入 Chrome Web Store 开发者后台,确认 `cpidmllglbedhpombjibeoalnafofipo` 对应条目状态 -2. 使用 `tmp/lime-chrome-0.4.0.zip` 上传扩展包 -3. 将 `extensions/lime-chrome/CHROME_WEB_STORE_SUBMISSION.md` 中的文案和权限说明填入后台 -4. 将 `extensions/lime-chrome/PRIVACY_POLICY.md` 对应的公开 URL 填入隐私政策字段 -5. 完成数据使用问卷、截图与可见性配置后提交审核或发布 - -## 进度日志 - -### 2026-04-20 - -- 补齐扩展 options 页中英文切换,并把缺配置状态改成明确的“需要配置 / Setup Required” -- 重新生成 `tmp/lime-chrome-0.4.0.zip`,剔除测试文件后记录正式 SHA-256 -- 将 Chrome 商店提交底稿与发布计划同步到 `0.4.0` 事实源 -- 将扩展 `icons/icon16.png`、`icon32.png`、`icon48.png`、`icon128.png` 全部替换为 `public/logo.png` 缩放版本,并重新打包上传产物 - -### 2026-04-13 - -- 完成本地打包与审核风险盘点 -- 确认需要先补齐发布文案与隐私政策,再进入发布后台 -- 生成 3 张 `1280x800` 商店截图草稿,位于 `tmp/chrome-store-assets/` -- 由于发布属于外部生产动作,暂未执行任何登录、上传或提交操作 diff --git a/docs/exec-plans/claude-code-agent-task-runtime-alignment-plan.md b/docs/exec-plans/claude-code-agent-task-runtime-alignment-plan.md deleted file mode 100644 index 3d3187a17..000000000 --- a/docs/exec-plans/claude-code-agent-task-runtime-alignment-plan.md +++ /dev/null @@ -1,106 +0,0 @@ -# Claude Code Agent Task Runtime 全面对齐计划 - -## 摘要 - -目标是把 Lime 的 agent 主链从“线程态 + 工具流 + 诊断信号”升级为对标 Claude Code 的“统一任务运行时”: - -- 主会话、子 agent、等待输入、完成结算都统一映射为可见任务。 -- 简单问题不再错误抬升为常驻 `MAIN TASK` 面板,只在复杂、长链路、可跟踪任务里显示当前进展。 -- 工具调用按批次聚合,必须产出中间过程结论,而不是只留下工具名。 -- `token usage` 与 `prompt cache` 在任务完成态和消息态都保持可见。 -- E2E 与 GUI smoke 后续统一以“任务是否创建、推进、完成”为核心断言。 - -## 关键改动 - -### 1. Agent Task Runtime 投影 - -- 新增统一任务投影模型,先覆盖 `main_session` 与 `subagent`。 -- 每次主会话回合都可以被投影成任务,但展示层增加“简单直答自动折叠”规则。 -- 当前回合的任务标题、状态、阶段、等待原因、工具批次摘要、子任务统计统一从现有 `thread_read / turns / items / messages / child_subagent_sessions` 归一投影。 - -### 2. 任务展示规则 - -- 仅在以下场景显示任务状态: - - 有工具批次或过程轨迹 - - 有子任务 - - 有排队 / 待补信息 / 等待确认 - - 回合失败或中断 -- 简单直接回答成功后默认折叠隐藏,不显示常驻 `MAIN TASK`。 -- 复杂任务也不再插入聊天主区大卡片,改挂输入区底栏弱提示 pill。 -- 任务状态 pill 保留: - - 主任务标题 - - 当前状态 - - 工具批次摘要 - - 子任务数量 - - 阻塞 / 排队信号 - -### 3. 工具批次与过程结论 - -- 复用现有工具批次聚合与工具过程摘要能力。 -- 任务状态条优先展示批次级结论,例如: - - 已探索项目 - - 已查看关键文件 - - 已检查页面 -- 当没有工具批次时,状态 pill 回退到等待原因、失败原因或当前阻塞摘要。 - -### 4. 回归与验收 - -- 前端单测覆盖: - - 简单直答完成后不显示任务状态条 - - 工具批次会显示输入区顶部弱提示条 - - 等待输入会显示等待态 - - 聊天主区仍保留消息级 `token usage` 与 `prompt cache` 摘要 -- 后续 GUI / E2E 继续对齐: - - 打开真实项目后触发分析请求 - - 断言复杂任务可见 - - 断言简单直答不出现误报任务卡 - -## 当前进度 - -- 2026-04-14:创建执行计划文件。 -- 2026-04-14:前端新增主任务投影工具与任务卡组件。 -- 2026-04-14:先前尝试把主任务直接插入聊天主区,已确认不符合 Claude Code 的任务层级。 -- 2026-04-14:主任务展示已回撤出聊天主区,并进一步收敛为输入区底栏弱提示 pill;完成态自动折叠。 -- 2026-04-14:补充任务投影、输入区与消息列表的定向回归测试。 -- 2026-04-14:定向 `vitest` 已通过,覆盖“复杂任务完成后不继续占据聊天主区,token usage / Prompt Cache 仍由消息结算区承载”。 -- 2026-04-14:定向 `eslint` 已通过;`verify:local` 仍被仓库现存无关问题阻塞,当前已知阻塞文件为 `src/components/agent/chat/utils/toolBatchGrouping.ts` 与 `src/components/memory/MemoryPage.tsx`。 -- 2026-04-14:`verify:gui-smoke` 已启动并推进到 headless Tauri 最终链接阶段,当前阻塞为首次临时 `CARGO_TARGET_DIR` 的 Rust/Tauri 大编译,尚未拿到 `http://127.0.0.1:3030/health` 就绪结果。 -- 2026-04-14:`verify:gui-smoke` 最终通过,确认默认 workspace、browser runtime、site adapter catalog 与 agent service skill entry 主链未回退。 -- 2026-04-14:浏览器 E2E 已验证复杂请求运行中只在输入区底栏显示状态 pill;完成后 pill 自动折叠消失,消息尾部继续显示 `token usage` 与缓存统计。 -- 2026-04-14:后端已落地“连续只读工具批次并发执行”,当前只对 Bash / PowerShell 的保守只读命令集启用并发,写操作与高风险命令继续串行。 -- 2026-04-14:补齐路径预检,避免在分析本地项目时盲猜不存在路径。 -- 2026-04-14:定位到 `tauri:dev*` 脚本把 `CARGO_TARGET_DIR` 写死为 `target`,会在 GUI 续测与 Rust 测试并行时放大构建锁竞争;现已改成“默认 target,但允许显式覆盖”。 -- 2026-04-14:继续收口“任务分工建议”视觉层级,首页空态与普通输入栏统一改为轻量胶囊提示,不再用大横幅抢占输入区主视觉。 -- 2026-04-14:按最新反馈去掉消息正文里的 `阶段结论` 标题壳;新消息直接显示结论正文,旧历史通过前端统一清洗兼容去标题。 -- 2026-04-14:继续追查 GUI 续测慢点,确认 `run-tauri-dev.mjs` / `run-tauri-profile.mjs` 会把相对 `CARGO_TARGET_DIR` 传进 `tauri dev`,在当前启动链下误写成 `src-tauri/src-tauri/target`;现已改成仓库根绝对路径下的 `src-tauri/target`,同时同步更新 README 说明。 - -## 本轮验证记录 - -### 已完成 - -- `npx vitest run "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/MessageList.test.tsx" "src/components/agent/chat/utils/agentTaskRuntime.test.ts"` -- `npx eslint "src/components/agent/chat/components/Inputbar/index.tsx" "src/components/agent/chat/components/Inputbar/components/InputbarComposerSection.tsx" "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/workspace/useWorkspaceInputbarSceneRuntime.tsx" "src/components/agent/chat/utils/agentTaskRuntime.ts"` - -### 进行中 - -- `npm run verify:gui-smoke` - - 当前表现:前端壳 `http://127.0.0.1:1420/` 可访问,但 `3030` DevBridge 尚未监听,页面仍处于 mock/fallback 状态。 - - 当前判断:阻塞源是 headless Tauri 首次完整构建与链接,不是任务 pill 回退或聊天主区重新渲染 task 卡片。 -- `npm run tauri:dev:headless` - - 当前表现:真实页面发送按钮 disabled 的直接原因不是输入组件,而是 `aster_agent_init` 因 DevBridge 不可达失败,页面落入 bridge cooldown / mock fallback。 - - 当前判断:根因之一不是单纯构建锁,而是开发脚本传入的相对 `CARGO_TARGET_DIR` 被 `tauri dev` 解析成 `src-tauri/src-tauri/target`,造成双层 target 与冷编译;脚本已改成绝对路径,正在重新拉起真实 bridge 做二次验证。 - -### 已完成补充验收 - -- 真实浏览器会话中已验证: - - 复杂请求运行中,聊天主区展示的是消息与过程结论,不再插入大 task 面板 - - 输入区底栏出现紧凑状态 pill,内容包含任务标题、状态与批次摘要 - - 任务完成后状态 pill 自动折叠隐藏 - - 消息结算区继续显示 `68.0K tokens` 与缓存统计 `缓存 62.3K(读 62.3K / 写 0)` - - 本轮真实交互后控制台未新增 bridge/runtime 错误,仍只剩浏览器模式的 i18n warning - -## 默认假设 - -- 本阶段优先修正产品感知与主路径可见性,不先重写底层 `session/thread/turn/item` 存储结构。 -- 媒体 / 插件任务暂不并入统一任务 runtime。 -- 真正的后端 `task event` 契约和 `thread_read.task_runs` 字段后续再补,当前先用前端投影收口主体验。 diff --git a/docs/exec-plans/cloud-commerce-user-center-boundary.md b/docs/exec-plans/cloud-commerce-user-center-boundary.md deleted file mode 100644 index 589bc65aa..000000000 --- a/docs/exec-plans/cloud-commerce-user-center-boundary.md +++ /dev/null @@ -1,25 +0,0 @@ -# 云端套餐与支付边界收口执行计划 - -## 主目标 - -把套餐购买、支付、账单、用量明细统一收敛到 `limecore` 用户中心网页;Lime 客户端只保留会话状态、当前套餐、积分余额、待支付提醒和跳转入口。 - -## 事实源 - -- `current`:`limecore` control-plane 与 `apps/user-center-web` 的 `/pricing`、`/billing`、`/subscription`、`/credits` -- `current`:Lime 客户端 `useOemCloudAccess` 负责登录态、权益摘要、API Key、支付回跳同步 -- `dead`:Lime 客户端内置套餐卡、充值包卡、用量图、账单表、直接创建购买订单的本地商业工作台 - -## 本轮进度 - -- 已将 Lime 设置页云端服务面收口为摘要卡 + 用户中心入口。 -- 已从客户端设置页移除本地套餐购买、积分充值、用量明细和账单表渲染。 -- 已从 `useOemCloudAccess` 返回面移除客户端直接创建套餐/充值订单的处理器。 -- 已在 `limecore` 用户中心 `/billing` 补齐用量与账单 tab,使用真实 usage / credits / billing dashboard 和真实 checkout。 -- 已将 `limecore` 用户中心 `/pricing` 文案从“模型价格”收敛为“套餐与价格”。 -- 已让 Lime 客户端入口直达 `/billing?tab=usage` 与 `/billing?tab=billing`,并让用户中心 tab 与 URL 查询参数同步。 -- 已从用户中心主导航移除独立“账单管理”菜单,保留 `/subscription` 直接路由作为旧链接可达页面,主导航收敛到 `/billing`。 - -## 下一刀 - -继续验证两个仓库的定向类型检查与回归测试;如果后续发现客户端仍存在套餐购买 UI 文案或旧 testid,应继续按 `dead` 删除,不再迁回客户端。 diff --git a/docs/exec-plans/creaoai-capability-authoring-p1a-plan.md b/docs/exec-plans/creaoai-capability-authoring-p1a-plan.md deleted file mode 100644 index e4bc19800..000000000 --- a/docs/exec-plans/creaoai-capability-authoring-p1a-plan.md +++ /dev/null @@ -1,152 +0,0 @@ -# CreoAI Capability Authoring P1A 执行计划 - -> 状态:P1A 完成,已通过 GUI smoke -> 创建时间:2026-05-05 -> 路线图来源:`docs/roadmap/creaoai/README.md`、`docs/roadmap/creaoai/coding-agent-layer.md`、`docs/research/pi-mono-coding-agent/README.md` -> 当前目标:实现 P1A 最小模块,让 Lime 能创建、存储、查看未验证 `Capability Draft`,并证明未验证草案不会进入默认 tool surface、不会自动注册、不会自动执行。 - -## 主目标 - -把 CreoAI 的 Coding Agent 启发收敛为 Lime current 主链里的 **Capability Authoring Agent / Skill Forge draft store**: - -```text -用户目标 - -> capability generation request - -> workspace-local draft store - -> unverified draft manifest - -> frontend API gateway - -> Workspace / Skills 工作台 draft review - -> 后续 P1B / P2 verification gate -``` - -固定宗旨: - -**不是永远限制能力;是永远限制未经验证、未经授权、不可审计的执行。** - -## 本轮范围 - -本轮做: - -1. 后端模块化 draft store。 - - 独立 Rust domain 模块,负责 manifest、路径 guard、文件清单和状态。 - - Tauri command 只做薄适配,不承载业务规则。 -2. 前端模块化 API 网关。 - - 新增 `src/lib/api/capabilityDrafts.ts`,组件不直接裸 `invoke`。 -3. 前端 UI 最小 review surface。 - - 优先接到现有 `SkillsWorkspacePage` 或相邻 feature 模块。 - - 展示 draft 名称、目标、状态、权限摘要、文件清单和“未验证不可运行”。 -4. 测试与 smoke。 - -- 后端路径 guard / manifest 单测。 -- 前端 API normalization 单测。 -- UI 状态回归:unverified draft 不显示运行/注册动作。 -- 契约检查:前端调用、Rust 注册、治理目录册、mock 保持一致。 - -本轮不做: - -1. 不实现完整 Coding Agent。 -2. 不实现 verification gate。 -3. 不注册 workspace-local skill。 -4. 不接 automation job。 -5. 不开放 full shell、依赖安装或外部写操作。 -6. 不新增平行 runtime、scheduler、evidence pack。 - -## 模块边界 - -### 后端 - -推荐结构: - -```text -src-tauri/src/commands/capability_draft_cmd.rs -src-tauri/src/services/capability_draft_service.rs -``` - -设计原则: - -1. `capability_draft_cmd.rs` 只负责 Tauri 参数 / 返回值适配。 -2. `capability_draft_service.rs` 负责业务规则、路径 guard、manifest 读写。 -3. 文件事实源暂定 workspace-local:`.lime/capability-drafts//manifest.json`。 -4. 写入范围必须限制在 draft root 内,不允许路径逃逸。 -5. 状态首期只允许 `unverified / failed_self_check`,不暴露运行能力。 - -### 前端 - -推荐结构: - -```text -src/lib/api/capabilityDrafts.ts -src/features/capability-drafts/ - domain/ - components/ - CapabilityDraftPanel.tsx -``` - -设计原则: - -1. API 网关统一封装命令名、参数与 normalization。 -2. domain 模块负责状态文案、权限文案和按钮可见性。 -3. 组件只做展示与用户操作,不拼接命令参数。 -4. UI 作为工作台信息面板,不做独立花哨页面。 -5. `unverified` 状态只允许查看、继续修复、丢弃;不允许运行和创建任务。 - -## 分阶段实施 - -### P1A-0:盘点与落 plan - -- [x] 新增本执行计划。 -- [x] 盘点现有 skill scaffold、Skills 工作台、Tauri command 注册、mock 和治理目录册。 -- [x] 确认不复用 `create_skill_scaffold_for_app`,新增独立 capability draft 命令,避免未验证 draft 进入 Skill reload 主链。 - -### P1A-1:后端 draft store - -- [x] 新增 manifest 类型和状态枚举。 -- [x] 新增 draft root 路径解析与 path escape guard。 -- [x] 新增 create/list/get 命令。 -- [x] 新增 Rust 单测。 - -### P1A-2:前端 API 与 domain - -- [x] 新增 `capabilityDraftsApi`。 -- [x] 新增状态 / 权限 / 可操作性 domain helper。 -- [x] 新增 API normalization 单测。 - -### P1A-3:Workspace UI review - -- [x] 在 Skills 工作台或相邻模块加入 draft review panel。 -- [x] 展示 `unverified` 隔离语义。 -- [x] 补 UI 回归测试。 - -### P1A-4:试跑与验收 - -- [x] 用 Rust service 定向测试创建一个只读 draft。 -- [x] 确认 manifest 与文件清单写入 draft root。 -- [x] 确认 UI 能看到 draft。 -- [x] 确认未验证 draft 不进入默认 tool surface。 -- [x] 通过 DevBridge 真实调用 `capability_draft_create/list/get`。 -- [x] 运行定向测试、`npm run test:contracts`。 -- [x] `npm run verify:gui-smoke` 全绿通过。 - -## 验收标准 - -1. 能创建一个 `unverified` capability draft。 -2. draft manifest 包含目标、来源、权限摘要、文件清单和状态。 -3. 路径逃逸被拒绝。 -4. 未验证 draft 不可运行、不可注册、不可绑定 automation job。 -5. 前后端通过单一 API / command 主链连接。 -6. 契约检查通过。 - -## 执行记录 - -### 2026-05-05 - -- 已创建执行计划,固定本轮只做 P1A draft store + review surface,不进入 P2/P3/P4。 -- 已完成后端模块:`capability_draft_service` 作为文件事实源,`capability_draft_cmd` 只做 Tauri 薄适配,新增 `capability_draft_create/list/get`。 -- 已完成前端模块:`capabilityDraftsApi`、`CapabilityDraftPanel` 与 presentation helper,接入 `SkillsWorkspacePage` 右侧工作台。 -- 已同步命令边界:`runner.rs`、DevBridge dispatcher、`agentCommandCatalog.capabilityDraftCommands`、`mockPriorityCommands` 的 bridge-truth 列表、`defaultMocks`。 -- 已试跑模块功能:Rust 定向测试真实创建 draft root、写入 `SKILL.md` 与 `manifest.json`、list/get 回读,并覆盖路径逃逸拒绝。 -- 已验证:前端定向测试 36 个通过,`cargo test ... capability_draft` 通过,`npm run test:contracts` 通过,`npm run typecheck` 通过,`cargo fmt --check` 通过。 -- 已通过 DevBridge smoke:在临时 workspace 下真实调用 `capability_draft_create/list/get`,生成 `unverified` draft,落盘 `SKILL.md` 与 `workflow/README.md`,list/get 回读一致。 -- 首次执行 `npm run verify:gui-smoke` 时,前序 `bridge health`、`workspace-ready`、`browser-runtime`、`site-adapters`、`agent-service-skill-entry`、`agent-runtime-tool-surface`、`agent-runtime-tool-surface-page` 已通过;当时失败在既有 `smoke:knowledge-gui` 的“知识库总览加载”等待,页面仍停留首页,未命中本轮新增的 Capability Draft 命令、mock 或 Skills 工作台 review surface。 -- 已定向复跑 `npm run smoke:knowledge-gui -- --app-url http://127.0.0.1:1420/ --health-url http://127.0.0.1:3030/health --invoke-url http://127.0.0.1:3030/invoke --timeout-ms 600000 --interval-ms 1000` 并通过;前次失败判断为运行中前端 / Tauri 会话抖动,不需要修改知识库代码。 -- 已重跑 `npm run verify:gui-smoke` 并全绿通过,P1A 达到 Lime GUI 产品交付门槛。 diff --git a/docs/exec-plans/creaoai-capability-discovery-p3b-plan.md b/docs/exec-plans/creaoai-capability-discovery-p3b-plan.md deleted file mode 100644 index 3a58851fd..000000000 --- a/docs/exec-plans/creaoai-capability-discovery-p3b-plan.md +++ /dev/null @@ -1,162 +0,0 @@ -# CreoAI Capability Discovery P3B 执行计划 - -> 状态:完成 -> 创建时间:2026-05-05 -> 前置计划:`docs/exec-plans/creaoai-capability-registration-p3-plan.md` -> 路线图来源:`docs/roadmap/creaoai/implementation-plan.md`、`docs/aiprompts/skill-standard.md`、`docs/aiprompts/commands.md` -> 当前目标:让 P3A 已注册到当前 workspace 的 Agent Skill 包可被产品层发现和审计,但仍不进入默认 runtime tool surface。 - -## 主目标 - -把 P3A 的文件注册事实推进到最小可见目录闭环: - -```text -/.agents/skills// - -> require .lime/registration.json provenance - -> inspect Agent Skills package - -> workspace registered skill catalog projection - -> Skills 工作台只读展示 - -> 后续 runtime gate / Query Loop binding -``` - -固定宗旨: - -**不是永远限制能力;是永远限制未经验证、未经授权、不可审计的执行。** - -## 本轮最小切口 - -本轮只做 **workspace-local registered skill discovery**: - -1. 后端新增 workspace 显式入参的已注册能力发现命令。 -2. 只扫描 `/.agents/skills`,不再依赖进程 `cwd`。 -3. 只返回带 `.lime/registration.json` 的 P3A 注册能力,不把任意项目 skill 都混进 CreoAI 生成链。 -4. 返回 Agent Skills 标准检查摘要、资源摘要、权限摘要、来源 draft / verification report。 -5. 前端 Skills 工作台展示“已注册但待运行接入”的只读卡片。 - -本轮明确不做: - -1. 不调用 `AsterAgentState::reload_lime_skills()`。 -2. 不修改 `get_local_skills_for_app` 的默认语义。 -3. 不把 workspace generated skill 合并进 `useSkills("lime")` 的已安装方法列表。 -4. 不展示“立即运行 / 自动化 / 继续这套方法”入口。 -5. 不接 `agent_runtime_submit_turn`、Query Loop、`tool_runtime` 或 automation job。 -6. 不解决 P4 Managed Objective 续跑。 - -## 为什么不用现有 local skills 列表直接承接 - -当前 `SkillService::get_catalog_roots(AppType::Lime)` 依赖: - -```text -app_paths::resolve_project_skills_dir() - -> std::env::current_dir() - -> cwd/.agents/skills -``` - -但 P3A 注册位置是: - -```text -/.agents/skills/ -``` - -因此如果直接扩 `get_local_skills_for_app`,会把“当前前端项目 workspace”与“后端进程 cwd”继续混在一起,还可能把 generated skill 误投进默认运行面。P3B 第一刀先新增独立 discovery 命令,等目录投影、权限和 UI 语义稳定后,再进入 runtime binding。 - -## 安全规则 - -1. **显式 workspaceRoot**:入参必须是存在的绝对目录。 -2. **registered-only**:目录必须同时包含 `SKILL.md` 与 `.lime/registration.json`。 -3. **不跟随 symlink**:扫描到 symlink 目录直接拒绝,避免通过目录投影读取 workspace 外内容。 -4. **不执行文件**:只读 `SKILL.md`、registration metadata 和包资源摘要。 -5. **不信任元数据路径**:返回真实扫描到的目录,同时保留 registration summary 作为 provenance。 -6. **默认不可运行**:返回对象必须显式标记 `launchEnabled=false` 与 runtime gate 提示。 - -## 实施步骤 - -### P3B-0:计划与边界 - -- [x] 新增本执行计划。 -- [x] 明确本轮只做 registered skill discovery,不做 runtime binding。 - -### P3B-1:后端 discovery service - -- [x] 新增 `ListWorkspaceRegisteredSkillsRequest`。 -- [x] 新增 `WorkspaceRegisteredSkillRecord` DTO。 -- [x] 新增 `list_workspace_registered_skills(...)` 服务函数。 -- [x] 只扫描 `/.agents/skills`。 -- [x] 只返回包含 `.lime/registration.json` 的标准 Skill 包。 -- [x] 补 Rust 单测:空目录、无 registration 忽略、注册后可发现、相对 workspaceRoot 拒绝、symlink 逃逸拒绝。 - -### P3B-2:命令边界 - -- [x] 新增 Tauri command `capability_draft_list_registered_skills`。 -- [x] 同步 `runner.rs`、DevBridge dispatcher。 -- [x] 同步 `agentCommandCatalog`、`mockPriorityCommands`、`defaultMocks`。 -- [x] 运行 `npm run test:contracts`。 - -### P3B-3:前端 API / UI - -- [x] 扩展 `capabilityDraftsApi.listRegisteredSkills(...)` 与 normalization。 -- [x] 新增 Workspace 已注册能力只读面板。 -- [x] Skills 工作台在 Capability Draft 隔离区附近展示已注册能力。 -- [x] 注册成功后刷新已注册能力面板。 -- [x] 补 API、组件、Skills 工作台回归测试。 - -### P3B-4:试跑与验收 - -- [x] 用 DevBridge 走 `create -> verify -> register -> list_registered_skills`。 -- [x] 确认返回 provenance、标准合规与 `launchEnabled=false`。 -- [x] 确认 UI 展示“已注册但待运行接入”,没有运行或自动化按钮。 -- [x] 根据 GUI 工作台改动补 `npm run verify:gui-smoke`。 - -## 验收标准 - -1. 不存在 `.agents/skills` 时返回空数组。 -2. 普通 project skill 没有 `.lime/registration.json` 时不会进入 CreoAI registered 列表。 -3. P3A 注册后的 skill 能被显式 workspaceRoot 发现。 -4. discovery 结果包含来源 draft、verification report、权限摘要和 Agent Skills 标准状态。 -5. discovery 结果显式 `launchEnabled=false`。 -6. UI 不出现“立即运行 / 自动化 / 继续这套方法”入口。 -7. 命令契约、DevBridge、mock、文档和 GUI smoke 保持一致。 - -## 执行记录 - -### 2026-05-05 - -- 已创建 P3B 执行计划,确认第一刀只补 workspace-local registered skill discovery。 -- 已确认 P3B 不复用 `get_local_skills_for_app` 的 cwd 语义,也不把 generated skill 直接混进默认已安装方法列表。 - -### 2026-05-06 - -- 已完成后端 `list_workspace_registered_skills(...)`、Tauri command、DevBridge dispatcher、前端 API 网关、默认 mock、治理目录册与 Skills 工作台只读面板。 -- 已把 discovery 语义固定为 `workspaceRoot -> .agents/skills -> .lime/registration.json provenance -> read-only projection`,结果显式返回 `launchEnabled=false` 与 runtime gate 文案。 -- Rust 默认 feature 定向测试曾因 `local-sensevoice / sherpa-onnx-sys` 冷编译阻塞中止;已改用无语音特性的定向命令补齐: - - `CARGO_TARGET_DIR="src-tauri/target-codex-p3-novoice" cargo test --manifest-path "src-tauri/Cargo.toml" --no-default-features capability_draft` - - 结果:`16` 个 capability draft 测试通过,`1203` 个测试按过滤器跳过。 -- 前端定向回归通过: - - `npm test -- "src/lib/api/capabilityDrafts.test.ts" "src/features/capability-drafts/domain/capabilityDraftPresentation.test.ts" "src/features/capability-drafts/components/CapabilityDraftPanel.test.tsx" "src/features/capability-drafts/components/WorkspaceRegisteredSkillsPanel.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - 结果:`5` 个文件、`48` 个测试通过。 -- 命令契约通过: - - `npm run test:contracts` - - 结果:command contracts、harness contracts、modality runtime contracts 与 cleanup report contract 均通过。 -- DevBridge 真实链路通过: - - `capability_draft_create -> capability_draft_verify -> capability_draft_register -> capability_draft_list_registered_skills` - - 临时 workspace:`/tmp/lime-creaoai-p3b-smoke.3KFuJW` - - 结果:发现 `capability-213ea44ef8d9`,`launchEnabled=false`,runtime gate 文案存在。 -- GUI smoke 通过: - - `npm run verify:gui-smoke -- --reuse-running --timeout-ms 300000` - - 覆盖 DevBridge health、workspace ready、browser runtime、site adapters、service skill entry、runtime tool surface、Knowledge GUI 与 Design Canvas smoke。 - -## P3B 收口结论 - -P3B registered discovery 已达到本计划可交付门槛:P3A 注册后的 workspace-local Skill 包可以被当前 workspace 明确发现、审计来源、展示权限与标准检查,但仍不会进入默认 tool surface,也不会暴露运行、自动化或继续执行入口。 - -下一阶段应单独开计划推进 runtime binding: - -```text -registered discovery - -> workspace-scoped catalog binding - -> Query Loop metadata - -> tool_runtime 授权裁剪 - -> artifact / evidence 调用记录 -``` - -在这条后续链路完成前,`registered` 与 `discovered` 只能表示“可审计存在”,不能表示“可自动运行”。 diff --git a/docs/exec-plans/creaoai-capability-registration-p3-plan.md b/docs/exec-plans/creaoai-capability-registration-p3-plan.md deleted file mode 100644 index 1d7d42eb4..000000000 --- a/docs/exec-plans/creaoai-capability-registration-p3-plan.md +++ /dev/null @@ -1,146 +0,0 @@ -# CreoAI Capability Registration P3 执行计划 - -> 状态:P3A 完成;已通过 DevBridge 注册链路验证与 GUI smoke -> 创建时间:2026-05-05 -> 前置计划:`docs/exec-plans/creaoai-capability-authoring-p1a-plan.md`、`docs/exec-plans/creaoai-capability-verification-p1b-plan.md` -> 路线图来源:`docs/roadmap/creaoai/implementation-plan.md`、`docs/aiprompts/skill-standard.md` -> 当前目标:把已通过 verification gate 的 `Capability Draft` 注册为当前 workspace 的本地 Agent Skill 包,但仍不接运行、不接自动化、不进入默认 tool surface。 - -## 主目标 - -把 P1B 的 `verified_pending_registration` 推进到最小可追踪注册闭环: - -```text -workspace-local capability draft - -> verified_pending_registration - -> registration gate - -> /.agents/skills// - -> draft manifest lastRegistration - -> Skills 工作台 review surface - -> 后续 P3B / P4 runtime binding -``` - -固定宗旨: - -**不是永远限制能力;是永远限制未经验证、未经授权、不可审计的执行。** - -## 本轮范围 - -本轮做: - -1. 后端最小 registration gate。 - - 新增 `capability_draft_register` 命令。 - - 只允许 `verified_pending_registration` 状态进入注册。 - - 注册前再次校验 draft 文件清单完整性与 Agent Skills 标准合规。 - - 将 draft 生成文件复制到 `/.agents/skills//`。 - - 写入 draft 侧 `registration/latest.json` 和 manifest `lastRegistration`。 -2. 前端 API / domain / UI 接入。 - - `capabilityDraftsApi.register(...)` 统一封装命令。 - - UI 只在 `verified_pending_registration` 显示“注册到当前 Workspace”。 - - 注册后展示目录与来源,不显示“立即运行 / 自动化”。 -3. 命令治理与 mock 同步。 - - Rust 注册、DevBridge dispatcher、`agentCommandCatalog`、`mockPriorityCommands`、`defaultMocks` 保持一致。 -4. 定向验证。 - -本轮不做: - -1. 不调用 `AsterAgentState::reload_lime_skills()`。 -2. 不修改全局 seeded skill 或用户级 Lime skill 目录。 -3. 不把已注册 skill 自动放进默认 tool surface。 -4. 不新增 runtime binding、scheduler、automation job 或 Managed Objective。 -5. 不执行 draft 中的脚本,不做 dry-run、shell、依赖安装或外部写操作。 -6. 不解决现有 `resolve_project_skills_dir()` 依赖进程 cwd 的完整 catalog 可见性问题;这属于 P3B discovery/runtime binding。 - -## P3A / P3B 边界 - -本计划只交付 **P3A:workspace-local file registration**。 - -```text -P3A: verified draft -> workspace .agents/skills package -> provenance -P3B: workspace catalog discovery -> skill launch metadata -> tool_runtime surface -P4 : managed execution / automation / objective loop -``` - -这样拆分的原因: - -1. registration 是文件与来源事实,不等于可运行能力。 -2. catalog discovery 需要解决 workspace 选择、进程 cwd、SkillService root 和 runtime session 的一致性,不能顺手塞进复制文件命令里。 -3. runtime binding 必须回到 `agent_runtime_submit_turn -> Query Loop -> tool_runtime -> artifact/evidence` 主链,不能让 `capability_draft_register` 变成第二套执行入口。 - -## 注册规则 - -1. **状态前置**:仅允许 `verified_pending_registration`。 -2. **标准前置**:`SKILL.md` 必须通过 Agent Skills 标准检查;P1B 的静态 gate 通过不等于标准合规。 -3. **路径前置**:只复制 manifest `generatedFiles` 清单内的相对路径,继续拒绝绝对路径、`..`、平台相关路径与 symlink。 -4. **目标位置**:只写当前 `workspaceRoot/.agents/skills//`。 -5. **冲突处理**:目标目录已存在时拒绝,不覆盖、不合并、不删除用户已有目录。 -6. **来源记录**:注册摘要必须包含 draft id、verification report id、权限摘要、文件数量、注册时间与目标目录。 -7. **可见性限制**:注册完成只表示“workspace 中已有标准 skill 包”,不表示已经进入运行时工具面。 - -## 实施步骤 - -### P3-0:计划与边界 - -- [x] 新增本执行计划。 -- [x] 明确本轮只做 P3A registration,不做 P3B discovery/runtime binding。 - -### P3-1:后端 registration service - -- [x] 新增 registration summary / request / result 类型。 -- [x] 新增注册目录派生、目标路径 guard、文件复制与 provenance 写入。 -- [x] 新增 `register_capability_draft(...)` 服务函数。 -- [x] 注册后更新 manifest 状态为 `registered`。 -- [x] 补 Rust 单测:未验证拒绝、验证失败拒绝、标准不合规拒绝、标准草案可注册、目标目录冲突拒绝。 - -### P3-2:命令边界 - -- [x] 新增 Tauri command `capability_draft_register`。 -- [x] 同步 `runner.rs`、DevBridge dispatcher。 -- [x] 同步 `agentCommandCatalog`、`mockPriorityCommands`、`defaultMocks`。 -- [x] 运行 `npm run test:contracts`。 - -### P3-3:前端 API / UI - -- [x] 扩展 `capabilityDraftsApi.register(...)` 与 normalization。 -- [x] 扩展 domain helper:`canRegisterCapabilityDraft`、注册摘要展示。 -- [x] 在 `CapabilityDraftPanel` 展示注册按钮和注册目录。 -- [x] 补 API、domain、UI 回归测试。 - -### P3-4:试跑与验收 - -- [x] 用 DevBridge 创建完整标准 draft,验证通过后注册。 -- [x] 通过 Rust service 定向测试确认生成 `/.agents/skills//SKILL.md`。 -- [x] 通过 Rust service 定向测试确认 manifest 进入 `registered` 并记录 `lastRegistration`。 -- [x] 通过前端回归测试确认 UI 仍没有运行或自动化入口。 -- [x] 根据改动风险补 `npm run verify:gui-smoke`。 - -## 验收标准 - -1. 未验证或验证失败 draft 无法注册。 -2. P1B 静态 gate 通过但 Agent Skills 标准不合规的 draft 仍无法注册。 -3. 标准合规 draft 能注册到当前 workspace 的 `.agents/skills`。 -4. 注册动作不会覆盖已有 skill 目录。 -5. 注册后 manifest 和 `registration/latest.json` 能追踪来源、权限和 verification report。 -6. UI 能看到注册结果,但没有运行、自动化或外部写入口。 -7. 命令契约、mock、文档与 GUI smoke 保持一致。 - -## 执行记录 - -### 2026-05-05 - -- 已创建 P3A 执行计划,明确本轮只做 workspace-local file registration。 -- 已确认 `create_skill_scaffold_for_app` 是人工 scaffold 主链,不复用为 draft registration;P3A 使用独立 `capability_draft_register`,避免未验证 / 未授权能力进入 Skill reload 或运行时主链。 -- 已完成后端 P3A registration gate:只允许 `verified_pending_registration`,注册前复核 manifest 文件完整性与 Agent Skills 标准,复制到当前 workspace 的 `.agents/skills//`,并写入 draft / registered skill 两侧 provenance。 -- 已完成命令边界同步:`capability_draft_register` 已接入 Tauri command、`runner.rs`、DevBridge dispatcher、`agentCommandCatalog`、`mockPriorityCommands`、`defaultMocks` 与前端 API 网关。 -- 已完成 Skills 工作台最小 UI:只有 `verified_pending_registration` 显示“注册到 Workspace”,注册成功只展示目录与来源提示,仍不展示立即运行、自动化或 runtime binding 入口。 -- 校验通过:`cargo fmt --manifest-path src-tauri/Cargo.toml --check`。 -- 校验通过:`CARGO_TARGET_DIR=src-tauri/target-codex-p3 cargo test --manifest-path src-tauri/Cargo.toml capability_draft`,11 个 capability draft 定向测试通过。 -- 校验通过:`npm test -- src/lib/api/capabilityDrafts.test.ts src/features/capability-drafts/domain/capabilityDraftPresentation.test.ts src/features/capability-drafts/components/CapabilityDraftPanel.test.tsx src/components/skills/SkillsWorkspacePage.test.tsx`,4 个文件 42 个测试通过。 -- 校验通过:`npm run test:contracts`,命令契约、Harness 契约、modality runtime contracts 与 cleanup report contract 通过。 -- 已做稳健性补强:注册复制使用目标目录独占创建,避免 race 下覆盖或合并已有 workspace skill 目录;manifest 写入失败时同步清理 draft 侧 registration summary,避免留下不可达 provenance。 -- GUI smoke 首次尝试时,`smoke:knowledge-gui` 点击旧 `ariaLabel=知识库` 失败,当前导航按钮实际为 `灵感库` / `项目资料` 等;这是 Knowledge 导航 smoke 断言与当前 UI 命名不一致,非 P3A Capability Draft 注册链路改动。 -- 已收口 Knowledge GUI smoke 导航断言:`scripts/knowledge-gui-smoke.mjs` 从旧的 `知识库` 导航切到当前 `项目资料` 入口,并更新 Agent 页资料使用文案断言。 -- 校验通过:`npm run smoke:knowledge-gui -- --app-url http://127.0.0.1:1420/ --health-url http://127.0.0.1:3030/health --invoke-url http://127.0.0.1:3030/invoke --timeout-ms 300000 --interval-ms 1000`。 -- 校验通过:`npm run verify:gui-smoke -- --reuse-running --timeout-ms 300000`,完整 GUI smoke 通过。 -- DevBridge 链路验证通过:通过 `capability_draft_create -> capability_draft_verify -> capability_draft_register` 创建标准 draft,验证结果 `passed`,注册后 manifest 状态为 `registered`,并确认生成 `.agents/skills//SKILL.md` 与 `.lime/registration.json`。 -- 已知非本轮阻塞:`npm run typecheck` 仍受 `src/lib/layered-design/imageTasks.ts` 既有类型问题影响,错误为 `LayeredDesignImageRuntimeContract` 不能赋给 `Record`;本计划不顺手修 layered-design 旁支。 diff --git a/docs/exec-plans/creaoai-capability-verification-p1b-plan.md b/docs/exec-plans/creaoai-capability-verification-p1b-plan.md deleted file mode 100644 index 3d50bb6ca..000000000 --- a/docs/exec-plans/creaoai-capability-verification-p1b-plan.md +++ /dev/null @@ -1,126 +0,0 @@ -# CreoAI Capability Verification P1B 执行计划 - -> 状态:P1B 完成,已通过 GUI smoke -> 创建时间:2026-05-05 -> 前置计划:`docs/exec-plans/creaoai-capability-authoring-p1a-plan.md` -> 路线图来源:`docs/roadmap/creaoai/implementation-plan.md`、`docs/roadmap/creaoai/coding-agent-layer.md`、`docs/roadmap/creaoai/architecture-review.md` -> 当前目标:在 P1A `Capability Draft` 事实源上补最小 verification gate,让草案可以被结构化检查并进入 `verification_failed` 或 `verified_pending_registration`,但仍不注册、不运行、不接自动化。 - -## 主目标 - -把 P1A 的“未验证草案可见”推进到“草案可以被门禁检查”: - -```text -workspace-local capability draft - -> static verification gate - -> verification report - -> manifest status update - -> Skills 工作台 review surface - -> 后续 P3 registration -``` - -固定宗旨: - -**不是永远限制能力;是永远限制未经验证、未经授权、不可审计的执行。** - -## 本轮范围 - -本轮做: - -1. 后端最小 verification gate。 - - 新增 `capability_draft_verify` 命令。 - - 只做结构、contract、权限声明、危险 token 静态扫描和 fixture 存在性检查。 - - 输出 `verification/latest.json` 报告,并同步 manifest 状态。 -2. 前端 API / domain / UI 接入。 - - `capabilityDraftsApi.verify(...)` 统一封装命令。 - - UI 暴露“运行验证”按钮,但不暴露“运行草案 / 注册方法 / 自动化”。 - - 展示最近验证摘要与失败建议。 -3. 命令治理与 mock 同步。 - - Rust 注册、DevBridge、`agentCommandCatalog`、`mockPriorityCommands`、`defaultMocks` 保持一致。 -4. 定向验证。 - -本轮不做: - -1. 不执行用户生成脚本。 -2. 不开放 shell、安装依赖、联网 dry-run 或外部写操作。 -3. 不注册 workspace-local skill。 -4. 不把 `verified_pending_registration` 草案放进 tool surface。 -5. 不新增 evidence pack 主链,只保留可后续消费的 verification report 文件。 - -## 最小检查矩阵 - -| 检查 | 目标 | 失败后状态 | -| ------------------------ | --------------------------------------------------------------------- | --------------------- | -| `package_structure` | `SKILL.md` 存在,manifest 文件清单与磁盘一致 | `verification_failed` | -| `skill_readme_quality` | `SKILL.md` 内容不是空壳,包含可读任务说明 | `verification_failed` | -| `input_contract` | 存在 `contract/input.schema.json` 或等价输入 schema | `verification_failed` | -| `output_contract` | 存在 `contract/output.schema.json` 或等价输出 schema | `verification_failed` | -| `permission_declaration` | 权限摘要非空,并能解释只读 / 草案内写入边界 | `verification_failed` | -| `static_risk_scan` | 未出现删除、发布、付款、依赖安装、任意 shell、HTTP 写操作等危险 token | `verification_failed` | -| `fixture_presence` | 至少存在 `tests/` 或 `examples/` 作为后续 dry-run 输入 | `verification_failed` | - -通过后状态只到: - -```text -verified_pending_registration -``` - -它表示“可以进入 P3 注册设计”,不表示现在已经能运行。 - -## 实施步骤 - -### P1B-0:计划与边界 - -- [x] 新增本执行计划。 -- [x] 确认 P1B 只做静态 gate,不做注册和执行。 - -### P1B-1:后端 verification service - -- [x] 扩展 draft 状态:`verification_failed / verified_pending_registration`。 -- [x] 新增 verification report 类型、summary、check item。 -- [x] 新增 `verify_capability_draft(...)` 服务函数。 -- [x] 写入 `verification/latest.json` 并更新 manifest。 -- [x] 补 Rust 单测:通过、缺 contract 失败、危险 token 失败。 - -### P1B-2:命令边界 - -- [x] 新增 Tauri command `capability_draft_verify`。 -- [x] 同步 `runner.rs`、DevBridge dispatcher。 -- [x] 同步 `agentCommandCatalog`、`mockPriorityCommands`、`defaultMocks`。 -- [x] 运行 `npm run test:contracts`。 - -### P1B-3:前端 API / UI - -- [x] 扩展 `capabilityDraftsApi.verify(...)` 与 normalization。 -- [x] 扩展 domain helper:状态文案、能否验证、验证摘要。 -- [x] 在 `CapabilityDraftPanel` 展示验证按钮与最近结果。 -- [x] 补 API、domain、UI 回归测试。 - -### P1B-4:试跑与验收 - -- [x] 用 DevBridge 创建一个完整 draft 并验证通过。 -- [x] 用 DevBridge 创建一个危险 draft 并验证失败。 -- [x] 运行前后端定向测试。 -- [x] 根据改动风险补 `npm run verify:gui-smoke` 或记录原因。 - -## 验收标准 - -1. 完整草案能进入 `verified_pending_registration`。 -2. 缺 input/output contract 的草案会进入 `verification_failed`。 -3. 出现危险 token 的草案会进入 `verification_failed`,并给出可修复建议。 -4. UI 能触发 verification gate 并刷新状态。 -5. 即使验证通过,也没有运行、注册或自动化入口。 -6. 命令契约、mock 与文档保持一致。 - -## 执行记录 - -### 2026-05-05 - -- 已完成后端 verification gate:`capability_draft_service` 扩展状态、report、check item 与 `verify_capability_draft(...)`,验证报告落到 `verification/latest.json`,manifest 同步 `lastVerification` 与 `verificationStatus`。 -- 已完成命令边界:新增 `capability_draft_verify`,同步 Tauri 注册、DevBridge dispatcher、`agentCommandCatalog.capabilityDraftCommands`、`mockPriorityCommands` 与 `defaultMocks`。 -- 已完成前端接入:`capabilityDraftsApi.verify(...)`、状态 / 验证摘要 domain helper、`CapabilityDraftPanel` 的“运行验证”按钮和最近验证摘要;验证通过后仍只显示“待注册”,没有运行、注册或自动化按钮。 -- 已通过 Rust 定向测试:`cargo test --manifest-path src-tauri/Cargo.toml capability_draft`,6 个 capability draft 测试通过。 -- 已通过前端定向测试:`npm test -- src/lib/api/capabilityDrafts.test.ts src/features/capability-drafts/domain/capabilityDraftPresentation.test.ts src/features/capability-drafts/components/CapabilityDraftPanel.test.tsx src/components/skills/SkillsWorkspacePage.test.tsx`,39 个测试通过。 -- 已通过契约与类型检查:`npm run test:contracts`、`npm run typecheck`、`cargo fmt --manifest-path src-tauri/Cargo.toml --check`。 -- 已通过 DevBridge smoke:完整草案验证后进入 `verified_pending_registration`;包含 `method: "POST"` 的危险草案验证后进入 `verification_failed`,失败项为 `static_risk_scan`。 -- 已通过 GUI smoke:`npm run verify:gui-smoke` 全绿,覆盖 DevBridge、workspace-ready、browser-runtime、site-adapters、agent-service-skill-entry、agent-runtime-tool-surface、agent-runtime-tool-surface-page 与 knowledge-gui。 diff --git a/docs/exec-plans/creaoai-completion-audit.md b/docs/exec-plans/creaoai-completion-audit.md deleted file mode 100644 index 6dd7328a0..000000000 --- a/docs/exec-plans/creaoai-completion-audit.md +++ /dev/null @@ -1,135 +0,0 @@ -# CREAO Roadmap Completion Audit - -> 状态:P0-P4 最小闭环完成审计通过 -> 日期:2026-05-06 -> 审计目标:确认 `docs/roadmap/creaoai/README.md` 与 `docs/roadmap/creaoai/implementation-plan.md` 中 CREAO-inspired 开发计划,已经收敛到 Lime current 主链,并具备完整、可验证、不过度扩展的 P0-P4 最小实现。 - -## 0. 审计结论 - -P0-P4 当前可以判定为 **最小可交付闭环完成**: - -```text -Capability Draft - -> verification gate - -> workspace-local registration - -> registered discovery - -> runtime binding readiness - -> Query Loop metadata - -> session-scoped tool_runtime authorization - -> ToolResult source metadata - -> Managed Job 草案 - -> automation owner evidence - -> completion audit input / summary - -> Harness UI / Workspace UI - -> evidence-gated Agent envelope / derived Agent card - -> workspace/team registered discovery sharing -``` - -关键判定: - -1. 没有新增平行 runtime、scheduler、queue、evidence、Marketplace 或 Agent card 存储表。 -2. 未验证 draft 不会进入默认 tool surface,也不会注册、运行或自动化。 -3. registered / discovered / readiness 只表示可审计存在和候选资格,不等于可调用。 -4. 真正调用必须经 `agent_runtime_submit_turn` + `workspace_skill_runtime_enable` + `SkillTool` session allowlist。 -5. `success` automation run 只能进入 completion audit input;`completed` 只能由 automation owner、Workspace Skill ToolCall 和 artifact / timeline evidence 共同判定。 -6. Agent envelope 是 Workspace 产品组合面,执行 owner 仍是 automation job / Managed Objective / runtime evidence 主链。 -7. 本轮额外修正了一个审计缺口:`evidencePackId` 单独存在不再让 Agent envelope 进入 `evidence_ready`,必须有 completed completion audit 且三项 evidence 齐全。 - -## 1. P0 文档与边界 - -| 要求 | 证据 | 状态 | 备注 | -| --- | --- | --- | --- | -| 研究和路线图落盘 | `docs/research/creaoai/README.md`、`docs/roadmap/creaoai/README.md`、`docs/roadmap/creaoai/implementation-plan.md` | 完成 | 已固定 CREAO pivot、组织 harness、Agent 产品模型和 Lime 差距。 | -| Skill Forge 不是 runtime | `docs/roadmap/creaoai/README.md`、`docs/roadmap/creaoai/coding-agent-layer.md`、`docs/roadmap/creaoai/architecture-review.md` | 完成 | 文档明确 build-time capability author 与 runtime owner 分离。 | -| generated capability 不能长期执行 | `docs/roadmap/creaoai/README.md`、`docs/exec-plans/creaoai-capability-authoring-p1a-plan.md` | 完成 | Draft 只能进入 verification / registration gate。 | -| 禁止 generated tools 平行 runtime | `docs/roadmap/creaoai/implementation-plan.md`、`docs/exec-plans/creaoai-managed-agent-envelope-p4-plan.md` | 完成 | P3E / P4 都回到 `agent_runtime_submit_turn`、automation、evidence 主链。 | - -## 2. P1 workspace-local skill scaffold - -| 要求 | 证据 | 状态 | 备注 | -| --- | --- | --- | --- | -| 创建 workspace-local Capability Draft | `src-tauri/src/services/capability_draft_service.rs:create_capability_draft`、`src-tauri/src/commands/capability_draft_cmd.rs`、`src/lib/api/capabilityDrafts.ts` | 完成 | 文件事实源为 `.lime/capability-drafts//manifest.json`。 | -| Draft 包含 `SKILL.md`、manifest、文件清单和权限摘要 | `CapabilityDraftManifest` / `CapabilityDraftRecord`、`create_capability_draft` 单测 | 完成 | P1A 创建时写入 draft root,路径 guard 拒绝逃逸。 | -| Workspace 可展示 draft 状态 | `src/features/capability-drafts/components/CapabilityDraftPanel.tsx`、`src/components/skills/SkillsWorkspacePage.tsx` | 完成 | UI 明确“未验证前不会注册,也不会自动运行”。 | -| 未验证 draft 不进默认 tool surface | `CapabilityDraftPanel` domain helper、P1A / P1B / P3A 执行计划验证记录 | 完成 | UI 无运行 / 自动化入口;后端注册也拒绝未验证状态。 | -| 从对话请求创建的边界 | `capability_draft_create` 已进入 command catalog / DevBridge / mock;当前产品入口仍是受控 draft store | 完成(最小闭环) | 未实现无限制 autonomous authoring agent;符合 P1A “不做完整 Coding Agent、先证明安全产生能力”的约束。 | - -## 3. P2 verification gate - -| 要求 | 证据 | 状态 | 备注 | -| --- | --- | --- | --- | -| 结构、contract、权限、风险、fixture 检查 | `src-tauri/src/services/capability_draft_service.rs:verify_capability_draft` | 完成 | 检查矩阵落为静态 gate,不执行用户脚本。 | -| 缺 contract 不能注册 | `verify_capability_draft_fails_without_contracts`、`register_capability_draft_rejects_verification_failed_draft` | 完成 | 状态进入 `verification_failed`。 | -| 危险 token / 权限不一致失败 | `verify_capability_draft_rejects_dangerous_tokens` | 完成 | 高风险外部写通过静态风险扫描阻断;后续放权必须走授权策略。 | -| 通过后进入 pending registration | `CapabilityDraftStatus::VerifiedPendingRegistration`、`verify_capability_draft_marks_complete_draft_pending_registration` | 完成 | 仍不代表可运行。 | -| verification 结果可消费 | `verification/latest.json`、manifest `lastVerification`、注册 provenance | 完成 | P3A 注册写入 verification report id。 | - -## 4. P3 registration / runtime binding - -| 阶段 | 要求 | 证据 | 状态 | -| --- | --- | --- | --- | -| P3A | 只注册 `verified_pending_registration` 到当前 workspace `.agents/skills` | `register_capability_draft`、`registration/latest.json`、`.lime/registration.json` | 完成 | -| P3A | 不覆盖已有目录、不修改全局 seeded skill、不运行 | `register_capability_draft_rejects_existing_skill_directory`、P3A plan 验证记录 | 完成 | -| P3B | 显式 `workspaceRoot` discovery,只读返回 provenance / 标准 / 权限 | `list_workspace_registered_skills`、`WorkspaceRegisteredSkillsPanel` | 完成 | -| P3B | `launchEnabled=false`,无运行 / 自动化入口 | `WorkspaceRegisteredSkillRecord.launchEnabled`、P3B tests / GUI smoke | 完成 | -| P3C | readiness projection 在 `agent_runtime_* / inventory` 主链下 | `agent_runtime_list_workspace_skill_bindings`、`runtime_skill_binding_service.rs:list_workspace_skill_bindings` | 完成 | -| P3C | `queryLoopVisible=false`、`toolRuntimeVisible=false`、`launchEnabled=false` | `runtime_skill_binding_service` DTO / tests | 完成 | -| P3D | `workspace_skill_bindings` 只进 Query Loop 只读 prompt | `workspace_skill_binding_prompt.rs`、`workspaceSkillBindingsMetadata.ts` | 完成 | -| P3D | 不打开 `allow_model_skills`,不注入 `SkillTool` registry | `harnessRequestMetadata.ts`、`runtime_turn.rs` tests | 完成 | -| P3E | `workspace_skill_runtime_enable` 显式启用当前 session | `runtime_skill_binding_service.rs:resolve_workspace_skill_runtime_enable`、`runtime_turn.rs` | 完成 | -| P3E | `SkillTool` 被裁剪到 `project:` / `` allowlist | `src-tauri/crates/agent/src/tools/skill_tool_gate.rs` | 完成 | -| P3E | ToolResult metadata 写回来源和授权 | `workspace_skill_source` / `workspace_skill_runtime_enable` metadata、SkillTool gate tests | 完成 | - -## 5. P4 managed execution / Agent envelope - -| 要求 | 证据 | 状态 | 备注 | -| --- | --- | --- | --- | -| 绑定 automation job,不新增 scheduler | `workspaceSkillAgentAutomationDraft.ts`、`SkillsWorkspacePage.tsx` | 完成 | 创建入口复用 `AutomationJobDialog` + `createAutomationJob`,默认暂停。 | -| payload 仍为 `agent_turn` | `buildWorkspaceSkillAgentAutomationInitialValues` | 完成 | `request_metadata.harness` 写入 `agent_envelope`、`managed_objective`、`workspace_skill_runtime_enable`。 | -| 支持暂停 / 恢复 | `WorkspaceRegisteredSkillsPanel.tsx` 调用 `updateAutomationJob(job.id, { enabled })` | 完成 | 不新增平行 pause state。 | -| app 重启后状态恢复或阻塞 | `WorkspaceRegisteredSkillsPanel` 每次加载复用 `getAutomationJobs()` 读取持久 job 事实 | 完成 | 恢复以 automation job storage 为事实源;失败显示 last_status / last_error。 | -| 失败可见步骤 / 原因 / 下一步 | `buildWorkspaceSkillManagedAutomationPresentation`、completion audit label | 完成 | Workspace 显示 blocked / paused / planned / verifying 文案;Harness 显示 audit blocking reasons。 | -| 产物 / timeline / evidence 可审计 | `runtime_evidence_pack_service.rs` | 完成 | `timeline.json` 保留 Workspace Skill ToolCall source metadata。 | -| automation owner evidence | `export_runtime_evidence_pack_with_owner_runs`、`runtime.json` / `artifacts.json` 的 `automationOwners` | 完成 | owner run、Agent envelope、Managed Objective、runtime enable 关系进入 evidence。 | -| completion audit input | `automationOwners.runs[].completionAudit` | 完成 | `success` run 仍为 `not_completed` 输入。 | -| completion audit summary | `build_completion_audit_summary_json`、`completionAuditSummary` normalizer / Harness UI | 完成 | `completed / blocked / needs_input / verifying` 由 evidence 判定。 | -| Agent envelope evidence gate | `agentEnvelopeDraftPresentation.ts` | 完成 | 只有 `completionAuditSummary.decision=completed` 且三项 evidence 齐全才 actionEnabled。 | -| 最近运行审计 | `WorkspaceRegisteredSkillsPanel.tsx` 调用 `getAutomationRunHistory` + `exportAgentRuntimeEvidencePack` | 完成 | 不新增 evidence 查询命令。 | -| Agent card / sharing | `agentEnvelopeDraftPresentation.ts`、Workspace panel tests | 完成 | `workspace-local/` 派生展示;共享限定 workspace / team。 | - -## 6. 验证证据 - -已记录通过的关键验证: - -1. P1A:`capability_draft_create/list/get` Rust / frontend / DevBridge / `npm run verify:gui-smoke`。 -2. P1B:`capability_draft_verify` Rust / frontend / DevBridge / `npm run test:contracts` / `npm run verify:gui-smoke`。 -3. P3A:`capability_draft_register` Rust / frontend / DevBridge / `npm run test:contracts` / `npm run verify:gui-smoke`。 -4. P3B:registered discovery Rust / frontend / DevBridge / `npm run test:contracts` / `npm run verify:gui-smoke`。 -5. P3C:runtime binding readiness Rust / frontend / `npm run typecheck` / `npm run test:contracts` / GUI smoke。 -6. P3D:workspace skill metadata prompt projection Rust / TS 定向测试,且文档边界已同步。 -7. P3E:workspace skill runtime enable metadata、SkillTool allowlist/source metadata、runtime turn 定向测试、`npm run test:contracts`。 -8. P4:Agent envelope presentation / Workspace panel / Skills workspace / Harness panel / Rust evidence pack 定向测试、`npm run typecheck`、`npm run test:contracts`、GUI smoke。 -9. 本审计轮复跑:`npx vitest run src/features/capability-drafts/agentEnvelopeDraftPresentation.test.ts src/features/capability-drafts/components/WorkspaceRegisteredSkillsPanel.test.tsx`,12 passed。 - -## 7. 非目标确认 - -以下仍保持未做,且是正确边界: - -1. 未新增 public Marketplace / Skill Store。 -2. 未新增 `agent_envelope_*` command 或 Agent card 存储表。 -3. 未新增独立 scheduler / queue / generated tool runtime / evidence 系统。 -4. 未允许未验证 draft 进入默认 tool surface。 -5. 未允许外部写操作在无人工确认时自动执行。 -6. 未把 `workspace_skill_bindings` readiness metadata 自动升级为可调用工具。 -7. 未把 automation `success` 直接判定为 Managed Objective `completed`。 - -## 8. 收口判定 - -P0-P4 的 CREAO-inspired 最小开发计划已经完成;后续如果继续推进,应作为新阶段处理: - -1. P5:真实 prompt-to-artifact 产品 E2E 场景,把“只读 CLI 每日报告”跑成完整演示数据集。 -2. P5:外部写操作的人类确认策略和 policy-approved scheduled write。 -3. P5:多 skill managed workflow 与 team-scoped sharing 的权限模型。 -4. P5:proactive agentization 信号,基于 rerun 频率、阻塞原因和修复次数建议固化 Agent。 - -当前 P0-P4 不需要继续补平行实现;下一步应只做验证样例或 P5 扩展,而不是扩大 P4 的 runtime 面。 diff --git a/docs/exec-plans/creaoai-managed-agent-envelope-p4-plan.md b/docs/exec-plans/creaoai-managed-agent-envelope-p4-plan.md deleted file mode 100644 index 7b6275553..000000000 --- a/docs/exec-plans/creaoai-managed-agent-envelope-p4-plan.md +++ /dev/null @@ -1,299 +0,0 @@ -# CREAO Managed Execution / Agent Envelope P4 执行计划 - -> 状态:P4 完成;P0-P4 完成审计通过 -> 创建时间:2026-05-06 -> 前置计划:`docs/exec-plans/creaoai-tool-runtime-authorization-p3e-plan.md` -> 路线图来源:`docs/roadmap/creaoai/README.md`、`docs/roadmap/creaoai/implementation-plan.md`、`docs/roadmap/managed-objective/README.md`、`docs/aiprompts/quality-workflow.md` -> 当前目标:把 P3E 已可显式启用并可审计调用的 workspace-local skill,推进到“成功运行后可固化为 Workspace 产品面的 Agent envelope 草案”,但不新增 runtime、scheduler 或 marketplace。 - -## 主目标 - -P4 第一刀只回答: - -```text -一个 P3E 显式启用并成功运行过的 workspace-local skill - -> 如何被展示成可 rerun 的 Agent envelope 草案 - -> 如何引用来源 draft、verification report、registered directory、session 授权和 evidence - -> 如何为后续 managed execution / schedule 预留明确边界 -``` - -固定边界: - -**Agent envelope 是 Workspace 产品组合面,不是新 runtime;执行仍然回到 `agent_runtime_submit_turn`、automation job、Managed Objective、artifact 和 evidence 主链。** - -## 本轮最小切口 - -第一刀不直接做完整定时任务。先做可验证的 envelope 草案展示与证据消费边界: - -1. 定义前端 `AgentEnvelopeDraft` presentation contract,来源必须是 P3A/P3B registered skill、P3C binding、P3E runtime source metadata 或已导出的 evidence pack。 -2. 在 Workspace 已注册能力面板中展示 “Agent envelope 草案 / 可固化条件” 区域,只对 ready binding 说明下一步,不创建自动化。 -3. 已有 P3E source metadata 时,草案摘要必须能显示 source draft、verification report、registered directory、permission summary 和 session authorization scope。 -4. “转成 Agent” 第一刀只做草案入口或 disabled-ready state,不创建 scheduler、不写长期 job、不绕过 `agent_runtime_submit_turn`。 -5. 补组件 / presentation 单测,证明 P4 入口不会在未 ready、未 evidence 或 blocked 状态下声称已可自动化。 - -## 本轮明确不做 - -1. 不新增 `agent_envelope_*` Tauri 命令。 -2. 不新增 scheduler、queue、automation job 存储或后台 runner。 -3. 不新增 Agent Marketplace / Skill Store。 -4. 不把 P3B / P3C readiness 当成已成功运行。 -5. 不把 `workspace_skill_runtime_enable` 升级成长期授权。 -6. 不允许模型自报完成后直接创建 Agent;必须引用 artifact / timeline / evidence 或后续 completion audit。 - -## 最小 Agent envelope 字段 - -```ts -interface AgentEnvelopeDraft { - id: string; - name: string; - sourceSkill: { - directory: string; - registeredSkillDirectory: string; - sourceDraftId: string; - sourceVerificationReportId?: string | null; - }; - runbook: { - skillName: string; - permissionSummary: string[]; - }; - permission: { - authorizationScope: "session" | "manual" | "scheduled"; - externalWriteRequiresConfirmation: boolean; - }; - evidence: { - status: "missing" | "source_metadata_only" | "evidence_pack_ready"; - sourceMetadata?: unknown; - evidencePackId?: string; - }; - schedule: { - status: "manual_only" | "draft" | "scheduled"; - }; -} -``` - -第一刀可以只落 presentation 层;后续若需要持久化,必须先回到 Managed Objective / automation job 主链设计,不新增平行实体。 - -## 第二刀最小切口 - -第二刀开始接入 managed execution,但只复用现有 automation job,不新增 scheduler / runtime: - -1. 对 `ready_for_manual_enable` 的 workspace skill,允许从 Workspace 已注册能力面板打开 “Managed Job 草案”。 -2. 草案默认 `enabled=false`,用户需要在现有持续流程弹窗里确认调度、权限和输出后再启用。 -3. automation payload 仍是 `agent_turn`,执行时继续走 `agent_runtime_submit_turn` / runtime queue。 -4. `request_metadata.harness` 必须携带: - - `agent_envelope`:source draft、verification report、registered skill directory、skill name 与 scheduled session authorization scope。 - - `managed_objective`:owner type 为 `automation_job`,completion audit 要求 artifact / timeline / evidence。 - - `workspace_skill_runtime_enable`:source 为 `agent_envelope_scheduled_run`,每次 automation run 仍在当前 session 内显式打开 allowlist。 -5. blocked / 缺少 verification provenance / 缺少 workspace root 的 skill 不能生成 Managed Job 草案。 - -## 实施步骤 - -### P4-0:计划与边界 - -- [x] 新增本执行计划。 -- [x] 明确 P4 第一刀是 Agent envelope 草案展示和 evidence 消费边界,不做 scheduler / marketplace / 新 runtime。 - -### P4-1:Presentation contract - -- [x] 新增最小 `AgentEnvelopeDraft` presentation builder。 -- [x] 输入优先级固定为:P3E ToolResult source metadata / evidence pack > P3C ready binding > P3B registered skill。 -- [x] 缺少 P3E source metadata 或 evidence 时,状态只能是 `source_metadata_only` 或 `missing`,不能显示为可自动化。 -- [x] 补单测覆盖 ready、blocked、missing evidence、source metadata 四类状态。 - -### P4-2:Workspace UI 第一刀 - -- [x] 在 `WorkspaceRegisteredSkillsPanel` 中展示 Agent envelope 草案摘要。 -- [x] ready binding 只显示“可在成功运行后固化为 Agent”,blocked binding 显示阻塞原因。 -- [x] “转成 Agent” 入口第一刀只允许 disabled / draft explanation,不创建 automation job。 -- [x] 保留 P3E “本回合启用”作为唯一真实运行入口。 - -### P4-3:Evidence 消费边界 - -- [x] 明确 timeline / evidence pack 读取 `workspace_skill_source` / `workspace_skill_runtime_enable` 的字段映射。 -- [x] 先做 presentation 级消费;同时确认 `timeline.json` 原先未保留 ToolCall source metadata,因此补 evidence exporter 最小透传。 -- [x] 避免 UI 伪造证据:P4 Agent envelope 草案只读取 P3E source metadata / evidence pack;timeline 不存在字段时仍保持 `missing`。 - -### P4-4:验证 - -- [x] 前端 presentation / component 定向测试。 -- [x] `npm run test:contracts` 只在触碰命令 / bridge / mock 时补跑;P4 第一刀未新增命令,沿用 P3E 已通过结果。 -- [x] Workspace 可见 UI 改动已补 `npm run verify:gui-smoke -- --reuse-running --timeout-ms 300000`。 - -### P4-5:Managed Job 草案与 owner metadata - -- [x] 新增 `workspaceSkillAgentAutomationDraft` helper,生成现有 `AutomationJobDialog` 可消费的 initial values。 -- [x] request metadata 固定写入 `harness.agent_envelope`、`harness.managed_objective` 与 `harness.workspace_skill_runtime_enable`,不新增命令或 runtime。 -- [x] Skills 工作台的 Workspace 已注册能力面板增加 “创建 Managed Job 草案”入口,只对 ready binding + verification provenance 可用。 -- [x] 创建确认继续复用现有 `AutomationJobDialog` + `createAutomationJob`;默认暂停,避免注册后自动长期运行。 -- [x] 补 helper / panel / Skills 工作台定向测试。 - -### P4-6:Automation owner evidence - -- [x] `agent_runtime_export_evidence_pack` 导出前会查询当前 session 关联的 `agent_runs`,把 automation owner runs 注入 evidence pack。 -- [x] `runtime.json` 与 `artifacts.json` 新增 `automationOwners`,保留 automation job id、状态、`agent_envelope`、`managed_objective` 与 `workspace_skill_runtime_enable`。 -- [x] 该证据仍来自 `agent_runs.metadata` 与 runtime evidence pack,不新增 evidence 事实源。 -- [x] Rust 定向测试覆盖 automation owner -> Agent envelope -> P3E runtime enable 的导出关系。 - -### P4-7:Workspace managed job 状态投影 - -- [x] Workspace 已注册能力面板读取现有 `automation_job` 列表,不新增查询命令。 -- [x] 通过 automation payload 的 `request_metadata.harness.agent_envelope` 反查绑定的 workspace skill directory / skill name。 -- [x] Agent envelope 草案区域展示 Managed Job 是否已创建、暂停/启用状态、调度摘要、最近运行与错误摘要。 -- [x] 状态投影仅显示现有 automation job 事实,不把 registered skill 误报为已运行或已完成。 - -### P4-8:Pause / resume 最小闭环 - -- [x] Workspace 已注册能力面板对已匹配的 Managed Job 展示暂停 / 恢复操作。 -- [x] 操作复用既有 `updateAutomationJob(job.id, { enabled })`,不新增命令、不新增 scheduler。 -- [x] 成功后以返回的 automation job record 更新本地投影,继续以 `enabled` 作为暂停 / 恢复事实源。 -- [x] 前端回归覆盖恢复按钮调用 `updateAutomationJob` 并刷新状态摘要。 - -### P4-9:Managed Objective 状态 / audit 投影 - -- [x] Workspace managed job 状态区新增 Managed Objective 最小状态投影:`planned` / `paused` / `running` / `blocked` / `verifying`。 -- [x] `last_status=success` 只进入 `verifying`,不会直接标为 `completed`。 -- [x] Completion Audit 文案明确要求 artifact / timeline / evidence 审计,避免模型自报完成。 -- [x] 前端 presentation 单测覆盖 success run 不直接 completed。 - -### P4-10:Evidence completion audit input - -- [x] Evidence pack 的 `automationOwners.runs[]` 新增 `completionAudit` 结构化输入。 -- [x] `completionAudit` 会检查 automation run status、`agent_envelope`、`managed_objective`、`workspace_skill_runtime_enable` 与 `managed_objective.completion_audit`。 -- [x] 即使 run status 为 `success`,`completionDecision` 仍保持 `not_completed`;真正 completed 必须由后续 artifact / timeline / evidence audit 产生。 -- [x] Rust evidence 定向测试覆盖 `audit_input_ready` 与 `not_completed`。 - -### P4-11:Evidence completion audit summary - -- [x] `runtime.json` / `artifacts.json` 新增 `completionAuditSummary`,统一输出 `completed / blocked / needs_input / verifying`。 -- [x] `completed` 只允许在 automation owner success、workspace skill ToolCall source metadata、artifact / timeline evidence 同时满足时出现。 -- [x] 非 success owner run、缺失 Agent envelope / Managed Objective / runtime enable、缺少 workspace skill ToolCall evidence 时分别落到 `blocked`、`needs_input` 或 `verifying`。 -- [x] Rust evidence 定向测试覆盖 evidence 齐全时 summary 才输出 `completed`。 -- [x] `summary.md` 新增 Completion Audit 摘要,让人类先读入口也能看到 decision、owner / ToolCall / artifact evidence 和 blocking reasons。 - -### P4-12:Evidence export UI projection - -- [x] `RuntimeEvidencePackExportResult` 新增 `completionAuditSummary`,让导出命令响应也携带 evidence-based completion audit。 -- [x] 前端 `AgentRuntimeEvidencePack` 类型和 normalizer 接入 `completion_audit_summary`,兼容 camelCase / snake_case。 -- [x] Harness 面板导出问题证据包后展示 Completion Audit 卡片,包含 decision、owner success、Skill ToolCall、artifact evidence 与 blocking reasons。 -- [x] 前端 API 与 Harness 面板回归覆盖 completion audit summary 投影。 - -### P4-13:Agent envelope completion audit gate - -- [x] `AgentEnvelopeDraftPresentation` 接入 `completionAuditSummary` 作为 evidence-ready 的结构化输入。 -- [x] 只有 `decision=completed` 且 automation owner / workspace skill ToolCall / artifact-or-timeline 三项 evidence 全为 true 时才进入 `evidence_ready`。 -- [x] `verifying` 或缺 ToolCall evidence 不会误报为可固化 Agent envelope。 -- [x] Presentation 单测覆盖 completed 正向与 verifying 负向 gate。 - -### P4-14:Workspace Agent envelope evidence-gated action - -- [x] `WorkspaceRegisteredSkillsPanel` 新增 `completionAuditSummariesByDirectory` 注入边界,不新增命令、不读取平行 runtime。 -- [x] 当指定 skill 的 completion audit 已 `completed` 且证据齐全时,“转成 Agent 草案”入口启用。 -- [x] 入口复用既有 `onCreateManagedAutomationDraft(binding)` / Managed Job 草案链,不新增 Agent envelope 存储或 scheduler。 -- [x] Workspace 组件回归覆盖 completed audit 打开入口并传回对应 binding。 - -### P4-15:Workspace recent run audit action - -- [x] 匹配到 Managed Job 后,Workspace 已注册能力面板展示“审计最近运行”。 -- [x] 点击后复用既有 `get_automation_run_history(job.id, 5)` 查最近 automation run,不新增查询命令。 -- [x] 找到 run `session_id` 后复用 `agent_runtime_export_evidence_pack(sessionId)` 获取 `completionAuditSummary`。 -- [x] audit summary 回填到当前 skill directory,并驱动 Agent envelope evidence gate / “转成 Agent 草案”入口。 - -### P4-16:Agent envelope card composition - -- [x] Agent envelope presentation 补齐 `Memory` 与 `Widget` 摘要。 -- [x] Workspace 已注册能力面板展示 Runbook、Memory、Widget、Permission、Schedule、Evidence 六块组成。 -- [x] Memory 只引用 verification report 与后续运行修正,不新增独立 memory runtime。 -- [x] Widget 只展示 Managed Job 状态、最近产物、审计结论和下一步动作,不新增执行实体。 - -### P4-17:Derived Agent card / workspace sharing - -- [x] Agent card 采用派生展示:`workspace-local/` 来自 registered skill + Managed Job + completion audit。 -- [x] 未完成 audit 时只显示草案等待态,不创建平行持久化实体。 -- [x] sharing 范围先限定当前 workspace / team,不进入 public Marketplace。 -- [x] Workspace 回归覆盖 completed audit 后展示 derived Agent card 与 sharing 摘要。 - -### P4-18:Workspace/team sharing discovery boundary - -- [x] Agent envelope presentation 展示 registered skill discovery 路径:`.agents/skills/`。 -- [x] 同 workspace 成员通过既有 registered skill discovery 发现 Agent card 来源,不新增 sharing 命令。 -- [x] 共享复用同一 Managed Job / evidence 事实源,不复制 automation job 或 evidence。 -- [x] 前端回归覆盖 sharing discovery 文案。 - -## 验收标准 - -1. blocked 或未 ready 的 registered skill 不出现可固化为 Agent 的积极入口。 -2. ready binding 可以看到 Agent envelope 草案组成:Skill / permission / schedule / evidence。 -3. UI 明确说明“成功运行后固化”,不能把注册、发现或 readiness 说成已经运行成功。 -4. “转成 Agent” 第一刀不创建 automation job、不新增 scheduler、不写长期授权。 -5. source draft、verification report、registered directory 与 session 授权范围能够从 P3E metadata / evidence 进入草案摘要。 -6. 组件测试覆盖 P4 入口不会破坏 P3E “本回合启用”的唯一真实运行入口。 -7. Managed Job 草案只能复用现有 automation job,payload 必须仍是 `agent_turn`,且每次运行都通过 `workspace_skill_runtime_enable` 做 session-scoped allowlist。 -8. Evidence pack 必须能导出 automation owner 与 Agent envelope / Managed Objective / workspace skill runtime enable 的关系,不能只靠前端草案说明。 -9. Workspace 面板必须能从已有 automation job 反投影 Managed Job 状态,展示下次运行 / 最近运行,而不是只提供创建入口。 -10. 暂停 / 恢复必须只修改 automation job 的 `enabled` 状态,不允许创建平行 pause state。 -11. `success` run 只能作为 completion audit 输入,不能直接把 Managed Objective 判为 completed。 -12. Evidence pack 必须显式导出 completion audit input,作为后续 completed / blocked / needs_input 判定的唯一输入之一。 -13. Evidence pack 必须显式导出 completion audit summary,且 `completed` 只能由 automation owner、workspace skill ToolCall 和 artifact / timeline 证据共同判定。 -14. `summary.md` 必须能直接展示 completion audit 结论和阻塞原因,不能要求用户只靠 JSON 手工定位。 -15. 导出问题证据包后的 UI 必须展示 completion audit summary,避免用户只能打开落盘文件才能知道 Managed Objective 是否完成。 -16. Agent envelope presentation 只能在 completion audit `completed` 且必要 evidence 齐全时进入 evidence-ready,不能把 `verifying` 或缺证据状态当成可固化。 -17. Workspace 的“转成 Agent 草案”只能由 completed completion audit 打开,并且必须复用现有 Managed Job 草案创建链。 -18. Workspace 的最近运行审计必须复用 `get_automation_run_history` 和 `agent_runtime_export_evidence_pack`,不能新增平行 evidence 查询或 runtime。 -19. Agent envelope 草案必须展示 Runbook、Memory、Widget、Permission、Schedule、Evidence 六块组成,且 Memory / Widget 只能是产品组合面摘要。 -20. Agent card 首期只能作为 registered skill + Managed Job + completion audit 的派生卡片,不新增存储表;sharing 先限定 workspace / team。 -21. Workspace/team sharing 只能复用 registered skill discovery、Managed Job 与 evidence 事实源,不能新增 sharing 命令、Marketplace 或复制执行实体。 - -## 执行记录 - -### 2026-05-06 - -- 已从 P3E 收口进入 P4,确认第一刀应消费 `workspace_skill_source` / `workspace_skill_runtime_enable`,而不是新增平行执行命令。 -- 已确认现有 `WorkspaceRegisteredSkillsPanel` 仍保留 P3C / P3E 边界:只对 `ready_for_manual_enable` 展示“本回合启用”,并明确不创建自动化。 -- 已新增 `agentEnvelopeDraftPresentation` presentation builder:ready binding 默认是 `manual_enable_required`,blocked binding 是 `blocked`,P3E source metadata 是 `source_metadata_ready`,evidence pack 是 `evidence_ready`;所有状态第一刀都不创建长期任务。 -- 已接入 `WorkspaceRegisteredSkillsPanel`:每个 registered skill 展示 Agent envelope 草案的 runbook、permission、manual rerun schedule 与 evidence 状态;P3E “本回合启用”仍是唯一真实运行入口。 -- 定向验证已通过:`npx vitest run src/features/capability-drafts/agentEnvelopeDraftPresentation.test.ts src/features/capability-drafts/components/WorkspaceRegisteredSkillsPanel.test.tsx src/components/skills/SkillsWorkspacePage.test.tsx -t "应在我的方法工作台展示 Workspace 已注册能力|buildAgentEnvelopeDraftPresentation|WorkspaceRegisteredSkillsPanel"`(3 files,9 passed / 29 skipped)。 -- TypeScript 校验已通过:`npm run typecheck`。 -- 全量 `src/components/skills/SkillsWorkspacePage.test.tsx` 当前仍有既有文案迁移断言失败(例如“我的方法” vs “我的 Skills”、“你来给”前缀等),与本 P4 第一刀无直接关系;本轮只修正了 P4 新增 disabled action 与 P3E enable button 的选择器歧义。 -- 已补 evidence pack timeline 最小透传:`timeline.json` 的 ToolCall item 会在存在 P3E metadata 时写出 `workspaceSkillToolCall.workspaceSkillSource` 与 `workspaceSkillToolCall.workspaceSkillRuntimeEnable`,让 Agent envelope 可追踪 source draft、verification report、registered directory 与 session 授权范围。 -- Rust evidence 定向验证已通过:`CARGO_INCREMENTAL=0 CARGO_TARGET_DIR=/tmp/lime-p4-agent-envelope-target cargo test --manifest-path src-tauri/Cargo.toml -p lime --lib timeline_should_preserve_workspace_skill_source_metadata_for_agent_envelope`(1 passed)。 -- GUI smoke 已通过:`npm run verify:gui-smoke -- --reuse-running --timeout-ms 300000`。首次 smoke 曾暴露 Skills 页面文案断言与 `react-syntax-highlighter` / `refractor` ESM 测试环境问题;已把断言对齐当前 UI,并在相关测试中 mock Markdown syntax highlighter,复跑通过 workspace ready、browser runtime、site adapters、service skill entry、runtime tool surface、runtime tool surface page、Knowledge GUI 与 Design Canvas。 -- 已新增 Managed Job 草案入口:`workspaceSkillAgentAutomationDraft` 会为 ready binding 生成 `AutomationJobDialogInitialValues`,并把 `agent_envelope` / `managed_objective` / `workspace_skill_runtime_enable` 写入 automation payload 的 `request_metadata.harness`。 -- 已接入 `SkillsWorkspacePage`:Workspace 已注册能力面板可打开现有持续流程弹窗,提交后调用既有 `createAutomationJob`;默认 `enabled=false`,不绕过用户确认和 automation 主链。 -- 定向验证已通过:`npx vitest run src/features/capability-drafts/workspaceSkillAgentAutomationDraft.test.ts src/features/capability-drafts/components/WorkspaceRegisteredSkillsPanel.test.tsx`(7 passed)。 -- Skills 工作台回归已通过:`npx vitest run src/components/skills/SkillsWorkspacePage.test.tsx`(30 passed)。 -- TypeScript 校验已复跑通过:`npm run typecheck`。 -- 已补 automation owner evidence:`agent_runtime_export_evidence_pack` 会把当前 session 的 `agent_runs` 注入导出服务,`runtime.json` / `artifacts.json` 写出 `automationOwners`。 -- Rust evidence 定向验证已通过:`CARGO_INCREMENTAL=0 CARGO_TARGET_DIR=/tmp/lime-p4-agent-owner-target cargo test --manifest-path src-tauri/Cargo.toml -p lime --lib evidence_pack_should_export_automation_owner_agent_envelope_metadata`(1 passed)。 -- 已补 Workspace managed job 状态投影:`WorkspaceRegisteredSkillsPanel` 会读取既有 automation jobs,并按 `agent_envelope.directory` / `skill` 显示 Managed Job 创建状态、schedule 与最近运行。 -- 前端定向验证已复跑通过:`npx vitest run src/features/capability-drafts/workspaceSkillAgentAutomationDraft.test.ts src/features/capability-drafts/components/WorkspaceRegisteredSkillsPanel.test.tsx src/components/skills/SkillsWorkspacePage.test.tsx`(38 passed)。 -- 已补 pause / resume 最小闭环:Workspace managed job 状态区可调用既有 `updateAutomationJob` 切换 `enabled`。 -- 已补 Managed Objective 状态 / audit 投影:success run 显示 `verifying`,等待 artifact / timeline / evidence 审计。 -- 已补 evidence completion audit input:`automationOwners.runs[].completionAudit` 输出 `audit_input_ready` / `missing_inputs` / `blocked_by_run_status`,并保持 `completionDecision=not_completed`。 -- 已补 evidence completion audit summary:`runtime.json` / `artifacts.json` 输出 `completionAuditSummary`,在 automation owner success、workspace skill ToolCall source metadata 与 artifact / timeline 证据齐全时才输出 `completed`。 -- 已补 completion audit summary 负向回归:覆盖缺 automation owner -> `needs_input`、owner run error -> `blocked`、缺 audit inputs -> `needs_input`、缺 workspace skill ToolCall evidence -> `verifying`。 -- 已补 `summary.md` Completion Audit 人类可读入口:导出 decision、owner success count、Workspace Skill ToolCall evidence、artifact evidence 与 blocking reasons。 -- Rust evidence 负向定向验证已通过:`CARGO_INCREMENTAL=0 CARGO_TARGET_DIR=/tmp/lime-p4-agent-owner-target cargo test --manifest-path src-tauri/Cargo.toml -p lime --lib completion_audit_summary_should_classify_negative_paths`(1 passed)。 -- Rust evidence 定向验证已复跑通过:`CARGO_INCREMENTAL=0 CARGO_TARGET_DIR=/tmp/lime-p4-agent-owner-target cargo test --manifest-path src-tauri/Cargo.toml -p lime --lib evidence_pack_should_export_automation_owner_agent_envelope_metadata`(1 passed)。 -- Rust timeline 定向验证已复跑通过:`CARGO_INCREMENTAL=0 CARGO_TARGET_DIR=/tmp/lime-p4-agent-owner-target cargo test --manifest-path src-tauri/Cargo.toml -p lime --lib timeline_should_preserve_workspace_skill_source_metadata_for_agent_envelope`(1 passed)。 -- 已补 evidence export UI projection:`RuntimeEvidencePackExportResult`、前端 normalizer 和 Harness 面板均接入 `completionAuditSummary`,导出问题证据包后可直接看到 evidence-based decision 与 blocking reasons。 -- 前端定向验证已通过:`npx vitest run src/lib/api/agent.test.ts src/components/agent/chat/components/HarnessStatusPanel.test.tsx`(77 passed)。 -- TypeScript 校验已通过:`npm run typecheck`。 -- 命令契约校验已通过:`npm run test:contracts`,覆盖 agent runtime client manifest、命令契约、harness metadata contract、modality contracts 与 cleanup report contract。 -- GUI smoke 已复跑通过:`npm run verify:gui-smoke -- --reuse-running --timeout-ms 300000`,覆盖 workspace ready、browser runtime、site adapters、service skill entry、runtime tool surface、runtime tool surface page、Knowledge GUI 与 Design Canvas。首次复跑曾在 `smoke:agent-service-skill-entry` 出现 Vitest worker `onTaskUpdate` 通信超时;单独复跑该 smoke 与完整 GUI smoke 均通过。 -- 已补 Agent envelope completion audit gate:presentation contract 消费 `completionAuditSummary`,completed + 三项 evidence 齐全才进入 `evidence_ready`;verifying / 缺 ToolCall evidence 仍不可固化。 -- 前端 presentation 定向验证已通过:`npx vitest run src/features/capability-drafts/agentEnvelopeDraftPresentation.test.ts`(6 passed)。 -- 已补 Workspace Agent envelope evidence-gated action:`WorkspaceRegisteredSkillsPanel` 支持按 directory 注入 completion audit summary,completed + evidence 齐全后“转成 Agent 草案”复用 Managed Job 草案创建链。 -- 前端 Workspace 定向验证已通过:`npx vitest run src/features/capability-drafts/agentEnvelopeDraftPresentation.test.ts src/features/capability-drafts/components/WorkspaceRegisteredSkillsPanel.test.tsx`(12 passed)。 -- 已补 Workspace recent run audit action:匹配 Managed Job 后可点击“审计最近运行”,通过 `getAutomationRunHistory` 找 session,再用 `exportAgentRuntimeEvidencePack` 导出并回填 `completion_audit_summary`,随后 evidence-gated Agent envelope 入口启用。 -- Skills 工作台回归已通过:`npx vitest run src/components/skills/SkillsWorkspacePage.test.tsx`(30 passed)。 -- GUI smoke 已在 recent run audit action 后复跑通过:`npm run verify:gui-smoke -- --reuse-running --timeout-ms 300000`,覆盖 workspace ready、browser runtime、site adapters、service skill entry、runtime tool surface、runtime tool surface page、Knowledge GUI 与 Design Canvas。 -- 已补 Agent envelope card composition:Workspace 草案区展示 Runbook、Memory、Widget、Permission、Schedule、Evidence 六块组成,仍不新增执行实体。 -- 前端定向验证已通过:`npx vitest run src/features/capability-drafts/agentEnvelopeDraftPresentation.test.ts src/features/capability-drafts/components/WorkspaceRegisteredSkillsPanel.test.tsx`(12 passed)。 -- TypeScript 校验已复跑通过:`npm run typecheck`。 -- 已补 derived Agent card / workspace sharing 摘要:completed audit 后显示 `workspace-local/` 派生 Agent card 与 workspace / team 共享范围;未完成审计时显示草案等待态。 -- 前端定向验证已复跑通过:`npx vitest run src/features/capability-drafts/agentEnvelopeDraftPresentation.test.ts src/features/capability-drafts/components/WorkspaceRegisteredSkillsPanel.test.tsx`(12 passed)。 -- 已补 workspace/team sharing discovery 边界:Agent card 摘要展示 `.agents/skills/` 的 registered discovery 来源,并说明复用同一 Managed Job / evidence。 -- 前端定向验证已复跑通过:`npx vitest run src/features/capability-drafts/agentEnvelopeDraftPresentation.test.ts src/features/capability-drafts/components/WorkspaceRegisteredSkillsPanel.test.tsx`(12 passed)。 -- 已完成 P0-P4 completion audit:新增 `docs/exec-plans/creaoai-completion-audit.md`,逐项映射 roadmap / implementation-plan 的 P0-P4 要求到代码、测试、命令验证和文档证据。 -- 审计发现并修正 Agent envelope gate 的一个边界:仅 `evidencePackId` 存在时不再进入 `evidence_ready`;必须 `completionAuditSummary.decision=completed` 且 automation owner / Workspace Skill ToolCall / artifact-or-timeline 三项 evidence 齐全。 -- 前端定向验证已复跑通过:`npx vitest run src/features/capability-drafts/agentEnvelopeDraftPresentation.test.ts src/features/capability-drafts/components/WorkspaceRegisteredSkillsPanel.test.tsx`(12 passed)。 diff --git a/docs/exec-plans/creaoai-query-loop-metadata-p3d-plan.md b/docs/exec-plans/creaoai-query-loop-metadata-p3d-plan.md deleted file mode 100644 index 46836c2f2..000000000 --- a/docs/exec-plans/creaoai-query-loop-metadata-p3d-plan.md +++ /dev/null @@ -1,123 +0,0 @@ -# CreoAI Query Loop Metadata P3D 执行计划 - -> 状态:完成 -> 创建时间:2026-05-06 -> 前置计划:`docs/exec-plans/creaoai-runtime-binding-p3c-plan.md` -> 路线图来源:`docs/roadmap/creaoai/implementation-plan.md`、`docs/aiprompts/commands.md`、`docs/aiprompts/quality-workflow.md` -> 当前目标:把 P3C 的 runtime binding readiness 作为 Query Loop 可读上下文投影进单次 `agent_runtime_submit_turn`,但仍不启用真实 SkillTool 执行。 - -## 主目标 - -P3D 第一刀只回答: - -```text -如果当前回合显式携带 workspace_skill_bindings metadata - -> Query Loop 能不能读到这些 registered skill 的来源、状态和下一道 gate - -> 模型能不能据此规划下一步 - -> 同时明确不能声称已运行、不能调用未启用 skill、不能自动化 -``` - -固定宗旨: - -**不是永远限制能力;是永远限制未经验证、未经授权、不可审计的执行。** - -## 本轮最小切口 - -本轮只做 Query Loop metadata prompt projection: - -1. 新增 `workspace_skill_bindings` / `workspaceSkillBindings` request metadata contract。 -2. Rust 在 full runtime system prompt 中注入只读说明块。 -3. 说明块把 registered skill 当作“候选能力上下文”,不是可调用工具。 -4. prompt 明确禁止模型声称已执行、禁止调用未授权 Skill、禁止创建自动化。 -5. 补最小 frontend metadata builder,用于后续 UI / send boundary 统一组装。 - -本轮明确不做: - -1. 不注入 `SkillTool` registry。 -2. 不把 P3C binding candidate 变成 `allow_model_skills=true`。 -3. 不创建 “运行 / 自动化 / 继续这套方法” UI 入口。 -4. 不新增 scheduler、queue、artifact 或 evidence 旁路。 -5. 不执行 `.agents/skills//scripts`。 - -## Metadata contract - -推荐放在: - -```json -{ - "harness": { - "workspace_skill_bindings": { - "source": "p3c_runtime_binding", - "bindings": [ - { - "directory": "capability-report", - "name": "只读 CLI 报告", - "description": "把只读 CLI 输出整理成 Markdown 报告。", - "binding_status": "ready_for_manual_enable", - "next_gate": "manual_runtime_enable", - "query_loop_visible": false, - "tool_runtime_visible": false, - "launch_enabled": false, - "permission_summary": ["Level 0 只读发现"], - "source_draft_id": "capdraft-...", - "source_verification_report_id": "capver-..." - } - ] - } - } -} -``` - -固定语义: - -- `workspace_skill_bindings` 表示“当前回合可读的 registered skill 候选上下文”。 -- `query_loop_visible=false` 表示尚未进入长期 Query Loop 目录。 -- `tool_runtime_visible=false` 表示尚未进入可调用工具面。 -- `launch_enabled=false` 表示前端和模型都不能把它当作可运行能力。 - -## 实施步骤 - -### P3D-0:计划与边界 - -- [x] 新增本执行计划。 -- [x] 明确 P3D 只做 Query Loop metadata projection,不做 execution。 - -### P3D-1:Rust prompt projection - -- [x] 新增 `workspace_skill_binding_prompt` 模块。 -- [x] 支持 snake_case / camelCase metadata。 -- [x] 限制最多投影 5 个 binding,避免 prompt 膨胀。 -- [x] 过滤空字段并截断长文本。 -- [x] 在 full runtime prompt stage 中插入 `WorkspaceSkillBindings`。 -- [x] 补 Rust 单测:无 metadata 不注入、有 binding 注入、禁止执行语义存在、stage 顺序稳定。 - -### P3D-2:Frontend metadata builder - -- [x] 新增 workspace skill binding metadata builder。 -- [x] 支持从 `AgentRuntimeWorkspaceSkillBinding` 安全裁剪为 request metadata。 -- [x] 保持 `allow_model_skills` 不被自动打开。 -- [x] 补 TS 单测。 - -### P3D-3:文档与校验 - -- [x] 更新 CreoAI 路线图 P3D 状态。 -- [x] 更新命令 / 质量文档中 metadata 边界。 -- [x] 跑 Rust / TS 定向测试、`npm run typecheck`、必要时 `npm run test:contracts`。 - -## 验收标准 - -1. 不带 `workspace_skill_bindings` metadata 时 prompt 不变化。 -2. 带 metadata 时 prompt 包含 skill 名称、目录、状态、来源与下一道 gate。 -3. prompt 明确说明这些 binding 只能用于规划,不能被直接调用或声称已运行。 -4. 该 metadata 不会自动打开 `allow_model_skills`。 -5. 所有新增测试和契约检查通过。 - -## 执行记录 - -### 2026-05-06 - -- 已创建 P3D 执行计划,确认本轮只把 P3C readiness 作为 Query Loop 可读上下文,不做 tool_runtime 执行授权。 -- 已新增 Rust `WorkspaceSkillBindings` prompt stage:支持 `workspace_skill_bindings` / `workspaceSkillBindings`,最多投影 5 个候选 binding,并在 prompt 中明确禁止声称已运行、禁止调用未授权 Skill、禁止创建 automation。 -- 已新增前端 `workspaceSkillBindingsMetadata` builder,并接入 `buildHarnessRequestMetadata` 可选参数;默认不改变发送行为,也不写入 `allow_model_skills`。 -- 已更新 CreoAI 路线图、命令边界与质量工作流,明确 P3D 是只读 Query Loop metadata projection,不是 runtime enable。 -- 后续 P3E / P4 收口验证已覆盖 P3D 边界:workspace skill metadata builder、harness metadata builder、runtime turn prompt projection、`npm run test:contracts` 与 `npm run typecheck` 均通过;P3D 判定完成。 diff --git a/docs/exec-plans/creaoai-runtime-binding-p3c-plan.md b/docs/exec-plans/creaoai-runtime-binding-p3c-plan.md deleted file mode 100644 index ca668d2c2..000000000 --- a/docs/exec-plans/creaoai-runtime-binding-p3c-plan.md +++ /dev/null @@ -1,156 +0,0 @@ -# CreoAI Runtime Binding P3C 执行计划 - -> 状态:完成 -> 创建时间:2026-05-06 -> 前置计划:`docs/exec-plans/creaoai-capability-discovery-p3b-plan.md` -> 路线图来源:`docs/roadmap/creaoai/implementation-plan.md`、`docs/aiprompts/commands.md`、`docs/aiprompts/quality-workflow.md` -> 当前目标:把 P3B 已发现的 workspace-local registered skill 推进为运行时可审计的 binding readiness projection,但仍不开放默认执行面。 - -## 主目标 - -P3C 第一刀只回答一个问题: - -```text -当前 workspace 里哪些 P3A/P3B registered skill - -> 已经具备进入 Query Loop / tool_runtime 的候选资格 - -> 还卡在哪个 gate - -> 为什么现在仍不能直接运行 -``` - -固定宗旨: - -**不是永远限制能力;是永远限制未经验证、未经授权、不可审计的执行。** - -## 本轮最小切口 - -本轮新增 `agent_runtime_*` 主链下的只读投影命令: - -```text -agent_runtime_list_workspace_skill_bindings - -> workspaceRoot - -> P3B registered skills - -> binding readiness / policy gate / next gate - -> Skills 工作台只读展示 -``` - -本轮只做: - -1. 显式按 `workspaceRoot` 读取 P3B registered skill。 -2. 返回 runtime binding candidate / blocked / next gate 等只读状态。 -3. 明确标注 `queryLoopVisible=false`、`toolRuntimeVisible=false`、`launchEnabled=false`。 -4. 前端只展示“runtime binding 候选 / 待启用”,不展示运行、自动化或继续方法入口。 -5. 同步 `agentRuntimeCommandSchema`、generated manifest、DevBridge、mock、命令目录册和文档。 - -本轮明确不做: - -1. 不调用 `AsterAgentState::reload_lime_skills()`。 -2. 不修改 `SkillService::get_catalog_roots` 的 cwd 语义。 -3. 不把 workspace registered skill 合并进默认 `useSkills("lime")`。 -4. 不把 generated skill 注入 `SkillTool` global registry。 -5. 不改变 `agent_runtime_submit_turn` 的工具可见性。 -6. 不创建 automation job 或 Managed Objective。 - -## 为什么 P3C 第一刀仍然只读 - -P3B 已证明“文件存在且可审计”,但它还没有证明: - -1. Query Loop 该如何在当前 session 中发现这个 skill。 -2. `tool_runtime` 该如何裁剪它的权限、caller、surface 和 sandbox。 -3. evidence pack 该如何记录来源 draft、verification report、registration 和运行事实。 -4. 当前 workspace 与后端进程 `cwd` 不一致时,运行时 loader 该读哪个 root。 - -因此 P3C 不能直接把 registered skill 交给现有 `SkillTool` 执行。第一刀先把 binding gate 明文化,让后续每一步都有事实源可验证。 - -## 安全规则 - -1. **workspace 显式入参**:不从进程 `cwd` 推断当前项目。 -2. **registered-only**:只消费 P3B 已认可的 `.lime/registration.json` provenance。 -3. **只读 projection**:不执行 `SKILL.md`、scripts、CLI 或外部 API。 -4. **默认不可运行**:所有结果必须显式 `launchEnabled=false`。 -5. **gate 可解释**:每条 binding 都必须说明当前状态、阻塞原因和下一道 gate。 -6. **后续执行回主链**:真正执行只能继续走 `agent_runtime_submit_turn -> Query Loop -> tool_runtime -> artifact/evidence`。 - -## 实施步骤 - -### P3C-0:计划与边界 - -- [x] 新增本执行计划。 -- [x] 明确第一刀只做 runtime binding readiness projection,不做 execution。 - -### P3C-1:后端 binding service - -- [x] 新增 workspace skill binding DTO。 -- [x] 新增 `list_workspace_skill_bindings(...)` 服务函数。 -- [x] 复用 P3B registered discovery 的 symlink / provenance / 标准检查边界。 -- [x] 返回 `ready_for_manual_enable` / `blocked` 等 binding 状态。 -- [x] 补 Rust 单测:空 workspace、相对 workspaceRoot 拒绝、registered skill 变成 binding candidate、缺 provenance blocked、非标准项 blocked。 - -### P3C-2:agent runtime 命令边界 - -- [x] 新增 Tauri command `agent_runtime_list_workspace_skill_bindings`。 -- [x] 同步 `runner.rs`、DevBridge dispatcher。 -- [x] 同步 `agentRuntimeCommandSchema.json` 并生成 `commandManifest.generated.ts`。 -- [x] 同步 `agentCommandCatalog`、`mockPriorityCommands`、`defaultMocks`。 -- [x] 运行 `npm run test:contracts`。 - -### P3C-3:前端 API / UI - -- [x] 扩展 `src/lib/api/agentRuntime/inventoryClient.ts`。 -- [x] 扩展 `WorkspaceRegisteredSkillsPanel`:展示 binding 状态与 next gate。 -- [x] 保持不出现“立即运行 / 自动化 / 继续这套方法”入口。 -- [x] 补 API、组件、Skills 工作台回归测试。 - -### P3C-4:试跑与验收 - -- [x] Rust 定向测试通过。 -- [x] 前端定向测试通过。 -- [x] `npm run test:contracts` 通过。 -- [x] 若 Skills 工作台 UI 可见行为变化,补 `npm run verify:gui-smoke`。 - -## 验收标准 - -1. `agent_runtime_list_workspace_skill_bindings` 只接受显式 `workspaceRoot`。 -2. 返回结果只包含 P3B registered skill。 -3. 每条结果包含来源 draft、verification report、registration、权限摘要和 next gate。 -4. 每条结果默认 `queryLoopVisible=false`、`toolRuntimeVisible=false`、`launchEnabled=false`。 -5. UI 展示 runtime binding 状态,但不出现运行、自动化或继续方法入口。 -6. 命令契约、DevBridge、mock、文档和 GUI smoke 保持一致。 - -## 执行记录 - -### 2026-05-06 - -- 已创建 P3C 执行计划,确认命令归属为 `agent_runtime_* / inventory` 主链,而不是继续扩 `capability_draft_*`。 -- 已确认第一刀不接 `SkillTool`、不 reload、不修改 cwd-based loader,只补 workspace binding readiness projection。 -- 已完成后端 `runtime_skill_binding_service`、Tauri command、DevBridge dispatcher、前端 API 网关、默认 mock、治理目录册与 Skills 工作台只读 binding 状态展示。 -- 已把 P3C 语义固定为 `workspaceRoot -> P3B registered skills -> runtime binding readiness / next gate`,结果显式返回 `queryLoopVisible=false`、`toolRuntimeVisible=false` 与 `launchEnabled=false`。 -- Rust 定向测试通过: - - `CARGO_TARGET_DIR="src-tauri/target-codex-p3c-novoice" cargo test --manifest-path "src-tauri/Cargo.toml" --no-default-features runtime_skill_binding` - - 结果:`5` 个 runtime skill binding 测试通过,`1224` 个测试按过滤器跳过。 - - 首次编译曾被既有媒体任务编译问题阻断;已补最小阻塞修复后复跑通过。 -- 前端定向回归通过: - - `npm test -- "src/lib/api/agentRuntime/inventoryClient.test.ts" "src/features/capability-drafts/components/WorkspaceRegisteredSkillsPanel.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/lib/api/capabilityDrafts.test.ts"` - - 结果:`4` 个文件、`41` 个测试通过。 -- 运行时 API 目录校验通过: - - `npm run typecheck` - - `npx eslint "src/lib/api/agentRuntime.ts" "src/lib/api/agentRuntime/*.ts" --max-warnings 0` -- 命令契约通过: - - `npm run test:contracts` - - 结果:agent runtime generated manifest、command contracts、harness contracts、modality runtime contracts 与 cleanup report contract 均通过。 -- GUI smoke 复跑通过: - - `npm run verify:gui-smoke -- --reuse-running --timeout-ms 300000` - - 首次运行在 `smoke:knowledge-gui` 的文件管理器资料导入等待处失败;复跑通过 workspace ready、browser runtime、site adapters、service skill entry、runtime tool surface、Knowledge GUI 与 Design Canvas。 - -## P3C 收口结论 - -P3C runtime binding readiness projection 第一刀已达到本计划可交付门槛:P3B registered skill 可以在 `agent_runtime_* / inventory` 主链下被投影为 workspace skill binding candidate,并明确说明当前 binding status、next gate、来源 provenance 与权限摘要;但仍不会进入 Query Loop、SkillTool registry、默认 tool surface,也不会暴露运行、自动化或继续方法入口。 - -下一阶段应继续单独推进: - -```text -runtime binding readiness - -> workspace-scoped Query Loop metadata - -> tool_runtime 授权裁剪 - -> 当前 session 显式启用 generated skill - -> artifact / evidence 调用记录 -``` diff --git a/docs/exec-plans/creaoai-tool-runtime-authorization-p3e-plan.md b/docs/exec-plans/creaoai-tool-runtime-authorization-p3e-plan.md deleted file mode 100644 index efae23acc..000000000 --- a/docs/exec-plans/creaoai-tool-runtime-authorization-p3e-plan.md +++ /dev/null @@ -1,101 +0,0 @@ -# CREAO Tool Runtime Authorization P3E 执行计划 - -> 状态:P3E 第一刀已完成,进入 P4 前收口 -> 日期:2026-05-06 -> 主线:`Capability Draft -> verification -> workspace-local skill -> P3B discovery -> P3C readiness -> P3D Query Loop metadata -> P3E tool_runtime authorization` - -## 目标 - -P3E 只回答一个问题:已注册的 workspace-local Skill 如何在单个 session / turn 中经过显式 enable 后进入可调用边界。 - -本轮不做: - -1. Agent Marketplace / Skill Store。 -2. 长期自动化、scheduler 或后台 job。 -3. 绕过 `agent_runtime_submit_turn` 的平行执行命令。 -4. 把 P3D `workspace_skill_bindings` 只读 metadata 直接升级成可调用工具。 - -## 合同 - -新增 runtime metadata contract: - -```json -{ - "harness": { - "workspace_skill_runtime_enable": { - "source": "manual_session_enable", - "approval": "manual", - "workspace_root": "/abs/workspace", - "bindings": [ - { - "directory": "capability-xxxx", - "skill": "project:capability-xxxx", - "source_draft_id": "capdraft-...", - "source_verification_report_id": "capver-..." - } - ] - } - } -} -``` - -约束: - -1. `workspace_root` 必须与当前 turn 的 workspace root 一致。 -2. `bindings[].directory` 必须来自 P3C `ready_for_manual_enable` binding。 -3. `SkillTool` 只在当前 session scope 内启用,并裁剪到 allowlist 中的 Skill 名称。 -4. P3E metadata 本身不写 `allow_model_skills`,避免与 P3D 只读候选混淆。 -5. Workspace Skill 加载只由 runtime enable gate 触发;注册和 discovery 仍不 reload Skill。 - -## 任务 - -### P3E-0:边界确认 - -- [x] 确认 `agent_runtime_list_workspace_skill_bindings` 仍只做 readiness,不新增命令。 -- [x] 确认 P3E 继续走 `agent_runtime_submit_turn` metadata,不创建平行 runtime command。 - -### P3E-1:Rust runtime gate - -- [x] 增加 `workspace_skill_runtime_enable` 解析与 P3C readiness 校验。 -- [x] 明确校验 workspace root、registered skill directory 和 verification provenance。 -- [x] 显式加载当前 workspace `.agents/skills`,并把 `project:` 放入 session allowlist。 -- [x] 扩展 `LimeSkillTool` session gate:支持 all-access 与 allowlist 两种模式。 - -### P3E-2:Prompt 与前端 metadata - -- [x] 在 full runtime prompt 中投影 runtime enable scope,提示只能调用列出的 workspace-local Skill。 -- [x] 增加前端 metadata builder,输出 snake_case `workspace_skill_runtime_enable`,且不写 `allow_model_skills`。 -- [x] 在 Workspace 已注册能力面板接入“本回合启用”,跳转到 Agent 后只通过 `initialAutoSendRequestMetadata.harness.workspace_skill_runtime_enable` 显式授权当前回合,不写长期自动化配置。 -- [x] 将 P3E enable binding provenance 注入 `SkillTool` session source store,并在 ToolResult metadata 中写回 `workspace_skill_source` / `workspace_skill_runtime_enable`,让 timeline / evidence pack 能追踪 source draft、verification report、registered directory 与 session 授权范围。 - -### P3E-3:验证 - -- [x] Rust 定向测试:runtime binding service / runtime turn / agent SkillTool gate。 -- [x] 前端定向测试:workspace metadata builder / harness metadata builder / Workspace 已注册能力启用入口。 -- [x] 视命令契约变更情况运行 `npm run test:contracts`;本轮不新增命令,主要用于确认未漂移。 - -## 进度日志 - -### 2026-05-06 - -- P3E 第一刀已落到 current 主链:`agent_runtime_submit_turn -> request_metadata.harness.workspace_skill_runtime_enable -> SkillTool session allowlist`。 -- 保留 P3D 只读语义:`workspace_skill_bindings` 仍不打开 `allow_model_skills`,不代表可调用。 -- Workspace 已注册能力面板已补“本回合启用”入口:只在 P3C `ready_for_manual_enable` binding 上可用,自动发送首回合时注入 P3E metadata,不创建 automation / scheduler / marketplace。 -- 前端定向验证已通过:`npx vitest run src/components/agent/chat/utils/workspaceSkillBindingsMetadata.test.ts src/components/agent/chat/utils/harnessRequestMetadata.test.ts src/features/capability-drafts/components/WorkspaceRegisteredSkillsPanel.test.tsx src/components/skills/SkillsWorkspacePage.test.tsx`(4 files / 54 tests)。 -- 命令 / harness 契约验证已通过:`npm run test:contracts`。 -- 已补 evidence / timeline 的最小来源链路:P3E projection 会把每个 enabled binding 转为 session-scoped `SkillToolSessionSkillSource`,`LimeSkillTool` 执行结果会携带 `workspace_skill_source` 与 snake_case `workspace_skill_runtime_enable` metadata;由于 timeline tool call payload 已保留 ToolResult metadata,后续 evidence pack 可直接消费该字段进入 P4 Agent envelope。 -- Rust SkillTool gate 定向验证已通过:`CARGO_INCREMENTAL=0 CARGO_TARGET_DIR=/tmp/lime-p3e-agent-target cargo test -p lime-agent allowlisted_session_should_preserve_workspace_skill_source_metadata`(1 passed)。 -- Rust runtime turn 定向验证已通过:`CARGO_INCREMENTAL=0 CARGO_TARGET_DIR=/tmp/lime-p3e-agent-target cargo test -p lime --lib workspace_skill_runtime_enable_metadata_should_force_full_runtime_context`(1 passed)。 -- 最新校验已通过:`rustfmt --edition 2021 ...`、`git diff --check -- ...`、`npm run test:contracts`、前端 P3E vitest 定向套件、Rust SkillTool gate 定向测试和 Rust runtime turn 定向测试。 - -## P3E 收口结论 - -P3E 已完成当前计划中的最小可交付闭环: - -1. 注册后的 workspace-local skill 仍默认不可调用,只作为 P3B / P3C / P3D 的只读候选和 readiness 上下文。 -2. 当前 session 只有在 `request_metadata.harness.workspace_skill_runtime_enable` 显式携带 P3C ready binding 后才打开 `SkillTool`。 -3. `SkillTool` tool surface 被裁剪到 `project:` / `` allowlist,且不通过 `allow_model_skills` 偷开全局 skills。 -4. runtime gate 会校验 workspace root、registered skill directory、source draft、verification report 和 readiness provenance。 -5. 调用结果会写回 `workspace_skill_source` / `workspace_skill_runtime_enable` metadata,后续 P4 可直接用于 timeline、evidence pack 和 Agent envelope 展示。 - -下一刀应进入 P4:把成功运行后的 workspace-local skill 包成 Workspace 产品面的 Agent envelope 草案,并继续复用 `agent_runtime_submit_turn`、automation job、Managed Objective、artifact 和 evidence 主链。 diff --git a/docs/exec-plans/limenext-plan.md b/docs/exec-plans/limenext-plan.md deleted file mode 100644 index d3228c893..000000000 --- a/docs/exec-plans/limenext-plan.md +++ /dev/null @@ -1,412 +0,0 @@ -# LimeNext 总实施计划 - -> 状态:`legacy current reference` -> 更新时间:2026-04-18 -> 上位总纲:`docs/roadmap/limenext/` -> 当前主规划:`docs/roadmap/limenextv2/README.md` -> 目标:把 LimeNext 从“上位平台定义”推进到“可持续实施的主线计划”,统一产品对象、运行时骨架、远程入口、长时执行、证据治理与场景选品的推进顺序。 - -> 说明:本文保留旧阶段实施锚点与推进历史,帮助理解 `limenext -> limenextv2` 的迁移背景;后续 current 实现与新增文档默认不再以本文为主规格,而应回到 `docs/roadmap/limenextv2/README.md` 及其子专题。 - -## 1. 先给结论 - -LimeNext 当前不是缺一篇愿景文档,而是缺一条能持续推进的平台主线。 - -本计划固定一个判断: - -**后续提到“推进 LimeNext”,默认不是泛泛优化平台,而是沿着 `产品对象 -> 业务装配 -> 运行时骨架 -> 长时执行与远程 -> 证据治理 -> 场景选品` 这条主线推进。** - -## 2. 当前基线 - -已经完成: - -1. `docs/roadmap/limenext/` 专题包已建立。 -2. Lime 的 current 平台事实源已经分别收口到: - - `overview.md` - - `query-loop.md` - - `command-runtime.md` - - `task-agent-taxonomy.md` - - `remote-runtime.md` - - `state-history-telemetry.md` - - `skill-standard.md` -3. `ribbi/`、`command-runtime/`、`harness-engine/`、`product convergence`、`service skill cloud config` 等子专题已被回挂到 LimeNext 总图。 -4. `sceneapp-capability-model.md` 已补齐,固定了五类 `SceneApp`、五种 skill / scene 设计模式与九类底层能力模块的判断标准。 -5. `base-setup-decoupling.md` 已把“基础设置包”和宿主内核边界单独收口。 -6. 多模态组合型样板已进入 LimeNext 总纲,开始用 `composition blueprint` 统一表达组合蓝图。 -7. `composition-blueprint-schema.md` 已补出文档级 schema 草案,后续可以继续下沉到 validator 与目录投影。 -8. `base-setup-package-schema.md` 已把基础设置包补成顶层装配对象,开始明确“改包、改投影、改宿主”的判断线。 -9. `base-setup-projection-lifecycle.md` 已把装配包发布、灰度、seeded 兜底与回滚链收口成可讨论的事实源。 -10. `base-setup-implementation.md` 已把 validator / compiler / rollout gate 的第一版代码落点收口到现有 `ServiceSkillCatalog` 与 launch/runtime 锚点。 -11. `src/lib/base-setup/*` 已新增第一版代码骨架,开始把基础设置包下沉到实际 TypeScript 模块与单测。 -12. `src/lib/base-setup/storage.ts`、`bootstrap.ts` 已落地,把基础设置包快照、bootstrap 提取与 compat 编译链收口成独立模块。 -13. `src/lib/api/serviceSkills.ts`、`src/lib/serviceSkillCatalogBootstrap.ts` 已正式接入 `Base Setup Package` 主链,远端刷新与 bootstrap 同步都能直接消费装配包并落基础设置快照。 -14. 默认云端 seeded 目录已从手写 `ServiceSkillCatalog` 迁到手写 `Base Setup Package` + compat 编译产物,开始把装配层推进为真正的内置事实源。 -15. seeded 本地 `local_custom` 项也已迁到手写 `Base Setup Package` + compat 编译产物,`x-article-export` 不再依赖手写 `ServiceSkillItem` 补丁。 -16. `SceneApp` 的 `project pack` 合同已经从基础设置编译层正式接到产品读模型、目录详情页和经营评分页: - - 统一暴露 `deliveryProfile / compositionProfile / scorecardProfile` - - 目录页已经能说明最终交付部件、组合步骤和经营关注点 - - mock 与 Tauri seeded DTO 已同步对齐,避免只在前端测试里存在结构字段 -17. `project pack` 已继续接到真实 `run summary / scorecard` 聚合: - - `artifactCount` 不再是唯一运行结果语义 - - 运行详情已经能解释“交齐几项、还缺什么、卡在哪个失败信号” - - `project pack` 经营评分已改成 `complete_pack_rate / review_pass_rate / publish_conversion_rate` - - `observedFailureSignals / topFailureSignal` 已从真实运行样本回流到产品面 -18. `project pack` 第二阶段已开始接到 `session / evidence` 主链: - - `SceneApp run summary` 在拿到 `sessionId` 时会优先读取真实 `SessionDetail + FileArtifact` - - runtime verification failure 已开始回挂到 `review_blocked` - - 只有缺少 session evidence 时才回退 `AgentRun.metadata.artifact_paths` -19. `project pack` 已开始补齐结构化结果入口,而不是只在运行详情里展示 viewer 文案: - - `SceneAppRunSummary` 已新增稳定 `deliveryArtifactRefs` - - 结果入口会优先从 runtime evidence 解析真实会话产物,并在缺失 session evidence 时回退 metadata artifact path - - 前端已改为复用现有 Agent 文件预览入口打开主稿 / 结果文件,不新增新的 viewer 协议 -20. `project pack` 已把治理入口接到 SceneApp 运行详情,而不再只展示“已接入会话证据”的文字判断: - - `SceneAppRunSummary` 已新增稳定 `governanceArtifactRefs` - - Rust 会按 `sessionId` 组装 `evidence/summary.md` 与 `review/review-decision.*` 的稳定引用 - - 前端继续复用现有 Agent 文件预览入口打开证据摘要、人工复核记录与复核 JSON,不新增新的 SceneApp viewer 协议 -21. `project pack` 已开始把治理入口从“可打开”推进到“缺失时自动补生成”: - - 新增 `sceneapp_prepare_run_governance_artifact` 当前命令 - - SceneApp 页面点击治理入口时会先按制品类型触发 evidence / review 导出,再继续打开对应文件 - - 页面仍只消费 `src/lib/api/sceneapp.ts` 网关,不直接耦合 `agent_runtime_export_*` 命令名 -22. `project pack` 已继续把治理入口从“单文件打开”推进到“业务动作”: - - 运行详情已新增 `治理动作` 区块,而不只是列出治理文件 - - 当前已支持: - - `准备周会复盘包` - - `准备结构化治理包` - - 两类动作都会先经由 `src/lib/api/sceneapp.ts` 批量补齐 evidence / review 制品,再打开对应主治理文件 - - SceneApp 页面仍不直接理解底层 runtime export 命令,也不自己拼接治理路径 -23. `project pack` 已开始把治理能力从“单次运行详情”推进到“页面级治理看板”: - - `SceneAppsPage` 已新增独立 `治理看板` - - 当前会把 `run + scorecard + evidence / review` 翻译成业务向状态,而不是只展示底层技术字段 - - 目录主视图已经能判断这条场景当前更适合: - - 周会复盘 - - 生成 / 看板消费 - - 自动化任务跟进 - - 结果编辑 / 发布 - - 页面级治理动作继续复用 `src/lib/api/sceneapp.ts` 与既有文件打开链,不新增平行协议 -24. `SceneAppsPage` 已开始从“单页堆叠工作台”收口到“分页式信息架构”: - - 当前固定拆成 `场景目录 / 场景详情 / 治理复盘` 三个分页 - - `catalog` 只负责选品与筛选,不再同时承载详情和治理解释 - - 目录卡片点击后会直接进入对应 `detail` 分页,而不是只停留在选中态 - - 顶部继续保留“当前场景”摘要,确保分页切换时不丢业务上下文 - - `detail / governance` 已补齐分页级空态与回退动作,不再让用户停在无下一步的空白页 - - 顶部已新增业务向工作流导轨,明确表达 `选场景 -> 补启动 -> 看治理` 的跨页顺序 - - 这条规则已经同步写回 `docs/aiprompts/design-language.md`,作为后续复杂工作台默认设计约束 -25. `创作场景执行摘要` 已从启动瞬间静态摘要继续推进到生成页运行态回流: - - `AgentChatWorkspace` 当前会按 `sessionId -> sceneapp run` 回查最近运行 - - 生成页顶部摘要卡已开始展示 `delivery completion / runtime evidence / governance artifact / observed failure signal` - - `AppPageContent` 已修正 `sceneapps` keep-alive 树位,`创作场景 -> 持续流程 -> 创作场景` 往返不会再触发目录页重挂载 - - `useAppNavigation` 已升级为 `requested / committed` 双态导航,`AppSidebar + AppPageContent` 统一按请求态渲染,快速切换时以最后一次点击为准,不再出现主区短暂空白或左侧导航瞬时消失 - - `SceneAppsPage` 当前只允许在激活且拥有当前导航请求时回写 `sceneapps` 参数与 recent visit,keep-alive 的旧页不会再把全局导航抢回去 -26. `创作场景 -> 持续流程 / 自动化` 的事实源已经开始统一,而不是继续各讲各的: - - `AutomationJobDetailsDialog` 当前会识别 `sceneapp` 派生任务的 metadata,并回查同一条 `descriptor / project pack plan / run summary / scorecard` - - 自动化详情里已新增 `创作场景闭环` 摘要块,可直接回到 `创作场景` 准备页或治理复盘页 - - 自动化详情里的结果文件、治理文件与治理动作,当前已复用 `SceneAppRunDetailViewModel + prepare_run_governance_artifact` 主链,不再额外发明 automation 专用 pack/gov 协议 -27. `创作场景 -> 场景目录` 当前也已开始接到同一份经营事实源,而不是继续停留在静态标题目录: - - `SceneAppsCatalogPanel` 目录卡片已开始同时展示 `delivery contract / latest run / scorecard action / top failure signal / operating summary` - - `useSceneAppsPageRuntime` 会按全量 descriptor 聚合最近运行与 scorecard,并把它们回流到同一份目录读模型 - - 目录卡片、生成页顶部执行摘要与自动化详情当前共享同一组 `descriptor + latest run + scorecard` 语义,不再各自发明一套“当前状态”解释 -28. `project pack` 已开始从治理复盘单点入口继续扩到 `生成准备 / 经营评分` 的结果消费入口: - - `SceneAppDetailPanel` 与 `SceneAppScorecardPanel` 当前都会展示最近可消费的 `Project Pack` 结果入口,而不再只停留在 `viewerLabel` - - 当最新运行仍在执行或尚未带回结果文件时,页面会自动回退到最近一轮已交付样本,而不是让准备页与评分页只剩规划文案 - - 结果入口仍继续复用现有 Agent 文件预览打开链,不新增新的 `Project Pack viewer` 协议 -29. `project pack` 已继续扩到 `生成主执行面` 的直接结果消费入口: - - `useSceneAppExecutionSummaryRuntime` 当前不再只回流 `runtimeBackflow` 摘要,还会同步回流最近可消费的 `Project Pack` 结果样本 - - `SceneAppExecutionSummaryCard` 已新增 `最近可消费结果` 区块,生成页可以直接打开结果文件,不再只停留在顶部摘要和 `viewerLabel` - - `生成主执行面` 与 `创作场景` 页面当前共享同一条 `findLatestSceneAppPackResultRun + deliveryArtifactEntries + Agent 文件预览打开链` current 主链,不再各自维护一套结果入口逻辑 -30. `生成主执行面` 已开始补齐回闭环动作,而不再让用户自己在左侧重新找入口: - - 执行摘要卡当前已新增 `回生成准备 / 去治理复盘` 深链动作 - - `去治理复盘` 会优先带到最近可消费样本对应的 run,而不是只回当前可能仍在执行中的 run - - 执行摘要卡当前还可直接触发 `填写人工复核 / 可继续复用 / 继续观察 / 补证据 / 先别继续` - - 这些动作继续复用 `review decision` 主链与 `RuntimeReviewDecisionDialog`,生成页不再复制平行治理协议 -31. `生成主执行面` 已开始补齐第一批 `生成后动作编排`,而不再只是“看结果 + 跳页面”: - - 执行摘要卡当前会直接展示 `周会复盘 / 生成 / 看板 / 持续流程 / 自动化 / 结果编辑 / 发布` 的推荐去向 - - 生成页当前可直接执行 `准备周会复盘包 / 准备结构化治理包 / 打开基础治理材料 / 恢复底层运行入口` - - 生成页当前还可在同一会话里直接触发 `补齐缺失部件 / 发布前检查 / 进入发布整理 / 生成渠道预览稿 / 整理上传稿`,继续复用 `@发布合规 / @发布 / @渠道预览 / @上传` 与当前 turn 提交主链,而不新增新的发布协议 - - `AgentChatWorkspace` 与 `SceneAppsPage` 当前共享 `resolveSceneAppRunEntryNavigationTarget + prepareSceneAppRunGovernanceArtifact(s)` current 主链,不再各自维护一份 run entry 恢复逻辑 - - 这一步把 `生成` 从“结果页旁边的跳转入口”推进成了第一批真正的统一编排面 -32. `生成主执行面` 已开始直接消费当前会话里的发布后产物,而不再只负责发起发布动作: - - `AgentChatWorkspace` 当前会按 `taskFiles / sessionFiles / artifacts` 聚合最近一份 `发布稿 / 渠道预览稿 / 上传稿`,只消费已带 `contentPostIntent / contentPostLabel` metadata 的 current 发布产物,不把普通 `content-posts/*.md` 误判为投放结果 - - `SceneAppExecutionSummaryCard` 已新增 `最近发布产物` 区块,用户可直接从生成页打开刚刚整理出的发布稿、渠道预览稿和上传稿,不需要再去消息流或侧栏翻文件 - - 打开链继续复用现有工作区文件预览主链:优先打开 `task file / artifact`,没有内存态时再回落到 `session file` 读取,不新增新的 viewer 协议 - - 旧结论里若继续写“生成页当前只会触发发布后动作、还不能消费动作结果”,当前都按已过时理解 -33. `生成主执行面` 已开始补第一层发布态判断,而不再只把 `发布稿 / 渠道预览稿 / 上传稿` 平铺出来: - - `sceneAppExecutionContentPosts` 当前会继续检查同名 `*.cover.json / *.publish-pack.json` 伴随文件,并推导 `可继续发布 / 优先渠道预览 / 优先上传整理 / 待补封面信息、发布包` 这类轻量就绪态 - - `SceneAppExecutionSummaryCard` 的 `最近发布产物` 卡片当前会直接显示就绪标签与伴随材料芯片,用户在生成页就能看出这轮结果更适合继续发布、先看预览还是先补投放材料 - - 这一步仍然只复用现有 `content-posts` 文件命名约定与 session/task/artifact 三路事实源,不新增新的发布状态协议 - -尚未完成: - -1. 把 `ServiceSkill` 在产品面、目录面、运行时面和自动化面真正打通成同一个对象。 -2. 让所有样板场景都按统一 `SceneApp` 类型与能力模块声明接入。 -3. 把 `SceneScorecard` 与现有 evidence / tracker / artifact 数据链打通。 -4. 在 `docs/exec-plans/` 里建立 LimeNext 的持续推进日志与阶段风险管理。 -5. 把已完成的样板进一步接到 `Artifact + Evidence + Scorecard`。 -6. 把 `SceneScorecard` 从概念字段推进到可被聚合和查看的产品对象。 -7. 把“主 App 宿主内核”与“基础设置包”分层固定下来,减少场景扩张对客户端发版的依赖。 -8. 让基础设置包的 schema 继续下沉到 bootstrap / seeded catalog 可消费的目录投影。 -9. 把 `composition blueprint` 从文档口径继续收口到可校验、可投影的装配对象。 -10. 继续把 `project pack` 的结构化读模型从当前已接通的 `session / evidence + deliveryArtifactRefs` 优先聚合,扩展到更完整的 `artifact validator / request telemetry / evidence summary` 主链。 -11. 把 `project pack` 的治理闭环从当前已接通的“生成主执行面 + 场景目录 + 生成准备 + 治理复盘深链 + 经营评分 + 页面级治理看板 + 自动化详情 + 周会复盘包 / 结构化治理包 + 同聊补件 / 发布前检查 / 进入发布整理 / 渠道预览稿 / 上传稿 + 最近发布产物直接消费 + 发布态轻量判断”继续扩展到更完整的正式投放动作与更强的 evidence/review 闭环。 -12. 把装配包从已接通的 `service_skill_catalog + scene_catalog` 继续扩到 `command_catalog` 投影代码。 -13. 决定第一版是“客户端内编译 package”还是“服务端下发预编译 projection,客户端只做 gate + fallback”。 -14. 把剩余 seeded 来源继续收口,重点转到 `command` 与 automation 相关入口,不再保留新的手写 `local_custom` 补丁。 -15. 把分页式 `SceneAppsPage` 继续补成真正的多页面工作台;当前跨页入口、分页级空态和工作流导轨已补齐,剩余重点转到 GUI smoke 交付证明与更强的子页级信息头部。 - -## 3. 总目标 - -LimeNext 的实施总目标固定为: - -`目标输入 -> Scene / ServiceSkill -> Agent / Binding 执行 -> Artifact 交付 -> Evidence / Review 治理 -> Scorecard 评估 -> Keep / Incubate / Retire` - -## 4. 实施阶段 - -### P0:总纲固化 - -目标: - -- 让 LimeNext 平台定义稳定,不再来回摇摆。 -- 固定 `SceneApp` 的能力分类,不再只停留在“场景工作台”的口号层。 - -已完成: - -- `docs/roadmap/limenext/` 专题包 - -退出条件: - -- 后续讨论新专题时,能先声明它属于 LimeNext 哪一层。 -- 新样板进入实施前,能先写出 `sceneapp_type`、`pattern_primary / pattern_stack`、`infra_profile` 与 `composition_blueprint`。 - -### P1:产品对象收口 - -目标: - -- 统一 `ServiceSkill / Scene` 的产品对象语义 -- 把首页卡、技能页、slash scene、推荐方案挂到同一对象 - -依赖: - -- `docs/research/ribbi/*` -- `docs/roadmap/limenextv2/product-principles.md` -- `docs/roadmap/limenextv2/implementation-roadmap.md` -- `docs/roadmap/lime-service-skill-cloud-config-prd.md` - -退出条件: - -- 前台不再把 `skill bundle` 和 `ServiceSkill` 混成一个词 -- 首页与输入栏围绕同一场景对象表达 - -### P1.5:业务装配收口 - -目标: - -- 固定基础设置包与 `composition blueprint` 的角色边界 -- 让多模态组合场景能优先通过装配层下发,而不是频繁改主 App - -退出条件: - -- 团队能明确回答“什么改动只改基础设置包,什么改动必须升级宿主” -- 第一条组合型样板能被写成标准设计卡,而不是口头 workflow - -### P2:运行时骨架收口 - -目标: - -- 让 `Scene / ServiceSkill` 真正走统一运行时主链 - -依赖: - -- `docs/roadmap/gongneng/command-runtime/*` -- `docs/aiprompts/query-loop.md` -- `docs/aiprompts/command-runtime.md` - -退出条件: - -- 至少一条 `Agent + ServiceSkill` 样板链路与一条 `Agent + Task` 样板链路稳定成立 - -当前状态: - -- `@配音 / voice_runtime / cloud-video-dubbing` 已被选定并沉淀为第一条 `Agent + ServiceSkill` current 样板方案包 -- `x-article-export` 已被沉淀为第二条 `Agent + ServiceSkill` current 样板方案包,并覆盖 `site_adapter / browser_assist` 分支 - -### P3:长时执行与远程收口 - -目标: - -- 把 `subagent turn / automation job / channels runtime / browser connector` 纳入统一平台解释与实施顺序 - -依赖: - -- `docs/aiprompts/task-agent-taxonomy.md` -- `docs/aiprompts/remote-runtime.md` - -退出条件: - -- 团队不再把 OpenClaw compat shell 或 scheduler tick 当成长期主线 - -### P4:证据与治理闭环 - -目标: - -- 让 evidence / replay / review / dashboard 成为平台默认治理面 - -依赖: - -- `docs/aiprompts/state-history-telemetry.md` -- `docs/roadmap/harness-engine/*` - -退出条件: - -- 失败场景可以稳定回挂到 evidence -> analysis/review -> fix -> regress 主链 - -### P5:场景工厂 - -目标: - -- 建立 `SceneScorecard` -- 固定 launch / keep / incubate / retire 规则 - -依赖: - -- `docs/roadmap/limenext/metrics-and-selection.md` - -退出条件: - -- 平台能够系统性淘汰低价值场景,而不是只增不减 - -当前补充: - -- `Artifact / Evidence / Scorecard` 的业务样板与图示已经建立 -- `Local Durable SceneApp` 当前样板已固定为 `每日趋势摘要 / 账号增长跟踪` -- `x-article-export` 的当前产品合同已固定为“资料包优先 + 同一路径后处理” -- `Base Setup` 解耦规则已单独成文,开始固定“什么该下发,什么必须跟宿主升级” -- `project pack` 已不再只是 schema 词汇,而是已经进入 SceneApp 目录和经营评分读模型 -- `project pack` 已进一步接到真实 `run summary / scorecard` 聚合对象 -- `project pack` 已开始改成 `session / evidence` 优先聚合,而不是只看 tracker metadata -- `project pack` 已开始把真实结果文件入口接到 SceneApp 运行详情,不再只展示 viewer kind 文案 -- `project pack` 已开始把证据摘要 / 人工复核记录 / 复核 JSON 接到同一条运行详情治理面 -- `project pack` 已开始在治理入口点击时自动补生成 evidence / review 文件,而不是让用户先回到 Agent 手动导出 -- `project pack` 已开始把治理面升级成业务动作,当前可直接准备周会复盘包与结构化治理包 -- `project pack` 已开始把治理面抬到 SceneApp 页面级看板,而不再只停留在单次运行详情里 -- `project pack` 已开始把最近可消费结果入口接到 `生成主执行面`,不再只停留在 `创作场景` 子页消费 -- 下一步不再只是补页面,而是要把这套治理看板继续接到更完整的发布/复盘动作、选品口径和后续自动治理主链 - -## 5. 默认样板链路 - -后续实施默认至少推进五条样板: - -1. `Agent + ServiceSkill` - - 第一条 current 样板:`@配音 / voice_runtime` - - 第二条 current 样板:`x-article-export` -2. `Agent + Task` - - `@配图` -3. `Prompt 型` - - `@总结` 或 `@分析` -4. `automation job` - - `每日趋势摘要` - - `账号增长跟踪` -5. `Multimodal Composition` - - `文本 -> 线框图 -> 配乐 -> 剧本 -> 短视频草稿` - -固定补充规则: - -- 每条样板都必须显式声明: - - `sceneapp_type` - - `pattern_primary` - - `pattern_stack` - - `infra_profile` - - `composition_blueprint` - - `execution_entity` - - `runtime_binding` - - `storage_strategy` - - `delivery_contract` - -推荐先从三句最短版开始写: - -- 这是什么类型的 `SceneApp` -- 它内部主要按什么模式组织 -- 它到底调用了哪些基础设施 - -## 6. 当前优先顺序 - -当前建议优先顺序固定为: - -1. 先按 `SceneApp` 能力模型收口样板声明标准 -2. 继续收口 `ServiceSkill` 作为产品对象 -3. 以 `@配音 / voice_runtime` 作为第一条 `Cloud-managed SceneApp` 样板进入实施 -4. 以 `x-article-export` 作为第一条 `Browser-grounded SceneApp` 样板进入实施 -5. 以 `每日趋势摘要 / 账号增长跟踪` 作为第一条 `Local Durable SceneApp` 样板进入实施 -6. 以多模态组合短视频草稿作为第一条 `Hybrid SceneApp` 样板进入实施 -7. 把五条样板链路接到 `Artifact + Evidence + Scorecard` - -当前不建议优先做: - -1. 扩目录数量 -2. 新增更多 compat 入口 -3. 新造一层平行 runtime - -## 7. 风险 - -### 风险 1:继续把 Lime 误讲成 `skills runtime` - -处理: - -- 所有执行文档都保持 `Skill / ServiceSkill / Scene / Artifact / Evidence / Scorecard` 分层 - -### 风险 2:把设计模式误当成产品对象 - -处理: - -- 文档中固定区分 `ServiceSkill / Scene` 与 `pattern_primary / pattern_stack` -- 不再出现“这是个 Pipeline 产品”这类混层说法 - -### 风险 3:只做总纲,不接实施 - -处理: - -- 本计划与进度日志持续更新 -- 每进入实现阶段,回挂具体子专题与验证命令 - -### 风险 4:只做治理减法,不回主线交付 - -处理: - -- 连续两轮主要在做治理后,下一轮必须回到样板场景交付 - -## 8. 当前下一刀 - -当前下一刀建议固定为: - -**把 LimeNext 从“durable automation 已回到装配主链”推进到“gate 定版与组合交付主链收口”。** - -当前已经成立的恢复协议: - -1. `automation -> automation job` -2. `chat / skill -> agent session` -3. `browser_assist -> browser runtime` -4. `cloud_scene -> structured cloud scene resume` -5. `native_skill -> structured service skill resume` - -当前已经补齐的装配收口: - -1. 保持 `SceneAppRunSummary` 继续只暴露稳定恢复引用,而不是让 UI 直接理解底层 metadata: - - `sourceRef` - - `sessionId` - - `browserRuntimeRef` - - `cloudSceneRuntimeRef` - - `nativeSkillRuntimeRef` - - `deliveryArtifactRefs` -2. durable 场景的 automation projection / fallback 已继续收回同一装配主链: - - `Base Setup Package` 已支持 `automationProfiles[]` - - `catalogProjection.automationProfileRef` 已进入 validator / parser / projection metadata / snapshot index - - durable seeded 样板已显式声明 automation profile - - `service-skills/automationDraft.ts` 现已优先消费装配层 schedule / delivery / retry / enabled 预设 -3. `browser-runtime` GUI smoke 与 `verify:local` 当前已重新通过,GUI 交付门槛不再被此前的 CDP 环境问题卡住 - -当前下一步转为: - -1. 决定客户端编译 vs 服务端预编译 gate 的最终定版位置 -2. `创作场景 -> 生成` 的执行摘要、`自动化详情`、`场景目录`、`生成准备` 和 `经营评分` 都已经接通运行态回流;下一步把同一份 `Project Pack + governance` 基线继续扩到生成主执行面的直接结果消费与更完整的治理消费入口 -3. 把 `SceneScorecard` 与周会模板、页面级治理看板和生成口径继续打通 -4. 继续让 automation detail / SceneApp run / scorecard 聚合消费同一组 base-setup refs,而不是回退到运行时猜测 - -这样 LimeNext 才会从“目录、启动、复盘、恢复、durable 装配都闭环”继续推进到“装配 gate 定版、组合交付与经营聚合也闭环”。 diff --git a/docs/exec-plans/limenext-progress-from-finder-edit.md b/docs/exec-plans/limenext-progress-from-finder-edit.md deleted file mode 100644 index f111d8716..000000000 --- a/docs/exec-plans/limenext-progress-from-finder-edit.md +++ /dev/null @@ -1,14 +0,0 @@ -# LimeNext 推进日志(临时镜像) - -这份文件是 2026-04-22 为绕过 macOS `Documents` 目录 `EPERM` 问题而临时创建的 Finder 镜像,不是正式事实源。 - -当前请统一以: - -1. `docs/exec-plans/limenext-progress.md` - -作为唯一有效的 LimeNext 推进日志。 - -补充说明: - -1. 这份镜像文件不再继续更新。 -2. 若后续文件系统权限恢复,可直接清理这份临时镜像。 diff --git a/docs/exec-plans/limenext-progress-from-finder.md b/docs/exec-plans/limenext-progress-from-finder.md deleted file mode 100644 index f111d8716..000000000 --- a/docs/exec-plans/limenext-progress-from-finder.md +++ /dev/null @@ -1,14 +0,0 @@ -# LimeNext 推进日志(临时镜像) - -这份文件是 2026-04-22 为绕过 macOS `Documents` 目录 `EPERM` 问题而临时创建的 Finder 镜像,不是正式事实源。 - -当前请统一以: - -1. `docs/exec-plans/limenext-progress.md` - -作为唯一有效的 LimeNext 推进日志。 - -补充说明: - -1. 这份镜像文件不再继续更新。 -2. 若后续文件系统权限恢复,可直接清理这份临时镜像。 diff --git a/docs/exec-plans/limenext-progress.md b/docs/exec-plans/limenext-progress.md deleted file mode 100644 index d328675ad..000000000 --- a/docs/exec-plans/limenext-progress.md +++ /dev/null @@ -1,6598 +0,0 @@ -# LimeNext 推进日志 - -> 注:自 2026-04-19 起,LimeNext current 前台主词固定为 `我的方法 / 灵感库 / 生成`。历史日志里若继续出现 `技能 / SceneApp / 创作场景 / Project Pack / 复盘 / 记忆工作台 / 任务工作台 / 任务视图` 等词,默认按当时实现阶段或 compat 旧称理解,不再代表 current 产品口径。 -> -> 补充说明:2026-04-17 中段几次关于“纯标题目录 / 无图场景墙”的尝试,当前都已被后续 `经营信号目录卡片` 方案取代。阅读本日志时,凡旧条目仍写“纯标题目录”,都按已废弃试探理解;current 以最新“目录卡片经营信号回流”条目为准。 -> -> 补充说明(2026-04-18):旧 Ribbi 过渡目录已清理。历史条目若继续出现旧 Ribbi 路径,默认按“当时旧路径、现已由 `docs/research/ribbi/*` 替代”理解。 -> -> 补充说明(2026-04-22):`sceneapp` 对象级 `SceneAppCurrent*` 过渡类型已全部删除。历史日志若继续出现 `SceneAppCurrentDescriptor / SceneAppCurrentPlanResult / SceneAppCurrentCatalog` 等表述,默认按当时过渡阶段理解;current 事实源已切回 base `SceneAppDescriptor / SceneAppCatalog / SceneAppPlanResult`,current 标量只保留 `SceneAppExecutorBindingFamily / SceneAppExecutionRuntimeAction / SceneAppType / SceneAppLaunchRequirementCoreKind`。 - -## 2026-04-27 - -### 已完成 - -- 修正任务中心在同一 `claw` 页面内通过左侧导航切换会话时,顶部 open tabs 把“旧会话 + 新会话”一起保留下来的回灌问题,并顺手把这条切换链路的前台预览态收口到“只显示目标会话”: - - 已更新: - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/agent/chat/index.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 之前从左侧“最近对话 / 归档”进入另一条会话时,`initialSessionId` 虽然已经换成目标会话,但任务中心在 `switchTopic` 真正完成前,`reconcileTaskCenterTabIds(...)` 又把旧 `sessionId` 当成当前会话塞回 open tabs,导致用户看到“明明只打开一个,却又冒出多个任务 tab” - - 当前已把这段“路由切换中”状态单独收口:只要 `initialSessionId !== sessionId`,任务中心会先把顶部预览态锁到目标会话,并在 reconcile 阶段禁止把旧 session 回灌回来 - - 这样处理后,左侧导航打开普通会话时,顶部只保留目标会话;打开归档会话时,也不会继续显示旧的普通任务 tab - - 这次顺手也验证了“打开慢”主观感受里有一部分来自错误的前台过渡:之前用户点击后先看到旧 tab,再晚一点跳到新 tab,看起来像卡住;现在至少顶部导航会立即对齐目标会话,不再制造额外错觉 - - 当前定向验证: - - `npm run test -- "src/components/agent/chat/index.test.tsx" -t "任务中心初始会话标签|已在任务中心内切到另一条导航会话时,不应把旧标签回灌回来|已在任务中心内切到归档导航会话时,不应继续显示旧的普通任务标签"` - - `npx eslint "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/index.test.tsx"` - - `npm run verify:gui-smoke` - - 结果: - - 任务中心相关定向 `vitest` 通过:新增的“会话内再切普通会话 / 会话内再切归档会话”两条回归都已通过 - - 定向 `eslint` 通过 - - `verify:gui-smoke` 通过:`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` 当前都已跑通,说明这次任务中心状态修正没有把 GUI 主路径打断 - -## 2026-04-25 - -### 已完成 - -- 对齐 `docs/research/ribbi/command-inventory.md` 里仍可安全挂到 `research` current 主链的搜索别名,把 `@Search Agent` 与 `@Instagram Research` 收进现有搜索命令,而不是新增搜索型 agent / 社媒研究协议: - - 已更新: - - `src/components/agent/chat/utils/searchWorkbenchCommand.ts` - - `src/components/agent/chat/utils/searchWorkbenchCommand.test.ts` - - `src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx` - - `src/lib/base-setup/seededCommandPackage.ts` - - `src/lib/base-setup/seededCommandPackage.test.ts` - - `src/lib/api/skillCatalog.test.ts` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `@Search Agent` 当前只是 `research` 的前台别名,不会把 Lime 带回“模型 agent 槽位”那套协议 - - `@Instagram Research` 当前也继续走 `research_skill_launch`,但在未显式声明站点时会自动补 `site=Instagram` - - 这样做对齐的是前台命令习惯,而不是新增第二套社媒研究 runtime;recent usage、catalog trigger 与发送链当前都已同步打通 - -- 对齐 `docs/research/ribbi/command-inventory.md` 里的 `@Image Logo Decomposition`,把它收成 Lime current 的 `@Logo拆解 / @Image Logo Decomposition` 前台命令,但底层继续复用 `analysis` 主链,不新增第二套媒体拆解协议: - - 已更新: - - `src/components/agent/chat/utils/logoDecompositionWorkbenchCommand.ts` - - `src/components/agent/chat/utils/logoDecompositionWorkbenchCommand.test.ts` - - `src/components/agent/chat/workspace/useWorkspaceSendActions.ts` - - `src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx` - - `src/components/agent/chat/utils/mentionCommandReplayText.ts` - - `src/components/agent/chat/utils/mentionCommandReplayText.test.ts` - - `src/lib/base-setup/seededCommandPackage.ts` - - `src/lib/base-setup/seededCommandPackage.test.ts` - - `src/lib/api/skillCatalog.test.ts` - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `@Logo拆解` 当前已成为 Lime 自己的前台命令,且继续兼容直接输入 `@Image Logo Decomposition` - - 底层没有新增 `logo_*` runtime;仍统一复用 `analysis_skill_launch -> Skill(analysis)` current 主链 - - 当前会把入口来源固定为 `at_logo_decomposition_command`,并额外带上 `analysis_mode=image_logo_decomposition`,让首刀更聚焦图片 / Logo 结构拆解,而不是退回泛分析 - - 最近使用回放、命令目录、输入面板能力分组也已同步补齐;这条命令现在不只是命名对齐,而是能真正进入发送链 - -- 对齐 `docs/research/ribbi/command-inventory.md` 的文件阅读能力,把新前台入口 `@读文件 / @Read File Content` 收进现有 `summary` current 主链,而不是新开第二套文件读取协议: - - 已更新: - - `src/components/agent/chat/utils/fileReadWorkbenchCommand.ts` - - `src/components/agent/chat/utils/fileReadWorkbenchCommand.test.ts` - - `src/components/agent/chat/workspace/useWorkspaceSendActions.ts` - - `src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx` - - `src/components/agent/chat/utils/mentionCommandReplayText.ts` - - `src/components/agent/chat/utils/mentionCommandReplayText.test.ts` - - `src/lib/base-setup/seededCommandPackage.ts` - - `src/lib/base-setup/seededCommandPackage.test.ts` - - `src/lib/api/skillCatalog.test.ts` - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `src-tauri/src/commands/aster_agent_cmd/summary_skill_launch.rs` - - `src-tauri/src/commands/aster_agent_cmd/tests.rs` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `@读文件` 当前已作为新的前台投影落到 `file_read_runtime`,但底层没有新增协议;仍继续复用 `summary_skill_launch.kind=summary_request` - - 文件路径当前会结构化写入 `request_metadata.harness.summary_skill_launch.summary_request.source_path`,并把入口来源固定为 `at_file_read_command` - - 最近使用回放、裸命令补全和能力分组当前也已同步补齐;`@读文件` 不再只是“目录里有”,而是能真正进入发送链、回放链和输入面板 - - Rust 侧 `summary_skill_launch` 当前也会显式识别并提示 `source_path`,让模型首刀更稳定地围绕给定文件做总结,而不是退回普通聊天或先去探测工具目录 - - 当前定向验证: - - `npx vitest run "src/components/agent/chat/utils/fileReadWorkbenchCommand.test.ts" "src/components/agent/chat/utils/mentionCommandReplayText.test.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" "src/lib/base-setup/seededCommandPackage.test.ts" "src/lib/api/skillCatalog.test.ts"` - - `npx eslint "src/components/agent/chat/utils/fileReadWorkbenchCommand.ts" "src/components/agent/chat/utils/fileReadWorkbenchCommand.test.ts" "src/components/agent/chat/utils/mentionCommandReplayText.ts" "src/components/agent/chat/utils/mentionCommandReplayText.test.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/lib/base-setup/seededCommandPackage.ts" "src/lib/base-setup/seededCommandPackage.test.ts" "src/lib/api/skillCatalog.test.ts"` - - `cd src-tauri && cargo test test_merge_system_prompt_with_summary_skill_launch` - - `npm run verify:gui-smoke` - - 结果: - - 上述前端定向 `vitest` 当前已通过:`5 files / 168 tests passed` - - 定向 `eslint` 当前已通过 - - Rust 定向测试当前已通过:`2 passed / 0 failed` - - `verify:gui-smoke` 本轮已成功拉起 `DevBridge`,并继续跑到 `smoke:site-adapters`;但因为这次使用独立临时 Cargo target 冷编译、耗时过长,当前未等待到最终整组 smoke 结论,已手动停止 - -- 把 `新建任务 / EmptyState` 首页主区从“顺序堆叠的信息货架”重排成更接近参考图的 `输入主舞台 + tab 化入口 deck`,避免首屏仍像说明页而不是开工页: - - 已更新: - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/Inputbar/styles.ts` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 首页推荐区当前不再把 `主推荐 / 其他起手结果 / 继续上次做法 / 做法入口` 全部顺序摊开;现在先收成一块带 tab 的入口 deck,默认聚焦 `推荐起手`,并按 `继续上次 / 做法入口` 分层切换 - - `推荐起手` 当前仍保留 `主推荐大卡 + 次级卡` 的结果导向结构,但卡区已经收进统一 surface,不再像三段说明区那样散开 - - `继续上次` 与 `做法入口` 当前正式拆成两套前台口径;不再沿用旧的 `directMethodItems` 回退逻辑把最近记录重复渲染到“做法入口”里 - - 首页大输入框当前也同步加厚成更明确的主卡壳:圆角、边框、阴影和底部轻设置区都更接近首页主舞台,而不是通用聊天输入条 - - 当前定向验证: - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/Inputbar/styles.ts"` - - `pnpm vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx"` - - `npm run verify:gui-smoke` - - 结果: - - `eslint` 通过 - - `vitest` 通过:`2 files / 73 tests passed` - - `verify:gui-smoke` 通过:`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` 当前都已跑通,说明这轮首页壳层重排没有把 GUI 主路径打断 - -- 把 `我的方法 -> launcher` 里的参考对象头部从“来源 / 分类 / tag 标签墙”收成轻量元信息,并同步把方法页搜索提示从对象词改成动作词: - - 已更新: - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `CuratedTaskLauncherDialog` 里的参考对象卡当前不再把 `来源 / 分类 / tag` 堆成一排 pill;现在先给一条 `来源 · 类型` 元信息,再把 tag 收成正文里的 `相关线索` - - 用户当前进入 launcher 时,会更先看到“这条参考是什么、为什么和这轮有关”,而不是像在看素材目录标签 - - `我的方法` 页搜索框当前也不再写 `站点或做法标题` 这类对象化提示,而是统一成 `搜索想拿的结果、这一步或做法名` - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run verify:gui-smoke` - -- 把 `service skill / 我的方法 / 首页结果模板` 里还残留的“工作区 / 补参 / 创建任务”系统动作词继续压回 `生成` 主链,避免首页、方法页和做法入口已经切到结果口径后,实际按钮、提示和结果去向仍把用户拉回旧心智: - - 已更新: - - `src/components/agent/chat/service-skills/skillPresentation.ts` - - `src/components/agent/chat/service-skills/skillPresentation.test.ts` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/agent/chat/workspace/useWorkspaceServiceSkillEntryActions.ts` - - `src/components/agent/chat/utils/curatedTaskTemplates.ts` - - `src/components/agent/chat/utils/workflowStepPresentation.ts` - - `src/components/agent/chat/utils/toolProcessSummary.ts` - - `src/components/agent/chat/utils/toolProcessSummary.test.ts` - - `src/components/agent/chat/utils/toolDisplayInfo.ts` - - `src/components/agent/chat/utils/toolDisplayInfo.test.ts` - - `src/components/memory/MemoryPage.tsx` - - `src/components/memory/MemoryPage.test.tsx` - - `src/lib/api/serviceSkills.ts` - - `src/components/settings-v2/system/automation/index.tsx` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `service skill` 当前已统一从 `对话内补参 / 创建任务 / 创建跟踪 / 进入工作区` 收成 `开始这一步 / 开始持续 / 开始跟进 / 补齐这一步 / 接着继续` - - `service skill` 的运行说明与结果去向当前也已统一改成 `回到生成 / 回到当前内容`,不再默认把用户带回 `当前工作区` - - `我的方法` 页里与继续开工直接相关的入口说明、回跳 banner、已沉淀方法说明和草稿 CTA 当前也同步改成 `回到生成 / 把这轮做下去`,不再继续暴露 `补参` 口径 - - 首页 `service skill` 推荐卡当前已把缺信息提示收成 `补齐这一步后开始`,结果模板里 `长文转多平台发布稿` 的结果去向也同步改成当前内容 / 生成口径 - - workflow 空态进度当前已从 `等待创建任务` 收成 `等待开始`,避免做法流程 rail 再把用户拉回旧任务系统 - - runtime 工具过程提示当前也已把 `先创建任务 / 已创建任务 / 创建任务中` 收成 `先开始这一步 / 已开始 / 开始中`,避免做法已经回到 `生成`,但执行经过又重新掉回旧任务系统 - - `灵感库` 当前把结果模板回跳 banner 也统一成 `回到生成 / 把这轮做下去`;`serviceSkills` 底层兜底结果去向与自动化入口标题也已同步跟上,不再只在前台卡片层换词 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/service-skills/skillPresentation.test.ts" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/workspace/useWorkspaceServiceSkillEntryActions.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/utils/curatedTaskTemplates.test.ts" "src/components/agent/chat/utils/workflowStepPresentation.test.ts"` - - `npm exec vitest run "src/components/agent/chat/utils/toolProcessSummary.test.ts" "src/components/agent/chat/utils/toolDisplayInfo.test.ts"` - - `npm exec vitest run "src/components/memory/MemoryPage.test.tsx" "src/lib/api/serviceSkills.test.ts"` - - `npx eslint "src/components/agent/chat/service-skills/skillPresentation.ts" "src/components/agent/chat/service-skills/skillPresentation.test.ts" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/workspace/useWorkspaceServiceSkillEntryActions.ts" "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/utils/workflowStepPresentation.ts"` - - `npx eslint "src/components/agent/chat/utils/toolProcessSummary.ts" "src/components/agent/chat/utils/toolProcessSummary.test.ts" "src/components/agent/chat/utils/toolDisplayInfo.ts" "src/components/agent/chat/utils/toolDisplayInfo.test.ts"` - - `npx eslint "src/components/memory/MemoryPage.tsx" "src/components/memory/MemoryPage.test.tsx" "src/lib/api/serviceSkills.ts" "src/components/settings-v2/system/automation/index.tsx"` - - `npm run verify:gui-smoke` - - 结果: - - 上述前台口径收口相关定向 `vitest`、`eslint` 与 `verify:gui-smoke` 当前都已通过;说明首页 / 我的方法 / service skill / 灵感库 / automation 入口这一组 current 主词已经能在现有 GUI 主链里稳定共存 - -- 把 `持续流程` 页当前还残留的旧 `任务 / 工作区 / 自动化任务` 词继续压回 current 前台对象,避免 `系统 -> 持续流程` 已经是正式入口,但弹窗、概览、健康面板、详情摘要和 sceneapp 回流文案仍把用户拉回旧自动化任务系统: - - 已更新: - - `src/components/settings-v2/system/automation/AutomationJobDialog.tsx` - - `src/components/settings-v2/system/automation/AutomationJobDetailsDialog.tsx` - - `src/components/settings-v2/system/automation/AutomationOverviewFocusCard.tsx` - - `src/components/settings-v2/system/automation/AutomationHealthPanel.tsx` - - `src/components/settings-v2/system/automation/index.tsx` - - `src/components/settings-v2/system/automation/automationPresentation.ts` - - `src/components/settings-v2/system/automation/serviceSkillContext.ts` - - `src/components/settings-v2/system/automation/useAutomationSceneAppRuntime.ts` - - `src/lib/sceneapp/product.ts` - - `src/lib/sceneapp/presentation.ts` - - `src/components/settings-v2/system/automation/AutomationJobDialog.test.tsx` - - `src/components/settings-v2/system/automation/AutomationJobDetailsDialog.test.tsx` - - `src/components/settings-v2/system/automation/AutomationOverviewFocusCard.test.tsx` - - `src/components/settings-v2/system/automation/AutomationHealthPanel.test.tsx` - - `src/components/settings-v2/system/automation/index.test.tsx` - - `src/lib/sceneapp/product.test.ts` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `持续流程` 弹窗头部、详情页、默认列表、概览卡与健康面板当前已统一改用 `持续流程 / 归属 / 开始方式 / 当前状态 / 当前起手内容`,不再继续暴露 `任务详情 / 任务类型 / 工作区 / 未填写任务描述` 这一套旧对象词 - - `service skill` 在 `持续流程` 页里的摘要、上下文和运行上下文当前也已统一成 `技能流程 / 定时运行 / 技能:...`,避免自动化页里又长回第二套 `技能任务` 语言 - - 输出投递说明当前也已同步收成 `运行完成后投递 / 投递失败不阻塞本轮 / 投递失败记为本轮失败`,不再把失败策略继续表述成旧任务执行语义 - - `sceneapp` 回流到 `持续流程` 详情和概览卡时,当前摘要源也不再生成 `自动化任务 / 最近投放任务 / 打开自动化任务`,而是统一成 `持续流程 / 最近运行 / 打开持续流程` - - 因此这一步继续服务 P1 前台对象语言收口:`系统 -> 持续流程` 当前终于不只是入口名称变了,而是页面内外的 current 文案也开始围绕同一条持续流程主词收敛 - - 当前定向验证: - - `npm exec vitest run "src/components/settings-v2/system/automation/AutomationJobDialog.test.tsx" "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.test.tsx" "src/components/settings-v2/system/automation/AutomationOverviewFocusCard.test.tsx" "src/components/settings-v2/system/automation/AutomationHealthPanel.test.tsx" "src/components/settings-v2/system/automation/index.test.tsx" "src/lib/sceneapp/product.test.ts"` - - `npx eslint "src/components/settings-v2/system/automation/AutomationJobDialog.tsx" "src/components/settings-v2/system/automation/automationPresentation.ts" "src/components/settings-v2/system/automation/serviceSkillContext.ts" "src/components/settings-v2/system/automation/AutomationOverviewFocusCard.tsx" "src/components/settings-v2/system/automation/AutomationHealthPanel.tsx" "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.tsx" "src/components/settings-v2/system/automation/index.tsx" "src/components/settings-v2/system/automation/useAutomationSceneAppRuntime.ts" "src/lib/sceneapp/presentation.ts" "src/lib/sceneapp/product.ts" "src/components/settings-v2/system/automation/AutomationJobDialog.test.tsx" "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.test.tsx" "src/components/settings-v2/system/automation/AutomationOverviewFocusCard.test.tsx" "src/components/settings-v2/system/automation/AutomationHealthPanel.test.tsx" "src/components/settings-v2/system/automation/index.test.tsx" "src/lib/sceneapp/product.test.ts"` - - `npm run verify:gui-smoke` - - 结果: - - 自动化页与 sceneapp 摘要源相关定向 `vitest` 通过:`6 files / 51 tests passed` - - 定向 `eslint` 通过 - - `verify:gui-smoke` 通过:`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` 当前都已跑通,说明这轮 `持续流程` 前台收口没有把 GUI 主路径打断 - -- 把 `消息渠道` 页当前还残留的旧 `联调 / 调试 / 高级工作台` 技术词收轻一层,避免 `系统 -> 消息渠道` 虽然已经是 current 正式入口,但首页说明、接入检查和日志页标题仍然更像开发工具面,而不是系统辅助页: - - 已更新: - - `src/components/channels/ImConfigPage.tsx` - - `src/components/settings-v2/system/channels/ChannelsDebugWorkbench.tsx` - - `src/components/channels/ImConfigPage.test.tsx` - - `src/components/settings-v2/system/channels/ChannelsDebugWorkbench.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `消息渠道` 首页当前已把说明文案从 `对话和投递` 收成更明确的 `消息接收 / 回复 / 结果投递`,避免用户一进来先读到系统内部词 - - 各渠道卡片里的 `联调检查` 当前已统一收成 `接入检查`,查看入口也改成 `查看日志与检查`,不再直接暴露开发排障语气 - - 下方折叠区与 `ChannelsDebugWorkbench` 当前也已统一从 `联调与排查` 收成 `日志与检查`,继续保留 current 运行排查能力,但不再把当前页面说成另一套调试工作台 - - `ImConfigPage` 里的折叠头当前顺手修掉了一处嵌套 `button` 结构警告,避免 `WorkbenchInfoTip` 继续在当前页触发 DOM nesting warning - - 因此这一步继续服务 P1 前台对象语言收口:`系统 -> 消息渠道` 当前不再一边叫“消息渠道”,一边在核心说明层继续用 `联调 / 调试` 这套旧技术面口径 - - 当前定向验证: - - `npm exec vitest run "src/components/channels/ImConfigPage.test.tsx" "src/components/settings-v2/system/channels/ChannelsDebugWorkbench.test.tsx"` - - `npx eslint "src/components/channels/ImConfigPage.tsx" "src/components/channels/ImConfigPage.test.tsx" "src/components/settings-v2/system/channels/ChannelsDebugWorkbench.tsx" "src/components/settings-v2/system/channels/ChannelsDebugWorkbench.test.tsx"` - - `npm run verify:gui-smoke` - - `npm run smoke:agent-runtime-tool-surface-page` - - 结果: - - `消息渠道` 相关定向 `vitest` 通过:`2 files / 9 tests passed` - - 定向 `eslint` 通过 - - `verify:gui-smoke` 本轮未拿到最终通过;`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface` 均已通过,但最后 `smoke:agent-runtime-tool-surface-page` 两次都停在 `wait-empty-state`,报 `等待 首页空态加载 超时` - - 该超时链路与本轮 `消息渠道` 页面不在同一路径;当前先按仓库现有环境 / 主壳 smoke 波动记录,不把它直接记成 `消息渠道` 页回归 - -- 把 `resources / 项目资料` 页与相邻图片、视频同步提示里的旧 `资料库 / 资料分类 / 项目素材库` 继续压回 `项目资料` 口径,避免辅助页标题已经换了,但页内说明、切换区和结果同步提示仍停在旧库心智: - - 已更新: - - `src/components/resources/ResourcesPage.tsx` - - `src/components/resources/ResourcesPage.test.tsx` - - `src/components/resources/ResourcesImageWorkbench.tsx` - - `src/components/resources/ResourcesImageWorkbench.test.tsx` - - `src/components/memory/MemoryPage.tsx` - - `src/components/memory/MemoryPage.test.tsx` - - `src/i18n/patches/zh.json` - - `src/i18n/patches/en.json` - - `src/i18n/__tests__/translation-coverage.test.ts` - - `src/components/image-gen/README.md` - - `src/components/workspace/media/ImageGallery.tsx` - - `src/lib/governance/legacySurfaceCatalog.json` - - `src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx` - - `src/lib/serviceModels.test.ts` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `src/components/workspace/video/VideoWorkspace.tsx` - - `src/components/workspace/video/VideoTipsBehavior.test.tsx` - - `docs/roadmap/limenextv2/entry-migration-map.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `项目资料` 页首 tips 当前已从“导入资源 / 项目资料 / 外部素材”这套旧对象说明,收成更直接的 `当前项目里的文档、图片和导入内容` - - 迁移提示条当前也已统一成 `浏览 / 补图 / 整理`,并明确 `回生成 / 去灵感库`,不再继续强调“默认主导航”这类入口治理术语 - - 左侧 `资料分类` 当前已改成 `内容分类`,项目切换区也不再继续把自己讲成“项目资料主入口” - - 跨项目图片提示、未选项目提示和空态说明当前已统一回 `当前项目 / 项目资料` 口径,不再出现 `资料库` - - `灵感库` 首屏里的 `项目资料` 辅助入口说明当前也已从 `项目素材` 收回 `项目资料 / 导入内容`,避免 `灵感库 -> 项目资料` 回桥继续暴露旧对象 - - 图片工作台发给画布的来源名,以及视频工作台里的同步提示、摘要卡和成功状态当前也已统一从 `项目素材库 / 项目素材` 收成 `项目资料` - - `i18n` patch、`translation coverage`、`image-gen` README、治理目录和 `ImageGallery` 注释里的旧 `资料库 / 项目素材` 现在也已统一改成 `项目资料` - - `Inputbar` 工作流示例、`@素材` 提词重写夹具和 `serviceModels` 配置夹具里的旧 `检索项目素材 / 资料库语义 / 资料库上下文` 也已同步收回 `项目资料` - - `entry-migration-map` 里的 current 页面语义与后续目标当前也已从 `项目资源 / 导入素材 / 项目素材浏览能力` 收成 `项目资料 / 导入内容 / 项目资料浏览能力` - - 当前定向验证: - - `npm exec vitest run "src/components/resources/ResourcesPage.test.tsx" "src/components/resources/ResourcesImageWorkbench.test.tsx" "src/components/workspace/video/VideoTipsBehavior.test.tsx"` - - `npm exec vitest run "src/components/memory/MemoryPage.test.tsx"` - - `npm exec vitest run "src/i18n/__tests__/translation-coverage.test.ts" "src/lib/serviceModels.test.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npx eslint "src/components/resources/ResourcesPage.tsx" "src/components/resources/ResourcesPage.test.tsx" "src/components/resources/ResourcesImageWorkbench.tsx" "src/components/resources/ResourcesImageWorkbench.test.tsx" "src/components/workspace/video/VideoWorkspace.tsx" "src/components/workspace/video/VideoTipsBehavior.test.tsx"` - - `npx eslint "src/components/memory/MemoryPage.tsx" "src/components/memory/MemoryPage.test.tsx"` - - `npx eslint "src/i18n/__tests__/translation-coverage.test.ts" "src/components/workspace/media/ImageGallery.tsx" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" "src/lib/serviceModels.test.ts" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npm run verify:gui-smoke` - - 结果: - - `项目资料 / 图片工作台 / 视频 tips` 定向 `vitest` 通过:`3 files / 14 tests passed` - - `灵感库` 辅助入口定向 `vitest` 通过:`1 file / 20 tests passed` - - `i18n / 工作流夹具 / 项目资料测试夹具` 定向 `vitest` 通过:`4 files / 151 tests passed` - - 定向 `eslint` 通过 - - `verify:gui-smoke` 本轮未通过;headless Tauri 在 `DevBridge` 就绪前提前退出,最终卡在仓库现有 Rust 编译错误: - - `src/dev_bridge/dispatcher/agent_sessions.rs:182` - - `crate::commands::aster_agent_cmd::agent_runtime_list_sessions(db, logs)` 缺少第三个参数 `Option` - - 该错误发生在 Rust 当前主干编译阶段,和本轮 `项目资料` / `视频` 前台文案收口不在同一改动边界;当前先按仓库现有编译阻塞记录,不直接记成这轮页面回归 - -- 对齐 `docs/research/ribbi/command-inventory.md` 第二批高价值 `@命令`,把社媒 Preview / Publish 的平台型入口继续收进现有 `content_post_with_cover` current 主链,而不是新开命令家族: - - 已更新: - - `src/components/agent/chat/utils/contentPostPlatform.ts` - - `src/components/agent/chat/utils/channelPreviewWorkbenchCommand.ts` - - `src/components/agent/chat/utils/publishWorkbenchCommand.ts` - - `src/components/agent/chat/utils/browserTaskRequirement.ts` - - `src/components/agent/chat/workspace/useWorkspaceSendActions.ts` - - `src/lib/base-setup/seededCommandPackage.ts` - - `src/components/agent/chat/utils/channelPreviewWorkbenchCommand.test.ts` - - `src/components/agent/chat/utils/publishWorkbenchCommand.test.ts` - - `src/components/agent/chat/utils/browserTaskRequirement.test.ts` - - `src/lib/base-setup/seededCommandPackage.test.ts` - - `src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `@Instagram Preview / @TikTok Preview / @Twitter Preview / @YouTube Preview` 当前都已并到原有 `channel_preview_runtime`,不新增新的 `commandKey` - - `@TikTok Publish / @Twitter Publish / @YouTube Publish` 当前都已并到原有 `publish_runtime`,继续复用 `content_post_with_cover` - - `Twitter` 当前在发布链里统一归一为 `platform_type=x`、`platform_label=X / Twitter`,避免前台 alias、平台枚举和 seeded skill 平台选项继续各说各话 - - 浏览器前置要求识别当前也已补上 `Instagram / TikTok / YouTube / X / Twitter`,保证这批别名不是“只能 parse”,而是能完整落到现有发布执行链 - -- 对齐 `docs/research/ribbi/command-inventory.md` 下一批搜索 / 读取工具别名,把 Ribbi 的搜索与网页读取入口继续压回现有 `research / modal_resource_search / webpage_read / research_report` 主链,而不是为单个命令名新开 skill: - - 已更新: - - `src/components/agent/chat/utils/searchWorkbenchCommand.ts` - - `src/components/agent/chat/utils/resourceSearchWorkbenchCommand.ts` - - `src/components/agent/chat/utils/urlParseWorkbenchCommand.ts` - - `src/components/agent/chat/utils/reportWorkbenchCommand.ts` - - `src/lib/base-setup/seededCommandPackage.ts` - - `src/components/agent/chat/utils/searchWorkbenchCommand.test.ts` - - `src/components/agent/chat/utils/resourceSearchWorkbenchCommand.test.ts` - - `src/components/agent/chat/utils/urlParseWorkbenchCommand.test.ts` - - `src/components/agent/chat/utils/reportWorkbenchCommand.test.ts` - - `src/lib/base-setup/seededCommandPackage.test.ts` - - `src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `@Search / @Google Search / @Daily Search` 当前都已并到原有 `research` 命令族;其中 `@Daily Search` 在未显式声明时间范围时默认补 `最近一天` - - `@Pinterest Image Search` 当前已并到原有 `modal_resource_search`,继续复用图片素材检索主链,不新增 provider 协议 - - `@URL Summarize` 当前已并到原有 `webpage_read`,继续走 `url_parse` 的摘要读取主链 - - `@Report Search` 当前已并到原有 `research_report`,继续复用 `report_generate` - - 这批改动仍然只是 trigger / parser / metadata alias 扩展,不新增新的 `commandKey`、skill 或运行时 taxonomy - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/utils/searchWorkbenchCommand.test.ts" "src/components/agent/chat/utils/resourceSearchWorkbenchCommand.test.ts" "src/components/agent/chat/utils/urlParseWorkbenchCommand.test.ts" "src/components/agent/chat/utils/reportWorkbenchCommand.test.ts" "src/lib/base-setup/seededCommandPackage.test.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx"` - - 结果: - - 定向 `vitest` 通过:`6 files / 127 tests passed` - -## 2026-04-24 - -### 已完成 - -- 把左侧 `任务` 分组里缺失的 `生成` 主入口补回 current 导航,避免文档、测试和真实前台继续分叉: - - 已更新: - - `src/lib/navigation/sidebarNav.ts` - - `src/components/AppSidebar.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 左侧一级导航当前继续保持 `任务 / 能力 / 资料 / 系统` 四段式结构,但 `任务` 分组不再只剩 `新建任务` - - `生成` 当前已作为固定主入口回到 `任务` 分组,并直接走 `agentEntry=claw` 主执行面 - - 因此 current 侧栏终于重新对齐 V2 文档口径:`新建任务 / 生成 / 我的方法 / 灵感库 / 设置` - - 这一步也同步回应了前面入口收口后的一个真实断层:用户不需要只靠首页或回跳才能重新进入 `生成` - - 当前定向验证: - - `npm exec vitest run "src/lib/navigation/sidebarNav.test.ts" "src/components/AppSidebar.test.tsx"` - - `npx eslint "src/lib/navigation/sidebarNav.ts" "src/components/AppSidebar.test.tsx"` - - `npm run verify:gui-smoke` - -- 把 `我的方法 / slash / @` 里的“方法库 / 技能组 / 已安装技能”再收成更接近 skill-first 的前台口径,避免首页已经切到 `先拿结果 -> 再续这轮`,但方法页和输入层还在继续暴露目录/来源语义: - - 已更新: - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `我的方法` 页右侧第二块当前已从 `我的方法库` 收成 `已经沉淀的方法`,并同步把说明文案从“库/整理”语气收成“上面没命中时,再从这里接着自己的方法往下走” - - `我的方法` 页顶部状态行当前不再回退显示 `租户技能目录` 这类 catalog/source label,只保留真正对当前使用有帮助的整理时间 - - `刷新方法库 / 云端方法库加载失败 / 本地方法加载失败 / 同步我的方法库失败` 这一组用户可见反馈当前也已统一收成更前台的 `做法` / `我的方法` 口径 - - `@` 与 `/` 输入面板当前也已同步把 `推荐技能 / 技能组 · ... / 已安装技能 / 未安装技能` 收成 `推荐做法 / 分组标题本身 / 我的方法 / 更多做法`;slash 空查询里的本地方法分组当前进一步收成 `已经沉淀的方法` - - 因此 `新建任务 / 我的方法 / slash / @` 当前会更像同一套“结果模板 + 继续上次做法 + 已沉淀的方法”前台结构,而不是一边讲方法,一边讲技能目录和库 - - 当前定向验证: - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - 结果: - - `SkillsWorkspacePage / CharacterMention` 定向 `vitest` 通过:`2 files / 115 tests passed` - - 定向 `eslint` 通过 - - `verify:gui-smoke` 本轮未通过;headless Tauri 在 `DevBridge` 就绪前提前退出,日志停在 `bridge:health fetch failed` 与超长 Rust 编译等待,不按本轮 `我的方法 / slash` 前台收口直接判为功能回归,但当前也不能把这一步记成完整 GUI 交付 - -- 把 `新建任务` 首页底部补充层继续从“支撑能力说明层”收成真正的“续接条”,避免首页虽然已经把首屏重心收回 `先拿结果`,但底部仍然保留 `查看支撑能力 -> 四张能力卡` 这套第二层系统说明: - - 已更新: - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 首页补充层当前已移除 `查看支撑能力` 展开入口,不再把 `我的方法 / 持续流程 / 任务拆分 / 浏览器接入` 做成第二层能力卡说明面 - - 当前只保留真正能立刻产生收益的续接动作:`继续最近会话`、`继续最近做法`、`查看全部做法`、`连接浏览器` - - 补充层标题当前也收成更轻的 continuation 语气:有续接动作时用 `也可以直接继续这轮。`,只有浏览器接入时才显示 `需要网页登录时,也可以先把浏览器接上。` - - 首页当前也不再显式暴露 `X 套做法可直接复用` 这类数量说明,避免刚把结果入口收轻,又在底部把用户拉回目录心智 - - 因此 `新建任务` 首页当前更接近 Ribbi 式 `先拿结果 -> 再续这一轮` 的前台起手面,而不是“结果入口 + 能力说明层”双轨并列 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - 结果: - - `EmptyState` 定向 `vitest` 通过:`1 file / 49 tests passed` - - 定向 `eslint` 通过 - - `verify:gui-smoke` 通过:`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` 当前都已跑通,说明这轮首页补充层减法没有把 GUI 主路径打断 - -- 把自动化概览里的 `当前经营焦点` 继续收成更轻的“续接卡”,避免 `SceneApps` 首屏已经改成“先续做法”,但自动化页还在用 `经营焦点 / 经营判断 / 业务去向` 这一套对象卡语言: - - 已更新: - - `src/components/settings-v2/system/automation/AutomationOverviewFocusCard.tsx` - - `src/components/settings-v2/system/automation/AutomationJobFocusStrip.tsx` - - `src/components/settings-v2/system/automation/AutomationJobDetailsDialog.tsx` - - `src/components/settings-v2/system/automation/index.tsx` - - `src/components/settings-v2/system/automation/AutomationOverviewFocusCard.test.tsx` - - `src/components/settings-v2/system/automation/AutomationJobFocusStrip.test.tsx` - - `src/components/settings-v2/system/automation/AutomationJobDetailsDialog.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 自动化概览卡当前已把标题从 `当前经营焦点` 收成 `现在先继续这条`,不再默认强调经营分析视角 - - 顶部 chip 当前只保留 `持续流程名 / 做法名 / 当前状态` 这类直接影响续接判断的信息,不再把 `工作区 / businessLabel / destinations` 一次性摊在首屏 - - 主体当前也收成 `这轮判断 / 先做 / 最近结果` 三段轻信息,不再拆成第二张 `经营判断` 卡和一组业务去向标签 - - 自动化详情弹窗里的 `做法闭环` 区块当前也已同步改成 `结果包 / 复盘材料 / 这轮判断` 口径,不再额外暴露 `businessLabel / typeLabel / patternSummary` 这类对象属性 - - 自动化表格里的 `当前经营焦点` 标识与错误 toast 当前也已同步改成同一口径,避免用户在自动化概览和任务列表之间看到两套说法 - - 当前定向验证: - - `npm exec vitest run "src/components/settings-v2/system/automation/AutomationOverviewFocusCard.test.tsx" "src/components/settings-v2/system/automation/AutomationJobFocusStrip.test.tsx"` - - `npm exec vitest run "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.test.tsx"` - - `npm exec vitest run "src/components/settings-v2/system/automation/index.test.tsx"` - - `npx eslint "src/components/settings-v2/system/automation/AutomationOverviewFocusCard.tsx" "src/components/settings-v2/system/automation/AutomationJobFocusStrip.tsx" "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.tsx" "src/components/settings-v2/system/automation/index.tsx" "src/components/settings-v2/system/automation/AutomationOverviewFocusCard.test.tsx" "src/components/settings-v2/system/automation/AutomationJobFocusStrip.test.tsx" "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.test.tsx" "src/components/settings-v2/system/automation/index.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - 结果: - - 自动化概览 / 焦点条 / 详情弹窗 / 设置页定向 `vitest` 通过:`4 files / 28 tests passed` - - 定向 `eslint` 通过 - - `verify:gui-smoke` 本轮未拿到最终结论;当前重新拉起 headless Tauri 时触发了超长 Rust 编译,`bridge:health` 已进入额外等待分支,属于环境编译耗时,不按本轮自动化概览文案收口回归处理 - -- 把 `SceneAppsPage` 首屏继续从“目录总览”收成“可继续的做法导轨”,避免 `全部做法` 虽然已经改成 `做法` 口径,但页首仍然停留在 `badge + 统计卡 + 当前对象栏` 这类目录语言: - - 已更新: - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `全部做法` 页首当前移除了 `全部做法 · 进入生成前的准备层` 徽标和 `当前目录 / 最近继续 / 当前焦点` 三张统计卡,不再先把用户带进“对象目录”阅读模式 - - `当前已带入` 与 `当前做法` 当前也已合并成一条轻量续接条,只保留真正影响下一步的事实:`这轮做法`、`已带几条灵感`、`是否已经写好启动意图`,以及这轮更适合直接去准备还是去复盘 - - `做法目录 / 生成准备 / 做法复盘` 三段 workflow rail 当前也继续缩短说明,首屏只回答“先去哪一步”,不再讲长段系统解释 - - 因此用户当前沿着 `我的方法 -> 查看全部做法 -> 生成` 这条链路时,首屏认知会更接近 Ribbi 式“先续做法、再看下一步”,而不是“先读目录状态、再理解对象数量” - - 当前定向验证: - - `npm exec vitest run "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npx eslint "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - `npm run verify:local` - - 结果: - - `SceneAppsPage` 定向 `vitest` 通过:`1 file / 34 tests passed` - - 定向 `eslint` 通过 - - `verify:gui-smoke` 未通过,但当前失败点仍停留在既有 `smoke:browser-runtime` 链路:`launch_browser_session / close_chrome_profile_session` 持续 `fetch failed`;前置 `DevBridge / workspace-ready` 已正常,不按本次 `SceneApps` 首屏改动回归处理 - - `verify:local` 未通过,当前阻塞仍是仓库既有无关 warning: - - `src/components/api-key-provider/ProviderSetting.tsx:174` `react-hooks/exhaustive-deps` - -- 把 `人工复盘 -> 首页 / 我的方法 / slash 结果模板横幅` 从“首屏可解释”继续推进成“首屏可直接续接”,避免三处横幅虽然都已经能说明“这轮为什么更适合这样继续”,但用户仍然要自己再去点下一层目录才能真正开工: - - 已更新: - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 首页 `结果入口` 的 `最近复盘已更新` 横幅当前新增 `继续去「...」` 动作,点击后直接复用当前已排到前面的推荐模板选择链,不再要求用户自己再去找一遍结果卡 - - `我的方法` 页 `先拿结果` 区块里的轻量复盘横幅当前也新增同名动作,点击后直接打开对应 `curated task launcher` - - slash `结果模板` 分组里的复盘横幅当前同样新增直达动作,点击后仍复用现有 `handleSelectCapability(item)` 主链,不额外发明一套输入层专属跳转 - - 因此 `人工复盘 -> 首页 / 我的方法 / slash` 这三处首屏入口,当前都已经从“能解释为什么推荐”推进到“能直接把下一步接起来” - - 这一步继续服务 `P5` 主线:让 `review_feedback` 的异步增益不只体现在排序和说明文字上,也体现在可立即续做的轻量动作上 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - 结果: - - `vitest` 通过:`3 files / 162 tests passed` - - 定向 `eslint` 通过 - - `verify:gui-smoke` 通过:`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` 当前都已跑通,证明这轮轻 CTA 没有把 GUI 主链打断 - -- 把 `人工复盘 -> 当前激活结果模板(active badge) / launcher` 从“发送前可见说明”继续推进成“发送前可直接改用更合适的结果模板”,避免首页、我的方法、slash 首屏都已经能一键续接,但用户真的走到发送前时,顶部 badge 和 launcher 里的复盘提示又退回成只读说明: - - 已更新: - - `src/components/agent/chat/skill-selection/CuratedTaskBadge.tsx` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` - - `src/components/agent/chat/components/EmptyStateComposerPanel.tsx` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/agent/chat/skill-selection/CuratedTaskBadge.test.tsx` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `CuratedTaskBadge` 当前会在“当前模板不是最近复盘首选”时显影 `改用「...」` 动作,不再只把最近复盘当作 badge 说明文字 - - `CuratedTaskLauncherDialog` 当前也会在“当前 launcher 不是最近复盘首选”时显影同一类切换动作,点击后继续复用现有 launcher 主链,而不是偷偷改 active capability - - `EmptyState` 当前已经把这条切换动作接回主执行面;从发送前 badge 点击后,会直接打开更合适结果模板的 launcher,并继续带着当前结果与参考对象 - - `CharacterMention` 当前也已经把同一条切换动作接回 slash launcher;因此用户从 slash 进入结果模板后,仍可在 launcher 内按最近复盘切到更合适的模板 - - 这一步继续服务 `P5` 主线:让 `review_feedback` 的异步增益正式穿过“选模板 -> 启动表单 -> 发送前 badge”这一段主执行链,而不只停留在首屏入口层 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/skill-selection/CuratedTaskBadge.test.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npx eslint "src/components/agent/chat/skill-selection/CuratedTaskBadge.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.tsx" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/CuratedTaskBadge.test.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - 结果: - - `CuratedTaskBadge / CuratedTaskLauncherDialog / EmptyState` 定向 `vitest` 通过:`3 files / 64 tests passed` - - `CharacterMention` 定向 `vitest` 通过:`1 file / 88 tests passed` - - 定向 `eslint` 通过 - - `verify:gui-smoke` 通过:`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` 当前都已跑通 - -- 把 `人工复盘 -> 我的方法 / 灵感库 launcher` 从“launcher 内只解释为什么更适合另一条模板”继续推进成“launcher 内可直接改用更合适模板”,避免首页和首屏卡片已经能按最近复盘续接,但用户一旦真正从 `我的方法` 或 `灵感库` 进入 launcher,又退回成只能自己关掉重找: - - 已更新: - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/memory/MemoryPage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `src/components/memory/MemoryPage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `SkillsWorkspacePage` 当前会在 `CuratedTaskLauncherDialog` 内真正接住 `onApplyReviewSuggestion`,因此用户从 `先拿结果` 进入 launcher 后,遇到最近复盘更适合的模板时,可以直接切过去,而不必先退回卡片区 - - `MemoryPage` 当前也已把同一条切换动作接回 `围绕当前灵感 / 围绕这条成果继续` 的 launcher,并继续保留当前 reference object 与 reference selection,不再因为切模板把成果基线丢掉 - - 到这里为止,current 非对话页里的两条 launcher 主链,已经都从“解释为什么推荐”推进到“在 launcher 里直接续接下一步” - - 当前定向验证: - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/memory/MemoryPage.test.tsx"` - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/memory/MemoryPage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/memory/MemoryPage.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - 结果: - - `SkillsWorkspacePage / MemoryPage` 定向 `vitest` 通过:`2 files / 46 tests passed` - - 定向 `eslint` 通过 - - `verify:gui-smoke` 通过:`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` 当前都已跑通 - -- 把 `人工复盘 -> 输入条 active curated task badge / 编辑态 launcher` 的真实控制器链补齐到 `useInputbarController`,避免文档层面已经把“发送前可直接改用更合适模板”记成已完成,但实际输入条顶部 badge 和编辑态 launcher 还没有真正接回 `onApplyReviewSuggestion`: - - 已更新: - - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 输入条顶部 `CuratedTaskBadge` 当前已能直接按最近复盘切到推荐模板,并同步改写当前 `active capability + prompt`,不再只显示一颗说明性 pill - - 输入条里的编辑态 `CuratedTaskLauncherDialog` 当前也已真正接住 `onApplyReviewSuggestion`;在 launcher 中切模板时,会继续保留当前 reference selection,并给出轻量 `prefill hint` - - 至此 current 所有 `CuratedTaskLauncherDialog` 父层都已经接回同一条 review 续接主链: - - `EmptyState` - - `CharacterMention` - - `SkillsWorkspacePage` - - `MemoryPage` - - `useInputbarController` - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npx eslint "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - 结果: - - `Inputbar` 定向 `vitest` 通过:`1 file / 45 tests passed` - - 定向 `eslint` 通过 - - `verify:gui-smoke` 通过:复用已运行的 headless 环境,完整跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - -- 把 `我的方法` 页首层继续从“对象目录”收成“结果优先 + 继续做法 + 已沉淀的方法”,避免 current 主链已经在 launcher / 输入层 / 结果侧不断减系统感,但 `我的方法` 页首屏仍然被数量 badge、组数、`/skill.key`、来源标签这些实现性露出拉回目录思维: - - 已更新: - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 页首摘要当前不再强调 `对话内继续 / X 条做法 / Y 组` 这类对象视角,而是直接讲“先拿一个结果起手;后面常用做法和自己沉淀的方法都在这里续上” - - `先拿结果 / 继续上次做法 / 我的方法库` 三块当前都去掉了低价值数量 badge,避免首屏继续被计数器和标签墙抢注意力 - - `我的方法库` 卡片当前也不再默认暴露 `本地 / 官方 / 社区` 来源标签、`已安装` 标识和 `/skill.key` 方法入口,只保留用户真正会据此决策的承诺:这套方法解决什么、你来给什么、会拿到什么、进生成后会怎么继续 - - 这一步继续服务 `P2` 主线:让 `我的方法` 更像 Ribbi 式“续做法工作台”,而不是“能力对象目录” - - 当前定向验证: - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - `npm run verify:local` - - 结果: - - `SkillsWorkspacePage` 定向 `vitest` 通过:`1 file / 27 tests passed` - - 定向 `eslint` 通过 - - `verify:gui-smoke` 通过:复用已运行的 headless 环境,完整跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - - `verify:local` 未通过;当前阻塞来自仓库既有无关 lint warning: - - `src/components/api-key-provider/ProviderSetting.tsx:174` 的 `react-hooks/exhaustive-deps` warning - - 因此本轮结论应更新为:`我的方法` 页这刀 current UI 收口已通过定向回归与 GUI smoke,仓库级统一入口仍受一条与本刀无关的存量 warning 阻塞 - -## 2026-04-23 - -### 已完成 - -- 把 `人工复盘 -> 首页 / 我的方法 / slash 结果模板横幅` 从“只显示复盘摘要”继续推进成“复盘摘要 + 下一步建议句”的统一前台投影,避免同一份 `review_feedback` 信号虽然已经影响推荐排序,但三处首屏入口还停留在偏泛化的说明层: - - 已更新: - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 首页 `结果入口`、`我的方法` 页 `先拿结果` 与 slash `结果模板` 分组,当前都会继续复用同一份 `buildReviewFeedbackProjection(...)` - - 三处横幅当前不再只显示 `signal.summary`,而是继续拼上 `projection.suggestionText`,直接解释“这轮复盘更建议优先回到哪条结果模板” - - 这一步继续服务 `P5` 主线:让 `人工复盘 -> 下一轮结果入口` 不只体现在排序变化上,也体现在统一可读的续做说明上 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - 结果: - - `vitest` 通过:`3 files / 162 tests passed` - - 定向 `eslint` 通过 - - `verify:gui-smoke` 本轮未拿到有效通过结论:前 5 段 smoke 已通过,但最后 `smoke:agent-runtime-tool-surface-page` 阶段 `DevBridge` 掉线,随后 `bridge:health` 复检也超时未就绪;当前按环境阻塞记录,不把它误记成这轮前台投影改动引入的功能回归 - -- 把任务层 / 模型层 / 事件链正式接回 Lime current runtime 主链,并把此前阻塞 `verify:local` 的既有噪音一并收口: - - 已更新: - - `docs/roadmap/task/README.md` - - `docs/roadmap/task/runtime-integration.md` - - `docs/roadmap/task/rollout-plan.md` - - `docs/roadmap/task/acceptance.md` - - `src-tauri/crates/agent/src/session_execution_runtime.rs` - - `src-tauri/crates/agent/src/protocol.rs` - - `src-tauri/src/commands/aster_agent_cmd/request_model_resolution.rs` - - `src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs` - - `src-tauri/src/commands/aster_agent_cmd/dto.rs` - - `src/lib/api/agentExecutionRuntime.ts` - - `src/lib/api/agentProtocol.ts` - - `src/lib/api/agentRuntime/types.ts` - - `src/lib/api/agentProtocol.test.ts` - - `src/components/agent/chat/hooks/useAgentSession.ts` - - `src/components/api-key-provider/ProviderModelList.tsx` - - `src/components/settings-v2/system/automation/index.tsx` - - `src/components/workspace/video/VideoCanvas.tsx` - - `src/lib/mediaGeneration.ts` - - `src/components/agent/chat/utils/curatedTaskTemplates.test.ts` - - `src/components/agent/chat/utils/processDisplayText.ts` - - `src-tauri/src/commands/aster_agent_cmd/tool_runtime/creation_tools.rs` - - 当前统一结论: - - `TaskProfile -> RoutingDecision -> LimitState` 现在已经是 Lime current runtime 的真实事实链,而不是只存在文档里的提案对象 - - `runtime_turn.rs` 当前会把这三类事实写回 `turn_context.metadata.lime_runtime`,并即时发出 `task_profile_resolved / routing_decision_made / limit_state_updated` - - `request_model_resolution.rs` 当前不再只返回 `provider_config`,而是返回完整 resolution envelope;`service_models.translation` 也已经进入统一路由链 - - `thread_read` 与前端协议当前都能直接消费 `task_kind / service_model_slot / routing_mode / decision_source / candidate_count / capability_gap / limit_state` - - 为了证明这轮主线真的可交付,本轮也一并修掉了此前会挡住 `verify:local` 的几处既有噪音,包括 `useAgentSession` 缺失 import、`ProviderModelList` hooks 依赖、视频 provider 判定以及部分测试夹具 / 文本归一化问题 - - 当前定向验证: - - `cargo check --manifest-path "src-tauri/Cargo.toml" -p lime-agent` - - `cargo check --manifest-path "src-tauri/Cargo.toml" -p lime` - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime-agent extracts_task_routing_and_limit_state_from_lime_runtime_metadata` - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime runtime_task_profile_marks_translation_service_slot` - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime explicit_provider_config_resolution_reports_single_candidate_routing` - - `npm exec vitest run "src/lib/api/agentProtocol.test.ts"` - - `npm exec vitest run "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` - - `npm exec vitest run "src/components/workspace/video/VideoCanvas.test.tsx"` - - `npm exec vitest run "src/lib/mediaGeneration.test.ts"` - - `npm exec vitest run "src/components/agent/chat/components/AgentThreadTimeline.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/components/StreamingRenderer.test.tsx"` - - `npm run test:contracts` - - `npm run verify:local` - - 结果: - - 所有上述定向 Rust / Vitest / contracts 校验通过 - - `verify:local` 当前已完整通过,包含 `verify:gui-smoke` - -- 把首页 `围绕当前灵感,先拿结果` 也补成和成果分区一致的结果续接语义,避免首页与 `MemoryPage/durable` 口径重新分叉: - - 已更新: - - `src/components/memory/MemoryPage.tsx` - - `src/components/memory/MemoryPage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 当首页 `activeRecommendationReferenceEntries` 里已经存在带 `taskPrefillByTaskId` 的成果条目时,首页推荐区当前也会显影同一张轻量 `当前续接成果` 上下文卡,不再只有成果分区才看得到“这轮结果还在继续带着走” - - 因此首页 `围绕当前灵感,先拿结果` 当前也能直接解释:这轮正在承接哪条成果、为什么现在优先推荐 `复盘 / 趋势 / 主稿` - - 这一步继续服务 `P4` 主线:让 `结果 -> 灵感库 -> 下一轮推荐` 不只在成果分区闭环,也在首页入口保持同一条前台叙事 - - 当前定向验证: - - `npm exec vitest run "src/components/memory/MemoryPage.test.tsx"` - - `npx eslint "src/components/memory/MemoryPage.tsx" "src/components/memory/MemoryPage.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - 结果: - - `MemoryPage` 定向 `vitest` 通过:`1 file / 18 tests passed` - - 定向 `eslint` 通过 - - `verify:gui-smoke` 通过 - -- 把成果类灵感条目的“为什么推荐下一步”正式前推到推荐层,而不再只在 launcher 打开后才解释得清楚: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskTemplates.ts` - - `src/components/agent/chat/utils/curatedTaskTemplates.test.ts` - - `src/components/memory/MemoryPage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `listFeaturedHomeCuratedTaskTemplates(...)` 当前会对 `experience` 类 reference entry 额外识别“成果续接型命中”,不再只靠通用关键词和 category weight 解释推荐原因 - - 只要当前成果条目已经为某个模板编出了 `taskPrefillByTaskId`,这条显式续接 reason 当前就会优先于泛化 `active_reference` signal,避免前台又退回“围绕当前成果”这种过宽解释 - - 当成果条目已经编出 `taskPrefillByTaskId` 时,`复盘这个账号/项目 / 每日趋势摘要 / 内容主稿生成` 当前会分别显影更明确的续接 reason: - - `先对齐这轮结果基线,再决定下一轮动作` - - `围绕这轮结果继续找趋势窗口` - - `把这轮结果直接带成下一版主稿` - - 因此 `MemoryPage` 的推荐卡当前不再只是“看起来推荐了下一步”;用户在成果条目旁边就能直接看懂 Lime 为什么建议先复盘、补趋势或起下一版主稿 - - 这一步继续服务 `P4` 主线:把 `结果 -> 灵感库 -> 下一轮推荐` 从 launcher 内部闭环,继续前推成首页/分区卡片层也能读懂的闭环 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/utils/curatedTaskTemplates.test.ts" "src/components/memory/MemoryPage.test.tsx"` - - `npx eslint "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/utils/curatedTaskTemplates.test.ts" "src/components/memory/MemoryPage.test.tsx"` - - `npm run verify:local` - - 结果: - - `curatedTaskTemplates + MemoryPage` 定向 `vitest` 通过:`2 files / 21 tests passed` - - 定向 `eslint` 通过 - - `verify:local` 本轮未拿到最终结论:smart 模式检测到工作区已有 `99` 个改动文件后,把校验扩大成全仓 `42` 批 `vitest-smart` + bridge / GUI / Rust 路径;本轮已实际跑过 `verify:app-version / lint / typecheck` 并进入 `vitest-smart` 前 10 批,但这不属于本刀推荐层的最小证明范围,因此没有把半程运行误记成最终绿灯 - -- 把同一份成果基线继续扩到下游结果模板,并让 launcher 的“当前结果基线”不再只认 sceneapp 合成对象: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskReferenceSelection.ts` - - `src/components/agent/chat/utils/curatedTaskReferenceSelection.test.ts` - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts` - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `experience` 类 `UnifiedMemory` 当前不只会编出 `account-project-review` 的 prefill,也会继续编出 `daily-trend-briefing` 与 `social-post-starter` 的结构化启动信息 - - `每日趋势摘要` 当前会默认带上 `主题或赛道 + 希望关注的平台/地域`;`内容主稿生成` 当前会默认带上 `主题或产品信息 + 目标受众` - - `buildSceneAppExecutionReviewPrefillSnapshot(...)` 当前也不再只认 `sceneapp_execution_summary`;任何带 `project_goal / existing_results` 结果基线的 reference entry 都能显影同一套 `当前结果基线 / 当前判断 / 当前卡点` - - `CuratedTaskLauncherDialog` 的 carry hint 当前已泛化到任意结果模板,因此趋势和主稿模板也会明确提示“哪些字段已按这轮结果自动带入” - - 这一步继续服务 `P4` 的 current 主线:让 `结果 -> 灵感库 -> 下一轮趋势/主稿` 也从“看起来像闭环”推进成“字段与基线都真实续接” - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/utils/curatedTaskReferenceSelection.test.ts" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts" "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx"` - - `npm exec vitest run "src/components/memory/MemoryPage.test.tsx"` - - `npx eslint "src/components/agent/chat/utils/curatedTaskReferenceSelection.ts" "src/components/agent/chat/utils/curatedTaskReferenceSelection.test.ts" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts" "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - 结果: - - `curatedTaskReferenceSelection / sceneAppCuratedTaskReference / CuratedTaskLauncherDialog` 定向 `vitest` 通过:`3 files / 20 tests passed` - - `MemoryPage` 定向 `vitest` 通过:`1 file / 17 tests passed` - - 定向 `eslint` 通过 - - `verify:gui-smoke` 本轮未拿到有效通过结论;当前环境存在并发 `cargo test --manifest-path src-tauri/Cargo.toml -p lime explicit_provider_config_resolution_reports_single_candidate_routing` 占用 `src-tauri/target` 锁,第一次重跑还叠加了临时 target 目录丢失导致的 `couldn't create a temp dir (os error 2)`,因此按环境并发噪音处理,不把它记成这轮功能回归失败 - -- 把成果类灵感条目正式编译成可直接预填复盘 launcher 的 reference entry,避免用户在灵感库里还得把刚才那轮结果重新讲一遍: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskReferenceSelection.ts` - - `src/components/agent/chat/utils/curatedTaskReferenceSelection.test.ts` - - `src/components/memory/MemoryPage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `buildCuratedTaskReferenceEntries(...)` 当前会为 `experience` 类 `UnifiedMemory` 统一补上 `taskPrefillByTaskId.account-project-review`,不再额外长一条 `MemoryPage-only` 的 continuation 编译层 - - 这份 prefill 会优先从成果 content 里的 `场景 / 结果摘要 / 当前交付 / 建议下一步 / 当前信号 / 最近反馈 / 运行态回流 / 当前判断` 结构化行抽取复盘基线;拿不到结构化行时,再回退到 `summary/content` 的压缩摘要 - - 因此 `MemoryPage -> 围绕这条成果继续 -> 复盘这个账号/项目` 当前不只是把成果带成 reference seed;launcher 打开时,`账号或项目目标 / 已有结果或数据` 也已经默认带好当前成果基线 - - 这一步继续服务 `P4` 的 current 主线:让 `结果 -> 灵感库 -> 复盘 -> 下一轮生成` 少一次人工复述,更接近 Ribbi 式自然续接 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/utils/curatedTaskReferenceSelection.test.ts"` - - `npm exec vitest run "src/components/memory/MemoryPage.test.tsx"` - - `npx eslint "src/components/agent/chat/utils/curatedTaskReferenceSelection.ts" "src/components/agent/chat/utils/curatedTaskReferenceSelection.test.ts" "src/components/memory/MemoryPage.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - 结果: - - `curatedTaskReferenceSelection` 定向 `vitest` 通过:`1 file / 5 tests passed` - - `MemoryPage` 定向 `vitest` 通过:`1 file / 17 tests passed` - - 定向 `eslint` 通过 - - `verify:gui-smoke` 通过 - - 本轮未重复执行 `npm run verify:local`;仓库级统一入口当前仍有既有无关阻塞: - - `src/components/agent/chat/hooks/useAgentSession.ts`:`normalizeLegacyThreadItems` 未定义 - - `src/components/api-key-provider/ProviderModelList.tsx`:既有 hooks warning - -- 把“当前续接成果”真正接进下一轮推荐,而不只是让它在成果分区里高亮可见: - - 已更新: - - `src/components/memory/MemoryPage.tsx` - - `src/components/memory/MemoryCuratedTaskSuggestionPanel.tsx` - - `src/components/memory/MemoryPage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `MemoryPage` 当前新增 `activeRecommendationReferenceEntries`,会优先把 `focusedDurableMemory` 编进推荐参考,再补灵感库其他参考对象;因此从结果页落到 `memory/experience` 时,推荐上下文不再是“灵感库全局前几条”,而是“当前这条成果优先” - - 首页 `围绕当前灵感,先拿结果` 与成果分区里的 `围绕这条成果继续` 当前都改为复用同一份 `MemoryCuratedTaskSuggestionPanel`,不再在 `MemoryPage` 里复制两套推荐卡片结构 - - 成果分区当前会直接露出围绕这条成果的下一步推荐,并优先把 launcher 的 `referenceEntries / creation_replay` 对准这条成果;因此“当前续接”已经从视觉提示推进成真正的启动事实 - - 这一步继续遵守当前 Ribbi 式前台方向:不把用户赶回首页、不加解释弹层,只在成果旁边给出下一步 - - 当前定向验证: - - `npm exec vitest run "src/components/memory/MemoryPage.test.tsx"` - - `npx eslint "src/components/memory/MemoryPage.tsx" "src/components/memory/MemoryCuratedTaskSuggestionPanel.tsx" "src/components/memory/MemoryPage.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - `npm run verify:local` - - 结果: - - `MemoryPage` 定向 `vitest` 通过:`17 tests passed` - - 定向 `eslint` 通过 - - `verify:gui-smoke` 通过 - - `verify:local` 未通过;当前阻塞仍是仓库既有无关问题: - - `src/components/agent/chat/hooks/useAgentSession.ts`:`normalizeLegacyThreadItems` 未定义 - - `src/components/api-key-provider/ProviderModelList.tsx`:既有 hooks warning - -- 把 `去灵感库继续` 从泛化首页跳转推进成“成果分区 + 当前续接对准”,避免用户刚从结果页返回灵感库时又得自己重找那条成果: - - 已更新: - - `src/types/page.ts` - - `src/components/agent/chat/utils/saveSceneAppExecutionAsInspiration.ts` - - `src/components/agent/chat/utils/saveSceneAppExecutionAsInspiration.test.ts` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/settings-v2/system/automation/index.tsx` - - `src/components/memory/MemoryPage.tsx` - - `src/components/memory/MemoryPage.test.tsx` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 新增 `buildSceneAppExecutionInspirationLibraryPageParams(...)`,统一把结果页里的“去灵感库继续”编译成 `section: "experience" + focusMemoryTitle + focusMemoryCategory` - - `AgentChatWorkspace`、`sceneapps` 深层页与自动化详情当前都复用这同一份 helper,不再各自硬编码 `memory/home` - - `MemoryPage` 当前已支持按这组 page params 对准成果条目,并给目标条目加轻量 `当前续接` 高亮;用户进入灵感库时看到的就不是泛化首页,而是刚才那轮成果所在的位置 - - 这一步继续保持 Ribbi 式前台:不新加说明弹层,不暴露额外系统状态,只把用户真正要继续的那条成果对到眼前 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/utils/saveSceneAppExecutionAsInspiration.test.ts" "src/components/memory/MemoryPage.test.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npx eslint "src/types/page.ts" "src/components/agent/chat/utils/saveSceneAppExecutionAsInspiration.ts" "src/components/agent/chat/utils/saveSceneAppExecutionAsInspiration.test.ts" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/settings-v2/system/automation/index.tsx" "src/components/memory/MemoryPage.tsx" "src/components/memory/MemoryPage.test.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - `npm run verify:local` - - 结果: - - `vitest` 通过:`3 files / 54 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过 - - `verify:local` 未通过;当前阻塞仍是仓库既有无关问题: - - `src/components/agent/chat/hooks/useAgentSession.ts`:`normalizeLegacyThreadItems` 未定义 - - `src/components/api-key-provider/ProviderModelList.tsx`:既有 hooks warning - -- 把 `保存到灵感库` 的前台反馈从 toast-only 收成“信号驱动的已收进灵感库”稳定状态,避免结果虽然已经沉淀成功,用户在结果面里却仍看到可重复点击的旧按钮: - - 已更新: - - `src/components/agent/chat/utils/saveSceneAppExecutionAsInspiration.ts` - - `src/components/agent/chat/utils/saveSceneAppExecutionAsInspiration.test.ts` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` - - `src/components/sceneapps/SceneAppRunDetailPanel.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `src/components/settings-v2/system/automation/AutomationJobDetailsDialog.tsx` - - `src/components/settings-v2/system/automation/AutomationJobDetailsDialog.test.tsx` - - `src/components/settings-v2/system/automation/index.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 新增 `hasSavedSceneAppExecutionAsInspiration(...)`,统一基于 `buildSceneAppExecutionInspirationDraft(...)` 和推荐信号事实源判断这轮结果是否已经被沉淀 - - `AgentChatWorkspace`、`sceneapps` 深层页和自动化详情当前都会订阅 `subscribeCuratedTaskRecommendationSignalsChanged(...)`,因此保存成功后会在页内即时重算状态,而不是等用户重开页面 - - `SceneAppExecutionSummaryCard` 与 `SceneAppRunDetailPanel` 当前都会把按钮切成禁用态 `已收进灵感库`;聊天结果卡、`sceneapps` 深层结果面和自动化详情里的结果面现在都会显影同一句轻量 hint:`这轮结果已进入灵感库,下一轮推荐会继续带上它` - - 这条 hint 旁边当前也会统一露出低权重 `去灵感库继续`;当前已升级成直接落到成果分区并尽量对准刚才那条成果,不再只是泛化导航到 `memory/home` - - 这一步刻意没有新造组件本地临时状态,也没有再加一层成功横幅,继续保持 Ribbi 式“轻提示、少系统感、先让用户知道下一步还在接着走”的前台节奏 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.test.tsx"` - - `npx eslint "src/components/agent/chat/utils/saveSceneAppExecutionAsInspiration.ts" "src/components/agent/chat/utils/saveSceneAppExecutionAsInspiration.test.ts" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/components/sceneapps/SceneAppRunDetailPanel.tsx" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.tsx" "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.test.tsx" "src/components/settings-v2/system/automation/index.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - `npm run verify:local` - - 结果: - - `vitest` 通过:`3 files / 50 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过 - - `verify:local` 未通过;当前阻塞仍是仓库既有无关问题: - - `src/components/agent/chat/hooks/useAgentSession.ts`:`normalizeLegacyThreadItems` 未定义 - - `src/components/api-key-provider/ProviderModelList.tsx`:既有 hooks warning - -- 把 `保存到灵感库` 从单一聊天结果卡扩到 `sceneapps` 深层结果面与自动化详情,避免高价值结果仍然只在一个结果入口里才能沉淀: - - 已更新: - - `src/components/agent/chat/utils/saveSceneAppExecutionAsInspiration.ts` - - `src/components/agent/chat/utils/saveSceneAppExecutionAsInspiration.test.ts` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/sceneapps/SceneAppRunDetailPanel.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `src/components/settings-v2/system/automation/AutomationJobDetailsDialog.tsx` - - `src/components/settings-v2/system/automation/AutomationJobDetailsDialog.test.tsx` - - `src/components/settings-v2/system/automation/index.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 新增 `saveSceneAppExecutionAsInspiration(...)`,统一复用 `buildSceneAppExecutionInspirationDraft(...) + createUnifiedMemory(...) + recordCuratedTaskRecommendationSignalFromMemory(...)`,不再让聊天结果卡、`sceneapps` 深层页和自动化详情各自复制一段保存逻辑 - - `SceneAppRunDetailPanel` 当前新增轻量 `保存到灵感库` 按钮;`sceneapps` 深层结果面与自动化详情弹窗都复用这同一枚入口,不再只有 `SceneAppExecutionSummaryCard` 能顺手沉淀结果 - - `AgentChatWorkspace` 当前也已切回同一条 helper,因此 `结果工作台 / sceneapps 深层页 / 自动化详情 -> 灵感库 -> 推荐信号 -> 下一轮推荐` 现在开始围绕同一份成果类灵感草稿运转 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/utils/saveSceneAppExecutionAsInspiration.test.ts" "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.test.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npx eslint "src/components/agent/chat/utils/saveSceneAppExecutionAsInspiration.ts" "src/components/agent/chat/utils/saveSceneAppExecutionAsInspiration.test.ts" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/sceneapps/SceneAppRunDetailPanel.tsx" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.tsx" "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.test.tsx" "src/components/settings-v2/system/automation/index.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - `npm run verify:local` - - 结果: - - `vitest` 通过:`3 files / 42 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过 - - `verify:local` 未通过;当前阻塞来自仓库既有无关 lint 问题: - - `src/components/agent/chat/hooks/useAgentSession.ts`:`normalizeLegacyThreadItems` 未定义 - - `src/components/api-key-provider/ProviderModelList.tsx`:既有 hooks warning - -- 把 `结果工作台 -> 灵感库` 这条主链补回 `SceneAppExecutionSummaryCard`,避免高价值结果仍然只停留在消息区或结果摘要里: - - 已更新: - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` - - `src/components/agent/chat/utils/sceneAppExecutionInspirationDraft.ts` - - `src/components/agent/chat/utils/sceneAppExecutionInspirationDraft.test.ts` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `SceneAppExecutionSummaryCard` 的 `继续动作` 区当前新增 `保存到灵感库`,用户在结果工作台里就能直接把这轮结果沉淀成灵感,不必退回消息列表找入口 - - `AgentChatWorkspace` 当前已把结果卡这条入口接到统一的 sceneapp 结果沉淀主链,继续复用 `createUnifiedMemory(...) + recordCuratedTaskRecommendationSignalFromMemory(...)` - - 新增的 `buildSceneAppExecutionInspirationDraft(...)` 会把 `结果摘要 / 当前交付 / 下一步 / 待补部件 / 当前信号 / 风格与反馈` 编成成果类灵感沉淀请求,不再只存一段泛化文案 - - 因此 `结果工作台 -> 灵感库 -> 推荐信号 -> 首页/灵感库/launcher 下一轮推荐` 现在已经形成一条 current 前台闭环 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/components/agent/chat/utils/sceneAppExecutionInspirationDraft.test.ts"` - - `npx eslint "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/components/agent/chat/utils/sceneAppExecutionInspirationDraft.ts" "src/components/agent/chat/utils/sceneAppExecutionInspirationDraft.test.ts"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - 结果: - - `vitest` 通过:`2 files / 9 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过 - -- 把 `灵感库` 首页的 P3 推荐区从“首屏快照”推进成“页内实时回流”,避免 `MemoryPage` 打开后仍然看不到后续保存到灵感库的变化: - - 已更新: - - `src/components/memory/MemoryPage.tsx` - - `src/components/memory/MemoryPage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `MemoryPage` 当前已订阅 `subscribeCuratedTaskRecommendationSignalsChanged(...)`,不再只在首屏 `loadAll()` 时抓一次灵感库快照 - - 收到推荐信号后,页面当前会同步重算首页 `围绕当前灵感,先拿结果` 推荐,并增量回拉 `getUnifiedMemoryStats() + listUnifiedMemories({ limit: 120 })` - - 因此 `保存到灵感库 / 更新推荐信号 -> 灵感对象统计 -> 首页参考对象 -> 推荐卡默认参考` 现在都会在页内一起刷新,不再要求用户重开 `MemoryPage` - - 这也意味着 `MemoryPage` 上打开中的共享 launcher 会继续吃到更新后的 `featuredMemoryReferenceEntries`,不会停留在进入页面时那一版旧参考 - - 当前定向验证: - - `npm exec vitest run "src/components/memory/MemoryPage.test.tsx"` - - `npx eslint "src/components/memory/MemoryPage.tsx" "src/components/memory/MemoryPage.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - 结果: - - `vitest` 通过:`1 file / 15 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过 - -- 把 `灵感库 -> 下一轮结果模板` 这条 P3 主链正式前推到 `MemoryPage` 首页,避免 taste/reference 回流仍然只停留在隐性的推荐排序里: - - 已更新: - - `src/components/memory/MemoryPage.tsx` - - `src/components/memory/MemoryPage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `MemoryPage` 首页当前新增 `围绕当前灵感,先拿结果` 区块,会基于灵感库里的参考对象直接编译共享 curated task 推荐 - - 这组推荐当前复用首页 / `我的方法` / slash 同一套 `listFeaturedHomeCuratedTaskTemplates(...)` 逻辑,不另造 `memory-only` 模板体系 - - 推荐卡当前会显影 `围绕当前灵感 / 默认带上几条参考对象 / 你先给 / 这一步先拿 / 接着可做`,让用户在灵感库里就能看见“下一轮更适合先做什么” - - 点击 `开始这一步` 当前不会退回裸 prompt,而是统一先打开共享 launcher;确认后继续走 `curated_task capabilityRoute + requestMetadata.harness.curated_task + creation_replay(memory_entry)` 主链 - - 因此 P3 当前第一次把 `灵感库 -> 结果模板 -> launcher -> 生成` 做成了正式前台动作,而不是要求用户自己带着灵感再回首页找起手入口 - - 当前定向验证: - - `npm exec vitest run "src/components/memory/MemoryPage.test.tsx"` - - `npx eslint "src/components/memory/MemoryPage.tsx" "src/components/memory/MemoryPage.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - 结果: - - `vitest` 通过:`1 file / 14 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过 - -- 把 `我的方法` 页左列目录继续从“补位说明块”收成更轻的备用方向入口,避免这块区域仍然像第二个需要理解的管理台: - - 已更新: - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 左列标题当前从 `方法目录` 收成 `换个方向`,并移除了 `补位目录` 这类解释 badge;空态也同步改成“去下方换个方向继续找” - - 方向卡当前主语气统一为 `先试 / 适合 / 进去后直接挑做法 / 进去挑`,不再强调“目录结构 / 做法组”本身 - - 进入组后的过渡层当前也从 `组内继续挑做法 / 这一组更偏向 / 起手建议 / 换一组做法` 收成 `已切到这一组 / 直接挑一条 / 换个方向` - - 因此 `我的方法` 页当前又向 Ribbi 式前台秩序推进了一刀:`先拿结果 -> 没命中就换个方向 -> 进去后直接挑一条 -> 继续上次做法 / 我的方法库` - - 当前定向验证: - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - 结果: - - `vitest` 通过:`1 file / 26 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过 - - `typecheck` 未通过;当前阻塞来自仓库既有无关问题: - - `src/components/agent/chat/hooks/useAgentSession.ts(231,11): Cannot find name 'normalizeLegacyThreadItems'` - - `src/components/agent/chat/hooks/useAgentSession.ts(482,9): Cannot find name 'normalizeLegacyThreadItems'` - -- 把 `我的方法 -> 生成` 这条 P2 主执行链的项目上下文断点补齐,避免 `service skill / installed skill / curated task` 虽然都已经能从 `SkillsWorkspacePage` 进入 `agent/new-task`,但当前项目容器在跳转时被丢掉: - - 已更新: - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `SkillsWorkspacePage` 当前已把 `creationProjectId` 收成同一份局部事实源 - - `对话内补参` 的 `service skill`、`我的方法库` 的 installed skill,以及 `先拿结果` 的 curated task launcher,当前进入 `生成` 时都会统一继承 `projectId` - - 因此 `我的方法 -> 生成` 当前不再只有 capability route 连上了,`project scope` 也会继续留在同一条主链里 - - 当前定向验证: - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - 结果: - - `vitest` 通过:`1 file / 26 tests passed` - - `eslint` 通过 - -- 把 `automation overview -> 当前经营焦点` 继续前推到默认任务列表,避免这条“现在最值得继续哪条持续流程”的判断只存在于概览页和详情弹窗里,用户停留在默认任务页时仍然得先跳走才能知道该进哪条链路: - - 已更新: - - `src/components/settings-v2/system/automation/AutomationJobFocusStrip.tsx` - - `src/components/settings-v2/system/automation/AutomationJobFocusStrip.test.tsx` - - `src/components/settings-v2/system/automation/index.tsx` - - `src/components/settings-v2/system/automation/index.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 默认任务页里的 `overviewFocusJob` 当前会直接长出一条轻量 `当前经营焦点` strip,显影 `当前判断 / 最近结果 / 下一步` - - 焦点行当前会直接给出 `继续复盘 / 去做法复盘`,因此用户停在任务表里也能判断“先进入哪条持续流程” - - 当 `当前经营焦点` 恰好就是已打开详情的那条任务时,当前又继续收掉一层重复取数,直接复用 `selectedSceneAppRuntime`,不再并行拉第二套 `overview runtime` - - 当前定向验证: - - `npm exec vitest run "src/components/settings-v2/system/automation/index.test.tsx" "src/components/settings-v2/system/automation/AutomationOverviewFocusCard.test.tsx" "src/components/settings-v2/system/automation/AutomationJobFocusStrip.test.tsx"` - - `npx eslint "src/components/settings-v2/system/automation/index.tsx" "src/components/settings-v2/system/automation/index.test.tsx" "src/components/settings-v2/system/automation/AutomationOverviewFocusCard.tsx" "src/components/settings-v2/system/automation/AutomationOverviewFocusCard.test.tsx" "src/components/settings-v2/system/automation/AutomationJobFocusStrip.tsx" "src/components/settings-v2/system/automation/AutomationJobFocusStrip.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 120000` - - 结果: - - `vitest` 通过:`3 files / 21 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过 - -- 把 `SceneScorecard -> 自动化详情里的做法闭环` 从“只读经营判断”推进到“可直接执行的业务去向”,避免 `生成结果卡 / sceneapps 深层页 / 工作台侧栏` 都已经能沿同一份结果基线继续下一步,但到了 `AutomationJobDetailsDialog` 仍然只剩标签摘要: - - 已更新: - - `src/components/sceneapps/sceneAppExecutionFollowupDestinations.ts` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` - - `src/components/settings-v2/system/automation/AutomationJobDetailsDialog.tsx` - - `src/components/settings-v2/system/automation/index.tsx` - - `src/components/settings-v2/system/automation/AutomationJobDetailsDialog.test.tsx` - - `src/components/settings-v2/system/automation/index.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 自动化详情里的 `经营判断` 当前会继续显影 `周会复盘 / 生成工作台 / 结果编辑` 这类业务去向的可执行动作,不再只显示 destinations 标签 - - `index.tsx` 当前也会先把 `descriptor + planResult + linkedRun + scorecard` 编成同一份 `sceneapp_execution_summary` 基线,再把“继续复盘当前项目”接回 `agent.initialInputCapability` - - 因此用户当前沿着 `自动化详情 -> 生成工作台` 这条链路时,也会继续带着 `当前结果基线 / 当前项目目标 / 当前已有结果`,不会在自动化旁路退回成静态说明 - - `sceneAppExecutionFollowupDestinations.ts` 当前成为结果卡与自动化详情共享的动作映射,避免两边再各写一套“这轮结果下一步去哪” - - 当前定向验证: - - `npx eslint "src/components/sceneapps/sceneAppExecutionFollowupDestinations.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx" "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.tsx" "src/components/settings-v2/system/automation/index.tsx" "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.test.tsx" "src/components/settings-v2/system/automation/index.test.tsx"` - - `npm exec vitest run "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.test.tsx" "src/components/settings-v2/system/automation/index.test.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 120000` - - 结果: - - `eslint` 通过 - - `vitest` 通过:`3 files / 27 tests passed` - - `verify:gui-smoke` 通过 - -- 把 `SceneScorecard -> GeneralWorkbench 当前进展 / 当前查看运行里的最近复盘建议卡` 从“只读提示”推进到“可直接续接到结果模板”,避免首页、launcher、结果卡和 `sceneapps` 深层页虽然都已经能点击下一步,但真正回到聊天工作台侧栏时,review 横幅仍然只是静态说明: - - 已更新: - - `src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx` - - `src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx` - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `GeneralWorkbenchWorkflowPanel` 当前会把最近复盘建议先编成可执行 follow-up payload,而不再只渲染 `reviewFeedbackProjection` 文案 - - 这条 payload 当前优先复用 `buildSceneAppExecutionCuratedTaskFollowUpAction(...)`,因此命中 `sceneapp_execution_summary` 基线时,仍会继续带着 `当前结果基线 / 当前项目目标 / 当前已有结果` - - 如果当前运行没有 `sceneapp` 结果基线,工作台侧栏当前也会继续复用同一条 `curated_task + referenceEntries + launchInputValues` 主链,不额外发明第四种 continuation 逻辑 - - `当前进展` 和 `当前查看运行` 两处最近复盘建议横幅当前都能直接把 continuation 回传给工作区 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts"` - - `npx eslint "src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx" "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts"` - - `npm run smoke:agent-service-skill-entry` - - `npm run verify:gui-smoke -- --timeout-ms 120000` - - 结果: - - `vitest` 通过:`2 files / 43 tests passed` - - `eslint` 通过 - - `smoke:agent-service-skill-entry` 通过 - - `verify:gui-smoke` 通过 - -- 把 `SceneScorecard -> sceneapps 深层页(review banner)` 从“只提示建议模板”推进到“可直接续接到 agent 结果模板”,避免聊天结果卡已经能点下一步,但 `做法表现 / 做法复盘 / 这轮结果` 里的最近复盘建议仍然只是说明文字: - - 已更新: - - `src/components/sceneapps/SceneAppReviewFeedbackBanner.tsx` - - `src/components/sceneapps/SceneAppScorecardPanel.tsx` - - `src/components/sceneapps/SceneAppGovernancePanel.tsx` - - `src/components/sceneapps/SceneAppRunDetailPanel.tsx` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `sceneapps` 深层页当前也会先把 `selectedDescriptor + selectedPlanResult + selectedRun/latestPackResult + scorecard` 编译成同一份 `sceneapp_execution_summary` 基线 - - `SceneAppReviewFeedbackBanner` 当前会给出“继续去某个结果模板”的动作按钮,不再只是横幅文案 - - 点击后 `useSceneAppsPageRuntime` 当前会复用 `buildSceneAppExecutionCuratedTaskFollowUpAction(...) + buildRuntimeInitialInputCapabilityFromFollowUpAction(...)`,直接导航回 `agent.initialInputCapability` 主链 - - continuation 当前仍会继续带着 `当前结果基线 / 当前项目目标 / 当前已有结果`,不会在 `sceneapps -> agent` 这条链路里退回成纯模板说明 - - 当前定向验证: - - `npm exec vitest run "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npx eslint "src/components/sceneapps/SceneAppReviewFeedbackBanner.tsx" "src/components/sceneapps/SceneAppScorecardPanel.tsx" "src/components/sceneapps/SceneAppGovernancePanel.tsx" "src/components/sceneapps/SceneAppRunDetailPanel.tsx" "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 120000` - - 结果: - - `vitest` 通过:`1 file / 33 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 本轮已执行到 `smoke:agent-runtime-tool-surface-page`,但最后卡在既有浏览器环境问题:`没有可用的 Chrome 会话,请先连接当前 Chrome 扩展并开启远程调试,或启动托管浏览器`;当前未把它判定为这轮 `sceneapps review continuation` 改动回归 - -- 把 `SceneScorecard -> 结果卡里的 review 建议横幅` 从“可见提示”推进到“可直接继续下一步”,避免首页、我的方法、launcher、发送前 badge 和发送后工作台虽然都已经围绕同一份项目结果基线收口,但真正落到 `SceneAppExecutionSummaryCard` 里的最近复盘建议时,用户仍然只能看到文案,不能直接接着做: - - 已更新: - - `src/components/agent/chat/utils/reviewFeedbackProjection.ts` - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts` - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `reviewFeedbackProjection` 当前除了建议标题,还会继续携带可执行的 `taskId/title`,不再只是横幅文案投影 - - `sceneAppCuratedTaskReference.ts` 当前新增通用 `buildSceneAppExecutionCuratedTaskFollowUpAction(...)`,因此结果卡上的 review 建议已经可以直接复用现有 `curated_task + referenceEntries` 主链,不新开第二套 continuation 协议 - - 当 review 建议切去非 `account-project-review` 的下游结果模板时,follow-up prompt 当前还会附上 `当前结果基线 / 当前项目目标 / 当前已有结果`,避免只剩一条参考对象摘要 - - `SceneAppExecutionSummaryCard` 当前会在最近复盘横幅里直接给出“继续去某个结果模板”的动作,点击后由 `AgentChatWorkspace` 复用既有 `applyWorkbenchFollowUpActionPayload(...)` 接回输入区主链 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` - - `npx eslint "src/components/agent/chat/utils/reviewFeedbackProjection.ts" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx"` - - `npm run smoke:agent-service-skill-entry` - - 结果: - - `vitest` 通过:`2 files / 12 tests passed` - - `eslint` 通过 - - `smoke:agent-service-skill-entry` 通过 - -- 把 `SceneScorecard -> 首页结果入口 / 我的方法 featured curated task 卡片` 这一段也接回下游结果模板基线,避免 `daily-trend-briefing / social-post-starter` 虽然在 slash、launcher、badge、当前进展里已经能解释这轮经营判断,但点击前卡片层仍只剩模板静态合同: - - 已更新: - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 首页 `结果入口` 当前会把 `当前结果基线:...` 直接编进推荐卡的 `contextSummary` - - `我的方法 -> 先拿结果` 当前也不再只让 `account-project-review` 显影经营摘要;带着 `sceneapp_execution_summary` 的下游结果模板会继续显示 `当前结果基线 / 当前判断 / 当前卡点 / 更适合去向` - - 因此 `首页/我的方法 卡片 -> slash -> launcher -> badge -> 当前进展` 这条 current 主链,当前已经在点击前卡片层也围绕同一份 `sceneapp` 基线说话 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run smoke:agent-service-skill-entry` - - 结果: - - `vitest` 通过:`2 files / 74 tests passed` - - `eslint` 通过 - - `smoke:agent-service-skill-entry` 通过 - - `verify:gui-smoke` 本轮额外重跑时遇到既有环境级问题:第一次卡在 `smoke:agent-runtime-tool-surface-page` 的 `browser_execute_action fetch failed`,第二次 fresh target 重编译期间 `DevBridge` 长时间未就绪;当前未把它判定为这轮卡片层改动回归 - -- 把 `SceneScorecard -> review follow-up -> 下游结果模板(active badge / slash / launcher / 当前进展)` 这条 continuation 最后一处断点补齐,避免 `复盘这个账号/项目` 虽然已经会带着 `sceneapp_execution_summary` 切到 `每日趋势摘要 / 内容主稿生成`,但前台显影又退回只剩模板静态说明: - - 已更新: - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts` - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts` - - `src/components/agent/chat/skill-selection/CuratedTaskBadge.tsx` - - `src/components/agent/chat/skill-selection/CuratedTaskBadge.test.tsx` - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx` - - `src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx` - - `src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `sceneAppCuratedTaskReference.ts` 当前会优先读取当前结果模板对应的 `taskPrefillByTaskId`,读不到时自动回退到同一条 `sceneapp_execution_summary` 里的 `account-project-review` 基线 - - 因此 `daily-trend-briefing / social-post-starter` 这类由复盘 follow-up 切过去的下游结果模板,当前也会继续显影 `当前结果基线 / 当前判断 / 更适合去向` - - 这份 fallback 基线当前已经同时接到了 slash 面板描述、发送前 active badge、launcher 顶部确认层,以及发送后的 `当前进展` 基线卡,不再只在复盘模板自身可见 - - 这一步继续只复用 `referenceEntries + sceneAppCuratedTaskReference.ts` 的共享 helper,没有引入新的 continuation 状态源 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts" "src/components/agent/chat/skill-selection/CuratedTaskBadge.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx" "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` - - `npx eslint "src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts" "src/components/agent/chat/skill-selection/CuratedTaskBadge.tsx" "src/components/agent/chat/skill-selection/CuratedTaskBadge.test.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx" "src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx" "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 120000` - - 结果: - - `vitest` 通过:`5 files / 136 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过 - -- 把 `SceneScorecard -> slash 面板结果模板 / launcher` 继续前推到对话内二次唤起入口,避免首页、我的方法、launcher、发送前 badge 和发送后工作台都已经围绕项目结果基线收口,但用户在对话里重新打开 `@ / /` 结果模板时,又退回只剩模板静态说明或丢最近启动参数: - - 已更新: - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - slash 面板里的 `account-project-review` 当前会显影轻量 `当前结果基线:...` 摘要,并继续带出 `当前判断 / 更适合去向` - - 普通 `curated_task` 条目当前也会携带合并后的 `launchPrefill + referenceEntries + referenceMemoryIds`,因此非空查询命中的结果模板仍会继续沿用最近一次启动参数 - - 因此 `slash -> 结果模板 -> launcher -> 生成` 这条 current 主链,当前也开始和首页 / 我的方法 / launcher / badge / 工作台围绕同一份上下文说话 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npx eslint "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 120000` - - 结果: - - `vitest` 通过:`1 file / 84 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过 - -- 把 `SceneScorecard -> 发送后第一层(GeneralWorkbench 当前进展 / 当前查看运行)` 继续前推到真正进入工作台后的首层摘要,避免首页、launcher 和发送前 badge 都已经会显影项目结果基线,但一发送进入 `生成工作台` 又退回只剩模板 follow-up 或最近复盘横幅: - - 已更新: - - `src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx` - - `src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `GeneralWorkbenchWorkflowPanel` 当前会在 `当前进展 -> 建议下一步` 与 `执行经过 -> 当前查看运行` 同时显影轻量 `当前结果基线` 卡 - - 命中 `account-project-review + sceneapp_execution_summary` 时,这张卡当前会继续带出 `当前判断 / 经营动作 / 更适合去向` - - 这层展示继续只复用 `sceneAppCuratedTaskReference.ts` 里的 `snapshot/highlights` helper,不新增工作台专属经营状态源 - - 因此 `首页/我的方法 -> launcher -> 发送前 badge -> 发送后工作台` 这条主链当前已经围绕同一份项目结果基线连通,不再在发送后退回只剩 follow-up - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` - - `npx eslint "src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx" "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 120000` - - 结果: - - `vitest` 通过:`1 file / 35 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过 - -- 把 `SceneScorecard -> 发送前最后一层(active curated task badge)` 继续前推到输入区顶部,避免首页、我的方法和 launcher 都已经会显影经营摘要,但用户真正准备发送前,active curated task badge 又退回只剩模板标题和 follow-up: - - 已更新: - - `src/components/agent/chat/skill-selection/CuratedTaskBadge.tsx` - - `src/components/agent/chat/skill-selection/CuratedTaskBadge.test.tsx` - - `src/components/agent/chat/components/EmptyStateComposerPanel.tsx` - - `src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx` - - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts` - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `CuratedTaskBadge` 当前已经可以接收 active curated task 的 `referenceEntries` - - 命中 `account-project-review + sceneapp_execution_summary` 时,badge 当前会显影紧凑版 `当前判断 / 更适合去向` - - `EmptyStateComposerPanel` 与 `useInputbarController` 当前都已经把 active capability 里的项目结果引用继续透传给 badge - - 因此 `首页/我的方法 -> launcher -> 发送前 badge` 这条主链当前已经不再在最后一层丢掉“这轮为什么这样继续”的解释 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/skill-selection/CuratedTaskBadge.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts"` - - `npx eslint "src/components/agent/chat/skill-selection/CuratedTaskBadge.tsx" "src/components/agent/chat/skill-selection/CuratedTaskBadge.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts"` - - `npm run typecheck` - - 结果: - - `vitest` 通过:`4 files / 69 tests passed` - - `eslint` 通过 - - `typecheck` 未通过;当前阻塞来自仓库现存测试与设置页类型问题,与本轮 badge 补线无关: - - `src/components/agent/chat/utils/buildUserInputSubmitOp.test.ts(225,12): 'op.preferences' is possibly 'undefined'` - - `src/components/agent/chat/utils/buildUserInputSubmitOp.test.ts(226,12): 'op.preferences' is possibly 'undefined'` - - `src/components/settings-v2/agent/providers/CompanionCapabilityPreferencesCard.tsx(388,11): providerLabel 不存在于 MediaPreferenceSectionProps` - - `src/components/settings-v2/agent/providers/CompanionCapabilityPreferencesCard.tsx(400,27): implicit any` - - `src/components/settings-v2/agent/providers/CompanionCapabilityPreferencesCard.tsx(447,11): providerLabel 不存在于 MediaPreferenceSectionProps` - - `src/components/settings-v2/agent/providers/CompanionCapabilityPreferencesCard.tsx(459,27): implicit any` - -- 把 `SceneScorecard -> 复盘模板启动确认层(CuratedTaskLauncherDialog)` 继续前推到真正点击后的确认层,避免首页和我的方法卡片虽然已经会显影经营摘要,但用户一进入 `复盘这个账号/项目` launcher,又退回只剩模板静态说明: - - 已更新: - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx` - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts` - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `CuratedTaskLauncherDialog` 当前会在顶部确认层显影 `当前结果基线` 卡,并继续显示 `当前判断 / 当前卡点 / 更适合去向` - - 这张卡继续只复用 `sceneAppCuratedTaskReference.ts` 里的共享拆解 helper,不新开 launcher 专属经营状态源 - - `项目结果` 类型的参考对象卡当前也会同步显影同一份经营摘要,保证顶部确认、字段预填和参考对象列表说的是同一件事 - - 因此 `首页/我的方法 -> 复盘模板 -> 启动确认层` 这条主链当前已经不再在最后一步丢掉“这轮为什么这样继续”的解释 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts"` - - `npx eslint "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts"` - - `npm run verify:local` - - `npm run typecheck` - - 结果: - - `vitest` 通过:`2 files / 9 tests passed` - - `eslint` 通过 - - `verify:local` 未通过;当前阻塞来自仓库现存 lint 警告,与本轮 launcher 补线无关: - - `src/components/agent/chat/workspace/useWorkspaceSendActions.ts:4434 react-hooks/exhaustive-deps` - - `typecheck` 未通过;当前阻塞来自仓库现存测试和设置页缺件,与本轮 launcher 补线无关: - - `src/components/agent/chat/utils/buildUserInputSubmitOp.test.ts(225,12): 'op.preferences' is possibly 'undefined'` - - `src/components/agent/chat/utils/buildUserInputSubmitOp.test.ts(226,12): 'op.preferences' is possibly 'undefined'` - - `src/components/settings-v2/agent/image-gen/index.tsx: Cannot find module '../shared/MediaPreferenceSection'` - - `src/components/settings-v2/agent/providers/CompanionCapabilityPreferencesCard.tsx: Cannot find module '../shared/MediaPreferenceSection'` - - `src/components/settings-v2/agent/providers/CompanionCapabilityPreferencesCard.tsx: implicit any` - - `src/components/settings-v2/agent/video-gen/index.tsx: Cannot find module '../shared/MediaPreferenceSection'` - - `src/components/settings-v2/agent/voice/index.tsx: Cannot find module '../shared/MediaPreferenceSection'` - -## 2026-04-22 - -### 已完成 - -- 把 `SceneScorecard -> 首页结果入口 / 我的方法里的复盘模板卡片` 继续前推到点击前入口,避免 `复盘这个账号/项目` 虽然已经会在启动时带上 `existing_results`,但用户在卡片层仍然只能看到模板静态说明: - - 已更新: - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts` - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `sceneAppCuratedTaskReference.ts` 当前新增共享 helper,会从 `sceneapp_execution_summary` 参考对象里的 `account-project-review` prefill 继续拆出 `当前判断 / 当前卡点 / 经营动作 / 更适合去向` - - 首页 `EmptyState` 当前会把这份摘要显影到 `复盘这个账号/项目` 推荐卡,用户点击前就能看见这轮现在卡在哪、该往哪里接 - - `SkillsWorkspacePage` 当前也会在同一张复盘模板卡片里显影 `当前结果基线` 经营摘要,而不只是停在顶部 `围绕最近复盘` 横幅 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run typecheck` - - 结果: - - `vitest` 通过:`3 files / 75 tests passed` - - `eslint` 通过 - - `typecheck` 未通过;当前阻塞来自仓库现存测试文件空值收口,与本轮首页/我的方法卡片补线无关: - - `src/components/agent/chat/utils/buildUserInputSubmitOp.test.ts(225,12): 'op.preferences' is possibly 'undefined'` - - `src/components/agent/chat/utils/buildUserInputSubmitOp.test.ts(226,12): 'op.preferences' is possibly 'undefined'` - -- 把 `SceneScorecard -> 做法目录卡片 / 复盘模板起手链` 继续前推到更靠前的入口,避免统一聚合对象虽然已经接到 `生成结果卡 / 做法表现 / 自动化详情`,但用户在目录卡和 `复盘这个账号/项目` 启动前仍然只能看到旧粒度的状态文案: - - 已更新: - - `src/lib/sceneapp/product.ts` - - `src/lib/sceneapp/product.test.ts` - - `src/components/sceneapps/SceneAppsCatalogPanel.tsx` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts` - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `buildSceneAppCatalogCardViewModel` 当前也会携带统一 `SceneAppScorecardAggregateViewModel` - - `做法目录卡片` 当前会优先显示同一份经营摘要,而不是只剩 `status + actionLabel` - - `buildCuratedTaskReferenceEntryFromSceneAppExecution` 当前会把 `当前判断 / 经营动作 / 更适合去向` 一起编进 `account-project-review` 的 `existing_results` - - 因此用户在 `做法目录 -> 复盘这个账号/项目` 这条更靠前的主链里,当前已经不需要自己再把运行结果和经营判断翻译一遍 - - 当前定向验证: - - `npm exec vitest run "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts"` - - `npx eslint "src/lib/sceneapp/product.ts" "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsCatalogPanel.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts"` - - `npm run typecheck` - - 结果: - - `vitest` 通过:`3 files / 54 tests passed` - - `eslint` 通过 - - `typecheck` 通过 - -- 把 `SceneScorecard -> 生成结果卡 / 做法表现 / 自动化详情` 这条主线聚合入口继续接通,避免 `SceneScorecard` 仍然散在 `operating summary / runtime backflow / automation card` 各自翻译,导致不同入口对“这轮该不该继续、先修哪里、先去哪”给出不同口径: - - 已更新: - - `src/lib/sceneapp/product.ts` - - `src/lib/sceneapp/product.test.ts` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` - - `src/components/sceneapps/SceneAppScorecardPanel.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `src/components/settings-v2/system/automation/AutomationJobDetailsDialog.tsx` - - `src/components/settings-v2/system/automation/AutomationJobDetailsDialog.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `product.ts` 当前新增统一 `SceneAppScorecardAggregateViewModel`,把 `status / summary / nextAction / actionLabel / topFailureSignal / destinations / metricKeys / failureSignals` 收成单一业务摘要对象 - - `buildSceneAppExecutionSummaryViewModel + backfillSceneAppExecutionSummaryViewModel` 当前会把这份摘要带到 `生成` 结果卡 - - `buildSceneAppScorecardViewModel` 当前也会把同一份摘要带到 `做法表现` - - `buildSceneAppAutomationWorkspaceCardViewModel` 当前会把同一份摘要带到自动化详情里的 `做法闭环` - - 因此 `生成结果卡 / 做法表现 / 自动化详情` 当前已经不再各写一段“下一步建议”,而是围绕同一份 `SceneScorecard` 聚合对象解释“这轮状态 / 当前卡点 / 下一步 / 适合去向` - - 当前定向验证: - - `npm exec vitest run "src/lib/sceneapp/product.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.test.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npx eslint "src/lib/sceneapp/product.ts" "src/lib/sceneapp/product.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/components/sceneapps/SceneAppScorecardPanel.tsx" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.tsx" "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.test.tsx"` - - `npm run typecheck` - - 结果: - - `vitest` 通过:`4 files / 61 tests passed` - - `eslint` 通过 - - `typecheck` 通过 - -- 把 `人工复盘 -> 全部做法深层结果面(sceneapps governance / run detail / scorecard)` 这条旁支结果链补齐,避免 `sceneapps` 页里的 `做法复盘 / 这轮结果 / 做法表现` 还停在静态 `最近反馈`,和首页、输入层、工作台、结果卡已经补齐的 `review_feedback` 解释链重新脱节: - - 已更新: - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/SceneAppGovernancePanel.tsx` - - `src/components/sceneapps/SceneAppRunDetailPanel.tsx` - - `src/components/sceneapps/SceneAppScorecardPanel.tsx` - - `src/components/sceneapps/SceneAppReviewFeedbackBanner.tsx` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `sceneapps` runtime 当前会按 `selectedProjectId + selectedRunSessionId/latestPackResultSessionId` 读取最新一条 `review_feedback` 推荐信号 - - `做法复盘 / 这轮结果 / 做法表现` 当前都会显影 `围绕最近复盘` 横幅,并带出最近复盘标题、复盘摘要与更适合继续的结果模板 - - 因此 `当前结果 -> 人工复盘 -> sceneapps 深层结果面` 这条旁支结果链,当前也已经不再在 `sceneapps` 里丢掉“为什么这轮这样继续”的解释 - - 当前定向验证: - - `npm exec vitest run "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npx eslint "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/sceneapps/SceneAppGovernancePanel.tsx" "src/components/sceneapps/SceneAppRunDetailPanel.tsx" "src/components/sceneapps/SceneAppScorecardPanel.tsx" "src/components/sceneapps/SceneAppReviewFeedbackBanner.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke -- --timeout-ms 120000` - - 结果: - - `vitest` 通过:`1 file / 32 tests passed` - - `eslint` 通过 - - `typecheck` 未通过;当前阻塞来自仓库现存设置页类型错误,与本轮 `sceneapps` 结果面补线无关: - - `src/components/settings-v2/agent/media-services/index.tsx(652,35): Type 'string' is not assignable to type '"azure" | "openai" | "google" | "whisper" | undefined'` - - `verify:gui-smoke` 已触发;当前停在 fresh cargo target 冷编译与 `DevBridge` 就绪前等待,若最终只体现为环境级耗时,将单独标注,不回滚这轮代码结论 - -- 把 `人工复盘 -> 结果卡(SceneAppExecutionSummaryCard)` 这条结果源头链补齐,避免用户在首页、输入层和工作台都已经能看懂“最近复盘让这轮该怎么继续”,但一回到结果卡本身,又只剩静态 `最近反馈`: - - 已更新: - - `src/components/agent/chat/utils/reviewFeedbackProjection.ts` - - `src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `reviewFeedbackProjection` 当前已下沉成共享 helper,不再只停在 workflow sidebar - - `SceneAppExecutionSummaryCard` 当前会直接显影 `围绕最近复盘` 横幅,并带出最近复盘标题、复盘摘要与更适合继续的结果模板 - - 因此 `当前结果 -> 人工复盘 -> 结果卡` 这一段,当前也已经不再丢掉“为什么这轮这样继续”的解释 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` - - `npx eslint "src/components/agent/chat/utils/reviewFeedbackProjection.ts" "src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - - 结果: - - `vitest` 通过:`2 files / 39 tests passed` - - `eslint` 通过 - - `typecheck` 已触发;当前未见新增类型错误 - - `verify:gui-smoke` 已触发;若最终仅出现环境级延迟,将单独标注,不回滚这轮代码结论 - -- 把 `人工复盘 -> 当前查看运行(run detail)` 这条结果侧链补齐,避免 `当前进展` 已经能显影最近复盘,但用户一展开 `执行经过 -> 当前查看运行`,又退回只剩运行摘要和模板自带 follow-up: - - 已更新: - - `src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx` - - `src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `GeneralWorkbenchWorkflowPanel` 当前把 `review_feedback` 的前台投影抽成共享复盘卡 - - 这张复盘卡当前会同时显影在 `当前进展 -> 建议下一步` 与 `执行经过 -> 当前查看运行` - - 因此 `当前结果 -> 人工复盘 -> 当前查看运行` 这条结果侧链,当前已经不再在 run detail 这一段丢掉“为什么这轮这样继续”的解释 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` - - `npx eslint "src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx" "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - - 结果: - - `vitest` 通过:`1 file / 33 tests passed` - - `eslint` 通过 - - `typecheck` 通过 - - `verify:gui-smoke` 通过 - -- 把 `人工复盘 -> 当前进展(workflow sidebar)` 这条结果侧主链补齐,避免首页、`我的方法`、slash、launcher 和输入条 active badge 都已经能解释“为什么这轮该这样继续”,但用户一回到 `生成工作台 -> 当前进展 -> 建议下一步` 又退回只看模板自带 follow-up: - - 已更新: - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx` - - `src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx` - - `src/components/agent/chat/components/buildGeneralWorkbenchSidebarOrchestrationSource.ts` - - `src/components/agent/chat/components/buildGeneralWorkbenchWorkflowPanelProps.ts` - - `src/components/agent/chat/components/generalWorkbenchSidebarComparator.ts` - - `src/components/agent/chat/components/generalWorkbenchSidebarContract.ts` - - `src/components/agent/chat/components/useGeneralWorkbenchSidebarOrchestration.ts` - - `src/components/agent/chat/workspace/WorkspaceGeneralWorkbenchSidebar.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `GeneralWorkbenchSidebar` 当前会把 `projectId / sessionId` 继续透传进 workflow panel - - `当前进展 -> 建议下一步` 当前会复用 current scope 下最新一条 `review_feedback` 推荐信号 - - 命中当前结果模板时,当前会显影 `围绕最近复盘` banner,并明确说明这轮仍建议沿当前模板继续推进 - - 因此 `当前结果 -> 人工复盘 -> 当前进展` 这条结果侧主链,当前已经不再在 workflow sidebar 这一段丢掉复盘解释 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` - - `npx eslint "src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx" "src/components/agent/chat/components/generalWorkbenchSidebarContract.ts" "src/components/agent/chat/components/generalWorkbenchSidebarComparator.ts" "src/components/agent/chat/components/buildGeneralWorkbenchSidebarOrchestrationSource.ts" "src/components/agent/chat/components/buildGeneralWorkbenchWorkflowPanelProps.ts" "src/components/agent/chat/components/useGeneralWorkbenchSidebarOrchestration.ts" "src/components/agent/chat/workspace/WorkspaceGeneralWorkbenchSidebar.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - - 结果: - - `vitest` 通过:`1 file / 32 tests passed` - - `eslint` 通过 - - `typecheck` 通过 - - `verify:gui-smoke` 通过 - -- 把 `人工复盘 -> 输入条 active curated task badge / 编辑态 launcher` 这条发送前最后一段闭环补齐,避免 slash 面板和 launcher 已经能解释“为什么这轮该这样继续”,但模板一旦真正激活到输入条顶部,就又退回只剩标题: - - 已更新: - - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` - - `src/components/agent/chat/components/Inputbar/index.tsx` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `src/components/agent/chat/components/EmptyStateComposerPanel.tsx` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/skill-selection/CuratedTaskBadge.tsx` - - `src/components/agent/chat/skill-selection/CuratedTaskBadge.test.tsx` - - `src/components/agent/chat/workspace/chatSurfaceProps.ts` - - `src/components/agent/chat/workspace/WorkspaceConversationScene.tsx` - - `src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `Inputbar` 当前会把 `projectId / sessionId` 透传给 active `CuratedTaskBadge` - - 编辑态 `CuratedTaskLauncherDialog` 当前也会继续收到同一组上下文作用域 - - workspace `EmptyState` 当前也会把 `sessionId` 继续透传给 empty-state composer 与 launcher - - `CuratedTaskBadge` 当前在命中最近复盘偏好模板时,会显影一条紧凑 `围绕最近复盘` pill - - 因此 `当前结果 -> 人工复盘 -> slash / launcher -> active curated task badge -> 编辑 / 发送` 当前已经不再在最后一段丢掉“为什么这轮这样继续”的解释 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/skill-selection/CuratedTaskBadge.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npx eslint "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/index.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/skill-selection/CuratedTaskBadge.tsx" "src/components/agent/chat/skill-selection/CuratedTaskBadge.test.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - - 结果: - - `vitest` 通过:`2 files / 43 tests passed` - - `vitest` 通过:`3 files / 108 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过 - - `typecheck` 未通过;当前阻塞来自仓库现存设置页模块缺失,与本轮输入条闭环改动无关: - - `src/components/settings-v2/agent/image-gen/index.test.tsx(31,34): Cannot find module '.'` - - `src/components/settings-v2/agent/media-services/index.tsx(19,39): Cannot find module '../image-gen'` - - `src/components/settings-v2/agent/media-services/preload.ts(9,23): Cannot find module '../image-gen'` - -- 把 `人工复盘 -> slash 面板 / launcher` 这条输入层起手链补成可解释的前台闭环,避免首页和 `我的方法` 页已经能说明“为什么这轮该这样继续”,但用户一回到输入层就又只剩排序变化: - - 已更新: - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - slash 面板里的 `结果模板` 分组当前会显影 `最近复盘已更新` 横幅 - - `CuratedTaskLauncherDialog` 当前在命中最近复盘偏好模板时,也会继续显影同一轮复盘提示 - - 这两处都不新开 recommendation store,而是继续复用 `review_feedback signal + featured curated task` 主链 - - 因此 `当前结果 -> 人工复盘 -> slash / launcher -> 下一轮生成` 当前已经不再只是“排序变了”,而是输入层也能明确解释“为什么这轮更适合这样继续” - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx"` - - `npx eslint "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx" "src/components/agent/chat/components/EmptyState.tsx" "src/components/skills/SkillsWorkspacePage.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - - 结果: - - `vitest` 通过:`2 files / 87 tests passed` - - `eslint` 通过 - - `typecheck` 通过 - - `verify:gui-smoke` 通过 - -- 把 `人工复盘 -> 首页结果入口 / 我的方法页` 这条异步回写补成首屏可解释的复盘横幅,并把这轮主路径 GUI smoke 补跑坐实,避免 `review_feedback` 虽然已经影响推荐排序,但用户首屏还是只能靠猜来理解“为什么这轮更适合这样继续”: - - 已更新: - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 首页 `结果入口` 与 `我的方法` 页 `先拿结果` 区块,当前都会在 current 项目存在最新 `review_feedback` 信号时显影 `最近复盘已更新` 横幅 - - 横幅当前直接显示 `复盘标题 + 复盘摘要 + 更适合继续的两条结果模板` - - 这两条推荐不会新开 review-only 推荐器,而是继续复用已有 `featured curated task` 主链;只是把“排序变化”翻译成首屏可理解的前台提示 - - 因此 `当前结果 -> 人工复盘 -> 回到首页 / 我的方法 -> 下一轮结果入口` 当前已经从“推荐顺序被改了”推进到“首屏能直接看懂为什么这样继续” - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - - 结果: - - `vitest` 通过:`1 file / 47 tests passed` - - `vitest` 通过:`1 file / 24 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过 - - 上一轮 `inferModelCapabilities` 的类型阻塞当前已不再出现;但本轮全量 `typecheck` 仍被两处与本次改动无关的仓库现存错误挡住: - - `src/components/settings-v2/agent/providers/index.tsx(1628,45): metadata.task_families is possibly undefined` - - `src/components/settings-v2/system/about/index.test.tsx(159,12): delete operand must be optional` - -- 把 `当前进展/结果卡 -> 建议下一步 -> 输入主执行面` 这条链补成有明确前台提示的 continuation,避免用户虽然已经点了下一步,但输入区只变了 prompt,没告诉他“现在到底沿着什么继续”: - - 已更新: - - `src/components/agent/chat/components/generalWorkbenchSidebarContract.ts` - - `src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts` - - `src/components/agent/chat/utils/sceneAppExecutionPromptContinuation.ts` - - `src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx` - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts` - - `src/components/agent/chat/utils/sceneAppExecutionPromptContinuation.test.ts` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `GeneralWorkbench` 的 `建议下一步` 当前会在 continuation payload 里同步携带一条 `bannerMessage` - - 同模板 continuation 当前会显式说明“已按哪条下一步继续推进”,跨模板 continuation 当前会显式说明“已切到哪条结果模板继续生成” - - `AgentChatWorkspace` 当前会复用现有 `entry banner` 主链,把这条提示显影到输入区上方,而不是另开一套 follow-up 提示系统 - - `SceneApp` 结果卡里的 `复盘当前项目` 与同聊 continuation 当前也已经对齐到同一条 banner 事实源 - - 即使用户手动关闭过同文案 banner,再次点击同一条 follow-up,当前也会重新显影 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts" "src/components/agent/chat/utils/sceneAppExecutionPromptContinuation.test.ts" "src/components/agent/chat/utils/inputCapabilityBootstrap.test.ts"` - - `npx eslint "src/components/agent/chat/components/generalWorkbenchSidebarContract.ts" "src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts" "src/components/agent/chat/utils/sceneAppExecutionPromptContinuation.ts" "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts" "src/components/agent/chat/utils/sceneAppExecutionPromptContinuation.test.ts"` - - `npm run typecheck` - - 结果: - - `vitest` 通过:`4 files / 39 tests passed` - - `eslint` 通过 - - `typecheck` 未通过;当前阻塞来自仓库现有模型元数据链,而不是本轮 follow-up 连续性改动: - - `src/lib/model/inferModelCapabilities.test.ts` - - `src/lib/model/inferModelCapabilities.ts` - -- 把 `带回生成 -> 生成首页` 这条链补成首屏可感知的连续性显影,避免 `creation replay` 只停在输入框顶上一枚被动 badge: - - 已更新: - - `src/components/agent/chat/components/CreationReplaySurfaceBanner.tsx` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/agent/chat/utils/creationReplaySurface.ts` - - `src/components/agent/chat/utils/creationReplaySurface.test.ts` - - `src/components/agent/chat/workspace/WorkspaceConversationScene.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 首页 `结果入口` 当前会在带着 `creation replay` 进入时直接显影一条连续性横幅,和 `生成工作台` 使用同一份 surface facts - - 横幅当前会直接说明 `当前带入什么 / 当前会怎么沿用 / 当前标题与摘要` - - `结果入口` 标题、说明和主推荐 eyebrow 当前也会同步切成更强的 continuation 文案,不再只写通用的“从这里开始” - - `skill_scaffold creation replay` 的前台词当前也已从 `技能草稿` 收口到 `做法草稿` - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/utils/creationReplaySurface.test.ts" "src/components/agent/chat/workspace/WorkspaceConversationScene.test.tsx"` - - `npx eslint "src/components/agent/chat/components/CreationReplaySurfaceBanner.tsx" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/utils/creationReplaySurface.ts" "src/components/agent/chat/utils/creationReplaySurface.test.ts" "src/components/agent/chat/workspace/WorkspaceConversationScene.tsx"` - - `npm run typecheck` - - 结果: - - `vitest` 通过:`3 files / 51 tests passed` - - `eslint` 通过 - - `typecheck` 通过 - -- 把 `我的方法库 -> 生成` 这条链补上更明确的前台连续性提示,避免用户虽然已经回到生成,但首屏不知道自己是沿着哪套方法回来的: - - 已更新: - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `我的方法库` 里的 installed skill 当前进入 `生成` 时会统一带上 `entryBannerMessage` - - 如果这次同时沿用了 `上次目标`,前台当前会显式写成“带着方法 + 上次目标进入生成” - - 因此 `我的方法库 -> 生成` 当前不再只是 capability route 生效,而是连“为什么回到这里、当前沿用哪套方法”也能在首屏看见 - - 当前定向验证: - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run typecheck` - - 结果: - - `vitest` 通过:`1 file / 23 tests passed` - - `eslint` 通过 - - `typecheck` 通过 - -- 把 `结果 -> 做法草稿 -> 我的方法页` 这条链继续补成首屏可理解、可回跳的闭环,避免用户虽然被带到了方法页,但还要靠弹窗和记忆自己理解当前上下文: - - 已更新: - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `我的方法` 页当前会在有 `initialScaffoldDraft` 时显影搜索区内的轻量 `当前草稿` strip,只保留 `草稿名 + 上次目标 + 来源摘要` - - 当前动作也已收成两个短按钮: - - `整理` - - `带回生成` - - 因此 `SceneApp 结果 -> 我的方法页 -> 整理 / 带回生成` 当前已经不再只是弹窗层面的半隐式状态,同时也不会再用重横幅抢走 `先拿结果` 的首屏权重 - - 当前定向验证: - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run typecheck` - - 结果: - - `vitest` 通过:`1 file / 23 tests passed` - - `eslint` 通过 - - `typecheck` 通过 - -- 把 `创建 Skill -> 回到我的方法库` 这条链继续补成“首屏就能续上”的闭环,避免用户虽然看见了“刚沉淀”,但还要自己再去找卡片按钮: - - 已更新: - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `我的方法库` 当前会在刚沉淀成功的新做法上方显示一条轻量续接横幅 - - 横幅当前直接显影 `做法名 + 上次目标 + 输入要求 + 结果去向` - - CTA 当前继续复用 `installed_skill capability route + slash usage.replayText`,可直接把用户带回 `生成` - - 因此 `SceneApp 结果 -> 沉淀为做法 -> 创建 Skill -> 我的方法库` 这条链,当前已经推进成“回到方法库首屏即可继续下一轮” - - 当前定向验证: - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run typecheck` - - 结果: - - `vitest` 通过:`1 file / 23 tests passed` - - `eslint` 通过 - - `typecheck` 通过 - -- 把 `SceneApp` 结果卡里的“结果去向”从说明卡补成可点击的业务续接卡,避免用户看到去向却还要自己再找入口: - - 已更新: - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `周会复盘 / 生成工作台 / 持续流程 / 结果编辑` 这 4 类去向,当前不再只是描述型卡片,而会在结果卡里直接暴露续接按钮 - - 这些续接入口当前继续复用同一条 current 动作边界,不新开第二套结果去向协议: - - `周会复盘` 复用 `governanceAction / governanceArtifact` - - `生成工作台` 复用 `复盘当前项目` - - `持续流程` 复用 `entryAction(open_automation_job)` - - `结果编辑 / 发布` 复用 `deliveryArtifact` - - 因此 `SceneApp 结果 -> 业务去向 -> 下一步动作` 当前已经不只停留在说明层,而是能在同一张结果卡里直接继续推进 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` - - `npx eslint "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` - - `npm run typecheck` - - 结果: - - `vitest` 通过:`1 file / 5 tests passed` - - `eslint` 通过 - - `typecheck` 通过 - -- 把 `SceneApp 结果 -> 沉淀为做法 -> 创建 Skill -> 首页继续上次做法` 这条链补成真闭环,避免新做法只是回到方法库高亮,却还没进入 recent 主链: - - 已更新: - - `src/components/skills/skillScaffoldCreationSeed.ts` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `buildSkillScaffoldReplayText(...)` 当前会从技能草稿里提取一条适合 recent continuation 的 `replayText`,不再把“刚创建的新做法”留在无 recent 语义的空白态 - - `SkillsWorkspacePage` 当前在技能草稿创建成功后,会立刻为新 skill 写入 `slashEntryUsage(kind = "skill")` - - 因此新做法除了继续保留 `刚沉淀` 高亮,也会在同页直接显影 `上次目标`,并能继续进入首页 / 我的方法 / 输入层共用的 installed skill recent 主链 - - 这一步没有新增任何 installed skill 专属 recent store,只是复用现有 `slashEntryUsage` - - 当前定向验证: - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/skills/skillScaffoldCreationSeed.ts" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run typecheck` - - 结果: - - `vitest` 通过:`1 file / 22 tests passed` - - `eslint` 通过 - - `typecheck` 通过 - -- 把 `sceneapp current-first` 收口的最后尾巴补齐,避免代码已经收干净,但 current planning source 和进度日志仍把旧别名写成现役路径: - - 已更新: - - `src/lib/api/sceneapp.ts` - - `docs/roadmap/limenextv2/sceneapp-current-boundary.md` - - `docs/exec-plans/limenext-progress.md` - - `docs/exec-plans/limenext-v2-fs-blocker-2026-04-22.md` - - 当前统一结论: - - `src/lib/api/sceneapp.ts` 已移除最后两个未使用的 `SceneAppExecutionPlan / SceneAppRuntimeAdapterPlan` import,`sceneapp` API 边界当前不再残留对象级过渡命名的 lint 尾巴 - - `docs/roadmap/limenextv2/sceneapp-current-boundary.md` 当前已重写为现状版:base `SceneApp*` 是 current 对象事实源,compat 旧值只允许停留在显式 compat 输入、目录编译、API 归一化和 compat 展示边界 - - `docs/exec-plans/limenext-v2-fs-blocker-2026-04-22.md` 当前已明确标注为历史阻塞记录;其中提到的临时命名如 `SceneAppCurrentPresentationDescriptor` 只按当时阶段理解,不再代表 current 实现 - - 经 `rg` 扫描,仓库里的 `SceneAppCurrent*` 现役命中当前只剩 `eslint.config.js` 守卫与历史文档,不再出现在源码实现或公开出口 - - 当前定向验证: - - `npm run typecheck` - - `npx eslint "src/lib/sceneapp/types.ts" "src/lib/api/sceneapp.ts" "eslint.config.js"` - - `npm exec vitest run "src/lib/api/sceneapp.test.ts" "src/lib/sceneapp/catalog.test.ts" "src/lib/sceneapp/presentation.test.ts" "src/lib/sceneapp/product.test.ts" "src/lib/sceneapp/launch.test.ts" "src/components/agent/chat/workspace/sceneAppLaunch.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `rg -n "SceneAppCurrentBindingFamily|SceneAppCurrentRuntimeAction|SceneAppCurrentType|SceneAppCurrentLaunchRequirementKind|SceneAppCurrentDescriptor|SceneAppCurrentCatalog|SceneAppCurrentPlanResult|SceneAppCurrentRuntimeAdapterPlan|SceneAppCurrentExecutionPlan|SceneAppCurrentReadiness|SceneAppCurrentEntryBinding|SceneAppCurrentCompositionProfile|SceneAppCurrentCompositionStepDescriptor|SceneAppCurrentExecutionPlanStep|SceneAppCurrentLaunchRequirement" .` - - 结果: - - `typecheck` 通过 - - `eslint` 通过 - - `vitest` 通过:`7 files / 71 tests passed` - - `rg` 扫描确认:仓库里的 `SceneAppCurrent*` 现役命中只剩 `eslint.config.js` 守卫与历史文档,不再出现在源码实现或公开出口 - - 当前文档口径已经从“base current + 过渡 current 别名并存”收敛为“base current 对象 + compat 输入边界” - -- 把 `sceneapp` 对象级 `Current*` 过渡出口真正删除,避免它们继续以“虽然没人用,但还能导出”的方式留在边界层: - - 已更新: - - `src/lib/sceneapp/types.ts` - - `src/lib/api/sceneapp.ts` - - `docs/roadmap/limenextv2/sceneapp-current-boundary.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `SceneAppCurrentDescriptor / SceneAppCurrentCatalog / SceneAppCurrentPlanResult` 以及配套的 `EntryBinding / CompositionProfile / ExecutionPlan / RuntimeAdapterPlan / Readiness` 这一组对象级别名当前已从 `types.ts` 删除 - - `api/sceneapp.ts` 当前也已同步移除这组对象级 re-export,因此它们不再是仓库里的公开类型出口 - - 经过 `rg` 扫描,`src` 中这组对象级 `Current*` 当前只剩历史文档,不再出现在源码实现或边界出口 - - 当前保留的 current 标量类型已改成无 `Current` 前缀命名,如 `SceneAppExecutorBindingFamily / SceneAppExecutionRuntimeAction / SceneAppType / SceneAppLaunchRequirementCoreKind` - - 当前定向验证: - - `npm run typecheck` - - `npx eslint "src/lib/sceneapp/types.ts" "src/lib/api/sceneapp.ts" "eslint.config.js"` - - `rg -n "SceneAppCurrentDescriptor|SceneAppCurrentCatalog|SceneAppCurrentPlanResult|SceneAppCurrentRuntimeAdapterPlan|SceneAppCurrentExecutionPlan|SceneAppCurrentReadiness|SceneAppCurrentEntryBinding|SceneAppCurrentCompositionProfile|SceneAppCurrentCompositionStepDescriptor|SceneAppCurrentExecutionPlanStep|SceneAppCurrentLaunchRequirement" src` - - `npm exec vitest run "src/lib/api/sceneapp.test.ts"` - - `printf 'import type { SceneAppCurrentDescriptor } from "@/lib/api/sceneapp";\\ntype _Smoke = SceneAppCurrentDescriptor;\\n' | npx eslint --stdin --stdin-filename "src/components/sceneapps/__sceneapp-removed-current-alias-smoke.ts"` - - 结果: - - `typecheck` 通过 - - `eslint` 通过 - - `rg` 扫描确认:源码内对象级 `Current*` 已清零 - - `1 file / 5 tests passed` - - `stdin removed current alias guard expected failure observed` - -- 把 `sceneapp API` 内部实现与 `Current` 过渡别名守卫继续收口,避免 current 主对象虽然已经统一,但 `api` 边界内部仍沿用旧别名思维: - - 已更新: - - `src/lib/api/sceneapp.ts` - - `eslint.config.js` - - `docs/roadmap/limenextv2/sceneapp-current-boundary.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `api/sceneapp.ts` 当前内部已切回 base `SceneAppCatalog / SceneAppDescriptor / SceneAppPlanResult / SceneAppLaunchRequirement` - - `SceneAppExecutorBindingFamily / SceneAppExecutionRuntimeAction` 当前在 `api` 内也已缩成局部 helper 类型,分别改由 `SceneAppExecutionPlan["bindingFamily"]` 与 `SceneAppRuntimeAdapterPlan["runtimeAction"]` 派生 - - `eslint.config.js` 当前也已把 `SceneAppCurrentDescriptor / SceneAppCurrentPlanResult / SceneAppCurrentCatalog` 的导入守卫扩大到整个 `src`,只显式豁免 `src/lib/api/sceneapp.ts` - - 这意味着 `SceneAppCurrent*` 当前已基本只剩 `types.ts / api` 的过渡 re-export surface;`src` 其余实现面重新引入这些别名时会被直接拦下 - - 当前定向验证: - - `npm run typecheck` - - `npx eslint "src/lib/api/sceneapp.ts" "eslint.config.js"` - - `printf 'import type { SceneAppCurrentPlanResult } from "@/lib/api/sceneapp";\\ntype _Smoke = SceneAppCurrentPlanResult;\\n' | npx eslint --stdin --stdin-filename "src/components/sceneapps/__sceneapp-current-alias-global-guard-smoke.ts"` - - `npm exec vitest run "src/lib/api/sceneapp.test.ts" "src/lib/sceneapp/catalog.test.ts" "src/lib/sceneapp/presentation.test.ts" "src/lib/sceneapp/product.test.ts"` - - 结果: - - `typecheck` 通过 - - `eslint` 通过 - - `stdin current alias global guard expected failure observed` - - `4 files / 29 tests passed` - -- 把 `sceneapp` 测试工厂与目录编译剩余的 base current 别名继续收掉,避免 default fixture 仍把 `SceneAppCurrent*` 当默认建模词: - - 已更新: - - `src/lib/sceneapp/catalog.ts` - - `src/lib/sceneapp/launch.test.ts` - - `src/components/agent/chat/workspace/sceneAppLaunch.test.ts` - - `src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.test.tsx` - - `src/components/settings-v2/system/automation/index.test.tsx` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `docs/roadmap/limenextv2/sceneapp-current-boundary.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `launch.test.ts / sceneAppLaunch.test.ts / useWorkspaceSceneAppEntryActions.test.tsx / index.test.tsx / SceneAppsPage.test.tsx` 当前都已切到 base `SceneAppPlanResult / SceneAppDescriptor / SceneAppCatalog` - - `catalog.ts` 当前也已去掉旧 current 执行族命名,改成 `SceneAppEntryBinding["bindingFamily"]` 这一类 base current 索引访问 - - `presentation.ts` 当前本地私有类型名也已去掉 `Current` 前缀;因此 `SceneAppCurrentDescriptor / SceneAppCurrentPlanResult / SceneAppCurrentCatalog` 当前已基本退出默认测试工厂和业务实现语境,不再是仓库里最容易被复制的样板写法 - - 当前定向验证: - - `npm run typecheck` - - `npx eslint "src/lib/sceneapp/catalog.ts" "src/lib/sceneapp/launch.test.ts" "src/components/agent/chat/workspace/sceneAppLaunch.test.ts" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.test.tsx" "src/components/settings-v2/system/automation/index.test.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm exec vitest run "src/lib/sceneapp/catalog.test.ts" "src/lib/sceneapp/launch.test.ts" "src/components/agent/chat/workspace/sceneAppLaunch.test.ts" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.test.tsx" "src/components/settings-v2/system/automation/index.test.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `rg -n "SceneAppCurrent[A-Za-z]+" src --glob '!src/lib/sceneapp/types.ts' --glob '!src/lib/api/sceneapp.ts'` - - `npx eslint "src/lib/sceneapp/presentation.ts"` - - `npm exec vitest run "src/lib/sceneapp/presentation.test.ts"` - - 结果: - - `typecheck` 通过 - - `eslint` 通过 - - `6 files / 63 tests passed` - - `rg` 扫描确认:`src` 内除 `types.ts / api/sceneapp.ts` 边界外已无 `SceneAppCurrent*` 命中 - - `1 file / 3 tests passed` - -- 把 `sceneapp` 边界层与默认 mock 样板继续从 `SceneAppCurrent*` 过渡别名切回 base current 类型,避免 current 事实源只停留在业务层表面: - - 已更新: - - `src/lib/sceneapp/catalog.ts` - - `src/lib/sceneapp/launch.ts` - - `src/lib/sceneapp/launchBridge.ts` - - `src/lib/tauri-mock/core.ts` - - `src/lib/sceneapp/product.test.ts` - - `src/lib/sceneapp/presentation.test.ts` - - `docs/roadmap/limenextv2/sceneapp-current-boundary.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `catalog.ts` 当前已直接使用 base `SceneAppCatalog / SceneAppDescriptor / SceneAppEntryBinding / SceneAppLaunchRequirement / SceneAppCompositionProfile`,目录编译层不再默认依赖 `SceneAppCurrent*` 过渡别名 - - `launch.ts / launchBridge.ts` 当前也已切到 base `SceneAppPlanResult`,并通过 `SceneAppRuntimeAdapterPlan["adapterKind" | "runtimeAction"]` 取 current 执行语义,不再把 `SceneAppCurrentPlanResult` 当执行草稿层默认输入 - - `tauri-mock/core.ts` 当前默认 mock 样板也已改成 base `SceneAppCatalog / SceneAppDescriptor / SceneAppPlanResult / SceneAppRuntimeAdapterPlan` - - 因此 current 事实源已从“业务层可见类型”继续推进到“目录编译、执行桥、默认样板”这一圈边界;剩余 `SceneAppCurrent*` 正在退回测试工厂和少量 current-only 标量别名 - - 当前定向验证: - - `npm run typecheck` - - `npx eslint "src/lib/sceneapp/catalog.ts" "src/lib/sceneapp/launch.ts" "src/lib/sceneapp/launchBridge.ts" "src/lib/tauri-mock/core.ts" "src/lib/sceneapp/product.test.ts" "src/lib/sceneapp/presentation.test.ts"` - - `npm exec vitest run "src/lib/sceneapp/catalog.test.ts" "src/lib/sceneapp/launch.test.ts" "src/lib/sceneapp/product.test.ts" "src/lib/sceneapp/presentation.test.ts" "src/components/agent/chat/workspace/sceneAppLaunch.test.ts" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.test.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - 结果: - - `typecheck` 通过 - - `eslint` 通过 - - `7 files / 69 tests passed` - -- 把 `sceneapp` current 业务层继续从 `SceneAppCurrent*` 过渡别名切回 base current 类型,避免主链表面看起来仍像“两套主类型并存”: - - 已更新: - - `src/lib/sceneapp/presentation.ts` - - `src/lib/sceneapp/product.ts` - - `src/lib/sceneapp/launcher.ts` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/settings-v2/system/automation/useAutomationSceneAppRuntime.ts` - - `src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.ts` - - `eslint.config.js` - - `docs/roadmap/limenextv2/sceneapp-current-boundary.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `SceneAppDescriptor / SceneAppPlanResult / SceneAppCatalog` 当前已明确成为 current 业务层默认类型,主链业务文件不再需要通过 `SceneAppCurrent*` alias 自证“这是 current” - - `eslint.config.js` 当前也已把机械守卫改成禁止业务层继续 import `SceneAppCurrentDescriptor / SceneAppCurrentPlanResult / SceneAppCurrentCatalog` - - `presentation.ts` 当前仍保留 compat 展示 helper 的合法边界,因此 compat token 守卫继续显式豁免它;但它的主输入类型当前也已切到 base `SceneAppDescriptor` - - 因此 `sceneapp` 当前前台主链进一步收敛成:base `SceneApp*` 负责 current 业务语义,`SceneAppCurrent*` 只再作为过渡别名和边界说明存在 - - 当前定向验证: - - `npm run typecheck` - - `npx eslint "eslint.config.js" "src/lib/sceneapp/presentation.ts" "src/lib/sceneapp/product.ts" "src/lib/sceneapp/launcher.ts" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/settings-v2/system/automation/useAutomationSceneAppRuntime.ts" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.ts"` - - `printf 'import type { SceneAppCurrentDescriptor } from "@/lib/api/sceneapp";\\ntype _Smoke = SceneAppCurrentDescriptor;\\n' | npx eslint --stdin --stdin-filename "src/components/sceneapps/__sceneapp-current-alias-guard-smoke.ts"` - - `npm exec vitest run "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.test.tsx" "src/components/settings-v2/system/automation/index.test.tsx" "src/components/agent/chat/workspace/sceneAppLaunch.test.ts"` - - 结果: - - `typecheck` 通过 - - `eslint` 通过 - - `stdin current alias guard expected failure observed` - - `5 files / 74 tests passed` - -- 把 `sceneapp` 主类型本身也继续收回 current-only,避免 base type 在字段层继续把 compat 云执行值视作当前合法输出: - - 已更新: - - `src/lib/sceneapp/types.ts` - - `src/lib/api/sceneapp.ts` - - `docs/roadmap/limenextv2/sceneapp-current-boundary.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `SceneAppEntryBinding / SceneAppLaunchRequirement / SceneAppCompositionStepDescriptor / SceneAppRuntimeAdapterPlan / SceneAppExecutionPlan / SceneAppReadiness` 这组 base type 的关键字段当前都已切回 current-only - - `SceneAppCurrentEntryBinding / SceneAppCurrentLaunchRequirement / SceneAppCurrentCompositionProfile / SceneAppCurrentRuntimeAdapterPlan / SceneAppCurrentExecutionPlan / SceneAppCurrentPlanResult` 当前已退化为对 base current 类型的别名,不再额外承载一套更宽的隐藏语义 - - `SceneAppCompatExecutionPlanInput` 当前也已补齐 `executorKind / bindingFamily / stepPlan / adapterPlan` 的嵌套 compat 输入镜像,compat planner 输入不再偷偷复用 current 主对象字段 - - `src/lib/api/sceneapp.ts` 当前的 `cloud_session` 过滤 predicate 也已改成显式消费 `SceneAppCompatLaunchRequirementInput`,API 归一化边界只负责“接旧输入 -> 投影 current 输出”,不再把宽 base type 当旧目录原始合同 - - 因此 `sceneapp` 当前主对象事实源已经进一步收口成:base `SceneApp*` 默认就是 current;compat 旧词只允许停留在 `Compat*Input` 与归一化 helper - - 当前定向验证: - - `npm run typecheck` - - `npx eslint "src/lib/sceneapp/types.ts" "src/lib/api/sceneapp.ts"` - - `npm exec vitest run "src/lib/api/sceneapp.test.ts" "src/lib/sceneapp/catalog.test.ts" "src/lib/sceneapp/presentation.test.ts" "src/lib/sceneapp/product.test.ts"` - - 结果: - - `typecheck` 通过 - - `eslint` 通过 - - `4 files / 29 tests passed` - -- 把 `sceneapp API` 这一层继续收回 current-first 类型边界,避免 `@/lib/api/sceneapp` 的 helper 在类型层继续把 compat 执行族当成普通 current 输出: - - 已更新: - - `src/lib/sceneapp/types.ts` - - `src/lib/api/sceneapp.ts` - - `src/lib/sceneapp/catalog.ts` - - `src/lib/sceneapp/launchBridge.ts` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/settings-v2/system/automation/useAutomationSceneAppRuntime.ts` - - `src/lib/sceneapp/launcher.ts` - - `src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.ts` - - `src/lib/tauri-mock/core.ts` - - `src/lib/sceneapp/launch.test.ts` - - `src/lib/sceneapp/product.test.ts` - - `src/lib/sceneapp/presentation.ts` - - `src/lib/sceneapp/product.ts` - - `src/lib/sceneapp/launch.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `src/components/agent/chat/workspace/sceneAppLaunch.test.ts` - - `src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.test.tsx` - - `src/components/settings-v2/system/automation/index.test.tsx` - - `src/lib/sceneapp/types-runtime-context.ts` - - `eslint.config.js` - - 当前统一结论: - - `sceneapp/types.ts` 当前已补出 `SceneAppCurrentDescriptor / SceneAppCurrentCatalog / SceneAppCurrentPlanResult` 这一组 API 归一化后投影类型 - - `normalizeCompatSceneAppBindingFamily(...)` 当前已显式返回 current 执行族 - - `collectNormalizedSceneAppBindingFamilies(...)` 当前已只产出 current 执行族,不再把 `cloud_scene` 作为 API 正常输出类型继续向后传播 - - `normalizeCompatSceneAppRuntimeAction(...)` 当前已显式返回 current 运行动作 - - `listSceneAppCatalog / getSceneAppDescriptor / planSceneAppLaunch / saveSceneAppContextBaseline` 当前也已开始返回 current 投影类型 - - `catalog.ts` 当前也已显式切到 `SceneAppCurrentDescriptor / SceneAppCurrentCatalog` 输出,`compileSceneAppCatalogFromPackage / compileSceneAppCatalogFromSnapshot / readStoredSceneAppCatalog` 不再继续对外声明宽目录 - - `catalog.ts` 当前目录编译入口也已直接收窄到 `BaseSetupAllowedBindingFamily` compat 输入,不再让宽 `SceneAppBindingFamily` alias 继续参与 `Base Setup -> SceneApp` current 目录编译 - - `SceneApps` 主页面 runtime、automation runtime、launcher 与工作区 `SceneApp` 入口当前也已开始显式消费 current 投影类型,而不是继续用宽 union - - 本地缓存目录回退当前已直接消费 `readStoredSceneAppCatalog()` 的 current 输出,不再额外过 `normalizeSceneAppCatalogProjection(...)` - - `launchBridge.ts` 当前公开合同也已切到 `SceneAppCurrentPlanResult`,启动桥不再在签名层继续承认宽 `SceneAppPlanResult` - - `launch.ts` 当前也已切到 `SceneAppCurrentPlanResult` 输入,执行草稿层内部不再继续保留 compat `launch_cloud_scene / cloud_scene` 投影 helper - - `tauri mock` 的默认目录与 planning builder、以及主链 `sceneapp` 测试夹具当前也已开始显式切到 `SceneAppCurrent*` - - `automation/index.test.tsx` 当前也已补成显式 `SceneAppCurrentDescriptor / SceneAppCurrentPlanResult` 夹具,`viewerKind` 这类字段不再靠无类型 mock 漂移 - - compat `launch_cloud_scene / cloud_scene` 当前只再留给 API 归一化边界与显式 compat 用例,不再占据执行草稿层默认样板 - - `presentation.ts / product.ts` 这类纯前台投影层当前也已切到 `SceneAppCurrent*` - - `launch.ts` 当前也已变成 current-only,`execution summary` 直接消费 current planning 结果 - - `tauri-mock/core.ts` 当前默认 SceneApp mock 也已只接受 current 执行族,不再在默认样板里保留 compat `cloud_scene -> agent_turn` 正规化后门 - - `types-runtime-context.ts` 当前已确认在 `src/docs` 范围零引用,并折叠成对 `types.ts` 的转发文件,避免 dead 类型副本继续漂移 - - `eslint.config.js` 当前也已补上 `no-restricted-imports` 守卫,禁止新代码继续 import `types-runtime-context.ts` - - `presentation.test.ts` 当前也已切到 `SceneAppCurrentDescriptor`,仓库里已不再存在业务层直接 import 宽 `SceneAppDescriptor / SceneAppPlanResult / SceneAppCatalog` 的存量样本 - - `eslint.config.js` 当前也已补上 `no-restricted-syntax` 守卫,禁止业务层与测试夹具重新 import 这三类宽 SceneApp 类型 - - `eslint.config.js` 当前也已再补第二层守卫,禁止业务层与测试夹具重新 import 宽 `SceneAppBindingFamily / SceneAppRuntimeAction` - - `src/lib/api/sceneapp.ts` 当前也已不再直接 import 宽 `SceneAppBindingFamily / SceneAppRuntimeAction`,而是改成显式 `current + compat` 本地联合 - - `sceneapp/types.ts` 当前也已补出 `SceneAppCompatDescriptorInput / SceneAppCompatCatalogInput / SceneAppCompatExecutionPlanInput / SceneAppCompatPlanResultInput` 这组 raw compat 输入类型 - - `api/sceneapp.ts` 当前 `safeInvoke(...)` 泛型与归一化 helper 也已切到这组 raw compat 输入类型,不再继续把宽 `SceneAppDescriptor / SceneAppCatalog / SceneAppPlanResult` 当成 API 原始输入事实源 - - `eslint.config.js` 当前也已补 raw compat 输入守卫,禁止业务层与测试夹具重新 import 上述四类 compat input 类型 - - `eslint.config.js` 当前也已再补 compat token 字面量守卫,禁止 `sceneapp` 业务消费层重新出现 `cloud_managed / cloud_runtime / cloud_session / cloud_scene / launch_cloud_scene / cloudSessionReady / cloud_session_ready` - - 因此当前宽 `SceneAppDescriptor / SceneAppPlanResult / SceneAppCatalog / SceneAppBindingFamily / SceneAppRuntimeAction` 已从“只剩 API 边界消费”进一步收口到“只剩 compat re-export 与类型模型本身”;raw compat 输入类型当前也只剩 `types.ts` 与 `api/sceneapp.ts` 两处允许持有;compat token 字面量当前也只剩 `types.ts / catalog.ts / presentation.ts / api/sceneapp.ts` 这组显式边界文件允许持有 - - 这一步当前没有改运行时行为,只收紧了 API 归一化 helper、目录编译入口与输出合同的 current / compat 边界 - - 当前定向验证: - - `npx eslint "src/lib/sceneapp/types.ts" "src/lib/api/sceneapp.ts" "eslint.config.js"` - - `npm exec vitest run "src/lib/api/sceneapp.test.ts" "src/lib/sceneapp/catalog.test.ts"` - - `printf 'import type { SceneAppCompatDescriptorInput, SceneAppCompatCatalogInput, SceneAppCompatExecutionPlanInput, SceneAppCompatPlanResultInput } from "@/lib/sceneapp";\\ntype _A = SceneAppCompatDescriptorInput;\\ntype _B = SceneAppCompatCatalogInput;\\ntype _C = SceneAppCompatExecutionPlanInput;\\ntype _D = SceneAppCompatPlanResultInput;\\n' | npx eslint --stdin --stdin-filename "src/__sceneapp-compat-input-guard-smoke.ts"` - - `rg -n "SceneAppCompatDescriptorInput|SceneAppCompatCatalogInput|SceneAppCompatExecutionPlanInput|SceneAppCompatPlanResultInput" "src"` - - `npx eslint "eslint.config.js" "src/lib/sceneapp/catalog.ts" "src/lib/sceneapp/navigation.ts" "src/components/sceneapps/useSceneAppsPageRuntime.ts"` - - `printf 'const _leaked = "cloud_scene";\\nconst _ready = { cloudSessionReady: true };\\n' | npx eslint --stdin --stdin-filename "src/components/sceneapps/__sceneapp-compat-token-guard-smoke.ts"` - - `printf 'const _legacy = "cloud_scene";\\nconst _ready = { cloudSessionReady: true };\\n' | npx eslint --stdin --stdin-filename "src/lib/sceneapp/catalog.ts"` - - `rg -n "import type .*SceneAppBindingFamily|SceneAppBindingFamily,|import type .*SceneAppRuntimeAction|SceneAppRuntimeAction," "src"` - - `npx eslint "eslint.config.js" "src/lib/api/sceneapp.ts" "src/lib/sceneapp/catalog.ts"` - - `printf 'import type { SceneAppBindingFamily, SceneAppRuntimeAction } from "@/lib/sceneapp";\\ntype _Binding = SceneAppBindingFamily;\\ntype _Action = SceneAppRuntimeAction;\\n' | npx eslint --stdin --stdin-filename "src/__sceneapp-wide-execution-type-guard-smoke.ts"` - - `npm run governance:legacy-report` - - `npm run typecheck` - - `npx eslint "src/lib/api/sceneapp.ts" "src/lib/sceneapp/types.ts"` - - `npm exec vitest run "src/lib/api/sceneapp.test.ts" "src/lib/sceneapp/presentation.test.ts" "src/lib/sceneapp/launch.test.ts"` - - `npx eslint "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/settings-v2/system/automation/useAutomationSceneAppRuntime.ts" "src/lib/sceneapp/launcher.ts" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.ts"` - - `npm exec vitest run "src/lib/api/sceneapp.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/agent/chat/workspace/sceneAppLaunch.test.ts" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.test.tsx"` - - `npm run typecheck` - - `npm exec vitest run "src/lib/api/sceneapp.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.test.tsx"` - - `npx eslint "src/lib/sceneapp/catalog.ts" "src/lib/sceneapp/launchBridge.ts" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.ts"` - - `npm exec vitest run "src/lib/sceneapp/catalog.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.test.tsx" "src/components/agent/chat/workspace/sceneAppLaunch.test.ts"` - - `npx eslint "src/lib/sceneapp/launch.ts" "src/lib/sceneapp/launch.test.ts" "src/lib/sceneapp/launchBridge.ts"` - - `npm exec vitest run "src/lib/sceneapp/launch.test.ts" "src/components/agent/chat/workspace/sceneAppLaunch.test.ts"` - - `npx eslint "src/components/settings-v2/system/automation/index.test.tsx" "src/lib/sceneapp/launch.ts" "src/lib/sceneapp/launch.test.ts"` - - `npm exec vitest run "src/components/settings-v2/system/automation/index.test.tsx" "src/lib/sceneapp/launch.test.ts" "src/components/agent/chat/workspace/sceneAppLaunch.test.ts"` - - `npx eslint "src/lib/sceneapp/types-runtime-context.ts" "src/lib/sceneapp/launch.ts" "src/components/settings-v2/system/automation/index.test.tsx"` - - `npx eslint "src/lib/tauri-mock/core.ts" "src/lib/sceneapp/types-runtime-context.ts"` - - `printf 'import \"@/lib/sceneapp/types-runtime-context\";\\n' | npx eslint --stdin --stdin-filename "src/__sceneapp-dead-import-smoke.ts"` - - `npx eslint "src/lib/sceneapp/presentation.test.ts" "src/lib/sceneapp/types-runtime-context.ts" "eslint.config.js"` - - `printf 'import type { SceneAppDescriptor } from "@/lib/sceneapp";\\ntype _Smoke = SceneAppDescriptor;\\n' | npx eslint --stdin --stdin-filename "src/__sceneapp-wide-type-guard-smoke.ts"` - - `npm exec vitest run "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.test.tsx" "src/components/agent/chat/workspace/sceneAppLaunch.test.ts"` - - `npx eslint "src/lib/tauri-mock/core.ts" "src/lib/sceneapp/launch.test.ts" "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/agent/chat/workspace/sceneAppLaunch.test.ts" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.test.tsx"` - - `npm exec vitest run "src/lib/sceneapp/launch.test.ts" "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/agent/chat/workspace/sceneAppLaunch.test.ts" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.test.tsx"` - - `npx eslint "src/lib/sceneapp/presentation.ts" "src/lib/sceneapp/product.ts" "src/lib/sceneapp/launch.ts"` - - `npm exec vitest run "src/lib/sceneapp/presentation.test.ts" "src/lib/sceneapp/product.test.ts" "src/lib/sceneapp/launch.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - 结果: - - `eslint` 通过 - - `3 files / 13 tests passed` - - `4 files / 46 tests passed` - - `typecheck` 通过 - - `3 files / 39 tests passed` - - `3 files / 37 tests passed` - - `4 files / 44 tests passed` - - `2 files / 8 tests passed` - - `2 files / 11 tests passed` - - `3 files / 26 tests passed` - - `3 files / 41 tests passed` - - `stdin import guard expected failure observed` - - `stdin wide type guard expected failure observed` - - `stdin wide execution type guard expected failure observed` - - `stdin compat input guard expected failure observed` - - `rg` 扫描确认:raw compat 输入类型当前只命中 `types.ts` 与 `api/sceneapp.ts` - - `stdin compat token guard expected failure observed` - - `catalog.ts` allowlist smoke passed` - - `rg` 扫描确认:实现层已无宽 `SceneAppBindingFamily / SceneAppRuntimeAction` import,剩余命中只在 compat re-export surface - - `governance:legacy-report` 通过,摘要为 `边界违规 0 / 分类漂移候选 0` - - `typecheck` 通过 - - `5 files / 64 tests passed` - - `4 files / 57 tests passed` - -- 把 `sceneapp` 的 current / compat 边界正式补成 `LimeNext V2` 的 current 事实源,避免后续继续按旧云执行命名摇摆: - - 已新增: - - `docs/roadmap/limenextv2/sceneapp-current-boundary.md` - - 已更新: - - `docs/roadmap/limenextv2/README.md` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-v2-fs-blocker-2026-04-22.md` - - 当前统一结论: - - `cloud_managed / cloud_runtime / cloud_session / cloud_scene / launch_cloud_scene` 只允许留在 compat 输入、归一化、显式 compat helper 或 compat 测试里 - - `SceneAppDescriptor.sceneappType` 的 current 语义固定只认 `local_instant / local_durable / browser_grounded / hybrid` - -- 在文件系统 `EPERM` 尚未恢复的前提下,确认并打通了一个可操作旁路,避免主线继续停在“只能写文档、不能改代码”的假进展: - - 当前现象: - - shell / `apply_patch` 仍无法直接读取仓库内受阻旧文件 - - 但 Finder 可以把受阻文件复制到 `/private/tmp`,也可以把 `/private/tmp` 里的同名文件覆盖回仓库 - - 当前工作流: - - `Finder duplicate -> /private/tmp` - - 在 `/private/tmp` 使用 `apply_patch` - - `Finder duplicate -> repo` 覆盖回原文件 - - 这条旁路当前只适合少量关键文件,不适合大范围批量改动 - -- 用这条旁路继续完成了 `sceneapp presentation` 这一刀的 current-first 收口: - - 已更新: - - `src/lib/sceneapp/types.ts` - - `src/lib/sceneapp/catalog.ts` - - `src/lib/sceneapp/launch.ts` - - `src/lib/sceneapp/presentation.ts` - - `src/lib/sceneapp/presentation.test.ts` - - 当前统一结论: - - `SceneAppBindingFamily` 当前已拆成 current / compat 两层,`cloud_scene` 不再只藏在共享别名里 - - `catalog / launch` 里的 compat 归一化函数当前也已显式返回 current 执行族 - - `SceneAppLaunchRequirementKind` 当前已拆成 current / compat 两层,`cloud_session` 不再和 current 启动前置混写 - - `SceneAppRuntimeContext` 当前也已只保留 current 字段;`cloudSessionReady / cloud_session_ready` 当前只继续保留在 compat input 类型与兼容读取 helper 里 - - `getSceneAppPresentationCopy(...)` 与 `inferFallbackCopy(...)` 当前已显式收窄到 current descriptor 视角 - - compat `cloud_managed / cloud_runtime` 当前只继续保留在显式 label helper 与 compat 测试里 - - `presentation.test.ts` 当前已拆开“compat helper 断言”和“current descriptor copy 断言”,不再允许用 `cloud_managed` 伪装成 current `SceneAppDescriptor` - - 当前定向验证: - - `npx --yes vitest@3.2.4 run /private/tmp/lime-sceneapp-edit/presentation.test.ts` - - 结果:`3 tests passed` - - 当前扩展旁路验证: - - 已通过: - - `npx --yes vitest@3.2.4 run "/private/tmp/sceneapp-scan/runEntryNavigation.test.ts" "/private/tmp/sceneapp-scan/launch.test.ts" "/private/tmp/sceneapp-scan/product.test.ts" "/private/tmp/sceneapp-scan/presentation.test.ts" "/private/tmp/sceneapp-scan/navigation.test.ts"` - - 结果:`5 files / 31 tests passed` - - 已确认但不记为代码回归: - - 直接把 `/private/tmp/sceneapp-scan/*.test.ts` 全跑时,`storage / entry` 会因缺少 `window/jsdom` 失败,`automation / executionPromptActions / catalog` 会因缺少 repo alias `@/...` 失败 - - 这些失败当前按“临时副本环境不完整”理解,不按本轮 `presentation` 收口引入的新断链处理 - -### 下一刀 - -- 继续把 `@/lib/api/sceneapp` 的“归一化后输出”类型再往 current 投影收窄: - - 当前 output alias、目录编译层、本地缓存回读、启动桥、执行草稿层、核心消费面、tauri mock 默认样板、主链测试夹具和纯前台投影层都已切过去,下一步优先继续清理剩余旁路 helper 与非主链工厂里的宽 union - - 目标是让 current 页面和 workspace 消费面在编译期也尽量不再碰到 compat union -- 继续借 Finder 旁路,把 repo 内正式校验补回来,优先顺序固定为: - - `npx eslint "src/lib/sceneapp/types.ts" "src/lib/sceneapp/presentation.ts" "src/lib/sceneapp/presentation.test.ts"` - - `npm exec vitest run "src/lib/sceneapp/presentation.test.ts" "src/lib/sceneapp/product.test.ts" "src/lib/api/sceneapp.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm run governance:legacy-report` - - `npm run typecheck` -- 如果 repo 内正式校验仍被 cwd / TCC 阻塞,就继续把更多定向校验切到 `/private/tmp` 副本上跑,直到 current 边界彻底收完。 - -## 2026-04-21 - -### 已完成 - -- 把 Rust `sceneapp` 内部还残留的旧云执行类型名继续往 compat alias 收口,避免 `CloudManaged / CloudScene / CloudSession / cloud_session_ready` 继续污染 current 内部建模语言: - - 已更新: - - `src-tauri/src/sceneapp/dto.rs` - - `src-tauri/src/sceneapp/adapters.rs` - - `src-tauri/src/sceneapp/runtime.rs` - - `src-tauri/src/sceneapp/governance.rs` - - `src-tauri/src/sceneapp/context/compiler.rs` - - 当前统一结论: - - Rust 内部枚举当前已改成 `DirectorySyncedCompat / ServiceSceneCompat / DirectorySessionCompat` - - `SceneAppRuntimeContext` 内部字段当前已改成 `directory_session_ready_compat` - - 对外 serde 合同当前仍继续兼容旧值与旧字段名:`cloud_managed / cloud_scene / cloud_session / cloudSessionReady` - - 因此 current 内部语义继续向“目录同步 compat / service-scene compat / directory session compat”收口,但不会打断前端和历史数据读取 - - 当前计划中的最小验证: - - `cargo fmt --manifest-path "src-tauri/Cargo.toml" --all` - - `cargo test --manifest-path "src-tauri/Cargo.toml" should_build_service_scene_adapter_plan_for_hybrid_sceneapp` - - `cargo test --manifest-path "src-tauri/Cargo.toml" build_sceneapp_scorecard_from_runs_should_keep_stable_scene` - - `cargo test --manifest-path "src-tauri/Cargo.toml" should_promote_selected_memory_entries_into_reference_items` - - 本轮验证备注: - - 已完成 `rustfmt --edition 2021 "src-tauri/src/sceneapp/dto.rs" "src-tauri/src/sceneapp/adapters.rs" "src-tauri/src/sceneapp/runtime.rs" "src-tauri/src/sceneapp/governance.rs" "src-tauri/src/sceneapp/context/compiler.rs"` - - 已通过: - - `cargo test --manifest-path "src-tauri/Cargo.toml" --lib should_build_service_scene_adapter_plan_for_hybrid_sceneapp` - - `cargo test --manifest-path "src-tauri/Cargo.toml" --lib build_sceneapp_scorecard_from_runs_should_keep_stable_scene` - - `cargo test --manifest-path "src-tauri/Cargo.toml" --lib should_promote_selected_memory_entries_into_reference_items` - - 以上测试执行期间曾短暂等待 Cargo `package cache / artifact directory` 锁,但最终都已在默认 `src-tauri/target` 下完成,不再记为未验证 - -- 把 Rust `service_scene_launch` 提取器的 current 默认值收回 `local_service_skill`,避免前端 metadata 已改成本地执行,但后端解析层仍把缺省 `kind` 视作 `cloud_scene`: - - 已更新: - - `src-tauri/src/commands/aster_agent_cmd/service_skill_launch.rs` - - `src-tauri/src/commands/aster_agent_cmd/tool_runtime/service_skill_tools.rs` - - `src-tauri/src/commands/aster_agent_cmd/tests.rs` - - 当前统一结论: - - `extract_service_scene_launch_context(...)` 当前默认按 `local_service_skill` 解析 - - Rust 侧当前同时接受 `local_service_skill / cloud_scene`,其中前者是 current,后者只再作为 compat alias - - `aster_agent_cmd` 的 current 定向测试样例也已切到 `local_service_skill`,避免测试事实源继续把 `cloud_scene` 当默认值 - - 当前计划中的最小验证: - - `rustfmt --edition 2021 "src-tauri/src/commands/aster_agent_cmd/service_skill_launch.rs" "src-tauri/src/commands/aster_agent_cmd/tool_runtime/service_skill_tools.rs" "src-tauri/src/commands/aster_agent_cmd/tests.rs"` - - `cargo test --manifest-path "src-tauri/Cargo.toml" service_scene_launch` - - `cargo test --manifest-path "src-tauri/Cargo.toml" should_extract_launch_context_from_environment_payload -- --exact` - - 本轮验证备注: - - 已完成 `rustfmt --edition 2021` - - 上述两条 Rust 定向测试会触发 `aster` crate 长时间重编;本轮已发起但未在可接受窗口内拿到最终结果,已主动中止,不记为已通过 - -- 把 `quality-workflow` 中仍残留的 `OEM run/timeline` 旧叙事改回 current 本地执行事实源,避免后续按质量清单做回归时又把 `@配音 / /scene-key` 理解成云执行链: - - 已更新: - - `docs/aiprompts/quality-workflow.md` - - 当前统一结论: - - `@配音` 的质量清单当前明确收口为 `service_scene_launch -> 本地 service-scene 直驱执行 -> 本地 ServiceSkill / tool timeline` - - `/scene-key` 的质量清单当前也明确收口为 `service_scene_launch -> 本地 service-scene 直驱执行 -> tool timeline` 主链,不再允许用 `OEM run/timeline` 或“Rust 侧云执行分支”描述 current 事实 - - `lime_run_service_skill` 当前已只作为 compat 护栏保留,不再允许在质量清单里被写成 current 执行桥 - - `service_scene_launch runtime` 的补充校验当前只再围绕本地 service-scene 执行桥与 compat 结果回流,不再暗示云端 run/poll - -- 把 `automation / service skill` 的 current 消费面继续收回“客户端执行 + 兼容目录标记”语义,避免设置页任务列表、详情弹窗和运行摘要仍把 `cloud_required` 展示成无差别的当前执行位置: - - 已更新: - - `src/components/settings-v2/system/automation/serviceSkillContext.ts` - - `src/components/settings-v2/system/automation/serviceSkillContext.test.ts` - - `src/components/settings-v2/system/automation/index.tsx` - - `src/components/settings-v2/system/automation/index.test.tsx` - - `src/components/settings-v2/system/automation/AutomationJobDetailsDialog.tsx` - - 当前统一结论: - - `cloud_required` 当前在 automation 上下文里会继续显示为 `客户端执行`,但会额外标记为 `旧目录兼容` - - 任务列表、任务详情和运行摘要当前都会把 compat 信息显式展示成“沿用旧目录兼容标记,实际仍在客户端执行”,不再让旧目录字段伪装成 current 执行面 - - `run metadata = client_default`、`job payload = cloud_required` 这类混合输入当前也会继续保留 compat 标记,避免运行层正规化后把旧目录来源洗掉 - - 当前计划中的最小验证: - - `npx eslint "src/components/settings-v2/system/automation/serviceSkillContext.ts" "src/components/settings-v2/system/automation/serviceSkillContext.test.ts" "src/components/settings-v2/system/automation/index.tsx" "src/components/settings-v2/system/automation/index.test.tsx" "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.tsx"` - - `npm exec vitest run "src/components/settings-v2/system/automation/serviceSkillContext.test.ts" "src/components/settings-v2/system/automation/index.test.tsx"` - -- 把 `service skill` 的旧云特例执行暗示继续压回“目录兼容标记”,避免 current 文档已经切到“目录云同步、本地执行”,但入口投影和工作区测试仍在暗示 `cloud_required = 云端执行`: - - 已更新: - - `src/lib/api/serviceSkills.ts` - - `src/components/agent/chat/service-skills/promptComposer.ts` - - `src/components/agent/chat/workspace/useWorkspaceServiceSkillEntryActions.test.tsx` - - 当前统一结论: - - `cloud_required` 当前只再表示旧目录兼容标记,不再表示“云端完成后回流” - - `ServiceSkill` bundle 推导出的 `output destination / compatibility` 当前都已收口到客户端执行语义 - - `workspace service skill entry` 的 current 测试也已同步改成“legacy 标记 -> 仍走本地执行主链”,并清掉未被当前主链使用的旧 `serviceSkillRuns` mock - - 当前计划中的最小验证: - - `npx eslint "src/lib/api/serviceSkills.ts" "src/components/agent/chat/service-skills/promptComposer.ts" "src/components/agent/chat/workspace/useWorkspaceServiceSkillEntryActions.test.tsx"` - - `npm exec vitest run "src/lib/api/serviceSkills.test.ts" "src/components/agent/chat/workspace/useWorkspaceServiceSkillEntryActions.test.tsx"` - -- 把 `Base Setup -> ServiceSkillCatalog` 的 compat 编译投影也收回 current 本地执行语义,避免包里还沿用 `cloud_scene / cloud_required` 时,前台 catalog item 又重新把它当成当前执行真相: - - 已更新: - - `src/lib/base-setup/compat/serviceSkillCatalogProjection.ts` - - `src/lib/api/skillCatalog.test.ts` - - 当前统一结论: - - `bindingFamily = cloud_scene` 当前在编译成 `ServiceSkillItem` 时会被正规化成 `defaultExecutorBinding = agent_turn` - - `executionLocation = cloud_required` 当前在编译投影里也会被正规化成 `client_default` - - 因此前台消费到的 `ServiceSkillCatalog / SkillCatalogItem` 当前不再把旧包标记继续投射成 current 执行边界;旧标记当前只允许停留在 legacy Base Setup / 远端 compat 输入层 - - 当前计划中的最小验证: - - `npx eslint "src/lib/base-setup/compat/serviceSkillCatalogProjection.ts" "src/lib/api/skillCatalog.test.ts"` - - `npm exec vitest run "src/lib/base-setup/seededServiceSkillPackage.test.ts" "src/lib/api/skillCatalog.test.ts" "src/lib/base-setup/compat/commandCatalogProjection.test.ts"` - -- 把 `Base Setup -> command/scene catalog` 的 compat execution kind 也往 current 本地语义收回,避免目录项明明已经只负责本地路由提示,却还继续对外暴露 `cloud_scene` 作为 current 执行真相: - - 已更新: - - `src/lib/base-setup/compat/commandCatalogProjection.ts` - - `src/lib/base-setup/compat/sceneCatalogProjection.ts` - - `src/lib/base-setup/compat/commandCatalogProjection.test.ts` - - `src/lib/api/skillCatalog.test.ts` - - 当前统一结论: - - `bindingFamily = cloud_scene` 当前在编译成 `command/scene` projection 时会被正规化成 `executionKind = agent_turn` - - `scene_detail` 这类 viewer/render contract 当前保持不变;只收口 current 执行语义,不改结果展示合同 - - 因此前台目录里的 command/scene 当前不再把旧 `cloud_scene` 继续显影成当前执行面;它当前只再是 legacy Base Setup / compat projection 的输入信号 - - 当前计划中的最小验证: - - `npx eslint "src/lib/base-setup/compat/commandCatalogProjection.ts" "src/lib/base-setup/compat/sceneCatalogProjection.ts" "src/lib/base-setup/compat/commandCatalogProjection.test.ts" "src/lib/api/skillCatalog.test.ts"` - - `npm exec vitest run "src/lib/base-setup/compat/commandCatalogProjection.test.ts" "src/lib/base-setup/seededCommandPackage.test.ts" "src/lib/api/skillCatalog.test.ts"` - -- 把 current seeded package 里还在主动产出的 `cloud_scene / cloud-scene-instant` dead compat surface 直接删掉,避免目录编译已经正规化成本地执行,但源包本身还继续给旧云语义续命: - - 已更新: - - `src/lib/base-setup/seededCommandPackage.ts` - - `src/lib/base-setup/seededServiceSkillPackage.ts` - - `src/lib/base-setup/seededCommandPackage.test.ts` - - `src/lib/base-setup/seededServiceSkillPackage.test.ts` - - 当前统一结论: - - `seededCommandPackage` 当前不再保留 `cloud-scene-instant` binding profile,也不再声明 `cloud_scene` kernel capability - - `seededServiceSkillPackage` 当前也不再保留 `cloud-scene-instant` binding profile 或 `cloud_scene` capability;`cloud-video-dubbing` 仅保留历史 skill id,不再携带云执行 binding - - 因此 current Base Setup 事实源当前已不再主动产出 `cloud_scene` 执行面;剩余旧命名仅留在 compat projection、sceneapp 规划与历史数据锚点 - - 当前计划中的最小验证: - - `npx eslint "src/lib/base-setup/seededCommandPackage.ts" "src/lib/base-setup/seededServiceSkillPackage.ts" "src/lib/base-setup/seededCommandPackage.test.ts" "src/lib/base-setup/seededServiceSkillPackage.test.ts"` - - `npm exec vitest run "src/lib/base-setup/seededCommandPackage.test.ts" "src/lib/base-setup/seededServiceSkillPackage.test.ts"` - - `npm run typecheck` - -- 给 `cloud_required / cloud_scene` 的类型定义补上 legacy compat 护栏注释,避免后续实现再次把“仍保留 union 分支”误读成“仍允许 current 云执行”: - - 已更新: - - `src/lib/base-setup/types.ts` - - `src/lib/api/serviceSkills.ts` - - `src/lib/api/skillCatalog.ts` - - 当前统一结论: - - `cloud_required` 当前在类型层被明确标注为旧目录兼容标记 - - `cloud_scene` 当前在 Base Setup / ServiceSkill / SkillCatalog 三处类型层都被明确标注为 legacy compat input,而不是 current 执行面 - - 当前计划中的最小验证: - - `npx eslint "src/lib/base-setup/types.ts" "src/lib/api/serviceSkills.ts" "src/lib/api/skillCatalog.ts"` - - `npm run typecheck` - -- 把 `SkillCatalog` 的 raw compat 输入也收回 current 本地执行语义,避免远端缓存或旧目录把 `cloud_scene` 直接写进前台目录对象后,又被 UI 当成当前执行面: - - 已更新: - - `src/lib/api/skillCatalog.ts` - - `src/lib/api/skillCatalog.test.ts` - - 当前统一结论: - - raw `skillCatalog.items[*].execution.kind = cloud_scene` 当前会在解析时正规化成 `agent_turn` - - raw `command.binding.executionKind = cloud_scene` 与 `scene.executionKind = cloud_scene` 当前也会一并正规化成 `agent_turn` - - 旧目录若仍依赖 `defaultExecutorBinding = cloud_scene` 或 `executionLocation = cloud_required` 自动生成 scene entry,当前仍可保留 auto scene 行为,但前台对象不会再显影 `cloud_scene` - - 因此 `SkillCatalog` 当前对象、缓存落盘与 UI 消费层继续统一回到本地执行语义;`cloud_scene` 只再允许停留在 compat 输入层 - - 当前计划中的最小验证: - - `npx eslint "src/lib/api/skillCatalog.ts" "src/lib/api/skillCatalog.test.ts"` - - `npm exec vitest run "src/lib/api/skillCatalog.test.ts"` - - `npm run typecheck` - -- 把 `ServiceSkill.skillBundle.metadata` 的 compat 泄漏也收回 current 本地语义,避免展示文案已经纠偏,但自动补齐的 bundle metadata 仍把 `cloud_required / cloud_scene` 写回当前前台对象: - - 已更新: - - `src/lib/api/serviceSkills.ts` - - `src/lib/api/serviceSkills.test.ts` - - 当前统一结论: - - 旧版 compat 服务技能若缺少 `skillBundle`,当前自动派生的 `Lime_execution_location` 会正规化为 `client_default` - - 同一条链路下的 `Lime_executor_binding` 当前也会正规化为 `agent_turn` - - `ServiceSkillItem` 原始 compat 字段仍可保留用于目录兼容,但当前 bundle metadata 不会再把它们显影成当前执行真相 - - 当前计划中的最小验证: - - `npx eslint "src/lib/api/serviceSkills.ts" "src/lib/api/serviceSkills.test.ts"` - - `npm exec vitest run "src/lib/api/serviceSkills.test.ts"` - - `npm run typecheck` - -- 把 `sceneapp/catalog` 的目录描述对象也继续去云执行化,避免 current 目录页虽然已经只谈“做法 / 本地执行”,但 `SceneAppDescriptor` 仍向前台显影 `cloud_scene / cloud_session / cloud_runtime`: - - 已更新: - - `src/lib/sceneapp/catalog.ts` - - `src/lib/sceneapp/catalog.test.ts` - - 当前统一结论: - - compat 输入里的 `bindingFamily = cloud_scene` 当前在 `SceneAppDescriptor.entryBindings / compositionProfile.steps` 中会正规化成 `agent_turn` - - compat 输入里的 `capabilityRefs = [cloud_scene]` 当前也会在目录描述对象里正规化成 `agent_turn` - - `launchRequirements` 当前不再因为 `cloud_scene / cloud_required` 自动长出 `cloud_session` - - `infraProfile` 当前也不再继续显影 `cloud_runtime` - - 单一旧 `cloud_scene` SceneApp 当前会在目录层被理解为 `local_instant`;混合编排场景则继续保留 `hybrid`,但不再把 compat 云绑定显影成当前执行真相 - - 当前计划中的最小验证: - - `npx eslint "src/lib/sceneapp/catalog.ts" "src/lib/sceneapp/catalog.test.ts"` - - `npm exec vitest run "src/lib/sceneapp/catalog.test.ts"` - - `npm run typecheck` - -- 把 `sceneapp presentation / product` 的 compat 展示词也收回 current 口径,避免目录对象已经正规化,但详情页和卡片摘要仍把 `cloud_scene / cloud_managed / cloud_runtime` 讲成当前产品语义: - - 已更新: - - `src/lib/sceneapp/presentation.ts` - - `src/lib/sceneapp/presentation.test.ts` - - `src/lib/sceneapp/product.ts` - - `src/lib/sceneapp/product.test.ts` - - 当前统一结论: - - compat `cloud_scene` 当前在展示层不再显示为“场景技能”,统一收成 `Agent 工作区` - - compat `cloud_runtime` 当前在基础设施摘要里不再显示为“目录控制面”,统一收成 `目录同步` - - compat `cloud_managed` 当前在类型标签与 fallback copy 里不再显示为“目录托管”,统一收成 `目录同步` - - 因此即使后续还有 compat descriptor 漏进展示层,前台也不会再继续讲“云执行/托管”叙事 - - 当前计划中的最小验证: - - `npx eslint "src/lib/sceneapp/presentation.ts" "src/lib/sceneapp/presentation.test.ts" "src/lib/sceneapp/product.ts" "src/lib/sceneapp/product.test.ts"` - - `npm exec vitest run "src/lib/sceneapp/presentation.test.ts" "src/lib/sceneapp/product.test.ts"` - - `npm run typecheck` - -- 把 `sceneapp launch` 的 current 启动草稿也继续收回本地执行主链,避免 compat `launch_cloud_scene` 还通过启动文案、notes 和 draft 适配器继续向工作区泄露旧“场景技能”语义: - - 已更新: - - `src/lib/sceneapp/launch.ts` - - `src/lib/sceneapp/launch.test.ts` - - `src/lib/tauri-mock/core.ts` - - 当前统一结论: - - `launch_cloud_scene` 当前仍保留为 compat runtime action 名,不直接删协议 - - 但 `workspace execution draft.adapterKind` 当前已正规化成 `agent_turn` - - `launch` 输出的 notes 当前会把“场景技能主链 / 场景技能入口”统一收成 `Agent 工作区主链 / Agent 工作区入口` - - `launch_cloud_scene` 在无显式用户输入时的 current prompt 也已改成“执行做法 / 在 Agent 工作区推进”,不再显影旧云场景语气 - - mock planner 与注入工具说明同步改成 current 口径,避免 dev/mock 场景继续把旧词带回前台 - - 当前计划中的最小验证: - - `npx eslint "src/lib/sceneapp/launch.ts" "src/lib/sceneapp/launch.test.ts" "src/lib/tauri-mock/core.ts"` - - `npm exec vitest run "src/lib/sceneapp/launch.test.ts" "src/components/agent/chat/workspace/sceneAppLaunch.test.ts" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.test.tsx"` - - `npm run typecheck` - -- 把 `sceneapp run detail -> entry action` 的 current 文案也收回 `生成` 主执行面,避免结果页仍把 compat `open_service_scene_session` 讲成“场景会话 / 场景上下文”: - - 已更新: - - `src/lib/sceneapp/product.ts` - - `src/lib/sceneapp/product.test.ts` - - `src/lib/sceneapp/runEntryNavigation.ts` - - `src/lib/sceneapp/runEntryNavigation.test.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - 当前统一结论: - - compat action kind `open_service_scene_session` 当前继续保留为内部协议,不直接删名 - - 但 run detail entry action 的用户可见标签当前已收成 `回到生成会话 / 恢复生成上下文` - - 结果页跳转到 Agent 页时的 banner 文案也同步改成 `恢复生成会话 / 恢复生成上下文` - - 因此 current 结果视图不再继续把 `sceneapp` 的恢复动作讲成另一套“场景会话”产品面 - - 当前计划中的最小验证: - - `npx eslint "src/lib/sceneapp/product.ts" "src/lib/sceneapp/product.test.ts" "src/lib/sceneapp/runEntryNavigation.ts" "src/lib/sceneapp/runEntryNavigation.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm exec vitest run "src/lib/sceneapp/product.test.ts" "src/lib/sceneapp/runEntryNavigation.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm run typecheck` - -- 把 `sceneapp API` 的 raw compat planner 输出也收回 current 对象语义,避免前面 catalog / launch / product 都已经正规化,但 `safeInvoke(sceneapp_*)` 仍直接把 `cloud_scene / launch_cloud_scene / cloud_runtime` 透给前端: - - 已更新: - - `src/lib/api/sceneapp.ts` - - `src/lib/api/sceneapp.test.ts` - - 当前统一结论: - - `listSceneAppCatalog` / `getSceneAppDescriptor` 当前会先正规化 descriptor: - - `capabilityRefs.cloud_scene -> agent_turn` - - `entryBindings.bindingFamily.cloud_scene -> agent_turn` - - `compositionProfile.steps.bindingFamily.cloud_scene -> agent_turn` - - `infraProfile.cloud_runtime` 不再继续显影 - - `launchRequirements.cloud_session` 不再继续显影 - - `planSceneAppLaunch` / `saveSceneAppContextBaseline` 当前会先正规化 `SceneAppPlanResult.plan`: - - `executorKind.cloud_scene -> agent_turn` - - `bindingFamily.cloud_scene -> agent_turn` - - `adapterPlan.adapterKind.cloud_scene -> agent_turn` - - `adapterPlan.runtimeAction.launch_cloud_scene -> open_service_scene_session` - - `SceneAppPlanResult` 当前还会继续正规化 compat planning 噪音: - - `readiness.unmetRequirements.cloud_session -> 丢弃` - - `readiness.ready` 会按过滤后的 unmet requirements 重新计算 - - `contextOverlay.compilerPlan.toolRefs.cloud_scene -> agent_turn` - - `contextOverlay.compilerPlan.toolRefs.cloud_session -> 丢弃` - - `contextOverlay.snapshot.toolRefs.cloud_scene -> agent_turn` - - `contextOverlay.snapshot.toolRefs.cloud_session -> 丢弃` - - `descriptor.sceneappType.cloud_managed -> 按绑定族/infra 信号正规化为 current 类型` - - 因此 current API 对象层现在也和 `skillCatalog / serviceSkills / sceneapp catalog / launch draft` 保持同一套本地执行语义 - - 当前计划中的最小验证: - - `npx eslint "src/lib/api/sceneapp.ts" "src/lib/api/sceneapp.test.ts"` - - `npm exec vitest run "src/lib/api/sceneapp.test.ts" "src/lib/sceneapp/launch.test.ts"` - - `npm run typecheck` - -- 把 `sceneapp` 深层 current 测试夹具里的旧云基础设施默认值继续收掉,避免测试事实源还在把 `cloud_runtime` 当常规目录字段: - - 已更新: - - `src/lib/sceneapp/product.test.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - 当前统一结论: - - `product` 与 `SceneAppsPage` 的默认 SceneApp descriptor/catalog fixture 当前只保留 current `infraProfile` - - `cloud_runtime` 现在只再留给显式 compat 用例,不再作为 current 基线样板的一部分 - - 因此后续围绕 sceneapp 读模型、目录页和结果页继续补测试时,不会再被旧云基础设施命名反向污染默认事实源 - - 当前计划中的最小验证: - - `npx eslint "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm exec vitest run "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - -- 给 `sceneapp` 的剩余旧云 runtime 类型补上 current/compat 分层护栏,避免实现面已经收回本地执行,但类型层仍把 `cloud_session / launch_cloud_scene` 看起来像 current 分支: - - 已更新: - - `src/lib/sceneapp/types.ts` - - 当前统一结论: - - `SceneAppLaunchRequirementKind.cloud_session` 当前明确标注为 `legacy compat only` - - `SceneAppRuntimeContext` 当前内部字段已补成 `directorySessionReadyCompat` - - `SceneAppRuntimeContext.cloudSessionReady` 当前只再保留为 compat 输入 alias,不再作为 current 内部命名 - - `SceneAppRuntimeAction` 当前拆成: - - `SceneAppCurrentRuntimeAction` - - `SceneAppCompatRuntimeAction(launch_cloud_scene)` - - `sceneapp API` 当前会在 invoke 前把 `directorySessionReadyCompat` 回写成 wire compat 字段 `cloudSessionReady` - - 因此类型层现在也更接近 `current = open_service_scene_session / 本地执行`,`compat = launch_cloud_scene / 旧云痕迹 / cloudSessionReady` 的事实源 - - 当前计划中的最小验证: - - `npx eslint "src/lib/sceneapp/types.ts"` - - `npm run typecheck` - -- 把首页 `service skill` 入口里的 compat binding 判断也收回 current 分支结构,避免首页推荐逻辑继续把 `cloud_scene` 写成并列执行面: - - 已更新: - - `src/components/agent/chat/service-skills/homeEntrySkills.ts` - - 当前统一结论: - - 首页推荐与 seeded fallback 当前会先把 `cloud_scene` 正规化成 `agent_turn` - - `resolveServiceSkillExecutionKind(...)` 当前不再把 `cloud_scene` 当 current switch 分支,而是只在 compat normalizer 里处理 - - 因此首页 skill 推荐这条 current 入口现在也更接近“先正规化、再按本地执行判断”的统一模型 - - 当前计划中的最小验证: - - `npx eslint "src/components/agent/chat/service-skills/homeEntrySkills.ts"` - - `npm run typecheck` - -- 把 `@命令` 的 recent 也补成可订阅的 live loop,避免输入层已经写入新的 builtin command recent,但面板还要关掉重开才刷新: - - 已更新: - - `src/components/agent/chat/skill-selection/mentionEntryUsage.ts` - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `mentionEntryUsage` 当前新增统一 changed event,并同时支持同页 custom event 与跨窗口 storage 监听 - - `CharacterMention` 当前会订阅这条事实源,并即时重建 `@` 面板里的 `最近使用` - - 因此 builtin command recent 当前会在面板已打开时直接刷新,不再停留在静态快照 - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/skill-selection/mentionEntryUsage.ts" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - 当前环境备注: - - `npm run typecheck` 当前被工作区中既有的 `src/components/agent/chat/workspace/useWorkspaceServiceSkillEntryActions.ts` 断链阻塞,报错集中在缺失 `createServiceSkillRun / recordServiceSkillCloudRun / getServiceSkillRunStatusLabel / sleep / prepareServiceSkillCloudResultWorkspacePayload` 等符号,不属于本轮 `@命令` recent live loop 改动 - - `npm run verify:gui-smoke` 当前也在 `smoke:agent-service-skill-entry` 被同一条 `useWorkspaceServiceSkillEntryActions.test.tsx` 既有失败阻塞,并非本轮输入层 recent 面板刷新引起 - -- 把 `service skill usage` 也补成可订阅的 recent 事实源,避免 `Generate` 或 `@命令` 已经成功写入 recent,但首页 / `我的方法` / slash 面板还停在旧排序: - - 已更新: - - `src/components/agent/chat/service-skills/storage.ts` - - `src/components/agent/chat/service-skills/useServiceSkills.ts` - - `src/components/agent/chat/service-skills/useServiceSkills.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `service skill usage` 当前新增统一 changed event,并同时支持同页 custom event 与跨窗口 storage 监听 - - `useServiceSkills(...)` 当前会订阅这条事实源,统一重算 `recentUsedAt / isRecent / badge` - - 因此首页 `继续上次做法`、`我的方法` 页分组排序,以及 slash 面板里的 recent service skill,当前都会在同页即时刷新,而不是等 catalog refresh - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/service-skills/storage.ts" "src/components/agent/chat/service-skills/useServiceSkills.ts" "src/components/agent/chat/service-skills/useServiceSkills.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/service-skills/useServiceSkills.test.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - -- 把 `curated task` 的 recent writeback 从“只在 launcher 确认时记录”补成“Generate 内成功发送也会更新”,避免工作台 continuation、初始 capability bootstrap 或输入区二次编辑后,recent 仍停留在旧启动参数: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskTemplates.ts` - - `src/components/agent/chat/utils/curatedTaskTemplates.test.ts` - - `src/components/agent/chat/components/Inputbar/hooks/useInputbarSend.ts` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `curated task usage` 当前新增统一 changed event,首页、`我的方法` 页与 slash 面板都能订阅同一条 recent 事实源 - - `Generate` 内成功发送激活中的 `curated_task` 时,当前会把最新 `launchInputValues + referenceMemoryIds + referenceEntries` 写回 recent usage - - 因此 `GeneralWorkbench` 的建议下一步、`initialInputCapability(curated_task)` 启动,以及输入区里二次编辑结果模板后再发送,当前都不再把 recent 留在旧参数上 - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/utils/curatedTaskTemplates.test.ts" "src/components/agent/chat/components/Inputbar/hooks/useInputbarSend.ts" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx" "src/components/skills/SkillsWorkspacePage.tsx"` - - `npm exec vitest run "src/components/agent/chat/utils/curatedTaskTemplates.test.ts" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - -- 把 `@命令 -> service skill` 的 recent continuation 也补成“字段 + 意图”双恢复,避免命令入口已经成功触发 service skill,但后续 recent 里只剩字段快照: - - 已更新: - - `src/components/agent/chat/workspace/useWorkspaceSendActions.ts` - - `src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx` - - `src/components/agent/chat/service-skills/serviceSkillLaunchPrefill.ts` - - `src/components/agent/chat/service-skills/serviceSkillLaunchPrefill.test.ts` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `resolveMentionCommandUsage(...)` 当前会从现有 command metadata 抽取 `prompt / user_input` - - 这条显式意图当前会一并写进 `service skill usage.launchUserInput` - - 因此 command-bound service skill recent 当前也能和 direct service skill recent 一样显影 `上次补充` - - recent summary 当前还补了最小去重:如果 `launchUserInput` 与已有槽位值一致,不再重复显示第二遍 - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/workspace/useWorkspaceSendActions.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" "src/components/agent/chat/service-skills/serviceSkillLaunchPrefill.ts" "src/components/agent/chat/service-skills/serviceSkillLaunchPrefill.test.ts"` - - `npm exec vitest run "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" "src/components/agent/chat/service-skills/serviceSkillLaunchPrefill.test.ts"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - -- 把 `service skill` recent continuation 从“只恢复 slotValues”补到“显式补充目标也能继续带回生成”,避免 recent 卡片已经显影 `上次填写`,但上一轮补充要求在再启动时静默丢失: - - 已更新: - - `src/components/agent/chat/service-skills/types.ts` - - `src/components/agent/chat/service-skills/storage.ts` - - `src/components/agent/chat/service-skills/serviceSkillLaunchPrefill.ts` - - `src/components/agent/chat/service-skills/serviceSkillLaunchPrefill.test.ts` - - `src/components/agent/chat/workspace/useWorkspaceServiceSkillEntryActions.ts` - - `src/components/agent/chat/workspace/useWorkspaceServiceSkillEntryActions.test.tsx` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `service skill usage` 当前可选记录 `launchUserInput` - - recent summary 当前会同时显影: - - `上次填写` - - `上次补充` - - `我的方法 -> 生成` 的 `initialPendingServiceSkillLaunch` 当前也会一并带回这条补充信息 - - `useWorkspaceServiceSkillEntryActions` 当前会把显式透传的 `launchUserInput` 继续写回 recent usage,保证后续 continuation 真能续上同一条方法 - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/service-skills/serviceSkillLaunchPrefill.ts" "src/components/agent/chat/service-skills/serviceSkillLaunchPrefill.test.ts" "src/components/agent/chat/workspace/useWorkspaceServiceSkillEntryActions.ts" "src/components/agent/chat/workspace/useWorkspaceServiceSkillEntryActions.test.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.ts"` - - `npm exec vitest run "src/components/agent/chat/service-skills/serviceSkillLaunchPrefill.test.ts" "src/components/agent/chat/workspace/useWorkspaceServiceSkillEntryActions.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - -- 把 `我的方法库 -> 生成` 的 installed skill continuation 补成真闭环,避免卡片已经显影 `上次目标`,点进去却还得自己重打一遍: - - 已更新: - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `我的方法库` 里的 installed skill 卡片如果已有 `slash usage.replayText` - - 点击 `进入生成` 时当前会同时带上: - - `initialInputCapability(installed_skill)` - - `initialUserPrompt(replayText)` - - 因此这条链路当前已经和首页 `继续上次做法` 的 installed skill continuation 对齐,不再只是“看得到上次目标”,而是能真正沿用它进入 `生成` - - 当前已确认通过: - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run verify:local` - -- 修复桌面端启动白屏的两条 current 主路径兜底,避免窗口已经起来但用户只看到空白页: - - 已更新: - - `src/i18n/withI18nPatch.tsx` - - `src/i18n/withI18nPatch.test.tsx` - - `src/components/agent/chat/index.tsx` - - `src/components/agent/chat/agentChatWorkspaceLoader.ts` - - `src/components/agent/chat/agentChatWorkspaceLoader.test.ts` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `withI18nPatch` 启动期不再直接 `return null`,而是先渲染轻量启动屏,避免 `get_config` 尚未返回时桌面端出现整窗白屏 - - `withI18nPatch` 的 ready 提交不再只依赖 `requestAnimationFrame`,额外补了超时兜底,避免窗口可见前 `opacity=0` 长时间挂住 - - `AgentChatPage` 当前对 `AgentChatWorkspace` 的懒加载增加了模块导入瞬时失败重试,并把 `fallback={null}` 收成可见加载态,避免 Vite dev 热启动或重连期间直接落成空白页 - - 这一步服务的不是旧 compat,而是 current `生成` 主执行面启动稳定性 - -- 把 `sceneapps` 内层详情/复盘面板继续从“工程说明页”收成更接近 Ribbi 的结果视角,避免外层已经叫 `全部做法 / 生成准备 / 做法复盘`,真正点进去后却又退回 `Project Pack / Governance Loop / Planning 基线`: - - 已更新: - - `src/components/sceneapps/SceneAppDetailPanel.tsx` - - `src/components/sceneapps/SceneAppGovernancePanel.tsx` - - `src/components/sceneapps/SceneAppRunDetailPanel.tsx` - - `src/components/sceneapps/SceneAppScorecardPanel.tsx` - - `src/components/sceneapps/SceneAppProjectPackRuntimePanel.tsx` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `src/lib/sceneapp/presentation.ts` - - `src/lib/sceneapp/product.ts` - - `src/lib/sceneapp/reviewDecision.ts` - - `src/lib/sceneapp/executionPromptActions.ts` - - `src/lib/sceneapp/product.test.ts` - - `src/lib/sceneapp/executionPromptActions.test.ts` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `生成准备` 内层当前已围绕 `默认会拿到 / 通常会这样推进 / 默认怎么判断 / 这轮准备情况 / 默认结果去向 / 开始这次生成` 收口,不再默认暴露工程说明词 - - `做法复盘` 左右两块当前也已继续收成 `做法复盘 / 这轮结果 / 做法表现` 这组前台语言,优先讲这轮拿到了什么、卡在哪里、下一步怎么走 - - `sceneapp` 的 runtime summary、运行建议、缺件补齐 prompt 与轻量反馈文案当前也已同步收口,不再默认把 `SceneApp / Project Pack / 治理材料 / Artifact` 直接暴露给用户 - - `Project Pack / Governance Loop / Planning 基线 / PRIMARY` 这类词当前已经从这些面板的首层用户可见文案里移走;保留的只是内部实现锚点与测试 id - - 这一步继续服务 P1:不是删掉复盘能力,而是把它们翻译成用户能直接理解的结果与判断页面 - - 当前已确认通过: - - `npx eslint "src/components/sceneapps/SceneAppDetailPanel.tsx" "src/components/sceneapps/SceneAppGovernancePanel.tsx" "src/components/sceneapps/SceneAppRunDetailPanel.tsx" "src/components/sceneapps/SceneAppScorecardPanel.tsx" "src/components/sceneapps/SceneAppProjectPackRuntimePanel.tsx" "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npx eslint "src/lib/sceneapp/presentation.ts" "src/lib/sceneapp/executionPromptActions.ts" "src/lib/sceneapp/reviewDecision.ts" "src/lib/sceneapp/product.ts" "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm exec vitest run "src/lib/sceneapp/product.test.ts" "src/lib/sceneapp/executionPromptActions.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - 当前环境备注: - - 已再次尝试 `npm run verify:gui-smoke -- --timeout-ms 1200000` - - 这次没有进入页面级断言失败,而是长时间停留在 `bridge:health` 等待阶段 - - 具体现象是 headless Tauri 冷启动后,Rust 构建持续占用十多分钟,`http://127.0.0.1:3030/health` 始终返回 `fetch failed` - - 因为阻塞点仍停在冷编译/DevBridge 就绪前,当前更像本地 GUI smoke 环境成本问题,而不是这轮 `sceneapps` 内层面板收口引入的新断链 - -- 把 `全部做法` 页继续从“分页控制面”收成更接近技能页的线性前台容器,避免 `sceneapps` 虽然退成内部锚点,但真实页面仍然像另一块并列工作台: - - 已更新: - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `全部做法` 页首当前不再强调 `ALL FLOWS` 之类工程词,而是直接说明这页只回答“做什么 / 会拿到什么 / 下一步去哪” - - `做法目录 / 生成准备 / 做法复盘` 当前改成带摘要的步骤卡,用户更容易理解这是同一条线性路径,而不是三块平级控制台 - - 目录筛选当前也不再直接把 `Pipeline / Reviewer / Inversion` 这类英文模式甩给用户,而是翻成更像做法路径的中文,并补显式 `清空筛选` - - `当前已带入` 与 `当前做法` 当前改成轻量状态卡,不再像顶部控制栏 - - `治理复盘` 对外当前继续收成 `做法复盘`,进一步和 `做法目录 / 做法准备` 主词对齐 - - 当前已确认通过: - - `npx eslint "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm exec vitest run "src/components/sceneapps/SceneAppsPage.test.tsx"` - - 当前环境备注: - - 本轮再次尝试 `npm run verify:gui-smoke` - - `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface` 当前都已通过 - - 仍失败在 `smoke:agent-runtime-tool-surface-page` - - 这次症状不再是 `fetch failed`,而是等待 `Runtime 能力摘要` 出现超时,最后结果为 `hasWorkbench=true`、`hasRuntimeSummary=false` - - 当前更像既有 agent runtime page smoke 的环境/时序抖动,不像这轮 `全部做法` 页收口本身引入的新断链 - -- 把 `技能` 页继续从“信息摊平的合同目录”收成更接近 Ribbi 的前台结构,只保留少数强入口与方法目录,不再默认把整套系统结构暴露给用户: - - 已更新: - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `先拿结果` 当前提升到主列顶部,成为技能页真正的第一起手层 - - `方法目录` 当前退回第二层,继续承担“知道方向后按组找做法”的角色 - - `继续常用做法 / 我的方法库` 当前继续保留在右侧,但卡片改成紧凑摘要,不再把一整页切成多块重说明板 - - `curated task` 卡片仍保留 `你来给 / 可选参考 / 会拿到 / 结果去向 / 下一步可继续` 这套 current 事实,只是改成单卡内的紧凑合同,不再用多层内嵌子卡放大结构感 - - 当前已确认通过: - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx"` - - 当前环境备注: - - 本轮再次尝试 `npm run verify:gui-smoke` - - `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface` 当前都已通过 - - 仍失败在 `smoke:agent-runtime-tool-surface-page` - - 具体现象是 `browser_execute_action / close_cdp_session / close_chrome_profile_session` 连续 `fetch failed` - - 这更像复用 headless 浏览器 page 会话时的既有环境抖动,不像这轮技能页布局收口本身引入的新断链 - -## 2026-04-20 - -### 已完成 - -- 把 `memory / automation` 旁路页继续收口到 `做法` 主词,避免用户离开主路径后又被旧 `创作场景` 文案拉回去: - - 已更新: - - `src/components/memory/MemoryPage.tsx` - - `src/components/settings-v2/system/automation/AutomationJobDetailsDialog.tsx` - - `src/components/memory/MemoryPage.test.tsx` - - `src/components/settings-v2/system/automation/index.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `灵感库` 当前会把“带参考进入 sceneapps”这类动作明确写成 `去做法目录` - - `taste` 和灵感条目说明当前统一改成服务 `做法 planning` - - 自动化详情里的闭环摘要当前改成 `做法闭环 / 回到做法准备`,不再把自动化旁路继续描述成另一条 `创作场景` 主链 - - 当前已确认通过: - - `npx eslint "src/components/memory/MemoryPage.tsx" "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.tsx" "src/components/memory/MemoryPage.test.tsx" "src/components/settings-v2/system/automation/index.test.tsx"` - - `npm exec vitest run "src/components/memory/MemoryPage.test.tsx" "src/components/settings-v2/system/automation/index.test.tsx"` - -- 把 `sceneapps` 深层运行态的 current 前台旧词继续收掉,避免只收页首和侧栏、真正进入做法详情和生成回桥后又退回 `创作场景`: - - 已更新: - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppDetailPanel.tsx` - - `src/components/sceneapps/SceneAppsCatalogPanel.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.ts` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` - - `src/lib/sceneapp/product.ts` - - `src/lib/sceneapp/presentation.ts` - - `src/lib/sceneapp/launch.ts` - - `src/lib/sceneapp/reviewDecision.ts` - - `src/lib/sceneapp/runEntryNavigation.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` - - `src/lib/sceneapp/launch.test.ts` - - `src/lib/sceneapp/runEntryNavigation.test.ts` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `做法目录 / 做法复盘 / 当前做法基线 / 做法执行摘要` 当前已经进入 `sceneapps` 详情页、治理页、生成回桥和轻量反馈主链 - - `SceneAppsCatalogPanel` 的搜索框当前也已改成 `搜索做法标题`,目录页不再一半讲“做法”、一半讲“场景” - - `presentation / launch / reviewDecision / runEntryNavigation` 这批 current fallback prompt 与回跳文案当前也开始同步改成 `做法` 口径,避免外层文案收口后,真实启动和复盘链又把用户拉回旧词 - - 当前已确认通过: - - `npx eslint "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/sceneapps/SceneAppDetailPanel.tsx" "src/components/sceneapps/SceneAppsCatalogPanel.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx" "src/lib/sceneapp/product.ts" "src/lib/sceneapp/presentation.ts" "src/lib/sceneapp/launch.ts" "src/lib/sceneapp/reviewDecision.ts" "src/lib/sceneapp/runEntryNavigation.ts" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/lib/sceneapp/launch.test.ts" "src/lib/sceneapp/runEntryNavigation.test.ts"` - - `npm exec vitest run "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/lib/sceneapp/launch.test.ts" "src/lib/sceneapp/runEntryNavigation.test.ts"` - - 当前环境备注: - - `npm run verify:gui-smoke` 本轮仍失败在复用 headless 环境下的 `smoke:browser-runtime` - - 具体现象是 `launch_browser_session` 与后续 `close_chrome_profile_session` 连续返回 `fetch failed` - - 这次阻塞发生在既有浏览器运行时 smoke 链,不像本轮 `sceneapps / 生成回桥 / 做法文案` 收口本身引入的新断链;后续应单独回到 `browser-runtime` 复用环境继续排查 - -- 把 `技能 -> 全部做法 -> SceneApps` 这条回桥补回 current 主线,并同步把 `sceneapps` 首屏从“创作场景主舞台”收回“全部做法”角色: - - 已更新: - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/roadmap/limenextv2/information-architecture.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `技能` 页的 `方法目录` 当前已新增弱入口 `查看全部做法`,用于显式进入 `sceneapps` 目录页 - - 如果用户已在 `技能` 页输入搜索词,这个入口当前会继续带着当前关键词打开 `sceneapps` 的 `catalog` 视图,避免再从头找一次 - - `sceneapps` 页首当前改成 `全部做法`,`场景目录` 当前改成 `做法目录`,空态和首轮治理提示也开始按“整套做法”的角色来讲自己 - - 因此这条页面已经不再像一块并列主舞台,而更像 `技能` 下的完整做法目录与后续装配页 - - 当前已确认通过: - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx"` - -- 把左侧导航继续收回 `技能 / 灵感库 / 生成` 主词,避免 `创作场景` 仍以一级入口身份和 current 主舞台抢叙事: - - 已更新: - - `src/lib/navigation/sidebarNav.ts` - - `src/lib/navigation/sidebarNav.test.ts` - - `src/components/AppSidebar.tsx` - - `src/components/AppSidebar.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 左侧一级侧栏当前改成 `创作 / 支撑 / 系统` 三段;`创作` 下固定只保留 `新建任务 / 技能 / 灵感库 / 生成` - - `创作场景` 当前不再作为一级侧栏入口直接暴露;`SceneApps` 仍保留为 current route,但它的对外进入点改回 `查看全部做法` 与 `技能` 所属区域 - - 当用户当前位于 `sceneapps` 页面时,侧栏当前会把它归属到 `技能` 主入口;因此 `SceneApps` 继续存在,但不再伪装成和 `技能 / 灵感库 / 生成` 平级的主舞台 - - 当前已确认通过: - - `npx eslint "src/lib/navigation/sidebarNav.ts" "src/lib/navigation/sidebarNav.test.ts" "src/components/AppSidebar.tsx" "src/components/AppSidebar.test.tsx"` - - `npm exec vitest run "src/lib/navigation/sidebarNav.test.ts" "src/components/AppSidebar.test.tsx"` - -- 把首页底部原来并列的 `更多起手方式` 与 `支撑能力` 继续收成一条更弱的续接条,避免结果入口下面又长出两个“平台补位块”: - - 已更新: - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 首页底部当前默认只保留 `继续最近做法 / 查看全部做法 / 连接浏览器 / 查看支撑能力` 这类轻入口 - - 旧的能力大卡当前不再从 hero 底部长成第二视觉中心;展开 `查看支撑能力` 时,当前只显示轻量说明列表 - - `SceneApp` 补位、浏览器接入与能力边界说明,当前都退回“如果你已经知道怎么接着做”的辅助层,不再与主结果入口平级竞争 - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` - - 当前环境备注: - - 已额外尝试 `npm run verify:gui-smoke` - - 第一次卡在复用旧 headless 链路后的 `smoke:browser-runtime` 过期 session 清理异常 - - 第二次主链 smoke 通过到最后一步,但 `smoke:agent-runtime-tool-surface-page` 卡在 `launch_browser_session / close_chrome_profile_session` - - 这轮应按 `DevBridge 浏览器会话层环境抖动` 理解,而不是首页 `EmptyState` 结构改动本身阻塞 - -- 把首页 `结果入口` 与 `CuratedTaskLauncherDialog` 一起继续收口,避免 current 主路径虽然已经 skill-first,但前台仍像“结果模板货架 + 重表单弹窗”: - - 已更新: - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 首页 `结果入口` 当前已从“首选结果 / 更多结果 / 快捷做法 / 继续上次做法”的多段货架,收成了 `1 个主推荐结果 + 轻量备选结果 + 辅助起手层` - - `CuratedTaskLauncherDialog` 当前已从“大块合同弹窗”收成更轻的启动确认卡;只先确认最少必填信息,参考对象仍保留,但不再和合同说明一起平铺 - - 这一步没有改推荐排序、typed capability、recent continuation 或 reference live refresh 的 current 主链;只是把前台投影进一步对齐到 Ribbi 式“Agent 引导起手” - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - -- 把 `curated_task` 的 bootstrap 恢复再补一刀,避免官网 deep link 或其他外部入口虽然已经带着结果模板 route 进入 `生成`,却在还没确认启动槽位时被直接退回成 prompt 起手: - - 已更新: - - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 当 `initialInputCapability.capabilityRoute.kind === "curated_task"` 且该模板本身存在必填槽位、但 route 还没带 `launchInputValues` 时,输入层当前会先自动打开 launcher,而不是直接把 `route.prompt` 塞进输入框 - - 当 route 已经带着 `launchInputValues` 时,输入层仍会按 current 主链恢复 badge,并在输入为空时自动回填 launch prompt - - 因此 `curated_task bootstrap` 当前已经开始区分“尚未确认启动信息”和“已确认启动信息”;外部入口也开始回到 launcher-first,而不再绕开最小启动合同 - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npm run verify:gui-smoke` - -- 把技能页 `先拿结果 -> 进入生成` 这条 bridge 再补一刀,避免结果模板 launcher 虽然已经把启动槽位写进 `requestMetadata`,但 `initialInputCapability.capabilityRoute` 仍退回只剩 prompt 与 reference: - - 已更新: - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 技能页 launcher 确认进入 `生成` 时,当前会把 `launchInputValues` 和 `referenceEntries` 一起写进 `initialInputCapability.capabilityRoute` - - 因此从技能页进入 `生成` 后,首屏 active capability 与后续重开 launcher 不再只靠首轮 prompt 文本恢复;已经确认过的槽位值会继续留在同一条 typed contract 里 - - 这一步继续服务 `P2` 主线:让首页、slash、技能页三条结果模板入口共享的不只是模板 id 与 prompt,而是完整启动事实 - - 当前已确认通过: - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run verify:gui-smoke` - -- 把 `GeneralWorkbench` 里的跨模板 continuation 再补一刀,避免 `复盘 -> 下一轮内容方案` 虽然已经能切到下游结果模板,但启动参数只剩 reference prefill、把上一轮已确认的 launch context 丢掉: - - 已更新: - - `src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx` - - `src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `GeneralWorkbench` 的 follow-up action 在切到下游 `curated_task` 时,当前会把已有 `launchInputValues` 一并并入目标模板的 reference prefill - - 因此 `复盘 -> 下一轮内容方案` 这类跨模板闭环,不再只靠 `referenceEntries` 重建启动信息;上一轮已经确认过的启动上下文会继续带过去 - - 这一步继续服务 `P4` 的 current 主线:让 `复盘 -> 再生成` 不只“跳得到下游模板”,也“保得住上一轮上下文” - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx" "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` - -- 把首页、技能页、slash 与 launcher 的推荐信号监听边界继续收口到统一订阅入口,避免同一条 `curated task recommendation signal` 主链在页面层仍保留三套手写事件接线: - - 已更新: - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/agent/chat/utils/curatedTaskRecommendationSignals.test.ts` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 首页 `结果模板`、技能页 `先拿结果`、slash `结果模板` 与 launcher 当前都通过 `subscribeCuratedTaskRecommendationSignalsChanged(...)` 订阅同一条推荐信号变化 - - 因此除了原有自定义事件外,storage 变更也会沿同一条 current 订阅边界回流,不再只有 launcher 走统一入口、其余页面各自手写监听 - - 这一步没有改变推荐排序规则,只是把 `saved_inspiration / review_feedback / active_reference` 的前台回流边界继续收成一条 current 主链 - - 当前已确认通过: - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/utils/curatedTaskRecommendationSignals.test.ts"` - - `npm exec vitest run "src/components/agent/chat/utils/curatedTaskRecommendationSignals.test.ts" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - -- 把打开中的 `CuratedTaskLauncherDialog` 再补一刀,避免 recent references 刷新时只保住 seed reference、却把用户刚手动勾选的非 seed 参考静默挤掉: - - 已更新: - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - launcher 在收到推荐信号后重拉 recent references 时,当前会把“已带入线程的 seed reference”和“用户手动勾选的参考对象”一起并回候选列表 - - 因此用户在弹窗打开态下先选了一条最近参考,再触发一次 `saved_inspiration` 回流时,先前勾选不会因为 recent list 旋转而消失 - - confirm payload 当前也会继续保留这批手动勾选 reference entries,不再只保留还留在 recent list 里的部分 - - 这一步继续服务 `P3` 的 current 主线:让 launcher live refresh 从“看得到新的参考对象”推进到“保得住已经选好的参考对象” - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx"` - - `npm run verify:gui-smoke` - -- 把 `CuratedTaskLauncherDialog` 的参考对象区继续补成“打开中也会回流”的 live 版本,避免用户保存了新的灵感后,当前已经打开的结果模板 launcher 仍停在旧快照: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskRecommendationSignals.ts` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `curatedTaskRecommendationSignals` 当前新增统一订阅入口,`CuratedTaskLauncherDialog` 会在打开态监听同一条推荐信号变更 - - launcher 不再只在打开瞬间拉一次最近参考对象;收到 `saved_inspiration` 等回流信号后,会重新拉取 recent references - - 这次 live refresh 当前刻意只刷新 recent reference cards,不重置 `selectedReferenceEntryIds` - - 因此已经带入线程的 seed reference 不会被静默冲掉,哪怕它来自 `sceneapp_execution_summary` 这类项目结果,确认启动时也仍会保留在 `referenceEntries` payload 里 - - 这一步继续服务 `P3` 的 current 主线:让“保存到灵感库”不只影响首页/技能页/slash 的下一轮推荐,也开始影响当前已经打开、仍在准备启动的结果模板 launcher - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/utils/curatedTaskRecommendationSignals.ts" "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx"` - - `npm run verify:gui-smoke` - -- 把 `taste/reference` 的 category-aware 口径继续接回推荐理由与结果模板 launcher,避免前台只在“当前带入对象”横条里分得清 `风格 / 偏好 / 参考 / 成果 / 收藏`,到了推荐和启动层又退回“灵感/参考”泛称: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskReferenceSelection.ts` - - `src/components/agent/chat/utils/creationReplaySurface.ts` - - `src/components/agent/chat/utils/creationReplaySurface.test.ts` - - `src/components/agent/chat/utils/curatedTaskRecommendationSignals.ts` - - `src/components/agent/chat/utils/curatedTaskRecommendationSignals.test.ts` - - `src/components/agent/chat/utils/curatedTaskTemplates.ts` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `CuratedTaskRecommendationSignal` 的理由摘要当前不再一律写成 `参考:...`,而会按 `风格 / 偏好 / 参考 / 成果 / 收藏` 直接显影 - - reference entry 的 fallback title 当前也不再统一退回 `未命名灵感`,而会回到 `未命名风格 / 未命名偏好 / 未命名成果` 这类 category-aware 兜底 - - `CuratedTaskLauncherDialog` 的引用区当前开始统一使用“参考对象”口径,并明确告诉用户可以带入风格参考、偏好基线与项目结果,而不是继续把它们都叫作“灵感” - - launcher 里的 reference 卡片当前也已显式区分 `灵感库` 与 `项目结果` 来源,不再要求用户靠标题猜来源 - - 这一步继续服务 `P3` 的 current 主线:让 taste/reference 不只停在后台事实源和主执行面横条,而是正式进入推荐与启动层的前台语言 - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/utils/curatedTaskReferenceSelection.ts" "src/components/agent/chat/utils/creationReplaySurface.ts" "src/components/agent/chat/utils/creationReplaySurface.test.ts" "src/components/agent/chat/utils/curatedTaskRecommendationSignals.ts" "src/components/agent/chat/utils/curatedTaskRecommendationSignals.test.ts" "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/utils/creationReplaySurface.test.ts" "src/components/agent/chat/utils/curatedTaskRecommendationSignals.test.ts" "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npm run verify:gui-smoke` - -- 把 `creation_replay(memory_entry)` 的前台投影补成 category-aware 的 taste/reference 对象,避免 `生成` 主执行面把 `风格 / 偏好 / 参考 / 成果 / 收藏` 全都泛化成“当前带入灵感”: - - 已更新: - - `src/components/agent/chat/utils/creationReplaySurface.ts` - - `src/components/agent/chat/utils/creationReplaySurface.test.ts` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `creation_replay(memory_entry)` 当前会按 `identity / preference / context / experience / activity` 分别显影为 `风格参考 / 偏好基线 / 参考素材 / 成果样本 / 收藏线索` - - 前台横条与首页输入区轻提示因此不再只会说“当前带入灵感”,而开始把 taste/reference 作为正式对象给用户看见 - - 这一步没有新增长期对象或新协议;只是继续复用现有 `creation_replay + reference entry` 事实源,把异步 taste/reference 层更准确地投到 `生成` 主执行面 - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/utils/creationReplaySurface.ts" "src/components/agent/chat/utils/creationReplaySurface.test.ts"` - - `npm exec vitest run "src/components/agent/chat/utils/creationReplaySurface.test.ts"` - -- 把 `P5` 的第六刀补成“recent usage 同页即时回流”,避免首页 `继续上次做法` 虽然已经能读到本地做法,但刚跑过的方法仍然要等重进页面才出现: - - 已更新: - - `src/components/agent/chat/skill-selection/slashEntryUsage.ts` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `slashEntryUsage` 当前新增统一 changed event 与订阅函数,不再只是 `localStorage` 静态快照 - - 首页 `EmptyState` 当前会在 recent usage 变化时立即重算 `继续上次做法` - - slash 输入层当前也会在面板打开状态下即时刷新 `最近使用`,不再出现“首页变了、slash 还没变”的分叉 - - 这一步属于 `P5` 的 current 第六刀:把 `recent usage` 从存量记录推进成主链可感知信号 - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/skill-selection/slashEntryUsage.ts" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npm run verify:gui-smoke` - - 当前补充说明: - - 这轮仍然没有新增第二套 recent cache,也没有引入 polling - - 只是把现有 `slash usage` 升级成同页实时回流信号,继续服务 `技能 / 灵感库 / 生成` 主叙事 - - 最新一次 `verify:gui-smoke` 已完整通过,说明这轮 recent usage 实时回流没有破坏当前 `生成` 主执行面、slash 输入层或页面级 runtime tool surface 主路径 - -- 把 `P5` 的第五刀补成“我的方法库回到首页继续层”的前台闭环,避免本地已安装 Skill 虽然已经能从技能页进入 `生成`,但回到首页后仍然消失在 `继续上次做法` 之外: - - 已更新: - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `EmptyState` 当前会从已有 `slashEntryUsage(kind = "skill")` 读取最近用过的本地做法,并把它们并入首页 `继续上次做法` - - 这批本地做法继续复用 installed skill 的统一轻合同投影,不再为首页再拼一套特供文案 - - 点击最近本地做法时,当前会直接恢复 `installed_skill` active capability;如果上次运行留下了 `replayText`,当前还会一并回填到输入框 - - 这一步属于 `P5` 的 current 第五刀:把 `我的方法库 -> 进入生成 -> 首页继续上次做法` 正式接成同一条主链 - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` - - 当前补充说明: - - 这一步刻意不新增 `recent installed skill` 专用存储,而是复用现有 `slash usage + installed skill capability route` - - 因此这轮是 current 主链收口,不是再造一套 recent/replay 子系统 - -- 把 `P5` 的第四刀补成“创建后回到我的方法库”的前台闭环,避免 `SceneApp -> 沉淀为做法` 虽然已经能产出技能草稿,但创建成功后仍然停在导入整理弹窗内部: - - 已更新: - - `src/components/skills/SkillsPage.tsx` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsPage.test.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `SkillsPage` 当前在创建 scaffold 成功后,会把新 Skill 事实回调给外层工作台,而不再只是自己打开检查弹窗 - - `SkillsWorkspacePage` 当前会立刻刷新本地已安装技能、关闭 `整理我的方法`,并把这条新做法高亮到 `我的方法库` - - 为了避免刷新稍慢时出现空档,当前还会先用 optimistic skill 把这条新做法插回列表,因此用户创建成功后能马上看到“刚沉淀”的方法卡 - - 已消费成功的 `initialScaffoldDraft` 当前不会在下次再次打开 `整理我的方法` 时重复自动弹出 - - 这一步属于 `P5` 的 current 第四刀:把 `SceneApp 结果 -> 沉淀为做法 -> 创建 Skill -> 我的方法库 -> 进入生成` 补成正式主链 - - 当前已确认通过: - - `npx eslint "src/components/skills/SkillsPage.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsPage.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm exec vitest run "src/components/skills/SkillsPage.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run verify:gui-smoke` - - 当前补充说明: - - 这轮 `verify:gui-smoke` 已重新完整通过,说明 `我的方法库 / 整理我的方法 / 生成` 这条工作台主路径没有被这次闭环收口破坏 - - 最新一次 `verify:local` 未能全绿,但这次不再是之前的 `chrome-relay` 文案断言,而是被现存的 Rust 编译错误阻塞: - - `src-tauri/crates/aster-rust/crates/aster/src/tools/agent_control.rs:951` - - 错误为缺少 `query_session` 导入,并伴随 `type annotations needed` - - 因此本轮关于 `P5` 第四刀的结论应更新为:`skills` 工作台 current 主链已通过定向回归与 GUI smoke,仓库级 `verify:local` 仍受一条与本刀无关的 Rust 编译问题阻塞 - -- 把 `P5` 的第三刀补成最小 skill 演化种子,避免 `SceneApp` 结果虽然已经能复盘、推荐下一轮结果模板,但还不能把这轮成功路径整理成可编辑做法: - - 已更新: - - `src/components/agent/chat/utils/sceneAppSkillScaffoldDraft.ts` - - `src/components/agent/chat/utils/sceneAppSkillScaffoldDraft.test.ts` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/roadmap/limenextv2/runtime-architecture.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `SceneAppExecutionSummaryCard` 当前新增 `沉淀为做法`,用户不需要先回消息流找一条合适的助手结果,才能开始整理技能草稿 - - 这条入口当前会把 `scene summary + latest pack result detail + latest review_feedback` 编译成一版 `initialScaffoldDraft`,并直接带去 `skills` 页 - - 草稿里当前会显式补出 `适用场景 / 输入骨架 / 输出合同 / 执行步骤 / 回退策略`,因此“复盘过的结果路径”第一次开始以可编辑做法的形式显影 - - 这一步仍然故意停在人工确认层:不会自动安装 skill,不会自动写进 `我的方法库`,也不会另起一套 skill evolution 工作台 - - 这一步属于 `P5` 的 current 第三刀:把 `当前结果 -> 人工复盘 -> 做法草稿` 补成正式主链,开始验证 Lime 的 skill 演化是否值得继续做深 - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/utils/sceneAppSkillScaffoldDraft.ts" "src/components/agent/chat/utils/sceneAppSkillScaffoldDraft.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx"` - - `npm exec vitest run "src/components/agent/chat/utils/sceneAppSkillScaffoldDraft.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/index.test.tsx" --testNamePattern="页面参数带着 pending service skill 时,应在当前对话挂起服务技能 A2UI"` - - `npm run verify:gui-smoke` - - 当前补充说明: - - 这轮 `verify:gui-smoke` 已重新完整通过,说明 `SceneApp -> 沉淀为做法` 没有再次破坏 `AgentChatWorkspace` 的主路径初始化顺序 - - 最新一次 `verify:local` 未能全绿,但失败项落在与本刀无关的 [chrome-relay 文案断言](/Users/coso/Documents/dev/ai/aiclientproxy/lime/src/components/settings-v2/system/chrome-relay/index.test.tsx#L511);当前报错为期待文案中没有空格版 `extensions/lime-chrome` 提示,而实际渲染内容多了一处空格 - - 因此这轮关于 `P5` 第三刀的结论应更新为:`SceneApp / Skills / AgentChatWorkspace` 主链已通过定向回归与 GUI smoke,仓库级 `verify:local` 仍受一条不相干设置页断言阻塞 - -- 把 `P5` 的第二刀补成共享推荐信号回路,避免人工复盘虽然已经写回 `SceneApp` 摘要,但首页 / 技能页 / slash 的下一轮结果入口仍旧和复盘结论脱节: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskRecommendationSignals.ts` - - `src/components/agent/chat/utils/curatedTaskTemplates.ts` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/agent/chat/utils/curatedTaskRecommendationSignals.test.ts` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/runtime-architecture.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `SceneApp` 结果卡保存人工复核结论后,当前除了刷新 `sceneApp execution summary runtime`,还会同步写入 `review_feedback` 推荐信号 - - 这条信号当前会按复盘状态映射 `preferredTaskIds`,并携带 `sceneTitle / riskLevel / riskTags / followUpActions` 等摘要事实,直接进入现有 `curated task recommendation signals` 主链 - - 首页 `结果入口`、技能页 `先拿结果` 与 slash `结果模板` 当前继续共用同一份 featured 排序逻辑,因此最近复盘会真实影响下一轮前排结果模板,而不是只停在某个局部视图里 - - 前台当前会显式显示 `围绕最近复盘` 与 `复盘:...`,因此“人工复盘已经开始影响下一轮推荐”对用户也是可感知的,不再只是 util 层静默生效 - - 这一步属于 `P5` 的 current 第二刀:把 `当前结果 -> 人工复盘 -> 下一轮结果模板前排` 接成共享异步增益链,而不是再做一套 review 专属前台对象 - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/utils/curatedTaskRecommendationSignals.ts" "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/utils/curatedTaskRecommendationSignals.test.ts" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/utils/curatedTaskRecommendationSignals.test.ts" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npm run verify:gui-smoke` - - `npm run verify:local` - - 当前补充说明: - - 最新 `verify:local` 已实际通过 `verify:app-version`、`lint`、`typecheck`、smart vitest、`cargo test --manifest-path src-tauri/Cargo.toml` 与 `verify:gui-smoke` - - `verify:gui-smoke` 末尾 `agent-runtime-tool-surface-page` 当前继续通过,且 `hasRuntimeSummary=true`、`hasWorkbench=true` - - 说明这次 P5 改动已经通过 Lime current GUI 主路径验证,不是只在推荐 util 或测试桩层成立 - -- 把 `P4` 再补一段:让 `SceneApp` 结果卡里的“同聊推进”不再退回裸 prompt,而是接回统一 typed continuation 主链: - - 已更新: - - `src/components/agent/chat/utils/sceneAppExecutionPromptContinuation.ts` - - `src/components/agent/chat/utils/sceneAppExecutionPromptContinuation.test.ts` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `SceneAppExecutionSummaryCard` 里的 `发布前检查 / 进入发布整理 / 生成渠道预览稿 / 整理上传稿`,当前会先被编译成统一 `prompt + capabilityRoute` payload - - 上述四类动作当前分别恢复到: - - `publish_compliance` - - `publish_runtime` - - `channel_preview_runtime` - - `upload_runtime` - - 因此用户点击这些动作后,会继续回到同一个 `生成` 主执行面与 active capability,而不是看起来在同聊推进、实际已经退回普通 prompt - - `补齐缺失部件` 当前也会优先恢复 `runtime_scene capability`,复用当前 SceneApp 的 `linkedSceneKey` 回到原场景主链继续补件 - - 只有拿不到稳定 `sceneKey` 的结果样本,当前才会继续回退到 prompt fallback - - 这一步继续服务 `P4` 的 current 目标:让 `项目结果 -> 发布/预览/上传下一步` 也和 `复盘 -> 再生成` 一样进入真实闭环,而不是另一处假闭环 - -- 收掉上一刀 `typed continuation` 带来的初始化顺序回归,避免 `fill_missing_parts -> runtime_scene` 已经接通,但 `生成` 主执行面本身因为 TDZ 在 GUI smoke 里起不来: - - 已更新: - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `handleRunSceneAppExecutionPromptAction` 当前已下移到 `sceneAppExecutionSummaryState` 初始化之后,不再在 hook 初始化阶段提前捕获未完成声明的摘要状态 - - 因此 `SceneAppExecutionSummaryCard` 的 `发布前检查 / 进入发布整理 / 生成渠道预览稿 / 整理上传稿 / 补齐缺失部件` 这组 continuation action,当前不仅类型上已回到统一路由,GUI 主路径上也不再触发 `Cannot access 'sceneAppExecutionSummaryState' before initialization` - - 这一步不是新功能扩展,而是把上一刀真正推到 Lime current 可交付门槛 - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/utils/sceneAppExecutionPromptContinuation.ts" "src/components/agent/chat/utils/sceneAppExecutionPromptContinuation.test.ts" "src/components/agent/chat/AgentChatWorkspace.tsx"` - - `npm exec vitest run "src/components/agent/chat/utils/sceneAppExecutionPromptContinuation.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/components/agent/chat/index.test.tsx" --testNamePattern="页面参数带着 pending service skill 时,应在当前对话挂起服务技能 A2UI"` - - `npm run verify:gui-smoke` - -- 把 `P5` 的第一条反馈回流补到 current 主执行面,避免人工复核虽然已经保存成功,但 `SceneApp` 摘要与下一轮基线仍停在旧状态: - - 已更新: - - `src/components/agent/chat/workspace/useSceneAppExecutionSummaryRuntime.ts` - - `src/components/agent/chat/workspace/useSceneAppExecutionSummaryRuntime.test.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `useSceneAppExecutionSummaryRuntime` 当前新增稳定 `requestRefresh()`,允许外部在不重建页面的前提下主动重新拉取 `SceneApp` 最新 `runs + scorecard` - - `SceneApp` 结果卡里的人工复核 / 轻量反馈保存成功后,`AgentChatWorkspace` 当前会立刻触发这次 refresh - - 因此 `runtimeBackflow`、`latestPackResultDetailView` 与后续 continuation 会消费的结果基线,当前会立即拿到最新 scorecard action 与 failure signal,不再要求用户手动重进页面 - - 这一步属于 `P5` 的 current 第一刀:先让显式反馈真正反哺主执行面,而不是停在 review decision 落盘这一层 - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/workspace/useSceneAppExecutionSummaryRuntime.ts" "src/components/agent/chat/workspace/useSceneAppExecutionSummaryRuntime.test.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx"` - - `npm exec vitest run "src/components/agent/chat/workspace/useSceneAppExecutionSummaryRuntime.test.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` - - `npm run verify:gui-smoke` - - `npm run verify:local` - -- 把 `P4:项目结果与复盘视角收口` 的 current 主链正式补成统一 `reference entry`,不再让 `sceneApp` 结果走一条单独的 review 专线: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskReferenceSelection.ts` - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/agent/chat/components/generalWorkbenchWorkflowData.ts` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `sceneApp execution summary` 当前会被包装成 `source_kind = "sceneapp_execution_summary"` 的统一 `reference entry` - - 首页空态、输入层、slash launcher 与结果模板启动层当前都会消费同一组 `defaultReferenceEntries`,不再拆成“灵感 seed”和“项目结果 seed”两套对象 - - `account-project-review` 当前可直接从 `taskPrefillByTaskId` 自动拿到 `project_goal + existing_results`,因此“复盘这个账号/项目”已经开始吃当前项目结果基线 - - `request metadata` 当前以 `reference_entries` 为 canonical 事实源;`reference_memory_ids` 只保留真实 memory id,旧 `reference_memory_entries` 只继续作为内部读取 fallback - - 因此 `结果模板 -> 生成 -> 当前进展/运行详情 -> 继续复盘/继续生成` 这条 P4 current 主链,当前已经开始围绕同一份参考基线闭环 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/utils/curatedTaskReferenceSelection.test.ts" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts" "src/components/agent/chat/components/generalWorkbenchWorkflowData.test.ts" "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npm run verify:local` - - 当前补充说明: - - 最新 `verify:local` 已实际通过 `verify:app-version`、`lint`、`typecheck`、smart vitest、`cargo test --manifest-path src-tauri/Cargo.toml` 与 `verify:gui-smoke` - - `smoke:agent-runtime-tool-surface-page` 最新 summary 仍为 `hasRuntimeSummary=true` 且 `hasWorkbench=true`,说明这条 P4 主链没有破坏 current GUI 主路径 - -- 修复 `CuratedTaskLauncherDialog` 在内容较长时无法下拉的问题,避免像“每日趋势摘要”这类结果模板因为参考区过长而把整窗内容裁掉: - - 已更新: - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - launcher 当前改成 `头部固定 + 中间滚动 + 底部固定` 的结构,中间主体会落在独立的 `overflow-y-auto` 容器里 - - 因此在小窗口或参考条目较多时,用户现在可以继续下拉查看完整表单、参考基线列表和底部操作按钮,不会再被 modal 外层直接裁掉 - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx"` - - `npm run verify:local` - -- 把 `P4` 再往前台推进一刀:让 `sceneApp` 当前结果卡可以直接进入 `复盘这个账号/项目`,不再要求用户先回首页再找结果模板: - - 已更新: - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts` - - `src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `SceneAppExecutionSummaryCard` 当前新增 `复盘当前项目` 动作,但没有新开 `sceneApp -> review` 专线 - - 这颗按钮当前会把同一份 `sceneapp_execution_summary reference entry` 编译成 `curated_task(account-project-review)` continuation payload - - 因此用户点击后会直接回到 `生成` 主执行面,并挂上同一个 `curated_task` active capability;`project_goal + existing_results + reference_entries` 也会一并保留 - - 这一步继续服务 `P4` 的 current 目标:让 `当前结果 -> 复盘 -> 下一轮生成` 成为显式前台动作,而不是只停在后台 metadata 已经连通 - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/utils/sceneAppCuratedTaskReference.ts" "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx"` - - `npm exec vitest run "src/components/agent/chat/utils/sceneAppCuratedTaskReference.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` - - `npm run verify:local` - -- 把 `P4` 的“复盘 -> 再生成”从假闭环补成真闭环,避免 `复盘这个账号/项目` 的建议下一步仍旧挂在 review 模板下继续说话: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskTemplates.ts` - - `src/components/agent/chat/utils/curatedTaskTemplates.test.ts` - - `src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx` - - `src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `account-project-review` 当前可以给 follow-up action 显式声明下游结果模板,不再把所有“建议下一步”都硬塞回原模板 - - 当用户在 `生成工作台` 的复盘结果里点击 `继续做趋势摘要` 或 `生成下一轮内容方案` 时,当前会分别切到 `daily-trend-briefing` 与 `social-post-starter` - - 这类 continuation 当前仍保留同一份 `reference_entries / reference_memory_ids`,并会按目标模板重新组织 prompt;因此复盘输出终于开始真正回到下一轮生成,而不是继续停留在 review 语境里兜圈 - - 这一步继续服务 `P4` 的 current 目标:让 `当前结果 -> 复盘 -> 下一轮生成` 成为真实的前台闭环,而不是只有按钮长得像闭环 - - 当前已确认通过: - - `npx eslint "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/utils/curatedTaskTemplates.test.ts" "src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx" "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/utils/curatedTaskTemplates.test.ts" "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` - - `npm run verify:local` - -## 2026-04-19 - -### 已完成 - -- 把 `recent continuation` 里的 `curated task` 从“最近点过什么”继续推进成“最近那版方法可以回来”,避免首页 `继续上次做法` 与 slash `最近使用` 仍然只会重新打开空白模板: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskTemplates.ts` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - recent `curated_task` 当前不再只记最近使用时间,也会保留最近一次成功启动该结果模板时的 `launchInputValues + referenceEntries` - - 首页 `继续上次做法` 与 slash `最近使用` 里点这类结果模板时,当前都会重开同一套 launcher,但已经带着上次那版参数和引用 - - launcher 顶部当前会显式提示“已根据你上次启动时的参数自动预填”,让“方法留下来了”变成前台可感知能力 - - 这样 `技能页/首页/输入层 启动结果模板 -> recent continuation -> 同一 launcher 带上次参数回来` 这条 current skill-first 主链继续闭合 - - 当前已确认通过: - - `npm run test -- src/components/agent/chat/components/EmptyState.test.tsx src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `npx eslint "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npm run verify:local` - - 当前补充说明: - - 本轮 `verify:local` 已实际覆盖 `verify:app-version`、`lint`、`typecheck`、smart vitest、`cargo test --manifest-path src-tauri/Cargo.toml` 与 `verify:gui-smoke` - - `verify:gui-smoke` 末尾 `agent-runtime-tool-surface-page` 当前继续通过,且 `hasRuntimeSummary=true`、`hasWorkbench=true` - - 说明这次 recent prefill 改动不只是局部交互增强,而是已经保持住 current GUI 主路径可交付 - -- 把 `recent continuation` 里的 `curated task` 也收回完整 current skill 合同,避免首页 `继续上次做法` 与 slash 最近使用还停在旧摘要层: - - 已更新: - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 首页 `继续上次做法` 里的 recent `curated task`,当前不再只显示 `需要 / 交付`,也会继续带出 `去向 / 下一步` 的缩略投影 - - slash 面板 `最近使用` 里的 recent `curated task` 当前也复用同一份 capability description,不再只回退到模板 summary - - 因此 `结果模板 / recent continuation / slash recent curated task / 生成工作台` 四条 current 前台入口,当前已经开始围绕同一份 `需要 / 交付 / 去向 / 下一步` 事实源收口 - - 当前已确认通过: - - `npm run test -- src/components/agent/chat/components/EmptyState.test.tsx` - - `npm run test -- src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - -- 把 `GeneralWorkbench` 里的 `建议下一步` 从“可见提示”继续推进成“可操作 continuation action”,避免 `followUpActions` 到了工作台又停在说明文案: - - 已更新: - - `src/components/agent/chat/components/generalWorkbenchSidebarContract.ts` - - `src/components/agent/chat/components/generalWorkbenchWorkflowData.ts` - - `src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx` - - `src/components/agent/chat/components/generalWorkbenchWorkflowData.test.ts` - - `src/components/agent/chat/utils/curatedTaskReferenceSelection.ts` - - `src/components/agent/chat/utils/inputCapabilityBootstrap.ts` - - `src/components/agent/chat/utils/inputCapabilityBootstrap.test.ts` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `GeneralWorkbench` 当前会把运行 metadata 里解析出的前两条 `followUpActions` 投成轻量按钮,不再只是展示“建议下一步” - - 运行 metadata 里的 `launch_input_values + reference_memory_ids + reference_entries` 当前也会被一并解析出来;旧 `reference_memory_entries` 只继续作为内部读取 fallback,不再是 current 写入口径 - - 点击后不再只是把 continuation prompt 写回输入框;它会继续恢复同一个 `curated_task capabilityRoute`,因此 `Inputbar` 会重新挂回 active capability badge - - `当前进展` 与 `当前查看运行` 两处都会共享这组 continuation action,因此 `首页结果入口 -> 输入激活态 -> 运行 metadata -> 生成工作台 -> 输入继续生成` 这条闭环当前已经正式接通,而且 continuation 的上下文没有在工作台丢失 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/generalWorkbenchWorkflowData.test.ts" "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx" "src/components/agent/chat/utils/inputCapabilityBootstrap.test.ts"` - - `npx eslint "src/components/agent/chat/components/generalWorkbenchSidebarContract.ts" "src/components/agent/chat/components/generalWorkbenchWorkflowData.ts" "src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/utils/curatedTaskReferenceSelection.ts" "src/components/agent/chat/utils/inputCapabilityBootstrap.ts" "src/components/agent/chat/utils/inputCapabilityBootstrap.test.ts" "src/components/agent/chat/components/generalWorkbenchWorkflowData.test.ts" "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` - - `npm run verify:local` - - 当前补充说明: - - 本轮 `verify:local` 已实际通过 `lint`、`typecheck`、smart vitest、`cargo test --manifest-path src-tauri/Cargo.toml` 与 `verify:gui-smoke` - - `smoke:agent-runtime-tool-surface-page` 最新 summary 已明确为 `hasRuntimeSummary=true`、`hasWorkbench=true`,说明这次 continuation capability 恢复已经通过 current GUI 主路径验证 - -- 把 `P3 / P4` 之间一直停留在模板里的 `followUpActions` 正式接回 current 前台主链,不再只在 launcher 合同区里出现一次: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskTemplates.ts` - - `src/components/agent/chat/skill-selection/CuratedTaskBadge.tsx` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx` - - `src/components/agent/chat/components/generalWorkbenchWorkflowData.ts` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx` - - `src/components/agent/chat/components/generalWorkbenchWorkflowData.test.ts` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 首页 `结果模板` 卡片当前会显式带出 `下一步`,不再只有 `需要 / 交付 / 去向` - - 输入区里已激活的 `curated_task` badge 当前会显示下一步摘要,让“结果模板正在接管这一轮生成”的后续方向可见 - - `GeneralWorkbench` 当前会从 `activeRunDetail.metadata.harness.curated_task` 解析当前结果模板,并在 `当前进展` 与 `当前查看运行` 里继续显示 `建议下一步` - - 这意味着 `curated task` 的 `resultDestination + followUpActions` 当前已经开始跨越 `首页结果入口 -> 输入激活态 -> 运行 metadata -> 生成工作台` 形成同一条闭环 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx" "src/components/agent/chat/components/generalWorkbenchWorkflowData.test.ts"` - - `npx eslint "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/skill-selection/CuratedTaskBadge.tsx" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx" "src/components/agent/chat/components/generalWorkbenchWorkflowData.ts" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx" "src/components/agent/chat/components/generalWorkbenchWorkflowData.test.ts"` - - `npm run verify:local` - -- 把 `P3:灵感库与 taste/reference 回流` 继续推进到输入层,让 slash 面板里的 `结果模板` 不再停留在静态目录顺序,而是正式接回与首页、技能页一致的推荐排序: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskTemplates.ts` - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/agent/chat/components/Inputbar/index.tsx` - - `src/components/agent/chat/components/Inputbar/components/InputbarComposerSection.tsx` - - `src/components/agent/chat/components/EmptyStateComposerPanel.tsx` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/workspace/useWorkspaceInputbarSceneRuntime.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - slash 面板当前会和首页、技能页一样,按 `projectId / sessionId / referenceEntries / saved_inspiration` 共同影响 `curated task` 排序 - - `CharacterMention` 当前会监听推荐信号变更事件,打开中的 slash 面板也能重算,不再只有重开页面后才看到推荐变化 - - 为了让强信号真正能抬升非默认模板,`featured` 的默认骨架分值当前已继续收轻,并给强匹配结果模板增加额外 signal lift;像 `复盘这个账号/项目` 这类入口,当前不再只是“有推荐理由但排不上来” - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/utils/curatedTaskRecommendationSignals.test.ts"` - - `npx eslint "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - -- 把前台品牌入口继续收回单一 current logo 事实源,避免侧边栏、欢迎页、关于页、消息空态仍各自直连旧 `/logo-v6.svg`,导致用户已切换 Lime 新品牌但主导航仍显示旧图标: - - 已更新: - - `src/lib/branding.ts` - - `src/components/AppSidebar.tsx` - - `src/components/onboarding/steps/WelcomeStep.tsx` - - `src/components/SplashScreen.tsx` - - `src/components/agent/chat/components/MessageList.tsx` - - `src/components/settings-v2/system/about/index.tsx` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 前台品牌展示当前统一走 `LIME_BRAND_LOGO_SRC = "/logo.png"`,不再让多个页面各自引用旧 logo 资源 - - `public/logo.png` 当前已恢复为 `logo-v6` 主图;左上角返回首页入口、欢迎页、Splash、About 和消息空态/任务中心空态都会回到同一张 `logo-v6` - - `src-tauri/icons/tray/tray-running.png`、`tray-warning.png`、`tray-error.png`、`tray-stopped.png` 当前也已回到 `logo-v6` 底图,只保留状态点颜色区分运行态 - - 侧边栏品牌入口当前也已去掉过重的外框阴影与高光描边,避免 `logo-v6` 在浅色侧栏里继续像一张独立小卡片,改回更轻的直接落版效果 - - 这样后续只要替换 `public/logo.png`,品牌主图、favicon 和前台入口就会一起收口,不再发生“只改一处、别处漏掉”的漂移 - -- 把首页空态输入区的运行时可见性从“收得过头”拉回 current 平衡点:恢复折叠态只读 `当前模型` pill,但继续把真正的模型切换收在 `高级设置`,避免首页和工作区输入栏继续出现状态感知不一致: - - 已更新: - - `src/components/agent/chat/components/EmptyStateComposerPanel.tsx` - - `src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 首页折叠态当前会和工作区输入栏一样显示只读 `当前模型` badge,帮助用户在发出第一句前确认本轮运行基线 - - badge 当前只承担“可见但不打扰”的状态确认职责,不恢复旧版折叠态下的模型选择器,也不把 `Provider / Model` 再抬回首页主路径 - - 因此 `P1` 的 current 口径应修正为:默认继续隐藏进阶控制,但不再把模型状态藏到完全不可见 - -- 把 `P2:Skill-First 前台` 里首批 curated skills 真正推进到“默认前台可发现 + 完整合同表达”,不再停留在“catalog 里有 6 个定义,但首页默认只露 4 个,且缺少结果去向”的半收口状态: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskTemplates.ts` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `src/lib/deepLink/websiteLaunch.ts` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `curatedTaskTemplates` 当前新增 `resultDestination`,并把它和 `requiredInputs / optionalReferences / outputContract / followUpActions` 一起收成同一份 current skill 合同事实源 - - 首页 `结果模板` 当前默认展示完整首批 6 个 curated skills,不再只有 4 个默认前排、另外 2 个只在推荐信号抬升时才露出 - - 技能页 `先拿结果` 当前也同步展示这 6 个入口;`脚本转口播/字幕稿` 与 `复盘这个账号/项目` 不再处于半隐藏状态 - - 首页缩略 meta、slash 面板里的结果模板描述、技能页 `先拿结果` 卡片,以及 `CuratedTaskLauncherDialog` 底部合同区,当前都会显式展示 `结果去向` - - 这一步继续服务 `P2` 主目标:让首页、技能页和输入层共享的不只是 `curated_task` id,而是完整的 current 前台 skill 合同与默认发现面 - - 当前已确认通过: - - `npx vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/utils/curatedTaskRecommendationSignals.test.ts"` - - `npm run typecheck` - - `npm run verify:local` - - 当前补充说明: - - 本轮 `verify:local` 已实际覆盖版本一致性、`lint`、`typecheck`、Vitest smart 40/40、`cargo test --manifest-path src-tauri/Cargo.toml`、以及 `verify:gui-smoke` - - `verify:gui-smoke` 末尾的 `agent-runtime-tool-surface-page` 本轮继续打印 `hasRuntimeSummary=true`,说明这次不只是列表层或卡片层修改,而是 current GUI 主路径完整可交付 - -- 把 `P2:Skill-First 前台` 当前主链最后的 GUI 交付门槛恢复到可用状态:`verify:gui-smoke` 现在既能自我避开损坏 cargo target,也已经重新通过完整 smoke 链: - - 已更新: - - `scripts/verify-gui-smoke.mjs` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `verify:gui-smoke` 当前新增 sqlite 构建产物自检;若目标 `cargo target` 下存在 `debug/build/libsqlite3-sys-*/out` 但缺少 `bindgen.rs`,脚本不再复用该目录,也不做破坏性删除,而是自动切到同级新的 `*-rebuild--` target - - 默认超时当前也会基于“最终实际使用的 cargo target”重新计算;未显式传 `--timeout-ms` 时,切到 fresh target 后会自动回到冷启动超时,不再沿用旧 warm target 的较短等待 - - `agent-runtime-tool-surface-page` 当前已被页面级 smoke 与整套 GUI smoke 双重证明真实包含 `Runtime 能力摘要`;先前“摘要未出现”的判断已确认是环境/时序波动,不再构成 current 阻塞 - - 这一步属于 `P2` 的交付支撑修复,不是继续扩前台功能,而是把 current 主线从“代码已收口但 GUI smoke 被旧缓存与时序抖动误伤”拉回“统一门槛重新可交付” - - 当前已确认通过: - - `node --check "scripts/verify-gui-smoke.mjs"` - - `npx eslint "scripts/verify-gui-smoke.mjs"` - - `node scripts/verify-gui-smoke.mjs --app-url "http://127.0.0.1:1421/" --timeout-ms 600000 --cargo-target-dir "/var/folders/87/s6cpr7hd1_v43cs833x4s_900000gn/T/lime-gui-smoke-target"` 已实际打印: - - 发现损坏 sqlite 构建缓存 - - 自动切换到新的 `lime-gui-smoke-target-rebuild-*` 目录 - - 开始用 fresh target 拉起 headless Tauri 编译链 - - `node scripts/agent-runtime-tool-surface-page-smoke.mjs --timeout-ms 180000` - - `npm run verify:gui-smoke -- --timeout-ms 1200000` - - `npm run verify:local` - - 当前补充说明: - - 本机在强制 fresh 前端链路时,仍可能观察到 `Port 1420 is already in use` 这类 Vite 端口复用现象;但这已不再阻塞 current 统一校验,因为脚本现在会自动切开损坏 sqlite target,并优先复用健康的 headless 环境 - - `agent-runtime-tool-surface-page` 最近一次页面级 smoke 的总结值已明确为 `hasRuntimeSummary=true`,且 `hasSubagentGap / hasTaskGap / hasTeamGap / hasWebSearchGap / hasWorkbench` 均为 `true` - - 因此 `P2` 当前关于 GUI 交付的统一结论应更新为“脚本层自愈 + 完整 smoke 恢复”,而不是“仍受 sqlite / runtime summary 阻塞” - -- 把 `P2:Skill-First 前台` 里最后几条还没进入合同层的 current 前台入口继续收口,避免首页 continuation、技能页最近做法、我的方法库和输入层 installed skill 继续各说各的: - - 已更新: - - `src/components/skills/installedSkillPresentation.ts` - - `src/components/skills/installedSkillPresentation.test.ts` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `installed skill` 当前新增共享的轻量 projection helper,优先复用 `metadata.lime_when_to_use / lime_argument_hint`,兜底到 `description + 对话里继续补充目标与约束 + 带着该方法进入生成主执行面` - - 首页 `继续上次做法` 当前不再只留标题;结果模板与 service skill 都会直接显示 `需要 / 交付` 缩略事实 - - 技能页 `继续常用做法` 当前补齐 `你来给 / 会拿到 / 结果去向`,`我的方法库` 也不再只是 `名字 + 描述 + /key` - - `@ / /` 输入层里的 installed skill 当前也回到同一套轻量 skill 合同,不再保留一条纯 description 链 - - 这一步继续服务 `P2` 的主目标:让首页、技能页和输入层共享的不只是 capability id,而是统一的 current 前台 skill 解释层 - - 当前已确认通过: - - `npm exec vitest run "src/components/skills/installedSkillPresentation.test.ts" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/skills/installedSkillPresentation.ts" "src/components/skills/installedSkillPresentation.test.ts" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run verify:local` - - 当前补充说明: - - `verify:local` 当前已经完整通过;前端、Vitest、`cargo test --manifest-path src-tauri/Cargo.toml` 与末尾 `verify:gui-smoke` 均为绿色 - - 因此这条 `installed skill` 合同收口当前已达到 Lime 的 current 可交付门槛,不再保留“GUI smoke 仍受 sqlite/bindgen 阻塞”的旧结论 - -- 把 `P2:Skill-First 前台` 的 `service skill` 前台合同投影接回与 `curated_task` 同一套 current 事实源,避免首页、输入层、技能页继续各讲各的: - - 已更新: - - `src/components/agent/chat/service-skills/skillPresentation.ts` - - `src/components/agent/chat/service-skills/skillPresentation.test.ts` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `service skill` 当前新增共享的 capability description helper,统一输出 `promise + 需要 + 交付` - - 首页 `快捷做法` 的缩略 meta、`@` 面板里的 service skill 描述、技能页组内做法卡片,当前都改成围绕同一套合同事实表达 - - 技能页组内卡片当前不再写 `入口`,而是显式展示 `你来给 / 会拿到 / 结果去向`,开始和 `curated_task` 的 skill 合同体验靠拢 - - 这一步继续服务 `P2` 第 2 条目标:让技能页、新建任务页和输入层共享的不只是 skill id,而是统一的 current 前台 skill 解释层 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/service-skills/skillPresentation.test.ts" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/agent/chat/service-skills/skillPresentation.ts" "src/components/agent/chat/service-skills/skillPresentation.test.ts" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run verify:local` - - 本次 `verify:local` 已实际覆盖 `verify:gui-smoke`,并跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - -- 把 `P2:Skill-First 前台` 里的 `curated_task` 启动事实与 skill 合同缩略投影继续收口到同一条 current 主链,避免首页、技能页、输入层只是“都能打开”,但仍各讲各的 skill: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskTemplates.ts` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 首页 `结果入口` 的缩略 meta 与 slash 面板里的结果模板描述,当前都改成共享 `buildCuratedTaskCapabilityDescription`;输入层里的结果模板不再只有一句 summary,而会同步暴露 `需要 / 交付` 的 current 缩略事实 - - 技能页桥接 `curated_task` 进入 `生成` 时,当前也会把 `referenceEntries` 一并带进 `initialInputCapability.capabilityRoute`,不再只有 `referenceMemoryIds` - - 到这里为止,首页、slash、技能页三条结果模板入口共享的不只是 `taskId + prompt`,还包括可回放的引用对象事实;首屏恢复与二次编辑 launcher 时,不会再出现某条链只剩 id 的分叉 - - 这一步继续服务 `P2` 第 2 条目标:让技能页、新建任务页和输入层共享同一 skill 事实源,而不是只共享模板目录 - - 当前已确认通过: - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npx eslint "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run verify:local` - - `npm run verify:gui-smoke` 已包含在本次 `verify:local` 中,并实际跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - - 这意味着之前日志里提到的 `site_capability_service` Rust 既有失败,当前已不再是本轮主线的有效阻塞状态 - -- 把 `生成` 后的 Team / Canvas / Inputbar 首层提示继续收口到和 GeneralWorkbench 一致的 current 主执行面,避免刚把工作台改成结果对象视角,team runtime 首层又长回第二套任务命名: - - 已更新: - - `src/components/agent/chat/utils/teamWorkspaceCopy.ts` - - `src/components/agent/chat/components/TeamWorkbenchSummaryPanel.tsx` - - `src/components/agent/chat/components/TeamWorkspaceDock.tsx` - - `src/components/agent/chat/components/ChatSidebar.tsx` - - `src/components/agent/chat/workspace/useWorkspaceCanvasSceneRuntime.tsx` - - `src/components/agent/chat/components/Inputbar/components/InputbarWorkflowStatusPanel.tsx` - - `src/components/agent/chat/components/CanvasWorkbenchLayout.tsx` - - `src/components/agent/chat/components/team-workspace-board/TeamWorkspaceEmptyShellState.tsx` - - `src/components/agent/chat/components/team-workspace-board/TeamWorkspaceCanvasToolbar.tsx` - - `src/components/agent/chat/components/team-workspace-board/TeamWorkspaceCanvasStage.tsx` - - `src/components/agent/chat/components/team-workspace-board/teamWorkspaceBoardPresentationSelectors.ts` - - `src/components/agent/chat/team-workspace-runtime/formationDisplaySelectors.ts` - - `src/components/agent/chat/utils/teamWorkspaceCanvas.ts` - - `src/components/agent/chat/utils/contextualRecommendations.ts` - - `src/components/agent/chat/utils/contextualRecommendations.test.ts` - - `src/components/agent/chat/utils/agentTaskRuntime.test.ts` - - `docs/exec-plans/claude-code-agent-task-runtime-alignment-plan.md` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - Team Summary / Team Dock / Canvas team tab / workflow status 当前统一使用 `生成工作台 / 当前进展`,空态按钮与进入提示也不再把 team runtime 包装成另一套平级“任务视图” - - `可继续稿件 / 可继续版本 / 产出记录 / 执行经过` 这套结果对象语言,当前已经从首页、GeneralWorkbench 继续接到了 Team / Canvas / Inputbar 首层提示 - - 在用户已明确“不做兼容”的前提下,`contextualRecommendations` 当前也已删掉把 `任务工作台` 当成 team runtime 触发词的历史容忍,只保留 current 文案与真实 team 语义 - - 这一步继续服务 `P1:前台口径收口`,让 `生成` 后首层路径不再同时存在两套执行命名;current 事实源现在收敛为 `生成 -> 生成工作台 -> 当前进展` - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/TeamWorkspaceDock.test.tsx" "src/components/agent/chat/components/TeamWorkspaceBoard.test.tsx" "src/components/agent/chat/components/TeamWorkbenchSummaryPanel.test.tsx" "src/components/agent/chat/components/CanvasWorkbenchLayout.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/workspace/useWorkspaceCanvasSceneRuntime.test.ts" "src/components/agent/chat/components/team-workspace-board/TeamWorkspaceCanvasSurfaceCopy.test.tsx" "src/components/agent/chat/components/team-workspace-board/TeamWorkspaceTeamOverviewChrome.test.tsx" "src/components/agent/chat/components/team-workspace-board/teamWorkspaceBoardPresentationSelectors.test.ts" "src/components/agent/chat/components/team-workspace-board/useTeamWorkspaceBoardShellProps.test.tsx" "src/components/agent/chat/components/team-workspace-board/teamWorkspaceBoardPropBuilders.test.ts" "src/components/agent/chat/components/team-workspace-board/useTeamWorkspaceBoardCanvasRuntime.test.tsx" "src/components/agent/chat/team-workspace-runtime/formationDisplaySelectors.test.ts" "src/components/agent/chat/utils/contextualRecommendations.test.ts" "src/components/agent/chat/utils/agentTaskRuntime.test.ts"` - - `npm run verify:local` - -- 把仓库其余仍会直接暴露给用户的旧 `任务工作台 / 任务视图` 文案继续收尾一刀,避免主链已换成 current 口径,旁路设置页还把用户拉回旧语境: - - 已更新: - - `src/components/settings-v2/system/automation/index.tsx` - - `src/components/settings-v2/system/automation/index.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 自动化设置页当前不再暴露 `打开任务工作台`,而是统一改成 `打开自动化工作台` - - workspace-only 描述当前也不再写 `默认进入任务视图`,而是改成 `默认进入当前进展` - - 这一步属于 P1 的旁路收尾:不是继续扩主链,而是防止 current 主词在其他真实前台页面被旧词反向污染 - - 当前已确认通过: - - `npm exec vitest run "src/components/settings-v2/system/automation/index.test.tsx"` - - `npx eslint "src/components/settings-v2/system/automation/index.tsx" "src/components/settings-v2/system/automation/index.test.tsx"` - -- 把 team runtime 里仍像“第二套任务面板系统”的 copy 继续收口到 `当前进展` 语义,避免 `生成工作台` 下面又长出另一套旧前台命名: - - 已更新: - - `src/components/agent/chat/team-workspace-runtime/formationDisplaySelectors.ts` - - `src/components/agent/chat/team-workspace-runtime/formationDisplaySelectors.test.ts` - - `src/components/agent/chat/team-workspace-runtime/boardChromeSelectors.ts` - - `src/components/agent/chat/team-workspace-runtime/boardChromeSelectors.test.ts` - - `src/components/agent/chat/components/team-workspace-board/TeamWorkspaceCanvasToolbar.tsx` - - `src/components/agent/chat/components/team-workspace-board/TeamWorkspaceEmptyShellState.tsx` - - `src/components/agent/chat/components/team-workspace-board/SelectedSessionInlineHeader.tsx` - - `src/components/agent/chat/components/team-workspace-board/teamWorkspaceBoardPresentationSelectors.ts` - - `src/components/agent/chat/components/team-workspace-board/TeamWorkspaceTeamOverviewControls.tsx` - - `src/components/agent/chat/components/team-workspace-board/TeamWorkspaceCanvasSurfaceCopy.test.tsx` - - `src/components/agent/chat/components/team-workspace-board/TeamWorkspaceTeamOverviewChrome.test.tsx` - - `src/components/agent/chat/components/team-workspace-board/teamWorkspaceBoardPresentationSelectors.test.ts` - - `src/components/agent/chat/components/TeamWorkspaceBoard.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - Team runtime 默认空态与画布提示当前不再写 `任务面板 / 任务摘要视图`,而是统一改成 `当前进展面板 / 进展摘要视图` - - canvas toolbar 与紧凑控制条当前不再写 `聚焦任务`,而是统一改成 `聚焦进展` - - lane 数、overview subtitle 与 selected session CTA 当前也不再写 `X 项任务已接入 / 打开任务 / 切换任务`,而是统一改成 `X 条当前进展已接入 / 打开进展 / 切换进展` - - 这一步继续服务 P1:不是否认 team runtime 里真实存在的任务拆分,而是把用户一眼看到的执行对象继续固定回 `当前进展` - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/team-workspace-runtime/formationDisplaySelectors.test.ts" "src/components/agent/chat/team-workspace-runtime/boardChromeSelectors.test.ts" "src/components/agent/chat/components/team-workspace-board/TeamWorkspaceCanvasSurfaceCopy.test.tsx" "src/components/agent/chat/components/team-workspace-board/TeamWorkspaceTeamOverviewChrome.test.tsx" "src/components/agent/chat/components/team-workspace-board/teamWorkspaceBoardPresentationSelectors.test.ts" "src/components/agent/chat/components/team-workspace-board/useTeamWorkspaceBoardCanvasRuntime.test.tsx" "src/components/agent/chat/components/TeamWorkspaceBoard.test.tsx"` - - `npx eslint "src/components/agent/chat/team-workspace-runtime/formationDisplaySelectors.ts" "src/components/agent/chat/team-workspace-runtime/boardChromeSelectors.ts" "src/components/agent/chat/components/team-workspace-board/TeamWorkspaceCanvasToolbar.tsx" "src/components/agent/chat/components/team-workspace-board/TeamWorkspaceEmptyShellState.tsx" "src/components/agent/chat/components/team-workspace-board/SelectedSessionInlineHeader.tsx" "src/components/agent/chat/components/team-workspace-board/teamWorkspaceBoardPresentationSelectors.ts" "src/components/agent/chat/components/team-workspace-board/TeamWorkspaceTeamOverviewControls.tsx" "src/components/agent/chat/team-workspace-runtime/formationDisplaySelectors.test.ts" "src/components/agent/chat/team-workspace-runtime/boardChromeSelectors.test.ts" "src/components/agent/chat/components/team-workspace-board/TeamWorkspaceCanvasSurfaceCopy.test.tsx" "src/components/agent/chat/components/team-workspace-board/TeamWorkspaceTeamOverviewChrome.test.tsx" "src/components/agent/chat/components/team-workspace-board/teamWorkspaceBoardPresentationSelectors.test.ts" "src/components/agent/chat/components/TeamWorkspaceBoard.test.tsx"` - -- 把 `生成现场` 与 topic switch 的边缘提示继续去任务化,避免主流程已经换词,继续入口和错误提示还在回退旧任务系统语境: - - 已更新: - - `src/components/agent/chat/components/ChatSidebar.tsx` - - `src/components/agent/chat/components/ChatSidebar.test.tsx` - - `src/components/agent/chat/workspace/useWorkspaceTopicSwitch.ts` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - task-center continuation 的 fallback 动作当前不再写 `打开任务`,而是改成和 `生成现场` 对齐的 `打开现场` - - topic switch 失败 toast 当前也不再写 `切换任务失败 / 加载任务失败`,而是统一改成 `切换会话失败 / 加载会话失败` - - 这一步继续服务 P1 的边缘收口:哪怕只是在失败或 fallback 场景里,也尽量避免把默认 `生成` 链重新讲成任务系统 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/team-workspace-runtime/boardChromeSelectors.test.ts" "src/components/agent/chat/components/ChatSidebar.test.tsx"` - - `npx eslint "src/components/agent/chat/team-workspace-runtime/boardChromeSelectors.ts" "src/components/agent/chat/team-workspace-runtime/boardChromeSelectors.test.ts" "src/components/agent/chat/components/ChatSidebar.tsx" "src/components/agent/chat/components/ChatSidebar.test.tsx" "src/components/agent/chat/workspace/useWorkspaceTopicSwitch.ts"` - -- 把 `生成` 后工作台里偏工程的对象名继续收口成结果对象视角,避免首页已经在讲“结果去向 / 继续上次做法”,一进入工作台又退回 `任务 / 分支 / 过程记录` 语境: - - 已更新: - - `src/components/agent/chat/components/GeneralWorkbenchSidebarShell.tsx` - - `src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx` - - `src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `任务工作台` 当前已改成 `生成工作台`,`任务视图` 当前已改成 `当前进展`,把 `生成` 固定为用户理解里的主执行面 - - `相关分支 / 相关版本` 当前已收成 `可继续稿件 / 可继续版本`,让用户优先理解“从哪一稿继续”,而不是先理解工程分支对象 - - `任务记录 / 过程记录` 当前已收成 `产出记录 / 执行经过`,并继续与首页 `结果去向` 的说明保持同一套结果对象语言 - - 这一步继续服务 `P1:首页默认复杂度收口`,但重点已经从首页进一步推进到 `生成` 后第一屏,让用户在执行面里也默认看到“结果 / 下一步 / 继续入口”,而不是后台对象名 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` - - `npx eslint "src/components/agent/chat/components/GeneralWorkbenchSidebarShell.tsx" "src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx" "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` - - `npm run verify:local` - - `npm run verify:gui-smoke` 已包含在本次 `verify:local` 中,并实际跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - -- 把 `生成` 后的进展摘要卡补成“结果去向 / 从哪里继续”的轻接线,避免首页提示一消失,用户又不知道结果会去哪: - - 已更新: - - `src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx` - - `src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 顶部摘要卡当前会继续提示:主稿、任务文件和运行产物会沉淀到下方 `产出记录 / 执行经过` - - 需要继续修改时,用户当前也能直接从 `可继续稿件/版本` 或首页 `继续上次做法` 这两个入口理解“从哪里接着跑” - - 这一步继续服务 `P1:首页默认复杂度收口`,但落点已经从首页延伸到 `生成` 后的结果/工作台首屏,让“结果不会丢、下次从哪里继续”不再只停留在首页一句提示里 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` - - `npx eslint "src/components/agent/chat/components/GeneralWorkbenchWorkflowPanel.tsx" "src/components/agent/chat/components/GeneralWorkbenchSidebar.test.tsx"` - - `npm run verify:local` - - `npm run verify:gui-smoke` 已包含在本次 `verify:local` 中,并实际跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - -- 把 `新建任务` 首页剩余非核心块继续收成“有真实收益才露出”的 current 显隐规则: - - 已更新: - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyStateSceneAppsPanel.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `更多起手方式` 当前不再因为“还有目录页可进”就默认露出;只有当前真有可直接启动的整套做法,或用户确实可以“继续最近做法”时,这块才出现 - - `支撑能力` 当前也不再因为“系统里有技能”就默认露出;只有浏览器接入、站点自动接入型做法,或最近沉淀出的复用方法形成直接收益时,才继续显示摘要层 - - 这一步继续服务 `P1:首页默认复杂度收口`,目标是避免首页在推荐层收完之后,又被“目录入口 / 能力目录”重新长回平台分层感 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyStateSceneAppsPanel.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npm run verify:local` - - `npm run verify:gui-smoke` 已包含在本次 `verify:local` 中,并实际跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - -- 把 `新建任务` 首页 `结果模板` 从同权 6 条入口继续收成“首选结果 + 更多结果 + 快捷做法”的强弱分层: - - 已更新: - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `结果模板` 当前不再把 4 条 curated task 与 2 条 service skill 以同一层级平铺给用户,而是改成: - - `首选结果`:默认先看最常用、最泛用的 2 条结果入口 - - `更多结果`:保留其余结果模板,作为第二层补充选择 - - `快捷做法`:把现成 service skill 收成捷径层,不再与结果模板混成同一层 - - 这一步继续服务 P1 的首页默认复杂度收口,只做首页结果 shelf 的层级优化,不改运行时协议、不改 skill / launcher 主链 - - 首页当前更接近“先给用户一个最该点的结果入口”,而不是“把所有能点的入口平铺出来” - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npm run verify:local` - - `npm run verify:gui-smoke` 已包含在本次 `verify:local` 中,并实际跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - -- 把 `新建任务` 首页 `结果入口` 继续补成“知道怎么开始,也知道结果会去哪”的轻闭环提示: - - 已更新: - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyStateSceneAppsPanel.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `结果入口` 当前已新增轻量 `结果去向` 提示,明确本轮产出会沉淀到当前任务/项目,跑通过的方法会回到 `继续上次做法`,参考与反馈会继续影响下一轮推荐 - - 这一步继续服务 P1 的首页默认复杂度收口:不是再开一个结果面,而是在首页先把“结果不会丢、下次从哪继续”说清楚 - - `更多起手方式` 当前也把说明文案再压短一层,继续保持补位入口,不重新长成解释性大块 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyStateSceneAppsPanel.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npm run verify:local` - - `npm run verify:gui-smoke` 已包含在本次 `verify:local` 中,并实际跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - -- 把 `新建任务` 首页原来平级的 `结果模板` + `继续上次做法` 收成同一个 `结果入口` shelf,继续减少首页块级切换感: - - 已更新: - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 首页 supporting 区当前不再把 `结果模板` 和 `继续上次做法` 渲染成两个平级面板,而是先收成一个总标题为 `结果入口` 的 unified shelf - - `结果入口` 内部当前分成两个 section:上半段负责“先拿什么结果”,下半段负责“最近跑过什么做法”;空态时也在同一个容器里提示,不再额外长出独立空块 - - `更多起手方式` 与 `支撑能力` 当前都退到 `结果入口` 后面,首页默认视觉重心继续稳定在 `目标输入 + 当前项目 + 结果入口` - - 这一步仍属于 P1 的首页默认复杂度收口,只改前台组合层,不改协议、不改后端、不改 `curated_task capability route` - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npm run verify:local` - - `npm run verify:gui-smoke` 已包含在本次 `verify:local` 中,并实际跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - -- 把 `新建任务` 首页底部的能力目录感继续收口一刀,改成“默认结果入口 + 按需展开支撑能力”的 current 前台结构: - - 已更新: - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyStateHero.tsx` - - `src/components/agent/chat/components/EmptyStateSceneAppsPanel.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 首页底部 `我的方法 / 持续流程 / 任务拆分 / 浏览器接入` 4 张大卡当前不再默认常显,而是收成一个轻量 `支撑能力` 摘要层;用户需要时再手动展开 - - `支撑能力` 摘要层当前会保留 `methodSummaryLabel`,并继续提供轻量 `连接浏览器` 快捷入口,避免把能力完全藏死 - - `EmptyStateHero` 当前只会在确实有卡片需要显示时才渲染底部卡片区,不再为空壳占位 - - 原 `创作场景` 区当前进一步降成 `更多起手方式`,明确它只是补位入口;如果用户已经知道想拿什么结果,优先走上方结果模板 - - 这一步仍属于 P1 的首页默认复杂度收口,不改协议、不改后端,只继续压低首页“能力超市 / 平台目录”观感 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyStateHero.tsx" "src/components/agent/chat/components/EmptyStateSceneAppsPanel.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npm run verify:local` - - `npm run verify:gui-smoke` 已包含在本次 `verify:local` 中,并实际跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - -- 把 `新建任务` 首页默认复杂度继续收口一刀,减少折叠态运行时噪音,稳住 `目标输入 + 项目 + 结果模板` 主入口: - - 已更新: - - `src/components/agent/chat/components/EmptyStateComposerPanel.tsx` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 首页输入区折叠态当前不再暴露 `当前模型` 轻提示,也不再在未展开时直接露出模型选择器;`Provider / Model / 权限模式 / Team` 继续统一收在 `高级设置` - - 首页 hero 徽标当前不再默认暴露 `执行模式 / 联网搜索` 等运行时状态,减少“系统控制台”观感 - - supporting 区当前改成 `结果模板 -> 继续上次做法 -> 创作场景补位` 的顺序,先让默认视觉重心回到结果入口 - - 这一步属于 P1 的首页默认复杂度收口,不改协议、不改后端,只继续压缩前台默认暴露 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npm run verify:local` - - `npm run verify:gui-smoke` 已包含在本次 `verify:local` 中,并实际跑通 `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - -- 把 `curated task` featured 推荐从“固定 4 张卡”推进成“静态 base + 当前参考/最近保存信号”的 P3 第二刀,打通 `当前参考 / 保存灵感 -> 下一轮推荐` 回流: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskRecommendationSignals.ts` - - `src/components/agent/chat/utils/curatedTaskRecommendationSignals.test.ts` - - `src/components/agent/chat/utils/curatedTaskTemplates.ts` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 首页空态与技能页 `先拿结果` 当前都会围绕 `projectId + 当前 referenceEntries + 最近保存灵感` 重新计算 featured 推荐 - - 推荐信号当前分成两类:`active_reference` 负责表达当前线程/launcher 已带入的参考对象;`saved_inspiration` 负责表达最近保存到灵感库的条目 - - `保存到灵感库` 成功后,当前会立刻记录推荐信号并广播刷新事件;featured 推荐不再依赖 memory 的旧 `updated_at` - - 推荐排序继续保留默认 4 张结果模板的 base 骨架,但强信号可以把 `account-project-review` 等非默认模板抬进前排,并给出“围绕当前参考 / 围绕最近收藏或偏好”等理由提示 - - 到这里为止,P3 已从“灵感带入生成”继续推进到“生成内保存与当前带入,都会影响下一轮结果模板建议” - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/utils/curatedTaskRecommendationSignals.test.ts" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/agent/chat/utils/curatedTaskRecommendationSignals.ts" "src/components/agent/chat/utils/curatedTaskRecommendationSignals.test.ts" "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx"` - - `npm run typecheck` - - `npm run verify:local` - -- 把 `creation_replay` 从“后台预填对象”推进成 `生成主执行面` 里的 current 前台对象,并打通 `灵感库 -> 生成 -> 结果模板默认引用回流` 这条 P3 第一刀: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskReferenceSelection.ts` - - `src/components/agent/chat/utils/creationReplaySurface.ts` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` - - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/agent/chat/components/Inputbar/components/InputbarComposerSection.tsx` - - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` - - `src/components/agent/chat/components/Inputbar/index.tsx` - - `src/components/agent/chat/workspace/useWorkspaceInputbarSceneRuntime.tsx` - - `src/components/agent/chat/components/EmptyStateComposerPanel.tsx` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/workspace/chatSurfaceProps.ts` - - `src/components/agent/chat/workspace/WorkspaceConversationScene.tsx` - - `src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx` - - `src/components/agent/chat/workspace/WorkspaceConversationScene.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `creation_replay` 当前不再只在 scene gate / service skill 里被内部消费;`生成主执行面` 已开始把它显影成“当前带入灵感 / 技能草稿”对象 - - 首页空态输入区当前也会露出同一条轻量提示,避免用户只在 entry banner 里看一次就丢 - - 从灵感库进入 `生成` 时带入的 `memory_entry creation_replay`,当前会自动成为结果模板 launcher 的默认 reference seed - - 这条默认 seed 既会作用于首页结果模板,也会作用于 slash 面板里的结果模板 - - launcher 当前会合并保留 seed entry 与最近灵感列表;即使该条灵感不在最近列表中,也不会被静默丢掉 - - `curated_task capabilityRoute` 当前也已开始保留 `referenceEntries`,保证页面 bootstrap / 首屏恢复 / 再次编辑 launcher 时不只剩 id - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx" "src/components/agent/chat/workspace/WorkspaceConversationScene.test.tsx"` - - `npx eslint "src/components/agent/chat/utils/curatedTaskReferenceSelection.ts" "src/components/agent/chat/utils/creationReplaySurface.ts" "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/components/Inputbar/components/InputbarComposerSection.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/index.tsx" "src/components/agent/chat/workspace/useWorkspaceInputbarSceneRuntime.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.tsx" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/workspace/chatSurfaceProps.ts" "src/components/agent/chat/workspace/WorkspaceConversationScene.tsx" "src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx" "src/components/agent/chat/workspace/WorkspaceConversationScene.test.tsx"` - -- 把 `curated task` 的“可选灵感引用”从静态文案补成 current typed contract,打通 `launcher -> route -> request metadata -> 生成` 最小闭环: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskReferenceSelection.ts` - - `src/components/agent/chat/utils/curatedTaskReferenceSelection.test.ts` - - `src/components/agent/chat/utils/curatedTaskTemplates.ts` - - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` - - `src/components/agent/chat/components/Inputbar/hooks/useInputbarSend.ts` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - launcher 当前会从灵感库最近更新中拉取候选项,允许在启动时附带轻量灵感引用 - - 这些引用会一起编进首轮 prompt,不再只是“可选参考”的说明文案 - - `curated_task capabilityRoute` 当前会正式保留 `referenceMemoryIds` - - 发送时会同步写入 `requestMetadata.harness.curated_task` - - 若存在引用,当前会把首条引用写进 `creation_replay`,以便后续主链继续消费 - - 到这里为止,`首页 / 技能页 / slash / 生成内编辑` 四个结果模板入口,当前都已经共享 `catalog + launcher + prompt compile + route + metadata` 这条 current 主链 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/utils/curatedTaskReferenceSelection.test.ts" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npx eslint "src/components/agent/chat/utils/curatedTaskReferenceSelection.ts" "src/components/agent/chat/utils/curatedTaskReferenceSelection.test.ts" "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/hooks/useInputbarSend.ts" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npm run verify:local` - -- 把 `生成主执行面` 里已经激活的 `curated task`,补成“可重新编辑启动信息”的完整闭环,不再只支持首发 launcher: - - 已更新: - - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` - - `src/components/agent/chat/components/Inputbar/index.tsx` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyStateComposerPanel.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` - - `src/components/agent/chat/skill-selection/CuratedTaskBadge.tsx` - - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/agent/chat/utils/curatedTaskTemplates.ts` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - 当前统一结论: - - `curated_task capabilityRoute` 当前会正式保留 `launchInputValues` - - 首页、slash、技能页桥接进 `生成` 后,active `curated_task` badge 都能重新打开同一套 launcher - - 重新编辑时会回填原始启动字段,并基于目录模板重新编译 prompt,不再拿“已经编译过一次的 prompt”继续套娃 - - `Inputbar` 与首页空态当前都共享这条“编辑 -> 回填 -> 更新 route”的 current 主链 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npx eslint "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/index.tsx" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/skill-selection/CuratedTaskBadge.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/utils/curatedTaskTemplates.ts"` - -- 把 slash 输入层里的 `curated task` 结果模板,也正式收口到同一套 `launcher -> curated_task capability -> 生成主执行面` 主链,不再保留“选择即写 base prompt”的输入层例外: - - 已更新: - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - 当前统一结论: - - slash 面板里的结果模板当前不再在选择瞬间把模板 prompt 直接塞回输入框 - - 选择后会先打开和首页、技能页同一套轻量 launcher,补齐 1 到 2 个最小启动字段 - - 确认后才会把编译后的 prompt 回填到输入框,并继续挂上 typed `curated_task capability` - - 到这里为止,`首页 / 技能页 / slash 输入层` 三个结果模板入口,当前已经同时共享 `catalog + launcher + capability route` 三层协议 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npx eslint "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - -- 把首页 `结果模板` 与 `继续上次做法` 里的结果模板,也正式收口到同一套 `curated task launcher -> 生成主执行面` 主链,不再保留“点卡片即直接写 prompt”的首页例外: - - 已更新: - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - 当前统一结论: - - 首页 `结果模板`、`继续上次做法` 里的结果模板,以及技能页 `先拿结果`,当前都已对齐到同一个轻量 launcher - - launcher 仍只负责补 1 到 2 个最小启动字段,然后把编译后的 prompt 通过 typed `curated_task capability` 带进 `生成` - - 因此首页不再是 `curated task` 主链里的特例;`skill-first` 前台当前对结果模板只有一条 current 启动协议 - - 文档里关于“首页继续快速起手、不走 launcher”的旧描述,当前也已同步清理 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npm run verify:local` - -- 把 `curated task` 从“展示 skill 合同”继续推进成“技能页可填写的最小 launcher”,让 `requiredInputs` 不再只是说明文案: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskTemplates.ts` - - `src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx` - - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - 当前统一结论: - - `curated task` 现在除了 `requiredInputs` 文案,还新增了真实可填写的 `requiredInputFields` - - 技能页 `先拿结果` 点击后,不再直接把模板 prompt 裸带进 `生成`,而是先打开轻量 launcher dialog - - 当前每条 curated task 只收 1 到 2 个最小启动字段,避免在技能页复制一整套重型 slot gate - - launcher 会通过 `buildCuratedTaskLaunchPrompt(...)` 把用户填写的启动信息编译进首轮 prompt,再继续走 typed `curated_task capability` - - 这意味着 P2 当前已经从“skill 合同可见”推进到“skill 合同可启动”,而不是继续停留在卡片说明层 - - 当前已确认通过: - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npx eslint "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npm run typecheck` - - `npm run governance:legacy-report` - - `npm run verify:local` - -## 2026-04-18 - -### 已完成 - -- 把 `curated task` 从“typed capability 可发送”继续推进成“前台可理解的 skill 合同对象”,补齐 `你来给 / 可选参考 / 会拿到 / 下一步` 四类事实,并同步回首页与技能页: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskTemplates.ts` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - 当前统一结论: - - `curated task` 当前不再只有 `title / summary / prompt` 这类轻量模板字段,而是已补齐: - - `requiredInputs` - - `optionalReferences` - - `outputContract` - - `followUpActions` - - 首页 `结果模板` 当前已开始展示“需要什么输入、会拿到什么交付”的缩略事实,不再只是标题列表 - - 技能页 `先拿结果` 当前已开始展示更完整的 skill 合同视图,用户能在进入 `生成` 之前先理解: - - 自己需要补什么 - - 可选参考能带什么 - - 这条 skill 会产出什么 - - 产出后还能怎么继续 - - 因此 `curated task` 当前已更接近 V2 设定里的正式 skill launcher,而不是仅靠 prompt 命名的“结果模板按钮” - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npx eslint "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/components/EmptyState.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npm run typecheck` - - `npm run governance:legacy-report` - - `npm run verify:gui-smoke` - -- 把 `curated task` 从共享 prompt catalog 继续推进成 current typed capability,补齐 `首页 / 技能页 / slash / Inputbar 首屏恢复` 同一条 route: - - 已更新: - - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` - - `src/components/agent/chat/workspace/inputCapabilityRouting.ts` - - `src/components/agent/chat/skill-selection/CuratedTaskBadge.tsx` - - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` - - `src/components/agent/chat/components/EmptyStateComposerPanel.tsx` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/AppPageContent.tsx` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `src/components/AppPageContent.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - 当前统一结论: - - `curated task` 当前已正式进入 `InputCapabilitySelection / InputCapabilitySendRoute / initialInputCapability` 主链,不再只是 prompt catalog - - 首页点结果模板后,当前不只是把 prompt 写进输入框,也会挂上 `curated_task` active capability;发送时会透传结构化 route - - 技能页 `先拿结果` 当前不再依赖 `initialUserPrompt` 进 `生成`,而是像 installed skill 一样走 typed `initialInputCapability` - - slash 面板里的结果模板当前会同时做两件事:回填用户可见 prompt,并激活 `curated_task` capability - - `Inputbar` 首屏恢复当前已支持 `curated_task`;如果输入为空,会自动预填 route 内 prompt,并展示 badge - - `AppPageContent` 当前也已把 `curated_task` 纳入页面 key 序列化;切换不同模板时不会复用旧工作区实例 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/AppPageContent.test.tsx"` - - `npx eslint "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/workspace/inputCapabilityRouting.ts" "src/components/agent/chat/skill-selection/CuratedTaskBadge.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/EmptyStateComposerPanel.tsx" "src/components/agent/chat/components/EmptyState.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/AppPageContent.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/AppPageContent.test.tsx"` - - `npm run typecheck` - - `npm run governance:legacy-report` - - `npm run verify:gui-smoke` - -- 把 `结果模板` 从首页私有推荐 util 提升成共享 `curated task catalog`,并同时接回 `新建任务 / 我的方法 / slash 输入层` 三个前台入口: - - 已更新: - - `src/components/agent/chat/utils/curatedTaskTemplates.ts` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - 当前统一结论: - - 首页里的 `结果模板` 不再只是一组 `EmptyState` 私有 prompt 推荐;现在它已经被收成共享 `curated task catalog` - - `我的方法` 页右侧新增了 `先拿结果` 桥接区;因此结果模板不再只存在于首页,技能页也能用同一套 curated task 把用户带回 `生成` - - `@ / /` 输入层当前也会展示同一套 curated task;slash 选择后会把模板 prompt 回填到输入框并记录最近使用,不再只有 runtime scene 能占据 `结果模板` 分组 - - 到这里为止,`首页结果模板 / 技能页桥接入口 / slash 结果模板` 已共用同一份前台事实源;`结果模板` 不再在三个入口里各讲各的话 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npx eslint "src/components/agent/chat/utils/curatedTaskTemplates.ts" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npm run typecheck` - -- 把 `AppPageContent` 这一层壳也补回 `initialInputCapability` current 主链,避免技能页直达生成时在页面分发层丢参或错误复用旧工作区实例: - - 已更新: - - `src/components/AppPageContent.tsx` - - `src/components/AppPageContent.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenextv2/runtime-architecture.md` - - 当前统一结论: - - `AgentPageParams.initialInputCapability` 当前不再只停留在页面参数类型和 `AgentChatPage` 直接测试里;`AppPageContent` 已正式透传这层 bootstrap 给 `AgentChatPage` - - `AppPageContent` 当前也已把 `initialInputCapability` 纳入 `AgentChatPage` key;因此从技能页或其他入口连续切换不同 installed skill / capability 时,会重建对应工作区实例,而不是偷偷复用上一条 current capability - - 到这里为止,`技能页 -> 页面路由 -> Agent 壳 -> Inputbar 首屏恢复` 这条 current 主链已经闭合,不再只有中间层正确、页面壳层漏参 - - 当前已确认通过: - - `npm exec vitest run "src/components/AppPageContent.test.tsx" "src/components/agent/chat/index.shell-routing.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/AppPageContent.tsx" "src/components/AppPageContent.test.tsx"` - - `npm run typecheck` - - `npm run governance:legacy-report` - - `npm run verify:gui-smoke` - -- 把 `技能页 / 新建任务页 -> 生成` 的 installed skill 入口也收口到 typed capability bootstrap,不再让“我的方法库”继续停留在被动展示: - - 已更新: - - `src/types/page.ts` - - `src/components/agent/chat/agentChatWorkspaceContract.ts` - - `src/components/agent/chat/workspaceEntry.ts` - - `src/components/agent/chat/index.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/agent/chat/workspace/useWorkspaceInputbarSceneRuntime.tsx` - - `src/components/agent/chat/components/Inputbar/index.tsx` - - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` - - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` - - `src/components/skills/SkillsWorkspacePage.tsx` - - `src/components/agent/chat/workspaceEntry.test.ts` - - `src/components/agent/chat/index.shell-routing.test.tsx` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `src/components/skills/SkillsWorkspacePage.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenextv2/runtime-architecture.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - 当前统一结论: - - `service skill` 继续通过 `initialPendingServiceSkillLaunch` 进入 `生成` 内 A2UI 补参主链;而 `installed skill` 当前则统一通过 `initialInputCapability` 恢复首屏 active capability - - `Inputbar` 当前可以在首屏根据 typed `capabilityRoute` 恢复 `builtin_command / installed_skill / runtime_scene`,因此从技能页进入 `生成` 不再需要伪造 `/` 文本 - - `我的方法库` 里的已安装 skill 当前已经不再只是目录卡,而是可以像 current curated service skill 一样,直接把用户带进 `生成` 主执行面 - - `AgentChatPage` / `workspaceEntry` 当前也已把 `initialInputCapability` 视为 direct workspace intent;因此新建任务入口不会再把这类请求误判成“空白首页” - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/workspaceEntry.test.ts" "src/components/agent/chat/index.shell-routing.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run typecheck` - - `npx eslint "src/types/page.ts" "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/agentChatWorkspaceContract.ts" "src/components/agent/chat/workspaceEntry.ts" "src/components/agent/chat/index.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/workspace/useWorkspaceInputbarSceneRuntime.tsx" "src/components/agent/chat/components/Inputbar/index.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/workspaceEntry.test.ts" "src/components/agent/chat/index.shell-routing.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run governance:legacy-report` - - `npm run verify:gui-smoke` - -- 把 `EmptyStateComposerPanel -> CharacterMention` 也收口到统一 capability 选择边界,不再让首页输入壳保留旧 `onSelectSkill` 主语义: - - 已更新: - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyStateComposerPanel.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenextv2/runtime-architecture.md` - - 当前统一结论: - - 首页输入壳当前也会像工作区 `Inputbar` 一样,把 `CharacterMention` 选择统一回调为 `onSelectInputCapability` - - 首页当前不只支持已安装 skill 的结构化发送,也支持 builtin command / runtime scene 的激活态显示、清除与结构化 route 透传 - - 因此 `EmptyState` 不再是“发送链统一、输入选择层仍旧语义”的半收口状态;首页 capability 主链当前已从选择、展示到发送保持同一套判断 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx"` - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx"` - - `npm run typecheck` - -- 把 `Inputbar / EmptyState` 运行时页面里的 `skillSelection` 直构造也回收到共享绑定边界,补齐 governance 收口: - - 已更新: - - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/skill-selection/skillSelectionBindings.ts` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenextv2/runtime-architecture.md` - - 当前统一结论: - - `Inputbar / EmptyState` 当前不再在运行时代码里 direct `createSkillSelectionProps(...)`,而是统一回到共享 `skillSelectionBindings` 边界 - - 因此 current 主路径的页面层不再一边走 `activeCapability`,一边再偷偷拼一套旧 `skill selection` 运行时模型 - - 这一步补齐了治理守卫要求的 `skill-selection-direct-construction-runtime-usage`,避免后续 AI 继续从页面层长回旧选择协议 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/skill-selection/skillSelectionBindings.ts"` - - `npm run governance:legacy-report` - - `npm run typecheck` - -- 把 `EmptyState` 首页入口也接回统一 capability 主链,不再把已安装 skill 降级成文本前缀发送: - - 已更新: - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.tsx` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenextv2/runtime-architecture.md` - - 当前统一结论: - - 首页空态当前不再使用 `useActiveSkill / wrapTextWithSkill` 把已安装 skill 拼成 `/ ...` 文本后再发送,而是改为与 `Inputbar` 同源的 `capabilityRoute + displayContent` - - `handleSendFromEmptyState` 当前已支持把结构化 `sendOptions` 继续交给主发送链;因此首页入口与工作区输入栏不再各说一套发送协议 - - 首页在“先选 installed skill,再切到 service skill / 做法卡 / 服务技能入口”时,当前会主动清掉旧 capability,不再残留过期 skill route - - 到这里为止,`生成` current 主路径里至少两条核心入口已经统一到同一套 capability 语义: - - 工作区 `Inputbar` - - 首页 `EmptyState` - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.test.ts"` - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - -- 把 `CharacterMention -> Inputbar` 的能力选择事件也收口成单一 current 边界,不再让 builtin / scene / installed skill 在主路径里各走一套接线: - - 已更新: - - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `src/components/agent/chat/components/Inputbar/components/InputbarComposerSection.tsx` - - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` - - `src/components/agent/chat/components/Inputbar/index.tsx` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenextv2/runtime-architecture.md` - - 当前统一结论: - - `Inputbar` 当前不再分别向 `CharacterMention` 透传 `onSelectBuiltinCommand / onSelectSceneCommand / onSelectSkill` 三套能力选择回调,而是统一改用 `onSelectInputCapability` - - `CharacterMention` 当前已支持把 `builtin_command / installed_skill / runtime_scene` 统一回调给父层 current 主路径;因此 `InputbarController` 内部的 active capability 不再需要靠三条并行接线去维持 - - `service skill / A2UI` 补参分支仍然保持独立入口;这条例外只服务必填 slot gate,不再影响“生成只有一条 capability 主链”的判断 - - 到这里为止,current 主路径的统一 capability 边界已经同时进入: - - 输入层 active capability 状态 - - 面板到输入栏的选择事件边界 - - 发送链的结构化 route 恢复 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npx eslint "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/Inputbar/components/InputbarComposerSection.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/index.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - -- 把 slash 面板里的已安装技能也接回 `activeCapability`,继续压缩“输入层文本回填”和“发送链结构化路由”之间的缝: - - 已更新: - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenextv2/runtime-architecture.md` - - 当前统一结论: - - slash 面板里的 `installed skill` 当前在存在父层 `onSelectSkill` 接管时,不再默认回填 `/` 文本,而是改成与 `runtime_scene` 相同的 active capability 语义 - - 最近使用的 slash skill 当前也会优先把 `replayText` 回填为用户可见正文,再切到 active skill;因此“最近使用”不再偷偷把内部 `/skill-key` 路由文本重新写回输入框 - - 未提供父层接管时,slash installed skill 仍保持原 fallback:继续回填 `/`,所以这刀没有打断独立 `CharacterMention` 的旧使用方式 - - 到这里为止,输入层的 current capability 语义已经对齐到三类主对象: - - `builtin_command` - - `installed_skill` - - `runtime_scene` - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npx eslint "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - -- 把 slash 面板里的 runtime scene 选择正式接进 `activeCapability`,让输入层与发送层对 scene 的理解不再分叉: - - 已更新: - - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `src/components/agent/chat/components/Inputbar/components/RuntimeSceneBadge.tsx` - - `src/components/agent/chat/components/Inputbar/components/InputbarComposerSection.tsx` - - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` - - `src/components/agent/chat/components/Inputbar/index.tsx` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - slash 面板里选择 `scene command` 时,如果不是“必填 slot 先交给 A2UI 补参”的场景,当前会像 builtin command 一样切换成 `activeCapability`,而不是继续把 `/scene-key` 前缀回填进输入框 - - runtime scene 当前已拥有和 builtin command / installed skill 对齐的输入层语义: - - 选择后保留用户正文输入 - - 顶部显示可清除 badge - - 发送时由 `capabilityRoute` 恢复内部路由文本 - - 成功后由发送链统一回写 slash recent usage - - 最近使用的 scene 当前也会优先把 `replayText` 回填为用户可见正文,并同时挂上 `runtime_scene` active capability,不再重新把 `/scene-key replayText` 写回输入框 - - 需要 `slot gate / A2UI` 的 scene 当前保持原路径:仍优先交给 `onSelectServiceSkill`,这刀不把 scene 补参 UX 和 active capability 混成一团 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npx eslint "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/Inputbar/components/RuntimeSceneBadge.tsx" "src/components/agent/chat/components/Inputbar/components/InputbarComposerSection.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/index.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - -- 把 `capabilityRoute` 从“发送前的结构化提示”继续推进成发送链内的第一版统一 capability router,并把 runtime scene 也纳入同一入口: - - 已更新: - - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` - - `src/components/agent/chat/workspace/inputCapabilityRouting.ts` - - `src/components/agent/chat/workspace/useWorkspaceSendActions.ts` - - `src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenextv2/runtime-architecture.md` - - 当前统一结论: - - `Inputbar` 继续只传 `displayContent + capabilityRoute`,不再回退去预拼 `@前缀`、`/skill-key` 或 scene 文本;真正的内部执行文本恢复点现在固定在 `useWorkspaceSendActions -> inputCapabilityRouting` - - `inputCapabilityRouting` 当前已统一承担三件事:恢复 builtin command / installed skill / runtime scene 的内部执行文本、推导 runtime scene 的结构化 route、产出 slash recent usage 的第一版统一结果 - - 纯文本输入的 `/scene-key ...` 当前也会在发送链内被推导成 `runtime_scene` route,再继续进入 `service_scene_launch` 主链;后续输入层如果直接给 scene route,也能复用同一条恢复逻辑 - - `executeSendPlan` 当前不再在发送后额外补一层“installed skill fallback usage”旁路;slash usage 统一从 plan 内的 `completedSlashUsage` 回写,避免 route 恢复与 usage 记录再次分叉 - - 当发送链因为默认参数补全等原因改写了真正 dispatch 文本时,`displayContent` 当前也会优先保留用户原始可见文案,不再被内部路由前缀污染 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx"` - - `npx eslint "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/workspace/inputCapabilityRouting.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - -- 把输入栏里“已选 capability 只是偷偷改写前缀文本”的旧做法继续收口成显式 dispatch route,并让发送链第一次吃到结构化的 active capability: - - 已更新: - - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` - - `src/components/agent/chat/hooks/handleSendTypes.ts` - - `src/components/agent/chat/components/Inputbar/hooks/useInputbarSend.ts` - - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` - - `src/components/agent/chat/components/Inputbar/index.tsx` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `src/components/agent/chat/workspace/useWorkspaceSendActions.ts` - - `src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `Inputbar` 当前在发送 active capability 时,不再只把能力压扁成 `@前缀` 或 `/skill-key` 文本;现在会同时透传结构化 `capabilityRoute` - - 已选 builtin command / installed skill 当前都会把原始输入保存在 `displayContent` 里,因此线程里展示给用户看的文案可以继续保持“我真正输入了什么”,而不是被路由前缀污染 - - `useWorkspaceSendActions` 当前已经开始消费这层 route:installed skill 成功发送后,会按显式 `capabilityRoute` 回写 slash 最近使用,不再只能依赖“用户是否手动输入了 `/skill-key ...`”去猜测 - - 这一步把 `active capability -> 发送链` 从“文本技巧”推进成了第一版结构化 current 路由,也给后面继续抽统一 capability router 留出了明确边界 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx"` - - `npx eslint "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/hooks/handleSendTypes.ts" "src/components/agent/chat/components/Inputbar/hooks/useInputbarSend.ts" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/index.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/workspace/useWorkspaceSendActions.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - -- 把 runtime scene 的匹配规则从“面板一套、发送链一套”收口成共享 scene binding helper,并补上完整 current 门槛验证: - - 已更新: - - `src/components/agent/chat/service-skills/runtimeSceneBinding.ts` - - `src/components/agent/chat/service-skills/runtimeSceneBinding.test.ts` - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/agent/chat/workspace/serviceSkillSceneLaunch.ts` - - `src/components/agent/chat/workspace/serviceSkillSceneLaunch.test.ts` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `CharacterMention` 当前不再自己维护 scene -> service skill 的匹配规则,slash 面板里“这个 scene 是否应回落成 service skill / A2UI 补参”统一改读 `runtimeSceneBinding` - - `serviceSkillSceneLaunch` 当前也不再单独维护 scene token、alias 与 `linkedSkillId` 的另一套判断;UI 面板和发送链对 `sceneKey / commandPrefix / aliases / linkedSkillId` 的理解已对齐 - - 这一步把 `生成` 主链里最容易漂移的一段 current 事实源先钉住:slash 发现面、scene 发射器和后续 service skill 回落不再各自解释“什么叫同一个场景” - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/service-skills/runtimeSceneBinding.test.ts" "src/components/agent/chat/workspace/serviceSkillSceneLaunch.test.ts" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npx eslint "src/components/agent/chat/service-skills/runtimeSceneBinding.ts" "src/components/agent/chat/service-skills/runtimeSceneBinding.test.ts" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/workspace/serviceSkillSceneLaunch.ts" "src/components/agent/chat/workspace/serviceSkillSceneLaunch.test.ts"` - - `npm run typecheck` - - `npm run verify:local` - -- 把 runtime capability catalog 从组件私有拼装继续收口成共享模块,并让输入面板与发送链各自读取同一套 current 目录选择器: - - 已更新: - - `src/components/agent/chat/skill-selection/runtimeInputCapabilityCatalog.ts` - - `src/components/agent/chat/skill-selection/runtimeInputCapabilityCatalog.test.tsx` - - `src/components/agent/chat/skill-selection/CharacterMention.tsx` - - `src/components/agent/chat/workspace/useWorkspaceSendActions.ts` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `CharacterMention` 当前不再自己订阅和组装 runtime skill catalog,而是统一改读 `useRuntimeInputCapabilityCatalog`;因此 `@` / `/` 面板里的 builtin command 与 runtime scene 列表不再是组件内私有事实源 - - `useWorkspaceSendActions` 当前也不再直接扫 `skillCatalog` 自建 mention command 两张 Map,而是改读同模块下的 `useRuntimeMentionCommandCatalog` - - 这一步特意把发送链做成“只拿自己真正需要的 mention 路由映射”,不再为了发送前补全 `@命令` 最近输入而顺手依赖整份 scene 列表;因此 current 主线更接近我们要的 typed capability registry,而不是继续把 UI 搜索目录和发送路由耦在一起 - - 到这里为止,`@ / /` current 主线已经形成三层同源收口:输入分组与激活态共享 capability section builder、scene 回落共享 runtime scene binding、发送链共享 runtime mention catalog - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/skill-selection/runtimeInputCapabilityCatalog.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx"` - - `npx eslint "src/components/agent/chat/skill-selection/runtimeInputCapabilityCatalog.ts" "src/components/agent/chat/skill-selection/runtimeInputCapabilityCatalog.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/workspace/useWorkspaceSendActions.ts"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - -- 把 `生成` 输入层的选择态与分组态往统一 capability registry 收口了一刀,不再让内建命令与已安装 skill 各持一套独立选择状态: - - 已更新: - - `src/components/agent/chat/skill-selection/inputCapabilitySelection.ts` - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx` - - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` - - `src/components/agent/chat/components/Inputbar/hooks/useInputbarSend.ts` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `@ / /` 面板当前已开始消费同一份前端 capability section builder:最近使用、内建命令、推荐技能、技能组、快捷操作、结果模板等分组不再散落在 `CharacterMentionPanel` 内部各自维护 - - 输入栏当前的“已选 capability”不再拆成 `activeBuiltinCommand + activeSkill` 两套状态,而是统一收口成单一 active capability;因此“先选内建命令再选 skill”这类链路会以后一次选择为准,不会再残留旧能力覆盖发送文本 - - 这一步仍属于前端 current 路径的第一版 unified capability registry:先收口输入层事实源与激活态,不引入新的后端协议,也不扩第二套执行系统 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npx eslint "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/hooks/useInputbarSend.ts" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - -- 把 unified capability registry 这一刀补齐到“能完整过当前统一门槛”,并顺手修掉服务技能入口残留旧 capability 的发送链污染: - - 已更新: - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `src/components/skills/WorkflowProgress.test.tsx` - - `src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts` - - `src/components/agent/chat/components/Inputbar/index.test.tsx` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - `inputCapabilitySections` 里最近使用分组的联合类型已经显式收口,不再因为 `flatMap` 首分支推断过窄,把 `service_skill / scene_command / installed_skill` 误判成非法返回值 - - `WorkflowProgress.test.tsx` 已补齐当前 `WorkflowStepInfo.dependencies` 与 `StepResult.step_name` 契约,`verify:local` 不再被落后的测试夹具卡住 - - 输入栏当前在“先选 `@命令`,再切到服务技能入口”时会主动清掉旧 active capability,不再把前一次 builtin command 前缀偷偷带进后续发送 - - 这一步继续沿着 V2 的同一条主线推进:`@ / /` 不只是 UI 分组统一,还要保证 capability 激活态、服务技能入口和最终发送链属于同一套 current 行为 - - 当前已确认通过: - - `npm run verify:local` - - `npm run typecheck` - - `npm exec vitest run "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/skills/WorkflowProgress.test.tsx"` - - `npx eslint "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/skills/WorkflowProgress.test.tsx"` - - 当前补充说明: - - `npm run verify:local` 是在“服务技能入口清空旧 capability”这一记收尾补丁之前启动的,但该补丁只落在输入栏前端 current 主链;补丁本身已经额外通过定向 `typecheck / vitest / eslint`,因此本轮交付按“统一入口通过 + 收尾补丁定向门槛通过”共同记录 - -- 把 Ribbi 命令研究正式收口成统一事实源,并同步回挂到 LimeNext V2 路线图,避免研究层与规划层再次分叉: - - 已更新: - - `docs/research/ribbi/command-inventory.md` - - `docs/research/ribbi/README.md` - - `docs/research/ribbi/agent-tool-orchestration.md` - - `docs/roadmap/limenextv2/README.md` - - `docs/roadmap/limenextv2/product-principles.md` - - `docs/roadmap/limenextv2/information-architecture.md` - - `docs/roadmap/limenextv2/runtime-architecture.md` - - `docs/roadmap/limenextv2/skill-first-system.md` - - `docs/roadmap/limenextv2/lime-vs-ribbi.md` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - Ribbi 的命令、agent、tool、sandbox、preview、publish 当前统一以 `docs/research/ribbi/command-inventory.md` 为唯一研究事实源,不再允许在其他文档里散写另一套命令口径 - - LimeNext V2 当前已明确:`生成` 不只是主执行面,还是统一调用面;`@ / /` 只是 `生成` 内的 typed capability registry 交互壳,不再被写成第二套执行系统 - - `技能` 与 `命令层` 当前已被明确拆分:`技能` 负责发现与启动,`命令层` 负责在线程内调用 skill、model agent、sandbox、search/read、media transform、preview/publish 等具体能力 - - 这一步把 V2 从“像 Ribbi 一样做闭环”的抽象描述,推进到了“Ribbi 的命令层如何影响 Lime 前台、IA 和运行时骨架”的可执行规划阶段 - -- 把 `新建任务` 首页里落后的硬编码精选 skill 逻辑收口成共享的 current curated helper,不再单独维护一套首页 skill 事实源: - - 已更新: - - `src/components/agent/chat/service-skills/homeEntrySkills.ts` - - `src/components/agent/chat/service-skills/useServiceSkills.ts` - - `src/components/agent/chat/components/EmptyState.tsx` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 首页精选 service skill 当前不再依赖硬编码 skill ID,而是复用同一份 service skill 目录、surface scope 与推荐分桶规则 - - 首页若当前运行时目录里没有可展示的 `home` 精选 skill,会用同一条 seeded service skill 事实源补齐精选位,而不是在 `EmptyState` 里手写一套单独对象 - - `useServiceSkills` 与 `新建任务` 首页当前共享同一条“首页可展示 skill”过滤规则;旧的首页精选硬编码实现已移除 - - 这一步把 `技能页 / 新建任务` 的 skill-first 收口往前推进了一刀:至少首页精选 skill 不再是独立维护的旧链 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/service-skills/useServiceSkills.test.tsx"` - - `npx eslint "src/components/agent/chat/service-skills/homeEntrySkills.ts" "src/components/agent/chat/service-skills/useServiceSkills.ts" "src/components/agent/chat/components/EmptyState.tsx"` - - 当前补充说明: - - `npm run typecheck` 这轮未通过,但阻塞点在既有 `src/components/skills/WorkflowProgress.test.tsx` 类型不匹配:`WorkflowStepInfo.dependencies` 与 `StepResult.step_name` 缺失,当前判断不是这次首页 skill 收口改动引入的新问题 - -- 把“上一版无人使用时不背历史包袱”的原则正式写回仓库级约束,避免后续继续给旧实现续命: - - 已更新: - - `AGENTS.md` - - `docs/aiprompts/governance.md` - - `.codex/skills/lime-governance/SKILL.md` - - `.codex/skills/lime-command-boundary/SKILL.md` - - `.codex/skills/lime-quality-workflow/SKILL.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 当用户已明确“上一版无人使用 / 不用兼容 / 旧实现阻碍主线”时,旧实现默认不再继续修补,而是按 `dead` 或带退出条件的 `deprecated` 收口 - - `legacy current reference` 统一只表示历史实现锚点,不再被解释成可以继续往旧页面、旧命令、旧协议上加功能 - - 后续若命中旧实现与 current 规划冲突,默认动作应先删旧实现和封旧路,再继续补主链 - -- 把 `生成主执行面` 的 `最近发布产物` 从“只列出文件”继续补成“带轻量发布态判断”的 current 结果区: - - 已更新: - - `src/components/agent/chat/workspace/sceneAppExecutionContentPosts.ts` - - `src/components/agent/chat/workspace/sceneAppExecutionContentPosts.test.ts` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` - - `docs/exec-plans/limenext-plan.md` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenext/README.md` - - 当前统一结论: - - `sceneAppExecutionContentPosts` 当前不再只聚合 `发布稿 / 渠道预览稿 / 上传稿` 三张文稿,还会顺手检查同名 `*.cover.json / *.publish-pack.json` 伴随文件 - - `生成` 页执行摘要卡里的 `最近发布产物` 现在会直接显示 `可继续发布 / 优先渠道预览 / 优先上传整理 / 待补封面信息、发布包` 等轻量就绪态,并把 `封面信息 / 发布包` 作为 companion 芯片带出来 - - 这一步仍只消费现有 `content-posts` 文件命名约定与 metadata,不新增新的发布状态协议;旧日志里若继续写“最近发布产物当前只是三个文件入口”,都按已过时理解 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/workspace/sceneAppExecutionContentPosts.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` - - `npx eslint "src/components/agent/chat/workspace/sceneAppExecutionContentPosts.ts" "src/components/agent/chat/workspace/sceneAppExecutionContentPosts.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` - - `npm run typecheck` - -- 把 `生成主执行面` 从“能发起发布后动作”继续补成“也能直接消费这些动作产物”: - - 已更新: - - `src/components/agent/chat/workspace/sceneAppExecutionContentPosts.ts` - - `src/components/agent/chat/workspace/sceneAppExecutionContentPosts.test.ts` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `docs/exec-plans/limenext-plan.md` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenext/README.md` - - 当前统一结论: - - `生成` 页执行摘要卡当前已新增 `最近发布产物` 区块,会直接聚合当前会话里的 `发布稿 / 渠道预览稿 / 上传稿` - - 聚合逻辑当前只消费带 `contentPostIntent / contentPostLabel` metadata 的 current 发布产物,不会把普通 `content-posts/*.md` 误判成投放结果 - - 打开链继续复用现有工作区预览主链:优先打开当前内存里的 `task file / artifact`,没有时再回落到 `session file` 读取;因此这一步没有新增新的 viewer 或发布协议 - - 旧日志里若继续写“生成页当前只能触发发布动作、不能直接消费发布稿结果”,当前都按已被本条替代的过时阶段理解 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/workspace/sceneAppExecutionContentPosts.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` - - `npx eslint "src/components/agent/chat/workspace/sceneAppExecutionContentPosts.ts" "src/components/agent/chat/workspace/sceneAppExecutionContentPosts.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx"` - - `npm run typecheck` - - GUI 校验补充说明: - - `npm run verify:gui-smoke` 这轮未通过,阻塞在启动期环境探测:脚本先误判 `http://127.0.0.1:1420/` 存在可复用前端壳,但 180 秒内实际无法连通该地址,随后 headless Tauri 在 `DevBridge` 就绪前提前退出(`exitCode=1`) - - 同轮补查 `1420 / 3030` 端口时都无法直接连接,说明这次失败属于本地 GUI smoke 环境启动问题,而不是“最近发布产物”这一条业务链本身在断 - -- 把 `创作场景 -> 持续流程 -> 创作场景` 的快速切换从局部 pending 修补收口成全局导航事务: - - 已更新: - - `src/hooks/useAppNavigation.ts` - - `src/hooks/useAppNavigation.test.tsx` - - `src/App.tsx` - - `src/components/AppSidebar.tsx` - - `src/components/AppPageContent.tsx` - - `src/components/AppPageContent.test.tsx` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `docs/exec-plans/limenext-plan.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - 全局导航当前固定为 `requestedPage / requestedPageParams` 与 `currentPage / pageParams` 双态;侧栏高亮与主内容区优先按最新请求态渲染,快速连点时以最后一次点击为准 - - `SceneAppsPage` 保留 keep-alive,但旧页失去导航所有权后不再回写 `sceneapps` 参数、也不再写 recent visit,因此不会再把页面抢回 `创作场景` - - `创作场景 -> 持续流程 -> 创作场景` 的快切链路当前已从“局部 pending 态互相覆盖”收口到“单一全局导航事实源”,不再出现闪动、空白或左侧导航短暂消失 - - 当前已确认通过: - - `npm exec vitest run "src/hooks/useAppNavigation.test.tsx" "src/components/AppSidebar.test.tsx" "src/components/AppPageContent.test.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm run verify:local` - - `npm run verify:gui-smoke` - - 当前补充说明: - - 额外盘点了仓库里其余 `onNavigate(...)` 调用点;当前未发现第二条与 `SceneApps keep-alive + 非激活态异步回写` 同型的导航抢写链路 - - 2026-04-18 追加复跑最新工作树的 `npm run verify:gui-smoke` 时,headless Tauri 启动阶段一直未等到 `DevBridge` 健康检查就绪,最终按 `bridge:health` 超时退出;当前判断这次阻塞发生在环境 / 启动期,不是导航链路的定向回归,因为同轮导航 Vitest 仍是 `58/58` 通过 - - 如果后续再出现同类闪回,下一步应优先继续排查是否还有页面在非激活态 effect 中自动回写全局导航 - -- 把 `生成主执行面` 的 `同聊推进` 从“发布前整理”继续扩到现有 `渠道预览 / 上传稿` 主链: - - 已更新: - - `src/lib/sceneapp/executionPromptActions.ts` - - `src/lib/sceneapp/executionPromptActions.test.ts` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` - - `docs/exec-plans/limenext-plan.md` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenext/README.md` - - 当前统一结论: - - `生成` 页执行摘要卡当前不再只停在 `补齐缺失部件 / 发布前检查 / 进入发布整理`,而是继续补到了 `生成渠道预览稿 / 整理上传稿` - - 这两条动作继续复用仓库里已经存在的 `@渠道预览 / @上传` 命令面与 `content_post_with_cover` 主链,不新增新的投放协议或平行发布系统 - - `生成渠道预览稿 / 整理上传稿` 与 `进入发布整理` 一样,当前都会按缺件和失败信号自动禁用并显式提示阻塞原因 - - 当前已确认通过: - - `npm exec vitest run "src/lib/sceneapp/executionPromptActions.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` - - `npx eslint "src/lib/sceneapp/executionPromptActions.ts" "src/lib/sceneapp/executionPromptActions.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - - 当前补充说明: - - 本轮第一次 `verify:gui-smoke` 在 `smoke:agent-runtime-tool-surface-page` 遇到一次 `bridge cooldown active` 环境抖动;未改代码重跑后完整 GUI smoke 已通过 - - 因此这次结论按“重跑后的完整 smoke 通过”记录,不把第一次环境性抖动误记成主线回归 - -- 把 `生成主执行面` 的 `生成后动作编排` 继续补到“同聊推进”层,而不再停在治理材料和页面跳转: - - 已更新: - - `src/lib/sceneapp/executionPromptActions.ts` - - `src/lib/sceneapp/executionPromptActions.test.ts` - - `src/lib/sceneapp/index.ts` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `docs/exec-plans/limenext-plan.md` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenext/README.md` - - 当前统一结论: - - `生成` 页执行摘要卡当前已新增 `同聊推进` 分组,可直接触发 `补齐缺失部件 / 发布前检查 / 进入发布整理 / 生成渠道预览稿 / 整理上传稿` - - `发布前检查 / 进入发布整理 / 生成渠道预览稿 / 整理上传稿` 继续复用现有 `@发布合规 / @发布 / @渠道预览 / @上传` 主链,`AgentChatWorkspace` 直接把动作 prompt 发送到当前会话,不新增新的 viewer 或发布协议 - - `进入发布整理 / 生成渠道预览稿 / 整理上传稿` 当前都会按缺件和失败信号自动禁用,并显式提示阻塞原因;因此“先治理、先预览还是先整理上传稿”不再只靠用户自己判断 - - 旧结论里若继续写“生成后动作编排还停在准备治理材料 + 恢复底层入口”,当前都按已过时理解 - - 当前已确认通过: - - `npm exec vitest run "src/lib/sceneapp/executionPromptActions.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` - - `npx eslint "src/lib/sceneapp/executionPromptActions.ts" "src/lib/sceneapp/executionPromptActions.test.ts" "src/lib/sceneapp/index.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - - 当前补充说明: - - 本轮第一次 `verify:gui-smoke` 曾被旧的本地 `lime` 调试进程占住 `3030/8999` 端口,导致新的 headless Tauri 半启动、workspace smoke 长时间挂起;清掉残留验证进程并重跑后,完整 GUI smoke 已通过 - - 因此这次交付结论以“重跑后的完整 GUI smoke 通过”为准,而不是以第一次被本地残留进程污染的结果为准 - -- 把 `生成主执行面` 继续补成第一批 `生成后动作编排`,不再只是“打开结果文件 + 跳回创作场景”: - - 已更新: - - `src/lib/sceneapp/runEntryNavigation.ts` - - `src/lib/sceneapp/runEntryNavigation.test.ts` - - `src/lib/sceneapp/index.ts` - - `src/lib/sceneapp/product.ts` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` - - `docs/exec-plans/limenext-plan.md` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenext/README.md` - - 当前统一结论: - - `生成` 页执行摘要卡当前会直接展示第一批推荐去向:`周会复盘 / 生成 / 看板 / 持续流程 / 自动化 / 结果编辑 / 发布` - - 生成页当前可直接执行 `准备周会复盘包 / 准备结构化治理包 / 打开基础治理材料 / 恢复底层运行入口` - - 上面这组动作当前已不再是终点;同一张摘要卡里已经继续补上 `补齐缺失部件 / 发布前检查 / 进入发布整理` - - `AgentChatWorkspace` 与 `SceneAppsPage` 当前共享 `resolveSceneAppRunEntryNavigationTarget + prepareSceneAppRunGovernanceArtifact(s)` current 主链,不再各自维护一套 run entry 恢复逻辑 - - 这一步把 `生成` 从“摘要页 + 导航中转站”推进为第一批真正的统一编排面,也把之前“只支持页面跳转”的旧判断标记为已过时 - - 当前已确认通过: - - `npm exec vitest run "src/lib/sceneapp/runEntryNavigation.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/components/agent/chat/workspace/useSceneAppExecutionSummaryRuntime.test.tsx"` - - `npm exec vitest run "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npx eslint "src/lib/sceneapp/runEntryNavigation.ts" "src/lib/sceneapp/runEntryNavigation.test.ts" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/lib/sceneapp/product.ts"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - - 当前补充说明: - - 本轮 `verify:gui-smoke` 已完整通过,说明这次 `生成后动作编排` 与共享 run entry 导航 helper 没有把 GUI 主路径打断 - - 旧日志里若继续出现“生成页当前还只支持页面跳转”之类说法,当前都按已被本条替代的过时阶段理解 - -- 把 `生成主执行面` 正式接到 current `Project Pack` 最近结果入口,而不再只停留在顶部摘要文案: - - 已更新: - - `src/lib/sceneapp/runtimeResults.ts` - - `src/lib/sceneapp/index.ts` - - `src/lib/sceneapp/product.ts` - - `src/components/agent/chat/workspace/useSceneAppExecutionSummaryRuntime.ts` - - `src/components/agent/chat/workspace/useSceneAppExecutionSummaryRuntime.test.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/sceneapps/SceneAppProjectPackRuntimePanel.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `docs/exec-plans/limenext-plan.md` - - `docs/roadmap/limenext/README.md` - - 当前统一结论: - - `useSceneAppExecutionSummaryRuntime` 当前不再只回流 `runtimeBackflow`,还会同步回流最近可消费的 `Project Pack` 结果样本,以及“当前 run 无文件时回退到最近已交付样本”的状态 - - `SceneAppExecutionSummaryCard` 已新增 `最近可消费结果` 区块,`生成` 页可以直接打开结果文件,不再逼用户先跳回 `创作场景` 子页 - - `SceneAppsPage` 与 `生成主执行面` 当前共享同一套 `findLatestSceneAppPackResultRun + resolveSceneAppRuntimeArtifactOpenTarget + deliveryArtifactEntries` current 打开链,不再各自维护一份结果入口协议 - - 这一步已经把 `创作场景 -> 生成 -> Project Pack -> 复盘` 里的“结果消费”真正补到 `生成` 主舞台,而不是继续停在准备页、评分页和治理页的旁路消费 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/workspace/useSceneAppExecutionSummaryRuntime.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` - - `npm exec vitest run "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npx eslint "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx" "src/components/agent/chat/workspace/useSceneAppExecutionSummaryRuntime.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/components/agent/chat/workspace/useSceneAppExecutionSummaryRuntime.test.tsx" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/sceneapps/SceneAppProjectPackRuntimePanel.tsx" "src/lib/sceneapp/product.ts" "src/lib/sceneapp/runtimeResults.ts"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - - 当前补充说明: - - `npm run verify:gui-smoke` 这轮已实际通过,说明 `生成主执行面` 与 `SceneApps` 共用的 current 结果入口链没有把 GUI 主路径打断 - - `npm run verify:local` 这轮未能整体通过,但失败点来自仓库里与本轮无关的既有 lint 问题: - - `src/components/agent/chat/workspace/useWorkspaceSendActions.ts` - - `src/components/agent/chat/workspace/workspaceSendHelpers.ts` - - 当前没有证据表明这些失败与本轮 `Project Pack` 结果入口改动相关,因此主线交付结论以 `定向回归 + typecheck + GUI smoke` 为准 - -- 把 `生成主执行面` 继续补成“结果消费 + 回闭环动作”入口,而不再让用户自己找回 `创作场景` 页: - - 已更新: - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` - - `docs/exec-plans/limenext-plan.md` - - `docs/exec-plans/limenext-progress.md` - - `docs/roadmap/limenext/README.md` - - 当前统一结论: - - 生成页执行摘要卡当前已新增 `回生成准备 / 去治理复盘` 两个继续动作 - - `去治理复盘` 当前会优先带到最近可消费样本对应的 run,而不是只盯着当前可能仍在执行的 run;因此结果消费与人工复核、轻量判断、治理动作已经开始接上同一条闭环 - - 生成页当前还能直接触发 `填写人工复核 / 可继续复用 / 继续观察 / 补证据 / 先别继续`,继续复用现有 `review decision` 主链与 `RuntimeReviewDecisionDialog` - - 这一步继续复用 `SceneAppsPage` 既有准备页与治理页,以及已有 `review decision` 协议,不在 `claw` 内再复制一套平行治理 UI,保持 current 事实源单一 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` - - `npm exec vitest run "src/components/agent/chat/workspace/useSceneAppExecutionSummaryRuntime.test.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` - - 定向 `eslint` - - 当前补充说明: - - 这一步主要补的是 `生成 -> 创作场景` 的回流动作层与直接复盘动作,没有新增新的运行态协议或页面对象 - - `npm run typecheck` 这轮未能整体通过,但失败点来自仓库里与本轮无关的既有问题: - - `src/components/onboarding/steps/VoiceShortcutTestStep.test.tsx` - - `npm run verify:gui-smoke` 这轮也未能完成,阻塞点仍是已有 headless 构建环境里的 `libsqlite3-sys` 临时 target `bindgen.rs` 缺失,不是这轮 `生成 -> 创作场景` 深链动作回归 - -## 2026-04-17 - -### 已完成 - -- 把 `Project Pack` 的结果消费入口从 `治理复盘 / 运行详情` 继续扩到 `生成准备 / 经营评分`: - - 已更新: - - `src/components/sceneapps/SceneAppProjectPackRuntimePanel.tsx` - - `src/components/sceneapps/SceneAppDetailPanel.tsx` - - `src/components/sceneapps/SceneAppScorecardPanel.tsx` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `docs/roadmap/limenext/README.md` - - `docs/exec-plans/limenext-plan.md` - - 当前统一结论: - - `生成准备` 与 `经营评分` 当前不再只展示 `Project Pack` 的查看方式文案,而会直接回流最近可消费样本的结果入口 - - 当最新运行仍在执行、或没有带回结果文件路径时,页面会自动回退到最近一轮已交付样本,避免准备页和评分页只剩静态规划信息 - - 结果入口继续复用 `SceneAppRunDetailViewModel.deliveryArtifactEntries -> Agent 文件预览打开链`,没有新增新的 `Project Pack viewer` 协议 - - 当前已确认通过: - - `npm exec vitest run "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npx eslint "src/components/sceneapps/SceneAppProjectPackRuntimePanel.tsx" "src/components/sceneapps/SceneAppDetailPanel.tsx" "src/components/sceneapps/SceneAppScorecardPanel.tsx" "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm run typecheck` - - GUI 续测结论: - - `npm run verify:gui-smoke` 当前不再卡 `libsqlite3-sys`;本轮失败点转为复用环境下的 `smoke:browser-runtime` 清理旧 `session_id` 时 `close_cdp_session` 返回“未找到 session”,属于浏览器运行时清理链问题,不是 `sceneapps` 主路径回归 - - 已改用真实页面续测补一刀:打开 `http://127.0.0.1:1420/`,进入 `创作场景 -> 生成准备 / 治理复盘`,确认 `最近结果入口 / 最近可消费结果` 面板已出现,控制台无新增 error,仅保留既有 `i18n` warn - - 当前 seed 运行样本在真实 GUI 环境里还没有带回可打开的结果文件路径,所以真实页面续测主要证明入口渲染与回退语义;“点击主稿文件即可打开”继续由新增的定向 Vitest 回归断言兜底 - -- 把 `创作场景` 目录分页正式接到 current `descriptor + latest run + scorecard` 同一事实源: - - 已更新: - - `src/lib/sceneapp/product.ts` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsCatalogPanel.tsx` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `docs/roadmap/limenext/README.md` - - `docs/exec-plans/limenext-plan.md` - - 当前统一结论: - - 场景目录卡片当前不再只是静态标题列表,而会同时回流 `delivery contract / latest run / scorecard action / top failure signal / operating summary` - - `useSceneAppsPageRuntime` 当前会在目录层聚合所有 descriptor 对应的 `latest run + scorecard`,并把这些经营信号压到同一份 `SceneAppCatalogCardViewModel` - - 目录卡片、生成页顶部执行摘要与自动化详情当前共享同一组 `descriptor + latest run + scorecard` 语义,不再各讲各的“当前状态” - - 这意味着 `创作场景` 目录已经从“选一个标题进去”推进到“先看哪条场景值得继续推进、该先补什么”这一层产品判断 - - 当前已确认通过: - - `npm exec vitest run "src/components/sceneapps/SceneAppsPage.test.tsx" "src/lib/sceneapp/product.test.ts"` - - `npx eslint "src/components/sceneapps/SceneAppsCatalogPanel.tsx" "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/lib/sceneapp/product.ts" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/lib/sceneapp/product.test.ts"` - - `npm run typecheck` - - 当前仍待继续: - - 本条能力本身已被后续更完整的 GUI 续测覆盖;当前整套 `verify:gui-smoke` 的最新阻塞已不再是 `libsqlite3-sys`,而是复用环境下 `smoke:browser-runtime` 清理旧会话失败 - -- 把 `持续流程 / 自动化` 详情页正式接到 current `创作场景 -> 生成 -> Project Pack -> 复盘` 同一事实源: - - 已更新: - - `src/lib/sceneapp/automation.ts` - - `src/lib/sceneapp/automation.test.ts` - - `src/components/settings-v2/system/automation/useAutomationSceneAppRuntime.ts` - - `src/components/settings-v2/system/automation/index.tsx` - - `src/components/settings-v2/system/automation/index.test.tsx` - - `src/components/settings-v2/system/automation/AutomationJobDetailsDialog.tsx` - - `src/components/automation/AutomationPage.tsx` - - `docs/roadmap/limenext/README.md` - - `docs/exec-plans/limenext-plan.md` - - 当前统一结论: - - 自动化详情弹窗当前不再只看 `调度状态 / payload / run history`;如果任务来自创作场景派生,它会按 job metadata 回查同一条 `SceneApp descriptor / project pack plan / run summary / scorecard` - - 弹窗里已新增 `创作场景闭环` 摘要块,能直接回到 `创作场景准备` 或 `治理复盘` - - 结果文件、治理文件与治理动作当前已复用 `SceneAppRunDetailViewModel + sceneapp_prepare_run_governance_artifact(s)` 主链,不再额外发明 automation 专用 pack / governance 协议 - - `SceneApp` 在这条链里继续只承担内部画像与运行时合同;自动化前台看到的仍是 `创作场景` 闭环,而不是新的对外主词 - - 当前已确认通过: - - `npm exec vitest run "src/lib/sceneapp/automation.test.ts" "src/components/settings-v2/system/automation/index.test.tsx"` - - `npm exec vitest run "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.test.tsx"` - - `npx eslint "src/lib/sceneapp/automation.ts" "src/lib/sceneapp/automation.test.ts" "src/components/settings-v2/system/automation/useAutomationSceneAppRuntime.ts" "src/components/settings-v2/system/automation/index.tsx" "src/components/settings-v2/system/automation/index.test.tsx" "src/components/settings-v2/system/automation/AutomationJobDetailsDialog.tsx" "src/components/automation/AutomationPage.tsx"` - - `npm run typecheck` - - 当前仍待继续: - - `npm run verify:gui-smoke` 本轮连续两次都卡在本地 headless Tauri Rust 构建环境,`libsqlite3-sys` 在临时 target 目录缺失 `bindgen.rs`,导致 DevBridge 未就绪;这次阻塞发生在 GUI smoke 启动期,而不是自动化 / 创作场景业务断链 - - `npm run verify:local` 本轮未继续执行,因为当前会被同一条 GUI smoke 环境故障阻塞 -- 把生成页顶部的 `创作场景执行摘要` 从启动静态卡继续补成“启动基线 + 运行态回流”的 current 主链: - - 已更新: - - `src/lib/sceneapp/product.ts` - - `src/lib/sceneapp/product.test.ts` - - `src/components/agent/chat/workspace/useSceneAppExecutionSummaryRuntime.ts` - - `src/components/agent/chat/workspace/useSceneAppExecutionSummaryRuntime.test.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` - - `src/components/AppPageContent.tsx` - - `src/components/AppPageContent.test.tsx` - - `docs/roadmap/limenext/README.md` - - `docs/exec-plans/limenext-plan.md` - - 当前统一结论: - - `生成` 页顶部的执行摘要当前不再只展示 `sceneapp_plan_launch` 时刻的 planning 快照,还会按当前 `sessionId -> sceneapp run` 回查最近运行,并把交付完成度、证据链、治理材料与失败信号继续回流到同一张摘要卡 - - `Project Pack / scorecard / governance` 这条运行态回流当前已开始直接进入 `生成主执行面`,用户不用再先跳回 `创作场景 / 复盘` 才能看到最近一次运行的主链状态 - - 为了守住 keep-alive 主路径,[AppPageContent.tsx](/Users/coso/Documents/dev/ai/aiclientproxy/lime/src/components/AppPageContent.tsx) 当前已把 `sceneapps` 常驻节点固定在稳定树位,`创作场景 -> 持续流程 -> 创作场景` 往返时不会再重挂载目录页 - - 当前已确认通过: - - `npm exec vitest run "src/lib/sceneapp/product.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx" "src/components/agent/chat/workspace/useSceneAppExecutionSummaryRuntime.test.tsx" "src/components/AppPageContent.test.tsx"` - - `npx eslint "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx" "src/components/agent/chat/workspace/useSceneAppExecutionSummaryRuntime.ts" "src/components/agent/chat/workspace/useSceneAppExecutionSummaryRuntime.test.tsx" "src/lib/sceneapp/product.ts" "src/lib/sceneapp/product.test.ts" "src/components/AppPageContent.tsx" "src/components/AppPageContent.test.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - -- 把 `创作场景 -> 生成` 的执行摘要真正接进 current `生成主执行面`,不再只把一段 prompt 丢给 `claw`: - - 已更新: - - `src/lib/sceneapp/product.ts` - - `src/lib/sceneapp/launch.ts` - - `src/types/page.ts` - - `src/components/AppPageContent.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.tsx` - - `src/components/agent/chat/workspace/WorkspaceConversationScene.tsx` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.tsx` - - `src/lib/sceneapp/launch.test.ts` - - `src/components/agent/chat/workspaceEntry.test.ts` - - `src/components/AppPageContent.test.tsx` - - `src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.test.ts` - - `src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx` - - `docs/roadmap/limenext/README.md` - - `docs/exec-plans/limenext-plan.md` - - 当前统一结论: - - `创作场景` 进入 `生成` 时,`Project Pack / scorecard / context baseline` 已通过 `initialSceneAppExecutionSummary` 进入生成页顶部,而不是再混进 runtime request metadata - - `initialAutoSendRequestMetadata` 当前也已显式透传到 `AgentChatPage`,`cloud_scene / browser_assist` 这类自动发送首刀不再丢失 metadata 主链 - - `生成` 页顶部现在会先展示“创作场景执行摘要”,再进入 step progress、timeline 与继续执行,用户可以直接看见当前场景的执行主链、上下文分层、Project Pack 合同与 scorecard 口径 - - 当前已确认通过: - - `npm exec vitest run "src/lib/sceneapp/launch.test.ts" "src/components/agent/chat/workspaceEntry.test.ts" "src/components/AppPageContent.test.tsx" "src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.test.ts" "src/components/agent/chat/workspace/SceneAppExecutionSummaryCard.test.tsx"` - -- 修掉 `治理复盘` 带 `runId` 重新进入时会在 runs 列表加载阶段回退到首条运行的状态抖动: - - 已更新: - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `src/components/AppPageContent.test.tsx` - - 当前统一结论: - - 目录刚加载完、场景选择还未落稳的过渡帧,runtime 不会再提前清空已有 `selectedRunId` - - 带 `runId` 重进 `治理复盘` 时,右侧运行详情会继续稳定指向该 run,而不是被 runs 列表里的首条记录覆盖 - - `AppPageContent` 的页面挂载回归也已同步修正,`verify:gui-smoke` 不会再在 `agent-service-skill-entry` 阶段被旧测试写法误伤 - - 当前已确认通过: - - `npm exec vitest run "src/components/sceneapps/SceneAppsPage.test.tsx" -t "带 runId 重新进入治理页时不应在运行列表加载阶段回退到首条运行"` - - `npm exec vitest run "src/components/AppPageContent.test.tsx"` - - `npm run verify:gui-smoke` - -- 把 `agentEntry=claw` 的 current 前台产品定义收口为 `生成主执行面`,不再继续用 `任务中心` 作为主叙事: - - 已更新: - - `src/lib/navigation/sidebarNav.ts` - - `src/types/page.ts` - - `src/components/agent/chat/workspace/chatSurfaceProps.ts` - - `src/components/agent/chat/components/MessageList.tsx` - - `src/components/agent/chat/components/ChatSidebar.tsx` - - `src/components/agent/chat/components/Inputbar/components/InputbarComposerSection.tsx` - - `src/components/agent/chat/service-skills/skillPresentation.ts` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/SceneAppDetailPanel.tsx` - - `src/lib/sceneapp/presentation.ts` - - `docs/roadmap/limenext/README.md` - - `docs/roadmap/limenext/prd.md` - - `docs/roadmap/limenext/architecture.md` - - `docs/roadmap/limenext/context-layer.md` - - `docs/roadmap/limenext/sceneapp-business-flows.md` - - `docs/roadmap/limenext/sceneapp-fullstack-implementation-plan.md` - - 旧 Ribbi 对位文档已清理;相关判断现统一收口到 `docs/research/ribbi/*` 与 `docs/roadmap/limenextv2/*` - - 当前统一结论: - - 侧边栏与前台 current 主词现在固定为 `新建任务 / 生成 / 我的方法 / 创作场景 / 消息渠道 / 资料库 / 灵感库` - - `agentEntry=claw` 继续保留为内部实现 route,但前台已统一按 `生成` 理解 - - `创作场景` 页当前明确退回执行前选路、planning 和上下文基线装配页,不再承担长期主执行面职责 - - `生成` 当前是 Lime 创作闭环唯一主执行面,继续承接执行过程、继续旧历史、最近结果与后续结果回流 - -- 把 `sceneapp_plan_launch` 与 `sceneapp_save_context_baseline` 的语义彻底拆开,收口成 latest-only 的显式场景基线主链: - - 已更新: - - `src-tauri/src/sceneapp/application.rs` - - `src-tauri/src/commands/sceneapp_cmd.rs` - - `src-tauri/src/app/runner.rs` - - `src-tauri/src/dev_bridge/dispatcher/sceneapp.rs` - - `src-tauri/src/dev_bridge/dispatcher.rs` - - `src/lib/api/sceneapp.ts` - - `src/lib/governance/agentCommandCatalog.json` - - `src/lib/dev-bridge/mockPriorityCommands.ts` - - `src/lib/tauri-mock/core.ts` - - `src/lib/tauri-mock/core.test.ts` - - `src/lib/api/sceneapp.test.ts` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppDetailPanel.tsx` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `docs/aiprompts/commands.md` - - `docs/roadmap/limenext/README.md` - - `docs/roadmap/limenext/context-layer.md` - - `docs/roadmap/limenext/inspiration-library-and-taste-profile.md` - - `docs/roadmap/limenext/sceneapp-fullstack-implementation-plan.md` - - `docs/roadmap/limenext/sceneapp-runtime-contract.md` - - 当前统一结论: - - `sceneapp_plan_launch` 现在只负责 preview 当前 planning,并读取已有项目级 Context Snapshot - - `sceneapp_save_context_baseline` 才代表把当前灵感对象、输入摘要与风格偏好显式写回 `.lime/sceneapp/context/.json` - - `创作场景` 详情页已新增“写入当前场景基线”按钮,不再把 preview planning 伪装成自动资产沉淀 - - 浏览器 mock、DevBridge、Tauri 注册、治理目录册与前端 API 网关都已同步到同一条 current 命令链 - - 当前已确认通过: - - `cargo test --manifest-path "src-tauri/Cargo.toml" sceneapp::` - - `npm exec vitest run "src/lib/api/sceneapp.test.ts" "src/lib/tauri-mock/core.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - -- 把 `创作场景治理页 / 运行详情 -> 轻量反馈按钮` 接回 current `review decision` 主链: - - 已更新: - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/SceneAppGovernancePanel.tsx` - - `src/components/sceneapps/SceneAppRunDetailPanel.tsx` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `docs/roadmap/limenext/README.md` - - `docs/roadmap/limenext/inspiration-library-and-taste-profile.md` - - `docs/roadmap/limenext/metrics-and-selection.md` - - `docs/roadmap/limenext/sceneapp-fullstack-implementation-plan.md` - - `docs/roadmap/limenext/sceneapp-runtime-contract.md` - - 当前统一结论: - - `可继续复用 / 继续观察 / 补证据 / 先别继续` 四个轻量判断按钮,当前已经落到治理看板与运行详情 - - 这些按钮不会新造 `sceneapp_feedback_*` 协议,而是先复用 `agent_runtime_export_review_decision_template / agent_runtime_save_review_decision` - - 保存后仍会沿用同一条 `review decision -> Context Snapshot -> planning 刷新` 主链 - - 完整人工复核入口继续保留;轻量判断只负责把高频结论更快写回 current 资产链 - - 当前已确认通过: - - `npm exec vitest run "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm run typecheck` - -- 补齐 `SceneApp current 命令 -> DevBridge browser 开发模式` 的最后一段桥接,修掉创作场景页在浏览器模式下的 `unknown command` 断链: - - 已更新: - - `src-tauri/src/dev_bridge/dispatcher/sceneapp.rs` - - `src-tauri/src/dev_bridge/dispatcher.rs` - - 当前统一结论: - - `sceneapp_list_catalog / sceneapp_get_descriptor / sceneapp_plan_launch / sceneapp_save_context_baseline / sceneapp_create_automation_job / sceneapp_list_runs / sceneapp_get_run_summary / sceneapp_prepare_run_governance_artifact / sceneapp_get_scorecard` 在 current 不只注册在 Tauri `generate_handler!`,也已显式接入 DevBridge `dispatcher` - - 浏览器开发模式下的 `创作场景` 页面已不再出现 `sceneapp_plan_launch / sceneapp_list_runs / sceneapp_get_scorecard` 的 `未知命令` - - current `sceneapp_*` 现在在桌面壳与浏览器开发模式下共享同一条 SceneApp 真相链,不再出现“合同存在但 DevBridge 少桥一半”的断层 - - 当前已确认通过: - - `cargo test --manifest-path "src-tauri/Cargo.toml" sceneapp_` - - `npm run test:contracts` - - 直接打开 `http://127.0.0.1:1420/`,进入 `创作场景` 页面后,控制台只剩 `i18n` warning,不再出现 `sceneapp_*` unknown command - - `npm run verify:gui-smoke -- --reuse-running --timeout-ms 600000` - - 本轮额外确认: - - 中途曾出现一次 `smoke:agent-service-skill-entry` 串联超时,表面报错是 `src/components/agent/chat/index.test.tsx` 的 `beforeAll` hook timeout - - 随后定向复跑 `node scripts/agent-service-skill-entry-smoke.mjs` 与整套 `verify:gui-smoke` 已恢复通过,说明这次更像运行时抖动,而不是 SceneApp / DevBridge current 主链回归 - -- 把 `review decision -> 项目级 Context Snapshot` 的显式人工复核入口接回 current 主链: - - 已更新: - - `src-tauri/src/commands/aster_agent_cmd/command_api/runtime_api.rs` - - `src-tauri/src/sceneapp/application.rs` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/SceneAppGovernancePanel.tsx` - - `src/components/sceneapps/SceneAppRunDetailPanel.tsx` - - `src/lib/sceneapp/product.ts` - - `src/lib/sceneapp/product.test.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - 当前统一结论: - - `agent_runtime_save_review_decision` 保存完成后,会尝试按 `session_id -> sceneapp run` 反查当前运行,并把人工复核结论同步回 `.lime/sceneapp/context/.json` - - `ReferenceItem.lastFeedbackLabel` 当前可直接承接 `人工接受 / 人工延后 / 人工否决 / 人工补证据` 等显式人工结论 - - `TasteProfile.feedbackSummary / feedbackSignals / lastFeedbackAt` 当前会同时承接自动反馈与人工复核,不再额外新增 `sceneapp_feedback_*` 协议 - - 创作场景治理页已经复用现有 `RuntimeReviewDecisionDialog`,保存后会刷新当前 planning 基线 - - 当前已确认通过: - - `cargo test --manifest-path "src-tauri/Cargo.toml" sceneapp::` - - `npm exec vitest run "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm run typecheck` - - `npm run test:contracts` - - 当前仍待继续: - - GUI smoke 当前被复用中的 `DevBridge health` 阻塞,尚未完成这轮 GUI 交付验证 - -- 把 `灵感库 -> 创作场景` 的正式引用对象链补齐到 current 主链: - - 已更新: - - `src/components/memory/MemoryPage.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/lib/sceneapp/navigation.ts` - - `src/lib/sceneapp/launch.ts` - - `src/lib/sceneapp/launcher.ts` - - `src-tauri/src/sceneapp/application.rs` - - `src-tauri/src/sceneapp/context/compiler.rs` - - `src-tauri/src/sceneapp/runtime.rs` - - `src-tauri/src/sceneapp/adapters.rs` - - `src/lib/tauri-mock/core.ts` - - 当前统一结论: - - `referenceMemoryIds` 已成为 `灵感库 -> 创作场景` 的 current 正式入口 - - `prefillIntent` 继续保留,但只做输入补充,不再承担“唯一灵感对象载体” - - `sceneapp_plan_launch` 已能按 `reference_memory_ids` 读取统一记忆条目,并编译成 `contextOverlay.snapshot.referenceItems` - - 编译结果会继续进入 `TasteProfile`、`projectPackPlan` 与 runtime adapter metadata / launch payload;显式落盘当前改由 `sceneapp_save_context_baseline` - - 浏览器 mock 已与 Rust current 合同对齐,不再只在真实后端链路里有 `reference_memory_ids` - - 当前已确认通过: - - `npm exec vitest run "src/lib/tauri-mock/core.test.ts" "src/lib/api/sceneapp.test.ts" "src/components/memory/MemoryPage.test.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/lib/sceneapp/storage.test.ts" "src/lib/sceneapp/launch.test.ts"` - - `cargo test --manifest-path "src-tauri/Cargo.toml" sceneapp::` - - 当前仍待继续: - - 如何让自动反馈回写与前台显式操作进一步统一成稳定资产链 - - provider 裁剪和更稳定的跨场景 taste 经营链 - -- 把 `运行 / scorecard / governance -> 项目级 Context Snapshot` 的自动反馈回写补齐到 current 主链: - - 已更新: - - `src-tauri/src/sceneapp/application.rs` - - `src-tauri/src/sceneapp/context/dto.rs` - - `src-tauri/src/sceneapp/context/compiler.rs` - - `src-tauri/src/sceneapp/context/store.rs` - - `src/lib/context-layer/types.ts` - - `src/lib/sceneapp/product.ts` - - `src/components/sceneapps/SceneAppDetailPanel.tsx` - - `src/components/sceneapps/SceneAppScorecardPanel.tsx` - - `src/components/sceneapps/SceneAppGovernancePanel.tsx` - - `src/components/sceneapps/SceneAppRunDetailPanel.tsx` - - 当前统一结论: - - `ReferenceItem` 已直接承接 `usageCount / lastUsedAt / lastFeedbackLabel` - - `TasteProfile` 已直接承接 `feedbackSummary / feedbackSignals / lastFeedbackAt` - - `sceneapp_get_run_summary / sceneapp_prepare_run_governance_artifact / sceneapp_get_scorecard` 会把最近运行的交付缺口、失败信号与治理判断自动回写到 `.lime/sceneapp/context/.json` - - 详情、评分、运行复盘、治理面当前都会继续消费同一套 `Planning 基线 + 最近反馈` 事实源 - - V2 current first cut 已不再依赖“像我 / 不像我”按钮才能形成反馈闭环;当前显式人工复核继续复用 review decision 主链补到同一份 snapshot - - 当前已确认通过: - - `cargo test --manifest-path "src-tauri/Cargo.toml" sceneapp::` - - `npm exec vitest run "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm run typecheck` - - `npm run test:contracts` - - 当前仍待继续: - - provider 裁剪和更稳定的跨场景 taste 经营链 - -- 把 LimeNext V2 的 current 文档事实源收口到 `创作场景 / 灵感库` 主线: - - 已更新: - - `docs/roadmap/limenext/README.md` - - `docs/roadmap/limenext/inspiration-library-and-taste-profile.md` - - `docs/roadmap/limenext/context-layer.md` - - `docs/roadmap/limenext/sceneapp-fullstack-implementation-plan.md` - - 当前统一结论: - - 前台主词固定为 `创作场景 / 灵感库 / 生成 / Project Pack / 复盘` - - `SceneApp` 继续保留为内部场景画像与运行时合同,不再作为前台主叙事 - - `灵感库` 当前是 `Memory Layer + Taste Layer` 的前台投影层,底层事实源仍在 `Memory Layer` - - `灵感库 -> 创作场景` 已进入 current 前台主链:灵感条目可带着 `referenceMemoryIds + prefillIntent` 进入场景 planning - - 当前真正缺口已从“有没有前台入口”收口为“如何把前台操作正式回写到 `ReferenceItem / TasteProfile`,以及如何补齐 provider 裁剪与反馈编译” - - 本轮额外沉淀: - - V2 不应再把“灵感库”与“记忆工作台”混成同一层;前台要讲投影层,底层要讲事实源与诊断层 - - `SceneApp` 这个词保留工程价值,但不应继续主导对外命名 - -- 把 compat 旧文档继续标注清理,避免旧图示覆盖 current 口径: - - 已更新: - - `docs/roadmap/limenext/sequences.md` - - `docs/roadmap/limenext/flowcharts.md` - - 当前固定规则: - - 这两份文档继续保留为 `compat reference` - - 文中若继续出现 `场景应用`、旧“场景工厂”等词,只按 compat 旧称理解,不能覆盖 current 的 `创作场景 / 灵感库 / Project Pack / 复盘` - -- 收掉 `SceneAppsPage` 剩余两条旧文案测试断言,避免 current 命名继续被旧 `SceneApp` 文案拖回去: - - 已更新: - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - 当前已确认通过: - - `npm exec vitest run "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm run typecheck` - -## 2026-04-16 - -### 已完成 - -- 收口 `SceneApp / Context Layer` 当前 latest-only 产品面,不再给旧 `projectPackPlan` 单独消费模型留历史包袱: - - `src/lib/sceneapp/product.ts` 已把 `contextPlan` 改成显式复用 `contextBaseline` 组装,清掉依赖隐式 spread 的旧空值心智 - - `src/lib/sceneapp/product.test.ts` 已统一改到 `planResult` 主签名,并补齐: - - `detail / scorecard / run detail / governance` 四个消费面的 `contextBaseline` 断言 - - `referenceItems / tasteKeywords / avoidKeywords / scopeLabel` 断言 - - `src/components/sceneapps/SceneAppsPage.test.tsx` 已补齐当前页面事实源断言: - - 详情页 `reference items / taste / avoid` - - 评分卡 `context baseline` - - 治理页 `context baseline` - - 运行详情 `context baseline` - - 顺手清掉一个测试历史噪音: - - “继续最近”用例已补 `act + flushEffects`,不再在定向回归里持续刷 React `act(...)` 警告 - - 当前已确认通过: - - `npm exec vitest run "src/lib/sceneapp/product.test.ts"` - - `npm exec vitest run "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm run typecheck` - - `cargo test --manifest-path "src-tauri/Cargo.toml" sceneapp::` - - `npm run verify:gui-smoke -- --reuse-running --timeout-ms 600000` - - 当前额外确认: - - `npm run verify:local` 在仓库全量 Rust 阶段失败于未改动模块 `services::site_capability_service::tests::should_report_requires_browser_runtime_when_no_attached_session_exists` - - 这轮 `SceneApp / Context Layer` 主线的前端、GUI 与 `sceneapp::` 定向 Rust 校验已通过,当前阻塞不是本轮 latest-only 收口引入 - -- 收口 `SceneApp / Context Layer` 这轮尾部校验,把最终阻塞从“实现错误”纠偏为“测试契约与 smoke 串联稳定性”: - - `src/components/agent/chat/utils/clawWorkspaceProviderSelection.test.ts` 已补齐 `normalizeFetchProviderModelsSource` mock,避免 provider API fallback 分支被旧测试契约静默吞掉 - - 之前 `verify:local` 首次失败里的两类红灯现已分别确认: - - `clawWorkspaceProviderSelection` 两条失败是测试 mock 落后,不是当前 provider 选择实现回退 - - Rust `media_task_cmd` 两条 image task 失败是受限环境里的端口绑定权限问题;在当前无沙箱环境下定向 `cargo test --manifest-path "src-tauri/Cargo.toml" execute_image_generation_task_should_` 已通过 - - GUI smoke 首次卡在 `smoke:agent-runtime-tool-surface-page` 的 `browser_execute_action / close_cdp_session / close_chrome_profile_session -> fetch failed`,但单独复跑该 smoke 与随后复跑整套 `verify:gui-smoke -- --reuse-running --timeout-ms 600000` 已全部通过,说明更像一次串联波动,而不是 SceneApp 主链回归 - - 当前已确认通过: - - `npm exec vitest run "src/components/agent/chat/utils/clawWorkspaceProviderSelection.test.ts"` - - `cargo test --manifest-path "src-tauri/Cargo.toml" execute_image_generation_task_should_` - - `npm run verify:gui-smoke -- --reuse-running --timeout-ms 600000` - - `npm run verify:local` - - 本轮额外沉淀: - - `SceneApp / Context Layer` 主线已经达到 Lime 当前本地可交付门槛,剩余重点不再是补兼容,而是继续把 page smoke 的串联稳定性保持住 - - 遇到 `fetch failed` 一类 GUI smoke 假红时,先拆成“单条 smoke / DevBridge 健康 / 定向 Rust 用例”三段验证,再决定是不是实现回退 - -- 修掉 `SceneAppsPage` 点击“继续最近”后因同页重复导航导致的持续闪屏: - - 根因不是纯样式问题,而是 `useSceneAppsPageRuntime` 在显式恢复最近参数后,`search / prefillIntent` 的 debounced 同步又拿旧值触发了一轮同页 `onNavigate("sceneapps", ...)` - - 当前已改成: - - 当本地 `searchQuery / launchInput` 与外部 `pageParams` 一致时,优先用当前值参与同步 - - 不再让 debounce 落后的旧值在“继续最近”后触发第二轮同页导航 - - 已补稳定回归: - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - 新增“点击继续最近场景后不应因为搜索与输入 debounce 再次重复导航”断言 - - 当前已确认通过: - - `npm test -- "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npx eslint --no-warn-ignored "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - -- [已被后续经营信号目录卡片方案替代] 把 `SceneApps` 目录页从“无图场景墙”进一步纠偏到“纯标题目录”: - - 删除目录分页里大外框、大卡片和“场景选品墙”式陈列 - - 最近访问入口继续保留,但已压缩成同一块目录里的纯文字标题入口 - - 场景目录当前只保留标题点击,不再在目录页展示产出、模式、基础设施与 CTA 块 - - 已同步更新: - - `src/components/sceneapps/SceneAppsCatalogPanel.tsx` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `docs/aiprompts/design-language.md` - - 本轮额外沉淀: - - 对“目录页”来说,真正的合并不是把两组卡片放进一个组件,而是把它们收成同一种文字语义 - - 如果页面目标只是快速选场景,宁可退成纯标题目录,也不要继续保留 SceneApp 大框 - -- 把首页 `SceneApps` 入口从“大卡片推荐面板”继续收口成“纯文字标题目录”: - - 命中组件是 `src/components/agent/chat/components/EmptyStateSceneAppsPanel.tsx`,不是 `SceneAppsPage` - - 首页入口当前只保留: - - 标题说明 - - 继续最近场景 / 查看全部场景 - - 一行可直接点击启动的场景标题目录 - - 删除首页入口里的: - - SceneApp 大卡片 - - 产出 / 模式 / 基建 / 来源信息块 - - 深色主 CTA 按钮 - - 已同步更新: - - `src/components/agent/chat/components/EmptyStateSceneAppsPanel.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `docs/aiprompts/design-language.md` - - 本轮额外沉淀: - - 首页场景入口和场景目录页都应共享“纯标题目录”语义,不能一个已经去框化,另一个还保留老式卡片 - -- 把 `SceneAppsPage` 首屏壳层从“大框工作台”继续收口成纯文字导航: - - 删除首屏 hero 外框、四张统计卡、当前场景摘要卡和 `WORKFLOW PATH` 三步卡 - - 当前只保留: - - 页面标题与说明 - - 刷新目录文字入口 - - 目录 / 详情 / 治理的文字型分页切换 - - 当前场景的一行文字状态与最小动作入口 - - 已同步更新: - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `docs/aiprompts/design-language.md` - - 本轮额外沉淀: - - `SceneAppsPage` 的“分页”与“卡片化壳层”不是一回事;保留分页不等于必须保留大块容器 - - 如果用户目标是快速选场景,顶层工作台也应回到文字导航,而不是继续展示经营看板式首屏 - -- 把 `browser runtime` 会话稳定性从“依赖首个 launcher 子进程存活”收口成“按 `profile_key` 管理当前活跃 session”: - - `src-tauri/src/commands/webview_cmd.rs` 已修正: - - Chrome profile 存活判断不再只依赖最初 launcher 子进程 - - 未受管 / 扩展附着 session 发现不再把 `/json/list` 瞬时失败直接判死 - - `close_browser_runtime_session_for_profile_key(...)` 现在会清这个 profile 的全部 runtime session - - `src-tauri/crates/browser-runtime/src/manager.rs` 已修正: - - 新增 `open_session_gate`,串行化同一 `profile_key` 的 `open_session` - - `find_session_by_profile_key(...)` 优先返回最新的 connected session - - 新增 `close_sessions_by_profile_key(...)`,避免旧 session 残留 - - 本轮已确认通过: - - `env CARGO_TARGET_DIR="/tmp/lime-browser-runtime-verify" cargo test --manifest-path "src-tauri/Cargo.toml" -p lime-browser-runtime` - - `npm run smoke:agent-runtime-tool-surface-page -- --timeout-ms 180000 --interval-ms 1000` - - `npm run smoke:browser-runtime -- --timeout-ms 180000 --interval-ms 1000 --headless` - - `npm run verify:gui-smoke -- --reuse-running --timeout-ms 600000` - - 本轮额外沉淀: - - 页级 runtime smoke 不应继续被旧 session / 孤儿 profile 清理策略拖垮 - - `browser runtime` 的事实源应围绕 `profile_key` 当前活跃会话,而不是某一次 launcher 生命周期 - -- [已被 current 目录经营卡片方案替代] 把 `SceneApps` 目录页从“最近场景 + 目录卡片”双块结构收口成统一的无图场景选品墙: - - 最近访问入口不再单独占一块面板,而是并入 `SceneAppsCatalogPanel` - - 目录卡片已补充: - - `产出` - - `模式` - - `基建` - - `业务动作` - - 当前目录页结构固定为: - - 顶部搜索与双层筛选 - - 同语义的“继续最近工作” - - 同语义的“按结果挑场景” - - 已同步更新: - - `src/components/sceneapps/SceneAppsCatalogPanel.tsx` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `src/lib/sceneapp/product.ts` - - `docs/aiprompts/design-language.md` - - 当前已确认通过: - - `npm test -- "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npx eslint --no-warn-ignored "src/components/sceneapps/SceneAppsCatalogPanel.tsx" "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/lib/sceneapp/product.ts"` - - `npm run verify:gui-smoke -- --reuse-running --timeout-ms 600000` - - 本轮额外沉淀: - - 目录页要让用户感觉自己在“选场景”,而不是在“最近记录区”和“目录区”之间切换 - - 没有图片时,也可以靠结果、模式、基建和当前状态做出 marketplace 式层级,但仍要保持 Lime 的桌面产品气质 - -- 把 `smoke:agent-runtime-tool-surface-page` 继续从“依赖全局配置写入”收口成“页面级调试覆盖 + 阶段日志”: - - 新增前端 `workspace harness` 调试覆盖读取: - - `src/lib/developerFeatures.ts` - - `src/hooks/useDeveloperFeatureFlags.ts` - - 当前支持通过 `localStorage["lime:debug:workspace-harness-enabled:v1"]` 临时打开处理工作台,而不必为了 smoke 去调用 `save_config` - - 这让页级 smoke 不再为了打开工作台去碰全局配置文件和环境变量应用链,进一步符合 LimeNext 当前主线里的“场景页 / smoke / 基础设置解耦”原则 - - `scripts/agent-runtime-tool-surface-page-smoke.mjs` 已同步改成: - - 仅注入本地 `localStorage` 调试覆盖 - - 不再在 `finally` 里回写全局配置 - - 每个关键阶段都会输出 `stage=...` 日志,便于继续定位真实卡点 - - 已补最小回归: - - `src/lib/developerFeatures.test.ts` - - 当前已确认通过: - - `npm test -- "src/lib/developerFeatures.test.ts"` - - `npx eslint --no-warn-ignored "src/lib/developerFeatures.ts" "src/lib/developerFeatures.test.ts" "src/hooks/useDeveloperFeatureFlags.ts" "scripts/agent-runtime-tool-surface-page-smoke.mjs"` - - 当前未完成但已确认环境状态: - - 正在重新拉起隔离 `headless Tauri` 环境,当前还卡在冷编译阶段,`http://127.0.0.1:3030/health` 暂未恢复 - - 下一步继续等 `DevBridge` 就绪后重跑 `npm run smoke:agent-runtime-tool-surface-page -- --timeout-ms 180000 --interval-ms 1000` - -- 重新执行 `npm run verify:gui-smoke`,当前主链进度已经前推到页级 runtime tool surface,而不再卡在最早的 `bridge:health`: - - 已确认通过: - - `smoke:workspace-ready` - - `smoke:browser-runtime` - - `smoke:site-adapters` - - `smoke:agent-service-skill-entry` - - `smoke:agent-runtime-tool-surface` - - 当前最终阻塞已缩小到: - - `smoke:agent-runtime-tool-surface-page` - - 具体现象: - - `browser_execute_action` 持续 `fetch failed` - - `close_cdp_session` 持续 `fetch failed` - - `close_chrome_profile_session` 持续 `fetch failed` - - 这说明本轮 SceneApp 分页改动没有把前面的 GUI 壳主链打断,剩余阻塞更像是页级浏览器动作链与 DevBridge/CDP 清理的稳定性问题 - -- 把 `SceneAppsPage` 的跨页路径继续从“标签切页”推进到“业务向工作流导轨”: - - 新增 `SceneAppsWorkflowRail`,固定把 SceneApp 主路径表达为: - - `选场景` - - `补启动` - - `看治理` - - 导轨不只是展示步骤,还会根据当前上下文给出不同动作: - - 已有运行样本时可直接进入治理 - - 还没有运行样本时,治理步骤会回指详情页先完成首轮启动 - - 没有选中场景时,详情与治理步骤会明确回到目录 - - 已同步更新: - - `src/components/sceneapps/SceneAppsWorkflowRail.tsx` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `docs/aiprompts/design-language.md` - - `docs/exec-plans/limenext-plan.md` - - 当前已确认通过: - - `npm test -- "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npx eslint --no-warn-ignored "src/components/sceneapps/SceneAppsWorkflowRail.tsx" "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - 本轮额外沉淀: - - 复杂分页工作台不应只给标签页,还应给任务路径导轨 - - 跨页按钮要根据业务状态自适应目标页,而不是机械地固定跳某一页 - -- 把 `SceneAppsPage` 的分页式工作台继续补成“可回退、可引导”的分页级空态,而不只是标签切页: - - 新增 `SceneAppsPageEmptyState`,统一承接 `detail / governance` 两页的分页级空态 - - `detail` 分页在没有匹配 SceneApp 时,会明确提示这是筛选结果为空,而不是继续落到“左侧目录”这种旧布局文案 - - 当前已支持一键: - - 回到场景目录 - - 清空筛选并返回目录 - - `governance` 分页在还没有任何运行样本时,不再只显示空表,而是明确引导用户先回到详情页启动首轮结果链 - - 已同步更新: - - `src/components/sceneapps/SceneAppsPageEmptyState.tsx` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppDetailPanel.tsx` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - 当前已确认通过: - - `npm test -- "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npx eslint --no-warn-ignored "src/components/sceneapps/SceneAppsPageEmptyState.tsx" "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/SceneAppDetailPanel.tsx" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - 本轮额外沉淀: - - 分页工作台不能只把内容拆开,还要把“当前无数据时下一步去哪”直接写进页面 - - 治理页的首轮空态默认应回指详情页启动,而不是把用户留在没有运行样本的复盘页里 - -- 把 `SceneAppsPage` 从“同页堆叠目录 + 详情 + 治理”继续收口成“分页式信息架构”: - - 当前固定拆成三页: - - `场景目录` - - `场景详情` - - `治理复盘` - - 顶部继续保留统一 `当前场景` 摘要和跨页入口,避免切页后丢失业务上下文 - - 目录卡片点击现在会直接进入对应详情分页,不再只是停留在选中态边框 - - 自动化摘要卡片与治理摘要的读模型残留问题已顺手收口: - - 修掉 `buildSceneAppAutomationWorkspaceCardViewModel(...)` 对 `getSceneAppPatternSummary(...)` 的错误入参 - - 删除 `buildSceneAppGovernancePanelViewModel(...)` 重构后遗留的未使用局部变量 - - 已同步更新: - - `src/components/sceneapps/SceneAppsCatalogPanel.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `src/lib/sceneapp/product.ts` - - `src/lib/sceneapp/product.test.ts` - - `docs/aiprompts/design-language.md` - - `docs/exec-plans/limenext-plan.md` - - 当前已确认通过: - - `npm test -- "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npx eslint --no-warn-ignored "src/lib/sceneapp/product.ts" "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/sceneapps/SceneAppsCatalogPanel.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - 本轮额外沉淀: - - 复杂工作台默认按任务阶段分页,不再把目录、详情、治理继续堆在一屏 - - 承担导航职责的目录卡片必须有明确点击结果,不能只保留“选中态”伪反馈 - -- 把 `SceneApp project pack` 的治理闭环从“单次运行详情”推进到“页面级治理看板”: - - 新增 `SceneAppGovernancePanel`,不再只在运行详情里解释治理动作 - - `buildSceneAppGovernancePanelViewModel(...)` 已把: - - `run summary` - - `scorecard` - - `evidence / review` - 收口成同一份业务向治理视图 - - 页面级治理看板当前已经能表达: - - 当前治理状态 - - 当前适合投放到哪里 - - 周会材料 / 结构化治理 / 请求链路 / 结果校验是否已齐 - - 推荐治理动作与继续处理入口 - - 页面级治理动作继续复用既有主链: - - `prepareSceneAppRunGovernanceArtifacts(...)` - - `prepareSceneAppRunGovernanceArtifact(...)` - - `initialProjectFileOpenTarget` - - `open automation job / agent session / browser runtime` - - 已同步更新: - - `src/lib/sceneapp/product.ts` - - `src/lib/sceneapp/product.test.ts` - - `src/components/sceneapps/SceneAppGovernancePanel.tsx` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `docs/exec-plans/limenext-plan.md` - - 当前已确认通过: - - `npx eslint --no-warn-ignored "src/lib/sceneapp/product.ts" "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppGovernancePanel.tsx" "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm test -- "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - 当前已发起但尚未拿到最终结果: - - `npm run verify:gui-smoke` - - 本机冷编译阶段长时间卡在 `bridge:health -> DevBridge` 启动前,日志持续显示 `rustc` 编译与 `fetch failed`,暂时无法给出 smoke 通过结论 - -- 把 `SceneApp project pack` 第二阶段从 `metadata artifact_paths` 启发式推进到 `session / evidence` 事实源: - - `runtime_evidence_pack_service` 已抽出可复用 helper: - - `resolve_runtime_export_workspace_root(...)` - - `build_runtime_evidence_sceneapp_snapshot(...)` - - `SceneApp` 运行摘要在拿到 `sessionId` 时,已优先读取: - - `SessionDetail` - - `AgentRuntimeThreadReadModel` - - 最近 `FileArtifact` - - verification failure outcomes - - `SceneApp project pack` 不再默认先信 `AgentRun.metadata.artifact_paths`,而是改成: - - 有 runtime evidence 时优先用真实会话产物 - - 只有缺少 session evidence 时才回退 metadata - - 交付覆盖率判断已纠正: - - 如果 session evidence 明确存在但没有产物,现在会把覆盖率视为“已知为 0”,而不是继续落成“未知” - - 因此运行详情能够明确给出 `missing parts / 0% / pack_incomplete` - - `verification failure outcomes` 已开始回挂到 SceneApp 失败信号: - - 即使部件齐全,只要 runtime evidence 里还有未恢复校验失败,也会标记为 `review_blocked` - - `SceneAppService` 已统一改走 `build_sceneapp_run_summary_from_agent_run_with_db(...)`,避免 tracker 和 automation 侧继续各自走旧启发式 - - 已补 Rust 定向回归: - - runtime evidence 优先于 metadata artifact 列表 - - runtime verification failure 会回挂成 `review_blocked` - - 已同步更新: - - `src-tauri/src/services/runtime_evidence_pack_service.rs` - - `src-tauri/src/commands/aster_agent_cmd/command_api/runtime_api.rs` - - `src-tauri/src/sceneapp/adapters.rs` - - `src-tauri/src/sceneapp/application.rs` - - `src-tauri/src/services/execution_tracker_service.rs` - - 本轮校验已确认通过: - - `cargo fmt --manifest-path "src-tauri/Cargo.toml"` 已执行 - - `cargo test --manifest-path "src-tauri/Cargo.toml" sceneapp::adapters -- --nocapture` - - `cargo test --manifest-path "src-tauri/Cargo.toml" sceneapp::governance -- --nocapture` - -- 把 `SceneApp project pack` 的结果入口从“viewer 文案”推进到“稳定可打开的交付文件引用”: - - Rust `SceneAppRunSummary` 已新增 `deliveryArtifactRefs` - - 结果入口聚合规则已固定为: - - 有 runtime evidence 时优先读取真实 `FileArtifact` - - 缺少 session evidence 时再回退 `metadata artifact_paths` - - 继续在 DTO 层暴露 `relativePath / absolutePath / partKey / projectId / workspaceId / source` - - 前端运行详情页已新增“结果入口”区块: - - 会按 `primaryPart` 优先标记主稿 - - 点击后继续复用现有 `Agent initialProjectFileOpenTarget` 打开结果文件 - - 不新增新的 SceneApp viewer 协议,也不让 UI 直接解读底层 metadata - - 已同步更新: - - `src-tauri/src/services/runtime_evidence_pack_service.rs` - - `src-tauri/src/sceneapp/dto.rs` - - `src-tauri/src/sceneapp/adapters.rs` - - `src-tauri/src/sceneapp/application.rs` - - `src-tauri/src/sceneapp/governance.rs` - - `src/lib/sceneapp/types.ts` - - `src/lib/sceneapp/product.ts` - - `src/components/sceneapps/SceneAppRunDetailPanel.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.tsx` - - 当前已确认通过: - - `cargo fmt --manifest-path "src-tauri/Cargo.toml"` - - `npx eslint "src/lib/sceneapp/types.ts" "src/lib/sceneapp/product.ts" "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppRunDetailPanel.tsx" "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/lib/tauri-mock/core.ts"` - - `npm test -- "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `cargo test --manifest-path "src-tauri/Cargo.toml" sceneapp::adapters -- --nocapture` - - `cargo test --manifest-path "src-tauri/Cargo.toml" sceneapp::governance -- --nocapture` - - Rust 定向测试最终结果已确认通过: - - `cargo test --manifest-path "src-tauri/Cargo.toml" sceneapp::adapters -- --nocapture` - - `cargo test --manifest-path "src-tauri/Cargo.toml" sceneapp::governance -- --nocapture` - -- 把 `SceneApp project pack` 的治理面继续从“有证据文案”推进到“有治理入口文件引用”: - - Rust `SceneAppRunSummary` 已新增 `governanceArtifactRefs` - - 适配层会按 `sessionId` 组装三类稳定治理路径: - - `.lime/harness/sessions/{sessionId}/evidence/summary.md` - - `.lime/harness/sessions/{sessionId}/review/review-decision.md` - - `.lime/harness/sessions/{sessionId}/review/review-decision.json` - - 前端运行详情页已在“证据与复核”区块新增“治理入口”卡片: - - 证据摘要 - - 人工复核记录 - - 复核 JSON - - 点击后继续复用现有 `Agent initialProjectFileOpenTarget` 打开文件,不新增新的 SceneApp viewer 协议,也不让 UI 直接拼底层 metadata - - 已同步更新: - - `src-tauri/src/sceneapp/dto.rs` - - `src-tauri/src/sceneapp/adapters.rs` - - `src-tauri/src/sceneapp/application.rs` - - `src-tauri/src/sceneapp/governance.rs` - - `src/lib/sceneapp/types.ts` - - `src/lib/sceneapp/product.ts` - - `src/components/sceneapps/SceneAppRunDetailPanel.tsx` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `src/lib/sceneapp/product.test.ts` - - `src/lib/tauri-mock/core.ts` - - 当前已确认通过: - - `cargo fmt --manifest-path "src-tauri/Cargo.toml"` - - `npx eslint "src/lib/sceneapp/types.ts" "src/lib/sceneapp/product.ts" "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppRunDetailPanel.tsx" "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/lib/tauri-mock/core.ts"` - - `npm test -- "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - 当前未完成但已定位的阻塞: - - `cargo test --manifest-path "src-tauri/Cargo.toml" sceneapp::adapters -- --nocapture` - - `cargo test --manifest-path "src-tauri/Cargo.toml" sceneapp::governance -- --nocapture` - - 两条 Rust 定向测试都会被仓库里无关编译错误挡住: - - `crates/services/src/api_key_provider_service.rs:1152` - - `cannot find value 'provider_type' in this scope` - -- 把 `SceneApp project pack` 的治理入口继续从“可打开”推进到“缺失时自动补生成”: - - 新增当前命令: - - `sceneapp_prepare_run_governance_artifact` - - 命令职责固定为: - - `evidence_summary` 只补导出 evidence pack - - `review_decision_markdown / review_decision_json` 走统一 review decision 模板导出链 - - 这样 SceneApp 页面不需要直接调用 `agent_runtime_export_evidence_pack` / `agent_runtime_export_review_decision_template` - - 前端交互已改成: - - 点击治理入口时先调用 `src/lib/api/sceneapp.ts` - - 导出成功后继续复用 `initialProjectFileOpenTarget` 打开对应治理文件 - - 命令边界已同步更新: - - `src-tauri/src/commands/sceneapp_cmd.rs` - - `src-tauri/src/app/runner.rs` - - `src/lib/api/sceneapp.ts` - - `src/lib/api/sceneapp.test.ts` - - `src/lib/dev-bridge/mockPriorityCommands.ts` - - `src/lib/governance/agentCommandCatalog.json` - - `src/lib/tauri-mock/core.ts` - - 页面与回归已同步更新: - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `src/lib/sceneapp/product.ts` - - 当前已确认通过: - - `cargo fmt --manifest-path "src-tauri/Cargo.toml"` - - `npx eslint --no-warn-ignored "src/lib/api/sceneapp.ts" "src/lib/api/sceneapp.test.ts" "src/lib/sceneapp/product.ts" "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/lib/dev-bridge/mockPriorityCommands.ts" "src/lib/tauri-mock/core.ts"` - - `npm test -- "src/lib/api/sceneapp.test.ts" "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm run test:contracts` - - 当前未完成但已定位的阻塞: - - `cargo test --manifest-path "src-tauri/Cargo.toml" sceneapp::adapters -- --nocapture` - - 仍会被仓库里无关编译错误挡住: - - `crates/services/src/api_key_provider_service.rs:1439` - - `cannot find value 'provider_type' in this scope` - -- 把 `SceneApp project pack` 的治理面继续从“文件入口”推进到“业务动作”: - - 前端运行详情页已新增 `治理动作` 区块,而不只是列出治理文件: - - `准备周会复盘包` - - `准备结构化治理包` - - 当前动作语义固定为: - - 周会复盘包:批量补齐 `evidence_summary + review_decision_markdown`,随后直接打开人工复核记录 - - 结构化治理包:批量补齐 `evidence_summary + review_decision_markdown + review_decision_json`,随后直接打开复核 JSON - - 批量治理仍继续经由 `src/lib/api/sceneapp.ts` 网关串行调用当前 `sceneapp_prepare_run_governance_artifact`,不让页面直接耦合底层 runtime export 命令名 - - 运行详情文案已开始改成业务向表达: - - 什么动作适合周会复盘 - - 什么动作适合生成 / 看板 / 后续自动治理消费 - - 已同步更新: - - `src/lib/api/sceneapp.ts` - - `src/lib/api/sceneapp.test.ts` - - `src/lib/sceneapp/product.ts` - - `src/lib/sceneapp/product.test.ts` - - `src/components/sceneapps/SceneAppRunDetailPanel.tsx` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `docs/exec-plans/limenext-plan.md` - - 当前已确认通过: - - `npx eslint --no-warn-ignored "src/lib/api/sceneapp.ts" "src/lib/api/sceneapp.test.ts" "src/lib/sceneapp/product.ts" "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppRunDetailPanel.tsx" "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm test -- "src/lib/api/sceneapp.test.ts" "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - 正在补充: - - `npm run verify:gui-smoke` - - 当前仍在冷启动 Rust GUI smoke 编译链,尚未拿到最终结果 - -## 2026-04-15 - -### 已完成 - -- 把 `SceneApp project pack` 从“目录描述”推进到“真实运行与经营聚合”,不再只靠静态 profile 讲故事: - - Rust `run summary` 已补齐业务级交付字段: - - `deliveryRequiredParts` - - `deliveryCompletedParts` - - `deliveryMissingParts` - - `deliveryCompletionRate` - - `deliveryPartCoverageKnown` - - `failureSignal` - - `AgentRun.metadata.artifact_paths` 与 `AutomationJob.last_delivery` 现在都会统一装配到同一份 `delivery state`,前端不再只看到 `artifactCount` - - `project pack` 的 scorecard 已改成专用聚合,而不是继续混在通用成功率面板里: - - `complete_pack_rate` - - `review_pass_rate` - - `publish_conversion_rate` - - `observedFailureSignals` - - `topFailureSignal` - - SceneApp 运行详情页已能直接解释: - - 这次交齐了几项 - - 还缺哪些部件 - - 当前卡在哪个失败信号 - - 经营评分页已能同时区分: - - 基础设置包声明的静态经营口径 - - 真实运行样本回流出来的实际失败信号 - - 已同步更新: - - `src-tauri/src/sceneapp/dto.rs` - - `src-tauri/src/sceneapp/adapters.rs` - - `src-tauri/src/sceneapp/application.rs` - - `src-tauri/src/sceneapp/governance.rs` - - `src/lib/sceneapp/types.ts` - - `src/lib/sceneapp/product.ts` - - `src/components/sceneapps/SceneAppRunList.tsx` - - `src/components/sceneapps/SceneAppRunDetailPanel.tsx` - - `src/components/sceneapps/SceneAppScorecardPanel.tsx` - - `src/lib/tauri-mock/core.ts` - - 本轮已确认通过: - - `npx eslint "src/lib/sceneapp/product.ts" "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppRunList.tsx" "src/components/sceneapps/SceneAppRunDetailPanel.tsx" "src/components/sceneapps/SceneAppScorecardPanel.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/lib/tauri-mock/core.ts"` - - `npm test -- "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm run test:contracts` - - Rust 定向测试已发起,但当前本机还有另一条长时间运行的 cargo 编译链占用构建资源,SceneApp 相关测试还在等待最终结果,后续需要补回最终通过记录 - -- 把多模态 `SceneApp` 的 `project pack` 合同正式接到统一目录、产品视图与 GUI 主链,而不是继续停留在 `blueprint ref / profile ref` 级别: - - `src/lib/sceneapp/types.ts` - - `src/lib/sceneapp/catalog.ts` - - `src/lib/sceneapp/product.ts` - - `src/components/sceneapps/SceneAppDetailPanel.tsx` - - `src/components/sceneapps/SceneAppScorecardPanel.tsx` - - 当前 `SceneAppDescriptor` 已新增三块稳定结构: - - `deliveryProfile` - - `compositionProfile` - - `scorecardProfile` - - `project pack` 相关的: - - `artifact profile` - - `viewer kind` - - `required parts` - - `composition steps` - - `failure signals` - 现在都能从编译层一路进入业务向详情面板和经营评分面板 - - 目录页不再只展示技术 ref,而会明确表达: - - 最终交付什么项目包 - - 这条链分几步完成 - - 当前经营判断重点看什么 - - `SceneApp` 的 mock 与 Tauri seeded DTO 也已同步对齐,避免只在前端测试环境里有字段、真实命令却没有: - - `src/lib/tauri-mock/core.ts` - - `src-tauri/src/sceneapp/dto.rs` - - `src-tauri/src/sceneapp/catalog.rs` - - 定向回归已覆盖: - - `src/lib/sceneapp/catalog.test.ts` - - `src/lib/sceneapp/product.test.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - 本轮已确认通过: - - `npm test -- "src/lib/sceneapp/catalog.test.ts" "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npx eslint "src/lib/sceneapp/types.ts" "src/lib/sceneapp/catalog.ts" "src/lib/sceneapp/presentation.ts" "src/lib/sceneapp/product.ts" "src/lib/sceneapp/catalog.test.ts" "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppDetailPanel.tsx" "src/components/sceneapps/SceneAppScorecardPanel.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/lib/tauri-mock/core.ts"` - - `npm run test:contracts` - - `rustfmt --check "src-tauri/src/sceneapp/dto.rs" "src-tauri/src/sceneapp/catalog.rs"` - - 当前仓库级阻塞仍存在: - - `npm run typecheck` 会被无关现有错误挡住: - - `src/components/api-key-provider/ProviderConfigForm.ui.test.tsx` - - `src/components/settings-v2/general/memory/index.tsx` - - `npm run verify:gui-smoke` 在 `smoke:browser-runtime` 阶段被现有环境问题挡住: - - `launch_browser_session` 持续超时,`180000ms` 内未收到 DevBridge 响应 - - 日志中还出现 `libsqlite3-sys ... bindgen.rs: No such file or directory` 的临时构建噪音,需要后续单独排查 - -- 把 `SceneApp` 前端启动编排继续收口成共享 runtime,而不是让目录页和聊天空态各写一套 launch 分支: - - 新增共享启动状态机与错误格式化: - - `src/lib/sceneapp/error.ts` - - `src/lib/sceneapp/launcher.ts` - - 把前端 action bridge 正式迁到共享层: - - `src/lib/sceneapp/launchBridge.ts` - - `src/components/agent/chat/workspace/sceneAppLaunch.ts` - - 统一由共享层负责: - - `sceneAppLaunchingId` - - 自动化弹窗开关与初始值 - - automation workspace 加载 - - `workspace_entry / automation_job` 启动收口 - - SceneApp 相关错误文案格式化 - - 两个高频入口现在都已消费同一套共享 runtime: - - `src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.ts` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `sceneAppLaunch.ts` 旧路径暂时保留为 re-export,避免现有调用方与测试路径立刻断裂 -- 完成 SceneApp 统一启动 runtime 的一轮针对性校验: - - `npm test -- "src/components/agent/chat/workspace/sceneAppLaunch.test.ts" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.test.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/lib/sceneapp/product.test.ts"` 通过 - - `npx eslint "src/lib/sceneapp/error.ts" "src/lib/sceneapp/launchBridge.ts" "src/lib/sceneapp/launcher.ts" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.ts" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/agent/chat/workspace/sceneAppLaunch.ts"` 通过 - - `npm run typecheck` 通过 - - `npm run verify:gui-smoke` 在沙箱内仍会因为 `listen EPERM: operation not permitted 127.0.0.1:1420` 失败 - - 提权后重跑 `npm run verify:gui-smoke` 已证明: - - 前端壳就绪 - - `workspace-ready` 通过 - - `browser-runtime` 通过 - - `site-adapters` 通过 - - `agent-service-skill-entry` 通过 - - `agent-runtime-tool-surface` 通过 - - `agent-runtime-tool-surface-page` 通过 - - 仓库级页面 smoke 阻塞已收口: - - `scripts/agent-runtime-tool-surface-page-smoke.mjs` 现在补齐了首页 origin / storage 就绪门禁 - - `browser_execute_action` 增加了针对 `CDP 调试端口不可用` 的重试 - - 首页输入提交改成 `focus + native setter + input/change + 短暂让步 + 鼠标事件链`,避免卡在发送按钮未真正推进运行态 - - 当前这条 GUI 主路径已完成最终验证: - - `npm run verify:gui-smoke` 通过 - - `npm run smoke:agent-runtime-tool-surface-page -- --timeout-ms 180000 --interval-ms 1000` 通过 - -- 新增基础设置包第一版代码骨架: - - `src/lib/base-setup/types.ts` - - `src/lib/base-setup/validator.ts` - - `src/lib/base-setup/compiler.ts` - - `src/lib/base-setup/rolloutGate.ts` - - `src/lib/base-setup/compat/serviceSkillCatalogProjection.ts` - - 固定第一版先把 `Base Setup Package` 编译成 compat `ServiceSkillCatalog` - - 固定 runtime 侧暂不新增执行链,继续只吃 current `request_metadata` -- 新增基础设置包主链接线模块: - - `src/lib/base-setup/storage.ts` - - `src/lib/base-setup/bootstrap.ts` - - `src/lib/base-setup/serviceSkillCatalogAdapter.ts` - - 固定“解析 package -> gate -> compile -> 生成快照”由基础设置层统一负责 - - 固定基础设置快照与当前激活目录一起落缓存,避免后续 `scene / command` projection 再次各自找事实源 -- 把基础设置包正式接回当前目录主链: - - `src/lib/api/serviceSkills.ts` - - `src/lib/serviceSkillCatalogBootstrap.ts` - - 远端 `refresh`、本地 `save`、bootstrap `sync` 都已支持直接消费 `Base Setup Package` - - 普通 catalog 覆盖时会清理旧基础设置快照,保证当前激活目录与装配快照一致 -- 把基础设置包继续接到统一 `skill / command / scene` 目录主链: - - `src/lib/base-setup/compat/sceneCatalogProjection.ts` - - `src/lib/api/skillCatalog.ts` - - `src/lib/skillCatalogBootstrap.ts` - - `Base Setup Package` 现在已经不只会编译 compat `ServiceSkillCatalog`,也会继续投影到真实 `SkillCatalog` - - 显式 `scene_catalog` projection 已能进入 slash / scene 面板真实消费链,而不是只停在 schema 或 compat 层 - - `skillCatalog` 的 `refresh`、本地 `save`、bootstrap `sync` 现在都支持直接消费 `Base Setup Package` - - 显式 scene projection 会优先覆盖 compat 自动 scene,避免场景面板继续吃到旧的 auto scene 文案 -- 把 `Base Setup Package -> command_catalog projection` 正式接回当前输入触发层,而不是继续停在 seeded 手写 command 定义: - - `src/lib/base-setup/compat/commandCatalogProjection.ts` - - `src/lib/api/skillCatalog.ts` - - `src/lib/skillCatalogBootstrap.ts` - - `src/components/agent/chat/workspace/useWorkspaceSendActions.ts` - - `skillCatalog` 现在会和 `scene_catalog` 一样继续编译显式 `command_catalog` - - 显式 command projection 会优先覆盖 seeded command 定义,避免同一 `commandKey` 继续双轨并存 - - 工作区发送层不再只读模块加载时的 seeded command map,而会按当前目录快照解析 `mention -> commandKey -> bound skill` - - 这一步把 LimeNext 从“目录主链回到装配层”继续推进到了“现有命令语义的输入触发层也开始回到装配层” -- 把剩余 seeded command fallback 也迁回基础设置包事实源,清掉 `SEEDED_COMMAND_ENTRY_DEFINITIONS` 这条 compat 双轨: - - `src/lib/base-setup/types.ts` - - `src/lib/base-setup/serviceSkillCatalogAdapter.ts` - - `src/lib/base-setup/validator.ts` - - `src/lib/base-setup/compat/commandCatalogProjection.ts` - - `src/lib/base-setup/seededCommandPackage.ts` - - `src/lib/api/skillCatalog.ts` - - `command_catalog` projection 现在支持命令侧显式 `commandBinding / commandRenderContract` - - seeded fallback 不再维护手写 command entry 数组,而是直接编译 seeded `Base Setup Package` - - 这一步把 LimeNext 从“显式 command projection 可覆盖 seeded”继续推进到了“seeded command 事实源本身也回到装配层” -- 把默认云端 seeded 目录迁到装配层事实源: - - `src/lib/base-setup/seededServiceSkillPackage.ts` - - `src/lib/api/serviceSkills.ts` - - 默认 `7` 个内置云端场景不再手写为 `ServiceSkillCatalog`,而是改成手写 `Base Setup Package` 后编译出 compat catalog -- 把 seeded 本地 `local_custom` 项也迁到装配层事实源: - - `src/lib/base-setup/seededServiceSkillPackage.ts` - - `src/lib/base-setup/compat/serviceSkillCatalogProjection.ts` - - `src/lib/api/serviceSkills.ts` - - `x-article-export` 不再手写为 `ServiceSkillItem` 补丁,而是改成手写 `Base Setup Package` 后编译出 `local_custom` 目录项 - - 当前 seeded 目录已经从“编译产物 + 手写补丁”推进到“云端默认包编译产物 + 本地定制包编译产物” - - 同步纠正了 `sceneBinding` 不应强行把 `runnerType` 覆盖成 `managed` 的 compat 编译逻辑 -- 新增基础设置包单测: - - `src/lib/base-setup/validator.test.ts` - - `src/lib/base-setup/compiler.test.ts` - - `src/lib/base-setup/rolloutGate.test.ts` - - `src/lib/base-setup/storage.test.ts` - - `src/lib/base-setup/bootstrap.test.ts` - - `src/lib/base-setup/seededServiceSkillPackage.test.ts` - - 证明结构校验、引用校验、catalog projection 与 rollout gate 决策已跑通 -- 新增 `scene_catalog` 接线回归: - - `src/lib/api/skillCatalog.test.ts` - - `src/lib/skillCatalogBootstrap.test.ts` - - 证明 `Base Setup Package -> SkillCatalog` 已跑通 - - 证明 bootstrap payload 直接下发 `baseSetupPackage` 时,`scene_catalog` projection 与基础设置快照都能落到真实消费链 - - 证明显式 scene projection 已能覆盖 compat 自动 scene -- 新增 seeded 本地定制装配回归: - - `src/lib/base-setup/seededServiceSkillPackage.test.ts` - - `src/lib/api/serviceSkills.test.ts` - - 证明 `x-article-export` 已由本地定制基础设置包编译生成,而不是继续依赖手写补丁 - - 证明 `local_custom` 来源、`browser_assist` binding、`sceneBinding` 与 skill bundle metadata 都已稳定保留 -- 新增基础设置包实现设计专题: - - [base-setup-implementation.md](../roadmap/limenext/base-setup-implementation.md) - - 固定第一版先以 `Base Setup Package -> compat ServiceSkillCatalog projection` 落地 - - 固定第一版不重写产品面 API,而是先改 `ServiceSkillCatalog` 背后的编译来源 - - 固定 validator / compiler / rollout gate 的建议模块拆分与接线顺序 -- 新增基础设置包投影与发布生命周期专题: - - [base-setup-projection-lifecycle.md](../roadmap/limenext/base-setup-projection-lifecycle.md) - - 固定装配包从编写、校验、投影编译、灰度发布、bootstrap 拉取、seeded 兜底到回滚的完整链路 - - 固定最小 validator 分层:`L0 结构 / L1 装配 / L2 宿主边界` - - 固定“只要 L2 不通过,就必须升级主 App”的门禁 -- 新增基础设置包顶层 schema: - - [base-setup-package-schema.md](../roadmap/limenext/base-setup-package-schema.md) - - 固定 `Base Setup Package` 的 v1 顶层字段、目录投影、profile 结构与最小 validator 口径 - - 固定“改包、改投影、改宿主”的判断表 -- 新增组合蓝图 schema 草案: - - [composition-blueprint-schema.md](../roadmap/limenext/composition-blueprint-schema.md) - - 固定 `composition blueprint` 的 v1 顶层字段、步骤字段、校验规则与 `project_pack` 最小合同 - - 固定 v1 只支持“有序步骤链”,不先做通用 DAG -- 继续收口 LimeNext 总纲,明确平台主张不仅是“场景工作台”,也是“快捷组合多模态能力的 SceneApp factory” -- 在以下文档中引入统一口径: - - [README.md](../roadmap/limenext/README.md) - - [prd.md](../roadmap/limenext/prd.md) - - [architecture.md](../roadmap/limenext/architecture.md) - - [sceneapp-capability-model.md](../roadmap/limenext/sceneapp-capability-model.md) - - [sceneapp-blueprints.md](../roadmap/limenext/sceneapp-blueprints.md) - - [flowcharts.md](../roadmap/limenext/flowcharts.md) - - [sequences.md](../roadmap/limenext/sequences.md) - - [artifact-evidence-scorecards.md](../roadmap/limenext/artifact-evidence-scorecards.md) - - [metrics-and-selection.md](../roadmap/limenext/metrics-and-selection.md) - - [execution-plan.md](../roadmap/limenext/execution-plan.md) - - [base-setup-decoupling.md](../roadmap/limenext/base-setup-decoupling.md) - - [agent-skills-profile.md](../roadmap/limenext/agent-skills-profile.md) -- 把 `composition blueprint` 固定为基础设置包中的通用装配对象: - - `recipe` 只保留为别名 - - 不新增 runtime taxonomy - - 不新增第六种 binding family -- 把第一条组合型样板正式收口为: - - `文本 -> 线框图 -> 配乐 -> 剧本 -> 短视频草稿` - - 归类为 `Hybrid / Multimodal Composition SceneApp` - - 交付合同固定为 `project pack` -- 把 LimeNext 业务图和业务时序继续改成“非技术同学也能看懂”的版本: - - 增加多模态组合业务流图 - - 增加基础设置包如何下发组合场景的技术图 - - 增加组合蓝图编排多模态结果链的业务 / 技术时序 -- 更新执行计划与总实施计划: - - [execution-plan.md](../roadmap/limenext/execution-plan.md) - - [limenext-plan.md](./limenext-plan.md) - - 明确多模态组合样板成为第五条默认样板链路 - - 明确当前下一刀已经切到“seeded 事实源迁移 + scene / command projection 扩展” -- 把 `SceneApp` 第一阶段全栈骨架正式落地到当前代码主链: - - `src/lib/sceneapp/*` - - `src/lib/api/sceneapp.ts` - - `src-tauri/src/sceneapp/*` - - `src-tauri/src/commands/sceneapp_cmd.rs` - - `docs/roadmap/limenext/sceneapp-*.md` - - 固定 `SceneApp` 不新增 runtime taxonomy,继续只作为 `Scene / ServiceSkill + 执行实体 + 基础设施画像 + 交付治理` 的装配层 -- 把第一条真实 `SceneApp` adapter 固定为 `SceneApp -> automation job`: - - `sceneapp_create_automation_job` 已接通 automation draft / tracker metadata / run summary 主链 - - `daily-trend-briefing` 已作为 `Local Durable SceneApp` 的 seeded descriptor、mock catalog 与测试样板统一事实源 - - `browser_assist / cloud_scene / native_skill / agent_turn` 其他 adapter 继续留在下一阶段推进 -- 把 `sceneapp_plan_launch` 从抽象 planner 推进到半结构化 adapter planner: - - `SceneAppPlanResult.plan.adapterPlan` 已能明确输出 `runtimeAction / targetRef / requestMetadata / launchPayload` - - 当前已覆盖 `cloud_scene / browser_assist / automation_job / native_skill / agent_turn` 五类 adapter draft - - 这让后续 SceneApp UI 和执行入口可以复用 current runtime,而不是再拼第二套 SceneApp 执行协议 -- 把 `SceneAppPlanResult.plan.adapterPlan` 继续收口成前端统一执行 facade: - - `src/lib/sceneapp/launch.ts` - - `buildSceneAppExecutionDraft(...)` 现已固定输出两类 current runtime 草稿: - - `workspace_entry` - - `automation_job` - - `workspace_entry` 继续复用当前工作区启动语义: - - `prompt` - - `initialAutoSendRequestMetadata` - - `projectId / contentId` - - `openBrowserAssistOnMount` - - `automation_job` 同时兼容当前两条自动化主链: - - `SceneAppAutomationIntent` - - `AutomationJobRequest` - - `AutomationJobDialogInitialValues` - - 这意味着 SceneApp 前端后续接线时,不必再让各个页面自己理解 `adapterPlan.launchPayload` 的 snake_case 草稿 - - 新增 SceneApp 执行 facade 回归: - - `src/lib/sceneapp/launch.test.ts` - - 覆盖 `cloud_scene / browser_assist / automation_job` 三条主链翻译 - - 证明 `story-video-suite / x-article-export / daily-trend-briefing` 已有可复用的前端执行草稿 -- 把 SceneApp 前端执行草稿继续接到真实前端 action bridge: - - `src/components/agent/chat/workspace/sceneAppLaunch.ts` - - 当前已形成统一 `SceneApp launch action bridge`: - - `resolveSceneAppLaunchAction(...)` - - `executeSceneAppLaunchAction(...)` - - `workspace_entry` 现在会继续翻译成真实 `resolveWorkspaceEntry(...)` 结果,而不是让 UI 自己再拼导航参数 - - `automation_job` 现在支持两条 current 前端路径: - - 打开标准自动化表单 - - 直接调用 `sceneapp_create_automation_job` - - 这让未来的 SceneApp 目录页、详情页、推荐位都可以复用同一套启动动作桥,而不是各写一份 launch 分支 -- 新增 SceneApp action bridge 回归: - - `src/components/agent/chat/workspace/sceneAppLaunch.test.ts` - - 覆盖: - - `workspace_entry -> agent navigation` - - `workspace_entry -> missing project` - - `workspace_entry -> missing navigate callback` - - `automation_job -> open dialog` - - `automation_job -> create job` - - 再补 `workspaceEntry.test.ts` 联动回归,证明新桥未偏离现有工作区导航合同 -- 把 SceneApp 统一启动桥真正接到主工作区空态入口: - - `src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.ts` - - `src/components/agent/chat/components/EmptyStateSceneAppsPanel.tsx` - - `src/components/agent/chat/sceneappEntryTypes.ts` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/workspace/chatSurfaceProps.ts` - - `src/components/agent/chat/workspace/WorkspaceConversationScene.tsx` - - `src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - 当前 `SceneApp` 已不再只停在库层: - - `story-video-suite` 会从空态推荐位直接进入当前会话继续 - - `daily-trend-briefing` 会直接打开标准自动化表单 - - `x-article-export` 会在检测到 URL 上下文时进入推荐位 - - 固定 `SceneApp` 自动化仍复用标准 `AutomationJobDialog` 与 `create_automation_job` 主链,只在 UI 层补回 `sceneapp` metadata,不新增第二套 editor -- 新增 SceneApp 工作区入口回归: - - `src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.test.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - `src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.test.ts` - - 覆盖: - - featured SceneApp 卡片分类 - - URL 条件显示 `x-article-export` - - `workspace_entry -> agent` 导航 - - `automation_job -> 标准自动化表单 -> create_automation_job` -- 把 `SceneApp` 从“空态推荐位”推进成真正的目录工作台: - - 新增独立页面与信息架构入口: - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsCatalogPanel.tsx` - - `src/components/sceneapps/SceneAppDetailPanel.tsx` - - `src/components/sceneapps/SceneAppScorecardPanel.tsx` - - `src/components/sceneapps/SceneAppRunList.tsx` - - `src/components/sceneapps/index.ts` - - `src/types/page.ts` - - `src/components/AppPageContent.tsx` - - `src/lib/navigation/sidebarNav.ts` - - 当前目录页已经具备完整闭环: - - 业务向目录检索与模式筛选 - - 详情页、启动输入、项目工作区选择 - - `workspace_entry -> agent` 启动 - - `automation_job -> AutomationJobDialog -> create_automation_job` - - `scorecard + recent runs` 统一回流展示 - - 同时把 `SceneApp` 展示语义和自动化辅助从聊天工作区抽成共享层: - - `src/lib/sceneapp/presentation.ts` - - `src/lib/sceneapp/automation.ts` - - 这意味着后续再扩: - - 首页推荐位 - - 目录页 - - 详情页 - - 未来更多入口 - 都不需要各写一份 `SceneApp` 文案、seed、project gate、automation metadata merge -- 把 `SceneApp` 目录页入口继续收口成可恢复的跨入口协议: - - `src/lib/sceneapp/entry.ts` - - `src/lib/sceneapp/storage.ts` - - 当前已固定三种目录进入模式: - - `browse` - - `resume_latest` - - `prefer_latest` - - 这让侧边栏、聊天空态、未来插件入口都不需要自己拼“最近访问优先还是浏览目录”的判断 - - 最近访问存储同时新增统一订阅能力,跨入口 UI 可以感知“是否存在可恢复场景”,而不用自己读取 localStorage 细节 -- 把 `SceneApp` 最近恢复能力接回两个高频入口: - - `src/lib/navigation/sidebarNav.ts` - - `src/components/AppSidebar.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/components/agent/chat/components/EmptyStateSceneAppsPanel.tsx` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/workspace/chatSurfaceProps.ts` - - `src/components/agent/chat/workspace/WorkspaceConversationScene.tsx` - - `src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.tsx` - - 当前交互已经更清楚: - - 侧边栏“场景应用”默认恢复最近一次 SceneApp 上下文 - - 聊天空态显式区分“继续最近场景”和“查看全部场景” - - 浏览目录与恢复上次上下文不再共用一个语义模糊的按钮 -- 新增最近恢复链路回归: - - `src/lib/sceneapp/entry.test.ts` - - `src/lib/sceneapp/storage.test.ts` - - `src/components/AppSidebar.test.tsx` - - `src/components/agent/chat/components/EmptyState.test.tsx` - - 证明: - - 最近访问订阅已生效 - - 侧边栏点击会优先恢复最近 SceneApp - - 空态会显式暴露“继续最近场景”动作 -- 把 `SceneApp` 目录页继续推进到独立的产品视图模型层: - - `src/lib/sceneapp/product.ts` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src/components/sceneapps/SceneAppsCatalogPanel.tsx` - - `src/components/sceneapps/SceneAppDetailPanel.tsx` - - `src/components/sceneapps/SceneAppScorecardPanel.tsx` - - `src/components/sceneapps/SceneAppRunList.tsx` - - `src/components/sceneapps/SceneAppRunDetailPanel.tsx` - - 当前 `SceneAppsPage` 已不再让组件自己直接解释底层 DTO: - - workbench summary stats - - catalog card copy - - detail panel copy - - scorecard view - - run list / run detail - 都统一收口到 `SceneApp product view model` - - 这让后续首页推荐位、独立详情页、经营面板可以复用同一层业务解释,而不是重复从 `descriptor / run / scorecard` 重新拼 UI -- 新增产品视图模型回归: - - `src/lib/sceneapp/product.test.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - 证明目录统计、详情视图和运行详情已经可以通过共享产品层稳定产出 -- 把空态 SceneApp 面板补上“查看全部场景”入口,并接到统一 `sceneapps` 目录页: - - `src/components/agent/chat/components/EmptyStateSceneAppsPanel.tsx` - - `src/components/agent/chat/components/EmptyState.tsx` - - `src/components/agent/chat/workspace/chatSurfaceProps.ts` - - `src/components/agent/chat/workspace/WorkspaceConversationScene.tsx` - - `src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.tsx` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - 现在用户可以: - - 在聊天空态直接启动精选 SceneApp - - 或跳到完整目录页再选型、看 scorecard、看 runs、再启动 -- 新增 SceneApp 目录页回归与路由回归: - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `src/components/AppPageContent.test.tsx` - - `src/hooks/useAppNavigation.test.tsx` - - `src/lib/navigation/sidebarNav.test.ts` - - 覆盖: - - 目录页渲染与详情联动 - - `workspace_entry -> agent` - - `automation_job -> 标准自动化弹窗` - - 侧边栏与页面分发接线 -- 把 SceneApp 目录页继续补到“运行详情可经营”的状态: - - `src/components/sceneapps/SceneAppRunDetailPanel.tsx` - - `src/components/sceneapps/SceneAppRunList.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/lib/sceneapp/presentation.ts` - - 当前目录页已经形成: - - `runs -> selected run -> run summary` 的独立状态流 - - `scorecard` 与 `runs` 解耦加载,不再因为一个接口失败把另一块也清空 - - 运行来源、运行阶段、下一步动作的共享解释层 - - 这意味着目录页不再只展示“最近运行列表”,而开始具备真实的运行复盘面板 - - 后续再接首页推荐位、运营面板或更细颗粒的 evidence 视图时,可以继续复用同一套 run presentation 语义 -- 把 SceneApp 目录页继续补到“状态可恢复、可分享”的状态: - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `src/components/AppPageContent.test.tsx` - - `src/types/page.ts` - - 当前目录页现在已经支持把以下状态安全回写到 `pageParams`: - - `sceneappId` - - `runId` - - `projectId` - - `search` - - `prefillIntent` - - `typeFilter / patternFilter` - - 同时补了反向回灌: - - 同页再次导航到 `sceneapps` 时,目录页会用新的 `pageParams` 覆盖本地状态 -- 把 SceneApp 运行详情继续补到“可回到业务入口”的状态: - - `src/lib/sceneapp/types.ts` - - `src/lib/sceneapp/product.ts` - - `src/components/sceneapps/SceneAppRunDetailPanel.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.tsx` - - `src-tauri/src/sceneapp/dto.rs` - - `src-tauri/src/sceneapp/adapters.rs` - - `src-tauri/src/sceneapp/application.rs` - - 当前目录页已经不再只是解释“这次跑完了什么”,还开始解释“现在该回哪里继续”: - - `SceneAppRunSummary` 新增 `sourceRef` - - 运行详情视图模型新增 `entryAction` - - 第一条真实恢复动作先固定为 `automation -> job detail` - - 第二条真实恢复动作已补成 `chat / skill -> agent session` - - 目录页运行详情现在可以直接跳回对应自动化任务: - - `source=automation` - - `sourceRef=jobId` - - 页面 runtime 会统一翻译成 `automation / selectedJobId / workspaceTab=tasks` - - 目录页运行详情现在也可以直接回到对应 Agent 会话: - - `SceneAppRunSummary` 新增 `sessionId` - - Agent 页新增 `initialSessionId` - - `source=chat / skill` 且存在 `sessionId` 时,会统一翻译成 `agent -> initialSessionId` - - 这一步把 `SceneApp` 从“可启动、可复盘”继续推进到“可恢复到业务入口”,为后续 agent / browser runtime 深链收口留出统一合同 -- 把 `browser_assist` 场景的运行恢复也接回统一协议,而不是继续由 UI 猜测浏览器上下文: - - `src/lib/sceneapp/types.ts` - - `src/lib/sceneapp/product.ts` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - `src-tauri/src/sceneapp/dto.rs` - - `src-tauri/src/sceneapp/adapters.rs` - - `src-tauri/src/commands/aster_agent_cmd/run_metadata/social_artifacts.rs` - - `src-tauri/src/commands/aster_agent_cmd/tests.rs` - - 当前已固定第一版浏览器恢复对象为: - - `browserRuntimeRef = { profileKey, sessionId, targetId }` - - 运行详情视图模型新增 `open_browser_runtime` 动作: - - 浏览器场景存在 `browserRuntimeRef` 时,优先回到 `browser-runtime` - - 没有浏览器引用时,`chat / skill -> agent session` 仍作为稳定兜底 - - Rust 侧运行摘要现在会统一合并两类事实源: - - 运行终态 metadata 里的 `browser_runtime_ref / browser_session` - - request metadata 里的 `browser_assist` - - 运行观测层也开始把 tool result metadata 中的浏览器会话回写到 run metadata: - - `profile_key` - - `session_id` - - `target_id` - - 这意味着 `x-article-export` 这类 `Browser-grounded SceneApp` 终于可以从目录页直接回到真实浏览器运行时,而不是只回聊天页 -- 把 `cloud_scene / native_skill` 也补进同一套 SceneApp 启动与恢复合同,而不是继续在 UI 层分散猜测 metadata: - - `src/lib/sceneapp/types.ts` - - `src/lib/sceneapp/product.ts` - - `src/lib/sceneapp/launch.ts` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/components/agent/chat/workspaceEntry.ts` - - `src/components/agent/chat/workspace/useWorkspaceServiceSkillEntryActions.ts` - - `src/components/agent/chat/AgentChatWorkspace.tsx` - - `src/types/page.ts` - - `src-tauri/src/sceneapp/dto.rs` - - `src-tauri/src/sceneapp/adapters.rs` - - 当前已固定两类新恢复引用: - - `cloudSceneRuntimeRef` - - `nativeSkillRuntimeRef` - - 当前目录页运行详情新增两类结构化业务动作: - - `open_cloud_scene_session` - - `open_native_skill_session` - - `cloud_scene` 现在不再只回退到普通会话: - - 有 `sessionId` 时优先回到原 Agent 会话 - - 没有 `sessionId` 时,会基于 `service_scene_launch` 结构化引用重新恢复云端 Scene 上下文 - - `native_skill` 启动桥也不再伪装成普通 prompt: - - SceneApp launch facade 现在会产出 `initialPendingServiceSkillLaunch` - - `AgentPendingServiceSkillLaunch` 新增 `skillKey / launchUserInput` - - 挂起技能入口现在可以保留原始 SceneApp 用户意图和已补齐 slots,再交给现有服务技能主链继续执行 - - Rust 侧运行摘要现在会统一提取两类事实源: - - `service_scene_launch` - - `sceneapp_native_skill_launch` - - 这意味着 SceneApp 的五类 current 执行体已经全部进入统一协议: - - `automation_job` - - `agent_turn` - - `browser_assist` - - `cloud_scene` - - `native_skill` -- 把 SceneApp 运行复盘与评分从 seeded 模板推进到真实聚合: - - `src-tauri/src/sceneapp/adapters.rs` - - `src-tauri/src/sceneapp/application.rs` - - `src-tauri/src/sceneapp/governance.rs` - - `src-tauri/src/commands/sceneapp_cmd.rs` - - `sceneapp_list_runs` 现在会统一聚合: - - `ExecutionTracker` 里的 chat / skill / automation 真实运行 - - 自动化任务的 durable job 记录 - - 没有真实样本时才回退 seeded baseline - - `sceneapp_get_scorecard` 现在会基于真实 runs 计算: - - 运行样本充足度 - - 执行成功率 - - 结果产出率 - - 重复使用率 - - 推荐动作也不再只按 `sceneapp_type` 写死,而会根据真实运行表现切到: - - `launch` - - `keep` - - `optimize` - - `retire` - - 同时补了 Rust 定向回归,覆盖: - - artifact count 从 run metadata / automation delivery 提取 - - scorecard 的 `keep` / seeded fallback / `retire` 决策 - - 不再只在首次挂载时读取参数 - - 固定实现规则: - - 文本类参数使用轻量防抖同步,避免输入时触发导航风暴 - - 统一 `normalize + serialize` 单一键值比较,不让页面和导航层各自发明一套相等性判断 - - 这意味着未来再做: - - 最近访问的 SceneApp 恢复 - - 可复制的目录页深链接 - - 从聊天页/推荐位/运营面板跳回目录的状态保持 - 都可以继续复用当前参数协议 -- 把 SceneApp 前台继续接到 `Base Setup Package` 的 scorecard / composition 装配层: - - `src/lib/sceneapp/catalog.ts` - - `src/lib/sceneapp/product.ts` - - `src/components/sceneapps/SceneAppDetailPanel.tsx` - - `src/components/sceneapps/SceneAppScorecardPanel.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - `src/lib/sceneapp/catalog.test.ts` - - `src/lib/sceneapp/product.test.ts` - - `src/components/sceneapps/SceneAppsPage.test.tsx` - - 当前目录页已经不再只显示 seeded 业务文案,而会继续暴露基础设置包里的: - - `compositionBlueprintRef / compositionStepCount` - - `scorecardProfileRef / scorecardMetricKeys` - - 详情面板现在可以直接看到组合蓝图和评分 profile - - 评分面板现在也会沿 view model 主链显示当前 scorecard profile 与 metric keys,而不是重新耦合 raw descriptor - - 即使还没有真实评分样本,评分面板也会先保留基础设置包里的观察口径,不再整块退回“纯空态” - - 即使评分接口暂时失败,评分面板也会继续保留当前 profile 与指标口径,不再因为 error state 把装配层上下文一起抹掉 - - 这意味着 `Base Setup Package -> SceneApp descriptor -> product view model -> SceneAppsPage` 这条前台消费链已经闭环 -- 把 SceneApp 目录页继续补到“最近访问 / 一键继续”的状态: - - `src/lib/sceneapp/navigation.ts` - - `src/lib/sceneapp/storage.ts` - - `src/lib/sceneapp/storage.test.ts` - - `src/components/sceneapps/SceneAppsRecentPanel.tsx` - - `src/components/sceneapps/useSceneAppsPageRuntime.ts` - - 当前目录页现在已经具备: - - `SceneApp` 最近访问记录的统一本地事实源 - - `sceneappId + projectId` 维度去重更新,而不是无上限堆积重复记录 - - “继续上次上下文”与最近场景列表的业务入口 - - 同时补了一个重要门禁: - - 空参打开目录页时,默认首项自动选中不会立刻写回导航和最近访问 - - 只有显式页面参数或用户真实交互后,才会触发同步与持久化 - - 这意味着后续再接: - - 侧边栏空参进入后的恢复入口 - - 首页推荐位跳转后的回流继续 - - 场景运营面板的最近活跃列表 - 都可以复用同一套 `SceneApp page state + recent visit` 协议 - -### 当前判断 - -- LimeNext 现在不该再被理解成“很多单点场景的目录”,而应被理解成“场景对象 + 组合蓝图 + 结果包”的装配平台 -- `composition blueprint` 这层已经进入正式文档口径,后续可以继续下沉到 schema、投影和校验规则 -- `composition blueprint` 现在已经不只是术语,而有了 v1 schema 草案和最小 validator 口径 -- `Base Setup Package` 现在也不再只是概念层,而有了顶层对象、目录投影和兼容性校验口径 -- 基础设置包现在不仅回答“长什么样”,也开始回答“怎么发布、怎么灰度、怎么回滚” -- 基础设置包这条线现在也开始回答“第一版先改什么代码、先不改什么代码” -- 基础设置包这条线现在已经不只是文档设计,而有了第一版代码骨架和最小单测闭环 -- 基础设置包这条线现在也不再只是“独立模块可跑”,而是已经接回 `serviceSkills.ts` 与 bootstrap 的真实主链 -- 基础设置包这条线现在还开始接管默认 seeded 云端目录,说明装配层已经不再只是“远端来的东西才走” -- 基础设置包这条线现在也开始接管 seeded 本地定制项,说明内置目录的主要来源已经都回到装配层 -- 基础设置包这条线现在也已经接回 `skillCatalog.ts` 与 `skillCatalogBootstrap.ts`,说明 `scene_catalog` 不再只是未来规划,而是进入真实产品入口 -- `SceneApp` 这一层现在也不再只是路线图术语,而已经具备前后端统一 descriptor、命令边界、durable adapter 与治理 metadata 主链 -- `SceneApp` planner 现在也不再只会输出“解释性步骤”,而开始输出可执行的 current runtime adapter draft -- `SceneApp` 前端现在也不再只有 planner 结果,而开始具备统一 execution draft facade,说明 `adapterPlan` 已经进入可接线阶段 -- `SceneApp` 前端现在也不再只有 execution draft facade,而开始具备真实 action bridge 与首个空态业务入口,说明“库层桥接”这一刀已经完成 -- `SceneApp` 统一恢复协议现在也不再只覆盖前三条浅链,而是已经把 `browser_assist / cloud_scene / native_skill` 的深链恢复一起收口 -- 当前 `SceneApp` 首页入口已经开始用业务语言而不是 runtime 术语表达: - - 多模态组合 - - 资料沉淀 - - 持续研究 -- `SceneApp` 消费层现在已经不再只有空态推荐,而开始具备真正的目录工作台、详情页、scorecard 和 recent runs 视图 -- 当前四类样板已经覆盖: - - 浏览器采集导出 - - 云端托管媒体生产 - - 本地持续跟踪 - - 多模态组合结果链 -- 基础设置包现在已经不只是“目录下发”,还承担多步骤组合链的业务装配语义 -- durable 场景的 automation 装配现在也不再只靠 `slot.type=schedule_time` 和运行时临时拼装: - - `Base Setup Package` 已新增 `automationProfiles[]` - - `catalogProjection.automationProfileRef` 已进入 validator / parser / projection metadata / snapshot index - - `每日趋势摘要 / 账号增长跟踪` seeded durable 样板已显式声明 automation profile - - `service-skills/automationDraft.ts` 现在会优先消费装配层的 schedule / delivery / retry / enabled 预设,再回退到旧的 slot fallback -- durable 场景的 automation fallback 现在也开始回到同一装配主链: - - `src/lib/base-setup/automationProjection.ts` 已成为统一解析层 - - 当前 durable 启动不再需要直接读页面层或手写 seeded 补丁来猜 automation 默认值 - - `service_skill.request_metadata.base_setup` 也开始携带稳定的 package / projection / automation profile 引用,方便后续 automation detail / SceneApp run / scorecard 继续对齐同一事实源 - -### 风险 - -- 如果后续只把 `composition blueprint` 写成单一场景私有 workflow,通用装配层会再次失效 -- 如果后续让 `catalog projection`、`binding profile`、`artifact profile` 分别在不同文档里各说各话,基础设置包会再次失去顶层约束 -- 如果后续只写 schema,不把 validator / rollout / seeded fallback 做成真实门禁,团队还是会退回“改了文档等于完成” -- 如果后续跳过 compat projection,直接要求所有前台入口原生理解 `Base Setup Package`,改动面会过大,容易再次拖慢主线 -- 如果后续 `command_catalog` 或 automation projection 继续停在手写补丁层,装配主线仍然会长期半双轨 -- 如果后续把新增 `command_catalog` projection 误判成“已经支持任意新命令 DSL”,会高估当前阶段;现阶段仍主要服务现有命令语义的事实源收口 -- 如果后续 `SceneApp` UI 又回到从 `serviceSkills.ts`、`skillCatalog.ts`、selector 各自拼语义,统一 descriptor 主链会再次失效 -- 如果后续给组合型场景单独发明 viewer 或 binding,宿主边界会再次变模糊 -- 如果后续只看最终视频草稿成败,不看 `project pack` 接受率与阶段返工率,组合场景很容易被误判 - -### 下一刀 - -- durable 场景的 automation projection / fallback 已收口到装配主链,下一步转为: - - 基于 `base-setup-implementation.md` 决定第一版真实实现路线:客户端编译,还是服务端预编译 + 客户端 gate - - 把多模态组合样板的 `project pack` 接到真实 artifact / viewer / scorecard 聚合入口 - - 把 `SceneScorecard` 与周会模板、场景看板和生成口径继续打通 - - 继续把 automation detail / SceneApp run / scorecard 聚合层消费同一组 base-setup refs,而不是各自回退到运行时猜测 -- `SceneApp` 恢复协议当前已稳定收口到: - - `sourceRef` - - `sessionId` - - `browserRuntimeRef` - - `cloudSceneRuntimeRef` - - `nativeSkillRuntimeRef` -- `browser-runtime` GUI smoke 当前也已恢复通过,所以后续主线不再是“先救 smoke 环境”,而是“把组合交付和经营聚合真正接起来” - -### 验证 - -- 已执行: - - `npm run harness:doc-freshness` - - 结果:`clean` - - `npm test -- "src/lib/base-setup/validator.test.ts" "src/lib/base-setup/compiler.test.ts" "src/lib/base-setup/rolloutGate.test.ts" "src/lib/base-setup/storage.test.ts" "src/lib/base-setup/bootstrap.test.ts" "src/lib/base-setup/seededServiceSkillPackage.test.ts" "src/lib/api/serviceSkills.test.ts" "src/lib/serviceSkillCatalogBootstrap.test.ts"` - - 结果:`8 files / 34 tests passed` - - `npm test -- "src/lib/api/skillCatalog.test.ts" "src/lib/skillCatalogBootstrap.test.ts"` - - 结果:`2 files / 9 tests passed` - - `npm test -- "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/workspace/sceneAppLaunch.test.ts"` - - 结果:`3 files / 33 tests passed` - - `npm test -- "src/lib/sceneapp/product.test.ts" "src/lib/sceneapp/launch.test.ts" "src/components/agent/chat/workspace/sceneAppLaunch.test.ts" "src/components/agent/chat/workspaceEntry.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/lib/api/sceneapp.test.ts"` - - 结果:`6 files / 47 tests passed` - - `cargo test --manifest-path "src-tauri/Cargo.toml" sceneapp::adapters` - - 结果:`5 tests passed` - - `cargo test --manifest-path "src-tauri/Cargo.toml" sceneapp::governance` - - 结果:`3 tests passed` - - `npm run typecheck` - - 结果:`passed` - - `npm test -- "src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.test.ts"` - - 结果:`1 file / 7 tests passed` - - `npx eslint "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.ts" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.test.tsx" "src/components/agent/chat/components/EmptyStateSceneAppsPanel.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.tsx" "src/components/agent/chat/workspace/WorkspaceConversationScene.tsx" "src/components/agent/chat/workspace/chatSurfaceProps.ts"` - - 结果:`passed` - - `npm test -- "src/lib/base-setup/seededServiceSkillPackage.test.ts" "src/lib/api/serviceSkills.test.ts" "src/lib/api/skillCatalog.test.ts" "src/lib/serviceSkillCatalogBootstrap.test.ts" "src/lib/skillCatalogBootstrap.test.ts"` - - 结果:`5 files / 32 tests passed` - - `npm test -- "src/lib/base-setup/compat/commandCatalogProjection.test.ts" "src/lib/api/skillCatalog.test.ts" "src/lib/skillCatalogBootstrap.test.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx"` - - 结果:`4 files / 94 tests passed` - - `npx eslint "src/lib/base-setup/compat/commandCatalogProjection.ts" "src/lib/base-setup/compat/commandCatalogProjection.test.ts" "src/lib/api/skillCatalog.ts" "src/lib/api/skillCatalog.test.ts" "src/lib/skillCatalogBootstrap.test.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx"` - - 结果:`passed` - - `npm run verify:gui-smoke` - - 结果:通过 - - `npm run verify:local` - - 结果:通过 - - `npm test -- "src/lib/base-setup/automationProjection.test.ts" "src/lib/base-setup/validator.test.ts" "src/lib/base-setup/compiler.test.ts" "src/lib/base-setup/storage.test.ts" "src/lib/base-setup/seededServiceSkillPackage.test.ts" "src/components/agent/chat/service-skills/automationDraft.test.ts"` - - 结果:`6 files / 21 tests passed` - - `npm run typecheck` - - 结果:通过 - - `npx eslint "src/lib/base-setup/types.ts" "src/lib/base-setup/serviceSkillCatalogAdapter.ts" "src/lib/base-setup/validator.ts" "src/lib/base-setup/compat/serviceSkillCatalogProjection.ts" "src/lib/base-setup/seededServiceSkillPackage.ts" "src/lib/base-setup/automationProjection.ts" "src/lib/base-setup/automationProjection.test.ts" "src/lib/base-setup/storage.test.ts" "src/lib/base-setup/seededServiceSkillPackage.test.ts" "src/lib/base-setup/validator.test.ts" "src/lib/sceneapp/catalog.test.ts" "src/components/agent/chat/service-skills/automationDraft.ts" "src/components/agent/chat/service-skills/automationDraft.test.ts"` - - 结果:通过 - - `npm run verify:local` - - 结果:未通过;当前仓库另一路改动在 `src/components/settings-v2/general/memory/index.tsx:269` 存在已有 lint parse error,阻塞全仓门槛,但不在本轮 `base-setup automation projection / durable automation draft` 变更范围内 - - `npm test -- "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/lib/api/sceneapp.test.ts"` - - 结果:`3 files / 13 tests passed` - - `npm test -- "src/components/AppPageContent.test.tsx" "src/components/agent/chat/workspace/useWorkspaceInitialSessionNavigation.test.tsx"` - - 结果:`2 files / 12 tests passed` - - `cargo check --manifest-path "src-tauri/Cargo.toml"` - - 结果:通过 - - `npm run test:contracts` - - 结果:通过 - - `npm run verify:gui-smoke` - - 结果:失败;`smoke:browser-runtime` 持续卡在 `launch_browser_session` 超时,`180000ms` 内未收到 DevBridge 响应 - - `npm run verify:local` - - 结果:失败;同样阻塞于 `smoke:browser-runtime`,非本轮 SceneApp / Agent session 恢复代码直接触发的断言失败 - - `npm run typecheck` - - 结果:通过 - - `npm test -- src/lib/sceneapp/catalog.test.ts src/lib/api/sceneapp.test.ts src/lib/dev-bridge/mockPriorityCommands.test.ts src/lib/tauri-mock/core.test.ts` - - 结果:`4 files / 18 tests passed` - - `cargo check --manifest-path "src-tauri/Cargo.toml"` - - 结果:通过 - - `npm test -- "src/components/sceneapps/SceneAppsPage.test.tsx"` - - 结果:`1 file / 4 tests passed` - - `npx eslint "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/sceneapps/SceneAppRunList.tsx" "src/components/sceneapps/SceneAppRunDetailPanel.tsx" "src/lib/sceneapp/presentation.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - 结果:通过 - - `npm run typecheck` - - 结果:通过 - - `npm run verify:gui-smoke` - - 结果:未通过;当前环境无法监听 `127.0.0.1:1420`,报错 `listen EPERM: operation not permitted 127.0.0.1:1420` - - `npm test -- "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/AppPageContent.test.tsx"` - - 结果:`2 files / 14 tests passed` - - `npx eslint "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/AppPageContent.test.tsx" "src/types/page.ts"` - - 结果:通过 - - `npm run typecheck` - - 结果:通过 - - `npm run verify:gui-smoke` - - 结果:未通过;当前环境无法监听 `127.0.0.1:1420`,报错 `listen EPERM: operation not permitted 127.0.0.1:1420` - - `npm test -- "src/lib/sceneapp/storage.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/AppPageContent.test.tsx"` - - 结果:`3 files / 18 tests passed` - - `npx eslint "src/lib/sceneapp/navigation.ts" "src/lib/sceneapp/storage.ts" "src/lib/sceneapp/storage.test.ts" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/sceneapps/SceneAppsRecentPanel.tsx" "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/AppPageContent.test.tsx" "src/types/page.ts"` - - 结果:通过 - - `npm run typecheck` - - 结果:通过 - - `npm run verify:gui-smoke` - - 结果:未通过;当前环境无法监听 `127.0.0.1:1420`,报错 `listen EPERM: operation not permitted 127.0.0.1:1420` - - `npm test -- src/lib/api/sceneapp.test.ts src/lib/tauri-mock/core.test.ts` - - 结果:`2 files / 14 tests passed` - - `npm test -- "src/lib/sceneapp/launch.test.ts" "src/lib/api/sceneapp.test.ts" "src/lib/tauri-mock/core.test.ts"` - - 结果:`3 files / 17 tests passed` - - `npm test -- "src/components/agent/chat/workspace/sceneAppLaunch.test.ts" "src/lib/sceneapp/launch.test.ts" "src/lib/api/sceneapp.test.ts"` - - 结果:`3 files / 13 tests passed` - - `npm test -- "src/components/agent/chat/workspaceEntry.test.ts" "src/components/agent/chat/workspace/sceneAppLaunch.test.ts"` - - 结果:`2 files / 14 tests passed` - - `npx eslint "src/components/agent/chat/workspace/sceneAppLaunch.ts" "src/components/agent/chat/workspace/sceneAppLaunch.test.ts" "src/lib/sceneapp/launch.ts"` - - 结果:通过 - - `npx eslint "src/lib/sceneapp/launch.ts" "src/lib/sceneapp/launch.test.ts" "src/lib/sceneapp/types.ts" "src/lib/api/sceneapp.ts"` - - 结果:通过 - - `npm run test:contracts` - - 结果:通过 - - `npm test -- "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/AppPageContent.test.tsx" "src/hooks/useAppNavigation.test.tsx" "src/lib/navigation/sidebarNav.test.ts" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.test.tsx" "src/components/agent/chat/workspace/sceneAppLaunch.test.ts" "src/lib/sceneapp/launch.test.ts"` - - 结果:`8 files / 56 tests passed` - - `npx eslint "src/components/sceneapps/SceneAppsPage.tsx" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/components/sceneapps/SceneAppsCatalogPanel.tsx" "src/components/sceneapps/SceneAppDetailPanel.tsx" "src/components/sceneapps/SceneAppScorecardPanel.tsx" "src/components/sceneapps/SceneAppRunList.tsx" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/components/AppPageContent.tsx" "src/components/AppPageContent.test.tsx" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/components/EmptyStateSceneAppsPanel.tsx" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.ts" "src/components/agent/chat/workspace/useWorkspaceSceneAppEntryActions.test.tsx" "src/components/agent/chat/workspace/sceneAppLaunch.test.ts" "src/components/agent/chat/workspace/WorkspaceConversationScene.tsx" "src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.tsx" "src/components/agent/chat/workspace/chatSurfaceProps.ts" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/lib/navigation/sidebarNav.ts" "src/lib/navigation/sidebarNav.test.ts" "src/types/page.ts" "src/lib/sceneapp/presentation.ts" "src/lib/sceneapp/automation.ts" "src/lib/sceneapp/launch.ts" "src/lib/sceneapp/launch.test.ts"` - - 结果:通过 - - `npm run typecheck` - - 结果:通过 - - `npm run verify:gui-smoke` - - 结果:失败,当前环境无法监听 `127.0.0.1:1420`,报错 `listen EPERM: operation not permitted 127.0.0.1:1420` - - `npm run verify:local` - - 结果:失败,但失败项仍为仓库已有无关问题,不在本轮 `SceneApp execution facade` 改动范围: - - `src/components/agent/chat/hooks/agentStreamFlowControl.test.ts` - - `src/components/agent/chat/utils/turnSummaryPresentation.ts` - - `src/lib/api/serviceSkills.ts` - - `src/lib/base-setup/serviceSkillCatalogAdapter.ts` - - `npm run lint` - - 结果:失败,但当前失败项为仓库已有无关问题,不在本轮 `SceneApp` 改动范围: - - `src/components/agent/chat/hooks/agentStreamFlowControl.test.ts` - - `src/components/agent/chat/utils/turnSummaryPresentation.ts` - - `src/lib/api/serviceSkills.ts` - - `src/lib/base-setup/serviceSkillCatalogAdapter.ts` - - `npm test -- "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/lib/api/sceneapp.test.ts"` - - 结果:`3 files / 24 tests passed` - - `cargo test --manifest-path "src-tauri/Cargo.toml" browser_runtime_ref` - - 结果:`2 tests passed` - - `cargo check --manifest-path "src-tauri/Cargo.toml"` - - 结果:通过 - - `npm run typecheck` - - 结果:通过 - - `npx eslint "src/lib/sceneapp/types.ts" "src/lib/sceneapp/product.ts" "src/components/sceneapps/useSceneAppsPageRuntime.ts" "src/lib/sceneapp/product.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx" "src/lib/api/sceneapp.ts"` - - 结果:通过 - - `npm run verify:gui-smoke` - - 结果:失败;`smoke:browser-runtime` 仍阻塞于 `launch_browser_session`,报错 `读取 CDP 标签页失败: error sending request for url (http://127.0.0.1:14509/json/list)` - -## 2026-04-14 - -### 已完成 - -- 建立 LimeNext 上位总纲专题包: - - [README.md](../roadmap/limenext/README.md) - - [prd.md](../roadmap/limenext/prd.md) - - [architecture.md](../roadmap/limenext/architecture.md) - - [flowcharts.md](../roadmap/limenext/flowcharts.md) - - [sequences.md](../roadmap/limenext/sequences.md) - - [code-structure.md](../roadmap/limenext/code-structure.md) - - [roadmap.md](../roadmap/limenext/roadmap.md) - - [execution-plan.md](../roadmap/limenext/execution-plan.md) - - [metrics-and-selection.md](../roadmap/limenext/metrics-and-selection.md) - - [migration-map.md](../roadmap/limenext/migration-map.md) -- 在 [docs/README.md](../README.md) 增加 LimeNext 总纲入口,确保文档中心可发现 -- 完成一轮文档新鲜度校验: - - `npm run harness:doc-freshness` - - 结果:`clean` -- 根据反馈把 LimeNext 定义改成更容易传播的三层版本: - - 给所有人看的白话版 - - 给产品团队看的版本 - - 给工程团队看的版本 -- 新增本执行计划与进度日志: - - [limenext-plan.md](./limenext-plan.md) - - [limenext-progress.md](./limenext-progress.md) -- 补齐 SceneApp 能力模型总纲: - - [sceneapp-capability-model.md](../roadmap/limenext/sceneapp-capability-model.md) - - 固定五类 `SceneApp` 分类 - - 固定五种 `Skill / Scene` 编排模式 - - 固定九类底层能力模块范围 - - 明确 `server skill / CLI / browser / cron / db / markdown / json` 的适用边界 -- 把 skill 设计模式正式写回基础标准与运行时标准: - - [skill-standard.md](../aiprompts/skill-standard.md) - - [command-runtime.md](../aiprompts/command-runtime.md) - - 明确 `Skill Bundle` 不是产品对象 - - 明确新增样板至少要声明 `sceneapp_type + pattern_primary / pattern_stack + infra_profile` -- 在 `SceneApp` 总纲里增加常见组合原型,避免分类只停在抽象概念 -- 新增 SceneApp 样板蓝图: - - [sceneapp-blueprints.md](../roadmap/limenext/sceneapp-blueprints.md) - - 用 `x-article-export`、`@配音`、`每日趋势摘要 / 账号增长跟踪` 三条样板补齐业务图、业务时序和经营指标 -- 更新 LimeNext 总纲图示: - - [flowcharts.md](../roadmap/limenext/flowcharts.md) - - [sequences.md](../roadmap/limenext/sequences.md) - - [architecture.md](../roadmap/limenext/architecture.md) - - 补齐“业务图在前、技术图在后”的双层表达 -- 选定 LimeNext 第一条 `Agent + ServiceSkill` 样板为 `@配音 / voice_runtime / cloud-video-dubbing` -- 重写 `docs/prd/gongneng/peiyin/` 六件套,形成完整实施级方案包: - - [prd.md](../prd/gongneng/peiyin/prd.md) - - [architecture.md](../prd/gongneng/peiyin/architecture.md) - - [flowcharts.md](../prd/gongneng/peiyin/flowcharts.md) - - [sequences.md](../prd/gongneng/peiyin/sequences.md) - - [code-structure.md](../prd/gongneng/peiyin/code-structure.md) - - [tasks.md](../prd/gongneng/peiyin/tasks.md) -- 新增 `docs/prd/gongneng/x-article-export/` 六件套,形成完整实施级方案包: - - [prd.md](../prd/gongneng/x-article-export/prd.md) - - [architecture.md](../prd/gongneng/x-article-export/architecture.md) - - [flowcharts.md](../prd/gongneng/x-article-export/flowcharts.md) - - [sequences.md](../prd/gongneng/x-article-export/sequences.md) - - [code-structure.md](../prd/gongneng/x-article-export/code-structure.md) - - [tasks.md](../prd/gongneng/x-article-export/tasks.md) -- 修正文档入口与引用,确保 `x-article-export` 作为 `Browser-grounded SceneApp` 样板可被发现: - - [docs/README.md](../README.md) - - [command-runtime/roadmap.md](../roadmap/gongneng/command-runtime/roadmap.md) - - [limenext/README.md](../roadmap/limenext/README.md) -- 新增 `Artifact / Evidence / Scorecard` 业务样板文档,并把它回挂到 LimeNext 总纲: - - [artifact-evidence-scorecards.md](../roadmap/limenext/artifact-evidence-scorecards.md) - - [metrics-and-selection.md](../roadmap/limenext/metrics-and-selection.md) - - [sceneapp-blueprints.md](../roadmap/limenext/sceneapp-blueprints.md) - - [flowcharts.md](../roadmap/limenext/flowcharts.md) - - [sequences.md](../roadmap/limenext/sequences.md) -- 把第三条 `Local Durable SceneApp` 样板固定到真实仓库锚点: - - `daily-trend-briefing` - - `account-performance-tracking` - - `useWorkspaceServiceSkillEntryActions.ts` - - `AutomationJobDialog.tsx` - - `automation_service/mod.rs` -- 新增通用解耦专题,明确“主 App 宿主内核”与“基础设置包”的边界: - - [base-setup-decoupling.md](../roadmap/limenext/base-setup-decoupling.md) - - 固定“换装配优先不升级主 App,换内核才升级” - - 固定基础设置包不是新 runtime,也不是新产品对象 -- 把 `x-article-export` 的产品合同从“待澄清”收口为固定口径: - - 先交付 `index.md + images/ + meta.json` - - 若带 `target_language`,只在同一路径 Markdown 上继续后处理 - - 若未来要支持“纯原文模式”,必须显式分流入口 -- 完成第二轮文档新鲜度校验: - - `npm run harness:doc-freshness` - - 结果:`clean` - -### 当前判断 - -- LimeNext 作为上位总纲已经成立 -- `SceneApp` 已不再只是一个抽象词,而有了统一能力模型 -- `SceneApp` 现在同时有“运行形态 + 编排模式 + 基础设施画像”三轴分类 -- `Skill` 设计模式已经不再只是经验说法,而进入了正式工程字段与设计卡 -- LimeNext 图示已经不再只有技术分层图,开始具备业务、产品、运营可读的总图与时序 -- LimeNext 现在不只有抽象分类,还有三条业务样板蓝图可以直接拿来对齐讨论 -- 第一条 `Agent + ServiceSkill` 样板已经不再空缺,当前由 `@配音 / voice_runtime` 承担 -- 第二条 `Agent + ServiceSkill` 样板也已不再空缺,当前由 `x-article-export` 承担 -- 第三条 `Local Durable SceneApp` 样板也不再只是概念词,当前由 `每日趋势摘要 / 账号增长跟踪` 承担 -- `Browser-grounded SceneApp` 已经不再停留在蓝图层,而有了完整实施级方案包 -- 当前最重要的问题不再是“第二条样板怎么补”,而是“样板如何接到 `Artifact + Evidence + Scorecard`” -- `Artifact / Evidence / Scorecard` 三层现在已经不再只是抽象词,而有了业务样板和图示 -- `x-article-export` 的产品合同也已不再摇摆,当前口径是“资料包优先 + 同一路径后处理” -- “尽量不升级主 App 也能使用基础设置” 这条原则也已不再只是口头要求,而被收口成通用分层规则 -- 当前还需要继续明确: - - `SceneScorecard` 后续具体落到哪些真实聚合对象与看板入口 - -### 风险 - -- 如果后续继续只写总纲与治理,而不落样板链路,LimeNext 很容易再次变成抽象平台叙事 -- 如果后续只停在 `@配音` 一条云端样板,LimeNext 仍然会被误解成“只适合云端场景” -- 如果后续不把 `Local Durable` 的经营口径接进真实看板,团队还是容易把它误讲成“只是定时任务” -- 如果后续把“基础设置包”写成某个单场景私有配置,解耦层会再次失效 -- 如果后续重新把 `Skill`、`ServiceSkill`、`Scene` 混成一个词,总纲会迅速失效 - -### 下一刀 - -- 把 `SceneScorecard` 聚合对象继续接到生成 / 场景看板 / 周会模板 -- 把三条样板的经营信号进一步映射到真实数据源与产品入口 -- 继续把结果卡文案从“技术摘要”升级成“业务可理解的交付说明” -- 把基础设置包收口成更明确的 schema 与校验规则 - -## 2026-04-23:P2 输入层 Capability 收口 - -- 把 `slash` 空查询首屏继续收成结果优先的 capability 前台,避免 `Generate` 里输入 `/` 时又退回成一整张 Codex 命令目录: - - 已更新: - - `src/components/agent/chat/skill-selection/inputCapabilitySections.ts` - - `src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx` - - `src/components/agent/chat/skill-selection/inputCapabilitySections.test.ts` - - `src/components/agent/chat/skill-selection/CharacterMention.test.tsx` - - `docs/roadmap/limenextv2/implementation-roadmap.md` - - `docs/exec-plans/limenext-progress.md` - - 当前统一结论: - - slash 空查询当前固定按 `先拿结果 -> 继续上次做法 -> 我的方法 -> 工作台操作 -> 最近操作` 出首屏,不再把纯 slash command 当成默认入口 - - `继续上次做法` 当前只吃 recent 里的非 command 项(`curated_task / scene / installed skill`);最近用过的 slash command 会单独压到 `最近操作` - - 搜索态当前继续保留 `结果模板 / 提示命令 / 状态 / 帮助 / 已安装技能` 分组,因此 `/review`、`/help` 这类提示/状态命令仍可被命中,只是不再默认摊在第一屏 - - `CharacterMentionPanel` 的 slash placeholder 当前改成 `搜索结果模板、做法或操作...`,进一步压低“命令总表”心理预期 - - slash 面板里的结果模板、最近做法与工作台动作当前又继续把“人话标题”提到前面:`scene / installed skill / local_action` 不再默认把 `/prefix` 当主标题,而是把 `/前缀` 退成辅信息 - - 空查询里的 `工作台操作` 当前也按 `新建任务 -> 清空任务 -> 压缩上下文` 重排,先露出真正影响起手的动作,再退到上下文整理类动作 - - `CharacterMentionPanel` 当前也开始把 section 语气拉开:`工作台操作 / 最近操作` 在空查询下会显影辅助说明,但只有 `工作台操作` 会被压成紧凑展示;`最近操作` 继续保留 replay 文案,避免“上次输入”这类续接信息被折掉 - - 当前定向验证: - - `npm exec vitest run "src/components/agent/chat/skill-selection/inputCapabilitySections.test.ts" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npx eslint "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.test.ts" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke -- --timeout-ms 600000` - - 结果: - - `vitest` 通过:`2 files / 91 tests passed` - - `eslint` 通过 - - `typecheck` 通过 - - `verify:gui-smoke` 通过:`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - - 补充说明:前一次 `120000` 校验失败已确认是复用半死 headless 链路与独立 target 冷编译窗口造成的环境噪音,不构成这轮 slash 输入层回归 - -- `Generate` 输入层当前开始明确区分“业务能力”和“工作台命令”,不再继续显示 `内建命令 / 快捷操作 / Lime 命令` 这类旧平台式标题 -- `@` builtin command 当前已按 `搜索 / 读取`、`生成 / 表达`、`媒体转换`、`预览 / 发布`、`浏览器 / 执行` 分组,直接对应 LimeNext V2 规划里要稳定显影的 capability categories -- `/` 的 Codex slash 当前已按 `工作台操作`、`提示命令`、`状态 / 帮助` 分组,避免和业务能力混成同一层 -- 这次继续往前推的空查询视觉收口当前已完成: - - `工作台操作 / 最近操作` 会在空查询下显影辅助说明,先提醒“这些是整理当前任务时再用的辅助入口” - - 只有 `工作台操作` 被压成紧凑展示,避免重新长成命令目录;`最近操作` 继续保留 `上次输入` 这类 replay 文案,不牺牲续接上下文 -- `我的方法` 这一层当前也继续收成更弱的备用方法库: - - `继续上次做法` 当前保持更强的 continuation 语气,帮助用户优先接回已跑过的方法 - - `我的方法` 当前保留轻合同,但图标与文本层级继续压低,不再和 `先拿结果 / 继续上次做法` 抢同一层视觉权重 - - 对应回归当前也补成真实并存场景:测试里不再只放 1 条 skill,而是同时覆盖“recent continuation 已吃掉一条 skill”后,`我的方法` section 仍然存在的情况 -- `我的方法` 页右侧桥接区当前也继续回推了这套层级,而不再只让 slash 输入层先收口: - - 右侧第一块当前已统一改成 `继续上次做法`,并显影同一条 continuation helper,避免页面和输入层一边讲“上次做法”,一边讲“常用做法” - - `我的方法库` 当前也补上与 slash 一致的补位 helper,明确它只承担“上面没命中时,再从这里挑一条本地做法”的职责 - - 右侧两块的卡片密度与 CTA 当前也继续拉开:continuation 保持更强的续接感,本地方法库则退成更安静的备用方法库 -- 左侧 `方法目录` 当前也继续收成补位目录,而不是第二组主入口卡片墙: - - 目录头部当前会直接提醒“上面没命中时,再按方向找一组做法”,不再和 `先拿结果` 抢同一层解释权 - - 做法组卡片当前继续压成更轻的目录卡,只保留 `可先看 / 更偏向 / 起手` 这些最小判断线索 - - 对应 copy 里“已沉淀到常用做法”当前也继续统一收成“已沉淀到继续上次做法”,避免页内外继续混词 -- 进入做法组后的顶部当前也继续退回目录过渡层,而不是第二层详情页: - - 组内头部当前只保留 `组内继续挑做法 + 组标题`,不再重复把标题、摘要和入口提示放大成说明大卡 - - helper 当前直接告诉用户“已进入这组,下面直接挑一条具体做法;没命中再换一组”,减少再次理解页面结构的负担 - - `summary / entryHint` 当前被收成最小判断线索;返回动作也统一改成 `换一组做法`,继续强调这是目录切换 -- 组内具体做法卡片当前也继续从“详情合同卡”退回“轻选择卡”: - - 顶部当前不再继续暴露类型标签,只保留 `来源 badge + 当前状态` - - 主体当前收成 `标题 + 一句话摘要 + 你先给 / 会拿到 / 进去后` 三条最小判断线索,不再重复展示分类与独立状态说明块 - - `结果去向` 当前退回底部辅助脚注;CTA 也退成次按钮,避免每张卡重新长成详情页 -- `先拿结果` 卡片当前也继续从“结果合同卡”退回“少数强结果入口”: - - 第一张结果卡当前会抬升成 `优先起手` 主推荐,其余结果退成轻量备选,不再每张卡都用同一层权重解释自己 - - 主体当前只保留 `标题 + 摘要 + 推荐理由/最近继续 + 你先给 / 这一步先拿` - - `结果去向 / 接着可做` 当前退回底部脚注;CTA 也重新拉开成“主推荐主按钮 + 其他卡次按钮” -- `我的方法` 顶部 header 当前也继续从“工作台说明卡”退回“前台起手层”: - - 顶部当前不再先放 `我的方法 · 对话内继续` hero badge 和长说明,而是收成 `标题 + 对话内继续 pill + 一句 helper` - - 搜索当前也前移成真正起手动作:标题收成 `搜做法`,目录状态退到搜索下方做轻 metadata,不再占掉首屏说明位 - - 同步来源、做法数量和同步时间当前继续留在右侧低权重 chips,避免再把 header 做成管理台面板 -- `最近复盘` 信号当前也继续从独立蓝色横幅退回结果区里的轻量续做 strip: - - 当前仍保留 `最近复盘已更新 / 摘要 / 更适合继续` 这三条判断线索,但已收成更薄的 inline 提示,不再压过结果入口本身 - - 这让 `先拿结果` 区继续保持“少数强入口”为主,复盘只负责排序与续做提醒 -- `当前带入做法草稿` 当前也继续从页头重横幅退回搜索区里的轻量草稿 strip: - - 当前只保留 `当前草稿 / 项目内整理 / 草稿名 / 来源 / 上次目标` 这些最小连续性线索,不再用大渐变卡解释系统状态 - - 当前动作收成 `整理 / 带回生成` 两个短按钮,且不再用强主按钮和 `先拿结果` 抢视觉权重 - - 这让 `结果 -> 做法草稿 -> 我的方法页` 仍保持可直达,但前台层级继续回到 `先结果 / 再目录 / 再补位` -- 原本偏后台感的整理入口当前也继续从显眼管理入口退回低权重 `整理 / 整理我的方法`: - - 页头与 `我的方法库` 的按钮当前都只显示 `整理`,并退成 ghost 辅助动作,不再与主入口同层 - - 搜索、方法库和弹窗 tips 当前不再外露后台维护词,只说明“没找到时整理自己的方法”和“新增、检查、清理” - - 弹窗标题当前改成 `整理我的方法`,继续把它定义成补位整理层,而不是前台第二套管理台 -- `我的方法库` 顶部的“刚沉淀成功”当前也继续退回轻量 continuation strip: - - 原本大渐变、高对比成功态和长说明当前已收成一条轻量续接:`刚沉淀 / 来源 / 方法名 / 上次目标 / 已回到我的方法库 / 继续生成` - - 高亮方法卡内部原本重复的“刚从当前结果沉淀下来”说明块当前也已移除,避免顶部横幅和卡片内部双重强调成功状态 - - `继续生成` 当前退成和草稿 strip 一致的小型 outline 动作,因此 `沉淀为做法 -> 回到方法库 -> 继续生成` 仍然成立,但首屏语气已回到“轻提示后继续开工” -- 页头剩余的 `刷新方法库` 当前也继续退回低权重工具动作: - - 页头当前只保留 `刷新 / 整理` 两个低权重工具动作,不再让“维护方法库”继续占据首屏最强按钮位 - - `刷新` 当前退成小型 outline 辅助按钮,和 `整理 / 继续生成 / 带回生成` 统一为同一层级的轻工具动作 - - 对应测试当前也切到 `data-testid`,不再把 `刷新方法库` 这类后台感更强的旧文案绑定成稳定契约 -- 页头剩余的目录状态与方法库 metadata 当前也继续退回单行弱 summary: - - 搜索框下方原本单独的目录状态 chip,当前已退成普通小号文案,不再像状态 badge 一样额外抬层 - - 右侧原本那组 `来源 / 做法数 / 分组数 / 同步于` badges 当前也已收成一条弱 summary,只保留 `多少条做法 / 多少组 / 最近同步` 这些最小信息 - - 因此页头当前更接近 `标题 + helper + 搜索 + 静默状态`,不会再像一个带统计条的管理头部 -- 页头默认状态句当前也继续压成更短的人话提醒: - - loading 态当前收成 `正在更新做法列表...` - - 默认态当前收成 `这里放跑通过的做法;不确定时先回首页拿结果。` - - 组内态当前收成 `当前浏览:{做法组}` - - 这让 header 状态线更像一句轻提醒,而不是再次解释页面结构 -- 这次子改动的定向验证当前已通过: - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run typecheck` - - `vitest` 通过:`1 file / 26 tests passed` - - `eslint` 通过 - - `typecheck` 通过 -- 这次子改动补跑 `npm run verify:gui-smoke -- --timeout-ms 180000` 当前也已完整通过: - - `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - - 补充说明:本轮先命中了临时 Cargo target 的冷编译,`DevBridge` 等待了较长时间才就绪;但最终 smoke 全链已通过,因此这次等待应记为环境成本,而不是 `SkillsWorkspacePage` 当前主路径回归 -- 这次子改动的定向验证当前已通过: - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run typecheck` -- 这次子改动补跑 `npm run verify:gui-smoke -- --timeout-ms 180000` 当前已完整通过: - - `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - - 说明这轮 header / 复盘 strip 的前台收口没有破坏 GUI 主路径,已经具备当前阶段的最小可交付旁证 -- 本轮还顺手收掉了 3 处与主线直接相关的 `typecheck` 断点: - - `src/components/agent/chat/hooks/agentRuntimeAdapter.test.ts` - - `src/components/agent/chat/utils/buildUserInputSubmitOp.test.ts` - - `src/components/settings-v2/system/automation/index.tsx` -- 定向校验已通过: - - `npm exec vitest run "src/components/agent/chat/skill-selection/inputCapabilitySections.test.ts"` - - `npx eslint "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/skill-selection/inputCapabilitySections.test.ts" "src/components/agent/chat/hooks/agentRuntimeAdapter.test.ts" "src/components/agent/chat/utils/buildUserInputSubmitOp.test.ts" "src/components/settings-v2/system/automation/index.tsx"` - - `npm run typecheck` -- GUI 主路径校验已通过: - - `npm run verify:gui-smoke -- --timeout-ms 600000` - - `workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` -- `npm run verify:local` 当前仍被工作树里的既有 lint warning 阻塞: - - `src/components/agent/chat/workspace/useWorkspaceSendActions.ts` `react-hooks/exhaustive-deps` - - 该阻塞目前应视为仓库级存量问题,不是本轮 capability 收口新增的问题 -- `我的方法` 页里的 `结果卡 / 做法卡 / launcher` 当前又继续前推了一刀,避免首层虽然已经收成 `先拿结果 -> 继续上次做法 -> 已经沉淀的方法`,但具体卡片和弹窗里仍然暴露 `云目录 / 站点技能 / 浏览器采集 / 已补 x/y` 这类目录式、系统式提示: - - `SkillsWorkspacePage` 当前已把 service skill 卡片的来源 badge 收掉,只保留 `当前状态 + 你先给 / 会拿到 / 接下来` 这三条最小判断线索 - - `先拿结果` 卡片当前已把 `featured badge` 收成正文里的轻量推荐理由,不再让 `围绕最近成果 / 围绕最近复盘` 以大 pill 方式压过结果入口本身 - - `做法组` 卡片当前已把 `先试 / 进去后直接挑做法` 收成一句更轻的起手建议,并把 CTA 统一改成 `进去看看` - - `CuratedTaskLauncherDialog` 顶部当前已改成 `还差 X 项关键信息 / 关键信息已齐`,不再继续暴露模板 badge 和 `已补 x/y` - - `site skill` 相关口径当前也同步从 `浏览器采集 / 登录态` 收成 `接着浏览器继续 / 已登录页面` -- 因此用户当前沿着 `我的方法 -> 结果模板 / 做法组 / service skill -> launcher -> Agent` 这条链路时,看到的已经更接近“这一步缺什么、会给我什么、接下来怎么继续”,而不是“这是哪类能力对象、来自哪个目录、当前填了几格表单”: - - service skill 卡当前更像一条可继续的方法,而不是一个带来源标签的能力对象 - - 结果模板卡当前会继续解释“为什么现在选它”,但这层解释已经退回正文轻提示,不再变成第二排 badge - - launcher 当前先告诉用户“现在能不能开始”,而不是先展示模板元信息 -- 这一步继续遵守 P2 的 current 边界: - - 不新增第二套方法详情页 - - 不新增 `service skill` 专属启动协议 - - 不改 `pendingServiceSkillLaunch`、`CuratedTaskLauncherDialog`、`site adapter` 现有主链,只做前台口径减法 -- 这次子改动的定向验证当前已通过: - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx" "src/components/agent/chat/service-skills/skillPresentation.test.ts"` - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.tsx" "src/components/agent/chat/components/CuratedTaskLauncherDialog.test.tsx" "src/components/agent/chat/service-skills/skillPresentation.ts" "src/components/agent/chat/service-skills/skillPresentation.test.ts"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - `vitest` 通过:`3 files / 43 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过:`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` -- 首页 `EmptyState` 与 slash 首屏当前又继续前推了一刀,避免 `我的方法` 页已经收成前台起手层,但首页推荐 shelf 和 `/` 首屏里还残留 `围绕最近成果 / 围绕最近复盘 / 结果模板 / 我的方法` 这类 badge-first 呈现: - - `EmptyState` 当前已把结果卡和续接卡的 badge 降为可选辅助字段;默认不再把 `结果模板 / 我的方法 / 围绕最近...` 顶在卡头 - - 首页推荐卡当前继续保留“为什么推荐这条”,但这层信息已退回正文 `meta / contextSummary`,不再用 badge 抢标题层 - - slash `先拿结果` 当前已把 curated task 行项目右侧 `kindLabel` 收掉;分组标题负责解释“这是结果模板”,行内只保留标题和合同描述 - - slash 里的最近复盘横幅当前也已去掉 badge pill,只保留 `最近复盘已更新`、摘要和 `继续去...` 动作 -- 因此用户当前沿着 `首页 -> 结果入口` 和 `slash -> 先拿结果` 两条主链时,看到的更接近“为什么现在该从这条开始”,而不是“这是哪个标签下的哪个对象”: - - 首页结果入口当前会先展示动作对象与推荐原因 - - slash 首屏当前会先展示结果模板本身与启动合同,不再把标签塞到标题右侧 - - 最近复盘 / 当前参考 / 最近成果这些高价值信号当前仍保留,但统一退到了正文说明层 -- 这一步继续遵守 P1 / P2 的 current 边界: - - 不新增首页专属推荐状态机 - - 不新增 slash 首屏第二套结果模板协议 - - 不改结果模板排序、launcher、`onSelectCuratedTask` 与现有 route 主链,只做前台呈现减法 -- 这次子改动的定向验证当前已通过: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.test.ts"` - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/skill-selection/inputCapabilitySections.test.ts" "src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - `vitest` 通过:`3 files / 140 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过:`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - -- `@ / slash` 输入能力面板当前又继续前推了一刀,避免首页和 `我的方法` 已经逐步切到 `先拿结果 -> 继续上次做法 -> 已经沉淀的方法`,但真正进入输入补全面板后,用户仍然会在行项目右侧看到 `技能 / 结果模板 / 工作台操作 · /new / 云目录式` 这一类对象标签: - - `inputCapabilitySections` 当前已把 `recent service skill`、`service skill group`、`scene result`、`recent installed skill`、`recent curated task` 这些条目的 `kindLabel` 收掉;分组标题负责说明语义,行项目只保留标题和轻合同描述 - - `slash command` 当前只保留最小可识别的命令前缀,例如 `/new /clear /compact`;不再继续把 `工作台操作 / 提示命令 / 状态帮助` 这层分类重复挂到条目右侧 - - `@` 面板里的内建命令分组当前也不再重复挂 `搜索 / 读取 / 生成 / 表达` 这类类别标签;用户先看到的是动作本身,而不是分类名 - - `CharacterMentionPanel` 当前又加了一层前台保险:即使后续数据层误塞了标签,除了真正需要识别的 slash 命令前缀,其它 `kindLabel` 也不会再轻易显影到用户前台 -- 因此用户当前沿着 `输入框 -> @ / slash 面板 -> 选一条继续` 这条主链时,认知会进一步从“我在挑某种能力对象”收回到“我现在先接这一步”: - - recent continuation 当前会优先展示“这条结果 / 这套方法”的标题和合同,而不是对象类别 - - scene / result / local skill 当前不会再额外挂 `结果模板 / 技能 / /skill-key` 这类次级标签 - - 工作台命令仍然保留最小的 `/command` 前缀,避免完全失去命令识别性 -- 这一步继续遵守 P1 / P2 的 current 边界: - - 不新增第二套输入补全面板 - - 不改 `onSelect*`、launcher、scene command、installed skill 的现有激活协议 - - 继续只在 `inputCapabilitySections` 与 `CharacterMentionPanel` 上做前台呈现减法,不改底层能力编排和选择主链 -- 这次子改动的定向验证当前已通过: - - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.test.ts"` - - `npx eslint "src/components/agent/chat/skill-selection/inputCapabilitySections.ts" "src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/skill-selection/inputCapabilitySections.test.ts"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - `vitest` 通过:`2 files / 93 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过:`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - -- 首页推荐 shelf 当前又继续前推了一刀,避免 `我的方法`、`slash`、`@` 面板已经逐步收成“先做哪一步 / 为什么先做这一步”,但 `EmptyState` 里的 service skill 推荐卡仍然会以 `云目录 / 最近使用` 这类 badge-first 方式抢占标题层: - - `EmptyState` 当前已把 service skill 推荐项上的 `badge` 去掉;首页推荐 shelf 里这类卡片现在只保留标题、摘要、`需要 / 交付` 合同,不再把 `云目录 / 最近使用` 直接挂到卡头 - - `CharacterMention` 运行时回退把 `scene -> service skill` 补参接管时,当前也不再额外给 `ServiceSkillHomeItem` 注入 `云目录 / 本地技能` badge,避免其它入口后续再把来源标签漏回前台 -- 因此用户当前沿着 `首页 -> 直接开工的做法` 和 `slash scene -> A2UI 补参接管` 这两条主链时,认知会继续从“这是哪个来源的能力对象”收回到“这条做法现在能帮我做什么”: - - 首页 service skill 推荐卡当前会先解释动作与交付,不再先解释目录来源 - - runtime scene 回退成 service skill 时,也不会再把 `云目录 / 本地技能` 这类历史 badge 带回当前链路 -- 这一步继续遵守 P1 / P2 的 current 边界: - - 不改首页推荐排序与 lead/alternative 逻辑 - - 不改 `onSelectServiceSkill`、scene 接管、launcher 或 service skill 执行合同 - - 继续只在 `EmptyState` 与 `CharacterMention` 的前台投影层做减法,不碰底层能力选择主链 -- 这次子改动的定向验证当前已通过: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/skill-selection/CharacterMention.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - `vitest` 通过:`2 files / 137 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过:`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - - 补充说明:这次 `verify:gui-smoke` 走的是重新拉起 headless Tauri 的路径,期间出现了异常 API Key UTF-8 warning 与 `3030/8999` 端口已占用噪音;但最终 smoke 全链已通过,应视为环境复用噪音,而不是本轮首页收口回归 - -- `我的方法` 页顶栏当前也继续做了一刀减法,避免首页、`slash`、`@` 面板都已经逐步收成前台动作语言,但方法页里的当前草稿条仍然用 `来源:...` 这种偏后台对象说明的口径: - - `SkillsWorkspacePage` 当前已把当前草稿条里的 `来源:{摘要}` 改成 `这次沿用:{摘要}`,让这条信息更像“这轮准备沿用哪条起手线索”,而不是在解释对象出处 -- 因此用户当前沿着 `首页 -> 我的方法 -> 当前草稿 -> 带回生成` 这条链路时,首屏认知会继续从“这是哪个对象来的”收回到“这轮准备接着什么继续做”: - - 当前草稿条当前会先说“这次沿用什么” - - `上次目标` 仍然保留,继续承担真正影响下一步动作的语义 -- 这一步继续遵守 P2 的 current 边界: - - 不改当前草稿条的结构、按钮、路由或带回生成主链 - - 继续只做文案层减法,不碰方法页的数据和激活协议 -- 这次子改动的定向验证当前已通过: - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - `vitest` 通过:`1 file / 27 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过:`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - -- 首页 `EmptyState` hero 当前又继续做了一刀减法,避免 `我的方法`、`slash`、首页推荐 shelf 都已经逐步收成前台起手层,但首屏顶部仍然挂着 `通用对话 / 模式 / 已挂载做法` 这一排系统状态 badge,把用户重新拉回“先读状态条”的心智: - - `EmptyState` 当前已移除 hero 的 `workspaceBadges` 注入,首屏现在只保留 `slogan / 创作说明 / 结果入口 / 继续这轮` - - 首页当前不再把 `通用对话`、创作模式和当前已挂载方法做成顶部 pill;即使已经选中本地方法,这层状态也只留在输入主执行面里,不再在 hero 再喊一次 -- 因此用户当前沿着 `新建任务 -> 结果入口 -> 输入 -> 发送` 这条链路时,首屏认知会继续从“我先确认系统状态”收回到“我现在先拿什么结果开工”: - - hero 当前只负责创作语义和起手承诺 - - 方法、模板、当前模型这些真正影响执行的状态,当前分别留在结果入口、输入执行面和高级设置里,不再叠成第二条状态带 -- 这一步继续遵守 P1 / P2 的 current 边界: - - 不改首页推荐排序、输入执行协议或 capability route - - 不新增新的 hero 提示层或替代 badge 样式 - - 继续只在 `EmptyState` 前台投影层做减法,不碰底层能力选择主链 -- 这次子改动的定向验证当前已通过: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - `vitest` 通过:`1 file / 49 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过:`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - - 补充说明:本轮 smoke 仍出现了异常 API Key UTF-8 warning、`8999` 端口占用与 companion 端口占用噪音,但最终整条 GUI 主链已跑通,应按环境复用噪音处理,而不是首页 hero 收口回归 - -- `我的方法` 页顶栏和当前草稿条当前又继续做了一刀减法,避免首页 hero 已经去掉系统状态带后,方法页首屏仍然残留 `当前草稿 / 项目内整理 / 技术化 tip` 这一类对象提示: - - `SkillsWorkspacePage` 当前已把方法主入口 tips 改成 `先从结果起手,顺手的做法和自己沉淀下来的方法都在这里续上`,不再继续解释 `Agent / adapter / runtime / YAML` - - 搜索 tips 当前也从“整理自己的方法”收成“先找这轮想拿的结果方向,没命中再接着自己顺手的方法”,减少管理台心智 - - 当前草稿 strip 当前已把 `当前草稿` 改成 `这次续用`,并移除了 `项目内整理` 来源 pill;草稿动作同步收成 `继续整理` - - 右侧 continuation 区的 tips 当前也从“方法库 / 沉淀区说明”收成“最近顺手的做法 / 自己的固定做法”这种前台口径 -- 因此用户当前沿着 `首页 -> 我的方法 -> 当前草稿/继续上次做法/已经沉淀的方法 -> 生成` 这条链路时,首屏认知会继续从“我在看一个方法对象目录”收回到“我这轮接着哪套做法往下做”: - - 顶栏 tips 当前先回答“这里怎么继续开工”,而不是“这是哪套系统结构” - - 当前草稿条当前先表达“这次续用什么”,而不是“这条东西来自哪里” - - 右侧两块当前也更像下一步动作入口,而不是方法库存说明 -- 这一步继续遵守 P2 的 current 边界: - - 不改 `SkillsWorkspacePage` 的布局骨架、分区顺序、跳转路由或带回生成主链 - - 不新增第二套方法详情页或草稿管理协议 - - 继续只在方法页首屏文案与轻标签层做减法,不碰底层数据、recent continuation 与 launcher 主链 -- 这次子改动的定向验证当前已通过: - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - `vitest` 通过:`1 file / 27 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过:`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - - 补充说明:本轮 smoke 继续出现了异常 API Key UTF-8 warning,以及 `3030/8999` 与 companion 端口占用噪音;但最终 GUI 主链已通过,应按环境复用噪音处理,而不是本轮方法页收口回归 - -- `我的方法` 页顶栏当前又继续做了一刀减法,避免首页和方法页都已经逐步压低系统说明后,header 右上角仍然挂着一个和下方重复的 `整理` 入口,把首屏重新拉回“先管理方法”而不是“先继续这轮”: - - `SkillsWorkspacePage` 当前已移除顶栏右上角那颗重复的 `整理` 按钮 - - `整理` 入口当前只保留在真正需要它的局部位置,例如当前草稿条和 `已经沉淀的方法` 区域,不再在页头重复提醒 -- 因此用户当前沿着 `首页 -> 我的方法 -> 继续这轮 / 已沉淀的方法 -> 生成` 这条链路时,首屏重心会继续从“先打开管理入口”收回到“先选一条做法继续”: - - 顶栏当前只保留与当前页主任务直接相关的动作 - - 整理动作当前退到具体上下文里出现,不再抢首屏标题区 -- 这一步继续遵守 P2 的 current 边界: - - 不改 `SkillsWorkspacePage` 的分区结构、弹窗路由或整理功能本身 - - 不新增新的管理页入口层级 - - 继续只做前台可见入口减法,不碰方法页数据与整理弹窗主链 -- 这次子改动的定向验证当前已通过: - - `npm exec vitest run "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npx eslint "src/components/skills/SkillsWorkspacePage.tsx" "src/components/skills/SkillsWorkspacePage.test.tsx"` - - `npm run verify:gui-smoke -- --timeout-ms 180000` - - `vitest` 通过:`1 file / 27 tests passed` - - `eslint` 通过 - - `verify:gui-smoke` 通过:`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - - 补充说明:本轮 `verify:gui-smoke` 复用了已运行的 headless Tauri 环境,仍经过完整 GUI 主链 smoke;最终通过,应视为当前 UI 收口已在真实主路径上坐实 - -- `skill-first` 主线当前继续对齐了一刀,直接处理了 `我的方法 / launcher / service skill` 里仍残留的目录心智,避免页面首屏已经收成“先拿结果 -> 继续上次做法 -> 已经沉淀的方法”,但实际数据和补参弹窗还在讲 `云目录 / Seeded 目录 / 租户技能目录 / 最近整理`: - - `useServiceSkills` 当前已把 service skill 的默认 badge 从来源标签改成前台动作语义:非 recent 做法统一回到 `现成做法`,站点型做法统一回到 `浏览器继续`;`catalogMeta.sourceLabel` 也同步收成 `起步做法 / 已同步做法` - - `SkillsWorkspacePage` 当前已去掉 header 搜索区下方的 `最近整理` 目录说明,不再在“我的方法”页首屏提醒用户这是一个被整理过的目录 - - `SkillsWorkspacePage` 的失败提示当前也已改成面向前台入口的两类提示:`现成做法暂时没同步下来` / `已经沉淀的方法暂时没读到`,避免错误态把用户拉回“云端目录 / 本地目录”心智 - - `CuratedTaskLauncherDialog` 当前又补上了和页面卡片同一套 `你先给 / 会拿到 / 接着可做` 轻合同;因此用户从 `我的方法` 或 slash 进入 launcher 后,看到的不再只是“确认几件事”,而是和入口页一致的 skill-first 起手合同 -- 因此当前主链又更接近 Ribbi 的 `前台卖任务,不卖目录来源`: - - `我的方法` 页首屏不再拿 catalog 元信息解释自己 - - service skill 数据层默认也不再把来源标签往前台漏 - - launcher 和方法页当前已经回到同一套起手合同,而不是各讲一套 -- 这一步继续遵守 P2 的 current 边界: - - 不改 runtime 协议、service skill 执行链和 sceneapps route - - 不新增长期 compat 包装层 - - 继续只收 `skill-first` 前台投影与事实源表述,不碰底层 agent / tool 合同 - -- `@命令` 当前继续回到主线,直接把 mention 面板收成更像 Ribbi 式的统一调用面,而不是“角色 / 技能混排列表”: - - `inputCapabilitySections` 当前已把 mention recent 分组从 `最近使用` 收成 `最近调用`,把 `推荐做法` 收成 `场景做法`,把 `角色` 收成 `协作角色` - - `CharacterMentionPanel` 当前已把输入提示和空态从 `搜索角色或技能 / 暂无可用角色或技能` 收成 `搜索 @命令、做法或协作角色 / 暂无可用 @命令、做法或协作角色`,明确 `@` 主体首先是调用面 - - mention 面板当前也补了命令主导的 landing 语义:recent 调用高亮保留,`场景做法 / 我的方法 / 更多做法 / 协作角色` 这些补位分组统一压轻,不再和命令分组抢同一层视觉重心 - - 因此用户当前沿着 `生成 -> @` 进入时,会先理解“我在调什么命令”,然后才看到整套做法、我的方法与协作对象;更接近 Ribbi 那种 `统一调用注册表`,而不是“另一个技能面板” -- 这一步继续遵守 P2 的 current 边界: - - 不改 `@` 选择后的 capability route、service skill 接管或 builtin command 执行合同 - - 不新开独立命令页,不把 `@` 长成第二执行系统 - - 继续只收 mention 输入层的前台分组、提示和视觉重心 - -- `@命令` 这一轮又继续补了一刀注册表语义,避免 mention 面板虽然已经“命令优先”,但首屏仍然不够像 Ribbi 那种统一调用注册表: - - `inputCapabilitySections` 当前已把 `浏览器 / 执行` 收成 `浏览器 / 编排`,让这组能力更贴近 `browser / code / web orchestration agents`,不再像一组模糊的杂项执行动作 - - mention 空查询当前已新增 `统一调用注册表` 首屏 banner:有 recent 时优先讲“继续最近调用,或切到其他执行器”,没有 recent 时明确讲“先调命令,再补做法”,并再次强调所有调用都会继续写回当前生成线程 - - mention 空查询的补位层当前也继续下沉:`场景做法 / 分组做法 / 我的方法 / 更多做法 / 协作角色` 现在统一压成命令后的补位层;`协作角色` 也下移到方法区之后,不再夹在方法中间抢注意力 - - `CharacterMentionPanel` 当前也补了方法层 helper 文案:`场景做法 / 我的方法 / 更多做法` 明确是命令后的补位入口,而不是和上面的 `@命令` 同层竞争 -- 因此用户当前沿着 `生成 -> @` 打开空查询面板时,会先读到“这是统一调用注册表”,再沿着 `最近调用 / 命令家族 / 做法补位 / 协作角色` 这条顺序做选择: - - `@` 首屏当前先卖执行器与命令家族,而不是混排对象目录 - - 浏览器与代码类命令当前也明确回到“编排执行器”心智,而不是挂在一个模糊的“执行”分组里 - - 协作角色当前继续保留,但已经退回命令和方法之后,避免重新长成第二主入口 -- 这一步继续遵守 P2 的 current 边界: - - 不改 `onSelectInputCapability`、`capabilityRoute`、builtin command 执行链或 service skill 接管链 - - 不新增新的命令页、执行页或角色页 - - 继续只在 mention 输入层做结构语义收口,不碰底层 runtime contract -- 这次子改动的定向验证当前已通过: - - `npm exec vitest run "src/components/agent/chat/skill-selection/inputCapabilitySections.test.ts" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npm run verify:gui-smoke` - - `vitest` 通过:`2 files / 94 tests passed` - - `verify:gui-smoke` 通过:`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - - `verify:local` 本轮已确认经过 `verify:app-version / lint / typecheck`,但仓库当前因大范围脏改动触发全量 smart 批次,后续批次出现既有 React warning 风暴;因此这轮仍以 mention 定向回归 + GUI smoke 作为主线交付证明 - -- `@命令` 当前又继续做了一刀治理减法,直接收掉 `CharacterMention` 对外还保留的旧选择表面,避免前台已经讲“统一调用注册表”,真正落地时却仍靠 `onSelectBuiltinCommand / onSelectSceneCommand / onSelectSkill` 三套并行接线: - - `CharacterMention` 当前已删除上述三条 public callback surface;内建命令、runtime scene、已安装方法现在只认 `onSelectInputCapability` 这条 current 主链 - - mention / slash 两侧的选择分支也同步收口:当上层给了 `onSelectInputCapability` 时,不再额外分流到旧 callback;只有在没有 current capability 边界的 fallback 场景下,才保留输入框文本回填 - - `CharacterMention.test.tsx` 当前也同步删掉了对应 compat 测试,改成围绕 current 路径补守卫:最近使用的 scene / 已安装方法现在都断言 `replayText` 会沿 `onSelectInputCapability` 一起回到发送主链 -- 因此当前 `@ / /` 的选择后合同又更接近路线图里要求的单一事实源: - - current:`onSelectInputCapability -> activeCapability -> resolveInputCapabilityDispatch -> capabilityRoute/displayContent` - - compat:仅剩“未提供 current callback 时的文本回填”这一条局部 fallback,用于脱离主工作区的纯输入场景 - - deprecated / dead:`CharacterMention` 级别的 `onSelectBuiltinCommand / onSelectSceneCommand / onSelectSkill` 已不再保留 -- 这一步继续遵守 P2 的 current 边界: - - 不改 service skill 补参与 A2UI 接管链 - - 不改 `InputbarController / EmptyState` 里的 active capability 事实源 - - 继续只清理 `CharacterMention` 的并行选择边界,不碰 runtime 协议和发送路由 -- 这次子改动的定向验证当前已通过: - - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npx eslint "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx"` - - `npm run typecheck` - - `npm run verify:gui-smoke` - - `vitest` 通过:`1 file / 62 tests passed` - - `eslint` 通过 - - `typecheck` 通过 - - `verify:gui-smoke` 通过:`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` - -- `@命令` 当前继续沿着 `统一调用注册表` 主线把最后一条明显的选择分叉收掉:`service skill` 不再作为 `CharacterMention -> Inputbar / EmptyState` 的特例 surface 暴露,而是并回统一 capability 选择协议,父层内部再转到既有的 service skill 启动链: - - `InputCapabilitySelection` 当前已新增 `service_skill`,但它被明确标成“只用于统一选择边界,不直接进入 send route”;因此 current 主链不再把 service skill 误当成普通 capability route 发送 - - `CharacterMention` 当前在 `@` 选择 service skill、以及 `/scene` 命中带补参需求的 linked scene 时,都会优先走 `onSelectInputCapability({ kind: "service_skill" })`;普通 runtime scene 则继续停留在 `runtime_scene` 主链,不再因为 scene 查询统一 callback 就额外走一轮异步 service skill 探测 - - `skillSelectionBindings` 当前也已停止把 `onSelectServiceSkill` 继续透传给主输入区的 `CharacterMention`;对 `Inputbar / EmptyState` 来说,current 选择边界现在只剩 `onSelectInputCapability` - - `useInputbarController` 与 `EmptyState` 当前则把 `service_skill` capability 作为内部转发分支消费:清掉已有 active capability 后,继续复用既有 `onSelectServiceSkill -> workspaceServiceSkillEntryActions` 启动链,因此这一步只统一“选择协议”,不重写 service skill 执行合同 - - `RuntimeSceneSlashCommand` 当前补上了 `linkedSkillId` 事实源;所以只有真正 linked 的 scene 才会继续尝试 A2UI / service skill 补参接管,普通 scene 不再被误判成 service skill 特例 -- 因此当前 `@ / /` 的 current / compat 口径又更清楚了一层: - - `current`:`CharacterMention -> onSelectInputCapability -> Inputbar / EmptyState -> service_skill 内部转发或 capability route` - - `compat`:`CharacterMention` 仅保留“没有 current callback 时,把 service skill 名称回填到输入框”这条纯输入 fallback - - `deprecated / dead`:主输入区上游继续直接依赖 `onSelectServiceSkill` 作为选择协议的做法,当前已不再保留 -- 这一步继续遵守 P2 的 current 边界: - - 不改 `workspaceServiceSkillEntryActions`、`service_skill_launch` metadata 和既有 service skill 工作区启动链 - - 不把 service skill 粗暴并进 `capabilityRoute` 发送合同,避免把补参型做法误降级成普通 slash route - - 继续只收口 `@命令` 的选择边界,不扩散到 runtime / workspace 执行协议 -- 这次子改动目前已完成的定向验证: - - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npx eslint "src/components/agent/chat/skill-selection/inputCapabilitySelection.ts" "src/components/agent/chat/skill-selection/builtinCommands.ts" "src/components/agent/chat/service-skills/runtimeSceneBinding.ts" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `vitest` 通过:`3 files / 157 tests passed` - - `eslint` 通过 - - `typecheck / verify:gui-smoke`:本轮已启动;当前环境因 `verify:gui-smoke` 触发独立 Cargo target 全量重建,仍在等待最终收口日志 - -- `@命令` 当前又继续往里收了一刀,把 `CharacterMentionPanel` 从“内部还保留多套 item -> callback 分发”的状态收成纯展示层,避免虽然外层已经统一成 `onSelectInputCapability`,但面板内部仍各自知道 `builtin / service skill / scene / installed skill` 的旧分叉: - - `CharacterMentionPanel` 当前只再暴露 `onSelectCapability(item)`,不再直接持有 `onSelectBuiltinCommand / onSelectServiceSkill / onSelectSceneCommand / onSelectInstalledSkill` 这一串内部 surface - - `CharacterMention` 当前接管全部 item 选择分发;因此 mention/slash 的真正行为事实源现在进一步集中到 `CharacterMention` 自己,而不是“面板分一部分、输入组件分一部分” - - `SkillSelector` 也同步复用同一条 `onSelectCapability(item)` 内部分发,但它只消费 `service_skill / installed_skill / available_skill` 三类与技能选择器主任务直接相关的 item,不再让面板替它理解选择语义 -- 因此当前 `@命令` 这一层的分类又更清楚了一点: - - `current`:`CharacterMentionPanel` 负责渲染,`CharacterMention` 负责选择语义,`Inputbar / EmptyState` 负责 capability 消费与 service skill 转发 - - `compat`:仅剩 `SkillSelector` 和工作区入口对 `onSelectServiceSkill` 的执行型消费;这条仍属于既有 service skill 工作区启动链,不是 `@命令` 选择协议 - - `dead`:`CharacterMentionPanel` 内部那套 `service skill` 特例分发当前已收掉 -- 这次子改动新增的定向验证当前已通过: - - `npm exec vitest run "src/components/agent/chat/skill-selection/CharacterMention.test.tsx" "src/components/agent/chat/skill-selection/SkillSelector.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx" "src/components/agent/chat/components/EmptyState.test.tsx"` - - `npx eslint "src/components/agent/chat/skill-selection/CharacterMentionPanel.tsx" "src/components/agent/chat/skill-selection/CharacterMention.tsx" "src/components/agent/chat/skill-selection/SkillSelector.tsx"` - - `vitest` 通过:`4 files / 165 tests passed` - - `eslint` 通过 -- 这轮补跑后的交付验证结论: - - `npm run typecheck` 通过 - - `npm run smoke:agent-runtime-tool-surface-page -- --timeout-ms 240000` 通过 - - `npm run verify:gui-smoke -- --timeout-ms 240000` 首轮在 `smoke:agent-runtime-tool-surface-page` 的 `wait-runtime-summary` 阶段超时;但同一环境下随后的单独复跑已通过,因此当前更接近页面级 smoke 偶发卡顿,而不是本轮 `@命令` 收口引入的新结构性失败 - -- `@命令` / 统一调用注册表当前又继续收掉了一条父层选择分叉:`SkillSelector` 对外不再保留 `onSelectSkill / onSelectServiceSkill` 这组旧 surface,而是彻底并回 `onSelectInputCapability`,让 `我的方法`、空态推荐和输入区技能选择都回到同一条 capability 选择协议: - - `SkillSelector` 当前对外只再暴露 `onSelectInputCapability`;已安装做法和 service skill 都直接吐出统一 capability,面板内部不再替父层维持两套旧 callback 协议 - - `skillSelectionBindings` 当前也同步改成只把 `onSelectInputCapability` 下发给 `SkillSelector`;因此 `Inputbar / EmptyState` 选择技能时,current 主链已统一成 `SkillSelector -> onSelectInputCapability -> activeCapability / service skill 内部转发` - - `EmptyState` 当前把推荐卡、持续流程里残留的 `handleSelectInstalledSkill / handleSelectServiceSkill` 全部收掉,已安装做法和 service skill 的点击都直接走 `handleSelectInputCapability` - - 同时保留 `SkillSelectionSourceProps.onSelectServiceSkill` 这条执行型入口,仅用于父层把 `service_skill` capability 内部转回既有工作区启动链;它现在属于执行消费边界,不再是选择协议 -- 因此当前这一层的治理分类继续收清: - - `current`:`CharacterMention / SkillSelector -> onSelectInputCapability -> Inputbar / EmptyState -> installed_skill | service_skill capability 消费` - - `compat`:`onSelectServiceSkill` 仅保留在 `Inputbar / EmptyState / workspace` 这条执行型消费链里,用于接既有 service skill 工作区启动合同 - - `dead`:`SkillSelector` 对外 `onSelectSkill / onSelectServiceSkill`,以及 `EmptyState` 内部 `handleSelectInstalledSkill / handleSelectServiceSkill` 这批旧选择 surface 当前已收掉 -- 这一步与路线图主目标的关系: - - 它继续把 `@命令 / 我的方法 / 空态推荐` 三处选择入口往 Ribbi 式统一调用注册表收敛,减少“前台讲统一调用,父层却还留多套选择回调”的断层 - - 下一步应继续回到 `@命令` 主链,把仍残留的命令族与 capability 注册表事实源再往单一合同收口,而不是回头给旧 callback 补 compat -- 这次子改动的定向验证当前已通过: - - `npm exec vitest run "src/components/agent/chat/components/EmptyState.test.tsx" "src/components/agent/chat/skill-selection/SkillSelector.test.tsx" "src/components/agent/chat/components/EmptyStateComposerPanel.test.tsx" "src/components/agent/chat/components/Inputbar/index.test.tsx"` - - `npx eslint "src/components/agent/chat/components/EmptyState.tsx" "src/components/agent/chat/skill-selection/SkillSelector.tsx" "src/components/agent/chat/skill-selection/skillSelectionBindings.ts" "src/components/agent/chat/components/Inputbar/hooks/useInputbarController.ts" "src/components/agent/chat/components/Inputbar/index.tsx"` - - `npm run typecheck` - - `vitest` 通过:`4 files / 126 tests passed` - - `eslint` 通过 - - `typecheck` 通过 - -- `@命令` 当前又回到更直接的 Ribbi 对齐主线,先补了一批“能直接复用现有 current 执行链、但 Lime 还没显式认出来”的优先命令别名,避免我们为了追 Ribbi 命令面去新开平级协议或假命令: - - 这轮优先补的是当前最贴现有主链的 10 个 Ribbi 风格入口: - - `@Browser Agent` -> `browser_runtime` - - `@Code Agent` -> `code_runtime` - - `@Read Webpage` / `@Get Homepage` -> `webpage_read` - - `@Image Search` / `@Fetch Image` -> `modal_resource_search` - - `@Audio Extractor` -> `transcription_generate` - - `@Website Voiceover` -> `voice_runtime` - - `@Write Translate` -> `translation` - - `@Web Composer` / `@HTML Preview` -> `webpage_generate` - - 这些入口当前都没有新开 commandKey,也没有新增新的 agent/tool 协议;而是统一作为现有 command projection 的额外 trigger hint 与 parser alias,继续落在既有 `browser / code / url_parse / resource_search / transcription / voice / translation / webpage` 主链 - - `useWorkspaceSendActions` 当前也补上了多词 `@命令` 前缀识别,因此这批 Ribbi 风格别名不只是“catalog 里有名字”,而是真的能带着原始消息进入当前发送主链 -- 因此当前这一刀的分类继续保持干净: - - `current`:新增的是现有 command family 的 Ribbi-compatible alias surface,继续收敛到同一条 `builtin_command -> current executor` 主链 - - `compat`:无新增 compat 命令;旧中文入口仍保留为当前前台名词,和新别名一起共用同一条执行合同 - - `dead`:没有为这批对齐需求新增平级 commandKey、第二套 parser 协议或第二套发送 metadata -- 这一步与路线图主目标的关系: - - 它直接推进了 `@ / /` 作为统一调用注册表的可用面,让 Lime 现在开始能认出一批 Ribbi 风格的浏览器、代码、网页读取、图片搜索与网页编排命令,而不是只在研究文档里对照名字 - - 下一步应继续补“高价值但还没 current 映射”的命令族,例如 preview/publish 渠道化入口与更明确的 browser/code/web orchestration 投影,但仍优先复用现有 command family,不新开第二协议 -- 这次子改动的定向验证当前已通过: - - `npm exec vitest run "src/lib/base-setup/seededCommandPackage.test.ts" "src/components/agent/chat/utils/browserWorkbenchCommand.test.ts" "src/components/agent/chat/utils/codeWorkbenchCommand.test.ts" "src/components/agent/chat/utils/urlParseWorkbenchCommand.test.ts" "src/components/agent/chat/utils/resourceSearchWorkbenchCommand.test.ts" "src/components/agent/chat/utils/transcriptionWorkbenchCommand.test.ts" "src/components/agent/chat/utils/voiceWorkbenchCommand.test.ts" "src/components/agent/chat/utils/translationWorkbenchCommand.test.ts" "src/components/agent/chat/utils/webpageWorkbenchCommand.test.ts"` - - `npm exec vitest run "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" -t "@Read Webpage|@Browser Agent"` - - `npx eslint "src/lib/base-setup/seededCommandPackage.ts" "src/lib/base-setup/seededCommandPackage.test.ts" "src/components/agent/chat/utils/browserWorkbenchCommand.ts" "src/components/agent/chat/utils/browserWorkbenchCommand.test.ts" "src/components/agent/chat/utils/codeWorkbenchCommand.ts" "src/components/agent/chat/utils/codeWorkbenchCommand.test.ts" "src/components/agent/chat/utils/urlParseWorkbenchCommand.ts" "src/components/agent/chat/utils/urlParseWorkbenchCommand.test.ts" "src/components/agent/chat/utils/resourceSearchWorkbenchCommand.ts" "src/components/agent/chat/utils/resourceSearchWorkbenchCommand.test.ts" "src/components/agent/chat/utils/transcriptionWorkbenchCommand.ts" "src/components/agent/chat/utils/transcriptionWorkbenchCommand.test.ts" "src/components/agent/chat/utils/voiceWorkbenchCommand.ts" "src/components/agent/chat/utils/voiceWorkbenchCommand.test.ts" "src/components/agent/chat/utils/translationWorkbenchCommand.ts" "src/components/agent/chat/utils/translationWorkbenchCommand.test.ts" "src/components/agent/chat/utils/webpageWorkbenchCommand.ts" "src/components/agent/chat/utils/webpageWorkbenchCommand.test.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx"` - - `npm run typecheck` - - parser / catalog 定向 `vitest` 通过:`9 files / 45 tests passed` - - 发送链定向 `vitest` 通过:`1 file / 93 tests passed` - - `eslint` 通过 - - `typecheck` 通过 - -- `@命令` 当前继续沿“高置信别名直接挂回现有 current 主链”的策略补了 4 个 Ribbi 入口,不做新 commandKey、不做第二套 expert 协议: - - `@Video Search` -> `modal_resource_search` - - 继续走现有素材检索主链,并在 parser 层默认锁成 `resource_type=video` - - `@Researchers Pro` -> `deep_search` - - 继续走深搜 / `research` 主链,不额外新开“研究专家”协议 - - `@Speaker 1` -> `broadcast_generate` - - 继续走口播 / 播报技能主链,保留现有 `broadcast_skill_launch` - - `@Flyer 3` -> `poster_generate` - - 继续走海报生成入口,并复用现有 `image_skill_launch` 装配合同 -- 这一步继续遵守 current / compat 边界: - - current:只新增 parser alias 与 seeded command trigger hint,全部回挂既有 `modal_resource_search / deep_search / broadcast_generate / poster_generate` - - compat:无新增 compat 命令、无新增旧协议兜底 - - dead:没有因为 Ribbi 命名而发明新的 expert profile commandKey、模型槽位或独立 runtime contract - -- `@命令` 当前继续补了 3 个“业务入口型 expert profile”,但仍坚持只挂回现有 current 主链,不新开 `expert_*` 协议: - - `@Product Search` -> `competitor_research` - - 继续走产品/竞品研究主链,不新增第二套产品搜索 executor - - `@Vision 1` -> `image_generate` - - 继续走视觉生成主链,作为 `@配图` 的 Ribbi 风格入口 - - `@Sales 1` -> `presentation_generate` - - 继续走演示稿主链,并在 parser 层默认收口为 `sales_deck` -- 这一步的 current / compat 口径保持不变: - - current:只新增 parser alias、默认语义和 seeded command trigger hint - - compat:不新增并行 expert profile runtime - - dead:没有把 `Product / Vision / Sales` 再做成独立命令家族或模型槽位按钮 - -- 任务中心导航与会话加载本轮又补了两刀,直接对应“工作台按钮不见了”和“打开会话仍慢”: - - 左侧一级导航当前新增显式 `工作台` 入口,点击后优先回到当前 workspace 的 `claw` 会话;如果当前已经在 `claw`,该入口会保持高亮 - - `AppSidebar` 顶部新增的 `工作台` 已在真实页面复测可见,`Playwright` 当前能看到 `新建任务 / 工作台 / 我的方法 / 灵感库` 四个主入口 - - `useAgentSession` 当前不再在进入 `claw` 工作台后无条件拉整包会话,而是改成带 `workspaceId` 调 `runtime.listSessions(...)`,减少“打开某个会话时又把整个库捞回来”的额外负担 -- 这一步与当前主线的关系: - - 它先修复任务中心当前最直接的导航回退问题,让用户能稳定回到工作台 - - 同时继续把“会话打开慢”从 `AppSidebar` 一层推进到 `claw` 自己的 topics hydrate 层,避免只修左侧列表、不修进入页内部的全量拉取 -- 这次子改动的最小验证当前已通过: - - `npm exec vitest run "src/components/AppSidebar.test.tsx" "src/lib/navigation/sidebarNav.test.ts" "src/components/agent/chat/hooks/agentRuntimeAdapter.test.ts"` - - `npx eslint "src/components/AppSidebar.tsx" "src/components/AppSidebar.test.tsx" "src/lib/navigation/sidebarNav.ts" "src/lib/navigation/sidebarNav.test.ts" "src/components/agent/chat/hooks/agentRuntimeAdapter.ts" "src/components/agent/chat/hooks/agentRuntimeAdapter.test.ts" "src/components/agent/chat/hooks/useAgentSession.ts"` - - `Playwright` 真实页面复测:左侧已出现 `工作台` 按钮,点击后主区顶部能看到 `工作台` 入口 - -- 继续排查“打开某个对话仍然很慢”时,已确认一个后端主因并先收一刀: - - `agent_runtime_get_session` 之前在“读取会话详情”前会无条件执行 `resume_runtime_queue_if_needed(...)`,导致单纯打开对话也可能顺带恢复队列、拉起浏览器 runtime,并把耗时堆进 `resume_queue_ms` - - 当前已把 `agent_runtime_get_session` 和 `agent_runtime_get_thread_read` 收回纯读取语义,不再在只读查询里自动恢复排队执行;恢复动作继续只保留给显式 `agent_runtime_resume_thread` - - 这一步直接对应用户现场里“打开归档/切回对话时很慢、还伴随 Chrome profile 拉起与内存波动”的链路,目的是先把“打开会话 = 可能触发执行恢复”这个错误耦合拆掉 - -- `@命令` 当前继续按 Ribbi 对齐主线补上了第一条“持续运营 expert”入口,但仍只挂回现有 current `local_service_skill` 主链,没有新开第二套 expert/runtime 协议: - - `@Growth Expert` -> `growth_runtime` -> `local_service_skill(account-performance-tracking)` - - 新增的 current 入口是 `@增长`,并把 `@Growth Expert` 作为 trigger hint / parser alias;因此前台统一仍是 Lime 当前命名,不再把 Ribbi 的 profile 名直接做成第二排主入口 - - `growthWorkbenchCommand` 当前已支持解析: - - 平台:`平台:X / platform:TikTok` - - 账号:`账号:@openai,@anthropic / accounts:@capcut,@notion` - - 回报频率:`回报频率:每天 09:00 / cadence: every day 08:00` - - 告警阈值:`告警阈值:互动率低于 2% / alert: engagement down 20%` - - 未显式写 `账号:` 时,也会最小化从 `@handle` 推断账号列表 - - `useWorkspaceSendActions` 当前会把这类输入统一改写成 `service_scene_launch.kind=local_service_skill`,并写入: - - `scene_key=growth_runtime` - - `entry_source=at_growth_command` - - `platform / account_list / report_cadence / alert_threshold` - - `slot_values` - - mention usage / service skill usage / replay text 现在也能正确记录这组增长字段,不再只支持 `@配音` 的 `target_language / voice_style` - - `seededCommandPackage` 当前已补上 `growth_runtime` 的 command projection,并绑定 `account-performance-tracking` - - current / compat / dead 口径保持一致: - - current:新增的是 `growth_runtime` 这个对现有 service skill 的前台入口投影 - - compat:无新增 compat 命令、无新增旧协议过桥 - - dead:没有把 `Growth Expert` 实现成新的 expert profile runtime、模型槽位或独立自动化协议 - - 这次定向验证当前已通过: - - `npx vitest run "src/components/agent/chat/utils/growthWorkbenchCommand.test.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" "src/lib/base-setup/seededCommandPackage.test.ts" "src/lib/api/skillCatalog.test.ts"` - - `npx eslint "src/components/agent/chat/utils/growthWorkbenchCommand.ts" "src/components/agent/chat/utils/growthWorkbenchCommand.test.ts" "src/components/agent/chat/utils/mentionCommandReplayText.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" "src/lib/base-setup/seededCommandPackage.ts" "src/lib/base-setup/seededCommandPackage.test.ts" "src/lib/api/skillCatalog.test.ts"` - - 定向 `vitest` 通过:`4 files / 118 tests passed` - - `eslint` 通过 - -- `@命令` 当前继续按 Ribbi 对齐主线补上了 4 个写作入口,但仍只挂回现有 current 内容成稿主链,没有新开 `writing / blog / newsletter` 第二协议: - - `@Writing Partner / @Writers 1 / @Blog 1 / @Newsletters Pro` -> `writing_runtime` -> `content_post_with_cover` - - 新增的 current 入口是 `@写作`,并把 `@文案 / @write` 作为本地 parser alias;Ribbi 风格命名只作为 trigger hint / alias,不再继续做独立 expert profile runtime - - `useWorkspaceSendActions` 当前会把这组输入统一改写成 `/content_post_with_cover ...`,并写入 `request_metadata.harness.publish_command.entry_source = at_writing_command` - - `writing_runtime` 的 seeded command、replay text、最近使用平台补齐、输入能力分组当前都已接通 - - current / compat / dead 口径保持一致: - - current:新增的是 `writing_runtime` 这个对现有 `content_post_with_cover` 的前台入口投影 - - compat:无新增 compat 命令、无新增旧协议桥接 - - dead:没有把 `Writing Partner / Blog 1 / Newsletters Pro` 再做成独立 runtime、模型槽位或 blog/newsletter 专用协议 - -- `@命令` 当前又补了一组“网页编排 / 网页素材处理”对齐,但仍全部挂回现有 current 主链,没有新开 `computer / fetch / web-copy / web-style` 第二协议: - - `@Mini Tester / @Web Scheduler / @Web Manage` -> `browser_runtime` - - `@Fetch` -> `web_scrape` -> `url_parse` - - `@Web Copy` -> `writing_runtime` -> `content_post_with_cover` - - `@Web Style` -> `webpage_generate` - - 这一步继续遵守 current / compat 边界: - - current:只新增 parser alias 与 seeded trigger hint,全部回挂既有 `browser_runtime / web_scrape / writing_runtime / webpage_generate` - - compat:无新增 compat 命令、无新增旧协议桥接 - - dead:没有把这些 Ribbi 标签做成独立 runtime family,也没有把 `Ribbi Computer / GPT 5 Search / Quick Agent` 这类当前缺少诚实宿主的项硬塞进前台 - -- 任务中心本轮继续修复“打开一个会话却出现多个顶部任务 Tab”和“直达会话等待 12 秒才出现 Tab”的问题: - - `claw + initialSessionId` 直达入口现在会在任务 Tab 初始状态阶段直接把当前 workspace 的 `lime_task_center_open_task_ids` 覆盖为单个会话 id,不再继承旧 localStorage 里的 6 个历史 Tab - - 归档 / detached 会话在目标不属于当前 active topics 时,不再触发 `reconcile` 回退生成默认多任务 Tab;打开归档会话时顶部不会混入普通任务 - - 直达已有会话时,`topics` 加载从原先 `SESSION_ENTRY_DEFERRED_LOAD_MS=12s` 改为立即加载;12 秒延迟只保留给空白新建任务首页和 skills / provider / memory 等辅助加载,避免会话恢复被首页懒加载策略误伤 - - Playwright 真实页面复测: - - 人为写入 6 个旧 Tab 后点击最近对话,单 Tab 就绪约 `298ms`,storage 覆盖为 `["420a426f-11cf-4749-96b5-fc11e2220775"]` - - 打开归档会话 `f24b2d03-b4a9-4ab4-a3ab-ec2a55e90d4d` 后顶部 `task-center-tab-*` 为 `[]`,storage 覆盖为该归档会话 id,不再显示普通任务 - - 本轮验证: - - `npm run test -- "src/components/agent/chat/utils/taskCenterTabs.test.ts"` 通过:`19 tests` - - `npm run test -- "src/components/agent/chat/index.test.tsx" -t "任务中心初始会话标签"` 通过:`3 tests` - - `npm run bridge:health -- --timeout-ms 120000` 通过 - - `npm run verify:gui-smoke` 通过 - - 剩余风险: - - 归档详情 `f24b2d03-b4a9-4ab4-a3ab-ec2a55e90d4d` 本次后端 `agent_runtime_get_session` 仍约 `3.2s`,主要耗时落在 `detail_ms≈3.0s`;这已经不是顶部多 Tab/12 秒 topics defer 问题,后续应单独排查归档会话详情读取路径 - -- 任务中心慢加载继续用 E2E 收口了一刀,确认本轮实际慢点已从 Tab 状态转到模型初始化桥接噪音: - - Playwright 本地 E2E 首轮复测时,普通最近对话已经能在 `~2.0s` 内显示单个 active Tab,但控制台仍出现 `get_provider_alias_config` / `get_all_models_by_provider` 的 DevBridge unknown command - - 当前已补齐 `src-tauri/src/dev_bridge/dispatcher/models.rs` 的模型命令桥接: - - `get_provider_alias_config` - - `get_all_models_by_provider` - - `get_all_available_models` - - `get_default_models_for_provider` - - 这些命令本来已经存在于正式 Tauri 注册和前端网关,本轮只是补齐浏览器 DevBridge 分发,不新增 compat 协议,也不让模型初始化继续掉 mock / unknown fallback - - DevBridge HTTP 探针已确认运行中桥接返回 `200`: - - `get_provider_alias_config` -> `{"result":null,"error":null}` - - `get_all_models_by_provider` -> provider map - - `get_all_available_models` -> `[]` - - Playwright 本地 E2E 复测结果: - - 首页可用:`~1.6s` - - 人为写入 6 个旧 Tab 后点击最近对话:`914ms` 出现单个 active Tab,`hasWorkbenchButton=true` - - 点击归档会话 `f24b2d03-b4a9-4ab4-a3ab-ec2a55e90d4d`:`908ms` 进入详情,顶部普通任务 Tab 为 `[]`,storage 覆盖为该归档 id - - 普通与归档两条路径 console error 均为 `0` - - 本轮新增验证: - - `cargo test --manifest-path "src-tauri/Cargo.toml" bridged` 通过:`22 tests` - - `npm run typecheck` 通过 - - `npm run test -- "src/components/agent/chat/utils/taskCenterTabs.test.ts"` 通过:`19 tests` - - `npm run test -- "src/components/agent/chat/index.test.tsx" -t "任务中心初始会话标签|归档会话|导航会话"` 通过:`5 tests` - - `npm run test:contracts` 通过 - - `npm run verify:gui-smoke` 通过 - - 剩余风险: - - 本轮证明“打开一个出现多个任务”和模型桥接 unknown 已收口;若用户仍感知慢,下一刀应继续看 `agent_runtime_get_session` 详情读取内部的 `detail_ms` 组成,而不是再改顶部 Tab 状态 diff --git a/docs/exec-plans/limenext-v2-fs-blocker-2026-04-22.md b/docs/exec-plans/limenext-v2-fs-blocker-2026-04-22.md deleted file mode 100644 index 5ad56647f..000000000 --- a/docs/exec-plans/limenext-v2-fs-blocker-2026-04-22.md +++ /dev/null @@ -1,156 +0,0 @@ -# LimeNext V2 文件系统阻塞记录(2026-04-22) - -> 后续状态说明:本文是当日权限阻塞的历史记录,不再代表 current 现状。 -> 现役事实源以 [../roadmap/limenextv2/sceneapp-current-boundary.md](../roadmap/limenextv2/sceneapp-current-boundary.md) 与 [./limenext-progress.md](./limenext-progress.md) 的最新条目为准。 -> 文中提到的临时命名如 `SceneAppCurrentPresentationDescriptor`,现已落回 `SceneAppPresentationDescriptor`;对象级 `SceneAppCurrent*` 也已全部删除。 - -## 背景 - -当前主线仍是把 `LimeNext V2` 的 current 对象边界继续收口,尤其是: - -1. `sceneapp` current API / 展示 / 测试夹具不再继续把 compat 云执行命名当成普通 current 值 -2. compat 旧值只保留在显式输入归一化、alias、历史锚点与 compat 测试里 - -在本轮前半段,已经完成: - -1. `src/lib/api/sceneapp.ts` - - compat `cloud_scene / cloud_session / cloud_runtime / launch_cloud_scene` 已继续被正规化为 current 本地执行语义 - - compat `sceneappType = cloud_managed` 已在 API 归一化阶段转成 current `local_instant / local_durable / browser_grounded / hybrid` -2. `src/lib/api/sceneapp.test.ts` - - 已补充 compat `cloud_managed` -> current 类型投影断言 -3. `src/lib/sceneapp/product.test.ts` - - 默认 current fixture 已去掉 `cloud_runtime` -4. `src/components/sceneapps/SceneAppsPage.test.tsx` - - 默认 current fixture 已去掉 `cloud_runtime` -5. `docs/exec-plans/at-command-local-execution-alignment-plan.md` -6. `docs/exec-plans/limenext-progress.md` - -## 本轮进一步想继续做但被阻塞的点 - -原计划继续收口这两处: - -1. `src/lib/sceneapp/types.ts` - - 理想目标:让 current `SceneAppDescriptor` 不再公开承认 `cloud_managed` - - 只在显式 compat helper / compat 输入边界保留 `SceneAppCompatType` -2. `src/lib/sceneapp/presentation.ts` - - 理想目标:`getSceneAppPresentationCopy(...)` 只消费 current descriptor - - compat `cloud_managed` 只保留给 `resolveSceneAppTypePresentation(...)` / `getSceneAppTypeLabel(...)` 这类显式 compat helper -3. `src/lib/sceneapp/presentation.test.ts` - - 理想目标:把「compat helper 断言」和「current descriptor copy 断言」拆开 - -## 实际阻塞 - -从本轮中段开始,仓库内既有文件出现系统级 `EPERM / Operation not permitted`: - -1. `apply_patch` 无法继续读取既有文件 -2. shell 无法直接读取或覆写既有文件 -3. `mv` 也无法用新文件原子替换既有文件 -4. `git` / `npm` / `node` 在仓库根 cwd 下也会受到连带影响 - -但新文件仍可创建,因此这份记录被补写下来。 - -## 继续诊断补充(2026-04-22) - -后续继续排查时,又确认了两件事: - -1. 当前执行器在仓库根真实调用 `getcwd()` 也会被系统拒绝 - - 表现为 Python `os.getcwd()` 报 `PermissionError: [Errno 1] Operation not permitted` - - 这解释了为什么部分依赖 cwd 的命令会出现额外异常 -2. 前端 dev server 仍能读取源码并通过 sourcemap 暴露 `sourcesContent` - - 可通过 `http://127.0.0.1:1420/src/...` 取回当前前端源码文本 - - 这条路径只适合继续分析 current 边界,不解决任何既有文件写入问题 -3. 根据 dev server 暴露出的当前源码,`src/lib/sceneapp/types.ts` 已经处于半收口状态 - - `SceneAppType` 已经是 current-only - - `SceneAppCompatType = "cloud_managed"` 已是显式 compat 类型 - - 当前更大的残留已转移到 `presentation.ts / presentation.test.ts` 的展示与测试边界 -4. 已确认一个可操作但不优雅的旁路 - - 直接 shell 仍无法读取或覆写受阻文件 - - 但 Finder 可以把受阻文件复制到 `/private/tmp`,也可以把 `/private/tmp` 里的同名文件覆盖回仓库 - - 因此当前可以通过: - - Finder duplicate 到 `/private/tmp` - - 在 `/private/tmp` 用 `apply_patch` 修改 - - 再由 Finder duplicate 覆盖回仓库 - - 继续推进代码收口 - -因此,本轮可继续做的事变成: - -1. 利用 dev server 把前端现状分析清楚 -2. 把 current 规划和阻塞记录补到可写文档 -3. 对少量关键文件使用 `Finder -> /private/tmp -> apply_patch -> Finder` 的旁路修改 - -本轮仍不能安全做的事: - -1. 大范围批量改仓库既有文件 -2. 依赖 repo cwd 的常规 `git / npm / node` 工作流 -3. 假装环境已经恢复正常 - -## 直接影响 - -当前不适合按常规 shell 工作流继续对既有源码文件做大范围机械修改,否则仍然容易在未知权限状态下把主线卡死。 - -但对少量关键文件,可以使用上面的 Finder 旁路继续推进。 - -## 权限恢复后建议的下一刀 - -本轮通过 Finder 旁路,已经实际完成: - -1. `src/lib/sceneapp/types.ts` - - 执行族当前已拆成: - - `SceneAppExecutorBindingFamily` - - `SceneAppCompatBindingFamily` - - 因此“当前执行族”和“只为兼容旧目录保留的 cloud_scene”不再混在单一别名里 -2. `src/lib/sceneapp/catalog.ts` - - `normalizeCompatSceneAppBindingFamily(...)` 当前已显式返回 current 执行族 - - `resolveDistinctBindingFamilies(...)` 当前也已收窄到 current 执行族数组 -3. `src/lib/sceneapp/launch.ts` - - `SceneAppWorkspaceExecutionDraft.adapterKind` 当前已收窄到 current 执行族 - - `normalizeWorkspaceAdapterKind(...)` 当前也已显式返回 current 执行族 -4. `src/lib/sceneapp/types.ts` - - `SceneAppLaunchRequirementKind` 当前已拆成: - - `SceneAppLaunchRequirementCoreKind` - - `SceneAppCompatLaunchRequirementKind` - - 因此“当前允许的启动前置”和“只为兼容旧目录保留的 cloud_session”不再混在同一个裸联合注释里 -5. `src/lib/sceneapp/types.ts` - - `SceneAppRuntimeContext` 当前已只保留 current 字段 - - `cloudSessionReady / cloud_session_ready` 当前已收进 `SceneAppCompatRuntimeContextInput` - - `readSceneAppDirectorySessionReadyCompat(...)` 继续兼容读取旧 wire 字段,但 current interface 不再直接承认它们 -6. `src/lib/sceneapp/presentation.ts` - - 新增 `SceneAppCurrentPresentationDescriptor` - - `getSceneAppPresentationCopy(...)` / `inferFallbackCopy(...)` 当前已显式收窄到 current descriptor -7. `src/lib/sceneapp/presentation.test.ts` - - compat `cloud_managed / cloud_runtime` 断言与 current descriptor copy 断言已拆开 - - 已删掉“compat descriptor 伪装成 current descriptor”的测试夹具写法 -8. 定向旁路验证 - - `npx --yes vitest@3.2.4 run /private/tmp/lime-sceneapp-edit/presentation.test.ts` - - 结果:`3 tests passed` -9. 扩展旁路验证 - - 已通过: - - `npx --yes vitest@3.2.4 run "/private/tmp/sceneapp-scan/runEntryNavigation.test.ts" "/private/tmp/sceneapp-scan/launch.test.ts" "/private/tmp/sceneapp-scan/product.test.ts" "/private/tmp/sceneapp-scan/presentation.test.ts" "/private/tmp/sceneapp-scan/navigation.test.ts"` - - 结果:`5 files / 31 tests passed` - - 已确认但暂不视为代码回归: - - 把整个 `/private/tmp/sceneapp-scan/*.test.ts` 一次性跑宽时,`storage / entry` 会因缺少 `window/jsdom` 失败,`automation / executionPromptActions / catalog` 会因缺少 repo alias `@/...` 失败 - - 这些失败说明的是“临时副本环境不完整”,不等于本轮 `sceneapp presentation` 收口本身引入了新断链 - -在常规权限恢复后,优先继续下面这组剩余收口: - -1. `src/lib/sceneapp/types.ts` - - 保持 `SceneAppType` 直接作为 current 类型事实源 - - 不要把 `SceneAppDescriptor` 再改宽回 compat 联合类型 -2. 然后补跑 repo 内正式校验: - - `npx eslint "src/lib/sceneapp/types.ts" "src/lib/sceneapp/presentation.ts" "src/lib/sceneapp/presentation.test.ts"` - - `npm exec vitest run "src/lib/sceneapp/presentation.test.ts" "src/lib/sceneapp/product.test.ts" "src/lib/api/sceneapp.test.ts" "src/components/sceneapps/SceneAppsPage.test.tsx"` - - `npm run governance:legacy-report` - - `npm run typecheck` - -## 结论 - -这不是路线图方向摇摆,而是一次纯环境阻塞。 - -主线判断不变: - -1. current 前台与 current API 对象继续坚持本地执行语义 -2. compat 云执行命名继续只留在显式兼容边界 -3. 当前已经通过 Finder 旁路推进了 `presentation` 这条 current 边界收口 -4. 一旦文件系统权限恢复,下一步就直接回到 repo 内正式校验和余下的少量边界清理 -5. 当前边界的文档事实源已补到: - - [../roadmap/limenextv2/sceneapp-current-boundary.md](../roadmap/limenextv2/sceneapp-current-boundary.md) diff --git a/docs/exec-plans/multimodal-runtime-contract-plan.md b/docs/exec-plans/multimodal-runtime-contract-plan.md deleted file mode 100644 index 147f020f7..000000000 --- a/docs/exec-plans/multimodal-runtime-contract-plan.md +++ /dev/null @@ -1,483 +0,0 @@ -# Lime 多模态运行合同实施计划 - -## 摘要 - -本计划承接 `docs/roadmap/warp/`,用于把 Warp / ClaudeCode 参考落成 Lime 可检查的底层多模态运行合同。 - -本轮主目标不是先改 `@` 命令,而是先建立: - -1. 底层运行事实源地图 -2. `ModalityRuntimeContract` schema -3. 可机器检查的 contract registry -4. 最小治理守卫 - -## 主线声明 - -从现在开始,多模态能力默认向下面这条 current 主链收敛: - -```text -runtime identity - -> ModalityRuntimeContract - -> capability matrix - -> ModalityExecutionProfile - -> executor binding - -> domain artifact graph - -> evidence / replay / task index - -> viewer - -> entry binding -``` - -`@` 命令、按钮、Scene 只允许作为上层 entry binding,不能直接拥有 task、model、artifact、viewer 或 evidence 的事实写入权。 - -## 当前阶段 - -### Phase 0:底层运行事实源盘点 - -状态:进行中。 - -本阶段输出: - -1. `docs/roadmap/warp/runtime-fact-map.md` -2. 底层 fact source 的 `current / compat / deprecated / dead` 分类 -3. 后续 contract registry 的 owner / reader / writer 约束 - -### Phase 1:ModalityRuntimeContract schema - -状态:进行中。 - -本阶段输出: - -1. `docs/roadmap/warp/contract-schema.md` -2. `src/lib/governance/modalityRuntimeContracts.json` -3. `scripts/check-modality-runtime-contracts.mjs` -4. `npm run governance:modality-contracts` - -### Phase 2:多模态能力矩阵 - -状态:进行中。 - -本阶段输出: - -1. `docs/roadmap/warp/capability-matrix.md` -2. `src/lib/governance/modalityCapabilityMatrix.json` -3. contract 守卫检查 `required_capabilities` 与 `routing_slot` 是否引用已登记能力和模型角色 -4. `request_model_resolution` 已开始消费 `TaskProfile.routingSlot`,把 `browser_reasoning_model`、`image_generation_model`、`audio_transcription_model`、`voice_generation_model` 等槽位折叠成最小模型能力需求;候选池会过滤不满足能力的模型,显式用户模型锁定仍保留锁定模型但输出 `*_candidate_missing` gap,并在 gap 来源为 `explicit_model_lock` 时把 `limit_state.status` 标为 `user_locked_capability_gap`,由 runtime turn 在模型执行前阻断。 - -### Phase 3:ModalityExecutionProfile - -状态:进行中。 - -本阶段输出: - -1. `docs/roadmap/warp/execution-profile.md` -2. `src/lib/governance/modalityExecutionProfiles.json` -3. `image_generation`、`browser_control`、`pdf_extract`、`voice_generation`、`audio_transcription`、`web_research`、`text_transform` 的最小 execution profile。 -4. contract 守卫检查 current contract 必须被 profile 覆盖,且 profile 的模型角色、权限、LimeCore policy、artifact policy 必须覆盖 contract。 -5. `src/lib/governance/modalityExecutionProfiles.ts` 把 profile / adapter registry 解析成 launch metadata 快照。 -6. Rust runtime contract snapshot、Evidence Pack、Replay 与统一媒体任务索引已经携带 profile / adapter key;媒体任务 worker 已在进入图片、配音、转写执行器前做最小 profile / adapter / executor binding preflight;Browser Assist 工具层现在也会在真实浏览器动作前校验 `browser_control` 的 execution profile、executor adapter 与 executor binding,失败时返回 `runtime_preflight` 工具错误并保留同一 runtime contract metadata,供 Evidence / Replay 识别为被合同阻断;`LimeSkillTool` 现在也会对 current Skill 主链生成治理 registry 驱动的 `modality_runtime_contract` metadata,并在上层显式传入冲突 `execution_profile` / `executor_adapter` / `executor_binding` 时阻断进入 Skill 执行器;旧 `lime_run_service_skill` 仍是 compat guard,但命中 `voice_generation` 时会携带并校验 `service_skill:voice_runtime` 合同,避免旧云运行工具被误看成 current executor;LimeCore policy refs/snapshot 已进入 runtime contract、Evidence Pack 与统一媒体任务索引;后续仍需在 registry 出现明确 `gateway:*` adapter 后接入 Gateway preflight、真实 runtime policy merge、更完整 thread read 决策解释和 GUI 可视化。 -7. `thread_read.runtime_summary.modalityRuntime` 现在会从最近 ToolCall / FileArtifact 的同一 `runtime_contract` 投影 `contractKey`、`modality`、`routingSlot`、`requiredCapabilities`、`profileKey`、`executorAdapterKey`、`executorKind` 与 `executorBindingKey`;这只暴露最近合同的 profile / adapter / binding 摘要,不把 thread read 变成上层 `@` 命令事实源。 -8. `SessionExecutionRuntimeTaskProfile.routingSlot` 已接入 provider/model resolution 的最小能力 enforcement:非显式用户锁定路径会优先在候选池内选择满足 runtime requirements 的模型,显式用户锁定路径继续 honored,但 `capability_gap` 会暴露 `browser_reasoning_candidate_missing`、`image_generation_candidate_missing` 等 gap code。 -9. `SessionExecutionRuntimePermissionState` 已把 `permissionProfileKeys` 推进为 `lime_runtime.permission_state` 最小权限摘要,并同步进入 `runtime_summary.permissionStatus / permissionAskCount / permissionBlockingCount`、`AgentRuntimeThreadReadModel.permission_state` 与前端 execution runtime / thread read 类型。本阶段解释 profile 声明、需确认 profile 与空阻断清单,不把 `ask_user_question` 视为风险权限;未解决确认现在会在 prelude 状态发出后、模型执行前阻断 turn,且最小 `RequestUserInput` 权限确认 + `agent_runtime_respond_action` 写回 + 下一轮 `resolved/denied` metadata merge 已接入,避免声明态需确认权限被误当成功执行;这仍不是完整权限系统或 LimeCore 云授权。 - -### Phase 5:Executor Adapter registry - -状态:进行中。 - -本阶段输出: - -1. `src/lib/governance/modalityExecutionProfiles.json` 的 `executor_adapters` -2. `skill:image_generate`、`browser:browser_assist`、`skill:pdf_read`、`service_skill:voice_runtime`、`skill:transcription_generate`、`skill:research`、`skill:text_transform` 的最小 adapter 声明。 -3. contract 守卫检查 current contract 的 `executor_binding` 必须能解析到 `executor_kind:binding_key` adapter。 -4. adapter 的 progress / cancel / resume / artifact 支持位、artifact output、permission requirements 与 failure mapping 必须覆盖 contract。 -5. 前端 `runtime_contract` snapshot 已携带 `executor_adapter` 摘要,避免上层入口继续只传 executor binding。 -6. 统一媒体任务索引已经能查询 `execution_profile_keys`、`executor_adapter_keys`、`limecore_policy_refs` 与每条 snapshot 的 `execution_profile_key` / `executor_adapter_key` / `executor_kind` / `executor_binding_key` / `limecore_policy_snapshot_status`;图片、配音、转写 worker 已消费同一 adapter registry 做执行前检查;Browser Assist 工具层已消费同一 `browser_control` runtime contract 做执行前检查,错误结果继续带 `modality_runtime_contract` 与 `last_error(stage=runtime_preflight)`;`LimeSkillTool` 已把 `pdf_read`、`research`、`report_generate`、`site_search`、`summary`、`translation`、`analysis`、`transcription_generate` 映射到 current 底层合同,并把 profile / adapter / binding 快照从治理 JSON 注入 Skill tool metadata;`lime_run_service_skill` 作为旧服务型工具只保留 compat guard,命中 `voice_generation` 时必须通过 `voice_generation_profile`、`service_skill:voice_runtime` adapter 与 `service_skill:voice_runtime` binding 检查,否则返回 `runtime_preflight`;Gateway preflight 仍后置,不能从 Telegram / 微信 / 飞书 / Discord ingress 硬造 `gateway:*` executor adapter。 -7. thread read 可见层已开始消费同一 adapter 摘要:`runtime_summary.modalityRuntime` 会并列暴露最近合同的 profile / adapter / binding key,供后续 GUI / evidence 解释复用;真实 Gateway adapter preflight 仍等待 registry 出现明确 `gateway:*` adapter 后再接。 -8. provider/model resolution 已消费同一 `routingSlot` 摘要来约束模型候选池:Browser reasoning、图片生成、音频转写、语音生成、结构化文档与 cheap summary 都会先映射成 runtime model capability requirements,再影响候选数、自动重选与 gap 输出。 - -### Phase 6:LimeCore 目录与策略接线 - -状态:进行中。 - -本阶段输出: - -1. `runtime_contract.limecore_policy_refs` 声明每个 current contract 依赖的 LimeCore 控制面事实源。 -2. `runtime_contract.limecore_policy_snapshot` 现在落最小本地默认决策:`status=local_defaults_evaluated`、`decision=allow`、`decision_source=local_default_policy`、`decision_scope=local_defaults_only`。这个 `allow` 只表示本地默认策略没有阻断继续路由,不等于 LimeCore tenant / provider 真实放行。 -3. `runtime_contract.limecore_policy_snapshot.policy_inputs` 现在按 ref 生成最小输入清单,标记 `status=declared_only`、`value_source=limecore_pending`;`missing_inputs` 继续列出等待 LimeCore 真实命中的控制面输入。 -4. Evidence Pack `modalityRuntimeContracts.snapshotIndex.limecorePolicyIndex` 汇总 policy refs、snapshot status、decision、decision source、policy inputs、missing inputs 与 unresolved refs,方便后续 allow / ask / deny 与 LimeCore audit 对齐。 -5. `list_media_task_artifacts` 的统一媒体任务索引输出 policy refs / snapshot status / decision / decision source / missing inputs / unresolved refs,以及 `policy_evaluation` 的 status / decision / blocking / ask / pending refs,让任务列表不必读取隐藏 task JSON 才能知道当前 contract 依赖哪些云控制面、卡在哪类 evaluator 输入。 -6. Harness evidence 面板现在展示 `LimeCore 策略缺口` 摘要,直接暴露 policy snapshot、控制面 refs、missing inputs、local default decision、profile / adapter 与 `declared_only / limecore_pending` 输入状态。 -7. Replay / grader 现在把 `limecorePolicyIndex` 纳入 suite tags、failure modes、success criteria、blocking checks 与多模态合同检查,要求 replay 继续保留 policy refs / missing inputs / local default decision,不能把本地默认 `allow` 当真实云策略放行。 -8. `policy_value_hits[]` / `pending_hit_refs[]` / `policy_value_hit_count` 已进入 runtime contract、Evidence Pack、统一媒体任务索引、前端 normalizer 与浏览器 mock;默认命中数为 `0`,只表达“真实 LimeCore 命中值尚未接入”,不伪造 model catalog / offer / tenant flags。 -9. Policy hit resolver seam 已能消费传入的 `status=resolved` 命中值,并自动把对应 ref 从 `missing_inputs` / `pending_hit_refs` 移到 `evaluated_refs`;当所有 refs 都已命中时,最小 `policy_input_evaluator` 会把已命中的 `model_catalog / provider_offer / tenant_feature_flags / gateway_policy` 信号折叠成 `allow / ask / deny` 的可审计决策;仍有 pending refs 时,顶层 `decision` 继续保持 `local_default_policy / local_defaults_only`,避免把输入缺口伪装成真实策略放行。 -10. 图片任务执行前的 model registry assessment 现在会作为最小本地 `model_catalog` hit producer 写回同一 `policy_value_hits(status=resolved, value_source=local_model_catalog)`;该 hit 只证明模型目录输入已命中,模型是否具备 `image_generation` 能力仍由 runtime preflight 单独判定。 -11. 图片任务进入真实执行器前已能从已解析的本地 runner config / API key 与 task payload provider/model 生成最小 `provider_offer` hit,写回同一 `policy_value_hits(status=resolved, value_source=local_provider_offer)`;该 hit 不序列化 API key,只证明 provider offer 输入已命中,不代表 tenant/provider/gateway 已策略放行。 -12. Browser Assist 与 Web Research 类 launch 会从请求侧 `harness.oem_routing` 生成最小 `gateway_policy` hit,写回同一 `policy_value_hits(status=resolved, value_source=request_oem_routing)`;该 hit 只记录 tenant/provider/quota/can_invoke/fallback 等路由输入,不包含 session token,也不把本地默认 `allow` 升级成真实网关放行。 -13. 请求侧会从 OEM Cloud bootstrap snapshot 的 `features` 生成最小 `tenant_feature_flags` hit,写回同一 `policy_value_hits(status=resolved, value_source=oem_cloud_bootstrap_features)`;该 hit 只解释租户功能开关输入已命中,不包含 session token。 -14. `policy_evaluation` 现在在每个 snapshot 中记录 evaluator 状态:`input_gap` 时只说明还缺控制面输入,`evaluated` 时才允许顶层 `decision_source=policy_input_evaluator`;统一媒体任务索引同步暴露 evaluation status / decision / source 与 blocking / ask / pending refs。该 evaluator 只消费本地已命中的 policy inputs,不接 LimeCore 云 run/poll,也不把 LimeCore 扩张为默认 executor。 -15. `thread_read.runtime_summary.limecorePolicy` 现在会从最新 tool metadata / file artifact 中的 runtime contract 读取 LimeCore policy snapshot,投影 contract、snapshot status、顶层 decision、decision source/scope/reason、refs、missing/pending refs、hit count 与 evaluator 摘要;这只解释当前线程最近一次可见 policy 决策输入,不新增命令、不接云 run/poll。 -16. `list_media_task_artifacts.modality_runtime_contracts` 现在会把 evaluator 摘要提升为索引字段:`limecore_policy_evaluation_statuses`、`limecore_policy_evaluation_decisions`、`limecore_policy_evaluation_decision_sources`、`limecore_policy_evaluation_blocking_refs`、`limecore_policy_evaluation_ask_refs`、`limecore_policy_evaluation_pending_refs`,并在每条 snapshot 输出对应字段;这让任务列表、恢复层和后续 GUI 卡片能直接区分 pending input gap、ask 与 deny,不读取隐藏 task JSON。 -17. 配音与转写任务卡恢复层现在消费同一索引里的 `limecore_policy_evaluation_*` 字段,把 `input_gap` 渲染为 `LimeCore 策略输入待命中: N`,把已评估 `deny / ask` 渲染为阻断或需确认的 refs;这只解释本地 evaluator 输入状态,不把 input gap 当成真实用户确认,也不把本地 `allow` 当云策略放行。 -18. 图片任务恢复层现在会从 `runtime_contract.limecore_policy_snapshot.policy_evaluation` 解析 evaluator 摘要并写入 `ImageRuntimeContractSnapshot`;图片 viewer 复用同一文案规则展示 `LimeCore 策略输入待命中 / 阻断 / 需确认` 胶囊标签,让图片任务也能在用户可见层解释 pending input gap、ask 与 deny。 -19. `thread_read.runtime_summary` 现在并列暴露 `limecorePolicy` 与 `modalityRuntime`:前者解释最近 policy decision input,后者解释同一合同的 profile / adapter / executor binding;这仍只消费已有 runtime contract,不新增 Tauri command、不接 LimeCore 云 run/poll,也不把 input gap 或本地 default decision 伪装成云端策略结论。 - -### Phase 7:上层入口绑定 - -状态:进行中。 - -本阶段输出: - -1. `image_generation.bound_entries` 先登记 `@配图`、`@海报`、`@修图`、`@重绘`、`@分镜` 与显式图片动作。 -2. 前端图片 launch 从 `ModalityRuntimeContract` registry 读取 contract 字段,不再在入口文件重复维护底层 contract 常量。 -3. 守卫要求 entry binding 声明 `entry_source` 且 `launch_metadata_path` 保持在 `harness.*`。 - -### Phase 8:Browser Assist 底层合同注入 - -状态:进行中。 - -本阶段输出: - -1. `browser_control` 先作为底层 Browser Assist 运行合同进入 `harness.browser_assist`,不新增独立 browser task 协议。 -2. `@浏览器 / @Browser Agent / @Mini Tester` 仍保留原始用户消息,只把 `browser_requirement`、launch URL 与 contract snapshot 交给后端 runtime 决策。 -3. `browser_control.bound_entries` 只登记 `@浏览器`、`@Browser Agent`、`@Mini Tester`、`@Web Scheduler`、`@Web Manage` 的 entry metadata;`@` 命令仍只是入口层,不能写 task / artifact / viewer 事实源。 -4. 后端 `BrowserAssistRuntimeHint` 必须解析并保留 `browser_control` 合同快照,browser tool result metadata 需要携带同一组 contract 字段。 -5. Evidence Pack 从 browser tool timeline metadata 导出 `browser_control` 的 `modalityRuntimeContracts`,使浏览器动作也进入 replay 可用的事实源。 -6. Evidence Pack 的 `modalityRuntimeContracts.snapshotIndex.browserActionIndex` 必须汇总 action、session、URL、observation 与 screenshot,使 Browser Assist 不再只能靠 raw snapshots 人工查找。 -7. Replay / grader 必须把 `browser_control` 识别成 Browser Assist 回归样本,检查 browser action trace / browserActionIndex、禁止 WebSearch 替代真实浏览器动作。 - -### Phase 9:PDF Extract 底层合同注入 - -状态:进行中。 - -本阶段输出: - -1. `pdf_extract` 作为文档型底层运行合同进入 `harness.pdf_read_skill_launch.pdf_read_request`,`@读PDF` 仅保留为 entry source。 -2. 前端 `@读PDF` 发送时保留原始消息,并注入 `modality_contract_key=pdf_extract`、`required_capabilities`、`routing_slot=base_model` 与 `runtime_contract` 快照。 -3. 后端 `prepare_pdf_read_skill_launch_request_metadata` 必须补齐并保留同一组合同字段,避免旧客户端或缺省 metadata 退回普通聊天总结。 -4. `Skill(pdf_read)` prompt 必须显式要求真实读取文件、保留合同字段,并禁止 `frontend_direct_pdf_parse` / `generic_chat_summary_only` 偏航。 -5. Evidence Pack 必须能从 `Skill(pdf_read)` timeline metadata 导出 `pdf_extract` 的 `modalityRuntimeContracts`,使 PDF 读取不再只停留在入口 prompt 合同里。 -6. Replay / grader 必须把 `pdf_extract` 识别成 PDF 读取回归样本,检查 `Skill(pdf_read)` / 文件读取 trace,并禁止 WebSearch、ToolSearch、Grep 或普通聊天替代真实读取。 -7. 本阶段暂不把 PDF 单独建成 task artifact 协议;如果后续需要 PDF viewer / artifact UI,再从同一份 `pdf_extract` contract 继续下沉,不能新增平行事实源。 -8. 完成底层闭环后,`@读PDF / @pdf / @read_pdf` 只登记为 `pdf_extract.bound_entries`,前端从 registry 读取 `entry_source`,不再把入口当作运行合同事实源。 - -### Phase 10:Voice Generation 服务型合同注入 - -状态:进行中。 - -本阶段输出: - -1. `voice_generation` 作为音频型底层运行合同进入 `harness.service_scene_launch.service_scene_run`,`@配音` 仅保留为 entry source。 -2. 前端 `@配音 / @voice / @dubbing` 发送时保留原始消息,并注入 `modality_contract_key=voice_generation`、`required_capabilities`、`routing_slot=voice_generation_model` 与 `runtime_contract` 快照。 -3. 后端 `prepare_service_scene_launch_request_metadata` 对 `scene_key=voice_runtime` / `entry_source=at_voice_command` 的旧客户端 metadata 补齐同一组合同字段。 -4. 服务型场景 prompt 必须显式说明当前底层合同,禁止退回 `legacy_tts_test_command` 或伪造“云端已提交”。 -5. Evidence Pack 必须能从 voice runtime / service scene timeline args 或 metadata 导出 `voice_generation` 的 `modalityRuntimeContracts`,使配音合同进入 replay 可评分事实源。 -6. Replay / grader 必须把 `voice_generation` 识别成本地 ServiceSkill/voice runtime 回归样本,检查 `service_scene_launch(scene_key=voice_runtime)` 或后续 audio_task/audio_output 证据,并禁止 `legacy_tts_test_command`、伪造云端提交、普通聊天文本或通用文件卡替代。 -7. 本阶段新增最小 `audio_generate` task artifact 协议,把 `voice_generation` 写入标准 `audio_task/audio_output` 产物;聊天区提供最小音频任务卡与运行时文档 viewer,并允许执行器通过同一 task artifact 回写 `audio_output.completed`。当前 `lime-audio-worker` 已接入 OpenAI-compatible speech provider seam:有 current API Key Provider 凭证时写入 `.lime/runtime/audio/*.mp3` 并回写 `payload.audio_output.completed`;未配置 provider / model / client 时必须显式写回 `audio_provider_*` 错误,聊天任务卡与运行时文档 viewer 都从同一 task artifact 展示完成/失败事实,不回退 legacy TTS,也不伪造音频路径。 - -### Phase 11:Web Research 合同注入 - -状态:进行中。 - -本阶段输出: - -1. `web_research` 作为混合型底层运行合同进入 `harness.research_skill_launch.research_request`、`harness.deep_search_skill_launch.deep_search_request`、`harness.site_search_skill_launch.site_search_request` 与 `harness.report_skill_launch.report_request`。 -2. `@搜索 / @深搜 / @站点搜索 / @研报 / @竞品` 仅保留为 entry source;前端发送时注入 `modality_contract_key=web_research`、`required_capabilities`、`routing_slot=report_generation_model` 与 `runtime_contract` 快照。 -3. 后端 `prepare_*_skill_launch_request_metadata` 需要为旧客户端或缺省 metadata 补齐同一组合同字段,避免回退成模型记忆回答、本地文件搜索或通用 WebSearch 旁路。 -4. research / deep search prompt 必须显式要求首刀 `Skill(research)`,site search prompt 必须说明它是 `web_research` 合同下的站点搜索子入口且首刀 `Skill(site_search)`。 -5. Evidence Pack 必须能从 `Skill(research)` / `Skill(site_search)` / `Skill(report_generate)` timeline args 或 metadata 导出 `web_research` 的 `modalityRuntimeContracts`,使联网研究进入 replay 可评分事实源。 -6. Evidence Pack 的 `modalityRuntimeContracts.snapshotIndex` 必须提供可检索摘要:按 contract key、source、routing outcome、expected routing slot 与 tool trace 汇总,使联网研究不只能靠 raw snapshots 人工查找。 -7. Replay / grader 必须把 `web_research` 识别成联网研究回归样本,检查 `Skill(research)` / `Skill(site_search)` / `Skill(report_generate)`、`search_query` / `lime_site_*` 工具时间线,并禁止模型记忆、本地文件搜索、ToolSearch 或通用 WebSearch 旁路替代真实研究。 -8. 本阶段不新增独立 `report_generation` contract;`@研报 / @竞品` 先作为 `web_research` 下的报告型子入口,后续只有当 report artifact、执行器或 viewer 形成独立事实源时才拆子合同。 - -### Phase 12:Text Transform 合同注入 - -状态:进行中。 - -本阶段输出: - -1. `text_transform` 作为文档型底层运行合同进入 `harness.summary_skill_launch.summary_request`、`harness.translation_skill_launch.translation_request` 与 `harness.analysis_skill_launch.analysis_request`。 -2. `@读文件 / @总结 / @翻译 / @分析 / @发布合规 / @Logo拆解` 仅保留为 entry source;前端发送时注入 `modality_contract_key=text_transform`、`required_capabilities`、`routing_slot=base_model` 与 `runtime_contract` 快照。 -3. 后端 `prepare_*_skill_launch_request_metadata` 需要为旧客户端或缺省 metadata 补齐同一组合同字段,避免回退成前端直出文本、ToolSearch、WebSearch 或普通聊天摘要。 -4. summary / translation / analysis prompt 必须显式要求首刀 `Skill(summary)` / `Skill(translation)` / `Skill(analysis)`,显式文件路径场景可保留 `list_directory` / `read_file` 证据,但不能绕过底层合同。 -5. Evidence Pack 必须能从 `Skill(summary)` / `Skill(translation)` / `Skill(analysis)` timeline args 或 metadata 导出 `text_transform` 的 `modalityRuntimeContracts`,使轻量文本/文档转换也进入 replay 可评分事实源。 -6. Replay / grader 必须把 `text_transform` 识别成文本转换回归样本,检查文本转换 Skill trace 与必要文件读取证据,并禁止 `frontend_direct_text_transform`、ToolSearch、WebSearch 或普通聊天替代。 -7. 本阶段不拆 `summary_generation`、`translation`、`analysis`、`publish_compliance` 或 `logo_decomposition` 平行 contract;只有当独立 artifact、执行器或 viewer 形成稳定事实源时才拆子合同。 - -### Phase 13:Audio Transcription 合同注入 - -状态:进行中。 - -本阶段输出: - -1. `audio_transcription` 作为音频转写底层运行合同进入 `harness.transcription_skill_launch.transcription_task`,`@转写 / @transcribe / @Audio Extractor` 仅保留为 entry source。 -2. 前端 `@转写` 发送时保留原始消息,并注入 `modality_contract_key=audio_transcription`、`required_capabilities`、`routing_slot=audio_transcription_model` 与 `runtime_contract` 快照。 -3. 后端 `prepare_transcription_skill_launch_request_metadata` 需要为旧客户端或缺省 metadata 补齐同一组合同字段,避免回退成前端直连 ASR、普通文件读取或 generic file transcript。 -4. `Skill(transcription_generate)` prompt 必须显式说明当前底层合同,继续压制 ToolSearch / WebSearch / Read / Glob / Grep 首刀偏航。 -5. 标准 `transcription_generate` task file 必须写入同一 `audio_transcription` 合同与 `transcript.pending` 子产物,CLI / Agent tool 回退入口不能另写平行协议。 -6. 媒体任务索引、Evidence Pack 与 Replay / grader 必须能定位 transcript 状态、来源、语言、输出格式与失败码,使 `audio_transcription` 不再只停留在入口 metadata。 -7. 本阶段接入最小 `lime-transcription-worker` 与用户可见恢复层:OpenAI-compatible provider 成功时写入 `.lime/runtime/transcripts/*` 并回写 `transcript.completed`,provider/source/contract 失败时回写 `transcript.failed` 与明确错误码;聊天任务卡和 `.lime/runtime/transcription-generate/*.md` 运行时文档优先消费统一媒体任务索引的 `transcript_*` snapshot,并在完成态读取 `transcript_path` 文本内容供复制校对;当前 viewer 已能从 JSON / SRT / VTT transcript 中解析时间轴与说话人,生成可逐段编辑校对的段落表;保存校对稿时复用 ArtifactDocument 版本链,写入 `transcriptCorrection*` / `transcriptSegmentsCorrected` / `transcriptCorrectionDiffSummary` metadata,不改写原始 ASR 输出,并在 viewer 中展示“校对稿已保存”状态;更多 ASR adapter 与本地离线 ASR 后续继续消费同一 task artifact 与 `transcriptIndex`。 - -## 本轮最小闭环 - -第一轮已完成治理底座;当前纠偏后的最小闭环必须至少贯通一个真实运行时 vertical slice。 - -### 已完成治理底座 - -1. 新增 runtime fact map 文档。 -2. 新增 contract schema 文档。 -3. 新增首批底层 contract registry。 -4. 新增 contract 校验脚本。 -5. 接入 npm 脚本,作为后续 `verify:local` 集成前的显式检查入口。 - -### 当前实现闭环 - -1. 选择 `image_generation` 作为第一条 current vertical slice。 -2. Rust 运行时在 `harness.image_skill_launch` 与内部 `image_task` 上注入 `modality_contract_key=image_generation`、`modality=image`、`required_capabilities`、`routing_slot` 与 `runtime_contract` 快照。 -3. `lime_create_image_generation_task` 工具 schema、别名归一化与 request builder 接受并补齐 contract 字段。 -4. `image_generate` task artifact payload 固化同一组 contract 字段,artifact 成为图片生成 contract 的 truth source。 -5. DevBridge / browser mock 与前端 `CreateImageGenerationTaskArtifactRequest` 类型同步 contract 字段,避免浏览器链路变成假绿。 -6. 图片工作台 viewer 从 task artifact / 工作台状态读取 `runtimeContract`,展示“按合同路由 / 合同阻止 / registry 能力缺口”。 -7. `browser_control` 第九刀从 registry 解析 `browser_reasoning_model` 合同,并写入 `harness.browser_assist`,使 Browser Assist 首刀能看到 `modality_contract_key=browser_control`、`required_capabilities`、`routing_slot` 与 `runtime_contract` 快照。 -8. `browser_control` 第十/十一刀在 Rust 侧解析同一份合同,并把 browser tool timeline metadata 纳入 evidence `modalityRuntimeContracts`,不再只停留在前端 request metadata。 -9. `browser_control` 第十二刀把 evidence 快照继续写入 replay tags / expected checks / grader,要求回放继续走 Browser Assist、产生 browser action trace,并显式禁止 WebSearch 替代。 -10. `pdf_extract` 第十三刀把 `@读PDF` 上层入口接到底层 `Skill(pdf_read)` 运行合同,前端和 Rust 侧都会保留同一份 contract snapshot。 -11. `pdf_extract` 第十四刀把 `Skill(pdf_read)` timeline metadata 纳入 evidence `modalityRuntimeContracts`,并让 replay / grader 继续检查 PDF 读取 trace,形成入口 -> executor -> evidence -> replay 的闭环。 -12. `pdf_extract` 第十五刀把 `@读PDF / @pdf / @read_pdf` 收为 registry entry binding,前端发送只消费 registry 派生的 `entry_source`,入口层不再拥有底层 contract 常量。 -13. `voice_generation` 第十六刀把 `@配音` 服务型入口接到底层 `voice_runtime` 运行合同,前端与 Rust prompt 侧都会保留同一份 contract snapshot。 -14. `voice_generation` 第二十二刀把 voice runtime / service scene timeline args 或 metadata 纳入 evidence `modalityRuntimeContracts`,并让 replay / grader 继续检查 `service_scene_launch(scene_key=voice_runtime)` 或后续 audio_task/audio_output 证据。 -15. `web_research` 第十七刀把 `@搜索 / @深搜 / @站点搜索` 收为 registry entry binding,并把三条 research launch metadata 与 Rust prompt 收敛到同一份 `web_research` contract snapshot。 -16. `web_research` 第十八刀把 `Skill(research)` / `Skill(site_search)` tool timeline args 或 metadata 纳入 evidence `modalityRuntimeContracts`,并让 replay / grader 继续检查联网研究 executor trace,形成入口 -> executor -> evidence -> replay 的闭环。 -17. `web_research` 第十九刀把 evidence `modalityRuntimeContracts` 从 raw snapshots 扩展为 `snapshotIndex`,提供 contract/source/routing/tool trace 汇总,使联网研究合同进入可检索索引层。 -18. `web_research` 第二十刀把 `@研报 / @竞品` 收为报告型子入口:入口仍走 `report_skill_launch -> Skill(report_generate)`,底层合同、evidence、replay 统一归入 `web_research`。 -19. `text_transform` 第二十一刀把 `@读文件 / @总结 / @翻译 / @分析 / @发布合规 / @Logo拆解` 收为文本/文档转换子入口:入口仍分别走 `summary_skill_launch`、`translation_skill_launch`、`analysis_skill_launch`,底层合同、evidence、replay 统一归入 `text_transform`。 -20. `voice_generation` 第二十三刀新增最小 `audio_generate` artifact protocol:`create_audio_generation_task_artifact` / `lime_create_audio_generation_task` 写入标准 `audio_task/audio_output` payload,前端 API、DevBridge mock、task index、evidence pack 与 replay grader 都消费同一份 `voice_generation` 合同快照。 -21. `voice_generation` 第二十四刀把 `audio_generate` tool result 恢复为聊天区任务卡与 `.lime/runtime/audio-generate/*.md` 运行时文档;打开任务卡不再尝试展示隐藏 `.lime/tasks/audio_generate/*.json`,而是进入可读的音频任务 viewer,同时继续把 task JSON 作为 primary source。 -22. `voice_generation` 第二十五刀新增最小 `audio_output` 完成态回写:`complete_audio_generation_task_artifact` 只更新标准 `audio_generate` task file,把 `audio_path / mime_type / duration_ms` 同步写入 payload、`payload.audio_output` 与 `record.result`,并通过同一媒体任务事件刷新前端,不新增云端执行协议。 -23. `voice_generation` 第二十六刀把完成态回流接回聊天任务卡:`useWorkspaceAudioTaskPreviewRuntime` 监听同一媒体任务事件并轮询已追踪的 `audio_generate` task file,从 `payload.audio_output` / `record.result.audio_output` 恢复 `audioUrl / mimeType / durationMs`,让执行器回写后能直接在现有轻卡中出现可播放结果。 -24. `voice_generation` 第二十七刀新增最小音频执行器骨架:`create_audio_generation_task_artifact` 创建标准 `audio_generate` 后会进入同一媒体任务执行链;在真实音频 provider 尚未接通时,worker 明确把 task 写成 `failed`、`last_error.code=audio_worker_unavailable`、`payload.audio_output.status=failed`,不伪造 `audio_path`,也不回流 `legacy_tts_test_command`。 -25. `voice_generation` 第二十八刀把音频执行器从纯骨架推进到 OpenAI-compatible provider seam:worker 通过 current API Key Provider 解析 `provider_id/model/api_key/base_url`,调用 `/audio/speech` 获取真实音频 bytes,保存到 `.lime/runtime/audio/.mp3`,并用同一 task artifact 回写 `payload.audio_output.completed`、`record.result.audio_output` 与 `worker_id=lime-audio-worker`;provider 未配置、resolver 缺失或非 OpenAI-compatible client 时分别写回 `audio_provider_unconfigured` / `audio_provider_resolver_unavailable` / `audio_provider_client_missing`,不回 legacy。 -26. `voice_generation` 第二十九刀把 worker 失败态回流到聊天音频任务卡:`useWorkspaceAudioTaskPreviewRuntime` 从 `payload.audio_output` / `record.last_error` 解析 `audio_provider_*` 错误码、错误原因与 retryable,不保留失败 artifact 里不存在的 `audio_path`;`TaskMessagePreview` 显示 Provider 错误码和原因,让“未配置 provider / resolver 不可用 / adapter 缺失”成为用户可见事实,而不是泛化成普通失败。 -27. `voice_generation` 第三十刀把完成/失败态同步到同一个运行时文档 viewer:音频任务轮询更新 `taskPreview` 的同时,会重建 `.lime/runtime/audio-generate/*.md` 对应的 ArtifactDocument metadata;打开任务卡时看到的是 `audio_output.completed` 的音频路径或 `audio_provider_*` 失败原因,而不是创建任务时的旧“等待执行器”文档。 -28. `voice_generation` 第三十一刀把 `audio_output` 细节接入 evidence / replay:`audio_task.modality_runtime_contract` 快照现在携带 `audioOutput.status/audioPath/providerId/model/workerId/errorCode`,`snapshotIndex.audioOutputIndex` 可检索完成/失败态;replay tags、failure modes、expected 与 grader 会区分 `audio_output.completed` 和 Provider 失败,禁止把已完成音频降级成 Markdown 文本、普通聊天或通用文件卡。 -29. `voice_generation` 第三十二刀把 `audio_output` 细节接入统一媒体任务索引:`list_media_task_artifacts` 的 `modality_runtime_contracts` 现在输出 `audio_output_count`、`audio_output_statuses`、`audio_output_error_codes` 与每个 snapshot 的 `audio_output_*` 字段;前端类型与浏览器 mock 同步,任务列表/恢复逻辑不必重新打开 task JSON 才能知道音频已完成、失败或缺少 Provider。 -30. `voice_generation` 第三十三刀让聊天音频任务恢复优先消费统一媒体任务索引:`useWorkspaceAudioTaskPreviewRuntime` 会先读取 `list_media_task_artifacts(modalityContractKey=voice_generation, taskType=audio_generate)` 的 `audio_output_*` snapshot,把完成态音频路径或 Provider 失败直接同步到任务卡与同一条运行时文档;只有索引缺失该 task 或没有 `audio_output_status` 时才回退读取单个 task artifact。 -31. `browser_control` 第三十八刀把同一份 `browserActionIndex` 接入最小 `browser_replay_viewer`:Harness evidence 面板的“打开复盘”会构造 `browser_assist` Artifact,并由 `BrowserAssistRenderer` 消费 `browserActionIndex` 展示 action/session/URL/observation/screenshot 与最近 `browser_session` / `browser_snapshot` 项;本刀不新增 browser task 协议,viewer 仍消费 Evidence Pack 的同一事实源。 -32. `audio_transcription` 第三十九刀把 `@转写 / @transcribe / @Audio Extractor` 收为 registry entry binding:前端 `transcription_skill_launch.transcription_task` 与 Rust prompt prepare 都会保留 `audio_transcription` 合同快照,`transcript` artifact graph 也反向登记该 current contract;本刀只建立底层合同,不新增真实转写 worker、完整 transcript viewer 或 replay 索引。 -33. `audio_transcription` 第四十刀把 `transcription_generate` task artifact 接到底层合同事实源:Agent tool 与 CLI 回退入口现在写入标准 `.lime/tasks/transcription_generate/*.json`,payload 固化 `audio_transcription` contract、`requested_target=transcript` 与 `transcript.pending`;`list_media_task_artifacts` 输出 transcript 状态/来源/语言/格式,Evidence Pack 输出 `snapshotIndex.transcriptIndex`,Replay / grader 能识别缺失 task trace、缺失 transcript index 与 `transcript.failed`。 -34. `audio_transcription` 第四十一刀接入最小 `lime-transcription-worker`:Agent tool 创建 task 后会启动转写执行链,OpenAI-compatible provider 成功时把响应写入 `.lime/runtime/transcripts/.json|txt|srt|vtt` 并回写 `transcript.completed` / `record.result.transcript`;缺少 AppHandle、provider/model、API Key、source 文件、非 OpenAI-compatible adapter 或 provider 请求失败时回写 `transcript.failed` 与 `transcription_*` 错误码,不回退 frontend ASR、普通文件读取或 generic_file transcript。 -35. `audio_transcription` 第四十二刀把 transcript 恢复层接回聊天区:`lime_create_transcription_task` 工具结果现在生成 `.lime/runtime/transcription-generate/*.md` 运行时文档;`useWorkspaceTranscriptionTaskPreviewRuntime` 监听同一媒体任务事件并优先按 `audio_transcription + transcription_generate` 查询 `list_media_task_artifacts`,从 `transcript_status/path/source/language/output_format/error_code` snapshot 恢复任务卡和 viewer,索引缺失时才回退读取单个 task artifact。 -36. `audio_transcription` 第四十三刀把 transcript 文本接入最小校对 viewer:完成态恢复时读取 `transcript_path` 指向的 `.lime/runtime/transcripts/*` 文本,并把内容嵌入 `.lime/runtime/transcription-generate/*.md` ArtifactDocument 的 `code_block`,打开任务卡即可复制和校对转写文本;失败态仍只展示 `transcription_*` 错误码,不伪造 transcript 内容。 -37. `audio_transcription` 第四十四刀把 transcript viewer 从纯文本推进到时间轴/说话人段落层:恢复层会解析 `.json` verbose transcript、SRT 与 VTT 的 segment / speaker / start-end 时间码,写回 `taskPreview.transcriptSegments`、聊天轻卡时间轴预览和 `.lime/runtime/transcription-generate/*.md` 的“转写时间轴(可逐段编辑校对)”表格;仍不读取隐藏 task JSON 作为主路径,也不新增前端 ASR 或 `generic_file` 旁路。 -38. `audio_transcription` 第四十五刀把 transcript viewer 从只读校对推进到可保存校对稿:`.lime/runtime/transcription-generate/*.md` ArtifactDocument 会标记 `transcriptCorrectionEnabled`、提示保存不改写原始 ASR 输出;用户编辑“转写文本”或“转写时间轴”并保存时,Workbench 复用同一 ArtifactDocument 版本链写入 `transcriptCorrectionStatus=saved`、`transcriptCorrectionEditedBlockId`、`transcriptCorrectionSourceTranscriptPath`、`transcriptCorrectionTextLength`、`transcriptCorrectionSegmentCount`、`transcriptCorrectionSpeakerCount` 与 `transcriptSegmentsCorrected`,不新增 Tauri command、frontend ASR 或并行 patch 协议。 -39. `audio_transcription` 第四十六刀把已保存校对稿显性化:保存后会插入/更新 `transcript-correction-status` callout,显示原始 ASR 输出保持不可变、原文/校对稿文本长度差异、段落差异和说话人数差异;同时写入 `transcriptCorrectionDiffSummary`,让后续专用 transcript viewer、diff 面板或导出器不必重新扫描 block 才能识别校对变更。 -40. `Phase 3 / Phase 5` 第四十七刀新增最小 `ModalityExecutionProfile` 与 `ExecutorAdapter` 事实源:`modalityExecutionProfiles.json` 覆盖 7 个 current contracts 与 7 个 executor adapters,`governance:modality-contracts` 会校验 profile 覆盖、adapter 绑定、支持位、产物、权限、LimeCore policy 与 failure mapping;本刀只建立 current 治理事实源,不新增命令、bridge、mock 或运行时执行分支。 -41. `Phase 3 / Phase 5` 第四十八刀把 profile / adapter 事实源接入前端 runtime contract resolver:`resolveModalityRuntimeContractBinding()` 现在会从 `modalityExecutionProfiles.json` 解析 `execution_profile` 与 `executor_adapter` 快照,并随 `runtime_contract` 进入所有 current launch metadata;本刀仍不新增 Tauri command、bridge、mock 或 Rust executor 分支,为下一步 Rust runtime preflight / evidence 可视化提供统一输入。 -42. `Phase 3 / Phase 5` 第四十九刀把 profile / adapter 快照接入 Evidence Pack:`runtime_evidence_pack_service` 会从 `runtime_contract.execution_profile.profile_key` 与 `runtime_contract.executor_adapter.adapter_key` 提取 `executionProfileKey` / `executorAdapterKey`,并写入 `modalityRuntimeContracts.snapshots[]`、`snapshotIndex.executionProfileKeys`、`snapshotIndex.executorAdapterKeys` 与 `toolTraceIndex.items[]`;本刀仍不改变真实 executor 行为,只让 evidence/replay 主链能看见 Phase 3/5 决策输入。 -43. `Phase 3 / Phase 5` 第五十刀把 profile / adapter 快照接入统一媒体任务索引:Rust `runtime_contract` snapshot 现在写入 `execution_profile.profile_key` 与 `executor_adapter.adapter_key`,`list_media_task_artifacts` 的 `modality_runtime_contracts` 输出 `execution_profile_keys`、`executor_adapter_keys`,并在每条 task snapshot 上暴露 `execution_profile_key` / `executor_adapter_key`;前端类型和浏览器 fallback mock 同步,图片、配音、转写任务列表不必重新打开 task JSON 才能查询 profile / adapter。 -44. `Phase 3 / Phase 5` 第五十一刀把 adapter registry 接入媒体 worker 执行前检查:图片、配音、转写 worker 在进入真实执行器前会校验同一份 `runtime_contract.execution_profile.profile_key`、`executor_adapter.adapter_key` 与 `executor_binding.executor_kind/binding_key`,不匹配时以 `*_execution_profile_*`、`*_executor_adapter_*`、`*_executor_binding_*` 阻断;`list_media_task_artifacts` 每条 snapshot 同步暴露 `executor_kind` / `executor_binding_key`,Evidence Pack 会把 runtime preflight 阻断识别为 `runtime_preflight` / `blocked`,避免 adapter 错配继续落成普通 provider 失败。 -45. `Phase 6` 第五十二刀把最小 LimeCore policy refs/snapshot 种进同一底层主链:central Rust contract helper、前端 runtime contract resolver 与浏览器 fallback mock 都会写入 `limecore_policy_refs` 和 `limecore_policy_snapshot(status=refs_declared, decision=not_evaluated)`;Evidence Pack 新增 `snapshotIndex.limecorePolicyIndex`,统一媒体任务索引新增 `limecore_policy_refs`、`limecore_policy_snapshot_count/statuses` 与每条 snapshot 的 policy refs/status/decision。该刀只让后续 allow / ask / deny 有审计字段,不新增命令、不实现 LimeCore 云 run/poll,也不把上层 `@` 入口提前接成云执行协议。 -46. `Phase 6` 第五十三刀把 policy snapshot 从纯 refs seed 推进到本地默认决策摘要:central Rust contract helper、前端 runtime contract resolver 与浏览器 fallback mock 现在写入 `status=local_defaults_evaluated`、`decision=allow`、`decision_source=local_default_policy`、`decision_scope=local_defaults_only`、`decision_reason=declared_policy_refs_with_no_local_deny_rule` 与 `unresolved_refs`;Evidence Pack 和统一媒体任务索引同步暴露 decision source / unresolved refs。该 `allow` 仅表示本地默认策略没有阻断 current 路由,不代表真实 LimeCore tenant policy、provider offer 或 gateway policy 已放行。 -47. `Phase 6` 第五十四刀把 policy decision 摘要补成可审计输入清单:`limecore_policy_snapshot.policy_inputs[]` 为每个 policy ref 标记 `declared_only / modality_runtime_contract / limecore_pending`,`missing_inputs[]` 明确哪些控制面输入还未由真实 LimeCore 命中;Evidence Pack 的 `limecorePolicyIndex` 与统一媒体任务索引同步暴露 `missingInputs` / `limecore_policy_missing_inputs`。该刀仍不接云 run/poll,也不把本地默认 `allow` 伪装成 tenant/provider/gateway 放行。 -48. `Phase 6` 第五十五刀把 policy gap 推进到 Harness evidence 可见面:`HarnessStatusPanel` 读取 `observabilitySummary.modalityRuntimeContracts.snapshotIndex.limecorePolicyIndex`,展示 `LimeCore 策略缺口` 卡片、控制面 refs、missing inputs、local default decision、profile / adapter 和 `declared_only / limecore_pending` 输入状态;该刀仍不新增命令、不接 LimeCore 云执行,也不把上层 `@` 入口当作策略事实源。 -49. `Phase 6` 第五十六刀把 policy gap 推进到 replay/grader 回归面:`runtime_replay_case_service` 现在会从 `limecorePolicyIndex` 派生 `limecore-policy` / `limecore-policy-gap` / `limecore-local-default-policy` suite tags 与 `limecore_policy_missing_inputs` / `limecore_policy_local_defaults_only` failure modes,并把 policy refs、missing inputs、decision source 写入 expected / grader 检查;该刀只增强复盘验收,不新增命令、不接云 run/poll。 -50. `Phase 6` 第五十七刀补真实 policy hit value 的空接线结构:`limecore_policy_snapshot`、Evidence Pack `limecorePolicyIndex`、统一媒体任务索引、前端 normalizer/types 与浏览器 fallback mock 都携带 `pending_hit_refs`、`policy_value_hits`、`policy_value_hit_count=0`;这为后续真实 `model_catalog / provider_offer / tenant_feature_flags / gateway_policy` 命中值提供稳定落点,但当前仍不写假值、不接 LimeCore 云调用。 -51. `Phase 6` 第五十八刀补最小 policy hit resolver seam:central Rust contract helper 与前端 runtime contract resolver 现在能消费传入的 `policy_value_hits(status=resolved)`,自动派生 `evaluated_refs`、收缩 `missing_inputs / pending_hit_refs`,Evidence Pack、统一媒体任务索引与浏览器 fallback mock 也会在 snapshot 只携带命中值时按同一规则派生待命中 refs;本刀仍不接云 run/poll、不改本地默认 `decision=allow/local_defaults_only`,避免把“输入命中”伪装成真实策略放行。 -52. `Phase 6` 第五十九刀接最小本地 `model_catalog` hit producer:图片任务执行前已有的 `model_registry` 能力评估现在会写入 `runtime_contract.limecore_policy_snapshot.policy_value_hits[]`,并把 `model_catalog` 从 `missing_inputs / pending_hit_refs` 移入 `evaluated_refs`;该刀仍不接 `provider_offer / tenant_feature_flags`,也不把目录命中升级成真实策略放行。 -53. `Phase 6` 第六十刀接最小本地 `provider_offer` hit producer:图片任务进入真实执行器前会先用已解析的 `ImageGenerationRunnerConfig`、非空 API key 与 task payload 的 `provider_id/model` 写入 `policy_value_hits(status=resolved, value_source=local_provider_offer)`,并把 `provider_offer` 从 `missing_inputs / pending_hit_refs` 移入 `evaluated_refs`;该 hit 只保留 endpoint origin/path、adapter 与 credential 状态,不序列化 API key,也不把本地默认 `allow` 升级成真实策略放行。 -54. `Phase 6` 第六十一刀接请求侧 `gateway_policy` hit producer:Browser Assist 与 Web Research 类 launch 会复用 `harness.oem_routing` / Rust `oem_policy` 已有事实源,把 tenant/provider/quota/can_invoke/fallback 输入写入 `policy_value_hits(status=resolved, value_source=request_oem_routing)`,并把 `gateway_policy` 从 `missing_inputs / pending_hit_refs` 移入 `evaluated_refs`;该 hit 不包含 token、不新增 Tauri command、不接 LimeCore 云 run/poll,也不把本地默认 `allow` 升级成真实网关策略放行。 -55. `Phase 6` 第六十二刀接请求侧 `tenant_feature_flags` hit producer:Workspace send metadata 会把 OEM Cloud bootstrap snapshot 的 feature flags 以 `harness.tenant_feature_flags` 透传给 Rust runtime;central contract helper 会把该输入写入 `policy_value_hits(status=resolved, value_source=oem_cloud_bootstrap_features)`,并把 `tenant_feature_flags` 从 `missing_inputs / pending_hit_refs` 移入 `evaluated_refs`。该 hit 只记录 boolean feature flags 与 tenant id,不包含 session token,不新增 Tauri command,不接云 run/poll,也不把功能开关命中解释成真实策略放行。 -56. `Phase 6` 第六十三刀补最小 allow / ask / deny evaluator seam:central Rust contract helper 与前端 runtime contract resolver 现在都会写入 `policy_evaluation`;当所有 refs 都有 `resolved` hit 且没有阻断信号时,snapshot 进入 `status=policy_inputs_evaluated`、`decision_source=policy_input_evaluator`、`decision_scope=resolved_policy_inputs`,并按 gateway can_invoke / offer_state / quota_low、tenant gatewayEnabled、model_catalog capability 与 provider credential state 推导 `allow / ask / deny`。该 evaluator 只消费已命中的 policy inputs,不接云 run/poll;仍有 missing inputs 时顶层 `decision` 保持本地默认解释。 -57. `Phase 6` 第六十四刀把 policy decision explanation 接入 thread read:`AgentRuntimeThreadReadModel` 会扫描最近的 ToolCall metadata / FileArtifact content 中的 runtime contract,把 LimeCore policy snapshot 投影到 `runtime_summary.limecorePolicy`,包含顶层 decision、decision_source/scope/reason、refs、missing/pending refs、hit count 与 evaluator blocking/ask/pending refs。该刀只让现有 thread read 能解释最近一次 policy 决策,不新增 Tauri command、不接云 run/poll,也不把 thread read 变成云审计事实源。 -58. `Phase 6` 第六十五刀把 policy evaluator explanation 接入统一媒体任务索引:`list_media_task_artifacts.modality_runtime_contracts` 现在汇总 evaluation status / decision / decision source 与 blocking / ask / pending refs,每条 snapshot 也输出对应字段;Rust index、前端类型、浏览器 fallback mock 与 `mediaTasks` 回归同步。该刀只让任务索引能展示 evaluator 解释,不新增 Tauri command、不接 LimeCore 云 run/poll,也不改变顶层 local default decision 语义。 -59. `Phase 6` 第六十六刀把 policy evaluator explanation 接入配音/转写任务卡恢复层:新增共享 meta helper,`useWorkspaceAudioTaskPreviewRuntime` 与 `useWorkspaceTranscriptionTaskPreviewRuntime` 从统一媒体任务索引 snapshot 生成 `LimeCore 策略输入待命中 / 阻断 / 需确认` 轻卡标签,并补 audio input gap 与 transcription deny 回归。该刀只消费现有索引,不新增命令、不碰上层 `@`,也不把 pending input gap 解释成真实用户确认。 -60. `Phase 6` 第六十七刀把 policy evaluator explanation 接入图片任务 viewer:`useWorkspaceImageTaskPreviewRuntime` 从图片 task artifact 的 `runtime_contract.limecore_policy_snapshot.policy_evaluation` 解析 snapshot / missing / pending / blocking / ask refs,`ImageTaskViewer` 复用共享 helper 展示 `LimeCore 策略输入待命中: N` 等轻量标签,并补图片恢复与 viewer 回归。该刀只消费已有 runtime contract,不新增命令、不接 LimeCore 云 run/poll,也不把图片上层 `@` 入口改成策略事实源。 -61. `Phase 6` 第六十八刀把 policy evaluator explanation 接入图片消息轻卡:`ImageWorkbenchMessagePreview` 复用共享 helper,从 `preview.runtimeContract` 解析同一份 evaluator 摘要,并在聊天区图片预览顶部展示 `LimeCore 策略输入待命中 / 阻断 / 需确认` 胶囊标签;该刀只让图片消息卡消费已有 runtime contract,不新增命令、不接 LimeCore 云 run/poll,也不改图片消息的布局骨架。 -62. `Phase 5/6` 第七十一刀把 profile / adapter 摘要接入 thread read:`AgentRuntimeThreadReadModel` 现在会扫描最近 ToolCall metadata / FileArtifact content 中的 runtime contract,并把 `contractKey`、`routingSlot`、`requiredCapabilities`、`profileKey`、`executorAdapterKey`、`executorKind`、`executorBindingKey` 写入 `runtime_summary.modalityRuntime`。该刀只投影已有底层合同,不新增命令、不接云 run/poll,也不把上层 `@` 命令当执行合同事实源。 -63. `Phase 5/6` 第七十二刀把 profile / adapter / binding 摘要合入 `SessionExecutionRuntimeTaskProfile`:`build_runtime_task_profile()` 现在会从 request metadata 中已有的 `runtime_contract / modality_runtime_contract` 提取 `modalityContractKey`、`routingSlot`、`executionProfileKey`、`executorAdapterKey`、`executorKind`、`executorBindingKey`,并按 `modalityExecutionProfiles.json` 补齐 `permissionProfileKeys` 与 `userLockPolicy`;`lime_runtime.task_profile` 和 `task_profile_resolved` 事件会承载同一摘要,前端 API 类型与协议测试同步。该刀仍不新增 Tauri command、不接 LimeCore 云 run/poll、不把上层 `@` 命令当事实源;权限判定执行、用户显式模型锁定 enforcement 与真实 `gateway:*` adapter preflight 继续后置。 -64. `Phase 5/6` 第七十三刀把 `routingSlot` 推进到最小模型能力 enforcement:`request_model_resolution` 现在会把 `routingSlot` 映射成 runtime model capability requirements,并用它过滤候选池、fallback 候选与多候选自动重选;`browser_reasoning_model` 会要求 reasoning,`image_generation_model` 会允许专用图片模型进入候选池,显式用户模型锁定仍 honored,但 `capability_gap` 会输出对应 `*_candidate_missing`。第 113 刀已把显式用户锁定导致的 capability gap 从“只解释”推进为 `user_locked_capability_gap` 执行前阻断;该刀本身不新增 Tauri command、不接 LimeCore 云 run/poll、不触碰上层 `@` 命令。 -65. `Phase 5/6` 第七十四刀把 `permissionProfileKeys` 推进到最小 runtime permission summary:`request_model_resolution` 现在会生成 `SessionExecutionRuntimePermissionState`,随 `lime_runtime.permission_state` 写入 turn metadata;runtime view、thread read fallback summary、前端 execution runtime 类型与内部辅助任务 metadata 都能识别该摘要。`ask_user_question` 不视为风险权限,`blockingProfileKeys` 本刀保持为空,因此这一步只解释权限声明和需确认 profile,不执行真实授权或阻断。 -66. `Phase 5/6` 第七十五刀把 `permission_state` 推到 thread read 结构化读取面:`AgentRuntimeThreadReadModel` 现在直接暴露 `permission_state`,前端 `AgentRuntimeThreadReadModel` 类型同步引用 `AsterSessionExecutionRuntimePermissionState`。这一步让上层读取完整 `requiredProfileKeys / askProfileKeys / blockingProfileKeys / notes`,不再只能从 `runtime_summary` 数字摘要或隐藏 turn metadata 推断;仍不新增事件、不阻断执行、不接真实权限授权。 - -暂不做: - -1. 暂不把所有 `@`、按钮、Scene 批量登记到 `bound_entries`;已进入主链的 `image_generation`、`browser_control`、`pdf_extract`、`voice_generation`、`web_research`、`text_transform`、`audio_transcription` 继续按合同逐条收口,未进入 current 事实源的入口不批量扩张。 -2. 暂不把 LimeCore 写成默认执行器;LimeCore 仍只作为 catalog / policy / offer / audit 控制面。 -3. 暂不批量改造视频、PDF、搜索、研报等其他 viewer;已补到最小 viewer / index 的 browser 与 voice 继续沿同一事实源演进,未形成稳定 artifact graph 的能力先不另开 viewer 协议。 -4. 暂不新增 PDF task artifact / reader viewer;PDF 本轮只收 executor trace、evidence 和 replay,避免在底层事实源未完全稳定前再开一套产物协议。 -5. 暂不新增完整音频工作台,也暂不把 Gemini / Azure 专有语音 API、LimeCore 云 run/poll 或语音后处理工作流并入主链;voice 目前只提供最小 `audio_generate` 任务卡、运行时文档 viewer、OpenAI-compatible speech provider seam 与完成/失败态回流。未配置可用 provider 时仍必须显式失败,不伪造云端提交,也不把普通聊天文本或通用文件卡当作音频产物。 -6. 暂不新增独立 `report_generation` 合同;`@研报 / @竞品` 继续走 `report_skill_launch -> Skill(report_generate)` 主链,但其底层能力归属先收敛到 `web_research`,避免把 report artifact 协议提前扩张成第二套事实源。 -7. 暂不新增独立 `summary_generation`、`translation`、`analysis`、`publish_compliance` 或 `logo_decomposition` 合同;这组轻量文本/文档转换入口先统一收敛到 `text_transform`,避免把上层 `@` 命令提前扩张成平行底层事实源。 -8. 暂不新增非 OpenAI-compatible ASR adapter 或本地离线 ASR 执行器;`audio_transcription` 当前交付标准 `transcription_generate` task writer、`lime-transcription-worker`、`transcript.completed/failed` 回写、统一媒体任务索引、聊天任务卡、可编辑校对运行时文档 viewer、JSON/SRT/VTT 时间轴与说话人段落展示、ArtifactDocument 版本化校对稿保存、校对稿状态/差异摘要、Evidence `transcriptIndex` 与 Replay 检查。 -9. 暂不在本刀实现完整权限判定系统、同 turn 自动恢复、LimeCore 云端 allow / ask / deny evaluator、真实 `gateway:*` adapter preflight 或完整 GUI/evidence 可视化;当前已让图片、配音、转写媒体 worker 消费 Phase 3 / Phase 5 的 profile / adapter 事实源做最小执行前检查,并把 Browser Assist preflight、通用 Skill metadata/preflight、`lime_run_service_skill` voice compat guard、Phase 6 的 LimeCore policy refs/snapshot、model/offer/gateway/tenant hit producers、最小本地 policy input evaluator、thread read 摘要、`SessionExecutionRuntimeTaskProfile` profile/adapter/binding merge、`routingSlot` 模型能力 enforcement、`permissionProfileKeys` 最小 runtime permission summary、thread read 结构化 `permission_state`、统一媒体任务索引 explanation、配音/转写任务卡 meta、图片 viewer policy 标签与图片消息轻卡标签接进 current 主链。显式用户模型锁定已能输出 capability gap,且 `explicit_model_lock` gap 会以 `user_locked_capability_gap` 在模型执行前阻断;权限 profile 已能输出需确认摘要,Evidence / Replay 已把 `not_requested / requested` 未解决确认作为交付阻断事实;未 resolved 的 `requires_confirmation` 也已在 prelude 后、模型执行前阻断 turn;最小 `runtime_permission_confirmation:*` / `RequestUserInput` 权限确认、`agent_runtime_respond_action` 写回和下一轮 `resolved/denied` metadata merge 已接入;`runtime_user_lock_capability:*` 的本地最小确认式恢复也已接入,同 `turn_id` 恢复时可释放本轮显式 provider/model 偏好并重新走模型解析。后续继续把同一决策扩展到完整权限授权、用户锁定 gap 的完整 GUI 自动恢复、云端策略 evaluator、真实 Gateway adapter、更多任务卡与更多 GUI 可视化。 - -## 分类 - -### current - -- `ModalityRuntimeContract` -- `runtime fact map` -- `domain artifact graph` -- `execution profile` -- `capability matrix` -- `evidence pack` -- `LimeCore catalog / policy` 作为云控制面 - -### compat - -- 旧 `@` 命令 metadata,只能绑定到底层 contract -- 旧 `generic_file` 展示,只能作为兜底 artifact kind -- 旧本地 CLI adapter,只能作为 typed `local_cli` executor -- 旧 `lime_run_service_skill` 只能作为服务型场景 compat guard;`voice_generation` 必须携带并校验 `service_skill:voice_runtime` 合同,不允许恢复云 run/poll。 - -### deprecated - -- 入口直接创建多模态 task -- viewer 自己猜 artifact 类型 -- skill 内部自由选择 Bash / WebSearch / ToolSearch 作为首刀 - -### dead - -- 把 LimeCore 当成所有多模态入口的默认执行器 -- 用 `@` 命令名作为底层 contract 主键 -- 用通用文件卡承载所有多模态结果 - -## 进度日志 - -- 2026-04-29:创建本计划;固定本轮从 Phase 0/1 开始,先做底层 fact map、contract schema 和轻量守卫,不改上层 `@` 命令。 -- 2026-04-29:已新增 `runtime-fact-map.md`、`contract-schema.md`、`modalityRuntimeContracts.json` 与 `check-modality-runtime-contracts.mjs`;首批 5 个 current contract 为 `image_generation`、`browser_control`、`pdf_extract`、`voice_generation`、`web_research`,`bound_entries` 暂为空,等待 Phase 7 再接上层入口。 -- 2026-04-29:已接入 `npm run governance:modality-contracts` 并通过;同时通过 `npm run harness:doc-freshness`、脚本语法检查和本轮触达 Markdown 链接 / code fence 检查。 -- 2026-04-29:继续推进 Phase 2,新增 `capability-matrix.md` 与 `modalityCapabilityMatrix.json`;首批登记 13 个 capability 与 9 个 model role,并扩展 contract 守卫校验 `required_capabilities` / `routing_slot` 引用关系。 -- 2026-04-29:已把 `npm run governance:modality-contracts` 接入 `npm run test:contracts`;`test:contracts`、`harness:doc-freshness`、脚本语法检查与本轮触达 Markdown 链接 / code fence 检查通过。 -- 2026-04-29:开始真实运行时实现,完成 `image_generation` vertical slice 第一刀:`prepare_image_skill_launch_request_metadata` 注入底层 contract,`lime_create_image_generation_task` request builder / schema 补齐 contract 字段,`create_image_generation_task_artifact_inner` 将 `modality_contract_key`、`required_capabilities`、`routing_slot`、`runtime_contract` 写入 `image_generate` artifact payload,并补 Rust / TS 定向断言。 -- 2026-04-29:验证通过 `npm run test:contracts`、`npm test -- src/components/agent/chat/workspace/useWorkspaceImageWorkbenchActionRuntime.test.tsx src/lib/tauri-mock/core.test.ts`、`npm run typecheck`,并通过 `CARGO_TARGET_DIR=src-tauri/target/codex-modality-contract cargo test --manifest-path src-tauri/Cargo.toml test_prepare_image_skill_launch_request_metadata_materializes_input_refs`;继续补跑图片 artifact / tool request Rust 定向测试时,当前工作区已有 `src-tauri/crates/agent/src/session_store.rs` 编译错误阻断,错误点不属于本轮 `image_generation` contract 改动。 -- 2026-04-29:继续 `image_generation` vertical slice 第二刀:在图片任务 worker 进入 `lime_media_runtime::execute_image_generation_task_with_hook` 前读取 task artifact 的 contract / required capabilities / routing slot,并对明显文本模型候选(例如 `gpt-5.2`)输出 `image_generation_model_capability_gap`,阻止 contract 要求的图片生成任务误路由到普通文本模型。 -- 2026-04-29:第二刀验证通过 `npm run test:contracts` 与 `npm run typecheck`;Rust 定向测试 `CARGO_TARGET_DIR=src-tauri/target/codex-modality-contract cargo test --manifest-path src-tauri/Cargo.toml validate_image_generation_task_execution_contract_should_reject_text_model_candidate` 被当前工作区已有 `src-tauri/src/commands/aster_agent_cmd/command_api/runtime_api.rs` 缺少 `AgentRuntimeSessionHistoryCursor` import 的编译错误阻断,未继续扩大范围修 unrelated 编译债。 -- 2026-04-29:已用最小 import 修复 `runtime_api.rs` 的 `AgentRuntimeSessionHistoryCursor` 编译阻塞,并补通 `image_generation` preflight 的 Rust 定向验证:明显文本模型会被 `image_generation_model_capability_gap` 阻止,`gpt-image-1` 类图片模型候选可通过。 -- 2026-04-29:继续 `image_generation` vertical slice 第三刀:`runtime_evidence_pack_service` 现在会从 `.lime/tasks/image_generate/*.json` 提取 `ModalityRuntimeContract` 与 routing 决策快照,写入 `runtime.json` / `artifacts.json` 的 `modalityRuntimeContracts`,并把 `modalityRuntimeContract` 纳入 `observabilitySummary.signalCoverage`;当 preflight 失败时,evidence 中可直接看到 `routingEvent=routing_not_possible`、`routingOutcome=blocked`、`failureCode=image_generation_model_capability_gap`。 -- 2026-04-29:第三刀验证通过 `CARGO_TARGET_DIR=src-tauri/target/codex-modality-contract cargo test --manifest-path src-tauri/Cargo.toml should_export_modality_runtime_contract_snapshot_from_failed_image_task`、`validate_image_generation_task_execution_contract_should_accept_image_model_candidate`、`should_export_auxiliary_runtime_snapshots_from_image_task_artifact`、`npm run test:contracts`、`npm run typecheck` 与 `git diff --check`。 -- 2026-04-29:继续 `image_generation` vertical slice 第四刀:`runtime_replay_case_service` 现在从 evidence `runtime.json` 读取 `modalityRuntimeContracts`,写入 replay `input.json` / `expected.json` / `grader.md` / `evidence-links.json`;同时把 `modality-runtime-contract`、`modality-image_generation`、`routing-not-possible` 纳入 suite tags,把 `modality_contract_routing_blocked` 与 `image_generation_model_capability_gap` 纳入 failure modes,并在 grader 中增加“多模态运行合同检查”,使模型误路由样本可被回归评分而不是只停留在 evidence 里。 -- 2026-04-29:第四刀验证通过 `CARGO_TARGET_DIR=src-tauri/target/codex-modality-contract cargo test --manifest-path src-tauri/Cargo.toml should_carry_modality_runtime_contract_into_replay_case`、`should_export_runtime_replay_case_to_workspace`、`npm run test:contracts` 与 `git diff --check`。 -- 2026-04-29:继续 `image_generation` vertical slice 第五刀:图片任务 worker 的模型能力 preflight 从纯字符串启发式推进到 `ModelRegistryState` / `EnhancedModelMetadata`,优先按 `task_families` 与 `output_modalities` 判断 `ImageGeneration` / `ImageEdit` / `Image` 输出能力;只有 registry 找不到模型时才回退到文本模型启发式,避免 `gpt-5.2` 这类普通文本模型误进图片执行器,同时允许 registry 明确声明的图片模型通过。 -- 2026-04-29:第五刀进一步把 registry 判定结果持久化为 `image_generate` task payload 的 `model_capability_assessment`,并同步进入 evidence `modalityRuntimeContracts.snapshots[].modelCapabilityAssessment` 与 replay 的 `modalityContractChecks`,让后续回归能区分 `model_registry` 判定和 heuristic fallback,而不是只看到最终失败码。 -- 2026-04-29:第五刀验证通过 `CARGO_TARGET_DIR=src-tauri/target/codex-modality-contract cargo test --manifest-path src-tauri/Cargo.toml assess_image_generation_model_capability_should_use_output_modality`、`assess_image_generation_model_capability_should_reject_registered_text_model`、`assess_image_generation_model_capability_should_match_provider_model_id`、`validate_image_generation_task_execution_contract_should_reject_registry_text_model`、`validate_image_generation_task_execution_contract_should_trust_registry_image_model`、`patch_image_task_model_capability_assessment_should_persist_registry_snapshot`、`should_export_modality_runtime_contract_snapshot_from_failed_image_task`、`should_carry_modality_runtime_contract_into_replay_case`、`npm run test:contracts` 与本轮触达文件 `git diff --check`。 -- 2026-04-29:继续 `image_generation` vertical slice 第六刀:`list_media_task_artifacts` 现在可以按 `modalityContractKey` 与 `routingOutcome` 筛选图片任务,并在返回结果中附带 `modality_runtime_contracts` 索引摘要;索引包含 contract keys、routing outcome 计数、blocked 计数、registry assessment 计数与每个 task 的 routing snapshot,使 task index 成为多模态运行合同的可检索事实源,而不是只能靠单个 task file 或 evidence pack 反查。 -- 2026-04-29:第六刀同步前端 `ListMediaTaskArtifactsRequest` / `ListMediaTaskArtifactsOutput` 类型与浏览器 fallback mock;图片任务恢复测试继续使用统一媒体任务接口,mock 也返回相同 `modality_runtime_contracts` 结构,避免浏览器链路假绿。 -- 2026-04-29:第六刀验证通过 `CARGO_TARGET_DIR=src-tauri/target/codex-modality-contract cargo test --manifest-path src-tauri/Cargo.toml list_media_task_artifacts_inner_should_index_modality_contract_routing_blocks`、`media_task_artifact_controls_should_share_same_task_file_protocol`、`npm test -- src/lib/api/mediaTasks.test.ts src/lib/tauri-mock/core.test.ts src/components/agent/chat/workspace/useWorkspaceImageTaskPreviewRuntime.test.tsx`、`npm run typecheck`、`npm run test:contracts` 与本轮触达文件 `git diff --check`。 -- 2026-04-29:继续 `image_generation` vertical slice 第七刀:前端图片任务恢复 runtime 现在会从 task artifact payload / `last_error` 解析 `runtimeContract` 快照,写入 `ImageWorkbenchTask` 与 `MessageImageWorkbenchPreview`;图片工作台 viewer 增加轻量胶囊标签,区分“运行合同 · 已按 image_generation 路由”“运行合同阻止 · image_generation_model_capability_gap”以及“模型能力来自 model_registry · 不支持图片生成”,让第六刀 task index 的路由事实进入用户可见 viewer。 -- 2026-04-29:第七刀验证通过 `npm test -- src/components/agent/chat/components/ImageTaskViewer.test.tsx src/components/agent/chat/workspace/useWorkspaceImageTaskPreviewRuntime.test.tsx`、`npm run typecheck`、`npm run test:contracts`、`npm run verify:gui-smoke` 与本轮触达文件 `git diff --check`。 -- 2026-04-29:继续 `image_generation` vertical slice 第八刀:`image_generation.bound_entries` 现在登记 `@配图 / @image / /image / @Vision 1`、`@海报 / @Flyer 3`、`@修图`、`@重绘`、`@分镜`、文稿正文配图和图片工作台续做入口;entry binding 只声明 `entry_source`、`launch_metadata_path` 和 input mapping,不拥有 task / artifact / viewer / evidence 事实源。 -- 2026-04-29:第八刀新增 `src/lib/governance/modalityRuntimeContracts.ts`,前端 `imageSkillLaunch.ts` 改为从 registry 读取 `contractKey / modality / requiredCapabilities / routingSlot / runtimeContract`,避免上层入口继续硬编码底层 contract;守卫同步要求 entry binding 声明 `entry_source` 且 launch metadata 留在 `harness.*`。 -- 2026-04-29:第八刀验证通过 `npm run governance:modality-contracts`、`npm test -- src/lib/governance/modalityRuntimeContracts.test.ts`、`npm test -- src/components/agent/chat/workspace/useWorkspaceImageWorkbenchActionRuntime.test.tsx src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx`、`npm run typecheck`、`npm run test:contracts`、`npm run verify:gui-smoke` 与本轮触达文件 `git diff --check`。 -- 2026-04-29:继续第九刀 `browser_control`:泛化 `ModalityRuntimeContract` registry resolver,新增 Browser Assist launch metadata helper;`@浏览器 / @Browser Agent / @Mini Tester` 发送时保留原始消息并关闭 WebSearch,同时把 `browser_control` 合同快照注入 `harness.browser_assist`,`buildHarnessRequestMetadata` 负责保留这些底层合同字段并补齐 profile / backend / auto launch。 -- 2026-04-29:第九刀验证通过 `npm test -- src/lib/governance/modalityRuntimeContracts.test.ts src/components/agent/chat/utils/harnessRequestMetadata.test.ts src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx`、`npm run governance:modality-contracts`、`npm run typecheck`、`npm run test:contracts`、`npm run verify:gui-smoke` 与本轮触达文件 whitespace / `git diff --check`。 -- 2026-04-29:继续第十刀 `browser_control` 后端消费:新增 Rust 侧 `BROWSER_CONTROL_*` contract 常量与 `browser_control_runtime_contract()`,`BrowserAssistRuntimeHint` 现在会从 `harness.browser_assist` 解析 `modality_contract_key=browser_control`、`required_capabilities`、`routing_slot`、`runtime_contract` 与 `entry_source`;`LimeBrowserMcpTool` 成功或失败结果都会把这组字段写入 tool result metadata,让 Browser Assist 动作进入 runtime timeline 事实源。 -- 2026-04-29:继续第十一刀 `browser_control` evidence:`runtime_evidence_pack_service` 现在会从 browser tool call metadata 导出 `modalityRuntimeContracts` snapshot,`source=browser_action_trace.modality_runtime_contract`、`routingEvent=browser_action_requested`、`routingOutcome=accepted`,使 Browser Assist 不再只能依赖图片 task artifact 的合同导出路径。 -- 2026-04-29:第十/十一刀验证通过 `CARGO_TARGET_DIR=src-tauri/target/codex-modality-contract cargo test --manifest-path src-tauri/Cargo.toml test_extract_browser_assist_runtime_hint_from_harness_metadata`、`test_lime_browser_tool_attaches_modality_contract_metadata`、`should_export_browser_control_contract_snapshot_from_tool_metadata`、`npm run test:contracts`、`npm run verify:gui-smoke` 与本轮触达文件 `git diff --check`。 -- 2026-04-29:继续第十二刀 `browser_control` replay/grader:`runtime_replay_case_service` 现在会把 `browser_control` 合同识别为 Browser Assist 回归样本,补 `browser-control`、`browser-assist`、`browser-action-trace` suite tags;`expected.json` / `grader.md` 会要求继续使用 `mcp__lime-browser__*`,禁止 WebSearch / 普通聊天替代真实浏览器动作,并检查 `browser_action_trace` / `browser_action_requested` 证据。 -- 2026-04-29:第十二刀验证通过 `CARGO_TARGET_DIR=src-tauri/target/codex-modality-contract cargo test --manifest-path src-tauri/Cargo.toml should_carry_browser_control_contract_into_replay_grader_checks`、`should_carry_modality_runtime_contract_into_replay_case`、`npm run test:contracts`、`npm run verify:gui-smoke` 与本轮触达文件 `git diff --check`。 -- 2026-04-29:继续第十三刀 `pdf_extract`:新增前端 registry resolver `resolvePdfExtractRuntimeContractBinding()`,`@读PDF` 发送时在 `harness.pdf_read_skill_launch.pdf_read_request` 注入 `pdf_extract` contract 快照;Rust 侧新增 `PDF_EXTRACT_*` 常量、`pdf_extract_runtime_contract()` 与 `insert_pdf_extract_contract_fields()`,`prepare_pdf_read_skill_launch_request_metadata` 会把缺省合同字段补齐到 launch 与 request,系统 prompt 显式要求 Skill(pdf_read) 保留 contract 字段、真实读取 PDF,并禁止 `frontend_direct_pdf_parse` / `generic_chat_summary_only`。 -- 2026-04-29:第十三刀验证通过 `npm test -- src/lib/governance/modalityRuntimeContracts.test.ts src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx`、`npm run governance:modality-contracts`、`npm run typecheck`、`npm run test:contracts`、`npm run verify:gui-smoke`、`cargo fmt --manifest-path src-tauri/Cargo.toml --check`、`CARGO_TARGET_DIR=src-tauri/target/codex-modality-contract cargo test --manifest-path src-tauri/Cargo.toml pdf_read_skill_launch`、`cargo test --manifest-path src-tauri/Cargo.toml` 与本轮触达文件 `git diff --check`;`npm run verify:local` 初跑曾在全量 Rust 阶段暴露 PDF 断言误落到 resource_search 测试,已修复并用全量 `cargo test` 复验通过。 -- 2026-04-29:继续第十四刀 `pdf_extract` evidence/replay:`runtime_evidence_pack_service` 现在会从 `Skill(pdf_read)` tool timeline metadata 或其 `args.pdf_read_request` 合同快照导出 `pdf_extract` 的 `modalityRuntimeContracts`,`source=pdf_read_skill_trace.modality_runtime_contract`、`routingEvent=executor_invoked`、`routingOutcome=accepted/failed`、`expectedRoutingSlot=base_model`。 -- 2026-04-29:第十四刀同步 `runtime_replay_case_service`:replay tags 增加 `modality-pdf_extract`、`pdf-extract`、`pdf-read-skill`、`pdf-read-trace`,`expected.json` / `grader.md` 明确要求继续走 `Skill(pdf_read)` 或真实 `list_directory` / `read_file` 文件读取证据,并禁止 `frontend_direct_pdf_parse`、`generic_chat_summary_only`、ToolSearch、WebSearch 或 Grep 替代真实读 PDF。 -- 2026-04-29:继续第十五刀 `pdf_extract` entry binding:`modalityRuntimeContracts.json` 现在登记 `at_pdf_read_command`,覆盖 `@读PDF / @pdf / @read_pdf`,并把 launch path 固定为 `harness.pdf_read_skill_launch.pdf_read_request`;`useWorkspaceSendActions` 从 `resolvePdfExtractRuntimeContractBinding().boundEntrySources` 读取 `entry_source`,只保留 `PDF_EXTRACT_DEFAULT_ENTRY_SOURCE` 作为 registry 缺省 fallback。 -- 2026-04-29:继续第十六刀 `voice_generation`:新增前端 registry resolver `resolveVoiceGenerationRuntimeContractBinding()`,`voice_generation.bound_entries` 登记 `at_voice_command`;`@配音` 发送时在 `harness.service_scene_launch.service_scene_run` 注入 `voice_generation` contract 快照,后端 `prepare_service_scene_launch_request_metadata` 也会为 `voice_runtime` 旧 metadata 补齐合同字段,服务型场景 prompt 会输出底层合同、所需能力与 `runtime_contract(JSON)`,并禁止退回 `legacy_tts_test_command`。 -- 2026-04-29:继续第十七刀 `web_research`:新增前端 registry resolver `resolveWebResearchRuntimeContractBinding()`,`web_research.bound_entries` 登记 `at_search_command`、`at_deep_search_command` 与 `at_site_search_command`;`@搜索 / @深搜 / @站点搜索` 发送时分别在 research / deep search / site search request 中注入 `web_research` contract 快照,Rust 侧 prepare 函数也会把缺省合同字段补齐到 launch 与 request,prompt 显式输出底层合同、所需能力与 `runtime_contract(JSON)`,并禁止退回模型记忆、本地文件搜索、通用 WebSearch 或 ToolSearch 偏航。 -- 2026-04-30:继续第十八刀 `web_research` evidence/replay:`runtime_evidence_pack_service` 现在会从 `Skill(research)` / `Skill(site_search)` tool timeline 的 args 或 metadata 导出 `web_research` 的 `modalityRuntimeContracts`,`source=web_research_skill_trace.modality_runtime_contract`、`routingEvent=executor_invoked`、`routingOutcome=accepted/failed`、`expectedRoutingSlot=report_generation_model`;`runtime_replay_case_service` 同步增加 `web-research`、`research-skill`、`web-research-trace` tags,并在 expected / grader 中要求继续走 `Skill(research)` / `Skill(site_search)` 与真实 search*query / `lime_site*\*`证据,禁止`model_memory_only_answer`、`local_file_search_before_research_skill`、ToolSearch 或普通聊天替代。 -- 2026-04-30:继续第十九刀 `web_research` 索引化:`runtime_evidence_pack_service` 的 `modalityRuntimeContracts` 现在输出 `snapshotIndex`,汇总 `contractKeys`、`sourceCounts`、`routingOutcomeCounts`、`expectedRoutingSlots` 与 `toolTraceIndex.items`;`web_research` replay input 会携带同一份索引,使回归样本能直接定位 `executorBindingKey=research`、`entrySource=at_search_command` 与 `web_research_skill_trace`,不再只能扫描 raw snapshots。 -- 2026-04-30:继续第二十刀 `web_research` 报告型子入口:`web_research.bound_entries` 纳入 `at_report_command` 与 `at_competitor_command`,前端 `@研报 / @竞品` 发送会在 `harness.report_skill_launch.report_request` 注入同一份 `web_research` contract;Rust `report_skill_launch` prepare / prompt 也补齐合同字段,同时保留首刀 `Skill(report_generate)`,并把 evidence / replay 扩展到 `report_generate` trace,避免另开 `report_generation` 平行事实源。 -- 2026-04-30:继续第二十一刀 `text_transform`:新增 `text_transform` contract 并登记 `at_file_read_command`、`at_summary_command`、`at_translation_command`、`at_analysis_command`、`at_publish_compliance_command`、`at_logo_decomposition_command`;前端 `@读文件 / @总结 / @翻译 / @分析 / @发布合规 / @Logo拆解`、Rust summary/translation/analysis prepare 与 prompt、evidence `text_transform_skill_trace`、replay tags / expected / grader 已统一收敛到同一份底层合同,入口层不再新增 summary / translation / analysis 平行事实源。 -- 2026-04-30:继续第二十二刀 `voice_generation` evidence/replay:`runtime_evidence_pack_service` 现在会从 voice runtime / service scene timeline args 或 metadata 导出 `voice_generation` 的 `modalityRuntimeContracts`,`source=voice_generation_service_scene_trace.modality_runtime_contract`、`routingEvent=executor_invoked`、`routingOutcome=accepted/failed`、`expectedRoutingSlot=voice_generation_model`;`runtime_replay_case_service` 同步增加 `voice-generation`、`voice-runtime`、`voice-generation-trace` tags,并在 expected / grader 中要求继续走 `service_scene_launch(scene_key=voice_runtime)` / 本地 ServiceSkill runtime 或后续 audio_task/audio_output 证据,禁止 `legacy_tts_test_command`、伪造云端提交、普通聊天文本或通用文件卡替代。 -- 2026-04-30:继续第二十三刀 `voice_generation` audio artifact protocol:新增 `audio_generate` task type、`create_audio_generation_task_artifact` Tauri 命令与 `lime_create_audio_generation_task` Agent tool,只写入标准 `audio_task/audio_output` 产物,不生成真实音频、不提交云端;前端 API、DevBridge mock、`list_media_task_artifacts` contract index、evidence `audio_task.modality_runtime_contract` 与 replay grader 已同步消费同一份 `voice_generation` 合同快照,下一刀再补 audio viewer / 真实 worker。 -- 2026-04-30:继续第二十四刀 `voice_generation` audio preview/viewer:`lime_create_audio_generation_task` 工具结果现在会带回 `source_text / voice / audio_path / duration_ms` 等任务元数据,前端 `taskPreviewFromToolResult` 可生成 `audio_generate` 任务卡,并同步生成 `.lime/runtime/audio-generate/*.md` 运行时文档 viewer;聊天区任务卡采用 Lime 现有轻卡视觉,打开后进入可读文档而不是暴露隐藏 task JSON,真实音频 worker 与完整音频工作台继续后置。 -- 2026-04-30:继续第二十五刀 `voice_generation` audio_output 回写闭环:新增 `complete_audio_generation_task_artifact` 命令与前端 API / DevBridge mock / governance catalog / mockPriority 同步,执行器可把标准 `audio_generate` task 从 pending 更新为 `succeeded`,并把完成态 `audio_output` 同时写入 payload 与 result;本刀仍不引入真实音频 worker、LimeCore 云执行 run/poll 或 legacy TTS。 -- 2026-04-30:继续第二十六刀 `voice_generation` audio preview runtime:新增 `useWorkspaceAudioTaskPreviewRuntime`,聊天工作区会监听 `lime://creation_task_submitted` 并轮询仍在 running 或缺少音频 URL 的 `audio_generate` 任务,从标准 task artifact 恢复完成态 `audio_output` 到任务卡;这一步把第二十五刀写回口真正接回用户可见轻卡,但仍不新增完整音频工作台。 -- 2026-04-30:继续第二十七刀 `voice_generation` audio worker skeleton:`create_audio_generation_task_artifact` 现在会在 emit 标准媒体任务事件后启动 `lime-audio-worker` 骨架;骨架先把任务推进到 `running`,随后在真实 provider 未接通时写回 `audio_worker_unavailable` 可重试失败与 `payload.audio_output.status=failed`,不生成假 `audio_path`、不调用 legacy TTS,也不新增 LimeCore 云 run/poll 协议。 -- 2026-04-30:继续第二十八刀 `voice_generation` OpenAI-compatible audio provider seam:`lime-audio-worker` 不再停在纯骨架失败,而是从标准 `audio_generate` task payload / 全局 `media_defaults.voice` 解析 provider 与 model,通过 current API Key Provider 主链拿到 OpenAI-compatible `api_key/base_url`,调用 `/audio/speech` 返回真实音频 bytes 后保存到 `.lime/runtime/audio/.mp3`,再回写 `payload.audio_output.completed` 与 `record.result.audio_output`;无 AppHandle、DbConnection、ApiKeyProviderService、provider/model/API Key 或非 OpenAI-compatible client 时写回明确 `audio_provider_*` 失败码,不回退 `legacy_tts_test_command`、`test_tts`、伪云端提交或通用文件卡。 -- 2026-04-30:继续第二十九刀 `voice_generation` audio failure preview:聊天区 `useWorkspaceAudioTaskPreviewRuntime` 现在会从标准 `audio_generate` task artifact 的 `payload.audio_output` / `record.last_error` 读取 `audio_provider_*` 错误码、错误原因与 retryable,并在失败 artifact 没有 `audio_path` 时清空任务卡音频路径;`TaskMessagePreview` 同步展示 Provider 错误码和原因,让未配置 provider、resolver 不可用或 adapter 缺失直接回到用户可见任务卡,不再泛化成普通失败,也不伪造音频结果。 -- 2026-04-30:继续第三十刀 `voice_generation` audio viewer sync:`useWorkspaceAudioTaskPreviewRuntime` 在从标准 `audio_generate` task artifact 恢复完成/失败态时,会同步重建同一条 `.lime/runtime/audio-generate/*.md` 运行时文档的 ArtifactDocument metadata;打开聊天任务卡时,viewer 会展示 `audio_output.completed` 的真实音频路径,或展示 `audio_provider_*` 错误码与原因,不再停留在创建任务时的“等待音频执行器”文档。 -- 2026-04-30:继续第三十一刀 `voice_generation` audio evidence/replay details:`runtime_evidence_pack_service` 现在会从 `audio_generate` task artifact 导出 `audioOutput` 摘要,并在 `snapshotIndex.audioOutputIndex` 汇总 audio output 状态、Provider 错误码与 worker;`runtime_replay_case_service` 同步把 `audio-output-completed` / `audio-output-failed` 纳入 suite tags / failure modes,并在 expected / grader 中要求 replay 保留 `audio_output.completed` 与真实 `audio_path`,或显式处理 Provider 失败,不允许回退 legacy TTS、伪造音频路径、普通聊天文本或通用文件卡。 -- 2026-04-30:继续第三十二刀 `voice_generation` audio task index details:`media_task_cmd` 的 `list_media_task_artifacts` 索引现在把 `audio_output` 完成/失败事实直接纳入 `modality_runtime_contracts`,包含按状态汇总、Provider 错误码汇总,以及每个 task snapshot 的 `audio_output_status/path/mime_type/duration_ms/error_code/retryable`;`src/lib/api/agentRuntime/types.ts` 与浏览器 fallback mock 同步更新,避免浏览器链路或前端恢复逻辑只能靠重新读取隐藏 task JSON 才能判断音频产物状态。 -- 2026-04-30:继续第三十三刀 `voice_generation` audio index restore:聊天工作区的 `useWorkspaceAudioTaskPreviewRuntime` 现在会先按 `voice_generation + audio_generate` 查询统一媒体任务索引,从 snapshot 的 `audio_output_status/path/mime_type/duration_ms/error_code/retryable` 直接恢复任务卡和 `.lime/runtime/audio-generate/*.md` viewer;索引缺失或旧 task 没有 `audio_output_status` 时才保留原来的单 task artifact 读取兜底,避免主路径继续依赖隐藏 task JSON。 -- 2026-04-30:继续第三十四刀 `Phase 4 artifact graph`:新增 `docs/roadmap/warp/artifact-graph.md` 与 `src/lib/governance/modalityArtifactGraph.json`,把 `image/audio/browser/pdf/report/presentation/webpage/generic_file` 的 artifact kind、truth source、viewer、evidence 与 task index 字段落成可检查事实源;`governance:modality-contracts` 现在会校验 contract 的 `artifact_kinds` 必须能在 artifact graph 中找到 truth source / viewer / evidence 交集,防止新增多模态能力继续退回未知 viewer 或通用文件卡旁路。 -- 2026-04-30:继续第三十五刀 `browser_control entry binding`:`browser_control.bound_entries` 现在登记 `@浏览器 / @browser / @browse`、`@Browser Agent`、`@Mini Tester`、`@Web Scheduler`、`@Web Manage`,所有入口只声明 `harness.browser_assist` launch metadata、默认输入映射与可见性策略;前端 Browser Assist launch 会按触发词从 registry 派生 `entry_source`,不再把所有浏览器别名压成同一个入口来源,也不让入口直接写 task / artifact / viewer。 -- 2026-04-30:继续第三十六刀 `browser_control browserActionIndex`:`runtime_evidence_pack_service` 现在会从 Browser Assist tool metadata 提取 `browserAction` 摘要,并在 `modalityRuntimeContracts.snapshotIndex.browserActionIndex` 汇总 actionCount、sessionCount、lastUrl、observationCount、screenshotCount、backend/status/action 计数与逐项 `browser_session` / `browser_snapshot` artifactKind;`runtime_replay_case_service` 同步把 `browser-action-index` 纳入 suite tags / expected / grader,要求 replay 继续导出可查询 browser session/snapshot 索引,而不是只靠 raw snapshots 或 WebSearch 替代。 -- 2026-04-30:继续第三十七刀 `browser_control Harness visible index`:Evidence Pack 的 `observabilitySummary.modalityRuntimeContracts.snapshotIndex.browserActionIndex` 现在会携带裁剪后的 Browser Assist 摘要,前端 `AgentRuntimeEvidencePack` 类型与 normalizer 同步解析该索引;`HarnessStatusPanel` 在导出问题证据包后展示 Browser Assist 索引卡,直接暴露 action/session/URL/observation/screenshot 与最近 `browser_session` / `browser_snapshot` 项,证明浏览器复盘已从 runtime.json 人工查找前进到用户可见 evidence 面板。 -- 2026-04-30:继续第三十八刀 `browser_control browser_replay_viewer`:`HarnessStatusPanel` 的 Browser Assist 索引卡新增“打开复盘”,以 evidence pack + `browserActionIndex` 构造临时 `browser_assist` Artifact;`BrowserAssistRenderer` 现在可从 artifact meta 或 JSON content 读取 `browserActionIndex`,渲染最小 `browser_replay_viewer`,展示动作统计、最近 URL、会话/target/entry、截图可用性与最近 `browser_session` / `browser_snapshot`。这一步把 evidence 可见摘要推进到 Lime 内部复盘面,但仍不新增 browser task 文件协议;完整交互回放、权限 profile 可视化与截图/DOM/network 深层展开继续后置。 -- 2026-04-30:继续第三十九刀 `audio_transcription contract`:新增 current `audio_transcription` contract,绑定 `@转写 / @transcribe / @Audio Extractor` 到 `harness.transcription_skill_launch.transcription_task`;前端 `@转写` metadata 现在携带 `modality_contract_key=audio_transcription`、`required_capabilities=[text_generation,audio_transcription]`、`routing_slot=audio_transcription_model` 与 `runtime_contract`,Rust `transcription_skill_launch` 也会为旧 metadata 补齐同一合同并在 prompt 中禁止 `frontend_direct_asr`、`generic_file_transcript`、转写前 ToolSearch/WebSearch 偏航。`transcript` artifact graph 已反向登记该合同;真实转写 worker、transcript viewer 与 evidence/replay 索引继续后置。 -- 2026-04-30:继续第四十刀 `audio_transcription transcript task/index/evidence/replay`:`lime_create_transcription_task`、`create_transcription_task_artifact_inner` 与 CLI `lime task create transcription` / `lime media transcription generate` 现在写入同一标准 `transcription_generate` task file,payload 固化 `audio_transcription` 合同、`requested_target=transcript` 与 `transcript.pending`;`list_media_task_artifacts` 增加 `transcript_count/statuses/error_codes` 与每个 task 的 `transcript_*` snapshot,Evidence Pack 增加 `snapshotIndex.transcriptIndex`,Replay / grader 增加 `audio-transcription`、`transcription-task-trace`、`transcript-index` 标签与缺失/失败阻断检查。真实 ASR worker、完成态 transcript 回写和专属 transcript viewer 仍作为下一刀。 -- 2026-04-30:继续第四十一刀 `audio_transcription transcription worker`:`lime_create_transcription_task` 现在在创建标准 `transcription_generate` task 后启动 `lime-transcription-worker`;worker 校验 `audio_transcription` contract、读取本地 source file 或下载 `source_url`,通过 current API Key Provider 解析 OpenAI-compatible credential,调用 `/audio/transcriptions`,成功时写入 `.lime/runtime/transcripts/*` 并回写 `transcript.completed`、`transcript_path`、`provider_id/model` 与 `record.result.transcript`;失败时回写 `transcript.failed` 和 `transcription_provider_*` / `transcription_source_*` / contract 错误码,不回退 frontend ASR、普通文件读取或 generic_file transcript。最小 GUI 恢复层已在第四十二刀接回,文本校对已在第四十三刀接回,时间轴/说话人段落展示已在第四十四刀接回;编辑保存型 transcript viewer、更多 ASR adapter 与本地离线 ASR 继续后置。 -- 2026-04-30:继续第四十二刀 `audio_transcription transcript visible restore`:聊天工作区新增 `useWorkspaceTranscriptionTaskPreviewRuntime`,会优先从 `list_media_task_artifacts(modalityContractKey=audio_transcription, taskType=transcription_generate)` 的 `transcript_*` snapshot 恢复完成/失败态,把 `transcript_path`、source、language、outputFormat、Provider 错误码同步到任务卡与 `.lime/runtime/transcription-generate/*.md` 运行时文档;只有索引缺失时才回退读取单个 task artifact,避免用户可见路径继续依赖隐藏 task JSON 或 generic_file transcript。 -- 2026-04-30:继续第四十三刀 `audio_transcription transcript proofreading viewer`:`useWorkspaceTranscriptionTaskPreviewRuntime` 在完成态恢复时读取 `transcript_path` 对应文本,并把 `transcriptText` 写回任务预览和 `.lime/runtime/transcription-generate/*.md` 运行时文档;`buildTranscriptionTaskArtifactDocument` 现在输出“转写文本(可编辑校对)”代码块,让打开任务卡即可在 Lime 内部读取、复制与校对 transcript,而不是只看到路径或退回 generic_file。 -- 2026-04-30:继续第四十四刀 `audio_transcription transcript timeline viewer`:新增 transcript segment 解析器,支持从 OpenAI verbose JSON、SRT 与 VTT 读取 `start/end/speaker/text`,并把结果回写到聊天任务卡时间轴预览与 `.lime/runtime/transcription-generate/*.md` ArtifactDocument 表格;本刀只消费同一 `transcription_generate` task file 与 `transcript_path` 输出,不新增协议、Tauri command、frontend ASR 或 generic_file 旁路。编辑保存型 transcript viewer、更多 ASR adapter 与本地离线 ASR 继续后置。 -- 2026-04-30:继续第四十五刀 `audio_transcription transcript correction save`:复用现有 ArtifactDocument Workbench 编辑保存链路,让转写运行时文档的文本与时间轴从“可复制校对”推进到“可保存校对稿”;生成文档会标记 `transcriptCorrectionEnabled` / `transcriptCorrectionSource=artifact_document_version` 并提示保存不改写原始 ASR 输出,保存时补 `transcriptCorrectionStatus=saved`、编辑 block、原始 transcript 路径、文本长度、段落/说话人数与 `transcriptSegmentsCorrected`。本刀没有新增 Tauri command、Rust worker 分支、frontend ASR 或 generic_file patch 旁路。 -- 2026-04-30:继续第四十六刀 `audio_transcription transcript correction status`:保存校对稿时会在同一 ArtifactDocument 中插入/更新 `transcript-correction-status` 成功提示块,明确“校对稿已保存为当前运行时文档的新版本;原始 ASR 输出文件保持不变”,并写入 `transcriptCorrectionDiffSummary`,汇总原文/校对稿文本长度、段落数量、变更段落和说话人数差异。该状态仍随同一 `.lime/runtime/transcription-generate/*.md` 运行时文档版本保存,不新增命令、worker 分支或并行 patch artifact。 -- 2026-04-30:继续第四十七刀 `Phase 3 / Phase 5 execution profile registry`:新增 `docs/roadmap/warp/execution-profile.md` 与 `src/lib/governance/modalityExecutionProfiles.json`,把 7 个 current contracts 的 profile、artifact policy、LimeCore policy refs 与 executor adapters 落成机器事实源;`check-modality-runtime-contracts.mjs` 现在会读取 profile registry,校验每个 current contract 都被 profile 覆盖、每个 `executor_binding` 都有 adapter、adapter 支持位/产物/权限/failure mapping 与 contract 对齐。该刀不改 Tauri command、bridge、mock 或真实 executor 行为,只把 Phase 3/5 的主线底座从文档要求推进成可阻断错误配置的 current 守卫。 -- 2026-04-30:继续第四十八刀 `Phase 3 / Phase 5 profile resolver`:新增 `src/lib/governance/modalityExecutionProfiles.ts` 与定向测试,`resolveModalityRuntimeContractBinding()` 会把 current contract 对应的 `execution_profile`、`executor_adapter`、`executionProfileKey`、`executorAdapterKey` 注入同一 runtime contract binding;所有现有上层入口继续只调用 runtime contract resolver,即可随 launch metadata 携带 profile / adapter 快照。本刀没有新增命令、bridge、mock、Rust executor 或 GUI surface,只把上一刀的机器事实源推进到前端主路径输入。 -- 2026-04-30:继续第四十九刀 `Phase 3 / Phase 5 evidence snapshot`:`runtime_evidence_pack_service` 现在会从 runtime contract 中提取 `executionProfileKey` 与 `executorAdapterKey`,并写入 `modalityRuntimeContracts.snapshots[]`、`snapshotIndex.executionProfileKeys`、`snapshotIndex.executorAdapterKeys` 与 `toolTraceIndex.items[]`;图片 contract preflight 失败样本与 web_research Skill trace 样本都增加断言,证明 profile / adapter 已进入 evidence 主链,而不是只停留在前端 metadata 或治理 JSON。本刀未改命令、bridge、mock、GUI 或真实 executor 行为。 -- 2026-04-30:继续第五十刀 `Phase 3 / Phase 5 task index snapshot`:Rust 多模态 `runtime_contract` snapshot 现在随 central contract helper 写入 `execution_profile.profile_key` 与 `executor_adapter.adapter_key`;`list_media_task_artifacts` 会把这些字段汇总到 `modality_runtime_contracts.execution_profile_keys`、`executor_adapter_keys`,并在每条 snapshot 输出 `execution_profile_key` / `executor_adapter_key`。前端 `MediaTaskModalityRuntimeContractIndex` 类型、浏览器 fallback mock、图片/配音/转写任务恢复测试同步更新,证明 profile / adapter 已进入统一媒体任务索引,而不是只停留在 evidence/replay。 -- 2026-04-30:继续第五十一刀 `Phase 3 / Phase 5 media worker adapter preflight`:`validate_*_task_execution_contract` 现在会在图片、配音、转写 worker 进入真实执行器前校验 `execution_profile.profile_key`、`executor_adapter.adapter_key` 与 `executor_binding.executor_kind/binding_key`,错配时以 `runtime_preflight` 阶段阻断,而不是等 provider/worker 泛化失败;`list_media_task_artifacts` snapshot 同步暴露 `executor_kind` / `executor_binding_key`,浏览器 fallback mock 与前端类型跟进,Evidence Pack 也会把这类阻断标记为 `runtime_preflight` / `blocked`。 -- 2026-05-01:继续第五十二刀 `Phase 6 policy snapshot seed`:central Rust contract helper、前端 runtime contract resolver 与浏览器 fallback mock 现在都会携带 `limecore_policy_refs` 与最小 `limecore_policy_snapshot(status=refs_declared, decision=not_evaluated)`;`list_media_task_artifacts` 汇总 policy refs/status/decision,Evidence Pack 增加 `snapshotIndex.limecorePolicyIndex`,前端 normalizer 与测试同步。该刀不新增命令、不实现真实 LimeCore 云执行,只把后续 allow / ask / deny 需要的审计字段接入 current 主链。 -- 2026-05-01:继续第五十三刀 `Phase 6 local policy decision summary`:`limecore_policy_snapshot` 从 `not_evaluated` 推进到本地默认 `allow` 摘要,并写入 `decision_source=local_default_policy`、`decision_scope=local_defaults_only`、`decision_reason=declared_policy_refs_with_no_local_deny_rule` 与 `unresolved_refs`;统一媒体任务索引和 Evidence Pack 同步暴露这些解释字段。该刀仍不新增命令、不调用 LimeCore 云、不碰上层 `@` 入口;真实 tenant / provider / gateway policy 命中值继续后置。 -- 2026-05-01:继续第五十四刀 `Phase 6 policy input gap summary`:`limecore_policy_snapshot` 新增 `policy_inputs[]` 与 `missing_inputs[]`,把每个 policy ref 标成 `declared_only / limecore_pending`;Evidence Pack `limecorePolicyIndex` 与统一媒体任务索引同步输出 missing inputs,让后续接入真实 LimeCore `model_catalog / provider_offer / tenant_feature_flags / gateway_policy` 命中值时有稳定 diff 面。该刀不新增命令、不触发云执行,也不修改上层 `@`。 -- 2026-05-01:收口第五十四刀验证:定向前端/Rust 测试、`typecheck`、`governance:modality-contracts`、`test:contracts`、`harness:doc-freshness`、相关文件 `git diff --check` 与 `verify:local` 均已通过;GUI smoke 复用 headless Tauri 与 DevBridge,证明本轮底层审计字段接线没有破坏 workspace、browser runtime、site adapter 与 agent runtime tool surface 主路径。 -- 2026-05-01:继续第五十五刀 `Phase 6 policy gap evidence visibility`:Harness evidence 面板新增 `LimeCore 策略缺口` 摘要卡,直接从 `limecorePolicyIndex` 展示 policy snapshot 数、refs、missing inputs、local default decision、profile / adapter、decision scope/reason 与 `declared_only / limecore_pending` 输入状态;该刀只消费现有 evidence 字段,不新增 Tauri command、不接 LimeCore 云 run/poll、不触碰上层 `@` 入口。 -- 2026-05-01:继续第五十六刀 `Phase 6 policy gap replay grader`:Replay case 现在会把 `limecorePolicyIndex` 转成 suite tags、failure modes、success criteria、blocking checks 与多模态合同检查,要求回放继续保留 policy refs、missing inputs、`local_default_policy` / `local_defaults_only` 解释;该刀确保 policy gap 能被复盘验收,而不是只停留在 evidence UI。 -- 2026-05-01:继续第五十七刀 `Phase 6 policy hit value wiring`:在不接云 run/poll 的前提下,为真实 LimeCore policy 命中值补空接线结构:`policy_value_hits[]` 保持空、`pending_hit_refs[]` 指向等待命中的 refs、`policy_value_hit_count=0`,并贯通 runtime contract、Evidence Pack、任务索引、前端类型/normalizer 与 mock;后续接真实 LimeCore 值时只需填充同一字段,不再改协议外形。 -- 2026-05-01:继续第五十八刀 `Phase 6 policy hit resolver seam`:`policy_value_hits(status=resolved)` 现在会被 central runtime contract helper、前端 resolver、Evidence Pack、媒体任务索引与浏览器 mock 统一识别;命中的 ref 会进入 `evaluated_refs`,未命中的 ref 继续留在 `missing_inputs / pending_hit_refs`。该刀只建立“真实命中值写入与派生待命中 refs”的 seam,不接 LimeCore 云 run/poll,也不把本地默认 decision 升级成真实 allow / ask / deny。 -- 2026-05-01:继续第五十九刀 `Phase 6 local model_catalog hit producer`:图片任务执行前复用已有 model registry assessment,把命中的模型目录事实写入 `policy_value_hits(status=resolved, value_source=local_model_catalog)`,同步更新 `runtime_contract` snapshot、当前 attempt input snapshot 与统一媒体任务索引;该刀只让 `model_catalog` 输入从 pending 变成 resolved,不接 provider offer / tenant flags,也不把本地默认 `allow` 解释成云策略放行。 -- 2026-05-01:继续第六十刀 `Phase 6 local provider_offer hit producer`:图片任务进入真实执行器前复用已解析的本地 runner config/API key 与 task payload provider/model,把 `provider_offer` 写入 `policy_value_hits(status=resolved, value_source=local_provider_offer)`,同步收缩 `missing_inputs / pending_hit_refs`;snapshot 只记录 endpoint origin/path、adapter 与 credential 状态,不写 API key,不新增 Tauri command,也不接 LimeCore 云 run/poll。 -- 2026-05-01:继续第六十一刀 `Phase 6 request gateway_policy hit producer`:Browser Assist 与 Web Research 类 launch 复用请求侧 `harness.oem_routing`,把 tenant/provider/quota/can_invoke/fallback 等真实路由输入写入对应 runtime contract 的 `policy_value_hits(status=resolved, value_source=request_oem_routing)`;命中后 `gateway_policy` 会进入 `evaluated_refs`,但 `decision` 仍保持 `local_default_policy / local_defaults_only`,不新增命令、不接云 run/poll,也不伪造 tenant feature flags。 -- 2026-05-01:继续第六十二刀 `Phase 6 request tenant_feature_flags hit producer`:Workspace send metadata 从 OEM Cloud bootstrap snapshot 的 `features` 生成 `harness.tenant_feature_flags`,Rust runtime contract helper 在所有 request metadata runtime contract 中写入 `policy_value_hits(status=resolved, value_source=oem_cloud_bootstrap_features)`;命中后 `tenant_feature_flags` 会进入 `evaluated_refs`,但 `decision` 仍保持 `local_default_policy / local_defaults_only`,不新增命令、不接云 run/poll,也不把 feature flags 当作真实 allow / ask / deny evaluator。 -- 2026-05-01:继续第六十三刀 `Phase 6 policy input evaluator seam`:central Rust contract helper 与前端 runtime contract resolver 新增 `policy_evaluation`,当所有 refs 都有 resolved hit 时用 `policy_input_evaluator` 给出 `allow / ask / deny` 顶层决策;gateway `can_invoke=false` / blocked、tenant `gatewayEnabled=false`、model catalog 不支持目标能力或 provider credential 非 configured 会产生 `deny`,quota low / subscribe required / logged out 会产生 `ask`。仍有 missing inputs 时只记录 `policy_evaluation.status=input_gap`,顶层仍保持 `local_default_policy / local_defaults_only`,不接云 run/poll、不新增命令。 -- 2026-05-01:继续第六十四刀 `Phase 6 thread read policy explanation`:`AgentRuntimeThreadReadModel` 现在会从最新 tool metadata / file artifact 中的 runtime contract 提取 `limecore_policy_snapshot`,并写入 `runtime_summary.limecorePolicy`;上层读取 thread read 时可直接看到 contract key、snapshot status、顶层 decision/source/scope/reason、refs、missing/pending refs、hit count 与 evaluator blocking/ask/pending refs。本刀不新增命令、不接 LimeCore 云 run/poll,也不把 thread read 结果当云端 audit 事实源。 -- 2026-05-01:继续第六十五刀 `Phase 6 media task policy evaluation index`:`list_media_task_artifacts` 的 `modality_runtime_contracts` 现在汇总 `policy_evaluation` status / decision / source 与 blocking / ask / pending refs,每条 snapshot 也输出同名 `limecore_policy_evaluation_*` 字段;前端类型、浏览器 fallback mock 与 mediaTasks 回归同步。该刀只把 evaluator explanation 推到任务索引,不新增命令、不接云 run/poll,也不把 input gap 的 evaluator `ask` 覆盖成顶层真实策略结论。 -- 2026-05-01:继续第六十六刀 `Phase 6 task card policy evaluation meta`:配音与转写任务卡恢复层现在会消费统一媒体任务索引的 `limecore_policy_evaluation_*` snapshot,通过共享 helper 生成 `LimeCore 策略输入待命中: N`、`LimeCore 策略输入阻断: ` 或 `LimeCore 策略输入需确认: ` meta 标签;audio input gap 与 transcription deny 都有稳定回归。该刀只让现有任务卡展示 evaluator explanation,不新增 Tauri command、不接 LimeCore 云 run/poll,也不触碰上层 `@` 命令。 -- 2026-05-01:继续第六十七刀 `Phase 6 image viewer policy evaluation meta`:图片任务恢复层现在会从 `runtime_contract.limecore_policy_snapshot.policy_evaluation` 解析 LimeCore evaluator 摘要,写入 `ImageRuntimeContractSnapshot` 并在图片 viewer 的运行合同标签旁展示 `LimeCore 策略输入待命中 / 阻断 / 需确认`;本刀只消费已有 task artifact runtime contract,不新增命令、不接 LimeCore 云 run/poll,也不修改图片上层入口。 -- 2026-05-01:继续第六十八刀 `Phase 6 image message card policy evaluation meta`:图片消息轻卡现在从 `preview.runtimeContract` 读取同一 LimeCore evaluator 摘要,并在预览顶部 meta pills 展示 `LimeCore 策略输入待命中 / 阻断 / 需确认`;本刀只消费已有图片 runtime contract,不新增命令、不接 LimeCore 云 run/poll,也不改变轻卡打开 viewer 的导航能力。 -- 2026-05-01:继续第六十九刀 `Phase 5 voice service compat guard`:旧 `lime_run_service_skill` 命中 `voice_generation / voice_runtime / at_voice_command / voice_generation_model` 时,会生成 `modality_runtime_contract` metadata 并校验 `contract_key=voice_generation`、`execution_profile=voice_generation_profile`、`executor_adapter=service_skill:voice_runtime`、`executor_binding=service_skill:voice_runtime`;错配返回 `runtime_preflight`,通过也只返回 compat guard,不执行云 run/poll。该刀把旧服务型工具收成 guard,不把它升级为 current executor,也不提前硬造 `gateway:*` adapter。 -- 2026-05-02:继续第七十刀 `Phase 5/6 Rust preflight verification seam`:`WebSearchPreflightRequest` 现在从 `lime_agent` crate 正式导出,真实 WebSearch preflight 集成测试改为使用请求对象调用;automation runtime turn 与 DevBridge session 创建调用点同步补齐新增缺省参数,恢复 `cargo test -p lime ` 对 Phase 5/6 Rust 集成测试编译面的覆盖。该刀不新增执行器、不改变 `@` 入口、不接 LimeCore 云 run/poll,只清掉阻挡后续 executor/policy preflight 定向验证的旧 API 漂移。 -- 2026-05-02:继续第七十一刀 `Phase 5/6 thread read modality runtime summary`:`AgentRuntimeThreadReadModel` 现在会从最近 ToolCall metadata / FileArtifact content 的同一 `runtime_contract` 提取 profile / adapter / binding 摘要,并写入 `runtime_summary.modalityRuntime`;`limecorePolicy` 继续解释 policy decision input,`modalityRuntime` 解释 profile / adapter / executor binding。该刀不新增 Tauri command、不接 LimeCore 云 run/poll,也不把上层 `@` 命令升级成底层合同事实源。 -- 2026-05-02:继续第七十二刀 `Phase 5/6 TaskProfile execution profile merge`:`SessionExecutionRuntimeTaskProfile` 新增 `modalityContractKey`、`routingSlot`、`executionProfileKey`、`executorAdapterKey`、`executorKind`、`executorBindingKey`、`permissionProfileKeys` 与 `userLockPolicy`;Rust request model resolution 会从 request metadata 已有 runtime contract 合并这些字段,并按 `modalityExecutionProfiles.json` 补齐 profile 权限与用户锁定策略,`task_profile_resolved` 前端协议测试也覆盖透传。该刀只推进 current runtime task profile 事实源,不新增命令、不接云 run/poll,也不让 `@` 命令成为底层执行合同事实源。 -- 2026-05-02:继续第七十三刀 `Phase 5/6 routingSlot capability enforcement`:`request_model_resolution` 现在从 `SessionExecutionRuntimeTaskProfile.routingSlot` 派生 runtime model capability requirements,并把它用于候选模型计数、catalog fallback 与多候选自动重选;非显式用户锁定路径会优先选择满足 runtime slot 的模型,显式用户锁定路径继续 honored,但会通过 `capability_gap` 输出 `browser_reasoning_candidate_missing` / `image_generation_candidate_missing` 等 gap。该刀不新增 Tauri command、不接 LimeCore 云 run/poll、不把上层 `@` 命令当底层事实源;完整权限判定、用户确认/阻断执行与真实 `gateway:*` adapter preflight 继续后置。 -- 2026-05-05:继续第七十四刀 `Phase 5/6 permissionProfileKeys runtime summary`:`request_model_resolution` 现在从 `SessionExecutionRuntimeTaskProfile.permissionProfileKeys` 生成 `SessionExecutionRuntimePermissionState`,随 `lime_runtime.permission_state` 写入 turn metadata;runtime view、thread read fallback summary、前端 execution runtime 类型和内部辅助任务 metadata 都同步识别这一摘要。`browser_control / web_search / media_upload / service_api_call / read_files / write_artifacts` 会进入 `askProfileKeys`,`ask_user_question` 只表示可补问用户,不视为风险权限;`blockingProfileKeys` 本刀保持为空,明确不做真实授权、不阻断执行、不新增命令、不接 LimeCore 云 run/poll、不把上层 `@` 命令当底层事实源。 -- 2026-05-05:继续第七十五刀 `Phase 5/6 thread read permission state`:`AgentRuntimeThreadReadModel` 现在结构化暴露 `permission_state`,前端 thread read 类型同步引用同一 `AsterSessionExecutionRuntimePermissionState`;上层读取可以拿到完整 required/ask/blocking profile keys 与 notes,不需要只依赖 `runtime_summary.permissionAskCount`。该刀仍只增强读取面,不新增 Tauri command、不新增 runtime 事件、不接真实权限授权、不阻断执行。 -- 2026-05-05:继续第七十六刀 `Phase 5/6 permission review runtime status`:`collect_runtime_request_resolution_side_events` 现在会把 `lime_runtime.permission_state(status=requires_confirmation)` 映射为现有 `runtime_status(phase=permission_review)` side event,metadata 携带 required/ask/blocking profile keys、decision source/scope 与 `declared_only=true`;`not_required` 不产生额外事件。该刀让权限声明态进入运行时事件流的可观察动作点,但仍不生成 `action_required`、不创建 pending approval、不阻断 turn、不新增 Tauri command、不接真实权限授权或 LimeCore 云 run/poll。 -- 2026-05-05:继续第七十七刀 `Phase 5/6 frontend permission review event contract`:前端 `agentProtocol` 与聊天 runtime status 类型现在正式接受 `phase=permission_review`,并保留 permission status、required/ask/blocking profile keys、decision source/scope 与 `declared_only` metadata;协议解析测试覆盖该事件不会被 normalize 回普通 `routing`。该刀只修正第七十六刀事件的前端消费边界,不新增 UI surface、不新增 bridge/Tauri command、不接真实授权。 -- 2026-05-05:继续第七十八刀 `Phase 5/6 permission evidence and replay facts`:Evidence Pack 的 `thread.runtimeFacts` 与 `observabilitySummary.runtimeFacts` 现在导出 `permissionState`,`signalCoverage` 增加 `permissionState` 覆盖项;Replay `runtimeFacts` 同步携带 `permissionState`,并在 `requires_confirmation` 或存在 `blockingProfileKeys` 时生成 blocking checks,要求回放不能把声明态权限误判为已获真实授权。该刀只增强审计/回放事实源,不创建 pending approval、不阻断执行、不新增命令或云策略。 -- 2026-05-05:继续第七十九刀 `Phase 5/6 permission confirmation state seed`:`SessionExecutionRuntimePermissionState` 新增 `confirmationStatus / confirmationRequestId / confirmationSource`,当前声明态 `requires_confirmation` 明确写为 `confirmationStatus=not_requested`、`confirmationRequestId=null`、`confirmationSource=declared_profile_only`;内部辅助任务写 `not_required`。前端 execution runtime 类型同步该字段。该刀只建立真实授权接入前的单一状态槽,不复用 `ApprovalRequest` 伪造 pending request、不阻断执行、不新增命令。 -- 2026-05-05:继续第八十刀 `Phase 5/6 live permission confirmation metadata`:`permission_review` runtime status metadata 现在同步携带 `confirmation_status / confirmation_request_id / confirmation_source`,前端 `agentProtocol` 会保留这些字段;`requires_confirmation` 的 live event 因此能明确表达“需要确认,但尚未发起真实审批请求”。该刀仍不创建 pending approval、不阻断执行、不新增命令。 -- 2026-05-05:继续第八十一刀 `Phase 5/6 thread read pending approval projection`:`AgentRuntimeThreadReadModel.permission_state` 现在会从同一 thread read 中真实存在的 pending tool `ApprovalRequest` 派生 `confirmationStatus=requested`、`confirmationRequestId=`、`confirmationSource=runtime_action_required`,`runtime_summary` 同步暴露 `permissionConfirmation*` 摘要。该刀只把已有真实 `action_required` 投影到权限确认状态槽,不创建审批、不改变 native approval 行为、不阻断执行、不新增命令。 -- 2026-05-05:继续第八十二刀 `Phase 5/6 resolved approval projection`:thread read 现在会从已完成或失败的真实 tool `ApprovalRequest.response.confirmed` 派生 `confirmationStatus=resolved / denied`,并保留真实 request id 与 `runtime_action_required` 来源。该刀仍只做读取模型投影,不改变审批提交、权限 enforcement 或执行恢复语义。 -- 2026-05-05:继续第八十三刀 `Phase 5/6 replay denied confirmation blocking`:Replay blocking checks 现在区分 permission confirmation 状态:`denied` 会生成明确阻断检查,`resolved` 不再被误报为“仍需确认”。该刀只修正 replay/grader 判定语义,不新增命令、不改审批执行、不接 GUI 或云策略。 -- 2026-05-05:继续第八十四刀 `Phase 5/6 evidence permission confirmation coverage`:Evidence Pack 的 `signalCoverage.permissionState` 现在会区分确认结果:`denied` 标为 `blocked` 并写入真实 request id,`resolved` 保持 `exported` 并说明已通过。该刀让审计摘要与 Replay 阻断语义对齐,不新增命令、不改审批执行、不接 GUI 或云策略。 -- 2026-05-05:继续第八十五刀 `Phase 5/6 evidence denied confirmation summary`:Evidence Pack 的 `knownGaps` 与 `summary.md` 现在会把 `confirmationStatus=denied` 暴露为人眼可见的阻断风险,摘要同时输出 `当前阻断信号`。该刀只增强导出解释,不改审批执行、不新增命令、不接 GUI 或云策略。 -- 2026-05-05:继续第八十六刀 `Phase 5/6 handoff permission confirmation summary`:Handoff bundle 的 `plan.md / handoff.md / review-summary.md / progress.json` 与 Analysis handoff 的 `analysis-brief.md / analysis-context.json / copy_prompt` 现在同步读取 `thread_read.permission_state.confirmationStatus`,`denied` 会作为不能成功交付的阻断风险输出真实 request id/source,`resolved` 会明确解释真实权限确认已通过;该刀只统一交接/外部分析摘要语义,不改审批执行、不新增命令、不接 GUI 或云策略。 -- 2026-05-05:继续第八十七刀 `Phase 5/6 review decision permission confirmation summary`:Review decision 模板现在从 Analysis handoff 的结构化 context 读取 `permissionConfirmationStatus / RequestId / Source / Summary`,并写入 `review-decision.md / review-decision.json` 的审核上下文、动态 checklist 与建议后续动作;`denied` 默认提示不能标记为 accepted,`resolved` 提醒不要误判为待处理阻塞。该刀只补人工审核记录的授权结论对齐,不改审批执行、不新增命令、不接 GUI 或云策略。 -- 2026-05-05:继续第八十八刀 `Phase 5/6 review decision API permission confirmation contract`:`agent_runtime_export_review_decision_template` / `agent_runtime_save_review_decision` 的返回模型现在把 `permissionConfirmation*` 摘要提升到 API 顶层,前端 `AgentRuntimeReviewDecisionTemplate` 类型、normalizer、DevBridge mock 与 `src/lib/api/agent.test.ts` 已同步覆盖 camelCase / snake_case,GUI/API 读取 review decision 时不会再丢掉 denied/resolved 权限确认结论。该刀只固定读取契约,不改 UI 交互、不改审批执行、不新增命令、不接云策略。 -- 2026-05-05:继续第八十九刀 `Phase 5/6 review decision GUI permission confirmation surface`:HarnessStatusPanel 的人工审核记录卡片现在直接展示 `permissionConfirmationStatus / Summary`,`denied` 会出现红色阻断提示,提醒当前 review decision 不能作为成功交付证据;对应组件回归固定了权限确认文案。该刀只把已有 API 字段接到 GUI 可见面,不改审批执行、不新增命令、不接云策略。 -- 2026-05-05:继续第九十刀 `Phase 5/6 review decision dialog permission confirmation guardrail`:`RuntimeReviewDecisionDialog` 现在在填写人工审核结果前展示同一份 `permissionConfirmationStatus / Summary / request_id`,`denied` 使用阻断提示说明当前 review decision 不能作为成功交付证据;HarnessStatusPanel 回归覆盖弹窗里的权限确认文案。该刀只把已有 API 字段补到人工审核填写入口,不改审批执行、不新增命令、不接云策略。 -- 2026-05-05:继续第九十一刀 `Phase 5/6 review decision denied acceptance guardrail`:`RuntimeReviewDecisionDialog` 在 `permissionConfirmationStatus=denied` 时会禁用“接受”选项,并在保存前阻止 `accepted` 结论写回;用户仍可保存拒绝、延后或需要更多证据的人工审核结果。HarnessStatusPanel 回归覆盖 denied 时不能保存 accepted、切换 rejected 后可正常保存。该刀只守住 review decision 写回语义,不改真实审批执行、不新增命令、不接云策略。 -- 2026-05-05:继续第九十二刀 `Phase 5/6 review decision save API denied acceptance guardrail`:Rust `save_runtime_review_decision` 现在在 `permissionConfirmationStatus=denied` 且写入 `decisionStatus=accepted` 时直接返回错误,防止 API / SceneApp / 测试绕过 GUI 把被拒绝权限确认沉淀成成功交付结论;`rejected / deferred / needs_more_evidence` 仍可保存,Rust 回归覆盖 accepted 被拒与 rejected 可保存。该刀只守住 review decision 写回事实源,不改审批执行、不新增命令、不接云策略。 -- 2026-05-05:继续第九十三刀 `Phase 5/6 review decision mock/API denied acceptance guardrail`:浏览器 `tauri-mock` 的 `agent_runtime_save_review_decision` 现在与 Rust save API 对齐,默认 denied 权限确认下保存 `accepted` 会抛错,保存 `rejected` 仍返回 denied 权限确认摘要;前端 API 回归确认后端 denied 错误会透传给调用方。该刀防止 DevBridge fallback / 浏览器测试链路假装 denied+accepted 成功,不改审批执行、不新增命令、不接云策略。 -- 2026-05-05:继续第九十四刀 `Phase 7 entry binding inventory guardrail`:新增 `entry-binding-inventory.md` 并把 Phase 7 验收落进 `check-modality-runtime-contracts.mjs`,要求所有 current contract 至少有一个 entry binding、entry key 全局唯一、`entry_source` 只能引用同一 contract 下的入口、`launch_metadata_path` 只能停留在 `harness.*`,且 scene entry 只有声明 `client_scenes / scene_policy` 后才允许登记;`/scene-key` 明确保持 planned,等待 LimeCore Scene catalog 与 audit contract 接齐后再进入 current。该刀只收口入口绑定事实源,不新增 `@` 命令、不改执行器、不接云 run/poll。 -- 2026-05-05:继续第九十五刀 `Phase 8 task index inventory guardrail`:新增 `task-index-inventory.md`,并把 task index 最低验收落进 `check-modality-runtime-contracts.mjs`:所有 current / partial artifact kind 必须声明 `task_id / contract_key / artifact_kind / status / created_at / updated_at`,且 `task_index_fields` 不允许重复。文档同时明确 `thread_id / turn_id / content_id / entry_key / model_id / executor_kind / cost_state / limit_state / limecore_policy_snapshot` 仍未统一稳定化,下一刀再从 `runtime_contract / entry_source / task_profile / policy snapshot` 回填查询维度。该刀只收口任务索引事实源,不新增执行器、不改 `@` 命令、不接云 run/poll。 -- 2026-05-05:继续第九十六刀 `Phase 8 task index entry_key projection`:`list_media_task_artifacts.modality_runtime_contracts` 现在会把媒体 task payload 中的 `entry_key / entry_source` 归一投影为 snapshot `entry_key`,并汇总 `entry_keys`;`image_task / image_output / audio_task / audio_output / transcript` 的 artifact graph 索引声明与机器守卫同步要求 `entry_key`,前端类型、浏览器 fallback mock 与 mediaTasks / tauri-mock 回归已同步。该刀只稳定媒体任务查询维度,不新增执行器、不改上层 `@` 命令、不接 LimeCore 云 run/poll。 -- 2026-05-05:继续第九十七刀 `Phase 8 task index executor policy dimensions`:`list_media_task_artifacts.modality_runtime_contracts` 现在汇总 `executor_kinds / executor_binding_keys`,媒体 artifact graph 与机器守卫同步要求 `entry_key / executor_kind / executor_binding_key / limecore_policy_snapshot_status`;前端类型、浏览器 fallback mock、mediaTasks 与 tauri-mock 回归已覆盖这些查询维度。该刀只把已有 runtime contract snapshot 投影为任务索引字段,不新增执行器、不改变上层 `@` 命令、不把本地默认 policy snapshot 伪造成 LimeCore 云策略结论。 -- 2026-05-05:继续第九十八刀 `Phase 8 task index runtime identity anchors`:媒体任务创建请求、task payload、Rust `list_media_task_artifacts.modality_runtime_contracts`、前端类型与浏览器 fallback mock 现在同步承载 `thread_id / turn_id / content_id`,并汇总为 `thread_ids / turn_ids / content_ids`;媒体 artifact graph 与机器守卫同步要求这组运行身份锚点。该刀只把已有媒体任务身份字段接入查询索引,不新增命令、不改变上层 `@` 命令,也不把非媒体 Evidence / Replay artifact 伪装成已完成。 -- 2026-05-05:继续第九十九刀 `Phase 8 task index modality skill model dimensions`:媒体任务索引现在从 task payload / runtime contract 投影 `modality / skill_id / model_id`,并汇总为 `modalities / skill_ids / model_ids`;`skill_id` 优先读取显式 payload 字段,缺省时只对 `skill / service_skill` executor 使用 `executor_binding_key` 作为当前查询锚点。媒体 artifact graph 与机器守卫同步要求这三个字段。该刀只稳定任务查询维度,不新增执行器、不改上层 `@` 命令,也不把非媒体 Evidence / Replay artifact 伪装成已完成。 -- 2026-05-05:继续第一百刀 `Phase 8 task index cost limit summaries`:媒体任务索引现在从 task payload、`runtime_summary` 与 `task_profile` 中读取 `cost_state / limit_state` 摘要,并汇总 `cost_states / limit_states / estimated_cost_classes / limit_event_kinds / quota_low_count`;snapshot 同步输出 `cost_state / limit_state / estimated_cost_class / limit_event_kind / quota_low`。媒体 artifact graph 与机器守卫同步要求这组成本/限额查询字段;同轮补齐 `creation_tools` 构造媒体任务请求时的 `thread_id / turn_id` 透传,避免第九十八刀新增身份锚点后 Rust 字面量编译漂移。该刀只稳定已有摘要的任务索引口径,不新增 Tauri command、不接 LimeCore 云 run/poll、不把上层 `@` 命令变成底层事实源。 -- 2026-05-05:继续第一百零一刀 `Phase 8 evidence taskIndex convergence`:Evidence Pack 的 `modalityRuntimeContracts.snapshotIndex` 新增 `taskIndex`,把 Browser / PDF / Web Research / Text Transform / Voice Service 等非媒体 runtime contract snapshot 的 `thread_id / turn_id / content_id / entry_key / modality / skill_id / model_id / executor_kind / executor_binding_key / cost_state / limit_state / estimated_cost_class / limit_event_kind / quota_low` 归一到与媒体任务索引一致的查询口径;前端 `AgentRuntimeEvidencePack` 类型与 normalizer 同步解析该索引。该刀只收敛 Evidence 审计事实源,不新增 Tauri command、不碰上层 `@` 命令、不接 LimeCore 云 run/poll;Replay / grader 消费同一 `taskIndex` 仍作为下一步收口。 -- 2026-05-05:继续第一百零二刀 `Phase 8 replay taskIndex consumption`:Replay case 现在消费 Evidence `snapshotIndex.taskIndex`,在 `input.json.runtimeContext.runtimeFacts.modalityTaskIndex` 输出 identity / executor / cost-limit compact 摘要,suite tags 增加 `modality-task-index / modality-task-identity / modality-task-cost-limit`,`expected.json` 与 `grader.md` 会要求保留 thread/turn/content/entry、executor binding 与 cost/limit 摘要;缺少 `taskIndex` 的多模态合同会生成 blocking check。该刀只把第 101 刀的 Evidence 索引接入复盘验收,不新增命令、不碰上层 `@`、不接云 run/poll;任务中心 / 客服诊断消费非媒体索引仍作为下一步。 -- 2026-05-05:继续第一百零三刀 `Phase 8 harness diagnostic taskIndex surface`:HarnessStatusPanel 的 Evidence Pack 区块新增“多模态任务索引”卡片,直接消费 `observability_summary.modality_runtime_contracts.snapshot_index.task_index`,展示 identity anchors、executor dimensions、cost/limit 统计与最近 `items[]`,并补组件回归覆盖 `thread/content/binding/limit` 可见。该刀只把既有 Evidence taskIndex 接入客服/开发诊断面板,不新增命令、不改 `@`、不接云 run/poll;任务中心过滤非媒体 artifact 仍作为下一步。 -- 2026-05-05:继续第一百零四刀 `Phase 8 taskIndex query model`:新增 `src/lib/agentRuntime/modalityTaskIndexPresentation.ts`,把 Evidence `snapshotIndex.taskIndex` 统一转换为任务中心可复用的 facets、rows 与 exact filters,并让 HarnessStatusPanel 的“多模态任务索引”卡片复用同一查询模型而不是本地临时汇总。该刀只建立非媒体任务索引的前端查询消费层,不新增命令、不碰上层 `@`、不接 LimeCore 云 run/poll;完整任务中心列表 UI 接入仍作为 Phase 8 收尾项。 -- 2026-05-05:继续第一百零五刀 `Phase 8 taskIndex task center filter surface`:HarnessStatusPanel 的“多模态任务索引”卡片新增“任务中心过滤列表”,直接消费 `modalityTaskIndexPresentation.rows`,支持按 entry、content、executor、cost、limit 过滤非媒体任务行,并展示过滤命中数与完整 artifact path。该刀把第 104 刀查询模型落成可见任务中心过滤 UI,不新增命令、不碰上层 `@`、不接 LimeCore 云 run/poll;后续若新增独立主任务中心入口,只能复用同一 rows。 -- 2026-05-05:继续第一百零六刀 `Phase 8 taskIndex surface cleanup guard`:把第 105 刀内联在 HarnessStatusPanel 的 taskIndex 列表/过滤 UI 抽成 `HarnessTaskIndexSection`,HarnessStatusPanel 只保留挂载面;`check-modality-runtime-contracts.mjs` 新增 `task index presentation guard`,要求 `modalityTaskIndexPresentation` 继续导出 facets / rows / filters、section 必须消费这些 helper,且禁止 HarnessStatusPanel 重新内联 taskIndex 查询/list UI。该刀是治理减法和守卫,不新增命令、不碰上层 `@`、不接云 run/poll。 -- 2026-05-05:继续第一百零七刀 `Phase 8 taskIndex section regression split`:新增 `HarnessTaskIndexSection.test.tsx`,独立覆盖 taskIndex 摘要、任务中心过滤列表、entry 过滤与清空过滤;`HarnessStatusPanel.test.tsx` 只保留 evidence pack 挂载与关键文案断言,不再承载 taskIndex 过滤交互细节。该刀继续收口测试边界,让 taskIndex UI 的回归跟随 current section,而不是依赖巨型面板测试;不新增命令、不碰上层 `@`、不接云 run/poll。 -- 2026-05-05:继续第一百零八刀 `Phase 5/6 unresolved permission delivery block`:Evidence Pack 现在把 `requires_confirmation` 且 `confirmationStatus=not_requested / requested` 的权限状态标为 `signalCoverage.permissionState=blocked`,`knownGaps` 同步输出“尚未发起 ApprovalRequest”或“真实权限确认等待处理”的交付阻断说明;Replay 补回归固定 `not_requested` 会生成 blocking check,`resolved` 仍不阻断。该刀只推进审计/复盘/交付判定事实源,不伪造 `ApprovalRequest`、不改变 native approval 行为、不阻断 turn 执行、不新增命令、不接 LimeCore 云策略。 -- 2026-05-05:继续第一百零九刀 `Phase 5/6 unresolved permission review decision guardrail`:`save_runtime_review_decision` 现在不只阻止 `denied + accepted`,也会在 `requires_confirmation` 且 `confirmationStatus=not_requested / requested / 未解决` 时拒绝保存 `accepted`;Review decision checklist / suggested actions 同步提示未解决权限确认不能作为成功交付证据,前端填写弹窗与浏览器 mock 也改为“权限确认未解决时不能保存接受”。该刀守住第 108 刀 Evidence / Replay 阻断语义的写回边界,不伪造 `ApprovalRequest`、不改变 native approval 行为、不阻断 turn 执行、不新增命令、不接 LimeCore 云策略。 -- 2026-05-05:继续第一百一十刀 `Phase 5/6 unresolved permission handoff analysis risk`:Handoff bundle 与 Analysis handoff 现在把 `not_requested / requested / denied` 未解决权限确认统一视为交付阻断风险;`plan.md / handoff.md / review-summary.md`、analysis brief、analysis context 与 copy prompt 会显示“权限确认尚未解决 / 尚未发起真实审批请求 / 不能作为成功交付证据”,`resolved` 仍保持非阻断。该刀把第 108 刀 Evidence / Replay 阻断事实同步到交接与外部分析入口,不伪造 `ApprovalRequest`、不改变 native approval 行为、不阻断 turn 执行、不新增命令、不接 LimeCore 云策略。 -- 2026-05-05:继续第一百一十一刀 `Phase 5/6 unresolved permission turn gating`:`runtime_turn` 现在会在 prelude 发出 `permission_review` 状态后、模型流真正开始前读取同一 `lime_runtime.permission_state`,当 `status=requires_confirmation` 且 `confirmationStatus` 不是 `resolved` 时把 turn 标为 failed 并发送错误事件;`permission_review` 文案同步说明未解决确认会阻断模型执行,`resolved` 才允许继续。该刀不伪造 `ApprovalRequest`、不新增 Tauri command、不接 LimeCore 云 run/poll,也不碰上层 `@` 命令;用户确认/恢复入口留给下一刀。 -- 2026-05-05:继续第一百一十二刀 `Phase 5/6 permission confirmation request recovery`:runtime turn 在未 resolved 的 `requires_confirmation` 阻断前,会为 `confirmationStatus=not_requested` 且尚无 request id 的权限摘要写入真实 `runtime_permission_confirmation:` / `RequestUserInput(elicitation)` timeline item,并发送同源 `action_required`;响应复用既有 `agent_runtime_respond_action`,只对该前缀请求写回 completed response,不新增 Tauri command,也不把它伪装成工具 `ApprovalRequest`。下一轮恢复请求会从同一 session detail 读取最近权限确认 item,把 response 派生为 `confirmationStatus=resolved/denied`、真实 request id 与 `runtime_action_required` 来源,再交给同一 turn gating 判定;这完成的是本地最小确认恢复闭环,完整权限系统、同 turn 自动恢复、用户锁定 gap 确认式恢复、云端 policy evaluator 与真实 Gateway adapter 仍后置。 -- 2026-05-05:继续第一百一十三刀 `Phase 5/6 user locked capability gap turn gating`:`request_model_resolution` 现在会给显式用户模型锁定导致的 runtime capability gap 标记 `capability_gap_source=explicit_model_lock`,并把 `limit_state.status` 收敛为 `user_locked_capability_gap`;`runtime_turn` 在 prelude 后、模型执行前读取同一 `lime_runtime.limit_state`,命中该状态时发出 routing runtime status、标记 turn failed 并发送错误事件,要求用户切换到满足 `routingSlot` 的模型或取消本轮显式锁定。该刀只把第 73 刀的 user lock gap 从解释推进为执行前阻断,不新增 Tauri command、不接 LimeCore 云 run/poll、不触碰上层 `@` 命令;确认式恢复与更完整 GUI 仍后置。 -- 2026-05-06:继续第一百一十四刀 `Phase 5/6 user locked capability offline delivery block`:`user_locked_capability_gap` 现在不只 live turn 阻断,Evidence Pack `knownGaps`、Replay blocking checks、Handoff bundle、Analysis handoff 与 Review decision 也会同步把它视为不能成功交付的阻断事实;Review decision 读取 `limitStatus / capabilityGap / userLockedCapabilitySummary` 后会提示切换满足 `routingSlot` 的模型或取消显式锁定,并在保存 `accepted` 时由 Rust API 直接拒绝。该刀只把第 113 刀的执行前阻断补齐到离线审计 / 复盘 / 交接 / 外部分析 / 人工审核写回链,不新增命令、不接 LimeCore 云 run/poll、不碰上层 `@` 命令;用户锁定 gap 的确认式恢复与 GUI 自动恢复仍后置。 -- 2026-05-06:继续第一百一十五刀 `Phase 5/6 user locked capability review API surface`:前端 `AgentRuntimeReviewDecisionTemplate` 与 normalizer 现在保留 `limitStatus / capabilityGap / userLockedCapabilitySummary`,DevBridge / browser mock 的 `agent_runtime_save_review_decision` 也会在 `limit_status=user_locked_capability_gap` 且保存 `accepted` 时抛出同类阻断错误;Harness 人工审核卡片和填写弹窗同步展示“模型锁定能力缺口”,并禁用 / 阻止“接受”结论。该刀把第 114 刀 Rust 离线阻断接到 API / Mock / GUI 读取与写回面,不新增命令、不接云 run/poll、不做独立任务中心或上层 `@` 入口。 -- 2026-05-06:继续第一百一十六刀 `Phase 5/6 user locked capability confirmation recovery`:`runtime_turn` 现在会在 `user_locked_capability_gap` 执行前阻断时写入真实 `runtime_user_lock_capability:` / `RequestUserInput(elicitation)`,响应继续复用既有 `agent_runtime_respond_action` 写回 completed response,不新增 Tauri command、不伪造 `ApprovalRequest`;下一轮同 `turn_id` 恢复请求会读取 completed response,把用户确认投影为 `user_lock_capability_recovery(status=resolved/denied)`,其中 `resolved` 会释放本轮显式 `provider/model` 偏好并重新走 provider/model resolution,`denied` 保持阻断。该刀只完成本地最小确认式恢复,不接 LimeCore 云 run/poll、不扩上层 `@`,完整 GUI 自动重试与云端策略授权继续后置。 diff --git a/docs/exec-plans/oem-cloud-commerce-loop-progress.md b/docs/exec-plans/oem-cloud-commerce-loop-progress.md deleted file mode 100644 index c068f0cb3..000000000 --- a/docs/exec-plans/oem-cloud-commerce-loop-progress.md +++ /dev/null @@ -1,29 +0,0 @@ -# OEM 云端商业闭环推进记录 - -## 主目标 - -把 Lime 客户端与 LimeCore 的云端购买链路收敛为单一 current 主链:套餐/充值下单 -> 真实支付 checkout -> 支付渠道 webhook -> 权益/积分/账本刷新 -> API Key 与网关使用。 - -## 当前阶段 - -- `current`:`useOemCloudAccess` 消费 `/client/cloud-activation`、订单、充值单、账本、支付配置与访问令牌,客户端不再本地兜底套餐、渠道或模型目录。 -- `current`:支付完成后优先通过 LimeCore HTTPS `payments/{provider}/return` bridge 回到客户端,再 302 到 `lime://payment/return`,触发云端状态刷新和订单 watcher。 -- `dead`:旧的客户端支付后台密钥配置入口已从设置页主链移除,管理型支付配置只保留在服务端管理面。 - -## 2026-04-28 进度 - -- 新增 `src/lib/oemCloudPaymentReturn.ts`,统一生成、解析、暂存和分发云端支付回跳事件。 -- `useDeepLink` 识别 `lime://payment/return`,不走旧 `handle_deep_link` 命令,直接分发 current 云端商业刷新事件。 -- `useOemCloudAccess` 在套餐购买和积分充值 checkout 中传入 `successUrl` / `cancelUrl`,支付页回跳后自动刷新云端权益、积分余额与账本,并重新接上订单 watcher。 -- 增加回归覆盖 deep link 分发、checkout 回跳 URL、支付回跳后刷新商业状态。 - -## 2026-04-28 追加进度 - -- LimeCore 新增公开 HTTPS bridge:`/api/v1/public/tenants/{tenantId}/payments/{provider}/return`,支持 GET 与 form POST。 -- bridge 只组装并 302 到 `lime://payment/return`,不在回跳页确认支付;真实权益发放仍只由 provider webhook 驱动。 -- Lime 客户端 checkout 回跳 URL 改为 HTTPS bridge,保留客户端 deep link 消费和状态刷新逻辑。 -- Creem checkout 已接入官方 `success_url` 参数,成功回跳进入 HTTPS bridge;取消回跳不伪造本地结果,继续依赖 watcher 与 webhook 后的服务端状态。 - -## 下一刀 - -继续用真实渠道沙箱串一次 EPay / Stripe / Creem / Waffo,确认各渠道回跳是否都能回到 `lime://payment/return`,同时验证 webhook finalize 后客户端账本、积分和权益刷新一致。 diff --git a/docs/exec-plans/old-session-open-performance-plan.md b/docs/exec-plans/old-session-open-performance-plan.md deleted file mode 100644 index 896c9cc0e..000000000 --- a/docs/exec-plans/old-session-open-performance-plan.md +++ /dev/null @@ -1,192 +0,0 @@ -# 旧会话打开性能优化计划 - -## 目标 - -降低打开旧对话的首帧等待和后续 invoke 争抢,优先保证旧会话能快速显示目标会话与最近消息,再逐步补齐历史与执行轨迹。 - -## 当前进度 - -- `P0` 已完成:所有非显式全量的 `getSession` 调用补齐 `historyLimit: 40`,避免静默恢复和 missing-from-topics 校验拉取全量历史。 -- `P1` 已完成:会话元数据 fallback 回填合并为一次 `updateSessionMetadata`;无本地快照切换时先进入目标会话 hydrating shell;侧边栏 focus refresh 降低为 idle 后台任务。 -- `P2` 已推进:加载更多历史已从递增 tail window 改为分页加载;首屏返回最近 `40` 条并带 `history_cursor.oldest_message_id`,加载更早历史时优先用 `historyBeforeMessageId` cursor,每次请求 `50` 条,`historyOffset` 保留为兼容 fallback;历史会话的 MessageList 首帧先渲染文本,timeline 在 idle 后补齐;timeline turn 绑定减少中间数组分配;折叠的 `AgentThreadTimeline` 明细改为展开时再物化;旧历史中已完成的单步 timeline 明细默认只渲染摘要,展开时再物化;已排序的 turn/thread item 不再重复复制排序。 -- `2026-04-29` 追加收口:过大的旧会话 transient / persisted snapshot 在恢复前直接丢弃;读取命中的会话快照不再同步刷新 `lastAccessedAt` 以避免点击时重写整张 snapshot map;历史消息与流式 text_delta 统一做 overlap 合并,修复累计快照式 delta 导致的重复吐字;完成态旧消息的执行过程与正文视觉分离,历史 timeline 默认折叠明细;浏览器 DevBridge 模式下跳过低优先级 metadata backfill,并且仅在活跃运行时订阅 team SSE,避免旧会话点击后抢占 bridge 连接。 - -- `2026-04-29` 追加 GUI 收口:复现旧会话顶部 `+` 新建后新 tab 仍显示旧消息的问题;`createFreshSession` 现在显式清空新建会话消息快照,同时 `ensureSession` 的首轮发送保留本地草稿,避免发送链路回归;旧会话 MessageList 仅在活跃发送/等待态底部锚定,已完成历史默认吸顶。 -- `2026-04-29` 追加任务中心收口:复现旧会话中点击侧栏会话/顶部标签后被 `initialSessionId` 路由抢回的问题;任务中心本地切换现在在 `switchTopic` 前先标记 local override,失败时再回滚,避免异步切换期间显示旧 tab 或空态。 -- `2026-04-29` 追加发送中吸顶收口:复现用户首条消息发送中仍贴近输入区、完成后才跳到上方的问题;MessageList 现在无论发送中、排队中还是完成态都保持 `justify-start`,避免完成前后布局跳动。 -- `2026-04-29` 追加一级新建任务收口:任务中心内点击侧栏一级 `新建任务` 现在与对话架 `新建对话` 复用同一个可取消草稿事件;只有任务中心真实接管后才阻止路由,避免旧会话 A 新增草稿、切到旧会话 B 后再次点击侧栏新建时误跳回 `new-task-home`。 - -## 剩余事项 - -- Cursor 分页已完成:`agent_runtime_get_session` 继续作为 current 主链,新增 `historyBeforeMessageId` 请求字段与 `history_cursor` 响应字段;无 cursor 或缓存恢复缺少 cursor 时继续 fallback 到 `historyOffset`。 -- 若用户仍反馈旧会话卡顿,再对 `AgentThreadTimeline` 内部渲染和 thread item 展开策略做专项测量。 -- 若后续仍有 CPU / 内存尖峰,下一刀优先检查真实旧会话中是否存在超长 artifact / markdown 表格渲染,以及 `StreamingRenderer` 首屏 markdown 解析成本。 -- `verify:local` 已完成通过;此前内嵌 smoke / 后续 smoke 重试中遇到的 DevBridge `fetch failed` 与临时 target 链接 `liblime_lib.dylib` 打开失败,已通过后续重跑消除,按历史环境/并发构建插曲保留记录。 - -## 验证记录 - -- `npm test -- src/components/agent/chat/utils/threadTimelineView.test.ts src/components/agent/chat/components/MessageList.test.tsx` 通过。 -- `npm test -- src/components/agent/chat/hooks/agentRuntimeAdapter.test.ts src/components/agent/chat/hooks/agentSessionRefresh.test.ts src/components/agent/chat/hooks/useAsterAgentChat.test.tsx src/components/AppSidebar.test.tsx src/components/agent/chat/components/MessageList.test.tsx src/components/agent/chat/utils/threadTimelineView.test.ts` 通过。 -- `npm run typecheck` 通过。 -- `npm run lint` 通过。 -- `cargo check --manifest-path src-tauri/Cargo.toml -p lime-services` 通过;期间修正 `api_key_provider_service.rs` 对运行时 Provider DTO 的显式导入,避免旧凭证池模型导出边界影响编译。 -- `npm run verify:gui-smoke` 通过。 -- `npm run generate:agent-runtime-clients` 通过,已更新 `agent_runtime_get_session` generated manifest。 -- `npm test -- src/components/agent/chat/hooks/agentChatHistory.test.ts src/components/agent/chat/hooks/useAsterAgentChat.test.tsx` 通过。 -- `cargo test --manifest-path src-tauri/Cargo.toml -p lime-core tail -- --nocapture` 通过。 -- `cargo test --manifest-path src-tauri/Cargo.toml -p lime-agent history_tail -- --nocapture` 通过。 -- `cargo test --manifest-path src-tauri/Cargo.toml -p lime-agent get_session_sync_with_history_limit_should_tail_persisted_history -- --nocapture` 通过。 -- `cargo test --manifest-path src-tauri/Cargo.toml normalize_runtime_session_history -- --nocapture` 通过。 -- `npx eslint "src/lib/api/agentRuntime.ts" "src/lib/api/agentRuntime/*.ts" "src/components/agent/chat/hooks/agentChatHistory.ts" "src/components/agent/chat/hooks/useAgentSession.ts" "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" --max-warnings 0` 通过。 -- `npm run test:contracts` 通过。 -- `npm run generate:agent-runtime-clients` 通过,已同步 `historyBeforeMessageId` generated manifest。 -- `npm test -- src/components/agent/chat/hooks/agentChatHistory.test.ts src/components/agent/chat/hooks/useAsterAgentChat.test.tsx` 通过(新增 cursor 起始索引与加载更早历史 cursor 请求断言)。 -- `npm test -- src/lib/api/agent.test.ts src/components/agent/chat/hooks/agentRuntimeAdapter.test.ts` 通过。 -- `cargo test --manifest-path src-tauri/Cargo.toml -p lime-core tail -- --nocapture` 通过。 -- `cargo test --manifest-path src-tauri/Cargo.toml -p lime-agent history_tail -- --nocapture` 通过。 -- `cargo test --manifest-path src-tauri/Cargo.toml -p lime-agent get_session_sync_with_history_limit_should_tail_persisted_history -- --nocapture` 通过。 -- `cargo test --manifest-path src-tauri/Cargo.toml normalize_runtime_session_history -- --nocapture` 通过。 -- `cargo test --manifest-path src-tauri/Cargo.toml should_skip_runtime_queue_snapshots_for_cursor_history_page -- --nocapture` 通过;首次重跑曾撞到并发修改/编译中的 `runtime_evidence_pack_service.rs`,随后重跑通过。 -- `npx eslint "src/lib/api/agentRuntime.ts" "src/lib/api/agentRuntime/*.ts" "src/components/agent/chat/hooks/useAgentSession.ts" "src/components/agent/chat/hooks/agentChatHistory.ts" --max-warnings 0` 通过。 -- `npm run typecheck` 通过。 -- `npm run test:contracts` 通过。 -- `npm run verify:local` 前置检查、前端测试、Rust 全量测试均通过;最后内嵌 `verify:gui-smoke` 因 DevBridge `fetch failed` 中断。 -- `npm run verify:gui-smoke` 后续重试在 headless Tauri 链接阶段失败,关键错误为临时 target 下 `liblime_lib.dylib` 打开失败;同命令此前已单独通过。 -- `npm test -- src/components/agent/chat/components/AgentThreadTimeline.test.tsx src/components/agent/chat/components/MessageList.test.tsx` 通过。 -- `npx eslint "src/components/agent/chat/components/AgentThreadTimeline.tsx" "src/components/agent/chat/components/AgentThreadTimeline.test.tsx" "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" --max-warnings 0` 通过。 -- `npm test -- src/components/agent/chat/utils/threadTimelineView.test.ts src/components/agent/chat/components/MessageList.test.tsx` 通过。 -- `npx eslint "src/components/agent/chat/utils/threadTimelineView.ts" "src/components/agent/chat/utils/threadTimelineView.test.ts" "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" --max-warnings 0` 通过。 -- `npm run typecheck` 通过。 -- `npm run verify:local` 通过;覆盖 `verify:app-version`、`lint`、`typecheck`、全量前端测试、`test:contracts`、全量 Rust 测试与内嵌 `verify:gui-smoke`。 -- `npm test -- src/components/agent/chat/components/AgentThreadTimeline.test.tsx src/components/agent/chat/components/MessageList.test.tsx` 通过(新增旧历史单步 timeline 展开后再物化明细断言)。 -- `npx eslint "src/components/agent/chat/components/AgentThreadTimeline.tsx" "src/components/agent/chat/components/AgentThreadTimeline.test.tsx" "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" --max-warnings 0` 通过。 -- `npm run typecheck` 通过。 -- `npm run verify:gui-smoke` 通过。 -- `npm test -- src/components/agent/chat/components/AgentThreadTimeline.test.tsx src/components/agent/chat/components/MessageList.test.tsx src/components/agent/chat/hooks/agentChatHistory.test.ts src/components/agent/chat/hooks/agentChatStorage.test.ts src/components/agent/chat/hooks/agentSessionScopedStorage.test.ts src/components/agent/chat/hooks/useAgentRuntimeSyncEffects.test.tsx src/components/agent/chat/hooks/useAsterAgentChat.test.tsx` 通过(7 files / 293 tests)。 -- `npx eslint "src/components/agent/chat/hooks/useAgentSession.ts" "src/components/agent/chat/hooks/useAgentRuntimeSyncEffects.ts" "src/components/agent/chat/hooks/useAgentRuntimeSyncEffects.test.tsx" "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" "src/components/agent/chat/hooks/agentChatHistory.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "src/components/agent/chat/hooks/skillCommand.ts" "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/AgentThreadTimeline.tsx" "src/components/agent/chat/hooks/agentChatStorage.ts" "src/components/agent/chat/hooks/agentSessionScopedStorage.ts" "src/components/agent/chat/hooks/agentChatHistory.test.ts" "src/components/agent/chat/components/MessageList.test.tsx" "src/components/agent/chat/components/AgentThreadTimeline.test.tsx" "src/components/agent/chat/hooks/agentChatStorage.test.ts" "src/components/agent/chat/hooks/agentSessionScopedStorage.test.ts" --max-warnings 0` 通过。 -- `npm run bridge:health -- --timeout-ms 120000` 通过,DevBridge `/health` 约 `20ms` 就绪。 -- Playwright E2E(`http://127.0.0.1:1420/`):连续切换 `E2E layout anchor -> 你好!👋 很高兴见到你! -> 你好!有什么我可以帮你的吗?😊 -> E2E layout anchor`,每次 `restoring=0`,耗时约 `109-425ms`,`body/html cursor=auto`,最终 `heap≈121MB`;`assistant-primary-timeline-shell` 高度 `94px`,`openDetails=0`,最终正文不在执行过程 shell 内,未检测到 assistant greeting 重复;等待 `9s` 后 `eventRequests=0`,控制台 `0 error / 1 warning`(仅浏览器模式 i18n 默认语言提示)。 -- `npx vitest run "src/components/agent/chat/components/MessageList.test.tsx" "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx"` 通过(2 files / 230 tests),覆盖旧会话吸顶、新建任务清空旧消息与首轮发送草稿保留。 -- `npx eslint "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" "src/components/agent/chat/hooks/useAgentSession.ts" "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" --max-warnings 0` 通过。 -- Playwright E2E(`http://127.0.0.1:1420/`):从新建空态点击侧边栏 `E2E layout anchor`,旧会话约 `237-331ms` 可见且 `message-list-column` 为 `justify-start`;再点击顶部 `+` 或侧边栏 `新建任务` 均回到 `青柠一下,灵感即来` 空态,旧会话文本不可见,`body cursor=auto`。本轮仅剩 DevBridge 偶发 `get_local_skills_for_app` / `project_memory_get` 1800ms timeout 控制台噪音,主交互未阻塞。 -- Playwright E2E(`http://127.0.0.1:1420/`):从首页点击侧栏 `E2E layout anchor` 约 `419ms` 可见旧会话;从空态点击顶部旧会话标签约 `304ms` 可见旧会话;旧会话中点击顶部 `+` 约 `124ms` 回到新建空态;旧会话中点击侧栏 `新建任务` 约 `106ms` 回到新建空态;旧会话 `message-list-column` 保持 `justify-start`,`cursor=auto`,控制台 `0 error / 0 warning`。 -- `npx vitest run "src/components/agent/chat/index.test.tsx" -t "任务中心初始会话标签"` 通过(7 tests),覆盖任务中心切到非路由会话时不被 `initialSessionId` 抢回。 -- `npx vitest run "src/components/agent/chat/index.test.tsx" "src/components/agent/chat/components/MessageList.test.tsx" "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx"` 通过(3 files / 326 tests)。 -- `npx eslint "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/index.test.tsx" "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" "src/components/agent/chat/hooks/useAgentSession.ts" "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" --max-warnings 0` 通过。 -- `npm run typecheck` 通过。 -- `npm run verify:gui-smoke` 通过。 -- `git diff --check -- src/components/agent/chat/AgentChatWorkspace.tsx src/components/agent/chat/index.test.tsx src/components/agent/chat/components/MessageList.tsx src/components/agent/chat/components/MessageList.test.tsx src/components/agent/chat/hooks/useAgentSession.ts src/components/agent/chat/hooks/useAsterAgentChat.test.tsx docs/exec-plans/old-session-open-performance-plan.md` 通过。 -- `npm run verify:local` 通过;覆盖 `verify:app-version`、`lint`、`typecheck`、全量前端测试、`test:contracts`、全量 Rust 测试与内嵌 `verify:gui-smoke`。 -- Playwright E2E 复测(`http://127.0.0.1:1420/`):刷新后控制台 `0 error / 1 warning`(仅浏览器模式 i18n 默认语言提示);点击侧栏 `E2E layout anchor` 约 `133ms` 可见旧会话且 `message-list-column` 为 `justify-start`;随后点击侧栏 `新建任务` 约 `118ms` 回到 `青柠一下,灵感即来` 空态,旧消息不可见,`body/html cursor=auto`。 -- `npx vitest run "src/components/agent/chat/components/MessageList.test.tsx" -t "短对话发送首帧|任务中心发送首帧|旧会话短消息"` 通过,覆盖发送中短消息与任务中心发送首帧均吸顶。 -- `npx vitest run "src/components/agent/chat/index.test.tsx" -t "任务中心初始会话标签"` 通过(7 tests),并将顶部加号测试改为等待按钮就绪后点击,降低慢机环境下的偶发失败。 -- Playwright E2E 复测(`http://127.0.0.1:1420/`):发送 `吸顶测试,请只回复 OK。` 后立即采样、`250ms`、`1250ms` 均为 `message-list-column` `justify-start`,首条消息距滚动视口顶部约 `22px`,`scrollTop=0`,`body/html cursor=auto`,确认发送中首帧不再贴底;旧会话 `E2E layout anchor` 打开后 `message-list-column` 同样为 `justify-start`;侧栏 `新建任务` 约 `97ms` 回到 `青柠一下,灵感即来` 空态且旧消息不可见。刷新后控制台保持 `0 error / 1 warning`(仅浏览器模式 i18n 默认语言提示)。 -- `npx vitest run "src/components/agent/chat/components/MessageList.test.tsx" "src/lib/api/memory.test.ts" -t "短对话发送首帧|任务中心发送首帧|旧会话短消息|project_memory_get|项目记忆|短时间重复|并发读取"` 通过(2 files / 6 tests)。 -- `npx vitest run "src/components/agent/chat/index.test.tsx" -t "任务中心初始会话标签"` 通过(7 tests)。 -- `npx eslint "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/index.test.tsx" "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" "src/lib/api/memory.ts" "src/lib/api/memory.test.ts" --max-warnings 0` 通过。 -- `npm run verify:gui-smoke` 通过;复用现有 headless Tauri 与 DevBridge,workspace / browser-runtime / site-adapters / service-skill-entry / runtime tool-surface page smoke 均通过。 -- `2026-04-29` 追加浏览器式 Tab 收口:任务中心顶部 `+` 改为本地 `task-draft-*` 草稿 tab,点击阶段不再创建真实 session;`CustomEvent` 新建请求改为可取消事件,只有任务中心工作区实际接管后侧栏才停止路由跳转,避免侧栏 `新建任务` 在任务中心内误跳回 `new-task-home`。 -- `npx eslint "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/index.test.tsx" "src/components/agent/chat/taskCenterDraftTaskEvents.ts" "src/components/AppSidebar.tsx" "src/components/agent/chat/components/EmptyState.tsx" --max-warnings 0` 通过。 -- `npx vitest run "src/components/agent/chat/index.test.tsx" -t "任务中心初始会话标签"` 通过(8 tests),覆盖顶部加号和侧栏事件新建草稿 tab,不触发 `createFreshSession` / 路由跳出。 -- `npx tsc --noEmit --pretty false` 通过;同时修复本轮 E2E 中暴露的 `EmptyState` 首页组件 HMR 崩溃,刷新后控制台恢复到 `0 error / 1 warning`(浏览器模式 i18n 默认语言提示)。 -- Playwright E2E(`http://127.0.0.1:1420/`):从旧会话点击顶部 `+`,`task-center-tab-task-draft-*` 约 `77ms` active,`青柠一下,灵感即来` 约 `95ms` 可见;旧 `message-list-column` 不再渲染,旧消息不可见;invoke trace `10` 条,`createSessionCalls=0`,无 invoke error。 -- 本轮 GUI smoke 未完成:`npm run bridge:health -- --timeout-ms 120000` 因当前工作区并行 Rust 改动导致 DevBridge 未就绪而等待,`tauri:dev:headless` 日志显示 `src-tauri/src/commands/aster_agent_cmd/service_skill_launch.rs` 存在非本轮编译错误(`ServiceSceneLaunchContext` 缺字段、mutable borrow 冲突),需先收口该 Rust 改动后再重跑 `npm run verify:gui-smoke`。 -- `2026-04-29` 追加多旧会话切换复现:新增回归覆盖 `旧会话 A -> 顶部 + 新增草稿 -> 路由切到旧会话 B -> 再次顶部 +`。根因是路由 `initialSessionId` 切到真实旧会话时只替换真实 tab,没有清掉仍 active 的本地 draft id,导致旧会话 B tab 不是 active,后续新增状态被旧 draft 干扰;现在切到真实路由会话时仅取消 active draft,保留草稿 tab 列表。 -- `npx vitest run "src/components/agent/chat/index.test.tsx" -t "切到另一条旧会话后仍应继续新增本地草稿标签"` 通过。 -- `npx vitest run "src/components/agent/chat/index.test.tsx" -t "任务中心初始会话标签"` 通过(9 tests),覆盖顶部 +、侧栏事件、旧会话 A/B 切换后再次新增、路由抢回防护。 -- `npx eslint "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/index.test.tsx" "src/components/agent/chat/taskCenterDraftTaskEvents.ts" "src/components/AppSidebar.tsx" --max-warnings 0` 通过。 -- `npx tsc --noEmit --pretty false` 通过。 -- Playwright 真实旧会话 A/B 复测当前仍被 DevBridge 阻塞:页面控制台为 bridge 连接错误,`npm run bridge:health -- --timeout-ms 120000` 超时;阻塞仍来自非本轮 Rust 编译错误,需先恢复 `src-tauri/src/commands/aster_agent_cmd/service_skill_launch.rs` 后重测。 -- `npx vitest run "src/components/AppSidebar.test.tsx" -t "任务中心内点击一级新建任务"` 通过,覆盖任务中心内一级主导航 `新建任务` 被草稿事件接管且不触发路由跳转。 -- `npx vitest run "src/components/AppSidebar.test.tsx"` 通过(34 tests)。 -- `npx vitest run "src/components/agent/chat/index.test.tsx" -t "任务中心初始会话标签"` 通过(9 tests);首次与 AppSidebar 全量测试并行时出现一次顶部 `+` 慢机 transition 偶发断言,单独重跑与整组重跑均通过。 -- `npx eslint "src/components/AppSidebar.tsx" "src/components/AppSidebar.test.tsx" --max-warnings 0` 通过。 -- `npx tsc --noEmit --pretty false` 通过。 -- `git diff --check -- src/components/AppSidebar.tsx src/components/AppSidebar.test.tsx src/components/agent/chat/AgentChatWorkspace.tsx src/components/agent/chat/index.test.tsx src/components/agent/chat/taskCenterDraftTaskEvents.ts` 通过。 -- `npm run bridge:health -- --timeout-ms 120000` 重新通过;本轮先清理了当前仓库残留的并发 Tauri/Cargo dev 进程,随后 `DevBridge` 在 `http://127.0.0.1:3030/health` 返回 `status=ok`。 -- Playwright E2E(`http://127.0.0.1:1420/`):刷新首页后执行 `旧会话 A(E2E layout anchor) -> 侧栏一级新建任务 -> 旧会话 B(Lime 助手) -> 侧栏一级新建任务`;打开 A 约 `669ms`,A 后新建草稿约 `63ms`,打开 B 约 `213ms`,B 后新建草稿约 `50ms`。两次新建均激活 `task-center-tab-task-draft-*`,不会出现 active `task-center-tab-new-task-home`;第二次后保留 `2` 个 draft tab,旧会话 tab inactive,首页空态可见,`body/html cursor=auto`。 -- 同轮 Playwright invoke trace:总 `/invoke` `16` 次,`agent_runtime_create_session=0`;两次 `agent_runtime_get_session` 均携带 `historyLimit: 40`;侧栏列表仅一次 `agent_runtime_list_sessions`,`limit=37`;无 invoke error。控制台 `0 error / 2 warning`,warning 为浏览器模式事件流中止与 i18n 默认语言提示,均非主链阻塞。 -- `npm run verify:gui-smoke` 通过;复用现有 headless Tauri 与 DevBridge,workspace-ready、browser-runtime、site-adapters、service-skill-entry、runtime tool-surface 与 runtime tool-surface page smoke 均通过。 -- `npm run verify:local` 已执行到前端全量测试第 `26/43` 批后失败,失败集中在 `src/components/agent/chat/components/EmptyState.test.tsx` 的 `18` 条旧首页断言;实际渲染已切到新的 `HomeStartSurface` / `HomeSkillGallery` 首页文案与结构,属于本轮侧栏 tab 修复之外的首页改版测试漂移,需后续单独收口 EmptyState 测试或恢复对应首页能力。 -- `2026-04-30` 追加修复“无法打开两个历史对话”:根因是外层 `AppSidebar` 点击历史会话只做路由跳转,任务中心没有本地打开意图;随后 `AgentChatWorkspace` 的 `initialSessionId` 同步 effect 将 open tab map 替换为单个目标会话。现在侧栏点击历史会话会先发送 `lime:task-center:open-task` 事件,任务中心先乐观 upsert 目标 tab 并记录本地路由追平意图;路由追平时仅激活/前置目标 tab,不再替换掉已有历史 tab。 -- 同轮收口:任务中心内部 `handleOpenSidebarTaskTopic` / `handleResumeSidebarTask` / `handleResumeRecentSession` / fallback restore 默认走追加/激活语义,只有外部直达会话仍保留 replace 语义,避免旧缓存污染首开深链。 -- `2026-04-30` 追加旧会话卡顿收口:MessageList 对恢复中或已分页旧会话使用更小的首屏批次(20 条)和 idle 小批量补齐;已完成的旧会话最后一个 turn 不再按 current turn 处理,避免历史 timeline 在首帧被当作活跃执行过程同步展开。 -- `2026-04-30` 追加 invoke 降噪:`workspace_get` 增加 1s 短 TTL 与同 id in-flight 合并,避免旧会话切换期间工作区详情重复抢占 bridge;打开旧会话时自动回填的 `recent_preferences` / `recent_team_selection` 改为同 session 后台合并队列,12s 后 idle 再写,若期间已切走则直接丢弃,手动偏好修改仍保持即时低延迟同步。 -- `2026-04-30` 追加旧会话预取:侧边栏会话按钮在 focus / pointer enter / pointer down 时发送 task-center prefetch 事件,当前 Agent 工作区复用 `runtime.getSession(historyLimit: 40)` 预取结果;若用户随后点击同一会话,`switchTopic` 直接等待同一个 in-flight 详情请求,不再重复打 `agent_runtime_get_session`,并把预取结果写入本地 tail snapshot。话题列表就绪后还会在测试环境外 idle 预取最近 3 条非当前会话,降低无本地 snapshot 时的首次点击等待。 -- `2026-04-30` 追加路由恢复收口:从首页/侧栏通过 `initialSessionId` 进入旧会话时不再默认 `forceRefresh`,仅 `workspace_error` 会话继续强制刷新;命中 fresh tail snapshot 时先渲染缓存,远端详情刷新延后到 1.2s + idle,避免点击主链马上再打 `agent_runtime_get_session`。 -- `npx vitest run "src/components/agent/chat/index.test.tsx" -t "任务中心初始会话标签"` 通过(11 tests),新增覆盖任务中心内部连续打开旧会话、外层侧栏事件 + 路由追平后保留两个历史 tab。 -- `npx vitest run "src/components/AppSidebar.test.tsx"` 通过(35 tests),新增覆盖任务中心内点击已有会话会先通知本地标签栏,再继续导航。 -- `npx eslint "src/components/AppSidebar.tsx" "src/components/AppSidebar.test.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/index.test.tsx" "src/components/agent/chat/taskCenterDraftTaskEvents.ts" --max-warnings 0` 通过。 -- `npx tsc --noEmit --pretty false` 通过。 -- `npm run bridge:health -- --timeout-ms 120000` 通过,DevBridge `/health` 约 `22ms` 就绪。 -- Playwright E2E(`http://127.0.0.1:1420/`):刷新后点击侧栏 `E2E layout anchor`,顶部仅显示并激活该旧会话;随后点击侧栏 `你好!👋 我是 Lime 助手,很高...`,顶部同时保留 `你好!👋 ...` 与 `E2E layout anchor` 两个历史 tab,目标会话 active,旧会话 inactive;页面停留 `http://127.0.0.1:1420/`,标题 `Lime`。 -- 同轮 Playwright invoke trace:两次 `agent_runtime_get_session` 均携带 `historyLimit: 40`;侧栏 list 请求为 `agent_runtime_list_sessions` `limit=37/60`;全部 `/invoke` 为 `200 OK`,控制台 `0 error / 0 warning`。 -- `npm run verify:gui-smoke` 通过;复用现有 headless Tauri 与 DevBridge,workspace-ready、browser-runtime、site-adapters、service-skill-entry、runtime tool-surface 与 runtime tool-surface page smoke 均通过。 -- `npx vitest run "src/components/agent/chat/components/MessageList.test.tsx"` 通过(77 tests);新增覆盖已分页旧会话首帧只挂载更小尾部批次、已完成旧 turn 不再作为 active current turn 展开历史 timeline。 -- `npx eslint "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" --max-warnings 0` 通过。 -- `npx tsc --noEmit --pretty false` 通过。 -- Playwright 性能复测(`http://127.0.0.1:1420/`):打开 `AI Trends Task`(188 总消息 / 最近 40)约 `567ms`,`longTasks=[]`,DOM 节点约 `637`;打开 `Slow typing E2E`(170 总消息 / 最近 40)约 `706ms`,`longTasks=[]`,DOM 节点约 `644`,控制台 `0 error / 0 warning`。 -- `npm run verify:gui-smoke` 通过;复用现有 headless Tauri 与 DevBridge,workspace-ready、browser-runtime、site-adapters、service-skill-entry、runtime tool-surface 与 runtime tool-surface page smoke 均通过。 -- `npm run verify:local` 本轮执行到 `lint` 阶段失败,失败点为非本轮文件 `src/components/agent/chat/home/HomeSceneSkillManagerDialog.tsx:388` 的 `react-hooks/exhaustive-deps` warning(`open` 为不必要依赖),本轮 touched 文件的定向 eslint 已通过。 -- Playwright 预优化采样(`http://127.0.0.1:1420/`):打开 `Slow typing E2E` 约 `393ms` 可见,早期 invoke 为 `agent_runtime_update_session` ×2 + `agent_runtime_get_session` ×1,且两次 metadata 回填排在 `get_session` 前;本轮据此将自动 metadata 回填降为后台合并。 -- `npx vitest run "src/lib/api/project.test.ts"` 通过(59 tests),覆盖 `workspace_get` 短缓存与并发去重。 -- `npx vitest run "src/components/agent/chat/hooks/useSelectedTeamPreference.test.tsx"` 通过(13 tests),覆盖自动 fallback Team 回填走后台同步、手动切换仍即时回写。 -- `npx eslint "src/lib/api/project.ts" "src/lib/api/project.test.ts" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/hooks/useSelectedTeamPreference.ts" "src/components/agent/chat/hooks/useSelectedTeamPreference.test.tsx" --max-warnings 0` 通过。 -- GUI smoke / Playwright 后置复测暂被本地并发 Cargo/Tauri 构建阻塞:`tauri:dev:headless` 首次暴露非本轮 `creation_tools.rs` 大型 `serde_json::json!` 递归限制,已在 `src-tauri/src/lib.rs` 补 `recursion_limit = "256"` 解除;随后仍有多个非本轮 `cargo test` / `cargo check` 并发进程占用 target/package lock,需环境空闲后重跑 `npm run bridge:health -- --timeout-ms 120000`、`npm run verify:gui-smoke` 与 Playwright 旧会话性能采样。 -- `2026-04-30` Playwright 预取前采样(`http://127.0.0.1:1420/`):刷新后点击 `Slow typing E2E`,早期 invoke 仅 `workspace_get_default` / `workspace_list` / `agent_runtime_get_session(historyLimit:40)`,其中 `get_session` 约 `1261ms`;`localStorage/sessionStorage` 未命中 `aster_session_snapshots*`,说明当前慢点主要是无本地 tail snapshot 时必须等后端详情返回。 -- `2026-04-30` Playwright 预取后采样(`http://127.0.0.1:1420/`):focus `AI Trends Task` 后预取 `agent_runtime_get_session(historyLimit:40)` 约 `116ms` 并写入 `aster_session_snapshots_*`;随后点击同会话,前 `500ms` 内不再出现 `agent_runtime_get_session`,仅剩 route/workspace 初始化类 `workspace_get/default/list`,消息组已可见,`body/html cursor=auto`。 -- `npx vitest run "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" "src/components/AppSidebar.test.tsx"` 通过(2 files / 191 tests),覆盖旧会话预取 in-flight 复用与侧边栏 focus 预取事件。 -- `npx eslint "src/components/agent/chat/hooks/useAgentSession.ts" "src/components/agent/chat/hooks/useAsterAgentChat.ts" "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" "src/components/agent/chat/AgentChatWorkspace.tsx" "src/components/agent/chat/taskCenterDraftTaskEvents.ts" "src/components/AppSidebar.tsx" "src/components/AppSidebar.test.tsx" "src/components/app-sidebar/AppSidebarConversationShelf.tsx" --max-warnings 0` 通过。 -- `npx tsc --noEmit --pretty false` 通过。 -- `2026-04-30` 追加旧会话首帧渲染降载:历史恢复路径的助手正文新增 `MarkdownRenderer renderMode="light"`,旧会话首屏跳过高成本 `rehypeRaw` / `rehypeKatex` / Prism 代码高亮;实时流式与普通新消息继续走标准模式。已分页旧会话首屏批次从 `20` 缩小到 `10`,idle 补齐批次从 `12` 缩小到 `6`,且恢复路径 idle 延迟从 `120ms` 提高到 `600ms`,避免点击后立即连续吃主线程。 -- `2026-04-30` 追加后端历史 payload 裁剪:`agent_thread_items` 的 tail / cursor 历史查询在 `file_artifact.content` 之外,继续裁剪超大的 `tool_call.output`、`command_execution.aggregated_output` 与 `web_search.output` 到约 `16KB` 并附截断提示;完整 `list_items_by_thread` 不裁剪,保留全量诊断能力。这针对本地 runtime.db 中数 MB 级 `social_generate_cover_image` tool output 导致旧会话恢复 CPU/内存尖峰的问题。 -- Context7 / WebSearch 校准结论:React 官方文档说明 `useDeferredValue` / `startTransition` 只能降低优先级,不能让慢列表本身变快;TanStack Virtual 对动态高度长列表建议 `useVirtualizer + measureElement + overscan`;Tauri 文档建议大 payload 走 async command 与 Channel/chunk。当前先落地低风险的“减少首帧同步工作 + 裁剪历史 payload”,后续若 40 条历史仍卡,下一刀应评估 MessageList 动态高度虚拟化或 `agent_runtime_get_session` 分块返回。 -- Playwright E2E(`http://127.0.0.1:1420/`):刷新后点击 `Slow typing E2E`,`agent_runtime_get_session(historyLimit:40)` 约 `322ms`,点击到首屏可见约 `605ms`,DOM 约 `491`,`body/html cursor=auto`,存在一次约 `113ms` long task;进一步缩小历史首屏批次后,等待页面稳定再切 `AI Trends Task -> Slow typing E2E`,可见旧会话 DOM 保持约 `480-626`,`cursor=auto`。当前 dev 环境 heap 读数约 `1.4GB`,更像 Vite/WebView 长会话累计值,不能单独当作本轮回归证据。 -- `npm test -- "src/components/agent/chat/components/StreamingRenderer.test.tsx"` 通过(29 tests),覆盖 `markdownRenderMode="light"` 透传到 `MarkdownRenderer`。 -- `npm test -- "src/components/agent/chat/components/MessageList.test.tsx"` 通过(82 tests),覆盖旧会话轻量 Markdown、长历史正文预览、历史 timeline 折叠与更小首屏批次。 -- `npm run lint -- "src/components/agent/chat/components/MarkdownRenderer.tsx" "src/components/agent/chat/components/StreamingRenderer.tsx" "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/StreamingRenderer.test.tsx" "src/components/agent/chat/components/MessageList.test.tsx"` 通过。 -- `cd src-tauri && CARGO_TARGET_DIR="/tmp/lime-core-test-target" cargo test -p lime-core item_tail_query_should` 通过(2 tests),覆盖历史 tail 查询裁剪大 file artifact 与大 tool output,完整查询不裁剪。 -- `npm run test:contracts` 通过;本轮未新增命令,仅收窄 `agent_runtime_get_session` 历史窗口返回中的超大 inline payload。 -- `npm run verify:gui-smoke` 通过;复用现有 headless Tauri 与 DevBridge,workspace-ready、browser-runtime、site-adapters、service-skill-entry、runtime tool-surface 与 runtime tool-surface page smoke 均通过。 -- `npm run typecheck` 通过。 -- `2026-04-30` 追加旧会话首帧二次降载:已分页/恢复旧会话中的长助手回复不再首帧挂载 `StreamingRenderer` / Markdown 解析,而是先展示纯文本预览,用户点击“展开完整内容”后才按轻量 Markdown 物化;超长历史回复的预览长度从约 `6000` 字收窄到约 `2000` 字,降低点击旧会话后的主线程解析与 DOM 压力。 -- 同轮将历史 timeline 的 idle 物化从旧会话首帧后约 `80ms` 延后到约 `900ms`,避免消息刚可见后立刻构建完整 `buildMessageTurnTimeline` 抢占主线程;非旧会话仍保留原 `80ms` 行为。 -- `npm test -- "src/components/agent/chat/components/MessageList.test.tsx"` 通过(83 tests),新增覆盖长助手回复纯文本预览与展开后再物化轻量 Markdown。 -- Playwright E2E 复测(`http://127.0.0.1:1420/`):刷新后切 `AI Trends Task -> Slow typing E2E`,旧会话首屏约 `77ms` 可见,DOM 节点约 `403`,历史助手正文纯文本预览 `1` 个,历史 timeline 预览 `1` 个、真实 timeline 挂载 `0` 个,`longTasks=[]`,`body/html cursor=auto`,控制台 `0 error / 0 warning`。invoke trace 中两次 `agent_runtime_get_session` 均携带 `historyLimit: 40`,无 `/invoke` 错误。 -- `npm run verify:gui-smoke` 通过;复用现有 headless Tauri 与 DevBridge,workspace-ready、browser-runtime、site-adapters、service-skill-entry、runtime tool-surface 与 runtime tool-surface page smoke 均通过。 -- `2026-04-30` 追加旧会话后台渲染节流:恢复/已分页旧会话不再自动 idle 补齐当前窗口里更早的消息,首屏只保留尾部批次,用户点击“立即展开更早消息”时才继续物化,避免打开后数秒内后台持续挂载 Markdown / timeline 造成 CPU 与内存尖峰;普通非旧会话仍保留空闲自动补齐。 -- 同轮进一步扩大历史 timeline 延后范围:即使旧会话只有少量消息,只要 execution/thread items 很多,也先显示正文,约 `900ms` 后再生成 timeline 摘要预览;这覆盖 `Slow typing E2E` 这类“消息少但工具轨迹多”的慢会话。 -- `npm test -- "src/components/agent/chat/components/MessageList.test.tsx"` 通过(84 tests),新增覆盖旧会话不自动补齐历史窗口、少消息多执行过程延后构建 timeline。 -- `npx eslint "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" --max-warnings 0` 通过。 -- `npm run typecheck` 通过。 -- 后置 `npm run verify:gui-smoke` 已尝试两次但未完成:当前本机已有非本轮 `cargo test --manifest-path src-tauri/Cargo.toml audio_generation_task` 与旧 `tauri:dev:headless` 长时间占用 Cargo artifact lock,DevBridge 无法就绪;为避免继续拉高 CPU,已停止本轮新拉起的 smoke 进程,未终止非本轮 cargo/tauri 进程。待该锁释放后需重跑 GUI smoke / Playwright。 -- `2026-04-30` 追加首字前反馈优化:Playwright MCP 当前 transport closed,改用本地 Playwright + Chrome 复测;真实 DevBridge 恢复后发送 `首字延迟 E2E ...`,点击到用户消息可见约 `295ms`,新的 `assistant-first-token-placeholder` 同步约 `295ms` 可见。后端随后因本机缺少 `claude` 凭证在约 `5.3s` 返回失败,因此本轮无法测真实模型首 token,但已消除“首个模型事件前 assistant 气泡为空/像没响应”的 UI 体感慢点。 -- 同轮代码收口:`MessageList` 在 assistant `isThinking` 且正文/parts/timeline 均为空但存在启动态 `runtimeStatus` 时,渲染轻量首字前占位;不把 runtimeStatus 塞回 `StreamingRenderer` 正文,也不渲染底部重复运行态,首个真实文本到来后自动切回正常流式渲染。 -- `npm test -- "src/components/agent/chat/components/MessageList.test.tsx"` 通过(84 tests),新增覆盖启动态 runtimeStatus 只渲染轻量首字前占位、已有正文时不重复占位。 -- `npx eslint "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx" --max-warnings 0` 通过。 -- `npm run typecheck` 通过。 -- `git diff --check -- "src/components/agent/chat/components/MessageList.tsx" "src/components/agent/chat/components/MessageList.test.tsx"` 通过。 -- `npm run verify:gui-smoke` 通过;复用现有 headless Tauri 与 DevBridge,workspace-ready、browser-runtime、site-adapters、service-skill-entry、runtime tool-surface 与 runtime tool-surface page smoke 均通过。 -- `2026-04-30` 追加 DeepSeek 首字续测:Playwright MCP 仍为 `Transport closed`,继续用本地 Chrome + Playwright;模型选择入口需先展开“高级设置”,再点击 `button[role="combobox"]`,可切到 `DeepSeek / deepseek-v4-flash`。 -- 同轮复现输出排版问题:DeepSeek 实际流里会返回 `thinking` 分片再返回最终 `text` 分片,例如 `llm_request.2.jsonl` 中先有 `thinking: "我们…好。"`,再有 `text: "好"`;旧前端在 thinking 关闭时仍渲染 thinking block,导致 UI 显示类似 `思考中…好。好`。 -- 同轮代码收口:`agentStreamTurnEventBinding` 将本轮 `thinking` 偏好透传给 `agentStreamRuntimeHandler`;当 thinking 关闭时,`thinking_delta` 只激活流状态、不再写入 assistant `thinkingContent/contentParts`,后续 `text_delta` 会清理已有 thinking part,避免 DeepSeek 隐式 reasoning 混入最终正文。 -- DeepSeek E2E 成功样本(`/tmp/lime-deepseek-first-token-e2e-retry.json`):`agent_runtime_create_session` 约 `73ms`,`agent_runtime_submit_turn` 约 `136ms`,首字前占位约 `117ms` 可见,最终 assistant 文本为 `好已完成·00:06`,不再出现 `思考中` / reasoning 重复吐字;过程中仍有一次非阻塞 `workspace_get` 5s timeout 噪音。 -- DeepSeek E2E 失败样本(`/tmp/lime-deepseek-first-token-e2e-final.json`):同样选择 `DeepSeek / deepseek-v4-flash` 后,`agent_runtime_submit_turn` 偶发在 `60s` 前端超时并返回 DevBridge timeout,且本地 `aster/state/logs` 没有对应 LLM request 新日志,说明失败发生在提交链路/bridge 阻塞或运行时排队阶段,未进入 provider 首 token;这是后续首字慢优化的下一刀证据。 -- `2026-05-02` 追加首页输入回车卡顿收口:`ensureSessionForCommandMetadata` 透传 `skipSessionRestore / skipSessionStartHooks`,首页首轮普通发送不再预热旧会话恢复,也跳过 submit 前队列恢复扫描;发送规划阶段新增 `workspaceSend.plan.ready` 性能点,能区分首页 shell、发送 plan、ensure session、submit invoke、首事件、首文本、首 paint。 -- 同轮快速响应路由收口:`lime-hub/gpt-5.5`、`lime-hub/gpt-5.4` 与 DeepSeek 推理/Flash 模型的首轮轻量普通对话,若无显式 provider/model override、无工具/团队/上下文/能力路由,直接使用 `deepseek/deepseek-chat` 与短系统提示;Provider 列表未返回 DeepSeek 时也允许内置快速路由,当前已是 `deepseek-chat` 时只启用短提示词、不重复写 provider/model override。 -- Playwright MCP E2E(`http://127.0.0.1:1420/`,输入 `只回答一个字:好`):修复前采样中首页到 `agentStream.request.start` 已约 `163ms`,但仍走 `provider=lime-hub / model=gpt-5.5`,`homeInputToFirstTextDeltaMs≈20515ms`;修复后两次复测均命中 `provider=deepseek / model=deepseek-chat`,样本一 `homeInputToPendingPreviewPaintMs=33ms`、`homeInputToStreamRequestStartMs=88ms`、`homeInputToFirstTextDeltaMs=1886ms`、`homeInputToFirstTextPaintMs=1914ms`,样本二 `23ms / 51ms / 1559ms / 1583ms`,`longTaskCount=0`,控制台 `0 error`。当前剩余首字耗时主要是 provider 首个文本 delta(约 `1.4-1.7s`),不是首页跳转或旧会话恢复阻塞。 -- `npm test -- src/components/agent/chat/utils/fastResponseModel.test.ts src/lib/agentUiPerformanceMetrics.test.ts` 通过(16 tests);`npm test -- src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx -t "首页快路径首轮普通发送不应预热旧会话恢复|首轮轻量对话不等待 Provider 列表也应命中内置快速响应路由|首轮轻量对话有 DeepSeek 时应注入快速响应路由"` 通过(3 tests);`npm run verify:gui-smoke` 通过。 -- `npm test -- "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts"` 通过(10 tests),新增覆盖 thinking 关闭时不渲染 reasoning_delta。 -- `npm test -- "src/components/agent/chat/hooks/agentStreamTurnEventBinding.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.test.ts"` 通过(7 tests)。 -- `npx eslint "src/components/agent/chat/hooks/agentStreamRuntimeHandler.ts" "src/components/agent/chat/hooks/agentStreamTurnEventBinding.ts" "src/components/agent/chat/hooks/agentStreamSubmitExecution.ts" "src/components/agent/chat/hooks/agentStreamRuntimeHandler.test.ts" --max-warnings 0` 通过。 -- `npm run typecheck` 通过。 -- `npm run verify:gui-smoke` 通过;本轮临时 target 首次编译耗时较长,随后 DevBridge / workspace-ready / browser-runtime / site-adapters / service-skill-entry / runtime tool-surface page smoke 均通过。 -- `2026-05-02` 追加首页首字体感指标拆分:在 `prepareAgentStreamSubmitDraft` 注入 assistant 草稿时记录 `agentStream.assistantDraft`,下一帧后记录 `agentStream.assistantDraftPaint`;性能汇总新增 `homeInputToAssistantDraftMs` 与 `homeInputToAssistantDraftPaintMs`,用于区分“页面已有首字前反馈”和“provider 真实首个 text_delta”。这避免继续把 DeepSeek 首包 `1.4-1.7s` 误判为首页跳转/主线程卡死。 -- 同轮实现保持现有 UI 主链:不把“正在连接模型”等占位文案写进 assistant 正文,继续复用 `AssistantFirstTokenPlaceholder`;真实 `text_delta` 到来后仍由 `agentStreamRuntimeHandler` 用模型累积内容渲染,避免复发重复吐字 / 占位污染最终回复。 -- 定向校验:`npm test -- "src/components/agent/chat/hooks/agentStreamSubmitDraft.test.ts" "src/lib/agentUiPerformanceMetrics.test.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" -t "assistant 草稿插入与绘制指标|首页输入提交到会话壳和发送派发|首轮轻量对话有 DeepSeek 时应注入快速响应路由"` 通过(3 tests);`npm run typecheck` 通过;`git diff --check -- "src/lib/agentUiPerformanceMetrics.ts" "src/lib/agentUiPerformanceMetrics.test.ts" "src/components/agent/chat/hooks/agentStreamSubmitDraft.ts" "src/components/agent/chat/hooks/agentStreamSubmitDraft.test.ts" "src/components/agent/chat/hooks/agentStreamUserInputSendPreparation.ts"` 通过。 -- Playwright MCP 后置复测当前被本地 DevBridge 环境阻塞:`http://127.0.0.1:1420/` 可加载,但首页跳过 onboarding 后卡在“正在准备生成工作区”,控制台唯一 error 为 `http://127.0.0.1:3030/health net::ERR_CONNECTION_REFUSED`;`npm run tauri:dev:headless` 被已有 Vite `1420` 占用,`LIME_WEB_BRIDGE_REUSE_EXISTING_ONLY=1` 可复用前端但仍被现有多组 `cargo test/check/tauri dev` 锁竞争阻塞;改用隔离 `CARGO_TARGET_DIR="/tmp/lime-codex-e2e-target"` 后冷编译中途因 target 目录消失失败。待 `3030` 恢复后需补跑一次真实首页发送 E2E,重点采集 `homeInputToAssistantDraftPaintMs`、`homeInputToFirstRuntimeStatusMs`、`homeInputToFirstTextDeltaMs` 与 `longTaskCount`。 -- `2026-05-05` 追加首轮纯聊天去 Browser Assist 负担:`withFastResponseMetadata` 写入快速响应路由时剥离默认 `harness.browser_assist / browserAssist`;首页首轮通用普通文本、无图片、无显式技能/浏览器需求、非 `/`/`@` 命令时跳过 `primeBrowserAssistBeforeSend`,避免发送前同步准备 Browser Assist 画布或把浏览器工具面带入普通快问快答。 -- Playwright MCP E2E(`http://127.0.0.1:1420/`,输入 `只回答一个字:好`):`npm run bridge:health -- --timeout-ms 20000` 通过,DevBridge `/health` 约 `36ms`;真实发送链路中 `agent_runtime_create_session` 约 `49ms`,`agent_runtime_submit_turn` 约 `193ms`,`agent_runtime_get_session(historyLimit:40)` 约 `151ms`,最终正文为 `好`,`body/html cursor=auto`,DOM 约 `384`,heap used 约 `131MB`,发送期间仅 1 个约 `73ms` long task。`submit_turn.turn_config` 命中 `provider_preference=deepseek` / `model_preference=deepseek-chat` / `skip_pre_submit_resume=true`,`metadata.harness` 仅保留 `theme/preferences/session_mode/browser_user_step_required/fast_response_routing`,未携带 `browser_assist`。 -- 同轮 E2E 观察到回复完成后还有一次辅助 `agent_generate_title`,耗时约 `2228ms`,随后 `agent_runtime_update_session(name)` 约 `2ms`;源码当前已通过 `AUTO_TITLE_DEFERRED_LOAD_MS=30000` + idle 调度延后自动标题生成,本轮采集器未记录每个 invoke 的绝对开始时间,因此暂不把它判定为首字慢根因。后续若继续出现“回答完仍卡 / 后续点击慢”,下一刀应补 invoke start-time 采集,并评估把标题生成下沉到更低优先级队列或延迟到用户空闲更久后执行。 -- 定向校验:`npm test -- "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" -t "首轮轻量对话有 DeepSeek 时应注入快速响应路由|首页快路径首轮普通发送不应预热旧会话恢复|已携带 service_skill_launch metadata"` 通过(3 tests);`npx eslint "src/components/agent/chat/workspace/useWorkspaceSendActions.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx" --max-warnings 0` 通过;`npm run typecheck` 通过;`git diff --check -- "src/components/agent/chat/workspace/useWorkspaceSendActions.ts" "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx"` 通过。 -- 后置 `npm run verify:gui-smoke` 已执行:workspace-ready、browser-runtime、site-adapters、agent-service-skill-entry、agent-runtime-tool-surface、agent-runtime-tool-surface-page 均通过;最后 `smoke:knowledge-gui` 因当前 worktree 里知识库命令 `knowledge_import_source` 未注册到 DevBridge 返回未知命令而失败。该失败属于现有知识库命令边界缺口,不是本轮首页首轮发送 / Browser Assist 降载回归;若要恢复全量 GUI smoke,需要单独按命令边界同步 `knowledge_import_source` 的前端调用、Rust dispatcher / handler、治理目录册与 mock。 diff --git a/docs/exec-plans/provider-model-taxonomy-progress.md b/docs/exec-plans/provider-model-taxonomy-progress.md deleted file mode 100644 index 3c8fc294f..000000000 --- a/docs/exec-plans/provider-model-taxonomy-progress.md +++ /dev/null @@ -1,242 +0,0 @@ -# Provider 模型能力 taxonomy 进度 - -## 2026-04-22 - -### 目标 - -- 把本地模式、用户自管云端 Provider、OEM 云端目录的模型能力语义收成一套轻量 taxonomy -- 明确区分 `对话 / 视觉理解 / 图片生成 / 音频 / Embedding`,避免继续把 `llm / vlm / multimodal` 混成一类 -- 支持 OpenAI relay / OEM 映射模型,例如 `gpt-images-2` -- 保持设置页与 Provider 目录页轻量,不走复杂“模型广场”路线 - -### 已完成 - -- Rust 模型注册表与请求解析链已补齐统一字段: - - `task_families` - - `input_modalities` - - `output_modalities` - - `runtime_features` - - `deployment_source` - - `management_plane` - - `canonical_model_id` - - `provider_model_id` - - `alias_source` -- 前端能力推断已统一到 `inferModelCapabilities.ts`: - - `gpt-images-2` 被识别为 `image_generation` - - `vision_understanding` 与 `image_generation` 明确分离 - - 旧 `capabilities` 只作为 compat fallback -- Provider 模型目录 UI 已改成轻量能力筛选: - - 保留按能力筛选,不引入复杂模型广场 - - 已区分 `本地 / 云端 / OEM 云端` - - 只有 `relay / oem` 别名才展示“实际映射” -- 图片生成选择链已切到统一 taxonomy: - - 图片 Provider 只会保留真正支持 `image_generation` 的模型 - - 避免把视觉理解模型混进生图候选 -- 媒体服务设置页已收口到统一“服务模型”骨架: - - 设置导航与首页快捷入口已从“媒体服务”统一改名为“服务模型” - - 服务模型页已对齐参考产品的总页结构,不再只保留图片 / 视频 / 语音三块 - - 新增通用助理模型设置: - - 话题自动命名 - - AI 图片话题命名 - - 消息内容翻译 - - 会话历史压缩 - - 助理信息生成 - - 输入自动补全 - - 提示词重写 - - 资源库提词重写 - - 新增统一设置区块: - - 语音识别服务 - - 自动结束语音识别 - - OpenAI 语音合成模型 - - OpenAI 语音识别模型 - - AI 图片默认数量 - - 图片 / 视频 / 语音统一为 `默认 Provider + 默认模型 + 自动回退` - - 图片默认数量已改为更接近参考页的 `滑杆 + 可直接输入数字` 简化交互 - - 旧图片出图参数面与旧语音调参面已从 current 设置主路径删除 - - 旧实验室 `VoiceSettings` 入口已清退,不再保留双轨 UI -- OEM 云端模型目录已收口到统一 schema: - - `oemCloudControlPlane.ts` 允许服务端直接下发 taxonomy 字段 - - `oemCloudModelMetadata.ts` 负责把 OEM 模型目录归一为 metadata-like 结构 - - OEM 设置页优先消费 taxonomy,`abilities` 只做兜底 -- OEM fallback 能力别名已统一: - - `llm -> chat` - - `vlm / multimodal / omni -> vision_understanding` - - `image_generation / text_to_image -> image_generation` -- 已补回归并通过: - - OEM 模型协议解析 - - OEM taxonomy helper - - Provider 模型目录别名展示 - - OEM 设置页 taxonomy 优先级 - - 图片生成筛选链 - - 媒体服务设置页定向回归: - - `src/lib/imageGeneration.test.ts` - - `src/lib/serviceModels.test.ts` - - `src/lib/api/appConfig.test.ts` - - `src/components/settings-v2/agent/media-services/index.test.tsx` - - `src/components/settings-v2/agent/image-gen/index.test.tsx` - - `src/components/settings-v2/agent/video-gen/index.test.tsx` - - `src/components/settings-v2/agent/voice/index.test.tsx` - - `src/components/settings-v2/system/experimental/index.test.tsx` - - 服务模型总页新增断言覆盖: - - 输入自动补全开关持久化 - - 自动结束语音识别持久化 - - 资源库自定义提示词持久化 - - 默认图片数量持久化 - - Rust 配置 roundtrip: - - `cargo test -p lime-core test_workspace_preferences_supports_service_models_roundtrip` - - GUI 冒烟: - - `npm run verify:gui-smoke` - - `npm run governance:legacy-report` -- 已额外确认: - - `isImageProvider("lime-hub", "openai", ["gpt-images-2"]) === true` -- 当前未完成的环境校验: - - `npm run verify:local` 当前被仓库中其他改动阻塞: - - `src/lib/sceneapp/product.ts:2070` - - `src/lib/sceneapp/product.ts:2101` - - 错误为 `SceneAppScorecardViewModel.aggregate` 缺失 - - 属于当前脏工作区里的 sceneapp 主线类型问题,不是本次服务模型页改动引入 - -### 当前边界 - -- `current` - - 本地 / 云端 / OEM 模型目录共享同一套轻量 taxonomy 语义 - - OEM 云端目录支持直接下发 taxonomy,也支持旧 `abilities` 兼容 - - UI 只做轻量筛选和标签展示,不做复杂模型广场 - - 媒体服务设置只保留服务模型级默认项,不再继续扩展旧细项调参面 -- `compat` - - OEM `abilities: string[]` - - OEM `upstreamMapping` - - 旧 `capabilities` 布尔字段 -- `dead` - - `src/components/voice/VoiceSettings.tsx` - - 实验室里的旧语音输入设置面 -- `not in scope` - - 把 OEM 云端目录完全同步进本地自定义模型持久化 - - 引入独立模型 marketplace / 多维排序 / 高复杂过滤器 - -### 下一刀 - -1. 推动 OEM 服务端稳定下发 taxonomy 字段,逐步减少前端对 `abilities` 的兼容推断依赖。 -2. 评估是否需要把 OEM 模型目录同步到 `useOemLimeHubProviderSync.ts` 的本地缓存面;若做,优先保持单一事实源,不新增第二套目录结构。 -3. 若后续把 OEM 云端服务模型接入媒体服务设置,优先复用当前服务模型骨架,只扩展选项数据源与来源标签,不新增第二套设置页。 -4. 若后续出现视频、文档理解、实时语音等新能力,再在现有 taxonomy 上小步扩展,不回退到“模糊模型类型”。 - -## 2026-04-23 - -### 继续收口 - -- 桌宠能力偏好页已统一回共享模型选择链: - - `MediaPreferenceSection -> SettingModelSelectorField -> ModelSelector` - - 不再继续保留旧 `providerLabel/providerValue/modelLabel/modelValue` 参数面 -- 桌宠通用模型区块已显式走 `general` 主题筛选,避免把明显非对话模型混进 quick action 候选 -- 桌宠通用 / TTS 区块都已按当前 consumer 能力做 Provider 过滤: - - 只展示当前桌宠 quick action / TTS 能真正消费的 Provider - - 继续兼容后续本地、自管云与 OEM taxonomy 扩展 -- `@配音` 的定向回归已补: - - 显式 mock 全局 `media_defaults.voice` - - 断言 `service_scene_run` 中携带 - - `preferred_provider_id` - - `preferred_model_id` - - `allow_fallback` - - 当 `preferred_provider_id + preferred_model_id` 同时存在时,当前发送链会把它们转成真实 `providerOverride / modelOverride` - - 当只声明 `preferred_provider_id`、未显式选模型时,不会误把当前会话模型硬塞给新 Provider -- 桌宠设置相关回归已补: - - `CompanionCapabilityPreferencesCard.test.tsx` - - `providers/index.test.tsx` - - 两处都断言当前页复用了统一 `ModelSelector` 组件,而不是另一套独立选择器 - -### 本轮校验事实 - -- 已通过: - - `npx vitest run "src/components/agent/chat/workspace/useWorkspaceSendActions.test.tsx"` - - 结果:`90` 个测试通过 -- 已通过: - - `npx vitest run "src/components/settings-v2/agent/providers/CompanionCapabilityPreferencesCard.test.tsx" "src/components/settings-v2/agent/providers/index.test.tsx"` - - 结果:`15` 个测试通过 -- 已通过: - - `cargo test -p lime-core test_workspace_preferences_supports_companion_defaults_roundtrip` - - `cargo test -p lime-core test_workspace_preferences_supports_service_models_roundtrip` -- 未完成: - - `cargo test -p lime ...` 在编译 `lime` 主 crate 链接阶段被环境阻塞 - - 具体错误:`No space left on device` - - 当前磁盘余量:`1.4Gi` - -### 2026-04-23 继续收口(第二刀) - -- Rust `request_model_resolution` 已开始真正消费 `service_scene_launch` 里的首选服务偏好: - - 当前若回合 metadata 同时声明 `preferred_provider_id + preferred_model_id` - - 且前端本轮没有显式 `provider_preference / model_preference` - - 后端会直接基于该 scene launch 偏好解析 `provider_config` -- `service_scene_launch.allow_fallback` 已接入后端解析策略: - - `false`:首选 provider/model 不可解析时直接报错,不再静默回退会话默认 - - `true`:首选 provider/model 失效时,允许继续回退到会话当前 provider/model -- 当前只声明 `preferred_provider_id`、未声明 `preferred_model_id` 时: - - 后端不会把它误当成完整首选模型偏好 - - 仍沿用现有显式请求 / 会话恢复链,避免跨 Provider 误绑模型 -- “服务模型”页已进一步简化: - - `输入自动补全助理` 当前已收口为只展示启停开关 - - 不再暴露尚未接入 current 执行面的模型选择 UI - - 这样继续保持“能用的配置必须真生效;没接上的不假装可配” - -### 2026-04-23 继续收口(第三刀) - -- 桌宠设置页已删除未接入 current 执行面的 `桌宠语音播报` 偏好区块: - - 当前 Rust `companion_service` 只真实消费 `companion_defaults.general` - - `companion_defaults.tts` 之前只有设置页写入,没有 quick action / voice chat / 播报执行链 consumer - - 因此 current UI 只保留 `桌宠通用模型`,继续复用共享 `ModelSelector` -- 桌宠偏好保存逻辑同步收口: - - 保存 `桌宠通用模型` 时不再继续保留旧的 `companion_defaults.tts` 假设置 - - 让桌宠页和实际执行面重新回到单一事实源 - -### 2026-04-23 继续收口(第四刀) - -- `VoiceSettings` 已从“只配语音生成任务模型”补齐为当前真实语音主链设置页: - - 语音输入启停 - - 主快捷键 - - 翻译模式快捷键 - - 麦克风设备 - - 交互音效 - - AI 润色开关 - - 润色 / 翻译共用模型选择 - - 默认润色指令 - - 翻译模式指令 - - 指令管理 - - 配音 / TTS 任务默认模型 -- 新语音设置页继续复用统一模型选择链: - - `SettingModelSelectorField -> ModelSelector` - - 不再继续使用旧 `PolishModelSelector` 作为另一套模型入口 -- 新增语音设置都已接到 current consumer: - - `processor.polish_provider / polish_model` 已真实透传到本地网关请求头 `X-Provider-Id` - - `translate_instruction_id` 与指令删除后的回退逻辑已收口,避免保存失效指令引用 - - `selected_device_id / sound_enabled / enabled / shortcut / translate_shortcut` 继续直连当前语音输入链 -- dead `Config.voice` 已彻底删除: - - 前端 `appConfigTypes` 不再暴露旧 `voice` 面 - - Rust `Config` 不再保留旧 `voice` 字段与导出 - - 相关旧测试 mock 与假配置项已同步清理 - -### 本轮新增校验 - -- 已通过: - - `npx vitest run "src/components/settings-v2/agent/media-services/index.test.tsx"` - - 结果:`5` 个测试通过 -- 已通过: - - `npx vitest run "src/components/settings-v2/agent/voice/index.test.tsx" "src/components/settings-v2/agent/media-services/index.test.tsx" "src/lib/api/appConfig.test.ts"` - - 结果:`18` 个测试通过 -- 已通过: - - `cargo test --manifest-path "src-tauri/Cargo.toml" service_scene_model_preference` - - 结果:新增 `2` 个 Rust 定向测试通过 -- 已通过: - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime-core test_voice_input_config_default` - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime-services --lib` - - 结果:`lime-core` 定向测试通过,`lime-services` `174` 个测试通过 -- 已通过: - - `npx vitest run "src/components/settings-v2/agent/providers/CompanionCapabilityPreferencesCard.test.tsx" "src/components/settings-v2/agent/providers/index.test.tsx"` - - 结果:`15` 个测试通过 -- 当前环境事实: - - 磁盘余量已恢复到约 `76GiB` - - 默认 `target` 目录偶发被并行 `cargo run` 占锁;不是本轮代码错误 - -### 下一刀 - -1. 先清出足够磁盘空间,再补 `lime` 主 crate 的 Rust 定向测试,确认 `runtime_turn / service_scene_launch / prompt_context` 全链编译通过。 -2. 若桌宠语音播报进入 current 执行链,优先复用这次已经统一好的 `companion_defaults.tts`,不要再新增第二套语音偏好入口。 diff --git a/docs/exec-plans/tech-debt-tracker.md b/docs/exec-plans/tech-debt-tracker.md deleted file mode 100644 index d633c4b5a..000000000 --- a/docs/exec-plans/tech-debt-tracker.md +++ /dev/null @@ -1,24 +0,0 @@ -# 技术债追踪 - -本文件记录需要持续、小额偿还的技术债,避免把问题堆到一次性大清理。 - -## 记录规则 - -1. 每条技术债都要写清具体代码面、影响和下一小步 -2. 能回挂路线图主线的,优先回挂路线图;不能回挂的,登记到这里 -3. 状态至少区分 `待处理`、`进行中`、`已完成`、`放弃` - -## 条目 - -| ID | 日期 | 区域 | 差距 / 债务 | 影响 | 下一小步 | 关联文档 | 状态 | -| ------- | ---------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ------ | -| CCD-001 | 2026-04-14 | Query Loop | Lime 已有 `submit_turn / runtime_turn / tool_runtime / evidence` 主链,但过去缺少单一 Query Loop 事实源;现已补齐 current 文档入口 | 已从“主链解释分散”降到“代码边界仍待继续收口”,后续推进顺序已稳定 | 继续沿 `docs/aiprompts/query-loop.md` 盘点代码侧重复边界,准备下一刀 helper 收口 | `docs/exec-plans/upstream-runtime-alignment-plan.md` | 已完成 | -| CCD-002 | 2026-04-14 | Remote Runtime | Telegram remote、OpenClaw、DevBridge、browser remote/debugging 等入口过去并存且语义混杂;现已补齐 `消息渠道 runtime + 浏览器连接器 / ChromeBridge` 的 current 主链,并明确 `DevBridge / OpenClaw` 为 compat、`telegram_remote_cmd` 为 deprecated | 已从“remote 入口平级并存”降到“只剩 compat / deprecated 退场减法”,后续 remote 主线解释已稳定 | 后续只允许 remote 新能力落到 `gateway_channel_*` 或 `browser connector / ChromeBridge` current ingress;`DevBridge / OpenClaw / telegram_remote_cmd` 默认只做减法和兼容维护 | `docs/exec-plans/upstream-runtime-alignment-plan.md` | 已完成 | -| CCD-003 | 2026-04-14 | Task / Agent | `subagent / automation / execution tracker / scheduler / heartbeat` 过去缺少统一 taxonomy;现已补齐 `agent turn / subagent turn / automation job` current 分型,并明确 `ExecutionTracker` 为摘要层、`SchedulerService` 为 compat 触发壳 | 已从“排期语言混乱”降到“只剩 compat / deprecated 退场减法”,后续主线解释已稳定 | 后续只允许新增长时执行需求落到 `agent turn / subagent turn / automation job` 三类之一;`SchedulerService` 与 `heartbeat_executions` 只继续做减法和退场 | `docs/exec-plans/upstream-runtime-alignment-plan.md` | 已完成 | -| CCD-004 | 2026-04-14 | Memory / Compaction | `memory_runtime_*`、`unified_memory_*`、`agent_runtime_compact_session` 与来源链 control plane 过去缺少统一主链叙事;现已补齐 current 文档入口,并明确 `project_memory_get` 为 compat 附属层、`memory_feedback_cmd` 为 deprecated | 已从“记忆、压缩、恢复分头演进”降到“后续只需守住 current 边界不回流” | 后续只允许新记忆 / 压缩需求落到 `docs/aiprompts/memory-compaction.md` 定义的 current 主链;发现回流时做定点治理 | `docs/exec-plans/upstream-runtime-alignment-plan.md` | 已完成 | -| CCD-005 | 2026-04-14 | State / History / Telemetry | reliability、harness、history、review、replay、evidence 过去分别成文且入口分散;现已补齐 `SessionDetail -> AgentRuntimeThreadReadModel -> RequestLog 关联键 -> export/history` 的 current 状态地图,并明确旧状态模型方案、reliability 计划与原始 request log 浏览面退回附属层 | 已从“状态模型叙事分散”降到“只剩 compat / deprecated 退场减法”,后续主线解释已稳定 | 后续只允许新状态 / 历史 / 遥测能力落到 `docs/aiprompts/state-history-telemetry.md` 定义的 current 主链;优先继续清 `reliability` 计划与 cleanup 旧语义 | `docs/exec-plans/upstream-runtime-alignment-plan.md` | 已完成 | -| CCD-006 | 2026-04-20 | Config / Host Surface | 参考运行时架构图复盘后确认:Lime 的 `ConfigTool` 宿主配置矩阵仍未补齐,但 `classifierPermissionsEnabled` 已接入 `current` 主链并与安全扫描 ML toggle 打通;进一步审计后又确认 `remoteControlAtStartup` 不能映射到现有 `get_auto_launch_status / set_auto_launch`,`taskCompleteNotifEnabled / inputNeededNotifEnabled / agentPushNotifEnabled` 也不能映射到更新提醒窗口或已下线的 `channels_cmd.rs` stub。`permissions.defaultMode` 这轮也已进一步收紧:prompt 层虽有 `PermissionMode::Plan / DontAsk` 文本能力,但 `plan` 仍只是显式 `EnterPlanMode / ExitPlanMode` 工具流,`dontAsk` 也还缺 provider flag 与 `PermissionInspector` 的全局 runtime 语义 | 若停在当前状态,`Config` 虽然不再把 classifier 开关卡死在 `unsupported`,但 remote-control / push-notification / permission-mode 仍无法通过 `current` 配置面真实控制;更糟的是,后续实现者容易把 OS auto-launch、更新提醒、plan prompt 文本或 stub notification CRUD 误判成可复用事实源,继续制造假对齐 | 已完成“真实宿主落点”与 `permissions.defaultMode` 执行语义审计;下一小步进一步收敛为二选一:要么新增真正的 remote-control / mobile push / dontAsk runtime 宿主面并把 `plan` 重构为可持久化权限模式,要么把这组差异明确沉淀为产品层不对齐;并继续明确 `channels_cmd.rs` 已非可复用宿主面,不再参与这组 setting 的事实源判断 | `docs/exec-plans/upstream-runtime-alignment-progress.md` | 进行中 | -| CCD-007 | 2026-04-20 | Team / Peer Messaging | `SendMessage / ListPeers` 已从“只支持 team 内 peers”收口到“team peers + synthetic `uds:` 本机会话 peers”的 live-aware `current`:`ListPeers` 会优先返回同一 `working_dir` 下 active / queued 的本机顶层 session,不足时才回退最近 session;对照参考仓库 `peerAddress.ts` 与 `SendMessageTool` 后,本地 peer surface 也已重新收口为“仅通过 `send_to=uds:` 暴露 peer address”,`SendMessage` 只把显式 `uds:` 识别为 cross-session local peer 路由,不再把 bare local `session_id` 当成 peer address fallback。Lime 仍使用 synthetic local registry,而不是真实 UDS/socket peer transport;`bridge:` 也继续明确留在 gap | 当前 misleading surface 已清掉:Lime 不再是“识别 `uds:` 但永远失败”的半成品,也不再把 bare session-id 误扩成参考运行时不存在的 peer address。剩余差距已被显式压回 `session registry / local ingress / remote bridge ingress` 产品 gap,不再继续污染 current 边界 | 后续若产品明确需要真实 local ingress 或 remote peer messaging,应另开新专题,围绕显式 session registry / transport host 设计推进;在那之前,`CCD-007` 只维护当前 `uds:` synthetic local peer current,不再扩展裸地址或假 bridge surface | `docs/exec-plans/upstream-runtime-alignment-progress.md` | 已完成 | -| CCD-008 | 2026-04-20 | Extension / Hook / Skill | `SkillTool`、project/plugin/session hooks、plugin skills/hooks/agents、plugin cache resolver 与 child worktree lifecycle 已陆续进入 `current` 主链;近几轮又继续补上了 `PermissionRequest.updatedPermissions` 的 session `setMode` 最小 current 子集、managed-session peer messaging、lead-side `shutdown_response` current subset、peer message display / cards / lifecycle-noise 收口,以及 lead-side current team context 下 `name + mode=plan` 命中 teammate plan lifecycle 的最小 honest reachability | 若停在当前状态,Lime 已不再是“plugin 只能带技能、不能真正带 runtime hooks”“压缩前完全绕过 hooks”“权限审批仍完全绕过 hooks”“turn 正常结束完全绕过 Stop hooks”“删除 session 完全绕过 SessionEnd hooks”“lead/team 已有 plan host 却仍被入口挡在外面”“peer 消息进了 runtime 却仍把 XML / lifecycle noise 原样暴露给主聊天”的假对齐;但扩展体系仍停留在“`SessionStart(clear)` 与 `SessionEnd.resume / clear / prompt_input_exit / logout / bypass_permissions_disabled` 仍无真实 current 宿主、`Stop` 仍缺 continuation gate、`PermissionRequest.updatedPermissions` 的 rules / directories / non-session destination 仍无 honest host、`isolation=remote` 与非 team child `plan` lifecycle 仍无 honest host、且 `hook.if / asyncRewake / 非 bash shell / allowedEnvVars` 仍显式未支持”的阶段 | 已完成 lead-side current team context 下 teammate `plan` reachability 收口;下一小步优先回到 `isolation=remote`,或只在未来真的补齐非 team child lifecycle / permission host 后再继续扩 `plan` 与 `updatedPermissions` 边界 | `docs/exec-plans/upstream-runtime-alignment-progress.md` | 进行中 | -| CCD-009 | 2026-04-20 | Remote Governance / Legacy Surface | 参考运行时对比后再次确认:`channels_cmd.rs` 这组 AI / 通知渠道 CRUD 基本仍是空壳,但仓库 current remote 事实源已经固定到 `gateway_channel_* + browser connector / ChromeBridge`;本轮已确认 `ImConfigPage` 走的是 `channelsRuntime.ts -> gateway_channel_*` current API,不依赖 `channels_cmd.rs` 旧 CRUD 命令,并已完成宿主面下线:移除 `runner.rs` 注册、移除 `commands/mod.rs` 模块声明、删除 `channels_cmd.rs` 文件本体,同时补上 `legacySurfaceCatalog` 的命令组与 Rust 文本守卫 | 若不下线,Rust 侧注册与 stub 文件会继续制造“仓库还有另一套可用渠道管理面”的误导,影响 remote 主链收口;现已通过删除与守卫把这类误导性 surface 从宿主编译图中清出 | 已完成删除后的最小验证:`legacySurfaceCatalog.test.ts`、`governance:legacy-report`、`test:contracts`、`cargo check --manifest-path src-tauri/Cargo.toml -p lime --lib` 均通过;下一步回到 `CCD-007`,继续判断 `SendMessage / ListPeers` 的 `uds:` / `bridge:` cross-session peer transport 是否应进入 `current` | `docs/aiprompts/remote-runtime.md` | 已完成 | -| CCD-010 | 2026-04-20 | Resources / Library | 资料库页过去同时存在“大 Hero + 页面级添加入口 + 侧栏新建入口 + 空态动作卡 + store selector / page 各写一套搜索排序分类规则”的旧心智;当前已把资料库 current 主链收窄为“项目切换 / 分类切换 / 搜索排序 / 浏览打开 / 重命名删除 / 图片视图上传插入”,并新增 `resourceQueries` 作为目录视图、分类视图与目录派生状态共用的查询事实源;同时已删掉 `selectors` 中间层,把内容区顶部收成“控制栏 + 当前范围状态条”一套壳,并把跨项目媒体提示并入当前范围状态条、移除内容列表头里的重复最近更新徽标;本轮继续沿主链做减法,把顶部剩余的文件夹 / 内容项 / 最近更新三张统计卡收薄为贴近项目切换的一条只读摘要,并把这组项目级派生进一步收回 `resourceQueries`,避免页面层再保留平行统计逻辑 | 若停在旧状态,后续实现者会继续在页面和 selector 两侧分别补过滤/分类规则,导致资料库行为漂移,也容易把已删除的页面级创建入口或重复状态壳重新接回 current 主链;顶部总览若继续保留独立统计卡,后续改动也容易在 Hero、状态条和分页脚三处重新长出不同口径的数量文案 | 下一小步继续判断这条项目只读摘要是否还应下沉到左侧“资料库切换”卡,彻底把项目级信息和范围级信息拆开;若新增范围派生文案或查询规则,只允许落到 `src/components/resources/services/resourceQueries.ts` 与当前范围状态条,不再把范围说明或结果统计回灌到 Hero | `src/components/resources/ResourcesPage.tsx` / `src/components/resources/services/resourceQueries.ts` | 进行中 | diff --git a/docs/exec-plans/upstream-runtime-alignment-plan.md b/docs/exec-plans/upstream-runtime-alignment-plan.md deleted file mode 100644 index 258009984..000000000 --- a/docs/exec-plans/upstream-runtime-alignment-plan.md +++ /dev/null @@ -1,205 +0,0 @@ -# 参考运行时主链对齐计划 - -> 状态:进行中 -> 更新时间:2026-04-14 -> 对照基线:本地参考运行时源码镜像(2026-04-14 快照) -> 目标:把 Lime 与参考运行时的“运行时主链”对齐工作,收口成一份唯一的排期与差距事实源,避免路线图、治理减法和专题计划继续并行漂移。 - -## 1. 先给结论 - -Lime 当前不是“能力不够”,而是“主链不够单一”。 - -已确认的现状: - -- `Tool Runtime / MCP / evidence / replay / review / subagent` 已具备较强底座 -- `Query Loop`、`Task / Agent taxonomy`、`Remote runtime` 与 `Memory / Compaction` 已完成 current 主链收口 -- 现有对齐文档散落在 `roadmap/`、`tech/`、`develop/`、`exec-plans/`,导致排期和治理容易串线 - -本计划固定一个判断: - -**后续“对齐上游运行时”默认指向运行时主链对齐,而不是目录、UI 或命名的 1:1 复制。** - -## 2. 对齐口径 - -### 2.1 对齐什么 - -默认对齐下面六条运行时主链: - -1. `Query Loop` -2. `Tool Runtime` -3. `Memory / Compaction` -4. `Remote / SDK / Server Mode` -5. `Task / Agent / Coordinator` -6. `State / History / Telemetry` - -### 2.2 不对齐什么 - -- 不以上游运行时的目录结构作为目标 -- 不先追求 UI 行为逐像素一致 -- 不为了对齐而回退 Lime 已有的 GUI、Artifact、Provider、Workspace 优势 -- 不把已有专题路线图全部重写成新体系;已有文档保留为下游专项 - -## 2.3 当前进度 - -- `M0` 统一排期事实源:`done` -- `M1` Query Loop 收口:`done` -- `M2` Task / Agent taxonomy 收口:`done` -- `M3` Remote runtime 收口:`done` -- `M4` Memory / Compaction 收口:`done` -- `M5` State / History / Telemetry 收口:`done` -- 当前阶段:`六条运行时主链 current 入口已补齐,后续转入守 current 边界与 compat / deprecated 退场` -- 当前进度日志:`docs/exec-plans/upstream-runtime-alignment-progress.md` - -## 3. 主链差距矩阵 - -| 主链 | 参考运行时基线模块 | Lime 当前事实源 | 当前判断 | 主要差距 | 下一刀 | -| --- | --- | --- | --- | --- | --- | -| `Query Loop` | `QueryEngine.ts`、`query.ts`、`query/deps.ts`、`services/tools/*`、`services/compact/*` | `src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs`、`runtime_api.rs`、`tool_runtime.rs`、`docs/aiprompts/query-loop.md` | `aligned` | `Query Loop` current 事实源与主循环入口已收口;旧的 `alignment/state-model/conversation-efficiency` 专项文档都已退回 compat 历史档案,Artifact 文档族也已改回 current 入口引用;`TurnInputEnvelope -> SessionConfig` 的 turn context snapshot 分叉、`action_runtime` 辅助恢复链旁路,以及 `compact_session` 控制回合的最小上下文边界都已显式化;剩余散落在 `persona_cmd` / `theme_context_cmd` 的一次性临时会话配置已收口为专用 helper,零入口的旧 `AsterAgentWrapper::send_message` 已删除;Tauri 命令层原始 `agent.reply` / `stream_reply_with_policy` 扫描结果也已固定为 `action_runtime(current) + persona/theme_context(compat)` 三处,并补了源码扫描守卫 | 维持 aligned 主链;下一刀转向继续盘点 `src-tauri/src` 非命令层与 README/示例面是否还残留会误导实现者的原始执行旁路叙事 | -| `Tool Runtime` | `src/tools/*`、`services/tools/*`、`services/mcp/*`、`ToolSearchTool` | `src-tauri/src/agent_tools/catalog.rs`、`inventory.rs`、`src-tauri/src/commands/aster_agent_cmd/tool_runtime/*`、`docs/aiprompts/commands.md`、`docs/aiprompts/command-runtime.md`、`docs/prd/tools/architecture.md` | `aligned` | 能力基本齐,但仍需持续防止命名、inventory、mock、MCP 注入回退到第二事实源 | 维持 current 主链,后续只做减法和守卫,不新增并行入口 | -| `Memory / Compaction` | `services/compact/*`、`services/SessionMemory/*`、`memdir/*` | `docs/aiprompts/memory-compaction.md`、`src/lib/api/memoryRuntime.ts`、`src-tauri/src/commands/memory_management_cmd.rs`、`src-tauri/src/services/memory_source_resolver_service.rs`、`src-tauri/src/services/auto_memory_service.rs`、`src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs`、`src-tauri/src/commands/aster_agent_cmd/command_api/runtime_api.rs`、`src/lib/api/unifiedMemory.ts`、`src-tauri/src/commands/unified_memory_cmd.rs` | `aligned` | `M4` 已建立统一主链:`来源链解析 -> 单回合 prefetch -> runtime_turn prompt augmentation -> session compaction -> working/durable memory 沉淀 -> GUI 稳定读模型`;`project_memory_get` 退回 compat 附属层,`memory_feedback_cmd` 退回 deprecated | 转入 `M5`,固定 `session / thread / turn / request / evidence / history` 的 current 状态地图 | -| `Remote / SDK / Server Mode` | `remote/*`、`server/*`、`entrypoints/sdk/*`、`cli/transports/*` | `docs/aiprompts/remote-runtime.md`、`src/lib/api/channelsRuntime.ts`、`src-tauri/src/commands/gateway_channel_cmd.rs`、`src/lib/webview-api.ts`、`src-tauri/src/commands/browser_connector_cmd.rs`、`src-tauri/src/commands/webview_cmd.rs`、`src-tauri/src/commands/browser_runtime_cmd.rs`、`src-tauri/src/dev_bridge/*`、`src-tauri/src/services/openclaw_service/*`、`src-tauri/src/commands/telegram_remote_cmd.rs` | `aligned` | `M3` 已建立统一 remote 主链:`消息渠道 runtime + 浏览器连接器 / ChromeBridge` 是 current ingress,`DevBridge / OpenClaw` 退回 compat,`telegram_remote_cmd` 退回 deprecated;后续残余减法转入 compat surface 继续处理 | 维持 aligned 主链,后续只做 compat / deprecated 退场减法 | -| `Task / Agent / Coordinator` | `tasks/*`、`tools/AgentTool`、`Task*Tool`、`EnterWorktreeTool`、`RemoteTriggerTool`、`coordinator/*` | `docs/aiprompts/task-agent-taxonomy.md`、`docs/aiprompts/query-loop.md`、`src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs`、`src-tauri/src/services/execution_tracker_service.rs`、`src-tauri/src/services/automation_service/*`、`src-tauri/src/app/scheduler_service.rs` | `aligned` | `M2` 已建立统一 taxonomy:`agent turn / subagent turn / automation job` 是 current 一等执行实体,`ExecutionTracker` 是统一执行摘要层,`SchedulerService` 退回 compat 触发壳;后续残余减法转入 execution tracker / scheduler 专项继续处理 | 维持 aligned 主链,后续只做定点减法与回归修复 | -| `State / History / Telemetry` | `state/*`、`bootstrap/*`、`assistant/sessionHistory.ts`、`cli/transports/ccrClient.ts`、`services/analytics/*` | `docs/aiprompts/state-history-telemetry.md`、`src-tauri/crates/agent/src/session_store.rs`、`src-tauri/src/commands/aster_agent_cmd/dto.rs`、`src-tauri/src/commands/aster_agent_cmd/command_api/runtime_api.rs`、`src-tauri/src/services/thread_reliability_projection_service.rs`、`src-tauri/src/services/runtime_handoff_artifact_service.rs`、`src-tauri/src/services/runtime_evidence_pack_service.rs`、`src-tauri/src/services/runtime_replay_case_service.rs`、`src-tauri/src/services/runtime_review_decision_service.rs`、`scripts/harness-eval-history-record.mjs` | `aligned` | `M5` 已建立统一状态地图,并继续完成 compat/deprecated 收口:`reliability / state-model / alignment / conversation-efficiency` 这些重型 compat 文档都已压成历史摘要档案,`telemetry_cmd.rs` 只再保留原始日志面定位 | 维持 current 主链;文档侧重型 compat 路线图已基本收完,下一刀优先回到 current 代码边界继续做减法 | - -## 4. 现有文档归位 - -本计划是排期总入口,不替代现有专题方案。现有文档按下列方式归位: - -| 文档群 | 归属主链 | 角色 | -| --- | --- | --- | -| `docs/roadmap/lime-aster-codex-alignment-roadmap.md` | `Query Loop`、`State / History / Telemetry` | Aster/Codex umbrella 历史专项档案,已吸收原状态模型与执行效率子专题,不再承担仓库级总排期或 current 实施入口职责 | -| `docs/roadmap/reliability/*` | `State / History / Telemetry` | Reliability control plane 专项 | -| `docs/tech/harness/*`、`docs/roadmap/harness-engine/*` | `State / History / Telemetry`、`Memory / Compaction` | Evidence / replay / review / observability / cleanup 专项 | -| `docs/develop/execution-tracker-technical-plan.md`、`docs/develop/execution-tracker-p1-p2-roadmap.md`、`docs/develop/scheduler-task-governance-p1.md` | `Task / Agent / Coordinator` | 长时执行与治理专项 | -| `docs/aiprompts/commands.md`、`docs/aiprompts/command-runtime.md`、`docs/prd/tools/*` | `Tool Runtime` | 当前工具面与协议事实源 | - -如果后续新增专项文档,必须先标明它属于哪条主链;如果说不清主链归属,就不允许单独立项。 - -## 5. 排期纪律 - -从本计划起,后续排期默认遵守以下规则: - -1. 同一时间只允许 `1` 条主链作为主任务。 -2. 每轮最多再搭配 `1` 条服务主链的治理任务。 -3. 所有任务必须声明: - - 所属主链 - - 当前分类:`current / compat / deprecated / dead` - - 阶段出口 -4. 治理减法如果不能直接缩短主链,就登记到 `docs/exec-plans/tech-debt-tracker.md`,不直接插队。 -5. 专题路线图完成后,必须回写本计划的矩阵状态,避免“专题 done,但总盘子仍 unknown”。 - -## 6. 推荐推进顺序 - -### `M0` 统一排期事实源 - -- 建立本计划,固定六条主链 -- 把现有对齐文档回挂到单一总入口 -- 把当前未收口差距登记进技术债追踪 - -### `M1` Query Loop 收口 - -- 为 Lime 补一份单一 Query Loop 事实图 -- 明确 `submit_turn -> turn runtime -> tool orchestration -> compaction -> evidence` 的 current 主链 -- 退出条件:不再需要横跳多份文档才能解释 Lime 主循环 - -当前进度(2026-04-14): - -- 已完成第一刀:`docs/aiprompts/query-loop.md` 已成为 Query Loop current 入口 -- 已完成第二刀实现:`runtime_turn.rs` 已将 `run_start_metadata`、`runtime_status_session_config`、`build_session_config` 的重复拼装收口为稳定 helper,主循环可读性继续提升 -- 已完成第三刀实现:单次流式执行成功后的 Artifact 自动落盘与记忆沉淀已收口为统一 helper,主成功分支与降级成功分支不再各自维护重复收尾逻辑 -- 已完成第四刀实现:两处 `stream_reply_once` 的运行时事件记录闭包已收口为统一 helper,主分支与降级分支共享同一条事件记录路径 -- 已完成第五刀实现:`RunFinishDecision` 组装与 terminal result 收尾已收口为统一 helper,主循环不再内联 success/error 两套终态处理 -- 已完成第六刀实现:主执行分支与降级到 ReAct 的分支已共用“单次流式尝试” helper,`build_runtime_user_message(...)`、`build_session_config()`、`stream_reply_once(...)` 与成功收尾逻辑不再在主循环中重复展开 -- 已完成第七刀实现:`CodeOrchestrated` 的扩展启用、失败降级、扩展清理已收口为统一策略 helper,`with_run_custom(...)` 内只保留一次 Query Loop 执行入口 -- 已完成第八刀实现:runtime turn 初始化、status 投射与 service preload 事件已收口为统一前奏 helper,主循环的前置准备阶段已压成单一语义块 -- 已完成第九刀实现:`run_start_metadata`、`timeline_recorder`、`runtime_status_session_config` 与流式 `session_config` 构建状态已收口为统一 execution context,主循环不再散落拼装这组前置状态 -- 已完成第十刀实现:`run_observation`、`run_finish decision` 与 terminal finalize 链路已回收到 execution context,主循环不再手工拼接 tracked execution 与终态收尾 -- 已完成第十一刀实现:`skill_tool_session_access` 与 `cancel_token` 已收口为统一 session scope,异常路径与正常路径共享同一套会话级清理边界 -- 已完成第十二刀实现:`runtime_snapshot -> runtime_projection_snapshot -> turn_state -> turn_input_envelope` 已收口为统一 `build_runtime_turn_artifacts(...)` helper,主循环不再内联读取 snapshot、派生 thread/turn 和构建 turn 输入诊断 -- 已完成第十三刀实现:`service_skill_preload -> prepared execution -> prelude/execute handoff` 已收口为 `prepare_runtime_turn_execution(...)` 与 `RuntimeTurnPreparedExecution`,submit 主路径已压成更明确的 `prepare -> execute` 语义块 -- 已完成第十四刀实现:`provider_continuation -> workspace sandbox apply -> tracker/session scope bootstrap` 已收口为 `prepare_runtime_turn_submit_bootstrap(...)`,submit 主路径不再内联铺开这组前置副作用和运行期参数拼装 -- 已完成第十五刀实现:`request.provider_config -> configure_provider/configure_provider_from_pool -> persist_session_provider_routing` 已收口为 `apply_runtime_turn_provider_config(...)`,submit 主路径不再内联铺开 provider apply 分支 -- 已完成第十六刀实现:`resolved_prompt -> prompt augmentation -> requested/effective strategy persist` 已收口为 `prepare_runtime_turn_prompt_strategy(...)`,submit 主路径不再内联铺开 prompt/strategy 组装与持久化 -- 已完成第十七刀实现:`tool surface metadata -> MCP warmup -> skill launch metadata normalize -> turn_input_builder seed` 已收口为 `prepare_runtime_turn_request(...)`,submit 主路径不再内联铺开 request prepare 分支 -- 已完成第十八刀实现:`runtime_chat_mode -> web_search/request_tool_policy -> execution_profile` 已收口为 `prepare_runtime_turn_policy(...)`,submit 主路径不再内联铺开 policy resolve 逻辑 -- 已完成第十九刀实现:`auto_continue -> workspace repair warning -> session_state_snapshot/working_dir update -> session_recent_runtime_context` 已收口为 `prepare_runtime_turn_session(...)`,submit 主路径的 session 级前置准备已压成单一 helper -- 已完成第二十刀实现:`session/policy/request/prompt_strategy -> provider apply/bootstrap` 已收口为 `prepare_runtime_turn_submit_preparation(...)`,submit 主路径已提升为单一 preflight 准备块 -- 已完成第二十一刀实现:`sync_browser_assist_runtime_hint -> prepare_runtime_turn_execution -> agent guard -> emit_prelude_and_execute` 已收口为 `execute_runtime_turn_submit(...)`,submit 主路径当前已压成 `prepare -> scoped execute` 两段主骨架 -- 已完成第二十二刀实现:`provider_config resolve -> harness metadata normalize -> workspace resolve/turn id/runtime_config` 已收口为 `prepare_runtime_turn_ingress_context(...)`,入口上下文边界不再散落在主路径中 -- 已完成第二十三刀实现:`agent init/session_store check -> support tools register` 已收口为 `prepare_runtime_turn_entry(...)`,主路径的运行时入口准备已形成独立阶段 -- 已完成第二十四刀实现:`model_skill_tool_access derive -> with_runtime_turn_session_scope -> execute_runtime_turn_submit` 已收口为 `execute_runtime_turn_with_session_scope(...)`,主路径不再拆包又重组 `submit_preparation` -- 已完成第二十五刀实现:`execute_aster_chat_request(...)` 已把 `entry -> ingress -> submit_preparation -> session_scope_execute` 提升为单一 `execute_runtime_turn_pipeline(...)` 调用,`M1` 外层 orchestration 收口完成 -- 已补最小 Rust 定向校验:`env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target-runtime-turn-2" cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib commands::aster_agent_cmd::runtime_turn::tests:: -- --nocapture` 通过(`37 passed`,仅剩 `workspace_tools.rs` 既有 dead_code warning) -- 已补文档新鲜度校验:`npm run harness:doc-freshness` 通过(`clean`) -- 已补格式化校验:`cargo fmt --manifest-path "src-tauri/Cargo.toml" --all` 通过 -- `M1` 退出判断:已满足“不再需要横跳多份文档才能解释 Lime 主循环”的出口条件,后续不再继续细切 `M1` - -### `M2` Task / Agent taxonomy 收口 - -- 为 Lime 定义统一的 task / agent / coordinator 分型 -- 将 `execution tracker / scheduler / subagent / automation` 收回同一语义层 -- 退出条件:所有长时执行入口都能归到唯一 taxonomy - -当前进度(2026-04-14): - -- 已完成第一刀:`docs/aiprompts/task-agent-taxonomy.md` 已成为 Task / Agent / Coordinator current 入口 -- 已完成第二刀:`ExecutionTracker / subagent runtime / automation service / scheduler trigger` 的 `current / compat / deprecated / dead` 已有明确归类 -- 已完成第三刀:`docs/README.md`、`docs/aiprompts/README.md`、`docs/aiprompts/overview.md`、`AGENTS.md` 已同步回挂新入口,仓库导航不再继续把 scheduler/heartbeat 叙事误当 current 主线 -- `M2` 退出判断:已满足“所有长时执行入口都能归到唯一 taxonomy”的出口条件,后续不再把 execution tracker、scheduler、subagent、automation 分散解释为多条平级主线 - -### `M3` Remote runtime 收口 - -- 盘点 remote/dev bridge/browser remote/IM remote 入口 -- 声明唯一 current remote runtime -- 退出条件:remote 不再是多个并列产品旁路 - -当前进度(2026-04-14): - -- 已完成第一刀:`docs/aiprompts/remote-runtime.md` 已成为 Remote runtime current 入口 -- 已完成第二刀:`gateway_channel_* + browser connector / ChromeBridge` 已明确为 current remote ingress,`DevBridge / OpenClaw` 已归到 compat,`telegram_remote_cmd` 已归到 deprecated -- 已完成第三刀:`docs/README.md`、`docs/aiprompts/README.md`、`docs/aiprompts/overview.md`、`AGENTS.md` 已同步回挂新入口,仓库导航不再继续把 debug 桥或单通道 Telegram 入口误当 remote 主线 -- `M3` 退出判断:已满足“remote 不再是多个并列产品旁路”的出口条件,后续只在 current ingress 上新增能力,其余 remote 面默认只做减法与兼容维护 - -### `M4` Memory / Compaction 收口 - -- 固定压缩边界、记忆预取、恢复和用户可见状态的主链 -- 退出条件:`memory_runtime_*` 与 `compact_session` 不再被当成分散能力点看待 - -当前进度(2026-04-14): - -- 已完成第一刀:`docs/aiprompts/memory-compaction.md` 已成为 Memory / Compaction current 入口 -- 已完成第二刀:`来源链解析 -> 单回合 prefetch -> runtime_turn prompt augmentation -> session compaction -> working/durable memory 沉淀 -> GUI 稳定读模型` 已明确为 current 主链 -- 已完成第三刀:`project_memory_get` 与角色/世界观/大纲资料链已明确退回 compat 附属层,`memory_feedback_cmd` 已退回 deprecated,`memory_search_cmd.rs.bak` 已标记为 dead -- 已完成第四刀:`docs/README.md`、`docs/aiprompts/README.md`、`docs/aiprompts/overview.md`、`AGENTS.md` 已同步回挂新入口,仓库导航不再继续把项目资料聚合或旧 feedback 侧链误当成记忆 / 压缩主线 -- `M4` 退出判断:已满足“`memory_runtime_*` 与 `compact_session` 不再被当成分散能力点看待”的出口条件,后续只允许在 current 边界继续长记忆 / 压缩能力 - -### `M5` State / History / Telemetry 收口 - -- 把 reliability、harness、history、review、replay 的事实源统一成一张状态地图 -- 退出条件:session / thread / turn / request / evidence / history 的读模型叙事收口 - -当前进度(2026-04-14): - -- 已完成第一刀:`docs/aiprompts/state-history-telemetry.md` 已成为 State / History / Telemetry current 入口 -- 已完成第二刀:`agent_sessions / agent_messages -> SessionDetail -> AgentRuntimeThreadReadModel -> RequestLog 关联键 -> handoff/evidence/replay/analysis/review -> history-record/trend/cleanup/dashboard -> HarnessStatusPanel / AgentThreadReliabilityPanel` 已明确为 current 主链 -- 已完成第三刀:原 `state-model` 历史子专题、`docs/roadmap/reliability/*` 与 `telemetry_cmd.rs` 已明确退回 compat;cleanup 报表里残留的 `requestTelemetry:unlinked` 旧语义已明确为 deprecated -- 已完成第四刀:`docs/README.md`、`docs/aiprompts/README.md`、`docs/aiprompts/overview.md`、`AGENTS.md` 已同步回挂新入口,仓库导航不再继续把状态模型专题计划、reliability 计划或原始 request log 控制台误当成 current 主链 -- 已完成第五刀:`docs/roadmap/reliability/README.md` 已补成 compat 目录入口;cleanup 核心脚本已把旧 `requestTelemetry:unlinked` 样本折叠为 `known_gap`,避免旧历史语义继续充当现役状态类别 -- 已完成第六刀:`docs/roadmap/reliability/*.md` 全部补上 compat 提示,正文开头先回挂 `state-history-telemetry.md`;`telemetry_cmd.rs` 也已明确只暴露原始 `RequestLog` 与聚合统计,不再和 thread read / evidence 主链抢解释权 -- 已完成第七刀:`docs/roadmap/reliability/*.md` 顶部重复的上位文档列表已压成统一 `README + current 主链 + PR 对应映射` 导航,专项正文不再继续堆叠第二套入口说明 -- 已完成第八刀:整组 `docs/roadmap/reliability/*` 已进一步压缩为 compat 历史摘要档案,只保留落地结果、current 映射与延后增强项;重复的目标/问题/范围/实施清单正文已回退到仓库历史 -- 已完成第九刀:原 `state-model` 历史摘要已完成压缩并最终并入 `docs/roadmap/lime-aster-codex-alignment-roadmap.md`,current 入口固定回到 `query-loop / state-history-telemetry / upstream-runtime-alignment-plan` -- 已完成第十刀:`docs/roadmap/lime-aster-codex-alignment-roadmap.md` 已固定为 compat umbrella 历史档案,只保留阶段映射、状态模型与执行效率的核心判断 -- 已完成第十一刀:原 `conversation-execution-efficiency` 历史摘要已并入 `alignment-roadmap`,`docs/roadmap/artifacts/*` 对运行时边界的引用也已统一改回 `query-loop / task-agent-taxonomy / state-history-telemetry / upstream-runtime-alignment-plan` -- `M5` 退出判断:已满足“session / thread / turn / request / evidence / history 的读模型叙事收口”的出口条件,后续只允许在 current 边界上继续长能力 - -## 7. 当前默认判断 - -- `Tool Runtime` 继续视为 `current` -- `Query Loop`、`Task / Agent / Coordinator`、`Remote / SDK / Server Mode`、`Memory / Compaction`、`State / History / Telemetry` 视为 `aligned` - -当前最值得继续推进的一刀固定为: - -**文档侧重型 compat 路线图已基本压成历史摘要档案;当前已收口 `TurnInputEnvelope -> SessionConfig` 的 turn context snapshot 分叉、`action_runtime` 辅助恢复链的 turn context 旁路,并显式化 `compact_session` 控制回合的最小上下文边界;剩余散落在 `persona_cmd` / `theme_context_cmd` 的一次性临时会话配置也已收口为专用 helper,零入口旧发送壳已删除;Tauri 命令层原始执行面也已固定为 3 处并补了源码扫描守卫。下一刀转向继续盘点 `src-tauri/src` 非命令层与 README/示例面是否还残留会误导实现者的原始执行旁路叙事。** - -这样做的原因是:六条运行时主链的 current 入口已经补齐;cleanup 的旧 `unlinked` 语义、telemetry 原始浏览面定位,以及 `reliability / state-model / alignment / conversation-efficiency` 这些重型 compat 文档都已经被收紧。继续留在文档治理上的边际收益已经明显下降,下一步更值得回到 current 代码边界继续做减法。 diff --git a/docs/exec-plans/upstream-runtime-alignment-progress.md b/docs/exec-plans/upstream-runtime-alignment-progress.md deleted file mode 100644 index a9bd8bf4a..000000000 --- a/docs/exec-plans/upstream-runtime-alignment-progress.md +++ /dev/null @@ -1,2038 +0,0 @@ -# 参考运行时主链对齐进度日志 - -## 2026-04-20 - -### 已完成 - -- 基于本地参考运行时源码镜像 `/Users/coso/Documents/dev/js/claudecode` 与用户提供的 Claude Code runtime 架构图,重新按 `Query Loop / Tool Runtime / Memory / Remote / Task / State / Host Product Surface` 七组能力做了一次全局差距盘点,避免后续继续把“产品壳差异”和“运行时主链未对齐”混为一谈。 -- 重新核对现有总计划与仓库 current 文档后,确认 `Query Loop / Tool Runtime / Memory / Task / State` 六条运行时主链的判断不需要回退: - - [upstream-runtime-alignment-plan.md](./upstream-runtime-alignment-plan.md) 里已有的 `aligned` 结论仍然成立。 - - [task-agent-taxonomy.md](../aiprompts/task-agent-taxonomy.md) 与 [state-history-telemetry.md](../aiprompts/state-history-telemetry.md) 定义的 current 边界仍是正确事实源。 - - 这次差距盘点的重点应从“再补一套 runtime”转向“补宿主 surface 或明确不对齐的产品层选择”。 -- 明确当前最值得继续推进的 `current gap`: - - `ConfigTool` 仍缺少参考运行时那组宿主配置闭环:`classifierPermissionsEnabled / remoteControlAtStartup / taskCompleteNotifEnabled / inputNeededNotifEnabled / agentPushNotifEnabled` 当前仍是“已知上游 setting,但 Lime runtime 未实现”的状态;`permissions.defaultMode` 也尚未对齐参考运行时的 `plan / dontAsk` 口径。 - - `voiceEnabled` 已不再是完全缺失:`runtime_turn` 当前已经通过宿主 callback 回填 `ConfigTool` 读写链路,但它仍只覆盖语音开关本身,没有连带补齐参考运行时那组 remote-control / push-notification 宿主配置矩阵。 - - `SendMessage / ListPeers` 仍只覆盖 team 内 peers;参考运行时支持的 `uds:` / `bridge:` cross-session peer address 目前在 Lime 里仍是受控失败,说明 team runtime 的当前事实源虽然已收口,但跨会话协作 surface 还没补齐。 - - `hooks` 与 `skills` 仍是明显半成品:`MCP hook / Prompt hook / Agent hook` 还是占位实现,`SkillExecutionMode::Agent` 依旧未实现;这说明 Lime 已经有工具层 current surface,但还没补齐参考运行时图里那层可执行的 extension / hook orchestration。 - - 浏览器宿主工具面仍有明确缺口:`shortcuts_list` 还返回“当前后端尚未实现”,说明 browser / desktop host integration 仍未闭环。 -- 明确本轮盘点中不应被误判成“运行时未对齐”的部分: - - `OpenClaw / DevBridge / telegram_remote_cmd` 仍按 [remote-runtime.md](../aiprompts/remote-runtime.md) 的既有判断处理:它们属于 `compat / deprecated` 支撑面,不应再被拔高成需要追平参考运行时的 current remote control plane。 - - `channels_cmd.rs` 这组 AI / 通知渠道 CRUD 目前大多还是 `暂未实现` 空壳;由于仓库已明确“多渠道 current 主链已经迁到 gateway_channel_cmd.rs”,这组命令更像需要重新分类并收口的 legacy surface,而不是值得继续扩展的 current 功能。 - - `Buddy / Kairos / Ultraplan` 这类 feature-flagged 产品壳在参考运行时中属于宿主产品选择;Lime 当前源码里没有对应实现,这件事应先作为产品路线判断,而不是默认归入“主链未对齐”。 - -### 当前判断 - -- 这一步服务于运行时主链对齐的关系是:把“主链已对齐”与“宿主 surface 未补齐”明确拆开,避免后续继续在已完成的 `M1-M5` 主链上空转。 -- 目前最值得继续推进的一刀固定为: - - 先补 `ConfigTool + Remote Control / Push Notification` 这一组宿主配置 surface,再补 `SendMessage / ListPeers` 的 cross-session peer messaging。 - - 只有补完这两刀,参考运行时架构图里最关键的 `permissions/config/remote-control/team-runtime` 宿主面才会真正进入 Lime 的 `current` 主链,而不再停留在“工具存在、文档对齐、产品层仍缺口”的状态。 -- 后续默认顺序: - 1. `ConfigTool` 宿主配置矩阵收口。 - 2. `SendMessage / ListPeers` 的 `uds:` / `bridge:` peer transport 判断与实现。 - 3. `hooks / skills` 从占位实现推进到至少一条可执行 current 主链。 - 4. 再决定 `Buddy / Kairos / Ultraplan` 是否属于 Lime 产品路线,不默认把它们当作 runtime 对齐任务。 - -### 继续推进(ConfigTool / classifierPermissionsEnabled) - -- 在 [config_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/config_tool.rs) 把 `classifierPermissionsEnabled` 从“已知上游 setting,但固定 unsupported”提升为真正可读写的 current setting: - - `ConfigTool` 现在直接读写用户面 key `classifierPermissionsEnabled` - - 默认读取值收口为 `false` - - 读取时兼容旧内部 key `SECURITY_PROMPT_CLASSIFIER_ENABLED` - - 写入 current key 后会清掉旧内部 key,避免继续停留在“一套工具面、一套内部键”的双轨状态 -- 在 [security/mod.rs](../../src-tauri/crates/aster-rust/crates/aster/src/security/mod.rs) 把安全扫描 ML toggle 的事实源切到 current key,并把旧内部 key 降回 compat fallback: - - 当前 runtime 先读 `classifierPermissionsEnabled` - - 只有 current key 缺失时才回退 `SECURITY_PROMPT_CLASSIFIER_ENABLED` - - 这样 `ConfigTool` 写入的值会真实影响 `SecurityManager::is_ml_scanning_enabled()`,不再出现“Config 改了但安全扫描不认”的断层 -- 补定向回归: - - `ConfigTool` 新增 default false、legacy fallback、rewrite current key 的测试 - - `security/mod.rs` 新增 default false、legacy fallback、current precedence 的测试 -- 已执行校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/security/mod.rs" "src-tauri/crates/aster-rust/crates/aster/src/tools/config_tool.rs"` 通过 - - `env CARGO_TARGET_DIR="/tmp/lime-target-configtool-check" cargo check --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" --lib` 通过 - - `env CARGO_TARGET_DIR="/tmp/lime-target-configtool" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" config_tool --lib` 未能完成:当前工作区存在与本轮无关的既有编译错误 [execution/manager.rs](../../src-tauri/crates/aster-rust/crates/aster/src/execution/manager.rs) `query_session` 未导入,导致 test target 在进入 `ConfigTool` 测试前就失败 - -### 当前判断补充 - -- `CCD-006` 已从“整组 setting 都停留在 unsupported”前进到“至少 `classifierPermissionsEnabled` 已进入 current 主链并接上真实宿主行为”。 -- 这一步服务路线图主目标的关系是:先把确实已有宿主落点的配置面收回 current,避免继续把所有 host surface 缺口打成一个大包。 -- 当前 `Config / Host Surface` 剩余最值得继续推进的缺口变为: - - `remoteControlAtStartup` - - `taskCompleteNotifEnabled / inputNeededNotifEnabled / agentPushNotifEnabled` - - `permissions.defaultMode` 的 `plan / dontAsk` 语义 - 这些项仍不能硬映射到 Lime 现有的 OS 自启动、桌面通知或现有 runtime mode;下一刀应继续按“先找真实宿主落点,再决定 current / compat / deprecated”推进。 - -### 继续推进(ConfigTool / host audit) - -- 继续核对剩余 host settings 对应的真实宿主落点后,确认 `remoteControlAtStartup` 仍不能进入 `current`: - - Lime 当前只有 [config_cmd.rs](../../src-tauri/src/commands/config_cmd.rs) 的 `get_auto_launch_status / set_auto_launch` 这条 OS 登录项 `current` 主链。 - - 它控制的是“开机自启动”,不是参考运行时 `remoteControlAtStartup` 那种“默认是否为所有 session 开启 Remote Control”的语义。 - - 因此这项 setting 继续明确维持为 `unsupported`;不能把 `remoteControlAtStartup` 硬映射到 `auto_launch`。 -- 继续核对通知相关 surface 后,确认 `taskCompleteNotifEnabled / inputNeededNotifEnabled / agentPushNotifEnabled` 也还没有可接入的 `current` 宿主面: - - Lime 当前确实有 [update_cmd.rs](../../src-tauri/src/commands/update_cmd.rs) / [update_window.rs](../../src-tauri/src/services/update_window.rs) 这条更新提醒通知面,但它只服务“版本更新提醒”,不是 remote-control / mobile push。 - - [channels_cmd.rs](../../src-tauri/src/commands/channels_cmd.rs) 这组通知渠道 CRUD 仍主要返回 `暂未实现`,更接近 `deprecated` 候选 stub,而不是可复用的 mobile push control plane。 - - 因此这三项 setting 继续明确维持为 `unsupported`;不能把它们误判成“只差 Config 映射”。 -- 这次审计后,`CCD-006` 的事实源分类进一步收敛为: - - `classifierPermissionsEnabled`:`current` - - `voiceEnabled`:`current`(宿主 callback) - - `remoteControlAtStartup`:`current gap`,当前无真实宿主面 - - `taskCompleteNotifEnabled / inputNeededNotifEnabled / agentPushNotifEnabled`:`current gap`,当前无 mobile push control plane - - `get_auto_launch_status / set_auto_launch`:`current`,但仅属于 OS auto-launch,不属于 remote-control config - - `channels_cmd.rs` 通知渠道 CRUD:`deprecated` 候选,不作为这组 setting 的事实源 -- 这一步服务路线图主目标的关系是:继续把“宿主产品面缺口”和“还能在 current 主链补的 runtime 对齐项”拆开,避免后续再把现有 OS 自启动、更新提醒或 stub 渠道面误当成参考运行时的 remote-control / push-notification 对齐。 -- 当前 `CCD-006` 的下一刀收敛为两类选择: - - 真正新增 remote-control / mobile push 宿主面,再回头把这些 setting 接入 `current` - - 或把这组差异明确沉淀为产品层不对齐,不再把它们当成“只差一层映射”的 runtime 缺口 -- `permissions.defaultMode` 的 `plan / dontAsk` 仍单独保留: - - 仓库内部虽然已有 prompt 侧 `PermissionMode::Plan / DontAsk` 文本能力 - - 但 runtime config、provider flag 与 permission inspector 还没有等价 `current` 语义,暂时不能直接在 `ConfigTool` 放行 - -### 继续推进(ConfigTool / permissions.defaultMode 审计) - -- 继续沿 `permissions.defaultMode` 深挖后,确认 `plan / dontAsk` 仍不能进入 Lime `current`: - - [plan_mode_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/plan_mode_tool.rs) 的 `plan` 当前是显式 `EnterPlanMode / ExitPlanMode` 工具流,不是持久化的全局默认权限模式。 - - [claude_code.rs](../../src-tauri/crates/aster-rust/crates/aster/src/providers/claude_code.rs) 与 [codex.rs](../../src-tauri/crates/aster-rust/crates/aster/src/providers/codex.rs) 的 provider flag 仍只围绕 `ASTER_MODE = Auto / SmartApprove / Approve / Chat` 做映射,没有 `plan / dontAsk` 的全局执行语义。 - - [permission_inspector.rs](../../src-tauri/crates/aster-rust/crates/aster/src/permission/permission_inspector.rs) 的工具审批主链也只分支 `Chat / Auto / Approve / SmartApprove` 四类,没有 `dontAsk` 对应的全局判断分支。 -- 因此这次没有去“补 enum 让 ConfigTool 通过”,而是继续把边界收紧成真实语义: - - `plan` 的失败提示现在明确说明:它当前是工具驱动的 plan flow,不是 persisted default mode。 - - `dontAsk` 的失败提示现在明确说明:它当前缺少 provider flag + `PermissionInspector` 的全局 runtime 支撑。 -- 补定向回归: - - `ConfigTool` 新增 `plan` 专项失败断言,锁住它必须继续指向 `EnterPlanMode / ExitPlanMode` - - `ConfigTool` 新增 `dontAsk` 专项失败断言,锁住它必须继续暴露“缺少 provider / inspector runtime” -- 这一步服务路线图主目标的关系是:把 `permissions.defaultMode` 从“模糊地未实现”推进成“缺哪条 current 主链就明确说哪条”,避免后续 AI 或人工把 prompt 文本能力误判成已经具备可持久化的全局权限模式。 - -### 继续推进(CCD-009 / channels_cmd 治理守卫) - -- 顺手继续推进 `CCD-009` 后,确认 [ImConfigPage.tsx](../../src/components/channels/ImConfigPage.tsx) 当前走的是 [channelsRuntime.ts](../../src/lib/api/channelsRuntime.ts) 暴露的 `gateway_channel_* / *_channel_probe / wechat_channel_*` current API,而不是 `channels_cmd.rs` 那组旧 CRUD 命令。 -- 因此本轮没有去扩或修 [channels_cmd.rs](../../src-tauri/src/commands/channels_cmd.rs) 的 `暂未实现` stub,而是先把它纳入仓库治理守卫: - - 在 [legacySurfaceCatalog.json](../../src/lib/governance/legacySurfaceCatalog.json) 新增 `channels-crud-stub-commands` - - 把 `get_ai_channels / create_ai_channel / get_notification_channels / create_notification_channel` 等整组旧命令标成 `dead-candidate` - - 允许引用路径保持为空,意味着任何前端 `safeInvoke/invoke` 若再接回这组命令,`governance:legacy-report` 都会直接报违规 -- 补定向目录册测试: - - [legacySurfaceCatalog.test.ts](../../src/lib/governance/legacySurfaceCatalog.test.ts) 新增 `channels_cmd` 命令组断言,锁住分类、命令集合与 `allowedPaths=[]` -- 这一步服务路线图主目标的关系是:先封住旧 remote / notification CRUD 命令回流,避免后续 AI 在 current remote 主链已固定到 `gateway_channel_*` 的情况下,又从 `channels_cmd.rs` 这层 stub surface 重新长功能。 - -### 继续推进(CCD-009 / channels_cmd 下线) - -- 在确认 current 前端没有任何 `safeInvoke/invoke` 依赖这组命令后,本轮继续把 [channels_cmd.rs](../../src-tauri/src/commands/channels_cmd.rs) 从宿主命令面正式下线: - - 从 [runner.rs](../../src-tauri/src/app/runner.rs) 的 `tauri::generate_handler!` 移除了整组 `get_ai_channels / create_ai_channel / get_notification_channels / create_notification_channel` 等旧 CRUD 注册 - - 从 [commands/mod.rs](../../src-tauri/src/commands/mod.rs) 移除了 `pub mod channels_cmd;` - - 删除了 [channels_cmd.rs](../../src-tauri/src/commands/channels_cmd.rs) 文件本体,不再让这组 `暂未实现` stub 继续进入编译图 -- 为了防止这条旧路再次回流,又补了 Rust 侧治理守卫: - - 在 [legacySurfaceCatalog.json](../../src/lib/governance/legacySurfaceCatalog.json) 新增 `rust-channels-cmd-legacy-surfaces` - - 明确禁止 `commands::channels_cmd::` 与 `pub mod channels_cmd;` 重新出现在 Rust 代码中 - - 在 [legacySurfaceCatalog.test.ts](../../src/lib/governance/legacySurfaceCatalog.test.ts) 补了对应断言 -- 补了删除后的最小收尾验证: - - `npx vitest run "src/lib/governance/legacySurfaceCatalog.test.ts"` 通过(`129 passed`) - - `npm run governance:legacy-report` 通过;`rust-channels-cmd-legacy-surfaces` 命中为 `0`,整体 `边界违规=0` - - `npm run test:contracts` 通过;命令契约、Harness 契约与 cleanup contract 全部通过 - - `env CARGO_TARGET_DIR="/tmp/lime-target-channels-governance-check" cargo check --manifest-path "src-tauri/Cargo.toml" -p lime --lib` 通过,确认 `runner.rs / commands/mod.rs` 删除 `channels_cmd` 后没有新增编译悬挂 -- 当前分类已收口为: - - `src/lib/api/channelsRuntime.ts + gateway_channel_* + browser connector / ChromeBridge`:`current` - - `channels_cmd.rs` 旧 AI / 通知渠道 CRUD stub surface:`dead` - - `legacySurfaceCatalog` 中的 `channels-crud-stub-commands` 与 `rust-channels-cmd-legacy-surfaces`:继续保留为防回流守卫 -- 这一步服务路线图主目标的关系是:把 `channels_cmd.rs` 从“口头上判成 stub / deprecated 候选”推进成“宿主命令面已实际下线”,让 current remote 主链只剩 `gateway_channel_* + browser connector / ChromeBridge`。 -- `CCD-009` 至此可以视为已完成;下一刀应回到 `CCD-007`,继续判断 `SendMessage / ListPeers` 的 `uds:` / `bridge:` cross-session peer transport 是否进入 Lime `current`。 - -### 继续推进(CCD-007 / peer transport 可行性审计) - -- 继续对照参考运行时后,确认 `CCD-007` 当前缺的不是“把 `SendMessage` 放开到 `uds:` / `bridge:`”这一层,而是缺少 upstream 那套 cross-session peer transport 底座: - - 参考运行时在 `UDS_INBOX` 打开时会启动本地 UDS messaging server,提供 `uds:` ingress。 - - 参考运行时还会持续写 PID/session registry,并回填 session name 与 `bridgeSessionId`,供 `ListPeers` 发现本机会话与 remote peer。 - - 参考运行时的 `SendMessage` 也不是只做字符串判断;它会把 `bridge:` 真正投递到 remote peer channel,把 `uds:` 真正投递到本地 socket。 -- Lime 当前的 `current` 事实源还停留在 team runtime 内部: - - [subagent_tools.rs](../../src-tauri/src/commands/aster_agent_cmd/tool_runtime/subagent_tools.rs) 里 `SendMessage` / `SendInput` callback 最终只会走 `agent_runtime_send_subagent_input_internal(...)` - - [execution/manager.rs](../../src-tauri/crates/aster-rust/crates/aster/src/execution/manager.rs) 的 `send_input_with_runtime(...)` 只能把消息排进已存在的 session runtime queue,本质上还是“对现有 session_id 排队 turn” - - [team_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/team_tools.rs) 的 `ListPeers` 只从 `TeamSessionState` 枚举 team 内成员,`send_to` 也只有 teammate name;没有 session registry、没有 socket 地址、没有 remote bridge peer id - - [agent_control.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/agent_control.rs) 对 `uds:` / `bridge:` 目前仍是正确的“受控失败”,它只是防止误投,不代表已经具备 transport -- 因此 `CCD-007` 的下一刀不该再表述为“是否要支持两个地址前缀”,而应收敛成先选 transport 底座: - - 若要补本机 cross-session peer messaging,至少需要一套 Lime 自己的 session discovery / reachability registry,并定义与 upstream `uds:` 的兼容映射 - - 若要补 remote peer messaging,至少需要一套独立于 `browser connector / ChromeBridge` 的 remote session identity + ingress 当前事实源;现有 browser bridge 不能直接冒充 `bridge:session_*` - - 在这两套底座都不存在之前,继续保持 `uds:` / `bridge:` 受控失败是正确的 current 行为 -- 这一步服务路线图主目标的关系是:把 `CCD-007` 从“看起来像一个小工具参数差异”重新校准为“缺 session registry / local ingress / remote ingress 三块底座”,避免后续继续在错误抽象层空转。 -- 当前最值得继续推进的一刀变为: - - 优先判断 Lime 是否真的需要“本机跨会话 peer messaging”这条产品能力;若需要,先设计 Lime 自己的 local session registry,再决定是否对外兼容 `uds:` 语义 - - `bridge:` remote peer messaging 暂不建议先做,因为 Lime 当前 remote `current` 主链仍是 browser connector / ChromeBridge,而不是参考仓库的 Remote Control peer session - -### 继续推进(CCD-007 / local session peer 最小 current) - -- 在不引入新 socket/remote transport 的前提下,先把 Lime 已有 `session_id + runtime queue` 收成一条最小本机 cross-session `current`: - - [ListPeers](../../src-tauri/crates/aster-rust/crates/aster/src/tools/team_tools.rs) 不再只返回 team 成员;现在会继续保留活跃 team peers,并额外枚举同一 `working_dir` 下最近 `12` 个本机顶层 session(`User / Scheduled / Terminal`),其 `send_to` 固定为 synthetic `uds:` - - 这条 `uds:` 目前不是参考运行时那种真实 socket path,而是 Lime current 的兼容地址语义,用来把“本机会话 peer”稳定映射到现有 `session_id` - - team peers 仍保持原状:`send_to=name`、`agent_id=name@team`;因此现有 team runtime surface 没有回退 -- [SendMessage](../../src-tauri/crates/aster-rust/crates/aster/src/tools/agent_control.rs) 现在正式接住这条本地 peer surface: - - `to="uds:"` 会先校验目标 session 存在,随后复用现有 `send_input` callback,把消息排进目标 session 的 runtime queue - - 这条本机 cross-session 路径只接受纯文本消息;结构化 `shutdown_request / shutdown_response / plan_approval_response` 仍明确拒绝,避免误把 team protocol 平移到跨会话 session - - 为了保留 reply 语义,投递到目标 session 前会把正文包装成 `...`;接收侧至少能看见来源地址,而不会和普通用户输入完全混在一起 - - `bridge:` 仍保持受控失败,继续明确为“remote peer messaging 未进入 current” -- 这一步的边界结论也更清楚了: - - `current`:team peer messaging、同一 `working_dir` 下的 synthetic `uds:` local session peer messaging - - `current gap`:真实 live session registry、真正的 UDS socket ingress、`bridge:` remote peer identity / ingress - - `deprecated / dead`:无新增;本轮没有回流旧 remote surface -- 这一步服务路线图主目标的关系是:先把参考运行时图里“本机跨会话协作”压缩成一条 Lime 能真实交付的 current 路径,不再停留在“只会识别前缀但始终失败”的半成品状态;下一刀应继续判断是否需要把 synthetic local registry 提升成真正的 live registry,以及是否值得单独实现 `bridge:` remote peer transport。 - -### 继续推进(CCD-007 / live-aware local peer registry 收口) - -- 在不新增 socket / remote ingress 的前提下,继续把 synthetic local peer surface 从“只有 recent fallback”收成“live-aware current”: - - [runtime_queue.rs](../../src-tauri/crates/aster-rust/crates/aster/src/session/runtime_queue.rs) 现在新增 `list_live_session_ids()`,会把 runtime queue 的 active session 与 queued session 合并成一份最小 live session 视图,避免 `ListPeers` 再逐个 session 猜测 reachability。 - - [team_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/team_tools.rs) 现在会优先返回同一 `working_dir` 下 live 的本机顶层 session;只有 live peers 不足时,才按 `updated_at` 回退到最近 session。因此当前 `ListPeers` 不再只是“历史记录列表”,而是“live-first + recent fallback”的 synthetic local registry。 -- 对照本地参考仓库 [`peerAddress.ts`](../../../../js/claudecode/src/utils/peerAddress.ts)、[`SendMessageTool.ts`](../../../../js/claudecode/src/tools/SendMessageTool/SendMessageTool.ts) 与 [`prompt.ts`](../../../../js/claudecode/src/tools/SendMessageTool/prompt.ts) 后,又把 local peer address 语义重新收口了一次: - - [agent_control.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/agent_control.rs) 现在只把显式 `to="uds:"` 视为 synthetic local peer address,并仅在这条路径上省略 `summary`、追加 `` 包装;不再把 bare local `session_id` 当成 cross-session peer address fallback。 - - [team_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/team_tools.rs) 也同步把工具描述钉回“本机会话请使用 `send_to` 里的 `uds:` 地址发送,不要把 `agent_id` 当作 peer address”,避免模型继续沿错误 surface 学习。 -- 这一步后的边界收紧为: - - `current`:team peers、live-first 的 synthetic local session peers、显式 `uds:` cross-session local dispatch - - `current gap`:显式 session registry 持久化、真实 UDS ingress、bare local `session_id` peer address fallback、remote `bridge:` peer identity / ingress - - `compat / deprecated / dead`:无新增;本轮没有引入第二套 local peer 路由 -- 这一步服务路线图主目标的关系是:把 `CCD-007` 的最小 local current 从“勉强可用的 recent session fallback”继续收成“live-first 且显式地址面受控”的 current,避免 Lime 在参考运行时明确不存在的 bare session-id 地址面上继续漂移;下一刀若继续推进,应优先判断是否值得把这份 synthetic live registry 升格成显式 session registry / local ingress,而不是直接跨到 `bridge:`。 -- `CCD-007` 至此可以视为已完成:当前 misleading peer surface 已全部收掉,Lime 的 `current` 已明确固定为“team peers + live-first synthetic local peers + 显式 `uds:` 地址面”;剩余 `session registry / local ingress / remote bridge ingress` 差距若未来需要推进,应另开 transport / host 专题,而不是继续在 `SendMessage / ListPeers` 当前 surface 上做假对齐。 - -### 继续推进(CCD-008 / SkillTool current) - -- 继续对照参考运行时后,确认 Lime 在 `skills` 这一层的最大假对齐点其实不是 `WorkflowTool`,而是 [tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/skills/tool.rs) 里的 `SkillTool`: - - 参考运行时里,skills 并不是只登记一次调用意图;它们会真正进入 prompt / workflow / agent 执行链。 - - Lime 之前的 `SkillTool` 只会返回 `Launching skill: ...`,本质上还是占位壳;即使 skill frontmatter 已声明 `execution-mode: workflow`,工具面也没有真实执行。 -- 本轮先把这条最显眼的占位执行链收成最小 `current`: - - [tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/skills/tool.rs) 现在改为持有显式 registry,不再把 `SkillTool` 绑定死在全局单例,后续也更适合定向测试和局部收口。 - - `SkillTool` 现在会像 [workflow_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/workflow_tool.rs) 一样解析当前 session provider;若 skill 自己绑定 provider,也会复用当前 provider 或按绑定名创建 provider,不再只回一句“已启动”。 - - `Prompt` 与 `Workflow` 两种 `execution_mode` 现在都会通过 `SkillExecutor` 真实执行,输出会回带 `success / output / error / stepsCompleted` 元数据;`Workflow` 不再只是“另有 WorkflowTool 可用”的旁路能力。 - - `SkillExecutionMode::Agent` 仍保持明确失败:当前 runtime 继续返回“尚未实现 SkillExecutionMode::Agent”,避免把多轮 agent orchestration 假装成已经 current。 -- 这一步后的分类也更清楚了: - - `current`:`SkillTool` 的 prompt/workflow 执行、`WorkflowTool` 的 workflow 执行、基于当前 session/provider 的 skill 执行解析 - - `current gap`:`SkillExecutionMode::Agent`、skill frontmatter hooks、skill 级 hook 注册与执行编排 - - `compat / deprecated / dead`:无新增;本轮没有再引入第二套 skill 执行壳 -- 已执行校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/skills/tool.rs"` 通过 - - `env CARGO_INCREMENTAL=0 RUSTFLAGS="-Cdebuginfo=0" CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_skill_tool_executes_prompt_skill_with_provider --lib --no-default-features -- --nocapture` 通过(`1 passed`) - - `env CARGO_INCREMENTAL=0 RUSTFLAGS="-Cdebuginfo=0" CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_skill_tool_executes_workflow_skill_with_provider --lib --no-default-features -- --nocapture` 通过(`1 passed`) - - `env CARGO_INCREMENTAL=0 RUSTFLAGS="-Cdebuginfo=0" CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_skill_tool_rejects_agent_mode_skill --lib --no-default-features -- --nocapture` 通过(`1 passed`) - - `env CARGO_INCREMENTAL=0 RUSTFLAGS="-Cdebuginfo=0" CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo check --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" --lib --tests --no-default-features` 已尝试执行;当前阻塞来自现有 `providers.rs` 集成测试在关闭 `provider-aws` feature 时仍引用 `bedrock / sagemaker_tgi`,不是本轮 `SkillTool` 改动引入 -- 这一步服务路线图主目标的关系是:先把参考运行时图里“skills 真正可执行”这条主链从 placeholder 推进成 current,避免 `CCD-008` 长期停留在“工具名看起来对齐、实际没有执行”的假完成状态;下一刀应回到 hooks 的真实加载与执行链。 - -### 继续推进(CCD-008 / hooks-skills gap 审计) - -- 继续对照 `/Users/coso/Documents/dev/js/claudecode` 后,`hooks / skills` 的剩余差距已经可以拆成 4 条具体链路,而不再只是笼统一句“hooks 半成品”: - - 参考运行时在 [loadSkillsDir.ts](/Users/coso/Documents/dev/js/claudecode/src/skills/loadSkillsDir.ts) 与 [loadAgentsDir.ts](/Users/coso/Documents/dev/js/claudecode/src/tools/AgentTool/loadAgentsDir.ts) 会从 frontmatter 解析 `hooks`;Lime 当前 [types.rs](../../src-tauri/crates/aster-rust/crates/aster/src/skills/types.rs) 的 `SkillFrontmatter` 还没有 `hooks` 字段,[loader.rs](../../src-tauri/crates/aster-rust/crates/aster/src/skills/loader.rs) 也不会解析这层配置。 - - 参考运行时在 [hooks.ts](/Users/coso/Documents/dev/js/claudecode/src/utils/hooks.ts)、[execPromptHook.ts](/Users/coso/Documents/dev/js/claudecode/src/utils/hooks/execPromptHook.ts) 与 [execAgentHook.ts](/Users/coso/Documents/dev/js/claudecode/src/utils/hooks/execAgentHook.ts) 里会真实执行 `prompt / agent` hooks;Lime 当前 [executor.rs](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/executor.rs) 只有 `command / url` 进入真实执行,`mcp / prompt / agent` 仍然是 `warn! + success(None)` 的占位实现。 - - 参考运行时不仅能加载 hooks,还会从 plugin / settings / frontmatter 合并并热更新;Lime 当前虽然有 [loader.rs](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/loader.rs) 能读 `.claude/settings.json` 与 `.claude/hooks/*.json`,但仓库里还没有稳定 `current` bootstrap 在 session 启动时调用 `load_project_hooks(...)`,也没有 plugin hook load / hot reload 主链。 - - 参考运行时的 hook event 面更宽,包含 `Setup / CwdChanged / FileChanged / PermissionDenied / Elicitation / WorktreeCreate` 等;Lime 当前 [types.rs](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/types.rs) 还缺这一整批 event,现有真实调用点基本只落在 [task_list_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/task_list_tools.rs) 的 `TaskCreated / TaskCompleted`。 -- 因此 `CCD-008` 当前更准确的边界应该是: - - `current`:`TaskCreated / TaskCompleted` hooks、`command / url` hook executor、`SkillTool` prompt/workflow execution - - `current gap`:project hooks 加载入口、hook event 矩阵、`prompt / mcp / agent` hook executor、skill/agent frontmatter hooks、plugin hooks/hot reload、`SkillExecutionMode::Agent` - - `compat / deprecated / dead`:暂无额外 legacy surface 需要回流;当前主要问题是执行链缺失,而不是旧链未删干净 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 从“好像哪里都缺一点”收敛成可下刀的 4 条执行链,避免后续又去补 schema、枚举或文案,却没有真的补到 hooks/skills 的 current 主路径。 -- 当前最值得继续推进的一刀也更明确了: - - 先把 `load_project_hooks(...) + 一个已存在 executor-backed event` 收成第一条真正的 hooks current 主链,优先考虑 `UserPromptSubmit` 或 `SessionStart` - - 等加载入口与第一条 event 跑通后,再决定是补 `Prompt hook` 还是继续上探 `Agent hook / MCP hook` - -### 继续推进(CCD-008 / UserPromptSubmit hooks current) - -- 这一轮继续沿上一刀确定的主线,把 project hooks 的第一条真实运行时链路收成 `UserPromptSubmit current`,而不是继续停留在“loader 有了、executor 有了、runtime 没人调用”的半成品: - - [loader.rs](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/loader.rs) 新增 `load_project_hooks_to_registry(...)`,并让现有 `load_hooks_from_file(...) / load_project_hooks(...)` 都回收到底层 `*_to_registry` 路径,避免再维持“一套全局加载逻辑 + 一套局部加载逻辑”的双轨。 - - [executor.rs](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/executor.rs) 新增 `run_hooks_with_registry(...)` 与 `run_user_prompt_submit_hooks_with_registry(...)`;现有全局 helper 现在只是委托到 registry-aware 执行器,不再把“只能跑全局注册表”当成 hooks 的隐式前提。 - - [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 现在会在 `prepare_runtime_turn_ingress_context(...)` 之后、`prepare_runtime_turn_submit_preparation(...)` 之前,为当前 `workspace_root` 创建临时 registry,加载 `.claude/settings.json` 与 `.claude/hooks/*.json`,然后对 `request.message` 执行 `UserPromptSubmit`;若 hook 返回 block,则在真正 submit 前直接短路返回错误。 -- 这一步后的分类再次收紧为: - - `current`:`TaskCreated / TaskCompleted` hooks、`command / url` hook executor、project-level `UserPromptSubmit` hooks、`SkillTool` prompt/workflow execution - - `current gap`:`SessionStart` 等更多 event 的 runtime bootstrap、`prompt / mcp / agent` hook executor、skill/agent frontmatter hooks、plugin hooks/hot reload、`SkillExecutionMode::Agent` - - `compat / deprecated / dead`:无新增;本轮没有为了接 runtime 而把 hooks 再接回全局共享状态 -- 已执行校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/hooks/loader.rs" "src-tauri/crates/aster-rust/crates/aster/src/hooks/executor.rs" "src-tauri/crates/aster-rust/crates/aster/src/hooks/tests.rs" "src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs"` 通过 - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_run_user_prompt_submit_hooks_with_registry_blocks_project_hook --lib --no-default-features` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/Cargo.toml" enforce_runtime_turn_user_prompt_submit_hooks_should_ --lib` 通过(`2 passed`) -- 这一步服务路线图主目标的关系是:把参考运行时图里“project hooks 真能拦截用户提交”这条最贴主链的 extension path 收成 Lime 的第一条 hooks `current`,避免 `CCD-008` 继续停在“只有 task hooks 真执行,用户输入主链仍完全绕过 hooks”。 -- 下一刀应继续回到同一主线: - - 优先把 `SessionStart` 接到这条新的 per-registry runtime bootstrap 上 - - 然后再决定是继续扩 event 矩阵,还是开始把 `Prompt hook` 从占位 executor 推进成真实执行 - -### 继续推进(CCD-008 / SessionStart hooks current) - -- 这一轮继续沿同一条 per-registry hooks 主链,把 `SessionStart` 收到 Lime 的 runtime session 创建入口上,而不是把 hook 语义下沉到 `SessionManager::create_session(...)` 这种底层公共能力: - - 新增 [runtime_project_hooks.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs),把“按 `workspace_root` 创建临时 registry、加载 project hooks、执行指定 event”收成单一 helper;`runtime_turn` 的 `UserPromptSubmit` 现在也复用这层,不再自己拼 registry。 - - [executor.rs](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/executor.rs) 新增 `run_session_start_hooks_with_registry(...)`,让 `SessionStart` 也能像 `UserPromptSubmit` 一样基于指定 registry 执行,而不是只能依赖全局注册表。 - - [session_runtime.rs](../../src-tauri/src/commands/aster_agent_cmd/session_runtime.rs) 的 `create_runtime_session_internal(...)` 现在会在创建 session 并持久化默认 access mode 后,对当前 workspace 运行 project-level `SessionStart`,其 `source` 固定落为 `startup`;hook 执行失败或返回 block 只记录 warning,不会反向阻断 session 创建。 -- 这一步后的分类继续收紧为: - - `current`:`TaskCreated / TaskCompleted` hooks、project-level `UserPromptSubmit` hooks、project-level `SessionStart` hooks、`command / url` hook executor、`SkillTool` prompt/workflow execution - - `current gap`:`SessionStart` 的 `resume / clear / compact` 复用、更多 runtime event bootstrap、`prompt / mcp / agent` hook executor、skill/agent frontmatter hooks、plugin hooks/hot reload、`SkillExecutionMode::Agent` - - `compat / deprecated / dead`:无新增;本轮没有把 hooks 再扩散到底层 `SessionManager` 或其它非主路径 -- 已执行校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/hooks/executor.rs" "src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs" "src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs" "src-tauri/src/commands/aster_agent_cmd/session_runtime.rs" "src-tauri/src/commands/aster_agent_cmd/mod.rs"` 通过 - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/Cargo.toml" create_runtime_session_internal_should_run_project_session_start_hooks --lib` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/Cargo.toml" enforce_runtime_turn_user_prompt_submit_hooks_should_ --lib` 通过(`2 passed`) -- 这一步服务路线图主目标的关系是:把参考运行时图里“session start 也会经过 project hooks”这条 extension 主链补进 Lime 的 current,而不是继续停留在“只有用户提交会经过 hooks,创建新 session 仍完全绕过 hooks”的半成品状态。 -- 下一刀应继续回到同一条主链: - - 优先把 `SessionStart` 的 `resume / clear / compact` 也复用到这套 per-registry bootstrap - - 或者开始把 `Prompt hook` 从占位 executor 推进成真实执行,但不建议两条线同时铺开 - -### 继续推进(CCD-008 / SessionStart compact hooks current) - -- 这一轮继续沿同一条 per-registry hooks 主链,把 `SessionStart(compact)` 也接进 Lime 的 runtime `current`,并且仍然只落在宿主入口,不把 hooks 语义下沉到更底层公共能力: - - [runtime_project_hooks.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 新增 `resolve_runtime_project_hook_workspace_root(...)` 与 `run_runtime_session_start_project_hooks_for_session(...)`,先按 `session_id -> runtime session detail -> workspace_id` 反查当前 workspace;若 workspace 已缺失,再显式回退 `working_dir`,避免 compact 阶段重新散落一套“自己猜 project root”的旁路。 - - [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 的 `compact_runtime_session_with_trigger(...)` 现在会在压缩成功、终态事件写回后,继续对当前 session 执行 project-level `SessionStart`,其 `source` 固定落为 `compact`;hook 执行失败或返回 block 仍只记 warning,不会反向破坏 compact 成功结果。 - - [runtime_project_hooks.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 也补了两组定向测试,分别覆盖: - - 正常 `workspace_id -> workspace_root` 路径会收到 `source=compact` - - workspace 缺失时会回退 `working_dir`,而不是直接让 compact hook 静默失效 -- 这一步后的分类继续收紧为: - - `current`:`TaskCreated / TaskCompleted` hooks、project-level `UserPromptSubmit` hooks、project-level `SessionStart(startup / compact)` hooks、`command / url` hook executor、`SkillTool` prompt/workflow execution - - `current gap`:`SessionStart(resume)` 是否存在真实 current 入口仍待确认;`/clear` 当前只是前端本地状态清空,不应再伪造为后端 `SessionStart(clear)`。除此之外,更多 runtime event bootstrap、`prompt / mcp / agent` hook executor、skill/agent frontmatter hooks、plugin hooks/hot reload、`SkillExecutionMode::Agent` 仍缺席 - - `compat / deprecated / dead`:无新增;本轮没有把 hooks 回流到底层 `SessionManager`,也没有为了凑齐 event 枚举去伪造 `clear` 生命周期 -- 已执行校验: - - `rustfmt --edition 2021 "src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs" "src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs"` 通过 - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/Cargo.toml" run_runtime_session_start_project_hooks_for_session_should_ --lib` 通过(`2 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/Cargo.toml" create_runtime_session_internal_should_run_project_session_start_hooks --lib` 通过(`1 passed`) -- 这一步服务路线图主目标的关系是:把参考运行时图里 `SessionStart(compact)` 这条 extension 主链真正补进 Lime 的宿主 `current`,不再停留在“新建 session 会走 hooks,但 compact 后的新上下文不会重新经过 project hooks”的半成品状态。 -- 下一刀应继续回到同一条主链: - - 优先判断 Lime 当前是否存在可被接受为 `SessionStart(resume)` 的真实 session 恢复入口;若没有,就不要硬映射 - - 或者开始把 `Prompt hook` 从占位 executor 推进成真实执行,但不建议与 `resume` 语义判定并行铺开 - -### 继续推进(CCD-008 / Prompt hook current) - -- 这一轮继续沿 `hooks / skills` 主链往前推,但没有把 `agent_runtime_resume_thread` 硬映射成 `SessionStart(resume)`: - - 重新核对 [command_api/runtime_api.rs](../../src-tauri/src/commands/aster_agent_cmd/command_api/runtime_api.rs) 后,确认 Lime 当前公开的是“恢复排队线程执行”,不是 Claude Code 那种明确的 session lifecycle resume;因此 `SessionStart(resume)` 继续保留为 `current gap`,不做假对齐。 - - [executor.rs](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/executor.rs) 的 `Prompt hook` 已从 `warn! + success(None)` 占位实现推进成真实执行: - - 新增 prompt 参数注入与 JSON 结果解析 helper,支持 `$ARGUMENTS` 替换;未显式使用占位符时会把 hook input JSON 追加到 prompt 尾部。 - - 新增按 `session_id -> query_session(...)` 解析当前 session `provider_name / model_config` 的 provider 选择逻辑;有 session 上下文时优先复用当前 session provider,没有 session 时才回退 `ASTER_PROVIDER / ASTER_MODEL`。 - - 新增最小 `output_schema` turn context,把 hook 输出约束到 `{"ok":true}` / `{"ok":false,"reason":"..."}` 两种 JSON 形态;解析失败会返回显式 failure,`ok=false` 时会产出真实的 blocked 结果。 -- 这一步后的分类继续收紧为: - - `current`:`TaskCreated / TaskCompleted` hooks、project-level `UserPromptSubmit` hooks、project-level `SessionStart(startup / compact)` hooks、`command / url / prompt` hook executor、`SkillTool` prompt/workflow execution - - `current gap`:`SessionStart(resume)` 是否存在真实入口仍待确认;`MCP hook / Agent hook` 仍是占位实现;skill/agent frontmatter hooks、plugin hooks/hot reload、`SkillExecutionMode::Agent` 仍缺席 - - `compat / deprecated / dead`:无新增;本轮没有为了凑齐 prompt hook 去引入第二套 provider 选择壳,也没有把 queue resume 伪装成 session lifecycle -- 已执行校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/hooks/executor.rs"` 通过 - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" execute_prompt_hook_with_provider_should_ --lib --no-default-features` 通过(`2 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" replace_prompt_hook_arguments_should_append_json_when_no_placeholder --lib --no-default-features` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" parse_prompt_hook_response_should_accept_fenced_json --lib --no-default-features` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_run_user_prompt_submit_hooks_with_registry_blocks_project_hook --lib --no-default-features` 通过(`1 passed`) -- 这一步服务路线图主目标的关系是:把参考运行时图里 `Prompt hook` 这条扩展执行链从“类型存在、执行器空壳”推进到 Lime 的 current,不再停留在“只有 command/url hook 能真正做判断,prompt hook 永远只是占位”的半成品状态。 -- 下一刀应继续回到同一条主链: - - 优先判断 `Agent hook` 能否沿同样的 provider / JSON decision 边界推进成最小 current - - 或继续核定 `SessionStart(resume)` 是否有真实宿主入口;若没有,就明确保留为 gap,不再反复犹豫 - -## 2026-04-16 - -### 已完成 - -- 在 [auto_memory_service.rs](../../src-tauri/src/services/auto_memory_service.rs) 把 `memdir` 从“无限追加日志”收成“有界目录”: - - `feedback / project / user / reference` 的 typed topic note 现在按“同 topic 一条当前记忆”覆盖更新,不再持续追加时间戳段落 - - 新增 `cleanup_memdir(...)`,统一负责去重入口链接、裁剪 README 历史段落,并把旧 topic 日志收口为当前有效版本 - - `MEMORY.md` 入口的时间戳 note 现在会在写入时自动去重并保留有界窗口,避免入口长期劣化成无上限流水账 -- 在 [memory_management_cmd.rs](../../src-tauri/src/commands/memory_management_cmd.rs)、[memory_runtime.rs](../../src-tauri/src/dev_bridge/dispatcher/memory_runtime.rs)、[runner.rs](../../src-tauri/src/app/runner.rs)、[memoryRuntime.ts](../../src/lib/api/memoryRuntime.ts)、[memoryRuntimeTypes.ts](../../src/lib/api/memoryRuntimeTypes.ts)、[core.ts](../../src/lib/tauri-mock/core.ts) 与 [mockPriorityCommands.ts](../../src/lib/dev-bridge/mockPriorityCommands.ts) 补齐 `memory_cleanup_memdir` 这条 current control-plane 命令,不再让 memdir 整理只停留在本地脚本或人工编辑 -- 在 [memory_source_resolver_service.rs](../../src-tauri/src/services/memory_source_resolver_service.rs) 调整 memdir linked item 的 prompt 预取优先级:具体 topic note 会优先于类型 `README.md`,同层内优先看最近更新时间,减少索引文件长期压过真正当前记忆的噪音 -- 在 [index.tsx](../../src/components/settings-v2/general/memory/index.tsx) 补上真实的 `整理 memdir` 入口,并把“同一 topic 会覆盖旧内容”的行为写回设置页说明;MemorySettings 不再只是能写、能初始化,还能直接治理已有脏记忆 -- 补回归: - - [auto_memory_service.rs](../../src-tauri/src/services/auto_memory_service.rs) 新增 typed topic overwrite 与 memdir cleanup 定向测试 - - [memory_source_resolver_service.rs](../../src-tauri/src/services/memory_source_resolver_service.rs) 新增“具体 topic 优先于 README”测试 - - [memoryRuntime.test.ts](../../src/lib/api/memoryRuntime.test.ts) 与 [index.test.tsx](../../src/components/settings-v2/general/memory/index.test.tsx) 新增 `memory_cleanup_memdir / 整理 memdir` 前端链路回归 -- 已执行校验: - - `npx prettier --write "src/lib/api/memoryRuntime.ts" "src/lib/api/memoryRuntimeTypes.ts" "src/lib/api/memoryRuntime.test.ts" "src/lib/tauri-mock/core.ts" "src/lib/dev-bridge/mockPriorityCommands.ts" "src/components/settings-v2/general/memory/index.tsx" "src/components/settings-v2/general/memory/index.test.tsx"` 通过 - - `rustfmt --edition 2021 "src-tauri/src/services/auto_memory_service.rs" "src-tauri/src/services/memory_source_resolver_service.rs" "src-tauri/src/commands/memory_management_cmd.rs" "src-tauri/src/dev_bridge/dispatcher/memory_runtime.rs" "src-tauri/src/app/runner.rs"` 通过 - - `npm exec vitest run "src/lib/api/memoryRuntime.test.ts" "src/components/settings-v2/general/memory/index.test.tsx" "src/lib/dev-bridge/mockPriorityCommands.test.ts"` 通过(`18 passed`) - -- 在 [verify-gui-smoke.mjs](../../scripts/verify-gui-smoke.mjs) 收紧 `waitForBridgeHealth` 的启动判定:不再把 `tauri dev` 父进程退出直接等同为失败,而是继续观察 GUI smoke 进程组是否仍有活跃 `cargo/rustc/tauri` 链路;同时把“编译结束后的 boot grace”放宽到“父进程仍活着或进程组仍活着”两种场景,避免冷启动时因为父进程提前退场而误判 `headless Tauri 在 DevBridge 就绪前提前退出` -- 已重新执行 `npm run verify:gui-smoke -- --timeout-ms 1200000 --cargo-target-dir "/tmp/lime-gui-smoke-target-debug-parent-exit"` 并通过:`workspace-ready`、`browser-runtime`、`site-adapters`、`agent-service-skill-entry`、`agent-runtime-tool-surface`、`agent-runtime-tool-surface-page` 全链路冒烟通过,GUI smoke 主路径重新恢复到 Lime 可交付门槛 -- 已再次核对 smoke Chrome profile 清理收口:GUI smoke 收尾后 `find "$HOME/Library/Application Support/lime/chrome_profiles" -maxdepth 1 -type d \( -name 'smoke-browser-runtime*' -o -name 'smoke-agent-runtime-tool-surface-page*' \) | sort` 结果为空;本轮预清理日志显示共回收 `78` 个历史 profile、结束 `264` 个残留进程,收尾阶段再清掉本轮新增的 `5` 个 profile 与 `2` 个残留进程 -- 在 [webview_cmd.rs](../../src-tauri/src/commands/webview_cmd.rs)、[runner.rs](../../src-tauri/src/app/runner.rs)、[bridge.rs](../../src-tauri/src/dev_bridge/dispatcher/browser/bridge.rs) 与 [core.ts](../../src/lib/tauri-mock/core.ts) 补上 `cleanup_gui_smoke_chrome_profiles` 这条 DevBridge current 清理命令:它只识别 `smoke-browser-runtime*` 与 `smoke-agent-runtime-tool-surface-page*` 两类 GUI smoke 专用 Chrome profile,统一收口“关闭受管 session / 关闭 runtime session / 杀掉孤儿 Chrome 进程 / 清 singleton 锁 / 删除 profile 目录”,不再把历史遗留清理逻辑散落在脚本层自己拼 `ps/find/rm` -- 在 [verify-gui-smoke.mjs](../../scripts/verify-gui-smoke.mjs) 接上新的清理主链:health URL 现在会自动推导 `invoke` 地址,bridge 就绪后会先做一次历史 `smoke-*` Chrome profile 预清理,所有 smoke 结束后再做一次收尾清理,失败场景也会走兜底清理日志;后续 GUI smoke 不再只解决“本轮别再新增泄漏”,而是开始回收旧 profile 垃圾 -- 在 [webview_cmd.rs](../../src-tauri/src/commands/webview_cmd.rs) 补定向回归:新增 `is_gui_smoke_chrome_profile_key_should_only_match_expected_prefixes` 与 `cleanup_gui_smoke_chrome_profiles_should_remove_only_smoke_dirs`,锁定只清 GUI smoke profile、不误删普通浏览器资料的边界 -- 已执行校验: - - `node --check "scripts/verify-gui-smoke.mjs"` 通过 - - `env CARGO_TARGET_DIR="/tmp/lime-target-gui-smoke-cleanup" cargo test --manifest-path "src-tauri/Cargo.toml" cleanup_gui_smoke_chrome_profiles_should_remove_only_smoke_dirs --lib -- --nocapture` 通过(`1 passed`) - - `npm run test:contracts` 通过 - - `npm run verify:gui-smoke -- --timeout-ms 1200000 --cargo-target-dir "/tmp/lime-gui-smoke-target-debug-parent-exit"` 通过 - -### 当前观察 - -- `verify:gui-smoke` 这条质量门槛本轮已经恢复为绿色,不再阻塞 `memdir` / memory 主线继续推进 -- 本次长冷启动通过时,现场另一个本地 `lime` 进程最终占住了 `127.0.0.1:3030`(当前可见 PID `32676`),因此我这条独立 headless binary 在真正启动后记录了 `Dev Bridge 启动失败: Address already in use (os error 48)`;也就是说,这次通过证明了脚本不会再因为冷启动等待而误判失败,但若后续要证明“本实例独占 3030 也能启动”,仍应在更干净的本地环境或独立端口策略下复验 - -### 继续推进(file checkpoint UI) - -- 在 [AgentThreadFileCheckpointDialog.tsx](../../src/components/agent/chat/components/AgentThreadFileCheckpointDialog.tsx) 新增最小 file checkpoint dialog,直接消费 `agent_runtime_list_file_checkpoints / agent_runtime_get_file_checkpoint / agent_runtime_diff_file_checkpoint` 这条 current 主链;弹窗打开时拉 list,默认选中最近 checkpoint,并在切换条目时并行刷新 detail / diff,不再只停留在可靠性面板上的单条“最近文件快照”摘要 -- 在 [AgentThreadReliabilityPanel.tsx](../../src/components/agent/chat/components/AgentThreadReliabilityPanel.tsx) 给“最近文件快照”卡片补上 `查看快照详情` 入口,并把弹窗状态维持在面板当前上下文内:只有存在 `diagnosticRuntimeContext.sessionId` 时才暴露入口,继续沿当前 thread/session 真相消费,不额外长第二套文件持久化读模型 -- 在 [AgentThreadReliabilityPanel.test.tsx](../../src/components/agent/chat/components/AgentThreadReliabilityPanel.test.tsx) 补上 file checkpoint 交互回归,覆盖入口出现、打开弹窗后拉 list、默认选中最近 checkpoint 拉 detail/diff,以及切换到旧版本 checkpoint 后重新刷新 detail/diff 与关键字段渲染 -- 在 [agent_sessions.rs](../../src-tauri/src/dev_bridge/dispatcher/agent_sessions.rs) 把 `agent_runtime_list_file_checkpoints / agent_runtime_get_file_checkpoint / agent_runtime_diff_file_checkpoint` 接回 browser DevBridge current 分发,不再让真实 GUI 在弹窗打开后掉回 `[DevBridge] 未知命令` -- 在 [dispatcher.rs](../../src-tauri/src/dev_bridge/dispatcher.rs) 补上 `agent_runtime_file_checkpoint_commands_are_bridged` 定向回归,锁定这 3 个命令至少已经进入 `agent_sessions` bridge 分支;即使测试态没有 `AppHandle`,也应报 `Dev Bridge 未持有 AppHandle`,而不是回退成 unknown command -- 为恢复本地真实 GUI 续测,又顺手收掉了当前工作区里会卡死 `tauri:dev:headless` 的一组 Rust 编译半状态:当前确认需要把 [api_key_provider_service.rs](../../src-tauri/crates/services/src/api_key_provider_service.rs) 中 `test_codex_responses_endpoint(...)` 的签名与 3 处调用点对齐到同一套 5 参链路,避免 `provider_type` 在调用侧 / 定义侧来回失配把整条 DevBridge 启动链卡死 -- 已用真实 GUI 复测打通 file checkpoint 弹窗主链:本地 `npm run tauri:dev:headless` 已成功启动 `target/debug/lime`,`npm run bridge:health -- --timeout-ms 30000` 返回 `status=ok`;随后在历史会话 `Hello greeting`(`session=6e7f8e4b-129a-4f78-9ad0-41d8a7a801ec`)里进入 `任务中心 -> 切换历史 -> Hello greeting -> 展开工作台 -> 线程可靠性 -> 查看快照详情`,弹窗已真实显示 `共 1 个` checkpoint、默认选中 `v1`、标题 `你好!👋`、状态 `draft`、`live_path / snapshot_path / currentVersionId` 以及完整 `ArtifactDocument` JSON,说明 browser DevBridge 已经从“unknown command”前进到真实 `list / detail / diff` 数据面 -- 已执行校验: - - `npx vitest run "src/components/agent/chat/components/AgentThreadReliabilityPanel.test.tsx"` 通过(`15 passed`) - - `npm run test:contracts` 通过 - - `npm run typecheck` 通过 - - `npm run tauri:dev:headless` 通过增量重编成功启动 `target/debug/lime` - - `npm run bridge:health -- --timeout-ms 30000` 通过(`status=ok`) - - `npm run verify:local` 已尝试执行,但当前仓库存在 `291` 个脏改,smart 模式被放大为全仓 workflow;本轮仅确认其已通过 `verify:app-version / lint / typecheck` 并进入 `vitest-smart` 多批次执行,随后为避免被无关改动长期占用而手动停止 - - `npm run verify:gui-smoke` 的这轮旧阻塞已在本节上方收口;当前 file checkpoint 弹窗链路也已补到真实 GUI 证据,不过现场仍可见与本轮主线无关的 browser DevBridge 缺口:`sceneapp_list_catalog`、`gateway_channel_status` 仍报 unknown command;其中历史会话里 `agent_runtime_update_session` 的 `full-access` / `full_access` 枚举别名 warning 已开始在 current DTO/agent runtime 边界收口,尚未单独做一次真实 GUI 复测 - -### 继续推进(recent_access_mode alias cleanup) - -- 在 [session_execution_runtime.rs](../../src-tauri/crates/agent/src/session_execution_runtime.rs) 把 `SessionExecutionRuntimeAccessMode` 的 serde 口径从只认 `snake_case` 收口为 `kebab-case` current 真相,并为历史 `read_only / full_access` 增加兼容 alias;后续 `recent_access_mode` 的序列化结果会稳定回到前端与运行时元数据已经在使用的 `read-only / current / full-access` -- 在 [tests.rs](../../src-tauri/src/commands/aster_agent_cmd/tests.rs) 补上 `agent_runtime_update_session` 的 `recentAccessMode` 反序列化回归,锁定 browser DevBridge / GUI 历史会话当前实际发送的 `full-access` 不会再因为 Rust DTO 只认 `full_access` 而掉 warning -- 已执行校验: - - `rustfmt --edition 2021 "src-tauri/crates/agent/src/session_execution_runtime.rs" "src-tauri/src/commands/aster_agent_cmd/tests.rs"` 通过 - - `npx vitest run "src/components/agent/chat/components/AgentThreadReliabilityPanel.test.tsx"` 通过(复跑,`15 passed`) - - `src-tauri/target/debug/deps/lime_lib-f738bc5b97ece89b --exact commands::aster_agent_cmd::tests::test_agent_runtime_update_session_request_deserializes_recent_access_mode_aliases --nocapture` 通过(`1 passed`) - - 已做真实 GUI 续测:`npm run bridge:health -- --timeout-ms 15000` 返回 `status=ok` 后,复用 `http://127.0.0.1:1420/` 现有页签重载首页,再沿 `任务中心 -> 切换历史 -> Hello greeting -> 展开工作台 -> 查看快照详情` 复走 file checkpoint 弹窗链路;控制台只剩既有的 `gateway_channel_status` / `sceneapp_list_catalog` unknown command 与 `i18n` warning,未再出现 `agent_runtime_update_session` 或 `full-access / full_access` 相关 warning - - `SessionExecutionRuntimeAccessMode` 自身的 agent crate 单测已补代码,但本地存在其他长期 `cargo run` 进程占用默认 Cargo cache;尝试绕开锁时会退化成重新下载整套 crates,因此本轮未继续等待 agent crate 独立测试跑完 - -## 2026-04-15 - -### 已完成 - -- 在 [runtime_file_checkpoint_service.rs](../../src-tauri/src/services/runtime_file_checkpoint_service.rs)、[dto.rs](../../src-tauri/src/commands/aster_agent_cmd/dto.rs) 与 [runtime_api.rs](../../src-tauri/src/commands/aster_agent_cmd/command_api/runtime_api.rs) 补上 runtime file checkpoint current 主链:继续以 `SessionDetail.items -> FileArtifact -> artifact_document_service sidecar` 为唯一事实源,新增 `thread_read.file_checkpoint_summary` 轻摘要,以及 `agent_runtime_list_file_checkpoints / agent_runtime_get_file_checkpoint / agent_runtime_diff_file_checkpoint` 三个 current 命令,不再引入第二套 transcript 文件真相 -- 在 [runtime_evidence_pack_service.rs](../../src-tauri/src/services/runtime_evidence_pack_service.rs) 与 [runtime_replay_case_service.rs](../../src-tauri/src/services/runtime_replay_case_service.rs) 把 `fileCheckpoints / fileCheckpointCount` 正式接入 evidence / replay sidecar,analysis / review / replay 后续统一复用同一份 checkpoint 读模型,不再各自重新扫描 artifact 状态 -- 在 [types.ts](../../src/lib/api/agentRuntime/types.ts)、[threadClient.ts](../../src/lib/api/agentRuntime/threadClient.ts)、[agentRuntimeCommandSchema.json](../../src/lib/governance/agentRuntimeCommandSchema.json)、[agentCommandCatalog.json](../../src/lib/governance/agentCommandCatalog.json)、[mockPriorityCommands.ts](../../src/lib/dev-bridge/mockPriorityCommands.ts) 与 [core.ts](../../src/lib/tauri-mock/core.ts) 同步命令边界五侧,生成清单 [commandManifest.generated.ts](../../src/lib/api/agentRuntime/commandManifest.generated.ts) 也已刷新,新的 file checkpoint 命令继续落在 `agent_runtime_*` current gateway,而不是 compat/legacy 旁路 -- 在 [AgentThreadReliabilityPanel.tsx](../../src/components/agent/chat/components/AgentThreadReliabilityPanel.tsx) 新增“最近文件快照”摘要块,并在 [AgentThreadReliabilityPanel.test.tsx](../../src/components/agent/chat/components/AgentThreadReliabilityPanel.test.tsx) 补稳定断言;同时建立持久化 current 文档 [persistence-map.md](../aiprompts/persistence-map.md),并回挂到 [docs/README.md](../README.md)、[docs/aiprompts/README.md](../aiprompts/README.md) 与 [AGENTS.md](../../AGENTS.md) -- 在 [runtime_evidence_pack_service.rs](../../src-tauri/src/services/runtime_evidence_pack_service.rs) 与 [runtime_replay_case_service.rs](../../src-tauri/src/services/runtime_replay_case_service.rs) 的现有测试里补上 `fileCheckpointCount / fileCheckpoints / checkpoint_id / path` 断言,确保 evidence / replay 已真实消费新的 checkpoint 读模型,而不是只在实现侧悄悄接线 -- 已执行校验: - - `node scripts/generate-agent-runtime-clients.mjs` 通过 - - `npx vitest run "src/components/agent/chat/components/AgentThreadReliabilityPanel.test.tsx" "src/lib/dev-bridge/mockPriorityCommands.test.ts"` 通过(`17 passed`) - - `npm run test:contracts` 通过 - - `npm run typecheck` 通过 - - `npx vitest run "src/components/api-key-provider/ProviderConfigForm.ui.test.tsx" "src/components/settings-v2/general/memory/index.test.tsx"` 通过(`19 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo check --manifest-path "src-tauri/Cargo.toml" --lib` 通过 - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/Cargo.toml" runtime_file_checkpoint_service::tests:: --lib -- --nocapture` 通过(`3 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/Cargo.toml" should_export_runtime_ --lib -- --nocapture` 通过(`6 passed`) - - `npm run verify:gui-smoke` 通过(复用现有 headless 环境,`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` 全部通过) - - `npm run verify:local` 通过 -- 当前更高层验证状态: - - 之前记录里的 `should_export_runtime_` / `SceneAppRunSummary` 阻塞已不再复现;当前仓库中的 `sceneapp` 初始化点已补齐新字段,本轮实际阻塞改为 [claude_custom.rs](../../src-tauri/crates/providers/src/providers/claude_custom.rs) 的 `Default` 实现缺口,现已修复并复测通过 - - 之前记录里的 `verify:local` TypeScript 阻塞也已修复;[ProviderConfigForm.ui.test.tsx](../../src/components/api-key-provider/ProviderConfigForm.ui.test.tsx) 与 [index.tsx](../../src/components/settings-v2/general/memory/index.tsx) 的类型问题不再复现,本轮已重新从统一入口跑通 `npm run verify:local` - -- 在 [auto_memory_service.rs](../../src-tauri/src/services/auto_memory_service.rs) 将自动记忆入口收口为 `memdir` 主链:新增 `user / feedback / project / reference` 四类目录脚手架、最小 provider seam、topic 文件递归索引与 `memory_type / provider / updated_at` 元数据;`feedback / project` 写入现在强制要求 `Why:` 与 `How to apply:` 结构,`project` 同时拒绝 `今天 / tomorrow / next week` 这类相对时间词,避免记忆过期后继续误导执行 -- 在 [memory_source_resolver_service.rs](../../src-tauri/src/services/memory_source_resolver_service.rs) 为来源链读模型补齐 `source_bucket / provider / memory_type / updated_at`,并让 `auto_memory_item` 真正进入 runtime 解析与 prompt 来源链;同时把 `memory_type` 约束到 memdir 来源,不再误打到普通项目规则或其它非 memdir 文件 -- 在 [memoryRuntimeTypes.ts](../../src/lib/api/memoryRuntimeTypes.ts)、[index.tsx](../../src/components/settings-v2/general/memory/index.tsx) 与 [MemoryPage.tsx](../../src/components/memory/MemoryPage.tsx) 同步前端主链:设置页可以直接初始化 `memdir`、按类型写入真实 note,并在前端先做结构化/绝对日期拦截;Memory 页面与设置页当前都按 `memdir` 分类、provider、最近更新时间展示真实来源,不再沿用旧的外部工具记忆心智文案 -- 将这轮 `memdir` 约束与元数据回写到 [memory-compaction.md](../aiprompts/memory-compaction.md),明确 `MEMORY.md -> user|feedback|project|reference` 是 current 组织方式,topic 文件必须继续挂在同一条索引主链下 -- 在 [browser-runtime-smoke.mjs](../../scripts/browser-runtime-smoke.mjs) 与 [agent-runtime-tool-surface-page-smoke.mjs](../../scripts/agent-runtime-tool-surface-page-smoke.mjs) 补上固定 smoke profile key 与 `close_chrome_profile_session` 前后清理,避免每次 GUI smoke 都遗留新的 headless Chrome profile 进程,连带拖慢后续 `browser_execute_action` 页面 smoke -- 已执行校验: - - `npm exec vitest run "src/lib/api/memoryRuntime.test.ts" "src/components/settings-v2/general/memory/index.test.tsx" "src/components/memory/MemoryPage.test.tsx"` 通过(`26 passed`) - - `npm run test:contracts` 通过 - - `npm run verify:gui-smoke -- --cargo-target-dir "/tmp/lime-gui-smoke-target-memdir-codex"` 通过(`workspace-ready / browser-runtime / site-adapters / agent-service-skill-entry / agent-runtime-tool-surface / agent-runtime-tool-surface-page` 全部通过) - -- 在 [tests.rs](../../src-tauri/src/commands/aster_agent_cmd/tests.rs) 新增基础 Prompt 主链源码守卫,固定 `runtime_turn` 的 current 组装顺序:入口段必须保持 `RuntimeAgents -> ExplicitLocalPathFocus -> FullRuntime/FastChat 分流`,`build_full_runtime_system_prompt(...)` 必须保持 `Memory -> ... -> AutoContinue` 的既定 augmentation 顺序,`ServiceSkillLaunchPreload` 只能在 FullRuntime 下作为尾部追加阶段 -- 同步把 `service_skill_launch_preload` 相关重复测试 fixture 收口为共享 helper,减少同一预执行样例在多条测试里重复内联,避免后续调整站点技能预执行 contract 时只改一半测试 -- 补最贴边界的定向校验: - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/Cargo.toml" runtime_turn_source_keeps --lib -- --nocapture` 通过(`3 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/Cargo.toml" service_skill_launch_preload --lib -- --nocapture` 通过(`3 passed`) - -### 继续推进(browser DevBridge sceneapp / channels current 收口) - -- 在 [sceneapp.rs](../../src-tauri/src/dev_bridge/dispatcher/sceneapp.rs)、[channels.rs](../../src-tauri/src/dev_bridge/dispatcher/channels.rs) 与 [dispatcher.rs](../../src-tauri/src/dev_bridge/dispatcher.rs) 把 `sceneapp_list_catalog`、`gateway_channel_status`、`wechat_channel_list_accounts` 继续接回 browser DevBridge current 分发;[dispatcher.rs](../../src-tauri/src/dev_bridge/dispatcher.rs) 也新增 `sceneapp_list_catalog_is_bridged`、`gateway_channel_status_is_bridged`、`wechat_channel_list_accounts_is_bridged` 定向守卫,锁定这些命令已进入对应 bridge 分支,不再回退成 `[DevBridge] 未知命令` -- 在 [agentCommandCatalog.json](../../src/lib/governance/agentCommandCatalog.json)、[mockPriorityCommands.ts](../../src/lib/dev-bridge/mockPriorityCommands.ts)、[mockPriorityCommands.test.ts](../../src/lib/dev-bridge/mockPriorityCommands.test.ts) 与 [core.ts](../../src/lib/tauri-mock/core.ts) 同步命令边界四侧: - - `gateway_channel_status` 与 `wechat_channel_list_accounts` 现在都被视为 browser 模式下必须走 bridge 真相的 current runtime gateway 命令 - - `wechat_channel_list_accounts` 同步补进默认 mock,避免非 browser 模式的开发回路缺少返回形态 -- 在 [wechat_channel_cmd.rs](../../src-tauri/src/commands/wechat_channel_cmd.rs) 抽出纯 helper `list_wechat_configured_accounts(...)`,让 Tauri 命令与 browser DevBridge 共享同一段“列微信账号”逻辑;不再把 `tauri::State` 包装态直接透传进 bridge 分支,避免 bridge 场景里额外引入命令包装态阻塞 -- 已执行校验: - - `npm test -- src/lib/dev-bridge/mockPriorityCommands.test.ts` 通过(`3 passed`) - - `npm run test:bridge` 通过(`22 passed`) - - `npm run test:contracts` 通过 - - `env CARGO_TARGET_DIR="/tmp/lime-devbridge-current-tests" cargo test --manifest-path "src-tauri/Cargo.toml" sceneapp_list_catalog_is_bridged --lib -- --nocapture` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/tmp/lime-devbridge-current-tests" cargo test --manifest-path "src-tauri/Cargo.toml" gateway_channel_status_is_bridged --lib -- --nocapture` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/tmp/lime-devbridge-current-tests" cargo test --manifest-path "src-tauri/Cargo.toml" wechat_channel_list_accounts_is_bridged --lib -- --nocapture` 通过(`1 passed`) -- 已补现场证据: - - 活跃在 `127.0.0.1:3030` 的旧 bridge 一度是 Codex 自己遗留的 [lime](/Users/coso/Documents/dev/ai/aiclientproxy/lime/src-tauri/target/debug/lime) 实例;该旧进程对 `sceneapp_list_catalog`、`gateway_channel_status` 的 `curl /invoke` 已能返回 `200`,但 `wechat_channel_list_accounts` 仍返回 `[DevBridge] 未知命令`,说明真实 GUI 当时看到的是“上一刀已生效、这一刀尚未热更新”的混合现场 - - 在清掉这条 Codex 遗留 bridge 后,`127.0.0.1:3030` 一度空闲,随后又被另一条 Codex 派生的 [lime](/Users/coso/Documents/dev/ai/aiclientproxy/lime/src-tauri/target/debug/lime) 实例接管;`/health` 与 `gateway_channel_status` 已恢复 `200` - - 当前活跃 bridge 上,`curl /invoke` 已能真实返回 `wechat_channel_list_accounts` 的账号目录,例如 `774304b339c6@im.bot` 这条已启用账号会返回 `baseUrl=https://ilinkai.weixin.qq.com`、`cdnBaseUrl=https://novac2c.cdn.weixin.qq.com/c2c`、`hasToken=true` 与 `scannerUserId` - - 真实 GUI 续测到的错误类型已经从 `[DevBridge] 未知命令` 前移为 bridge 级超时:在 `消息渠道 -> 高级排障 -> 微信` 页,控制台已出现 `wechat_channel_list_accounts` / `gateway_channel_status` 的调用与 `timeout after 1800ms`,不再是 `unknown command` -- 在 [http-client.ts](../../src/lib/dev-bridge/http-client.ts) 收紧 browser DevBridge HTTP client 的时序策略: - - `sceneapp_list_catalog`、`gateway_channel_status`、`wechat_channel_list_accounts` 等“必须以 bridge 为真相”的命令现在统一使用 `5000ms` 请求超时,不再沿用默认 `1800ms` - - `fetch_provider_models_auto`、`test_api_key_provider_connection`、`test_api_key_provider_chat` 三条 provider 探测命令继续使用 `30000ms` 长超时,避免模型目录探测在浏览器模式下过早被前端判死 - - `ensureBridgeReachable()` 对“首个 health probe timeout”不再直接写入 cooldown;只有硬连接失败才进入 `bridge cooldown active`,避免首页第一次慢探测把后续数秒都拖进假性不可用 -- 在 [http-client.test.ts](../../src/lib/dev-bridge/http-client.test.ts) 补齐回归护栏: - - 区分“硬连接失败会进入 cooldown”和“timeout 只会触发重试,不会立刻 cooldown” - - 锁定 bridge 真相命令的 `5000ms` 超时窗口与 provider 探测命令的 `30000ms` 超时窗口 - - 锁定事件流监听只会在硬连接失败后的短退避窗口里阻止新 `EventSource` 建连 -- 本轮追加校验: - - `npm test -- src/lib/dev-bridge/http-client.test.ts` 通过(`10 passed`) - - `npm test -- src/lib/dev-bridge/mockPriorityCommands.test.ts` 通过(`3 passed`) - - `npm run test:bridge` 通过(`22 passed`) - - `npm run test:contracts` 通过 -- 本轮追加 live 证据: - - `curl -sS -m 5 "http://127.0.0.1:3030/health"` 返回 `{"service":"DevBridge","status":"ok","version":"1.0.0"}` - - `curl -sS -m 10 -X POST "http://127.0.0.1:3030/invoke" -d '{"cmd":"sceneapp_list_catalog"}'` 返回 scene app catalog - - `curl -sS -m 10 -X POST "http://127.0.0.1:3030/invoke" -d '{"cmd":"gateway_channel_status","args":{"request":{"channel":"wechat"}}}'` 返回 `{"channel":"wechat","status":{"accounts":[],"runningAccounts":0}}` - - `curl -sS -m 10 -X POST "http://127.0.0.1:3030/invoke" -d '{"cmd":"wechat_channel_list_accounts"}'` 返回真实微信账号目录,当前可见 `774304b339c6@im.bot` - -### 当前观察 - -- `sceneapp_list_catalog`、`gateway_channel_status`、`wechat_channel_list_accounts` 三条 current bridge 命令现在都已经具备代码、契约、Rust 定向测试与 live `/invoke` 证据;消息渠道页的真实 blocker 已经从 `unknown command` 前移到 bridge 性能/时序层,而不再是命令缺口 -- 由于现场存在多条长期 `tauri dev` / `lime` 进程,本轮继续保留“用隔离 `CARGO_TARGET_DIR` 串行验证 bridge 改动”的做法,避免再次和默认 Cargo target 抢锁;后续若继续做消息渠道页的 GUI 续测,应优先复用当前已经接管 `3030` 的新版 bridge,而不是再让 Codex 遗留实例占住端口 -- 本轮尝试继续做 GUI 复测时,`Playwright MCP` 仍直接报 `Target page/context/browser has been closed`,`chrome_devtools` 也出现 page/transport 提前断开;因此当前已经拿到“bridge live 可用 + 前端定向状态机回归通过”的证据,但“消息渠道页控制台里 `1800ms timeout` 是否已显著减少”还需要在更稳定的 MCP 浏览器会话下补一次真实 GUI 复测 - -## 2026-04-14 - -### 已完成 - -- 建立基础 Prompt current 文档 [prompt-foundation.md](../aiprompts/prompt-foundation.md),把 `runtime_turn -> prompt_context / prompt services -> TurnInputEnvelope -> aster PromptManager / embedded prompts` 固定为唯一基础 Prompt 事实源;同时明确 `query-loop.md` 负责提交主循环、本文负责 Prompt 主链,功能样板与历史工作台文档不再反向定义 system prompt 顺序 -- 将 [content-creator.md](../aiprompts/content-creator.md) 明确回挂到 [prompt-foundation.md](../aiprompts/prompt-foundation.md),把“首条消息注入 systemPrompt”的旧工作台叙事降回归档背景说明,不再误导成当前基础 Prompt 入口 -- 将 [docs/aiprompts/README.md](../aiprompts/README.md) 与 [docs/README.md](../README.md) 同步回挂到 [prompt-foundation.md](../aiprompts/prompt-foundation.md),后续改 `system prompt / subagent prompt / plan prompt / prompt_context / augmentation` 时有单一入口 -- 补文档新鲜度校验:`npm run harness:doc-freshness` 已通过(`doc freshness: clean`),确认新增的基础 Prompt 文档、入口回挂与路径引用没有漂移 -- 在 [MessageList.tsx](../../src/components/agent/chat/components/MessageList.tsx) 将运行状态线从输入区底栏迁到最后一条 assistant 消息尾部,统一承载 `处理中 / 已完成`、耗时、工具批次、输入输出 token 与 Prompt Cache 摘要,不再让状态提示霸占输入区主视觉;本轮继续补齐“完成态保留最后一批工具统计”,真实 GUI 已确认可见 `已完成 · 00:20 · 工具 读 2 / 列 2 · 输入 11.4K / 输出 309` -- 在 [MessageList.test.tsx](../../src/components/agent/chat/components/MessageList.test.tsx) 补上“复杂任务完成后状态线应跟随最后一条 assistant 消息尾部”的稳定断言,并通过真实 GUI 复测确认运行态 footer 位于消息流内、显著高于输入框,不再回落到底部输入栏 -- 建立总计划 [upstream-runtime-alignment-plan.md](./upstream-runtime-alignment-plan.md),固定六条主链作为唯一排期事实源 -- 建立 Query Loop current 文档 [query-loop.md](../aiprompts/query-loop.md),把提交入口、turn 组包、queue、tool runtime、流式执行、压缩与 evidence 消费收口成单一主链 -- 在 [turn_input_envelope.rs](../../src-tauri/crates/agent/src/turn_input_envelope.rs) 与 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 收口一条 Query Loop current 旁路:`TurnInputEnvelope` 现会记录最终 turn output schema 与 workspace-derived turn context metadata,`SessionConfig` 改为直接消费 envelope 提前固化的 turn context,不再在执行前再次拼装 `artifact output schema / auto_compact` 这一层真实输入 -- 在 [action_runtime.rs](../../src-tauri/src/commands/aster_agent_cmd/action_runtime.rs) 继续收口 Query Loop 辅助恢复链:`agent_runtime_respond_action` 的 elicitation / ask 恢复路径现复用 `runtime_turn` 的 turn context snapshot helper,不再只单独注入 `auto_compact`,artifact output schema 与 request metadata 也会走同一条 current turn context 边界 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 把 `compact_session` 控制回合的最小 `SessionConfig` 边界编码为专用 helper,并补测试守卫:压缩控制回合只保留 `thread_id / turn_id`,真正的 conversation 替换与 summary cache 更新仍复用共享 `perform_context_compaction(...)` core;[memory-compaction.md](../aiprompts/memory-compaction.md) 也已同步修正文档,避免继续误写成 `agent.compact_session()` 旁路 -- 在 [aster_agent.rs](../../src-tauri/src/agent/aster_agent.rs)、[persona_cmd.rs](../../src-tauri/src/commands/persona_cmd.rs) 与 [theme_context_cmd.rs](../../src-tauri/src/commands/theme_context_cmd.rs) 完成剩余 `SessionConfigBuilder` 生产落点分类:`generate_persona` 与 `aster_agent_theme_context_search` 现在统一复用“专用一次性会话” helper,显式声明它们不参与 Query Loop 的 submit turn / runtime queue / turn context snapshot 真相;零入口的旧 `AsterAgentWrapper::send_message` 聊天壳已删除,避免继续伪装成 current 主链 -- 在 [tests.rs](../../src-tauri/src/commands/aster_agent_cmd/tests.rs) 补上命令层 raw execution 源码扫描守卫:当前只允许 `action_runtime.rs`、`persona_cmd.rs`、`theme_context_cmd.rs` 三处保留原始 `agent.reply(...)` / `stream_reply_with_policy(...)`,一旦 Tauri 命令层再长出第四条未分类旁路,测试会直接失败 -- 在 [query-loop.md](../aiprompts/query-loop.md) 与 [src-tauri/src/agent/README.md](../../src-tauri/src/agent/README.md) 回写命令层边界说明:`agent_runtime_respond_action` 明确属于 current 恢复链;`generate_persona` 与 `aster_agent_theme_context_search` 明确属于受控 compat 一次性命令;README 的底层 `agent.reply(...)` 示例也已补充“不要在 Tauri 命令层继续新增 raw 执行旁路”的提醒 -- 建立 Task / Agent current 文档 [task-agent-taxonomy.md](../aiprompts/task-agent-taxonomy.md),把 `agent turn / subagent turn / automation job / scheduler tick / execution run` 收口成单一 taxonomy -- 建立 Remote runtime current 文档 [remote-runtime.md](../aiprompts/remote-runtime.md),把 `消息渠道 runtime / 浏览器连接器 / ChromeBridge / DevBridge / OpenClaw / telegram_remote` 收口成单一 remote taxonomy -- 建立 Memory / Compaction current 文档 [memory-compaction.md](../aiprompts/memory-compaction.md),把 `来源链 / working memory / durable memory / Team Memory / 会话压缩 / project memory sidecar` 收口成单一 memory taxonomy -- 将 `ExecutionTracker / subagent runtime / automation service / scheduler trigger` 明确分类为 `current / compat / deprecated / dead`,其中 `SchedulerService` 退回 compat 触发壳,`automation_jobs.payload.browser_session` 明确为 dead -- 将 `gateway_channel_* + browser connector / ChromeBridge` 明确归到 remote current 主链,把 `DevBridge / OpenClaw` 降回 compat、`telegram_remote_cmd` 降回 deprecated -- 将 `memory_runtime_* + unified_memory_* + agent_runtime_compact_session` 明确归到 memory current 主链,把 `project_memory_get` 相关项目资料链降回 compat 附属层、`memory_feedback_cmd` 降回 deprecated、`memory_search_cmd.rs.bak` 标记为 dead -- 将新 taxonomy 入口同步回 [docs/README.md](../README.md)、[docs/aiprompts/README.md](../aiprompts/README.md)、[docs/aiprompts/overview.md](../aiprompts/overview.md) 与 [AGENTS.md](../../AGENTS.md),仓库导航不再继续把旧 `heartbeat_service` 叙事当成 current -- 将 remote 入口同步回 [docs/README.md](../README.md)、[docs/aiprompts/README.md](../aiprompts/README.md)、[docs/aiprompts/overview.md](../aiprompts/overview.md) 与 [AGENTS.md](../../AGENTS.md),仓库导航不再继续把 debug 桥或单通道 Telegram 入口误当成 remote 主线 -- 将 memory 入口同步回 [docs/README.md](../README.md)、[docs/aiprompts/README.md](../aiprompts/README.md)、[docs/aiprompts/overview.md](../aiprompts/overview.md) 与 [AGENTS.md](../../AGENTS.md),仓库导航不再继续把项目资料聚合或旧 feedback 侧链误当成记忆 / 压缩主线 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第二刀代码收口:把 `run_start_metadata`、`runtime_status_session_config`、`build_session_config` 的重复拼装下沉为 helper,继续缩短 Query Loop 主循环 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第三刀代码收口:把流式执行成功后的 Artifact 自动落盘与记忆沉淀收口为统一 helper,消除主成功分支与降级成功分支的重复收尾逻辑 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第四刀代码收口:把两处 `stream_reply_once` 的事件记录闭包收口为统一 helper,主分支与降级分支共享同一条事件记录路径 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第五刀代码收口:把 `RunFinishDecision` 组装与 terminal result 收尾收口为统一 helper,主循环不再内联 success/error 两套终态处理 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第六刀代码收口:把主执行分支与降级到 ReAct 的分支统一为“单次流式尝试” helper,消除 `build_runtime_user_message(...)`、`build_session_config()`、`stream_reply_once(...)` 与成功收尾逻辑的重复展开 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第七刀代码收口:把 `CodeOrchestrated` 的扩展启用、失败降级与扩展清理统一为策略 helper,让 `with_run_custom(...)` 内只保留一次 Query Loop 执行入口 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第八刀代码收口:把 runtime turn 初始化、status 投射与 service preload 事件收口为统一前奏 helper,主循环的前置准备阶段已压成单一语义块 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第九刀代码收口:把 `run_start_metadata`、`timeline_recorder`、`runtime_status_session_config` 与流式 `session_config` 构建状态统一为 execution context,主循环不再散落拼装这组前置状态 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第十刀代码收口:把 `run_observation`、`run_finish decision` 与 terminal finalize 链路回收到 execution context,主循环不再手工拼接 tracked execution 与终态收尾 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第十一刀代码收口:把 `skill_tool_session_access` 与 `cancel_token` 收口为统一 session scope,异常路径与正常路径共享同一套会话级清理边界 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第十二刀代码收口:把 `runtime_snapshot -> runtime_projection_snapshot -> turn_state -> turn_input_envelope` 统一收口为 `build_runtime_turn_artifacts(...)` helper,主循环不再散落读取 snapshot、派生 thread/turn 和构建 turn 输入诊断 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第十三刀代码收口:把 `service_skill_preload -> prepared execution -> prelude/execute handoff` 统一收口为 `prepare_runtime_turn_execution(...)` 与 `RuntimeTurnPreparedExecution`,submit 主路径已进一步压成 `prepare -> execute` 两个清晰阶段 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第十四刀代码收口:把 `provider_continuation -> workspace sandbox apply -> tracker/session scope bootstrap` 统一收口为 `prepare_runtime_turn_submit_bootstrap(...)`,submit 主路径不再内联铺开这组前置副作用和运行期参数拼装 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第十五刀代码收口:把 `request.provider_config -> configure_provider/configure_provider_from_pool -> persist_session_provider_routing` 统一收口为 `apply_runtime_turn_provider_config(...)`,submit 主路径不再内联铺开 provider apply 分支 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第十六刀代码收口:把 `resolved_prompt -> prompt augmentation -> requested/effective strategy persist` 统一收口为 `prepare_runtime_turn_prompt_strategy(...)`,submit 主路径不再内联铺开 prompt/strategy 组装与持久化 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第十七刀代码收口:把 `tool surface metadata -> MCP warmup -> skill launch metadata normalize -> turn_input_builder seed` 统一收口为 `prepare_runtime_turn_request(...)`,submit 主路径不再内联铺开 request prepare 分支 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第十八刀代码收口:把 `runtime_chat_mode -> web_search/request_tool_policy -> execution_profile` 统一收口为 `prepare_runtime_turn_policy(...)`,submit 主路径不再内联铺开 policy resolve 逻辑 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第十九刀代码收口:把 `auto_continue -> workspace repair warning -> session_state_snapshot/working_dir update -> session_recent_runtime_context` 统一收口为 `prepare_runtime_turn_session(...)`,submit 主路径的 session 级前置准备已压成单一 helper,并顺手移除新增的 `runtime_chat_mode` 未使用 warning -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第二十刀代码收口:把 `session/policy/request/prompt_strategy -> provider apply/bootstrap` 统一收口为 `prepare_runtime_turn_submit_preparation(...)`,submit 主路径已从多段 helper 串联提升为单一 preflight 准备块 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第二十一刀代码收口:把 `sync_browser_assist_runtime_hint -> prepare_runtime_turn_execution -> agent guard -> emit_prelude_and_execute` 统一收口为 `execute_runtime_turn_submit(...)`,submit 主路径当前已压成 `prepare -> scoped execute` 两段主骨架 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第二十二刀代码收口:把 `provider_config resolve -> harness metadata normalize -> workspace resolve/turn id/runtime_config` 统一收口为 `prepare_runtime_turn_ingress_context(...)`,入口上下文边界不再散落在主路径中 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第二十三刀代码收口:把 `agent init/session_store check -> support tools register` 统一收口为 `prepare_runtime_turn_entry(...)`,主路径的运行时入口准备已形成独立阶段 -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第二十四刀代码收口:把 `model_skill_tool_access derive -> with_runtime_turn_session_scope -> execute_runtime_turn_submit` 统一收口为 `execute_runtime_turn_with_session_scope(...)`,主路径不再拆包又重组 `submit_preparation` -- 在 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 完成第二十五刀代码收口:把 `execute_aster_chat_request(...)` 的 `entry -> ingress -> submit_preparation -> session_scope_execute` 外层编排统一收口为 `execute_runtime_turn_pipeline(...)`,`M1` 主路径现在只保留日志入口与单次 pipeline 调用 -- 为解除 `runtime_turn` 定向测试的编译阻塞,在 [task_list_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/task_list_tools.rs) 把两处 `TeamSessionState / TeamMembershipState` 的团队状态恢复改为复用现有 `from_session(...)` 包装,避免当前工作区里 trait 静态方法解析差异继续卡住主线校验 -- 完成最小 Rust 定向校验:`cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib commands::aster_agent_cmd::runtime_turn::tests:: -- --nocapture`,结果为 `35 passed` -- 在工作区存在其他 Cargo 并行任务时,补充使用独立 `CARGO_TARGET_DIR=.codex-target-runtime-turn` 重跑同一条 `runtime_turn` 定向测试,结果仍为 `35 passed` -- 在完成第十六到第十九刀后,补充使用独立 `CARGO_TARGET_DIR=.codex-target-runtime-turn-2` 重跑同一条 `runtime_turn` 定向测试,结果更新为 `37 passed`;当前仅剩 [workspace_tools.rs](../../src-tauri/src/commands/aster_agent_cmd/tool_runtime/workspace_tools.rs) 的既有 `format_output` dead_code warning -- 在完成第二十到第二十一刀后,再次使用独立 `CARGO_TARGET_DIR=.codex-target-runtime-turn-2` 重跑同一条 `runtime_turn` 定向测试,结果保持 `37 passed`;第 20-21 刀未引入新的 runtime_turn warning -- 在完成第二十二到第二十四刀后,再次使用独立 `CARGO_TARGET_DIR=.codex-target-runtime-turn-2` 重跑同一条 `runtime_turn` 定向测试,结果仍为 `37 passed`;新增的 `session_id` 未使用 warning 已收掉,当前只剩 [workspace_tools.rs](../../src-tauri/src/commands/aster_agent_cmd/tool_runtime/workspace_tools.rs) 的既有 `format_output` dead_code warning -- 在完成第二十五刀后,再次使用独立 `CARGO_TARGET_DIR=.codex-target-runtime-turn-2` 重跑同一条 `runtime_turn` 定向测试,结果仍为 `37 passed`;新增的 `unused_mut` warning 已收掉,当前只剩 [workspace_tools.rs](../../src-tauri/src/commands/aster_agent_cmd/tool_runtime/workspace_tools.rs) 的既有 `format_output` dead_code warning -- 完成文档新鲜度校验:`npm run harness:doc-freshness`,结果为 `clean` -- 将新入口回挂到 `docs/README.md`、`docs/aiprompts/README.md`、`docs/exec-plans/README.md` -- 将 Query Loop 差距从“口头判断”改为可追踪状态,并更新技术债与总计划进度 -- 继续对齐参考运行时 `src/tools` current surface: - - [plan_mode_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/plan_mode_tool.rs) 的 `ExitPlanMode` 现已在 team teammate 场景通过 `send_input` 回调真实向 team lead 投递 `plan_approval_request`,输出补齐 `awaitingLeaderApproval / requestId` - - [task_list_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/task_list_tools.rs) 的 `TaskList` 现已对齐参考语义,自动从 `blockedBy` 里过滤已 `completed` 的 blocker,避免后续任务误判仍被阻塞 - - [mod.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/mod.rs) 已把 agent control 的 `send_input` 回调注入 `ExitPlanMode` 注册路径,保持默认注册与 team tools 注册条件不回退 - - [task_output_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/task_output_tool.rs) 已继续向参考 `TaskOutputTool` 收口:`task_type` 改为 `local_bash`,移除 payload 中额外的 `outputFile` 字段,补齐 `block=false -> not_ready` 与 `block=true + timeout -> timeout` 的回归测试,并去掉空输出占位文案 - - [task_stop_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/task_stop_tool.rs) 已改成参考 `TaskStopTool` 的结构化输出:成功返回 `message / task_id / task_type / command` JSON,`task_type` 改为 `local_bash`,`shell_id` 仅作为兼容别名保留,非运行中任务改成与参考一致的错误语义 - - [agent_control.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/agent_control.rs) 的 `SendMessage` 已补 `plan_approval_response` 权限守卫:只有 team lead 可以发送 approve / reject,并补 teammate 被拒绝、lead 可发送的定向测试 - - [task_list_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/task_list_tools.rs) 已把 `TaskCreate / TaskGet / TaskUpdate` 的 Rust 反序列化层与 schema 一起收紧到 `deny_unknown_fields / additionalProperties: false`,避免多余字段在 current surface 下静默穿透 - - [task_list_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/task_list_tools.rs) 已把 team task board 的读写边界收口到 lead session:同一 team 下的 `TaskCreate / TaskList / TaskGet / TaskUpdate` 现在统一从 lead session 的 `task_list.v1` 快照读取并回写,跨不同 tool registry / 不同 teammate session 也能看到同一份共享任务板,不再依赖单个 agent 进程内的内存缓存 - - [task_list_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/task_list_tools.rs) 已把 `TaskUpdate` 的 `verificationNudgeNeeded` 再向参考语义收紧:subagent / teammate 完成最后一个任务时不再误触发“主线程收尾验证提醒”,只保留在非 `SubAgent` session 的完成收尾场景下评估该提示 - - [hooks/types.rs](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/types.rs)、[hooks/loader.rs](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/loader.rs) 与 [task_list_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/task_list_tools.rs) 已把 `TaskCreated / TaskCompleted` 正式接入当前 hooks 体系:hook 载荷补齐 `task_id / task_subject / task_description / teammate_name / team_name`,`TaskCreate` 现在会在持久化后执行 `TaskCreated` hook 并在阻塞时回滚任务,`TaskUpdate(status=completed)` 会在真正完成前执行 `TaskCompleted` hook,并按参考语义返回 `success=false` - - [task_list_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/task_list_tools.rs) 已把 `TaskUpdate.owner` 变更继续向参考 `TaskUpdateTool` 收口:当 owner 变更为当前 team 中可解析的成员时,会通过现有 `UserMessageManager` 给目标 session 追加一条 agent-only 的 `task_assignment` JSON 消息,替代参考仓库的 file-mailbox 路径,同时保持“同 owner 重复写入不重复通知”的语义 - - [team_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/team_tools.rs) 已把 `TeamCreate / TeamDelete / ListPeers` 的输入反序列化层统一收紧为 `deny_unknown_fields`,保持 team surface 与参考的严格对象语义一致 - - [team_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/team_tools.rs) 已继续向参考 `TeamDeleteTool` / `ListPeers` 收口:`TeamDelete` 改为只拦截“仍可达且仍活跃”的 non-lead 成员,idle teammate 不再误阻塞删除,并在成功清理 team 时同步清掉 reachable idle teammate 的 `TeamMembershipState`;`ListPeers` 现会过滤缺失有效 membership 的 stale member,只暴露当前仍可直接通信的 peer - - [agent_control.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/agent_control.rs) 的 `SendMessage` 现已继续向参考 `SendMessageTool` 收口:纯字符串消息缺少 `summary` 时会在 dispatch 前直接报 `summary is required when message is a string`,并补齐命名子 agent 路由场景的回归测试;`shutdown_response` 的 target / reject-reason 参数错误文案也已对齐参考英文语义 - - [team_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/team_tools.rs) 的 `TeamCreate` 现已补齐参考默认值语义:未显式传 `agent_type` 时,team lead 成员默认记录为 `team-lead`,避免 `ListPeers` / team 状态里出现空 lead role - - [team_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/team_tools.rs) 的 `TeamCreate / ListPeers` 输出面已继续向参考收口:对外返回的 `lead_agent_id` 与 `peers[].agent_id` 改为稳定的 `name@team` display id,内部 team session / membership 仍保持当前 runtime 所需的真实 session id 路由,`sendTo` 继续作为消息发送主入口 - - [team_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/team_tools.rs) 的 `TeamCreate` 已继续向参考 `TeamCreateTool` 收口:`team_file_path` 现改为稳定的 `/teams//config.json` 形态,不再返回 `session://...` 伪路径 - - [team_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/team_tools.rs) 的 `TeamCreate` 重名策略已从 `name-2/name-3` 递增后缀改成随机三段式 slug,行为更接近参考仓库的 `generateWordSlug()` - - [agent_control.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/agent_control.rs) 的 `SendMessage` 已补齐当前 team display id 路由:当 `to` 传入 `ListPeers` 暴露的 `name@team` 标识时,会先规范化成当前 team 成员名再进入既有路由与权限校验,因此 `team-lead@alpha` 这类目标现在可用于普通消息和 `shutdown_response` - - [agent_control.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/agent_control.rs) 的 `Agent / SendMessage` 已继续把 strict schema 收口到 Rust 反序列化层:`AgentToolInput` 与 `SendMessageToolInput` 现已补上 `deny_unknown_fields`,多余字段会在 dispatch 前直接被拒绝,不再绕过 JSON schema 静默穿透 - - [remote_trigger_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/remote_trigger_tool.rs) 的 `RemoteTrigger` 也已补上 `deny_unknown_fields`,让 `additionalProperties: false` 与实际解析行为保持一致,并补齐未知字段回归测试 - - [send_user_message_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/send_user_message_tool.rs) 已继续向参考 `BriefTool` 的附件校验语义收口:输入反序列化改为 `deny_unknown_fields`,附件路径现支持 `~` 展开,缺失文件、权限拒绝和非 regular file 会分别返回与参考一致的细粒度错误文案,同时保留前端当前依赖的 `"Message delivered to user."` 摘要输出不回退 - - [workflow_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/workflow_tool.rs)、[config_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/config_tool.rs)、[powershell_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/powershell_tool.rs)、[worktree_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/worktree_tools.rs)、[cron_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/cron_tools.rs) 与 [sleep_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/sleep_tool.rs) 已完成同一批 strict-schema 收口:这些工具凡是 schema 已声明 `additionalProperties: false` 的 current surface,现已统一在 Rust 输入结构上补齐 `deny_unknown_fields`,避免多余字段继续从反序列化层静默穿透 - - [config_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/config_tool.rs) 已继续向参考 `ConfigTool` / `supportedSettings.ts` 收口:工具面从仅支持 `model` 与 `permissions.defaultMode` 扩到当前参考仓库的全部非 feature-gated setting(`theme / editorMode / verbose / preferredNotifChannel / autoCompactEnabled / autoMemoryEnabled / autoDreamEnabled / fileCheckpointingEnabled / showTurnDuration / terminalProgressBarEnabled / taskTrackingEnabled / alwaysThinkingEnabled / language / teammateMode`),同时把布尔值字符串写入、枚举项校验和动态 description 统一收口到受控 setting 表 - - [config_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/config_tool.rs) 的 `permissions.defaultMode` 已补齐当前 Lime runtime 别名语义:除参考当前可映射的 `default / acceptEdits / auto` 外,现也显式支持 `approve / chat` 两个 Lime 运行时模式,并对参考里的 `plan / dontAsk` 返回“当前 runtime 尚未实现”的结构化失败,避免继续把不等价模式静默映射错位 - - [plan_mode_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/plan_mode_tool.rs) 已重新确认 current 边界:`ExitPlanMode` 顶层输入仍刻意保持 `additionalProperties: true`,因此这轮不再把顶层反序列化收紧;只保留 `allowedPrompts` item 级 strict object,不让计划模式工具偏离当前 surface - - [ask.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/ask.rs) 已把 `AskUserQuestion` 继续向参考 strict object surface 收口:顶层 `questions`、question item、option item 的 schema 全部显式补齐 `additionalProperties: false`,Rust 输入结构同步补上 `deny_unknown_fields`;同时把 `AskOptionInput` 改成手写反序列化,避免 `untagged enum` 吞掉 option 子项的未知字段错误,当前 `extra` 这类脏字段会稳定返回 `unknown field` 失败而不再被泛化成匹配失败 - - [worktree_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/worktree_tools.rs) 已把 `EnterWorktree / ExitWorktree` 的输出面继续向参考收口:`EnterWorktree` 成功消息补齐“退出 session 也会提示处理 worktree”的语义;`ExitWorktree` 的成功输出去掉当前 runtime 实际不会返回的 `noop` 字段,避免继续暴露参考 current surface 外的冗余字段 - - [tool_search_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/tool_search_tool.rs) 已把 `ToolSearch` 的输入面继续向参考收口:Rust 输入结构补上 `deny_unknown_fields`,schema 顶层补齐 `additionalProperties: false`;同时在“无命中结果”时补回参考 `pending_mcp_servers` 输出字段,并保留当前 Lime UI 仍在消费的 `notes` 字段不回退 - - [extension_manager.rs](../../src-tauri/crates/aster-rust/crates/aster/src/agents/extension_manager.rs) 已补最小 pending 扩展状态:`ExtensionManager` 现在会在 `add_extension(...)` 连接期间维护一个排序后的 `pending_extensions` 集合,供 `ToolSearch` 在扩展尚未连上时暴露 `pending_mcp_servers`,同时对并发重复启用同名扩展做去重,避免重复连接 - - [toolSearchResultSummary.ts](../../src/components/agent/chat/utils/toolSearchResultSummary.ts) 与 [ToolSearchSummaryPanel.tsx](../../src/components/agent/chat/components/ToolSearchSummaryPanel.tsx) 已完成 `pending_mcp_servers` 的最小前端兼容:summary parser 会识别后端新增字段,面板会在无命中但 MCP 仍在连接时显示“以下 MCP 服务仍在连接中”,避免这次 `ToolSearch` 对齐只停留在后端埋字段 - - [agent.rs](../../src-tauri/crates/aster-rust/crates/aster/src/agents/agent.rs) 已把两个测试 helper 的 `CallToolRequestParam.name` 显式改成 `Cow::Owned(...)`,用于消除 lib test 编译时的 `'static` 推断歧义,避免它继续阻塞 tools 定向校验 - -### 本轮补充校验 - -- `npx vitest run "src/components/agent/chat/components/MessageList.test.tsx" "src/components/agent/chat/components/AgentThreadTimeline.test.tsx"` -- `cargo fmt --manifest-path "src-tauri/Cargo.toml" --all` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target-runtime-turn" cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib commands::aster_agent_cmd::runtime_turn::tests:: -- --nocapture` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target-runtime-turn-2" cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib commands::aster_agent_cmd::runtime_turn::tests:: -- --nocapture` -- `npm run harness:doc-freshness` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" plan_mode_tool::tests:: --lib -- --nocapture` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" task_list_tools::tests:: --lib -- --nocapture` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" tools::tests::test_register --lib -- --nocapture` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" task_output_tool::tests:: --lib -- --nocapture` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" task_stop_tool::tests:: --lib -- --nocapture` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" agent_control::tests:: --lib -- --nocapture` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" remote_trigger_tool::tests:: --lib -- --nocapture` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" team_tools::tests:: --lib -- --nocapture` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" send_user_message_tool::tests:: --lib -- --nocapture` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" config_tool::tests:: --lib -- --nocapture` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" ask::tests:: --lib -- --nocapture` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" tool_search_tool::tests:: --lib -- --nocapture` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" extension_manager::tests:: --lib -- --nocapture` -- `npx vitest run "src/components/agent/chat/utils/toolSearchResultSummary.test.ts" "src/components/agent/chat/components/ToolSearchSummaryPanel.test.tsx"` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" worktree_tools::tests:: --lib -- --nocapture` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" cron_tools::tests:: --lib -- --nocapture` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" sleep_tool::tests:: --lib -- --nocapture` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" powershell_tool::tests:: --lib -- --nocapture` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" workflow_tool::tests:: --lib -- --nocapture` -- `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" hooks::tests:: --lib -- --nocapture` -- 建立 State / History / Telemetry current 文档 [state-history-telemetry.md](../aiprompts/state-history-telemetry.md),把 `session / thread / turn / request / evidence / history` 收口成单一状态地图 -- 将 `agent_sessions / agent_messages -> SessionDetail -> AgentRuntimeThreadReadModel -> RequestLog 关联键 -> handoff/evidence/replay/analysis/review -> history-record/trend/cleanup/dashboard -> HarnessStatusPanel / AgentThreadReliabilityPanel` 明确归到 state/history/telemetry current 主链 -- 将原 `state-model` 历史子专题、`docs/roadmap/reliability/*` 与 [telemetry_cmd.rs](../../src-tauri/src/commands/telemetry_cmd.rs) 明确归到 compat,并把 cleanup 报表里残留的 `requestTelemetry:unlinked` 旧语义标记为 deprecated -- 将 state/history/telemetry 入口同步回 [docs/README.md](../README.md)、[docs/aiprompts/README.md](../aiprompts/README.md)、[docs/aiprompts/overview.md](../aiprompts/overview.md) 与 [AGENTS.md](../../AGENTS.md),仓库导航不再继续把旧状态模型方案或 reliability 计划当成 current 主线 -- 再次执行 `npm run harness:doc-freshness` 并通过(`clean`) -- 新增 [docs/roadmap/reliability/README.md](../roadmap/reliability/README.md),把 reliability 目录补成明确的 compat 入口,不再让分阶段计划文件继续承担 current 导航职责 -- 在 [generated-slop-report-core.mjs](../../scripts/lib/generated-slop-report-core.mjs) 将旧 `requestTelemetry:unlinked` 语义折叠为 `known_gap` 兼容别名,并补定向测试守卫,避免 cleanup/dashboard 继续把旧历史样本当成现役 observability 状态 -- 在 `docs/roadmap/reliability/*.md` 全部补上 compat 提示,正文开头统一先回挂 [state-history-telemetry.md](../aiprompts/state-history-telemetry.md),避免专项正文继续被误读成 current 主入口 -- 在 `docs/roadmap/reliability/*.md` 进一步压缩顶部导航:把重复的上位文档长列表统一收口为 `README + current 主链 + PR 对应映射`,减少专项正文重复解释 -- 将整组 `docs/roadmap/reliability/*` 进一步压缩为 compat 历史摘要档案:只保留落地结果、current 映射与延后增强项,重复的目标/问题/范围/实施清单正文统一回退到仓库历史 -- 将原状态模型历史子专题进一步压缩并最终并入 [lime-aster-codex-alignment-roadmap.md](../roadmap/lime-aster-codex-alignment-roadmap.md):只保留状态边界判断、current 映射与延后增强项,不再保留独立顶层路线图 -- 在 [lime-aster-codex-alignment-roadmap.md](../roadmap/lime-aster-codex-alignment-roadmap.md) 收紧顶部导航:当前入口统一回挂到 [query-loop.md](../aiprompts/query-loop.md)、[state-history-telemetry.md](../aiprompts/state-history-telemetry.md) 与 [upstream-runtime-alignment-plan.md](./upstream-runtime-alignment-plan.md) -- 将 [lime-aster-codex-alignment-roadmap.md](../roadmap/lime-aster-codex-alignment-roadmap.md) 进一步压缩为 compat 历史摘要档案:只保留阶段映射、历史判断与 current 回看入口,不再继续承载长篇阶段任务与验证流水 -- 将原对话执行效率历史子专题进一步压缩并并入 [lime-aster-codex-alignment-roadmap.md](../roadmap/lime-aster-codex-alignment-roadmap.md):只保留历史主题、current 映射与延后方向,不再保留独立顶层路线图 -- 将 `docs/roadmap/artifacts/*` 中仍把旧执行效率路线图当 current 运行时依据的说明,统一改回 `query-loop / task-agent-taxonomy / state-history-telemetry / upstream-runtime-alignment-plan` -- 在 [telemetry_cmd.rs](../../src-tauri/src/commands/telemetry_cmd.rs) 收紧命令注释:这些命令只暴露原始 `RequestLog` 与聚合统计,不负责定义 session/thread current 状态真相 -- 继续对齐 team / task tool surface: - - 在 [task_output_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/task_output_tool.rs) 为 `block` 补齐参考仓库 `semanticBoolean` 兼容,允许模型把布尔值误写成字符串 `"true"` / `"false"` 时仍能按当前 `TaskOutput` 主链执行 - - 在 [tool_search_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/tool_search_tool.rs) 为 `TaskCreate / TaskGet / TaskList / TaskUpdate / TaskOutput / TaskStop / TeamCreate / TeamDelete / ListPeers` 补齐参考仓库常见别名与意图词,减少 `kill shell`、`agent output`、`ListPeersTool`、`swarm peers` 这类上游表述在 Lime 中搜不到当前工具的漂移 - - 在 [catalog.rs](../../src-tauri/src/agent_tools/catalog.rs) 补齐 `KillShell -> TaskStop` 与 `ListPeersTool -> ListPeers` 的 reference alias 规范化,避免参考仓库工具名在 Lime 运行时目录册中掉映射 - - 在 [agent_control.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/agent_control.rs) 与 [team_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/team_tools.rs) 显式收口 peer surface 差异:`SendMessage` 现会识别参考仓库 `uds:` / `bridge:` peer address,并返回“当前 Lime runtime 未实现 cross-session peer messaging”的结构化失败,不再误把这类 target 当作普通 `agent_id` 投递;`ListPeers` 描述同步明确当前只枚举 team 内可达 peers - - 在 [base.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/base.rs)、[registry.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/registry.rs)、[task_list_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/task_list_tools.rs)、[task_output_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/task_output_tool.rs)、[task_stop_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/task_stop_tool.rs)、[team_tools.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/team_tools.rs) 与 [agent_control.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/agent_control.rs) 补齐执行层 alias 兼容:`ToolRegistry` 现在会把 `BashTool / ConfigTool / FileReadTool / FileWriteTool / FileEditTool / EnterPlanModeTool / ExitPlanModeTool / EnterWorktreeTool / ExitWorktreeTool / GlobTool / GrepTool / LSPTool / NotebookEditTool / PowerShellTool / BriefTool / SkillTool / SleepTool / WebFetchTool / WebSearchTool`,以及 `TaskCreateTool / TaskListTool / TaskGetTool / TaskUpdateTool / TaskOutputTool / AgentOutputTool / BashOutputTool / TaskStopTool / KillShell / SendMessageTool / SendInput / TeamCreateTool / TeamDeleteTool / ListPeersTool` 真实解析到 current native tools,不再停留在“目录能搜到、运行时却找不到”的半对齐状态 -- 继续对齐 Config current surface: - - 在 [config_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/config_tool.rs) 把 `classifierPermissionsEnabled / voiceEnabled / remoteControlAtStartup / taskCompleteNotifEnabled / inputNeededNotifEnabled / agentPushNotifEnabled` 纳入 `ConfigTool` 已知 setting 集合,不再继续落到 `Unknown setting` - - 同时将上述 6 个 setting 明确收口为“已知上游表面,但当前 Lime runtime 未实现”的结构化失败,避免把分散存在的语音 / 通知 / autostart / remote 能力误绑定到错误配置键 - - 进一步收紧 [config_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/config_tool.rs) 的 `voiceEnabled / remoteControlAtStartup` unsupported 文案:前者明确卡在“缺少宿主 callback 同步全局语音快捷键副作用”,后者明确 Lime 当前只有 OS auto-launch,并不等同于上游 remote-control-at-startup 语义 - - 在 [config_tool.rs](../../src-tauri/crates/aster-rust/crates/aster/src/tools/config_tool.rs) 与 [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 接上 `voiceEnabled` 宿主回调:当前 runtime turn 入口会用 Tauri 宿主的 `get_voice_input_config / save_voice_input_config` 回填 `ConfigTool`,因此 `voiceEnabled` 现在会真实读取/更新 `experimental.voice_input.enabled`,并同步触发全局语音快捷键注册/注销副作用;`remoteControlAtStartup` 仍保持 unsupported -- 补执行边界校验: - - `npx vitest run "scripts/lib/generated-slop-report-core.test.ts"` 通过(`8 passed`) - - `npm run harness:cleanup-report:check` 通过(`ok`) - - `npm run harness:doc-freshness` 通过(`clean`,含历史摘要压缩后的再次确认) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" task_output_tool::tests:: --lib -- --nocapture` 通过(`11 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" tool_search_tool::tests:: --lib -- --nocapture` 通过(`25 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/Cargo.toml" test_tool_catalog_entry_normalizes_reference_js_tool_names_to_current_surface --lib -- --nocapture` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" config_tool::tests:: --lib -- --nocapture` 通过(`14 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_registry_resolves_native_aliases_during_lookup_and_execution --lib -- --nocapture` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_registry_unregister_clears_native_aliases --lib -- --nocapture` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_register_default_tools --lib -- --nocapture` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_registers_team_tools_when_spawn_and_send_callbacks_exist --lib -- --nocapture` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/Cargo.toml" test_normalize_workspace_tool_permission_behavior_auto_mode_allows_warning --lib -- --nocapture` 通过(`1 passed`,确认主 crate 的 `runtime_turn` 编译链已带起) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" agent_control::tests:: --lib -- --nocapture` 已启动重跑,但本轮未等到 `aster` test binary 重编译完成;后续需补跑以确认 `uds:` / `bridge:` 受控失败分支未回退现有 `team` / `named child` 路由 - -### 本轮继续补齐 - -- 继续推进“应用层优先消费统一 runtime tool surface”: - - 在 [inventory.rs](../../src-tauri/src/agent_tools/inventory.rs)、[runtime_api.rs](../../src-tauri/src/commands/aster_agent_cmd/command_api/runtime_api.rs)、[types.ts](../../src/lib/api/agentRuntime/types.ts)、[core.ts](../../src/lib/tauri-mock/core.ts) 与 [HarnessStatusPanel.tsx](../../src/components/agent/chat/components/HarnessStatusPanel.tsx) 已补统一 `runtime_tools` 视图后,本轮继续把前端 usage 从“只在工具库存面板里看四张表”往“主界面直接消费实际 runtime tool surface”推进 - - [useWorkspaceHarnessInventoryRuntime.ts](../../src/components/agent/chat/workspace/useWorkspaceHarnessInventoryRuntime.ts) 现在会在主界面启用时预取工具库存,不再等 Harness 面板展开后才第一次拉取 - - 新增 [runtimeToolAvailability.ts](../../src/components/agent/chat/utils/runtimeToolAvailability.ts),把 `runtime_tools` 优先、`registry_tools` 兜底的真实 current surface 收口为 `webSearch / subagent(team) / task` 三组 capability 派生 - - [useWorkspaceInputbarSceneRuntime.tsx](../../src/components/agent/chat/workspace/useWorkspaceInputbarSceneRuntime.tsx)、[AgentRuntimeStrip.tsx](../../src/components/agent/chat/components/AgentRuntimeStrip.tsx)、[WorkspaceConversationScene.tsx](../../src/components/agent/chat/workspace/WorkspaceConversationScene.tsx)、[EmptyState.tsx](../../src/components/agent/chat/components/EmptyState.tsx) 与 [EmptyStateComposerPanel.tsx](../../src/components/agent/chat/components/EmptyStateComposerPanel.tsx) 已开始直接消费这份派生结果:Runtime strip 会显示实际 runtime tool surface 规模与 team/task gap,首页主输入区也会在用户开启 `联网搜索 / 任务拆分` 偏好但 runtime current tools 尚未接通时给出明确提示,不再把静态偏好误显示成“真实可用能力”;此前误导性的两条页级黄提示已从主路径移除,只在工作台诊断位保留真实缺口摘要 - - 本轮继续补齐测试与 smoke: - - 新增 [runtimeToolAvailability.test.ts](../../src/components/agent/chat/utils/runtimeToolAvailability.test.ts),覆盖 `runtime_tools` current surface 派生与开发态 override - - 新增 [AgentRuntimeStrip.test.tsx](../../src/components/agent/chat/components/AgentRuntimeStrip.test.tsx) 与 [EmptyState.test.tsx](../../src/components/agent/chat/components/EmptyState.test.tsx) 的 `runtime tool surface` 页级断言,验证 runtime strip 的 team/task gap 与首页空态告警都能真实透传 - - 在 [HarnessStatusPanel.tsx](../../src/components/agent/chat/components/HarnessStatusPanel.tsx) 新增 `Runtime 能力摘要`,让工具库存面板也直接消费 `deriveRuntimeToolAvailability(...)`,显式展示 `WebSearch / 子任务核心 tools / Team current tools / Task current tools` 的已接通状态或缺口,不再只显示 raw runtime tool list - - 在 [HarnessStatusPanel.test.tsx](../../src/components/agent/chat/components/HarnessStatusPanel.test.tsx) 新增 `runtime tool surface` 断言,覆盖 team/task gap 暴露与 current surface 完整接通两种情况 - - 新增 [agent-runtime-tool-surface-smoke.mjs](../../scripts/agent-runtime-tool-surface-smoke.mjs),并接入 [verify-gui-smoke.mjs](../../scripts/verify-gui-smoke.mjs) 与 [package.json](../../package.json) 的 `smoke:agent-runtime-tool-surface` current smoke 入口,避免这条主线只停留在局部单测 - - 新增 [agent-runtime-tool-surface-page-smoke.mjs](../../scripts/agent-runtime-tool-surface-page-smoke.mjs),通过真实页面执行 `onboarding -> 最小发送 -> 工作台` 链路,断言 `Runtime 能力摘要` 中的 `WebSearch / 子任务核心 tools / Team current tools / Task current tools` 缺口文案,同时确认旧页级黄提示不再回到页面主路径;脚本固定使用 `stream_mode=events`,避开真实页面在 `cdp_direct + frames/both` 下会把 `Runtime.evaluate` 挤到超时的已知运行时特性 - - 本轮已执行校验: - - `npm run smoke:agent-runtime-tool-surface` 通过 - - `npm run smoke:agent-runtime-tool-surface-page` 通过 - - `npm run verify:gui-smoke` 已接入新的 `smoke:agent-runtime-tool-surface-page` - - 真实页面自动 smoke 已验证:开发态 override 下可稳定进入工作台 `Runtime 能力摘要`,并且旧页级黄提示不会重新出现 - -### 当前判断 - -- `M0` 统一排期事实源:已完成 -- `M1` Query Loop 收口:已完成第二十五刀实现,并继续收口 `TurnInputEnvelope -> SessionConfig` 的 turn context snapshot 分叉、`action_runtime` 辅助恢复链的 turn context 旁路,以及 `compact_session` 控制回合的最小上下文边界;当前主路径已压成 `execute_aster_chat_request -> execute_runtime_turn_pipeline -> entry/ingress/submit_preparation/session_scope_execute`,turn context 的 output schema / auto_compact / request metadata 也已进一步收紧到共享 snapshot helper -- `M2` Task / Agent taxonomy 收口:已完成 current taxonomy 文档、索引回挂与分类判断;当前长时执行入口统一按 `agent turn / subagent turn / automation job` 解释,`ExecutionTracker` 只作为统一执行摘要层,`SchedulerService` 只作为 compat 触发壳 -- `M3` Remote runtime 收口:已完成 current remote 文档、索引回挂与分类判断;当前远程入口统一按 `消息渠道 runtime + 浏览器连接器 / ChromeBridge` 解释,`DevBridge` 与 `OpenClaw` 只作为 compat 支撑,`telegram_remote_cmd` 只作为 deprecated 单通道入口 -- `M5` State / History / Telemetry 收口:已完成 current 状态地图、索引回挂与分类判断;当前状态链统一按 `SessionDetail -> AgentRuntimeThreadReadModel -> RequestLog 关联键 -> export/history` 解释,旧状态模型方案、reliability 计划、Aster/Codex 联合路线图与原始 request log 浏览面只作为 compat 附属层,其中 `docs/roadmap/reliability/*` 与 [lime-aster-codex-alignment-roadmap.md](../roadmap/lime-aster-codex-alignment-roadmap.md) 已进一步压成 umbrella 历史摘要档案 -- `M1` 退出判断:已满足“不再需要横跳多份文档才能解释 Lime 主循环”的出口条件,后续默认不再继续微切 `runtime_turn.rs` -- `M2` 退出判断:已满足“所有长时执行入口都能归到唯一 taxonomy”的出口条件,后续不再继续把 execution tracker、scheduler、subagent、automation 当作多条平级主线分别排期 -- `M3` 退出判断:已满足“remote 不再是多个并列产品旁路”的出口条件,后续只允许在 `gateway_channel_*` 与 `browser connector / ChromeBridge` current ingress 上继续长能力 -- `M4` 退出判断:已满足“`memory_runtime_*` 与 `compact_session` 不再被当成分散能力点看待”的出口条件;后续只允许在 `memory_runtime_*`、`unified_memory_*` 与 `agent_runtime_compact_session` current 边界继续长记忆 / 压缩能力 -- `M5` 退出判断:已满足“session / thread / turn / request / evidence / history 的读模型叙事收口”的出口条件;后续只允许在 `SessionDetail`、`AgentRuntimeThreadReadModel`、`RequestLog` 关联键与 `agent_runtime_export_*` current 边界继续长能力 - -### 下一刀 - -- `docs/roadmap/reliability/*` 与 [lime-aster-codex-alignment-roadmap.md](../roadmap/lime-aster-codex-alignment-roadmap.md) 的 compat 历史档案化已完成;其中原 `state-model` 与 `conversation-execution-efficiency` 子专题已经并入 `alignment-roadmap`。当前又收口了 `TurnInputEnvelope -> SessionConfig` 的 turn context 分叉、`action_runtime` 辅助恢复链旁路,并显式化了 `compact_session` 控制回合的最小上下文边界;剩余散落在 `persona_cmd` / `theme_context_cmd` 的一次性临时会话配置也已收回专用 helper,零入口旧发送壳已删除,Tauri 命令层 raw execution 也已经固定为 3 处并补了源码扫描守卫。下一刀转向继续盘点 `src-tauri/src` 非命令层与 README/示例面是否还残留会误导实现者的原始执行旁路叙事 -- 后续若出现 `runtime_turn` 行为回退,再回到 `M1` current 主路径做定点修复,而不是继续常态化微切 - -### 继续推进(CCD-008 / Agent hook current) - -- 继续沿 `hooks / skills` 主线推进后,`Agent hook` 已从占位实现推进成真实 current 执行,不再只是 `warn! + success(None)`: - - [types.rs](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/types.rs) 里的 `AgentHookConfig` 已补 direct `prompt / model` 字段,作为 current 事实源;原有 `agent_type / agent_config` 继续保留为 compat,其中 `agent_config.prompt / model / max_turns` 仍可回退解析,避免直接打断旧草案配置。 - - [executor.rs](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/executor.rs) 里的 `Agent hook` 现在会复用与 `Prompt hook` 相同的 provider 解析优先级:先按 `session_id -> query_session(...) -> provider_name / model_config`,命不中当前 session 上下文时才回退 `ASTER_PROVIDER / ASTER_MODEL`。 - - `Agent hook` 的实际执行不再另造 query loop,而是接入现有 [agent.rs](../../src-tauri/crates/aster-rust/crates/aster/src/agents/agent.rs) `Agent.reply(...)` 主链:运行时会为 hook 创建隔离的临时 subagent session store,复用现有 tool surface、StructuredOutput/output schema 与 turn runtime,而不把一次 hook 验证写进正式 session 存储。 - - 为了避免 non-interactive hook verifier 卡死在审批流,本轮新增 `Agent::set_permission_mode(...)`,并在 hook agent 上显式切到 `AsterMode::Auto`;这样 hook verifier 会保持 headless current 行为,不会因为 `AskUserQuestion / confirmation_rx` 进入等待。 - - `Agent hook` 现同样使用最小 JSON decision contract:最终通过 `StructuredOutput` 返回 `{"ok":true}` 或 `{"ok":false,"reason":"..."}`;`ok=false` 会真实映射到 `HookResult::blocked(...)`。 -- 这一步后的 `CCD-008` 边界进一步收紧为: - - `current`:`TaskCreated / TaskCompleted` hooks、project-level `UserPromptSubmit`、`SessionStart(startup / compact)`、`command / url / prompt / agent` hook executor、`SkillTool` prompt/workflow execution。 - - `current gap`:`MCP hook`、`SessionStart(resume)`、skill frontmatter hooks、plugin hook load/hot reload、更多 event bootstrap、`SkillExecutionMode::Agent`。 - - `compat`:`agent_type / agent_config` 继续保留,但不再主导 `Agent hook` current 行为。 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 从“prompt hook 已 current、agent hook 仍是假实现”的断层,推进成“扩展体系至少已有两条真实 LLM hook current 主链”;这样后续剩余差距就集中到 `MCP hook + 更多 event bootstrap + skill frontmatter/plugin hooks`,不再混着一个明显的执行空洞。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/hooks/executor.rs" "src-tauri/crates/aster-rust/crates/aster/src/hooks/types.rs" "src-tauri/crates/aster-rust/crates/aster/src/hooks/registry.rs" "src-tauri/crates/aster-rust/crates/aster/src/hooks/tests.rs" "src-tauri/crates/aster-rust/crates/aster/src/agents/agent.rs"` 通过 - - `env CARGO_INCREMENTAL=0 RUSTFLAGS="-Cdebuginfo=0" CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" execute_agent_hook_with_provider_should_ --lib --no-default-features` 通过(`3 passed`) - - `env CARGO_INCREMENTAL=0 RUSTFLAGS="-Cdebuginfo=0" CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_agent_hook_config_ --lib --no-default-features` 通过(`2 passed`) - - `env CARGO_INCREMENTAL=0 RUSTFLAGS="-Cdebuginfo=0" CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" execute_prompt_hook_with_provider_should_ --lib --no-default-features` 通过(`2 passed`) - - `env CARGO_INCREMENTAL=0 RUSTFLAGS="-Cdebuginfo=0" CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" parse_prompt_hook_response_should_accept_fenced_json --lib --no-default-features` 通过(`1 passed`) - - `env CARGO_INCREMENTAL=0 RUSTFLAGS="-Cdebuginfo=0" CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" replace_prompt_hook_arguments_should_append_json_when_no_placeholder --lib --no-default-features` 通过(`1 passed`) - - 运行时仍会看到工作区既有 `unused import` warning:`task_list_tools.rs`、`worktree_tools.rs`;与本轮 `Agent hook` 改动无关,继续不顺手扩大范围清理。 -- 当前最值得继续推进的一刀也已变化: - - `SessionStart(resume)` 继续明确保留为 gap,不再回头把 queue resume 或前端 `/clear` 硬映射成 session lifecycle resume。 - - 下一刀优先转向 `MCP hook current`,这样 `CCD-008` 剩余 executor placeholder 就只剩一类,而不是继续卡在 `command/url/prompt/agent` 四种里只差一个。 - -### 继续推进(CCD-008 / MCP hook current) - -- 继续沿 `hooks / skills` 主线推进后,`MCP hook` 已从占位实现推进成真实 current 执行,不再只是 `warn! + success(None)`: - - [types.rs](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/types.rs) 新增 `HookRuntimeContext` 与 `McpHookExecutor`,让 `aster hooks` 可以显式接收宿主 runtime 提供的 MCP dispatcher,而不是在 `aster` crate 里直接耦合 Tauri 层状态。 - - [executor.rs](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/executor.rs) 的 `MCP hook` 现在会真正执行 runtime dispatcher,并在 hook 边界统一处理 timeout / missing-dispatcher;`run_hooks_with_registry(...)`、`UserPromptSubmit` 与 `SessionStart` 也都补了 `*_with_registry_and_context(...)` 入口,避免再把“只能跑无上下文 hook”当成默认前提。 - - [runtime_project_hooks.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 新增 Lime current runtime 注入层:执行 `MCP hook` 前会先确保 `Agent` 已初始化,再按现有主链做 `ensure_lime_mcp_servers_running(...) + inject_mcp_extensions(...)`,随后复用当前 [extension_manager.rs](../../src-tauri/crates/aster-rust/crates/aster/src/agents/extension_manager.rs) `dispatch_tool_call(...)` 分发真实 `mcp____` 调用,而不是绕到底层另造一套 MCP lifecycle。 - - 同一层还补了 `CallToolResult -> HookResult` 收口:若 MCP 返回 `structured_content` 或文本 JSON 中带 `{"blocked":true,"message":"..."}`,现在会真实映射到 `HookResult::blocked(...)`;普通文本/structured payload 则回传为 hook output。 - - [runtime_turn.rs](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 的 `UserPromptSubmit`,以及 [session_runtime.rs](../../src-tauri/src/commands/aster_agent_cmd/session_runtime.rs) / compact `SessionStart` 入口,现在都会带着 runtime context 跑 project hooks,确保 Lime 当前宿主主路径上的 `MCP hook` 真能命中 current MCP bridge。 -- 这一步后的 `CCD-008` 边界进一步收紧为: - - `current`:`TaskCreated / TaskCompleted` hooks、project-level `UserPromptSubmit`、`SessionStart(startup / compact)`、`command / url / prompt / agent / mcp` hook executor、`SkillTool` prompt/workflow execution。 - - `current gap`:`SessionStart(resume)`、skill frontmatter hooks、plugin hook load/hot reload、更多 event bootstrap、`SkillExecutionMode::Agent`。 - - `compat`:`agent_type / agent_config` 继续只作为 `Agent hook` fallback;没有新增兼容 MCP 路径。 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 剩余最后一类明显的 executor placeholder 推成 Lime current,避免扩展体系继续停留在“command/url/prompt/agent 都能真执行,唯独 MCP hook 还是空壳”的断层状态。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/hooks/types.rs" "src-tauri/crates/aster-rust/crates/aster/src/hooks/executor.rs" "src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs" "src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs" "src-tauri/src/commands/aster_agent_cmd/session_runtime.rs" "src-tauri/src/commands/aster_agent_cmd/command_api/session_api.rs" "src-tauri/src/commands/aster_agent_cmd/command_api.rs" "src-tauri/src/dev_bridge/dispatcher/agent_sessions.rs"` 通过 - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" execute_mcp_hook_should_ --lib --no-default-features` 通过(`4 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/Cargo.toml" convert_runtime_mcp_call_result_should_ --lib` 通过(`2 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/Cargo.toml" create_runtime_session_internal_should_run_project_session_start_hooks --lib` 通过(`1 passed`) -- 当前最值得继续推进的一刀也已变化: - - `SessionStart(resume)` 继续明确保留为 gap,不再回头把 queue resume 或前端 `/clear` 硬映射成 session lifecycle resume。 - - 下一刀优先转向 `SkillExecutionMode::Agent` 或 skill frontmatter hooks,这样 `CCD-008` 剩余差距会进一步集中到 skill/plugin/event bootstrap,而不再混着 executor 空洞。 - -### 继续推进(CCD-008 / SkillExecutionMode::Agent current) - -- 继续对照本地参考运行时 `"/Users/coso/Documents/dev/js/claudecode/src/tools/SkillTool/SkillTool.ts"` 与 `"/Users/coso/Documents/dev/js/claudecode/src/utils/forkedAgent.ts"` 后,确认 `SkillExecutionMode::Agent` 不该再往 `SkillExecutor` 里补一套平行 runtime: - - upstream 的 forked skill 本质是“先构造 skill content,再起隔离子 agent,上到既有 agent query loop”; - - 因此 Lime 本轮把 `Agent` skill 的 current 事实源固定到 [`skills/tool.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/skills/tool.rs) + [`agent.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/agents/agent.rs) `Agent.reply(...)` 主链,而不是继续扩 `SkillExecutor`。 -- [`skills/tool.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/skills/tool.rs) 现已完成这条收口: - - `SkillTool.execute_skill(...)` 遇到 `SkillExecutionMode::Agent` 时不再直接报“未实现”,而是进入新的 `execute_agent_skill(...)`。 - - skill prompt 构造已向 upstream 靠拢:会注入 `Base directory for this skill: ...` 头部,并替换 `${CLAUDE_SKILL_DIR}` / `${CLAUDE_SESSION_ID}`;参数仍保持当前最小行为,继续追加 `**ARGUMENTS:** ...`,没有为了统一接口再倒腾一套假命令插值层。 - - provider 解析收回到单一 `resolve_skill_provider(...)`:优先复用当前 session provider;skill 自带 provider 时按绑定名创建或复用同名 provider;`Prompt / Workflow` 继续包进 `SessionLlmProvider`,`Agent` 直接消费真实 `Arc`。 - - agent skill 会创建隔离的 `SkillAgentSessionStore` 与临时 `SubAgent` session,并显式把权限模式切到 `AsterMode::Auto`,然后直接复用 `Agent.reply(...)` 执行;这样 skill agent 不会污染正式 session 存储,也不会卡在交互式审批流。 - - `Prompt / Workflow` 继续保持在 `SkillExecutor` current 边界,没有为了“看起来统一”把 agent path 再塞回 executor。 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:`TaskCreated / TaskCompleted` hooks、project-level `UserPromptSubmit`、`SessionStart(startup / compact)`、`command / url / prompt / agent / mcp` hook executor、`SkillTool` prompt/workflow/agent execution。 - - `current gap`:`SessionStart(resume)`、skill frontmatter hooks、plugin hook load/hot reload、更多 event bootstrap,以及 agent skill 的 `allowed_tools` 真实权限收紧目前仍未接入 runtime permission context。 - - `compat / deprecated / dead`:无新增;本轮没有为了“兼容旧 executor”再引入第二套 skill runtime。 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 最后一个明显的 skill executor 空洞补到 current,让 Lime 不再停在“hooks 都能真执行,但 agent skill 仍是假实现”的断层状态;下一刀应优先回到 skill/plugin/event bootstrap 缺口,而不是再回头发明 compat 包装层。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/skills/tool.rs"` 通过 - - `env CARGO_INCREMENTAL=0 RUSTFLAGS="-Cdebuginfo=0" CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_skill_tool_ --lib --no-default-features` 通过(`9 passed`) - - 运行时仍会看到工作区既有 `unused import` warning:`task_list_tools.rs`、`worktree_tools.rs`;与本轮 `SkillExecutionMode::Agent` 收口无关,继续不顺手扩大范围清理。 - -### 继续推进(CCD-008 / Skill frontmatter hooks current) - -- 继续对照本地参考运行时: - - `"/Users/coso/Documents/dev/js/claudecode/src/skills/loadSkillsDir.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/processUserInput/processSlashCommand.tsx"` - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/hooks/registerSkillHooks.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/hooks/sessionHooks.ts"` - 后确认 `skill frontmatter hooks` 也不该再额外造一套 skill-specific hook executor;upstream 的事实源本质是“skill 加载出 hooks,slash command 执行时注册到 session-scoped hook store,真正执行仍走统一 hooks runtime”。因此 Lime 本轮继续把事实源收口到现有 `HookConfig + run_hooks_with_registry_and_context(...)` 主链,而不是给 skill hooks 再补平行 runtime。 -- [`hooks/types.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/types.rs) 与 [`skills/types.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/skills/types.rs) 现已补齐 current 类型面: - - `SkillFrontmatter` / `SkillDefinition` 新增 `hooks` - - `FrontmatterHooks = event -> matcher[] -> hooks[]` - - `command / prompt / agent / http(url alias)` 会在注册阶段转换成 Lime 当前 `HookConfig` - - `timeout` 按 upstream 秒制收口到当前毫秒制 - - `once` 进入注册语义,而不是留在前端假字段 -- 为了避免假兼容,当前没有真实 runtime 语义的字段继续显式拒绝,而不是静默吞掉: - - `hook.if` - - `command.asyncRewake` - - `command.shell != bash` - - `http.allowedEnvVars` - 这些字段现在会在注册阶段返回明确错误,并通过 `SkillTool` warning 暴露,不会伪装成“已支持”。 -- [`hooks/registry.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/registry.rs) 新增 `SessionHookStore`,把 skill frontmatter hooks 收口到 session-scoped current store: - - 每条注册项都有唯一 `entry.id` - - `once` hook 成功后按 entry 级别删除,避免重复注册后一删全删 - - `clear_hooks()` 与 `run_session_end_hooks(...)` 都会清掉当前 session hooks -- [`hooks/executor.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/executor.rs) 现已在统一 hooks runtime 中合并 session hooks: - - 先跑 registry hooks,再按 `input.session_id` 合并 session hooks - - `once` 仅在 hook 成功后移除 - - 没有为了接 skill hooks 把执行逻辑分叉成第二条路径 -- [`skills/loader.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/skills/loader.rs) 与 [`skills/tool.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/skills/tool.rs) 现已把这条链真正接到 Skill current 主入口: - - loader 会把 `SKILL.md` frontmatter 里的 `hooks` 读进 `SkillDefinition` - - `SkillTool.execute_skill(...)` 会在 skill 真正执行前,把 frontmatter hooks 注册到当前 session - - 若当前调用缺少 `session_id`,只会 warning 并跳过注册;不会为了“看起来兼容”偷偷落回全局共享 registry -- 宿主主路径也已补了回归证明这条链真的接进 Lime runtime,而不只是 crate 内部自测: - - [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 新增定向测试,证明 `run_runtime_session_start_project_hooks_for_session(...)` 执行 `SessionStart(compact)` 时,会同时命中当前 session 的 skill hooks -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:`TaskCreated / TaskCompleted` hooks、project-level `UserPromptSubmit`、`SessionStart(startup / compact)`、`command / url / prompt / agent / mcp` hook executor、`SkillTool` prompt/workflow/agent execution、skill frontmatter hooks - - `current gap`:agent frontmatter hooks 及其 `Stop -> SubagentStop` 事件改写、`SessionStart(resume)`、plugin hook load/hot reload、更多 event bootstrap、agent skill 的 `allowed_tools` 真实权限收紧 - - `explicitly unsupported gap`:`hook.if`、`asyncRewake`、非 `bash` shell、`allowedEnvVars` - - `compat / deprecated / dead`:无新增;本轮没有为了接 skill hooks 再造 compat executor 或回退到全局共享状态 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 里“skill frontmatter hooks 只是 schema 存在、runtime 仍空着”这一块推进到 Lime current,避免扩展体系继续停在“project hooks 能执行、agent skill 能执行,但 skill 自己声明的 hooks 仍完全不生效”的断层状态。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/hooks/types.rs" "src-tauri/crates/aster-rust/crates/aster/src/hooks/registry.rs" "src-tauri/crates/aster-rust/crates/aster/src/hooks/executor.rs" "src-tauri/crates/aster-rust/crates/aster/src/skills/loader.rs" "src-tauri/crates/aster-rust/crates/aster/src/skills/tool.rs" "src-tauri/crates/aster-rust/crates/aster/src/hooks/tests.rs" "src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs"` 通过 - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target-2" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" frontmatter --lib --no-default-features` 通过(`26 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target-2" cargo test --manifest-path "src-tauri/Cargo.toml" run_runtime_session_start_project_hooks_for_session_should_merge_session_skill_hooks --lib` 通过(`1 passed`) -- 下一刀最值得继续推进的是: - - 先补 agent frontmatter hooks,并按 upstream 明确把 `Stop` 重写为 `SubagentStop` - - 然后再处理 agent skill `allowed_tools` 的真实权限上下文 - - `plugin hooks / hot reload` 继续留在下一梯队,不建议与前两刀同轮并摊 - -### 继续推进(CCD-008 / Agent skill allowed_tools current) - -- 继续对照本地参考运行时: - - `"/Users/coso/Documents/dev/js/claudecode/src/tools/AgentTool/runAgent.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/tools/AgentTool/loadAgentsDir.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/hooks/registerFrontmatterHooks.ts"` - 后确认 agent skill 的 `allowed_tools / disallowed_tools` 也不该再额外造一套 agent-specific permission 容器;upstream 的事实源本质是“agent surface 接收 tool scope,再把它下沉到当前 session 权限规则”。因此 Lime 本轮继续把事实源收口到现有 `ToolPermissionManager + PermissionScope::Session` 主链,而不是为了迁就旧实现再补一层 compat 包装。 -- [`dto.rs`](../../src-tauri/src/commands/aster_agent_cmd/dto.rs)、[`types.ts`](../../src/lib/api/agentRuntime/types.ts)、[`tool_runtime/subagent_tools.rs`](../../src-tauri/src/commands/aster_agent_cmd/tool_runtime/subagent_tools.rs) 与 [`agent_control.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/tools/agent_control.rs) 现已补齐 current 输入面: - - `AgentRuntimeSpawnSubagentRequest` 新增 `allowed_tools / disallowed_tools` - - `SpawnAgentRequest` 同步承载同名字段 - - callback-backed `Agent` current surface 也会把这两组字段带入 runtime,而不是只在 prompt 或 metadata 里做展示 -- [`subagent_profiles.rs`](../../src-tauri/crates/agent/src/subagent_profiles.rs)、[`session_store.rs`](../../src-tauri/crates/agent/src/session_store.rs) 与 [`subagent_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs) 现已把这组 tool scope 收进 subagent current 持久化主链: - - `SubagentCustomizationState` 新增 `allowed_tools / disallowed_tools` - - `build_subagent_customization_state(...)` 会做去空、去重、归一化 - - subagent system prompt 会显式渲染 `Allowed Tools` 与 `Disallowed Tools` - - spawn / send_input 进入子会话时,这两组字段都会写入 `request.metadata.subagent` -- [`tool_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/tool_runtime.rs) 现已把 metadata 里的 tool scope 真正转成 session-scoped runtime 权限,而不是停留在“前端传了、后端知道、执行时没用”的假支持: - - 新增 `append_subagent_tool_scope_session_permissions(...)` - - 若存在 `allowed_tools`,先写一条 `tool="*"` 的 session-scoped deny,优先级 `1298` - - 再为每个 allow 工具写入 session-scoped allow,优先级 `1299` - - 最后为每个 disallow 工具写入 session-scoped deny,优先级 `1300` - - 这样保持“白名单默认收紧,黑名单高于白名单,并且只作用于当前 child session” -- [`agent.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/agents/agent.rs) 与 [`subagent_tool.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/agents/subagent_tool.rs) 继续把 current/非 current 边界收紧: - - current callback-backed `Agent` surface 只要携带 `allowed_tools / disallowed_tools`,就强制走 callback-backed runtime,不再悄悄退回旧的 foreground native subagent path - - 非 callback-backed runtime 若传这两项,会显式报错 `allowed_tools is only supported in callback-backed runtimes` / `disallowed_tools is only supported in callback-backed runtimes` - - 也就是说,本轮没有为了“看起来兼容”把不生效的字段继续吞掉 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:`TaskCreated / TaskCompleted` hooks、project-level `UserPromptSubmit`、`SessionStart(startup / compact)`、`command / url / prompt / agent / mcp` hook executor、`SkillTool` prompt/workflow/agent execution、skill frontmatter hooks、agent skill `allowed_tools / disallowed_tools` session permission 收口 - - `current gap`:agent frontmatter hooks 及其 `Stop -> SubagentStop` 事件改写、`SessionStart(resume)`、plugin hook load/hot reload、更多 event bootstrap - - `explicitly unsupported gap`:`hook.if`、`asyncRewake`、非 `bash` shell、`allowedEnvVars` - - `compat / deprecated / dead`:无新增;本轮没有为了 agent tool scope 再引入第二套 subagent 权限容器,也没有把旧 foreground path 包装成“看起来支持” -- 这一步服务路线图主目标的关系是:把 `CCD-008` 里“agent skill 看起来能声明工具白名单,但 runtime 实际不会收紧权限”的最后一段假对齐推进到 Lime current,避免扩展体系继续停在“schema 有字段、system prompt 有文案、真实执行权限仍没变”的断层状态。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/agents/subagent_tool.rs"` 通过 - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target-subagent-runtime" cargo test --manifest-path "src-tauri/Cargo.toml" test_append_subagent_tool_scope_session_permissions_enforces_child_session_scope --lib` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target-aster-subagent" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_agent_tool_routes_tool_scope_through_callbacks --lib --no-default-features` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target-lime-agent" cargo test --manifest-path "src-tauri/crates/agent/Cargo.toml" build_child_subagent_session_summary_should_merge_customization_state --lib` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target-subagent-runtime" cargo test --manifest-path "src-tauri/Cargo.toml" spawn_subagent_request_should_parse_current_fields --lib` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target-subagent-runtime" cargo test --manifest-path "src-tauri/Cargo.toml" test_build_subagent_customization_system_prompt_renders_builtin_configuration --lib` 通过(`1 passed`) -- 下一刀最值得继续推进的是: - - 先补 agent frontmatter hooks,并按 upstream 明确把 `Stop` 重写为 `SubagentStop` - - 再决定 `SessionStart(resume)` 是否存在真实 current 入口;若没有,就不要硬映射 - - `plugin hooks / hot reload` 继续留在下一梯队,不建议与前两刀同轮并摊 - -### 继续推进(CCD-008 / Agent frontmatter hooks current) - -- 继续对照本地参考运行时: - - `"/Users/coso/Documents/dev/js/claudecode/src/tools/AgentTool/runAgent.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/hooks/registerFrontmatterHooks.ts"` - 后确认 agent frontmatter hooks 也不该再额外造一套 agent-specific hook runtime;upstream 的事实源本质是“agent spawn 请求携带 hooks,child session 创建完成后注册到 session-scoped hook store,并在 agent 场景把 `Stop` 改写为 `SubagentStop`”。因此 Lime 本轮继续把事实源收口到现有 `SpawnAgentRequest -> SessionHookStore -> unified hooks executor` 主链,而不是为了迁就旧实现去扩 `.claude/agents`、`loadAgentsDir` 或第二套 hook 容器。 -- [`hooks/types.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/types.rs) 与 [`hooks/registry.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/registry.rs) 现已补齐 agent frontmatter hooks 的 current 注册能力: - - frontmatter hook 相关类型补了 `PartialEq / Eq`,确保 `SpawnAgentRequest` 与 `SubagentCustomizationState` 继续能作为 current 状态值稳定比较 - - 新增 `register_agent_session_frontmatter_hooks(...)` - - `Stop -> SubagentStop` 只在 frontmatter 注册层做事件改写,不把分支散到执行器里 - - 空 matcher / 空 hooks 会在注册前被收掉,不会为了“看起来兼容”留下空壳配置 -- [`agent_control.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/tools/agent_control.rs)、[`dto.rs`](../../src-tauri/src/commands/aster_agent_cmd/dto.rs) 与 [`types.ts`](../../src/lib/api/agentRuntime/types.ts) 现已补齐 current 输入面: - - `SpawnAgentRequest` 新增 `hooks` - - `AgentRuntimeSpawnSubagentRequest` 新增 `hooks` - - 前端 runtime 类型同步暴露 `AgentRuntimeFrontmatterHooks` - - `SpawnAgentTool` 继续显式传 `hooks: None`,没有把这组字段扩成模型自由生成的新工具协议 -- [`subagent_profiles.rs`](../../src-tauri/crates/agent/src/subagent_profiles.rs)、[`subagent_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs) 与 [`tool_runtime/subagent_tools.rs`](../../src-tauri/src/commands/aster_agent_cmd/tool_runtime/subagent_tools.rs) 现已把 callback-backed runtime 的 agent hooks 收进 child session current 主链: - - `SubagentCustomizationState` 新增 `hooks` - - `build_subagent_customization_state(...)` 会保留并归一化 `request.hooks` - - callback-backed runtime 转发 spawn request 时会继续透传 `hooks` - - `create_runtime_subagent_session(...)` 在 child session 初始化完成后调用 `register_runtime_subagent_frontmatter_hooks(...)` -- [`execution/manager.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/execution/manager.rs) 则把 aster 原生 spawn path 一并收口: - - 新增 `register_spawned_agent_frontmatter_hooks(...)` - - `spawn_agent_with_runtime(...)` 在 child session 完整创建后注册 hooks - - 这样 Lime 当前两条真实 child session 创建点都已接上 agent frontmatter hooks,而不是只补 callback-backed 一半 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:`TaskCreated / TaskCompleted` hooks、project-level `UserPromptSubmit`、`SessionStart(startup / compact)`、`command / url / prompt / agent / mcp` hook executor、`SkillTool` prompt/workflow/agent execution、skill frontmatter hooks、agent skill `allowed_tools / disallowed_tools` session permission 收口、agent frontmatter hooks 与 `Stop -> SubagentStop` 注册改写 - - `current gap`:`SessionStart(resume)`、plugin hook load/hot reload、更多 event bootstrap - - `explicitly unsupported gap`:`hook.if`、`asyncRewake`、非 `bash` shell、`allowedEnvVars` - - `compat / deprecated / dead`:无新增;本轮没有为了 agent hooks 再发明第二套 agent definition / hook runtime -- 这一步服务路线图主目标的关系是:把 `CCD-008` 里“skill hooks 已 current,但 agent 自己声明的 frontmatter hooks 仍完全不生效”的最后一段 frontmatter 断层推进到 Lime current,避免扩展体系继续停在“project/skill 都会注册 hooks,唯独 subagent surface 仍绕开 hooks”的假对齐状态。 -- 已执行定向校验: - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target-aster-subagent" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_agent_frontmatter_hooks_rewrite_stop_to_subagent_stop --lib --no-default-features` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target-aster-subagent" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_spawned_named_agent_registers_name_route_for_parent_session --lib --no-default-features` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target-subagent-runtime" cargo test --manifest-path "src-tauri/Cargo.toml" spawn_subagent_request_should_parse_current_fields --lib` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target-subagent-runtime" cargo test --manifest-path "src-tauri/Cargo.toml" test_build_subagent_customization_state_keeps_frontmatter_hooks --lib` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target-subagent-runtime" cargo test --manifest-path "src-tauri/Cargo.toml" test_register_runtime_subagent_frontmatter_hooks_rewrites_stop_event --lib` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target-lime-agent" cargo test --manifest-path "src-tauri/crates/agent/Cargo.toml" build_child_subagent_session_summary_should_merge_customization_state --lib` 通过(`1 passed`) - - `npm run test:contracts` 通过 -- 下一刀最值得继续推进的是: - - 先判断 `SessionStart(resume)` 是否存在真实 current 宿主入口;若没有,就明确留作 gap,不再反复犹豫 - - 然后转向 `plugin hooks / hot reload` - - 更多 event bootstrap 继续按真实宿主入口逐条推进,不建议为了“枚举对齐”先补假调用点 - -### 继续推进(CCD-008 / Plugin hooks current) - -- 继续对照本地参考运行时: - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/plugins/loadPluginHooks.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/sessionStart.ts"` - 后确认 Lime 这一刀不该把旧 `PluginInstaller / plugin_cmd.rs` 再抬成 runtime hook 事实源;upstream 的真实主链是“enabled plugin settings + plugin cache -> hooks merge -> SessionStart/UserPromptSubmit bootstrap”。因此本轮继续把事实源收口到 `runtime_project_hooks.rs -> HookRegistry` 当前主链,而不是为了迁就旧实现再补第二套 plugin hook executor。 -- [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 现已把 plugin hooks 接进当前 runtime registry: - - `load_runtime_project_hook_registry(...)` 现会在装载 project hooks 后继续合并 enabled plugin cache hooks - - enabled plugin 读取链先按 `~/.claude/settings.json -> ~/.claude/settings.local.json -> /.claude/settings.json -> /.claude/settings.local.json` 覆盖收口 - - 插件目录只认 `~/.claude/plugins/cache////` current cache,不再把 Lime 自己的 installer 目录包装成“看起来也能跑”的 compat 主链 - - hook 装载支持标准 `hooks/hooks.json` 与 `.claude-plugin/plugin.json` 里的 `manifest.hooks`,包括 path / inline / array 三种 upstream 当前形态 - - runtime registry 每次 `SessionStart` / `UserPromptSubmit` 入口都会重新构建,因此已支持的 plugin hook 变更会在下一次 runtime 入口自然生效,不再额外发明 watcher 或第二层缓存失效协议 -- 这一步同时把 `SessionStart(resume)` 的结论显式钉住: - - Lime 当前公开的 [`agent_runtime_resume_thread`](../../src-tauri/src/commands/aster_agent_cmd/command_api/runtime_api.rs) 仍只是恢复排队线程执行,不是 Claude Code 那种明确的 session lifecycle resume - - 因此 `SessionStart(resume)` 继续保留为 `current gap`,本轮没有把 queue resume 或前端本地清空动作硬包装成假宿主入口 -- 新增定向测试已经把两条 plugin hook current 路径锚住: - - 标准 `hooks/hooks.json` 插件 hook 会进入 `SessionStart` current registry,并真实执行 - - `.claude-plugin/plugin.json` 里的 inline `manifest.hooks` 会进入 `UserPromptSubmit` current registry,并能真实阻止提交 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:`TaskCreated / TaskCompleted` hooks、project-level `UserPromptSubmit`、`SessionStart(startup / compact)`、`command / url / prompt / agent / mcp` hook executor、`SkillTool` prompt/workflow/agent execution、skill frontmatter hooks、agent frontmatter hooks、plugin hooks(runtime `SessionStart / UserPromptSubmit` current surfaces) - - `current gap`:`SessionStart(resume)`、更多 runtime event bootstrap、plugin hook 与 upstream managed policy / builtin plugin 加载链的完全同构仍未补齐 - - `explicitly unsupported gap`:`hook.if`、`asyncRewake`、非 `bash` shell、`allowedEnvVars` - - `compat / deprecated / dead`:无新增;本轮没有为了 plugin hooks 再接 `PluginInstaller` 目录、也没有发明第二套 plugin hook runtime -- 这一步服务路线图主目标的关系是:把 `CCD-008` 里“project/skill/agent hooks 都已 current,但 plugin 自带 hooks 仍完全绕过 runtime”的最后一段 plugin 断层推进到 Lime current,避免扩展体系继续停在“插件只会带技能,不会真正带 runtime hooks”的假对齐状态。 -- 已执行定向校验: - - `cargo fmt --manifest-path "src-tauri/Cargo.toml" --all` - - `cargo check --manifest-path "src-tauri/Cargo.toml" -p lime --tests` 通过 - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib load_runtime_project_hook_registry_should_include_` 通过(`2 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib runtime_project_hooks::tests::` 通过(`7 passed`) -- 下一刀最值得继续推进的是: - - 继续保持 `SessionStart(resume)` 为显式 gap,不再来回犹豫 - - 然后按真实宿主入口继续补更多 runtime event bootstrap,而不是为了枚举对齐先补假调用点 - - 如果要追平 plugin loader 语义,再单独评估 managed policy / builtin plugin hooks 是否也要并入当前 Rust runtime,而不是把旧 installer 重新接回来 - -### 继续推进(CCD-008 / PreCompact hooks current) - -- 继续对照本地参考运行时: - - `"/Users/coso/Documents/dev/js/claudecode/src/services/compact/compact.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/hooks.ts"` - 后确认这一步最适合继续补的是 `PreCompact`,而不是为了追枚举先去硬造 `Stop / SessionEnd / PermissionRequest` 宿主入口。Lime 当前唯一干净、单一的压缩宿主入口就是 [`compact_runtime_session_with_trigger(...)`](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs),因此本轮继续把事实源收口到 `runtime_turn -> runtime_project_hooks -> HookRegistry` 当前主链,不去扩第二套 lifecycle runtime。 -- [`executor.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/executor.rs) 现已补齐 `PreCompact` 的 registry-aware current 执行入口: - - 新增 `run_pre_compact_hooks_with_registry(...)` - - 新增 `run_pre_compact_hooks_with_registry_and_context(...)` - - 现有 `run_pre_compact_hooks(...)` 只负责委托到 registry-aware helper,不再把 `PreCompact` 隐式绑死在全局注册表上 -- [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 现已补齐 `PreCompact` 的 per-workspace runtime helper: - - 新增 `enforce_runtime_pre_compact_project_hooks_with_runtime(...)` - - 新增 `enforce_runtime_pre_compact_project_hooks_for_session_with_runtime(...)` - - helper 会继续复用现有 `resolve_runtime_project_hook_workspace_root(...)`,因此 `workspace_id -> workspace_root` 与 `working_dir fallback` 仍保持单一事实源,不会为了压缩前 hooks 再散出一套 project root 猜测逻辑 - - hook 结果继续经过 `log_runtime_project_hook_results(...)`;失败型 hooks 只记 warning,真正 `blocked` 才会中断压缩 -- [`runtime_turn.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 现已把 `PreCompact` 真正接到 runtime 宿主入口: - - `compact_runtime_session_with_trigger(...)` 会在读取到可压缩 conversation 之后、真正创建 compaction turn 之前,先运行 project/plugin/session 的 `PreCompact` - - `manual / auto` 两种压缩统一映射到 `CompactTrigger::Manual / Auto`,不再只有手动 `/compact` 才经过 hooks - - `current_tokens` 会优先使用 session 上的 `total_tokens`,缺失时再回退 `TokenEstimator::estimate_total_tokens(conversation.messages())`,避免把 `PreCompact` 输入继续留成空壳 - - 若 `PreCompact` 返回 `blocked`,手动压缩会直接失败;自动压缩则继续复用现有降级策略,由 `maybe_auto_compact_runtime_session_before_turn(...)` 把失败转成 warning 并继续当前 turn -- 这一步同时也把“当前不该补什么”钉得更清楚: - - `SessionStart(resume)` 仍然继续保留为 gap,本轮没有回头把 queue resume 伪装成 session lifecycle - - `Stop / SessionEnd / PermissionRequest` 仍待先确认 Lime 是否存在单一、可接受的 current 宿主入口;本轮没有为了枚举对齐先补假调用点 -- 新增定向测试已经把 `PreCompact` current 路径锚住: - - `PreCompact` hook 会收到真实 `event / trigger / current_tokens / session_id` - - 阻塞型 `PreCompact` hook 会真实中断压缩,而不是只打日志继续往下执行 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:`TaskCreated / TaskCompleted` hooks、project-level `UserPromptSubmit`、`SessionStart(startup / compact)`、`PreCompact`、`command / url / prompt / agent / mcp` hook executor、`SkillTool` prompt/workflow/agent execution、skill frontmatter hooks、agent frontmatter hooks、plugin hooks(runtime `SessionStart / UserPromptSubmit / PreCompact` current surfaces) - - `current gap`:`SessionStart(resume)`、`Stop / SessionEnd / PermissionRequest` 等更多 runtime event bootstrap、plugin hook 与 upstream managed policy / builtin plugin 加载链的完全同构仍未补齐 - - `explicitly unsupported gap`:`hook.if`、`asyncRewake`、非 `bash` shell、`allowedEnvVars` - - `compat / deprecated / dead`:无新增;本轮没有为了 `PreCompact` 再发明第二套 compaction lifecycle runtime -- 这一步服务路线图主目标的关系是:把参考运行时图里“压缩前也会经过 hooks”这条 extension 主链补进 Lime current,避免扩展体系继续停在“SessionStart / UserPromptSubmit 已 current,但 compaction 仍完全绕过 hooks”的断层状态。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/hooks/executor.rs" "src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs" "src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs"` 通过 - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib enforce_runtime_pre_compact_project_hooks_for_session_should_` 通过(`2 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib runtime_project_hooks::tests::` 通过(`9 passed`) - - `cargo check --manifest-path "src-tauri/Cargo.toml" -p lime --tests` 通过(仅剩工作区既有 warning:`crates/services/src/api_key_provider_service.rs` 的 `selected_key` 未使用) -- 下一刀最值得继续推进的是: - - 继续保持 `SessionStart(resume)` 为显式 gap,不再来回犹豫 - - 优先核定 `Stop / SessionEnd / PermissionRequest` 哪一条在 Lime 里已有单一 current 宿主入口,再补下一类 event bootstrap - - 如果要追平 plugin loader 语义,再单独评估 managed policy / builtin plugin hooks 是否也要并入当前 Rust runtime,而不是把旧 installer 重新接回来 - -### 继续推进(CCD-008 / PermissionRequest hooks current) - -- 继续对照本地参考运行时: - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/hooks.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/permissions/permissions.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/hooks/toolPermission/PermissionContext.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/cli/structuredIO.ts"` - 后确认这一步最需要补的不是再去给 `ToolRegistry` 造一层 callback 兼容壳,而是把 `PermissionRequest` 直接接到 Lime 当前真实 approval host:[`handle_approval_tool_requests(...)`](../../src-tauri/crates/aster-rust/crates/aster/src/agents/tool_execution.rs)。因此本轮继续把事实源收口到 `runtime_turn -> agent permission_request_hook_handler -> tool_execution approval host -> runtime_project_hooks -> HookRegistry` 当前主链,不去扩第二套 permission runtime。 -- [`types.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/agents/types.rs)、[`mod.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/agents/mod.rs) 与 [`agent.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/agents/agent.rs) 现已补齐 `PermissionRequest` 当前宿主注入面: - - 新增 `PermissionRequestHookContext / PermissionRequestHookDecision / PermissionRequestHookHandler` - - `Agent` 新增 `permission_request_hook_handler` 字段与 `set_permission_request_hook_handler(...)` - - handler 默认仍为 `None`,避免把 hooks 语义硬塞进所有 runtime;只有 Lime current 宿主入口会显式安装它 -- [`tool_execution.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/agents/tool_execution.rs) 现已把 `PermissionRequest` 接进真实 approval host: - - `handle_approval_tool_requests(...)` 会在发出 `action_required` 之前,先执行 `run_permission_request_hook_handler(...)` - - hook 返回 `Allow` 时会直接 `dispatch_tool_call(...)`,不再继续发人工审批 - - hook 返回 `Deny { message }` 时会直接把错误 `CallToolResult` 写回 response message,不再继续发人工审批 - - hook 执行失败时只记 warning,并显式回退到现有人工审批链,不会因为 hook 出错把当前 permission path 打断 - - `permission_mode` 当前只做保守映射:`Approve / SmartApprove -> default`、`Auto -> bypassPermissions`、`Chat -> None`;本轮没有为了追平文本枚举去硬塞 `plan / dontAsk` -- [`runtime_turn.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 与 [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 现已补齐 `PermissionRequest` 的 current 宿主对接: - - `prepare_runtime_turn_entry(...)` 会安装 `PermissionRequestHookHandler` - - handler closure 继续只捕获当前 single-source runtime 依赖:`db + AsterAgentState + McpManagerState` - - `decide_runtime_permission_request_project_hooks_for_session_with_runtime(...)` 继续复用 `resolve_runtime_project_hook_workspace_root(...)` 与同一条 project/plugin/session hook registry 主链,不为 `PermissionRequest` 再散一套 project root / plugin loader 旁路 - - 当前 hook JSON 决策只支持: - - `{"decision":"allow"}` - - `{"decision":"deny","message":"..."}` -- [`hooks/types.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/types.rs) 与 [`hooks/executor.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/executor.rs) 现已把 `permission_mode` 接进现有 hook 输入与执行环境: - - `HookInput` 新增 `permission_mode` - - command hook 环境变量新增 `CLAUDE_HOOK_PERMISSION_MODE` - - command 占位符新增 `$PERMISSION_MODE` - - url hook payload 也会继续透传 `permissionMode` -- 这一步同时也把“当前不该假装完成什么”钉得更清楚: - - `SessionStart(resume)` 仍然继续保留为 gap,本轮没有回头把 queue resume 伪装成 session lifecycle - - `Stop / SessionEnd` 仍待先确认 Lime 是否存在单一、可接受的 current 宿主入口;本轮没有为了补齐 event 名字先补假调用点 - - upstream `PermissionRequestResult` 里的 `updatedInput / updatedPermissions / interrupt` 仍未实现;本轮只先补最小 current allow/deny 决策,不为迁就旧逻辑去拼半套兼容协议 - - plugin hook 与 upstream managed policy / builtin plugin 加载链的完全同构仍未补齐 -- 新增定向测试已经把 `PermissionRequest` current 路径锚住: - - project hook 会收到真实 `event / permission_mode / tool_use_id / session_id` - - `allow / deny(message)` 两条 decision path 都已落到 runtime helper 定向测试 - - approval host 侧已补 `auto-allow / auto-deny` 两条 end-to-end 单测,防止之后又回流成 `action_required` -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:`TaskCreated / TaskCompleted` hooks、project-level `UserPromptSubmit`、`SessionStart(startup / compact)`、`PreCompact`、`PermissionRequest`、`command / url / prompt / agent / mcp` hook executor、`SkillTool` prompt/workflow/agent execution、skill frontmatter hooks、agent frontmatter hooks、plugin hooks(runtime `SessionStart / UserPromptSubmit / PreCompact / PermissionRequest` current surfaces) - - `current gap`:`SessionStart(resume)`、`Stop / SessionEnd` 等更多 runtime event bootstrap、`PermissionRequest` richer decision surface(`updatedInput / updatedPermissions / interrupt`)、plugin hook 与 upstream managed policy / builtin plugin 加载链的完全同构仍未补齐 - - `explicitly unsupported gap`:`hook.if`、`asyncRewake`、非 `bash` shell、`allowedEnvVars` - - `compat / deprecated / dead`:无新增;本轮没有为了 `PermissionRequest` 再发明第二套 approval runtime,也没有把旧 callback 边界重新接回主链 -- 这一步服务路线图主目标的关系是:把参考运行时图里“工具审批前也会经过 project/plugin/session PermissionRequest hooks”这条 extension 主链补进 Lime current,避免扩展体系继续停在“PreCompact 已 current,但权限审批仍完全绕过 hooks”的断层状态。 -- 已执行定向校验: - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib decide_runtime_permission_request_project_hooks_for_session_should_` 通过(`2 passed`) - - `cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" handle_approval_tool_requests_should_auto_ --lib` 通过(`2 passed`;仅剩工作区既有 warning:`task_list_tools.rs / worktree_tools.rs` 的 `SessionManager` 未使用) - - `cargo check --manifest-path "src-tauri/Cargo.toml" -p lime --tests` 通过(增量复查已确认本轮新增 warning 已收干净) -- 下一刀最值得继续推进的是: - - 继续保持 `SessionStart(resume)` 为显式 gap,不再来回犹豫 - - 优先核定 `Stop / SessionEnd` 哪一条在 Lime 里已有单一 current 宿主入口,再补下一类 lifecycle event bootstrap - - 如果要继续追平 `PermissionRequest` 语义,再单独补 `updatedInput / updatedPermissions / interrupt`,不要把这三种 richer decision 混进现有最小 current allow/deny 路径里硬拼 - - 如果要追平 plugin loader 语义,再单独评估 managed policy / builtin plugin hooks 是否也要并入当前 Rust runtime,而不是把旧 installer 重新接回来 - -### 继续推进(CCD-008 / Stop hooks current) - -- 继续对照本地参考运行时: - - `"/Users/coso/Documents/dev/js/claudecode/src/query.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/query/stopHooks.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/entrypoints/sdk/coreSchemas.ts"` - 后确认这一步最该补的是 `Stop`,而且只能接在 Lime 当前真正的 turn 正常收尾宿主上;因此本轮明确把事实源收口到 [`runtime_turn.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 的 `finalize_runtime_turn_result(...) -> runtime_project_hooks -> HookRegistry` 当前主链,没有把 `agent_runtime_interrupt_turn(...)`、session delete、queue resume 或前端 clear 动作硬包装成假 `Stop / SessionEnd` 入口。 -- [`hooks/types.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/types.rs) 现已把上游 `Stop` 最小输入面补回当前 `HookInput`: - - 新增 `stop_hook_active` - - 新增 `last_assistant_message` - - 这两个字段会继续沿现有 command stdin / url payload JSON 透传,不再要求 hook 自己回读 transcript 才能拿到最后一条 assistant 文本 -- [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 现已补齐 `Stop` 的 per-workspace runtime helper: - - 新增 `run_runtime_stop_project_hooks_with_runtime(...)` - - 新增 `run_runtime_stop_project_hooks_for_session_with_runtime(...)` - - 测试侧补了 `run_runtime_stop_project_hooks(...) / ...for_session(...)`,继续复用 `resolve_runtime_project_hook_workspace_root(...)` 这条唯一 `workspace_id -> workspace_root / working_dir fallback` 事实源,不为 `Stop` 再散一套项目根目录猜测逻辑 - - hook 结果继续统一走 `log_runtime_project_hook_results("Stop", ...)`,本轮只先收通 current 宿主执行,不把 `preventContinuation` 假装映射成 turn 失败或中断 -- [`runtime_turn.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 现已把 `Stop` 真正接到 turn 正常结束宿主: - - `execute_runtime_stream_attempt(...)` 现在会把最终 `assistant_output` 返回给收尾阶段 - - `finalize_runtime_turn_result(...)` 在成功分支里、发出 `FinalDone` 之前,先运行 project/plugin/session 的 `Stop` - - 失败分支仍只发 `Error`,不会把 provider error / interrupt / timeout 误记成 `Stop` - - `stop_hook_active` 当前固定传 `false`;`last_assistant_message` 直接取本回合真实 `assistant_output` -- 这一步同时把“当前不该假装完成什么”钉得更清楚: - - upstream `Stop` 不是用户手工停止,也不是 `SessionEnd` - - `SessionStart(resume)` 仍继续保留为 gap,本轮没有回头把 queue resume 伪装成 lifecycle resume - - `SessionEnd` 仍未接;`clear / shutdown / delete session` 也没有被硬并到 `Stop` - - upstream `Stop` richer 行为里的 `preventContinuation / stopReason` 当前仍未映射到 Lime runtime turn policy;本轮只先补 current 执行宿主与真实输入面,不做假兼容 -- 新增定向测试已经把 `Stop` current 路径锚住: - - `Stop` hook 会收到真实 `event / session_id / stop_hook_active / last_assistant_message` - - `runtime_turn` 原有 `UserPromptSubmit` 定向测试继续通过,证明这次签名改动没有把既有 turn hook 主链带坏 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:`TaskCreated / TaskCompleted` hooks、project-level `UserPromptSubmit`、`SessionStart(startup / compact)`、`PreCompact`、`PermissionRequest`、`Stop`、`command / url / prompt / agent / mcp` hook executor、`SkillTool` prompt/workflow/agent execution、skill frontmatter hooks、agent frontmatter hooks、plugin hooks(runtime `SessionStart / UserPromptSubmit / PreCompact / PermissionRequest / Stop` current surfaces) - - `current gap`:`SessionStart(resume)`、`SessionEnd`、`Stop` richer continuation policy、`PermissionRequest` richer decision surface(`updatedInput / updatedPermissions / interrupt`)、plugin hook 与 upstream managed policy / builtin plugin 加载链的完全同构仍未补齐 - - `explicitly unsupported gap`:`hook.if`、`asyncRewake`、非 `bash` shell、`allowedEnvVars` - - `compat / deprecated / dead`:无新增;本轮没有为了 `Stop` 再发明第二套 turn-end lifecycle runtime,也没有把 interrupt/delete path 接回 current -- 这一步服务路线图主目标的关系是:把参考运行时图里“每个 query turn 正常结束后会经过 Stop hooks”这条 lifecycle extension 主链补进 Lime current,避免扩展体系继续停在“PermissionRequest 已 current,但 turn 正常收尾仍完全绕过 Stop hooks”的断层状态。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/hooks/types.rs" "src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs" "src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs"` 通过 - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib run_runtime_stop_project_hooks_for_session_should_pass_last_assistant_message_and_flag -- --nocapture` 通过(`1 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib enforce_runtime_turn_user_prompt_submit_hooks_should_ -- --nocapture` 通过(`2 passed`) - - `cargo check --manifest-path "src-tauri/Cargo.toml" -p lime --tests` 通过 -- 下一刀最值得继续推进的是: - - 继续保持 `SessionStart(resume)` 为显式 gap,不再来回犹豫 - - 优先核定 `SessionEnd` 在 Lime 里是否存在单一 current 宿主入口,再继续补 lifecycle event bootstrap - - 如果要继续追平 `Stop` 语义,再单独设计 `preventContinuation / stopReason` 应该如何落到 Lime 的 auto-continue / turn policy,而不是把它硬塞成通用错误返回 - -### 继续推进(resume current surface / runtime root 收口) - -- 把 Agent Chat 主工作台的 Claude Code 风格 resume 入口接回 current 对话主链: - - `ChatSidebar` 顶部入口当前已改成“继续最近会话”,并显式提示“上下文已保留”。 - - `EmptyState` 当前也已补出最近会话恢复入口,恢复动作继续复用现有 `handleResumeSidebarTask(...)`,没有再扩第二套 resume 执行路径。 - - `AgentChatWorkspace / WorkspaceConversationScene / useWorkspaceConversationSceneRuntime` 当前已贯通最近会话 topic 的透传与展示,避免 resume 入口只停留在静态文案层。 -- 继续把 runtime 主链收回单一事实源,修掉全量 Rust 校验里最后一组 `Aster path root` 初始化分叉: - - `lime_agent` 的 [aster_runtime_support.rs](../../src-tauri/crates/agent/src/aster_runtime_support.rs) 现在会优先认领上游 `aster` 已初始化的 shared runtime root,再决定是否回退到 Lime 自己的 app path。 - - `aster` 的 [config/paths.rs](../../src-tauri/crates/aster-rust/crates/aster/src/config/paths.rs) 当前补了 `initialized_path_root()` 只读访问器,避免 Lime wrapper 在上游已经锁定 root 后又尝试走默认目录,导致 `OnceLock + PATH_ROOT_OVERRIDE` 分叉。 - - 这一步之后,之前只在全量 `cargo test` 下暴露的 `test_list_current_surface_tool_definitions_includes_agent_tool` / `test_tool_search_bridge_includes_current_surface_agent_tool` 已恢复通过,`ToolSearch current surface` 也不再因为 runtime root 初始化顺序而假失败。 -- 本轮校验结果: - - 前端 resume 定向回归已通过:`agentChatShared / ChatSidebar / EmptyState` - - `cargo test --manifest-path "src-tauri/Cargo.toml"` 已全绿 - - `npm run verify:local` 已通过,包含 smart Vitest、全量 Rust 与 `verify:gui-smoke` -- 这一步服务主线目标的关系是: - - 产品层把“继续最近会话”真正放回 current 对话入口,而不是继续依赖旧侧栏语义; - - 运行时层把 Lime wrapper 与上游 shared runtime root 收回到同一事实源,避免 queue / resume / tool surface 校验继续被初始化顺序噪声干扰。 - -## 2026-04-21 - -### 继续推进(CCD-008 / SessionEnd hooks current) - -- 继续对照本地参考运行时: - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/hooks.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/commands/clear/conversation.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/screens/REPL.tsx"` - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/gracefulShutdown.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/entrypoints/sdk/coreSchemas.ts"` - 后确认这一步最该补的是 `SessionEnd` 的真实 session lifecycle 宿主,而且只能接在 Lime 当前唯一诚实的 session 结束入口上;因此本轮明确把事实源收口到 [`action_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/action_runtime.rs) 的 `agent_runtime_delete_session(...) -> runtime_project_hooks -> HookRegistry -> session_runtime` 当前主链,没有把 `agent_runtime_resume_thread(...)`、`agent_runtime_interrupt_turn(...)`、compact 或前端 `/clear` 动作硬包装成假 `SessionEnd` 入口。 -- [`executor.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/hooks/executor.rs) 现已补齐 `SessionEnd` 的 registry-aware current 执行入口: - - 新增 `run_session_end_hooks_with_registry(...)` - - 新增 `run_session_end_hooks_with_registry_and_context(...)` - - `SessionEnd` 执行完成后会继续 `clear_session_hooks(session_id)`,避免 session 级 hook 注册在生命周期结束后残留成脏状态 -- [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 现已补齐 `SessionEnd` 的 per-workspace runtime helper: - - 新增 `run_runtime_session_end_project_hooks(...)` - - 新增 `run_runtime_session_end_project_hooks_with_runtime(...)` - - 新增 `run_runtime_session_end_project_hooks_for_session(...)` - - 新增 `run_runtime_session_end_project_hooks_for_session_with_runtime(...)` - - helper 继续复用 `resolve_runtime_project_hook_workspace_root(...)` 这条唯一 `workspace_id -> workspace_root / working_dir fallback` 事实源,不为 `SessionEnd` 再散一套项目根目录猜测逻辑 -- [`action_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/action_runtime.rs) 与 [`session_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/session_runtime.rs) 现已把 `SessionEnd` 真正接到 Lime 当前 session 删除宿主: - - `agent_runtime_delete_session(...)` 会先 `cancel session` - - 再 `clear runtime queue` - - 然后运行 project/plugin/session 的 `SessionEnd` - - 最后才真正删除 session - - `SessionEndReason` 当前固定落为 `other`;本轮没有把删除会话伪装成 upstream 的 `clear / prompt_input_exit / logout` - - 原先零引用的 `delete_runtime_session_internal(...)` 已删除,只保留 `delete_runtime_session_internal_with_runtime(...)` 当前主路径,避免继续保留无 runtime hook 的旧 delete 旁路 -- 这一步同时也把“当前不该假装完成什么”钉得更清楚: - - `SessionStart(resume)` 仍继续保留为 gap,本轮没有回头把 queue resume 伪装成 lifecycle resume - - `SessionEnd` 当前只接住 `agent_runtime_delete_session -> SessionEnd(other)`;`clear / prompt_input_exit / logout` 仍没有 Lime 当前真实宿主 - - `agent_runtime_interrupt_turn(...)` 仍不是 `Stop`,也不是 `SessionEnd` - - compact 仍只属于 `SessionStart(compact)` / `PreCompact`,本轮没有把它并进 session 结束语义 -- 新增定向测试已经把 `SessionEnd` current 路径锚住: - - `SessionEnd` hook 会收到真实 `event / session_id / reason=other` - - session hook 会在 `SessionEnd` 后被真实清掉,不会残留到后续 session 生命周期 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:`TaskCreated / TaskCompleted` hooks、project-level `UserPromptSubmit`、`SessionStart(startup / compact)`、`PreCompact`、`PermissionRequest`、`Stop`、`SessionEnd(other via delete_session)`、`command / url / prompt / agent / mcp` hook executor、`SkillTool` prompt/workflow/agent execution、skill frontmatter hooks、agent frontmatter hooks、plugin hooks(runtime `SessionStart / UserPromptSubmit / PreCompact / PermissionRequest / Stop / SessionEnd` current surfaces) - - `current gap`:`SessionStart(resume)`、`SessionEnd(clear / prompt_input_exit / logout)`、`Stop` richer continuation policy、`PermissionRequest` richer decision surface(`updatedInput / updatedPermissions / interrupt`)、plugin hook 与 upstream managed policy / builtin plugin 加载链的完全同构仍未补齐 - - `explicitly unsupported gap`:`hook.if`、`asyncRewake`、非 `bash` shell、`allowedEnvVars` - - `compat / deprecated / dead`:无新增;本轮没有为了 `SessionEnd` 再发明第二套 session lifecycle runtime,也没有把 interrupt / resume / clear path 接回 current -- 这一步服务路线图主目标的关系是:把参考运行时图里“session 生命周期结束时也会经过 hooks”这条 extension 主链补进 Lime current,避免扩展体系继续停在“`Stop` 已 current,但 session delete 仍完全绕过 `SessionEnd` hooks”的断层状态,同时继续把没有真实宿主的 lifecycle 差异显式保留为 gap,而不是做假兼容。 -- 已执行定向校验: - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib run_runtime_session_end_project_hooks_for_session_should_pass_reason_and_clear_session_hooks -- --nocapture` 通过(`1 passed`) - - `cargo check --manifest-path "src-tauri/Cargo.toml" -p lime --tests` 通过 -- 下一刀最值得继续推进的是: - - 继续保持 `SessionStart(resume)` 为显式 gap,不再来回犹豫 - - 优先核定 Lime 当前是否存在真实 `SessionEnd(clear / prompt_input_exit / logout)` 宿主;若没有,就明确保留为产品差异,不做假映射 - - 如果要继续追平 `Stop / PermissionRequest` 语义,再分别单独补 `preventContinuation / stopReason` 与 `updatedInput / updatedPermissions / interrupt`,不要把 richer 行为混进现有最小 current 路径里硬拼 - -### 继续推进(CCD-008 / SessionEnd lifecycle host audit) - -- 继续对照本地参考运行时: - - `"/Users/coso/Documents/dev/js/claudecode/src/commands/clear/conversation.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/gracefulShutdown.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/screens/REPL.tsx"` - - `"/Users/coso/Documents/dev/js/claudecode/src/entrypoints/sdk/coreSchemas.ts"` - 后确认 upstream 的 `SessionEnd` 宿主矩阵并不是抽象枚举,而是四类真实 lifecycle: - - `/clear -> executeSessionEndHooks("clear")` - - `REPL resume -> executeSessionEndHooks("resume")` - - `gracefulShutdown -> executeSessionEndHooks("prompt_input_exit" / "logout" / "other")` - - schema 侧还显式保留 `bypass_permissions_disabled` -- 继续排查 Lime current 宿主后,确认这几类入口目前都不存在等价实现: - - 仓内没有 Claude Code 那种 `clearConversation(...) + regenerateSessionId(...)` 会话清空并重生的 runtime 生命周期;当前前端删除 topic 只是 [`useAgentSession.ts`](../../src/components/agent/chat/hooks/useAgentSession.ts) 在 `runtime.deleteSession(...)` 后清本地状态,不是 session clear host。 - - 仓内没有 `gracefulShutdown(...)` / `prompt_input_exit` 这类 runtime session 退出宿主;当前 `logout` 相关代码要么是 [`external_tools_cmd.rs`](../../src-tauri/src/commands/external_tools_cmd.rs) 返回 `"codex logout"` 字符串,要么是 [`oemCloudControlPlane.ts`](../../src/lib/api/oemCloudControlPlane.ts) 的 OEM control plane 登出接口,都不是 Aster runtime session lifecycle。 - - 当前公开的 [`agent_runtime_resume_thread`](../../src-tauri/src/commands/aster_agent_cmd/command_api/runtime_api.rs) 仍只是恢复排队线程执行,不是 upstream 那种 session 切换前后的 `SessionEnd(resume) / SessionStart(resume)` 宿主。 -- 因此这一轮把 `SessionEnd` 剩余差距进一步钉成显式结论: - - `current`:只有 `agent_runtime_delete_session -> SessionEnd(other)` - - `current gap`:`SessionEnd(resume / clear / prompt_input_exit / logout)` 与 `SessionStart(resume)` - - `product difference until new host exists`:`bypass_permissions_disabled` - - `not a host`:`open_codex_cli_logout`、OEM cloud `logoutClient(...)`、topic 删除后的前端本地清空 -- 这一步服务路线图主目标的关系是:把 `SessionEnd` 剩余 gap 从“还要继续找找看”推进成“已审计确认 Lime 当前没有这些宿主”,后续除非新增真实 current lifecycle host,否则不再围绕 `clear / resume / logout / prompt_input_exit` 反复做假映射判断。 -- 下一刀最值得继续推进的是: - - 继续保持 `SessionStart(resume)` 与 `SessionEnd(resume / clear / prompt_input_exit / logout)` 为显式 gap,不再来回犹豫 - - 后续只有在 Lime 真新增对应 lifecycle host 时,才重新打开这组对齐项 - - 当前主线应回到 richer 语义差距:`Stop` 的 `preventContinuation / stopReason` 与 `PermissionRequest` 的 `updatedInput / updatedPermissions / interrupt` - -### 继续推进(CCD-008 / PermissionRequest updatedInput current) - -- 继续对照本地参考运行时: - - `"/Users/coso/Documents/dev/js/claudecode/src/types/hooks.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/cli/structuredIO.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/services/tools/toolExecution.ts"` - 后确认 upstream 的 `PermissionRequest.updatedInput` 不是展示字段,而是会真实改写后续工具执行输入;因此这一步继续只沿 `runtime_project_hooks -> PermissionRequestHookDecision -> handle_approval_tool_requests(...)` 当前主链推进,不额外发明第二套 permission rewrite runtime。 -- [`types.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/agents/types.rs) 现已把 `PermissionRequestHookDecision::Allow` 收成带载荷的 current 语义: - - `Allow { updated_input: Option> }` - - `updated_input` 只接受 object 形状,与 Lime 当前 `CallToolRequestParam.arguments` 和 upstream `Record` 保持同构,不再用宽泛 `Value` 做伪兼容 -- [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 现已把 `updatedInput` 接进 PermissionRequest hook 解析: - - `{"decision":"allow","updatedInput":{...}}` 会被解析成 `PermissionRequestHookDecision::Allow { updated_input: Some(...) }` - - 若 `updatedInput` 不是 object,会直接 warning 并忽略该 decision,回退到后续 hook / 人工审批;不会偷偷拿原始输入继续 auto-allow - - 现有 `allow`、`deny(message)` 路径保持不变,没有为了迁就 richer 语义再扩 compat 协议 -- [`tool_execution.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/agents/tool_execution.rs) 现已把改写后的输入真正送入工具执行: - - 新增 `apply_permission_request_updated_input(...)` - - `handle_approval_tool_requests(...)` 的 auto-allow 分支会先改写 `CallToolRequestParam.arguments` - - 然后再 `dispatch_tool_call(...)`,确保 hook 返回的 `updatedInput` 真正进入工具,而不是只在 decision 对象里“看起来支持” -- 新增定向测试已经把这条 richer current 路径锚住: - - `runtime_project_hooks` 侧新增 `allow + updatedInput` 解析测试 - - `tool_execution` 侧新增 end-to-end 测试,确认 auto-allow 时工具实际收到改写后的参数,而不是原始 `README.md` -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:`TaskCreated / TaskCompleted` hooks、project-level `UserPromptSubmit`、`SessionStart(startup / compact)`、`PreCompact`、`PermissionRequest`(含 `allow + updatedInput`)、`Stop`、`SessionEnd(other via delete_session)`、`command / url / prompt / agent / mcp` hook executor、`SkillTool` prompt/workflow/agent execution、skill frontmatter hooks、agent frontmatter hooks、plugin hooks(runtime `SessionStart / UserPromptSubmit / PreCompact / PermissionRequest / Stop / SessionEnd` current surfaces) - - `current gap`:`SessionStart(resume)`、`SessionEnd(clear / prompt_input_exit / logout)`、`Stop` richer continuation policy、`PermissionRequest` richer decision surface(`updatedPermissions / interrupt`)、plugin hook 与 upstream managed policy / builtin plugin 加载链的完全同构仍未补齐 - - `explicitly unsupported gap`:`hook.if`、`asyncRewake`、非 `bash` shell、`allowedEnvVars` - - `compat / deprecated / dead`:无新增;本轮没有为了 `updatedInput` 再发明新的 approval 协议,也没有把宽泛 JSON 重写偷偷塞回当前主链 -- 这一步服务路线图主目标的关系是:把参考运行时图里 `PermissionRequest` 剩余最贴近 current 的 richer 语义推进到 Lime 当前主链,避免扩展体系继续停在“allow / deny 已 current,但 hook 仍无法真实改写工具输入”的半成品状态。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/agents/types.rs" "src-tauri/crates/aster-rust/crates/aster/src/agents/tool_execution.rs" "src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs"` 通过 - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib decide_runtime_permission_request_project_hooks_for_session_should_ -- --nocapture` 通过(`3 passed`) - - `cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" handle_approval_tool_requests_should_ --lib -- --nocapture` 通过(`3 passed`;仅剩工作区既有 warning:`task_list_tools.rs / worktree_tools.rs` 的 `SessionManager` 未使用) - - `cargo check --manifest-path "src-tauri/Cargo.toml" -p lime --tests` 通过 -- 下一刀最值得继续推进的是: - - 继续保持 `SessionStart(resume)` 与 `SessionEnd(resume / clear / prompt_input_exit / logout)` 为显式 gap,不再来回犹豫 - - 若继续追 `PermissionRequest` richer 语义,只能在找到真实权限事实源与 interrupt 宿主后,再分别推进 `updatedPermissions` 与 `interrupt` - - 当前更稳的一刀是回到 `Stop` 的 `preventContinuation / stopReason` 审计,先确认 Lime 是否存在同样诚实的 continuation gate,再决定是否进入 current - -### 继续推进(CCD-008 / Stop continuation gate audit) - -- 继续对照本地参考运行时: - - `"/Users/coso/Documents/dev/js/claudecode/src/query/stopHooks.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/query.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/types/hooks.ts"` - 后确认 upstream 的 `Stop.preventContinuation / stopReason` 不是展示字段,而是 query loop 里的真实 continuation gate: - - `handleStopHooks(...)` 会把 `preventContinuation` 返回给 query loop - - query loop 会据此走 `stop_hook_prevented / hook_stopped`,阻断后续 continuation - - `stopReason` 只是在这个 gate 生效时给用户看的解释,不是独立功能 -- 继续排查 Lime current 宿主后,确认本地目前没有与之等价的 continuation gate: - - [`runtime_turn.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 的 [`finalize_runtime_turn_result(...)`](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs#L3616) 只会在 turn 成功后 fire-and-forget 运行 `Stop` hooks,然后继续发送 `FinalDone`;当前不会回收任何 hook continuation 决策。 - - [`prompt_context.rs`](../../src-tauri/src/commands/aster_agent_cmd/prompt_context.rs#L3) 与 [`dto.rs`](../../src-tauri/src/commands/aster_agent_cmd/dto.rs#L1834) 里的 `auto_continue` 只是“文稿续写”提示词增强,不是 upstream 那种 query-loop continuation state machine。 - - 因此 Lime 当前只有 `Stop event host`,没有 `Stop continuation gate host`;不能把 `auto_continue.enabled`、turn 正常收尾、或任何现有 runtime flag 硬映射成 `preventContinuation` -- 为了避免继续制造假对齐,这一轮补了最小守卫而不是伪实现: - - [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 新增 `parse_runtime_stop_hook_continuation_request(...)` - - 当 `Stop` hook 输出 upstream 形状的 `{"continue":false,"stopReason":"..."}` 时,Lime 会显式 warning: - 当前 runtime 识别到了这个 richer 请求,但仍无与 Claude Code 等价的 continuation gate,本次不会阻断 turn 收尾 - - [`runtime_turn.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 现已把这条 warning 从后台 tracing log 提升为前台 `RuntimeAgentEvent::Warning`,并写入 timeline;因此 gap 不再只是“开发者看日志才知道”,而是 turn 收尾前用户也能看到这是显式 unsupported - - 这样 gap 从“静默忽略”收口成“显式 unsupported”,但没有为了迁就差异去伪造一套 continuation 行为 -- 新增定向测试已经把这层 guardrail 锚住: - - `run_runtime_stop_project_hooks_for_session_should_detect_unsupported_continue_false_request` - - 覆盖 `continue:false + stopReason` 的解析与统一 warning message 返回路径,确保后续不会再把这种 richer 请求默默当成功输出吞掉 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:`TaskCreated / TaskCompleted` hooks、project-level `UserPromptSubmit`、`SessionStart(startup / compact)`、`PreCompact`、`PermissionRequest`(含 `allow + updatedInput`)、`Stop` event host、`SessionEnd(other via delete_session)`、`command / url / prompt / agent / mcp` hook executor、`SkillTool` prompt/workflow/agent execution、skill frontmatter hooks、agent frontmatter hooks、plugin hooks(runtime `SessionStart / UserPromptSubmit / PreCompact / PermissionRequest / Stop / SessionEnd` current surfaces) - - `current gap`:`SessionStart(resume)`、`SessionEnd(clear / prompt_input_exit / logout)`、`Stop` richer continuation policy(`preventContinuation / stopReason` 仍无 honest host)、`PermissionRequest.updatedPermissions`、plugin hook 与 upstream managed policy / builtin plugin 加载链的完全同构仍未补齐 - - `explicitly unsupported gap`:`hook.if`、`asyncRewake`、非 `bash` shell、`allowedEnvVars` - - `compat / deprecated / dead`:无新增;本轮没有为了 `Stop` richer 语义再发明第二套 continuation runtime,也没有把 `auto_continue` 或 turn 正常结束硬包装成 query-loop gate -- 这一步服务路线图主目标的关系是:把 `Stop` richer gap 从“也许还能找个现有 flag 复用”推进成“已审计确认 Lime 当前没有等价 continuation gate”,并用代码守卫封住静默假对齐,避免后续继续把 `auto_continue` 或普通 turn 收尾误判成 upstream `preventContinuation`。 -- 已执行定向校验: - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib run_runtime_stop_project_hooks_for_session_should_ -- --nocapture` - - `cargo check --manifest-path "src-tauri/Cargo.toml" -p lime --tests` -- 下一刀最值得继续推进的是: - - 继续保持 `Stop.preventContinuation / stopReason` 为显式 gap,除非 Lime 新增真实 continuation gate,否则不再围绕现有 `auto_continue` / turn 收尾反复犹豫 - - 若继续追 richer 语义,更值得回到 `PermissionRequest.updatedPermissions / interrupt` 的真实宿主审计 - -### 继续推进(CCD-008 / PermissionRequest interrupt current) - -- 继续对照本地参考运行时: - - `"/Users/coso/Documents/dev/js/claudecode/src/types/hooks.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/hooks/toolPermission/PermissionContext.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/cli/structuredIO.ts"` - 后确认 upstream 的 `PermissionRequest.deny + interrupt` 不是普通提示字段,而是会直接触发当前 turn 的中断: - - hook 返回 `{"decision":"deny","message":"...","interrupt":true}` 后,会走 `toolUseContext.abortController.abort()` - - deny message 仍会保留给当前工具拒绝结果,但 query / tool-use 主链会把这次 turn 当作被中断处理 -- 继续审计 Lime current 主链后,确认本地其实已经存在与之诚实对应的 interrupt 宿主: - - [`runtime_turn.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 的 `with_runtime_turn_session_scope(...)` 会为当前 session 建立单一 `CancellationToken` - - [`agent.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/agents/agent.rs) 的 `reply(...) / reply_internal(...)`、tool stream 合并循环与 turn finalize 都会持续检查这个 token;一旦被 cancel,turn 会按 `Aborted` 收尾 - - 因此 `interrupt` 不需要伪造第二套 runtime;只要沿当前 `PermissionRequest hook -> session cancel token` 主链接上,就是 honest host -- 这一轮据此把 `interrupt` 正式接进 Lime current,而没有继续把它误判成 gap: - - [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 新增 `RuntimePermissionRequestHookRequest` - - `parse_runtime_permission_request_hook_request(...)` 现在会解析 deny 分支里的 `interrupt:boolean` - - `decide_runtime_permission_request_project_hooks_with_runtime(...)` 在 production current path 上发现 `interrupt:true` 后,会直接调用 `AsterAgentState.cancel_session(session_id)`,并记录 `source=hook` 的 interrupt marker - - 这样 `PermissionRequest` deny 结果仍保持当前工具级拒绝语义,但 turn 本身也会像 upstream 一样进入中断收尾,而不是只回一条 deny message 后继续跑 -- 同时继续把 `updatedPermissions` 诚实保留为 gap,而不是硬拼半套权限映射: - - `PermissionRequest` allow 分支若带 `updatedPermissions`,Lime 当前不再“继续执行 allow 但忽略更新”,而是 fail-closed 回退到原生审批流: - - 不执行 hook allow - - 不应用 `updatedInput` - - 不应用 `updatedPermissions` - - 这样做是为了避免假对齐:upstream 的 `updatedPermissions.destination="session"` 会直接写回 `ToolPermissionContext`,既影响后续 turn,也会立刻影响当前 turn 后续工具决策;如果 Lime 只放行当前工具、却不真正改写权限事实源,会把 hook 作者带进错误语义 - - 继续往本地权限设施下钻后也确认,这不是“仓库里完全没权限代码”,而是“现有权限代码没有接在当前 approval 主链上,也没有 session 级权限事实源”: - - [`tool_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/tool_runtime.rs) 每次 turn 都会重建 `ToolPermissionManager::new(None)` 并重新挂到 `ToolRegistry`;这套 session permission 只是本 turn 内存对象 - - [`session_execution_runtime.rs`](../../src-tauri/crates/agent/src/session_execution_runtime.rs) 当前持久化到 session extension data 的只有 `recent_access_mode / recent_preferences / recent_team_selection`,没有 permission rules、额外目录或 upstream `defaultMode` - - [`runtime_store.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/session/runtime_store.rs) 的 `SessionRuntimeSnapshot` 只聚合 thread / turn runtime,也没有 session 权限规则快照 - - [`tool_inspection.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/tool_inspection.rs) 里的 `update_permission_manager(...)` 只会把用户点击 `AlwaysAllow` 收成按工具名写入的 legacy `PermissionManager` - - [`permission/permission_inspector.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/permission/permission_inspector.rs) 的 `IntegratedPermissionManager` 只是可选能力,当前 `PermissionRequest` hook path 并不会在 allow 分支里消费 hook 返回的 permission update payload - - [`permission/manager.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/permission/manager.rs) 虽然存在更宽的 `ToolPermissionUpdate / update_permission(...)`,但当前仓库没有把这套更新器接到 `runtime_project_hooks -> PermissionRequest -> tool_execution` 这条 current path 上 - - 也就是说,这一轮只把 `interrupt` 从误判 gap 里收回 `current`;`updatedPermissions` 仍保持“显式 unsupported 的 current gap”,并且当前行为已经收紧为“显式回退审批流”,不再半执行 hook allow -- 新增定向测试已经把这条边界钉住: - - `decide_runtime_permission_request_project_hooks_should_fallback_to_native_approval_when_allow_requests_updated_permissions` - - `parse_runtime_permission_request_hook_request_should_detect_updated_permissions_request` - - `decide_runtime_permission_request_project_hooks_with_runtime_should_interrupt_session_on_deny_interrupt_true` -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:`TaskCreated / TaskCompleted` hooks、project-level `UserPromptSubmit`、`SessionStart(startup / compact)`、`PreCompact`、`PermissionRequest`(含 `allow + updatedInput` 与 `deny + interrupt`)、`Stop` event host、`SessionEnd(other via delete_session)`、`command / url / prompt / agent / mcp` hook executor、`SkillTool` prompt/workflow/agent execution、skill frontmatter hooks、agent frontmatter hooks、plugin hooks(runtime `SessionStart / UserPromptSubmit / PreCompact / PermissionRequest / Stop / SessionEnd` current surfaces) - - `current gap`:`SessionStart(resume)`、`SessionEnd(clear / prompt_input_exit / logout)`、`Stop` richer continuation policy(`preventContinuation / stopReason` 仍无 honest host)、`PermissionRequest.updatedPermissions`、plugin hook 与 upstream managed policy / builtin plugin 加载链的完全同构仍未补齐 - - `explicitly unsupported gap`:`hook.if`、`asyncRewake`、非 `bash` shell、`allowedEnvVars` - - `compat / deprecated / dead`:无新增;本轮没有为了 `updatedPermissions` 再造一层 permission compat,也没有把用户 API `agent_runtime_interrupt_turn` 包一层假 hook host,而是直接复用当前 turn cancel token -- 这一步服务路线图主目标的关系是:把 `PermissionRequest` richer 语义里原本混在一起的两部分彻底拆开,只把已经存在 honest host 的 `interrupt` 收进 current,把还没有真实权限事实源的 `updatedPermissions` 留在显式 gap,避免后续再围绕“这俩是不是都没法做”产生误判。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs"` 通过 - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib decide_runtime_permission_request_project_hooks_ -- --nocapture` 通过(`5 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib parse_runtime_permission_request_hook_request_should_detect_updated_permissions_request -- --nocapture` 通过(`1 passed`) - - `cargo check --manifest-path "src-tauri/Cargo.toml" -p lime --tests` 通过 -- 下一刀最值得继续推进的是: - - 继续保持 `PermissionRequest.updatedPermissions` 为显式 gap,除非 Lime 先收敛出真实权限事实源,否则不做半套规则映射 - - `Stop.preventContinuation / stopReason` 仍应保持 gap,不要因为 `interrupt` 已 current 就误判 `Stop` 也有 continuation gate - - 若继续追平 upstream extension 语义,更值得回到 managed plugin policy / builtin plugin hooks 的完全同构审计 - -### 继续推进(CCD-008 / Session lifecycle unsupported host guard) - -- 继续对照本地参考运行时: - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/hooks.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/sessionStart.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/commands/clear/conversation.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/screens/REPL.tsx"` - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/gracefulShutdown.ts"` - 后确认 upstream 的 session lifecycle 比 Lime 当前宿主面更宽: - - `SessionStart` 的 source 真实包含 `startup / resume / clear / compact` - - `SessionEnd` 的 reason 真实包含 `clear / resume / logout / prompt_input_exit / other / bypass_permissions_disabled` -- 继续审计 Lime current 宿主后,确认本地真正有调用点的只有: - - [`session_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/session_runtime.rs) 里的 `create_runtime_session_internal_with_optional_runtime(...) -> SessionSource::Startup` - - [`runtime_turn.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 的压缩入口 -> `SessionSource::Compact` - - [`session_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/session_runtime.rs) 的 `delete_runtime_session_internal_with_runtime(...) -> SessionEndReason::Other` - - [`command_api/runtime_api.rs`](../../src-tauri/src/commands/aster_agent_cmd/command_api/runtime_api.rs) 的 `agent_runtime_resume_thread(...)` 只是恢复 runtime queue,不是 upstream `/resume` 那种“旧 session 结束 + 新 query session start” - - [`execute_commands.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/agents/execute_commands.rs) 的 `/clear` 只是清空 conversation,也还没有接成 upstream `/clear` 那种 `SessionEnd(clear) + SessionStart(clear)` lifecycle host -- 为了避免后续有人把这些 enum 误当成“已经有 current host”,这一轮继续补了显式 unsupported guard,而不是偷接假宿主: - - [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 新增 `build_runtime_session_start_unsupported_warning_message(...)` - - 对 `SessionStart.resume / clear`,当前 runtime 会显式 warning 并直接跳过 hook 执行;不会因为 enum 已存在就默认放行 - - 同文件新增 `build_runtime_session_end_unsupported_warning_message(...)` - - 对 `SessionEnd.clear / logout / prompt_input_exit`,当前 runtime 也会显式 warning 并直接跳过 hook 执行;当前唯一允许的 `SessionEnd` current host 仍只有 `delete_session -> other` - - 这样做的目的不是“删掉未来能力”,而是先把 current 宿主边界钉死,防止 `resume_thread`、`/clear` 或其他局部动作被误包成完整 lifecycle hook host -- 新增定向测试已经把这层 guardrail 锚住: - - `build_runtime_session_start_unsupported_warning_message_should_allow_only_current_sources` - - `run_runtime_session_start_project_hooks_for_session_should_skip_unsupported_resume_source` - - `build_runtime_session_end_unsupported_warning_message_should_allow_only_other_reason` - - `run_runtime_session_end_project_hooks_for_session_should_skip_unsupported_clear_reason` -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:`TaskCreated / TaskCompleted` hooks、project-level `UserPromptSubmit`、`SessionStart(startup / compact)`、`PreCompact`、`PermissionRequest`(含 `allow + updatedInput` 与 `deny + interrupt`)、`Stop` event host、`SessionEnd(other via delete_session)`、`command / url / prompt / agent / mcp` hook executor、`SkillTool` prompt/workflow/agent execution、skill frontmatter hooks、agent frontmatter hooks、plugin hooks(runtime `SessionStart / UserPromptSubmit / PreCompact / PermissionRequest / Stop / SessionEnd` current surfaces) - - `current gap`:`SessionStart(resume / clear)`、`SessionEnd(resume / clear / prompt_input_exit / logout / bypass_permissions_disabled)`、`Stop` richer continuation policy(`preventContinuation / stopReason` 仍无 honest host)、`PermissionRequest.updatedPermissions`、plugin hook 与 upstream managed policy / builtin plugin 加载链的完全同构仍未补齐 - - `explicitly unsupported gap`:`hook.if`、`asyncRewake`、非 `bash` shell、`allowedEnvVars` - - `compat / deprecated / dead`:无新增;本轮没有把 `agent_runtime_resume_thread`、`/clear` 或退出动作硬包装成 Session lifecycle compat host,而是先用代码守卫封住误接线 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 里最容易被 enum / schema 误导的 lifecycle 差距进一步钉死为“只有真实宿主才允许进入 current”,避免后续实现者把 queue resume、conversation clear 或任意退出路径误判成已经对齐 Claude Code 的 `SessionStart / SessionEnd` 生命周期。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs" "src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs"` 通过 - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib run_runtime_session_start_project_hooks_for_session_should_ -- --nocapture` 通过 - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib run_runtime_session_end_project_hooks_for_session_should_ -- --nocapture` 通过 - - `cargo check --manifest-path "src-tauri/Cargo.toml" -p lime --tests` 通过 -- 下一刀最值得继续推进的是: - - 若要继续追 `SessionStart(clear / resume)` 或 `SessionEnd(...)`,先找出单一、真实、产品层接受的 lifecycle host,再接 hooks;不要反过来从 enum 倒推宿主 - - 更可能直接推进主线的一刀,仍是继续审 `managed plugin policy / builtin plugin hooks` 与 upstream loader 同构差距 - -## 2026-04-21 - -### 继续推进(CCD-008 / plugin cache fact-source convergence) - -- 继续对照本地参考运行时: - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/plugins/loadPluginHooks.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/plugins/pluginLoader.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/plugins/pluginStartupCheck.ts"` - 后确认 Lime 当前更直接的漂移点不是“还没补 managed policy”,而是仓库内部已经有两套 `enabledPlugins + cache root` 解析事实源: - - [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 会合并 `home/workspace + settings/settings.local`,再只加载 marketplace cache plugin hooks - - [`skills/loader.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/skills/loader.rs) 之前却只看 `~/.claude/settings.json`,并自己重扫一遍 `~/.claude/plugins/cache` -- 这一轮先没有为了“补名字”把旧 plugin installer 或另一套 plugin system 接回 current,而是直接把 repo 内部双轨收口成单一 helper: - - 新增 [`claude_plugin_cache.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/claude_plugin_cache.rs),统一负责: - - 合并 `~/.claude/settings.json` - - 合并 `~/.claude/settings.local.json` - - 合并 `/.claude/settings.json` - - 合并 `/.claude/settings.local.json` - - 解析 `plugin@marketplace` - - 选择 `~/.claude/plugins/cache///` 下的最高版本目录 - - [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 现在直接复用这条 helper 加载 plugin hooks,不再自己维护 `enabledPlugins` merge、plugin id 解析和 cache version 排序 - - [`skills/loader.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/skills/loader.rs) 现在也复用同一 helper 加载 plugin skills,并补了一条定向测试锁住 `workspace/.claude/settings.local.json` 对 plugin skill 可见 - - `@builtin` 不再在 hook / skill 两侧各自静默掉过,而是统一标记为显式 unsupported gap:当前没有 honest host,就不伪装成 marketplace cache plugin current -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:plugin hooks 与 plugin skills 已共享 `claude_plugin_cache.rs` 单一 resolver;home/workspace settings 合并、latest-version 选择与 `@builtin` gap 口径都已收敛 - - `current gap`:upstream 的 managed plugin policy、builtin plugin hooks、plugin hot reload / prune 仍未同构;Lime 目前只对齐到 marketplace cache plugin 这一层 current 事实源 - - `compat / deprecated / dead`:无新增;这一轮没有把旧 installer、legacy plugin manager 或另一套 plugin surface 抬回 current -- 这一步服务路线图主目标的关系是:先把 Lime 仓库内部自己长出来的 plugin loader 双轨清掉,避免后续一边补 upstream gap、一边继续让 hook 与 skill 各自漂移;下一刀才值得继续追 `managed policy / builtin plugin hooks` 的真实宿主审计。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/claude_plugin_cache.rs" "src-tauri/crates/aster-rust/crates/aster/src/lib.rs" "src-tauri/crates/aster-rust/crates/aster/src/skills/loader.rs" "src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs"` 通过 - - `cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" claude_plugin_cache::tests --lib -- --nocapture` 通过(`3 passed`) - - `cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_load_skills_from_plugin_cache_uses_workspace_settings_local_and_latest_version --lib -- --nocapture` 通过(`1 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime --lib runtime_project_hooks -- --nocapture` 通过(`22 passed`) - - `cargo check --manifest-path "src-tauri/Cargo.toml" -p lime --tests` 通过 -- 下一刀最值得继续推进的是: - - 继续审 `managed plugin policy / builtin plugin hooks` 与 upstream loader 的同构差距 - - 在没有真实宿主前,继续保持 `@builtin` 为显式 gap,不把旧 plugin installer、legacy manager 或其他非 current plugin 系统重新接回主链 - -### 继续推进(CCD-008 / managed plugin policy unsupported guard) - -- 继续对照本地参考运行时后,进一步把 `managed plugin policy` 和 Lime 现有 `policySettings` 区分开: - - upstream 的 plugin loader 会把 `policySettings.enabledPlugins / strictKnownMarketplaces / blockedMarketplaces / extraKnownMarketplaces` 直接并进 `loadAllPluginsCacheOnly()` 的 discovery / merge / policy current 主链 - - Lime 当前虽然在 [`config_manager.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/config/config_manager.rs) 有 `.aster/managed_settings.yaml` 的 `policySettings` 概念,但它属于通用配置管理器,不是 Claude 风格 `.claude plugin policy` 当前宿主,也没有接进 `plugin hook / plugin skill` loader -- 因此这一轮没有把 `.aster policySettings` 硬接成 plugin managed host,而是继续做 honest guard: - - [`claude_plugin_cache.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/claude_plugin_cache.rs) 现在会额外探测 `~/.aster/managed_settings.yaml` / `~/.aster/policy.yaml` - - 如果这些文件里声明了 Claude 风格 plugin policy keys:`enabledPlugins / extraKnownMarketplaces / strictKnownMarketplaces / blockedMarketplaces` - - resolver 会统一返回显式 skipped reason,说明“检测到 managed plugin policy key,但当前 runtime 尚未接入 policySettings/plugin loader current 宿主,已忽略” - - 这样 `runtime_project_hooks` 和 `skills/loader` 复用同一 resolver 时,会共享这条 warning 口径,而不是继续静默掉过 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:marketplace cache plugin 的 hook / skill loader 继续共享单一 resolver;`@builtin` 与 managed plugin policy gap 都已有统一的代码级 skipped reason - - `current gap`:upstream 的 managed plugin policy merge、builtin plugin registry、builtin plugin hooks、plugin hot reload / prune 仍未同构;Lime 还没有可复用的 honest host - - `compat / deprecated / dead`:无新增;本轮没有把 `.aster policySettings`、旧 plugin installer 或其他 builtin/managed 相关旧面抬成 current -- 这一步服务路线图主目标的关系是:把“Lime 也有 policySettings”这种最容易诱发假对齐的点钉死成显式 unsupported guard,避免后续实现者把 `.aster managed_settings.yaml` 误当成 Claude Code 的 plugin managed policy current 宿主。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/claude_plugin_cache.rs"` 通过 - - `cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" claude_plugin_cache::tests --lib -- --nocapture` 通过(`5 passed`) - - `cargo check --manifest-path "src-tauri/Cargo.toml" -p lime --tests` 通过 -- 下一刀最值得继续推进的是: - - 继续审 upstream 的 builtin plugin registry 与 builtin plugin hooks 是否在 Lime 存在真实宿主;如果没有,就继续保持 gap,而不是把 Lime 现有 builtin skill / extension / preset 系统误抬成 plugin current - -### 继续推进(CCD-008 / builtin plugin registry host audit) - -- 继续对照本地参考运行时: - - `"/Users/coso/Documents/dev/js/claudecode/src/plugins/builtinPlugins.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/plugins/bundled/index.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/plugins/pluginLoader.ts"` - 后确认 upstream 的 `@builtin` 确实不是 marketplace cache plugin,而是单独的 builtin plugin registry 宿主: - - [`builtinPlugins.ts`](../../../../js/claudecode/src/plugins/builtinPlugins.ts) 定义了 `BuiltinPluginDefinition -> registerBuiltinPlugin() -> getBuiltinPlugins()` 这一条独立 registry - - [`pluginLoader.ts`](../../../../js/claudecode/src/utils/plugins/pluginLoader.ts) 也明确把 `marketplace` 与 `builtin` 分开装配,builtins 通过 `getBuiltinPlugins()` 合并进最终 plugin load result,而不是走 `plugins/cache` - - 但按当前参考源码,[`plugins/bundled/index.ts`](../../../../js/claudecode/src/plugins/bundled/index.ts) 仍是空 scaffold,今天还没有真正注册任何 builtin plugin -- 这意味着 Lime 当前不该做的事更明确了: - - 不能把 `@builtin` 当成另一种 cache plugin 继续沿 `~/.claude/plugins/cache` 猜目录 - - 也不能把本地现有的 builtin skill / builtin profile / builtin team preset / builtin extension config 这些“名字里带 builtin”的系统,误抬成 Claude Code 的 builtin plugin registry current 宿主 -- 因此这一轮只继续补 honest guard,不做假映射: - - [`claude_plugin_cache.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/claude_plugin_cache.rs) 里的 `@builtin` skipped reason 现在进一步收紧为: - - 当前缺少独立的 builtin plugin registry/current 宿主 - - 不能回退为 marketplace cache plugin - - 也不能回退到其他 builtin surface -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:marketplace cache plugin 的 hook / skill loader 与 managed-policy unsupported guard 已收敛到单一 resolver - - `current gap`:upstream 的 builtin plugin registry host 目前在 Lime 缺席;不过参考运行时今天也还没有实际注册的 builtin plugins,所以这条 gap 当前属于“结构已存在、活跃能力尚未落地”的 dormant gap - - `compat / deprecated / dead`:无新增;本轮没有把 builtin skill / profile / preset / extension 平移成 plugin compat -- 这一步服务路线图主目标的关系是:把 `@builtin` 的误导性空间进一步压扁,避免后续实现者因为仓库里到处有 `builtin` 命名,就误判 Lime 已经具备 Claude Code 的 builtin plugin current 宿主。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/claude_plugin_cache.rs"` 通过 - - `cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" claude_plugin_cache::tests --lib -- --nocapture` 通过(`5 passed`) - - `cargo check --manifest-path "src-tauri/Cargo.toml" -p lime --tests` 通过 -- 下一刀最值得继续推进的是: - - 若继续沿 plugin loader 对齐主线推进,比起 builtin plugin,更值得回到 plugin hot reload / prune 与 managed policy merge 的 current 宿主差距 - -### 继续推进(CCD-008 / plugin skill on-demand refresh) - -- 继续对照本地参考运行时并回看 Lime 当前实现后,进一步确认 `plugin hot reload / prune` 在仓库里的真实漂移点已经收缩: - - [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 这条 hook current 主链本来就是“按次构建 `HookRegistry` -> 重新加载 project/plugin hooks”,所以 `plugin hooks` 侧并不存在一个额外的全局缓存宿主需要单独热刷新 - - 真正仍会漂的是 [`skills/registry.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/skills/registry.rs) 里的全局 `SkillRegistry`:它之前挂在 `OnceLock` 后只初始化一次,导致 plugin skill 的 enable/disable、cache version 切换、同一路径 `SKILL.md` 内容变更都不会反映到后续 skill / workflow 使用 -- 因此这一轮没有去发明新的 plugin listener、也没有把别的 legacy plugin/extension 面接回 current,而是继续沿现有 Rust runtime 补最诚实的一刀: - - [`skills/loader.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/skills/loader.rs) 新增 `build_plugin_skill_registry_snapshot_with_context(...)`,基于共享的 [`claude_plugin_cache.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/claude_plugin_cache.rs) resolver 生成 plugin skill snapshot;snapshot 会记录: - - 当前可见的 `plugins` - - 当前 `skipped` reasons - - 每个 plugin root 下 `skills/*/SKILL.md` 的路径、文件长度、修改时间与内容 hash - - [`skills/registry.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/skills/registry.rs) 新增 `plugin_snapshot` 状态,以及: - - `initialize_with_context(...)` - - `reload_with_context(...)` - - `refresh_plugin_skills_if_needed_with_context(...)` - - `refresh_shared_registry_if_needed(...)` - - 刷新语义保持极简: - - snapshot 不变时不 reload - - snapshot 变化时重新装载整套 skills(plugin / user / project),沿用既有优先级 - - `invoked` 历史不清空,不为了刷新把使用记录抹掉 - - [`skills/tool.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/skills/tool.rs) 与 [`workflow_tool.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/tools/workflow_tool.rs) 现在都会在 current 入口前触发这层 refresh,因此下一次使用 `SkillTool` / `WorkflowTool` 时,就会真实反映 plugin skill 的启停、prune、版本切换和 `SKILL.md` 更新 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:plugin hooks 继续通过按次重建 registry 获得天然刷新;plugin skills 则已补上基于 snapshot 的 on-demand refresh,当前 `SkillTool / WorkflowTool` 会在使用前自动收敛到最新可见 plugin skill 集合 - - `current gap`:Lime 还没有 upstream 那种 push-style plugin settings listener / managed policy merge host;builtin plugin current 宿主也仍缺席,所以这一步只是把“效果对齐”补到当前 skill runtime,而不是宣称已拥有同构的 plugin loader 生命周期 - - `compat / deprecated / dead`:无新增;本轮没有为了追平热刷新语义,把旧 installer、legacy manager、`.aster policySettings` 或其它 extension surface 抬回 current -- 这一步服务路线图主目标的关系是:把 `CCD-008` 在仓库内部最后一个明显的 plugin skill 全局缓存漂移点收掉,让 Lime 现有 skill/runtime 主链不再停在“settings 已变、skill 仍读旧快照”的半成品阶段;下一刀才值得继续评估是否需要真正的 push listener / policy merge 宿主。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/skills/loader.rs" "src-tauri/crates/aster-rust/crates/aster/src/skills/registry.rs" "src-tauri/crates/aster-rust/crates/aster/src/skills/tool.rs" "src-tauri/crates/aster-rust/crates/aster/src/tools/workflow_tool.rs"` 通过 - - `cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" refresh_plugin_skills_if_needed_with_context --lib -- --nocapture` 通过(`3 passed`) - - `cargo check --manifest-path "src-tauri/Cargo.toml" -p lime --tests` 通过 -- 下一刀最值得继续推进的是: - - 继续判断 Lime 是否真的需要补 upstream 风格的 plugin settings listener / managed policy merge host;如果没有真实宿主,就继续把这层差异保留为 gap,而不是把别的系统硬包装成 current - -### 继续推进(CCD-008 / platform skills extension fact-source convergence) - -- 顺着 `plugin skill` 刷新主线继续盘点后,又发现仓库里还留着一条容易误导实现者的平行技能面: - - [`agents/skills_extension.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/agents/skills_extension.rs) 过去会自己扫描 `~/.claude/skills`、`~/.config/agents/skills`、`$PWD/.claude/skills`、`$PWD/.aster/skills`、`$PWD/.agents/skills` - - 这条 platform extension loader 与当前 [`skills/loader.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/skills/loader.rs) / [`skills/registry.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/skills/registry.rs) 的 current skill 主链不是同一事实源,甚至会把 `.aster/skills`、`.agents/skills` 这类 Claude Code 当前语义里并不存在的目录重新抬成可见 surface - - 如果继续默认启用,它会形成第二套 `skills__loadSkill` 工具面,与 native `SkillTool` / `WorkflowTool` 并存,进一步偏离参考运行时 -- 这一轮没有为了保留旧行为继续补 compat,而是直接收口: - - [`extension.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/agents/extension.rs) 里 `skills` platform extension 已从 `default_enabled: true` 降为 `false`,并在描述里明确 native `Skill tool` 才是 current surface - - [`skills_extension.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/agents/skills_extension.rs) 即使被手动启用,也不再自己扫描那套旧目录,而是改为直接复用共享的 `SkillRegistry`: - - 读取前先执行 `refresh_shared_registry_if_needed(...)` - - `loadSkill` 改为通过共享 registry 查找 skill - - skill instructions 与工具可见性也都改为从共享 registry 读取 - - 这样处理后,仓库里不再存在“native skills 一套事实源,platform skills extension 另一套事实源”的并行 current -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:native `SkillTool / WorkflowTool + SkillRegistry` 继续是唯一技能 current surface - - `compat`:platform `skills` extension 现在只剩显式 opt-in legacy surface;即便开启,也只能委托共享 `SkillRegistry`,不再拥有独立 loader / directory semantics - - `dead`:`.aster/skills`、`.agents/skills` 这类 platform skills extension 私有目录语义已不再参与当前运行时事实源 -- 这一步服务路线图主目标的关系是:把 Lime 仓库内部最后一个“技能系统自己再长一套目录发现逻辑”的平行面压回去,避免 `CCD-008` 主线刚把 native skill/runtime 收口完,另一边 platform extension 又把旧目录和旧工具面重新接回产品。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/agents/extension.rs" "src-tauri/crates/aster-rust/crates/aster/src/agents/skills_extension.rs"` 通过 - - `cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" skills_extension::tests --lib -- --nocapture` 通过(`12 passed`) - - `cargo check --manifest-path "src-tauri/Cargo.toml" -p lime --tests` 通过 -- 下一刀最值得继续推进的是: - - 回到真正还没有 honest host 的部分,继续审 `plugin settings listener / managed policy merge` 是否需要产品级 current 宿主;如果没有,就继续把这层差异留在 gap,而不是从旧 extension / config surface 里找替身 - -### 继续推进(CCD-008 / plugin cache legacy fallback) - -- 继续对照本地参考运行时 [`pluginLoader.ts`](../../../../js/claudecode/src/utils/plugins/pluginLoader.ts) 后,确认 plugin cache 目录语义还差最后一层真实 resolver 行为: - - upstream 的 `resolvePluginPath(...)` 不是“只认 versioned cache” - - 它会先尝试 `~/.claude/plugins/cache////` - - 若该 versioned 路径不存在,再回退到历史遗留的 `~/.claude/plugins/cache//` -- 因此这一轮没有去补没有 honest host 的 settings listener / managed policy merge,而是先把 Lime 的 cache resolver 对齐到 upstream 当前真实行为: - - [`claude_plugin_cache.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/claude_plugin_cache.rs) 里的 `resolve_cached_plugin_root(...)` 现在改为: - - 先在 versioned `cache///` 下选择最高版本目录 - - 找不到可用 versioned root 时,再回退到 legacy non-versioned `cache//` - - marketplace / plugin path component 也改为按 upstream 同样的 sanitize 规则解析,避免 `@scope/plugin@demo.market` 这类真实插件 ID 因路径字符差异被误判成不存在 - - 这样 `runtime_project_hooks.rs` 与 `skills/loader.rs` 继续共享同一个 resolver 时,会同时获得: - - versioned cache 优先 - - legacy cache fallback - - `@builtin` / managed policy gap 的统一 skipped reason - - 这一步只对齐 Claude Code 当前仍承认的 legacy cache path,不等于把 Lime 自己的 installer、`.aster` 插件目录或其它非 Claude cache 面接回 current -- 也补了最贴边界的回归测试,锁住 resolver 口径: - - 只有 legacy `cache//` 时,仍能解析出 plugin root - - versioned 与 legacy 同时存在时,必须优先选 versioned root - - scoped plugin / 带点号 marketplace 会命中 sanitize 后的 cache 路径 - - `runtime_project_hooks.rs` 已补消费者级 legacy cache 集成测试,证明 plugin hook 当前主链也会吃到这条 fallback - - `skills/loader.rs` 已补消费者级 sanitized path 集成测试,证明 plugin skill 当前主链也会吃到同一条 path 规则 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:plugin hooks / plugin skills 继续共享单一 `claude_plugin_cache.rs` resolver,当前口径已覆盖 home/workspace `settings*.json` 合并、highest-version 选择,以及 upstream 仍承认的 legacy cache fallback - - `current gap`:push-style plugin settings listener、managed policy merge、builtin plugin registry / hooks 仍无 honest host;这些差距继续保留为 gap,不做假映射 - - `compat / deprecated / dead`:无新增;本轮没有把其它 plugin installer、legacy manager 或 `.aster policySettings` 抬回 current -- 这一步服务路线图主目标的关系是:把 `CCD-008` 在 plugin cache resolver 这一层收成真正与 upstream 一致的 current 事实源,避免后续实现者继续把“只认 versioned cache”的半截语义误当成已经对齐。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs" "src-tauri/crates/aster-rust/crates/aster/src/skills/loader.rs"` 通过 - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime load_runtime_project_hook_registry_should_include_legacy_cached_plugin_user_prompt_hooks -- --nocapture` 通过(`1 passed`) - - `cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_load_skills_from_plugin_cache_uses_sanitized_plugin_cache_paths --lib -- --nocapture` 通过(`1 passed`) - - `cargo check --manifest-path "src-tauri/Cargo.toml" -p lime --tests` 通过 - -### 继续推进(CCD-008 / legacy plugin manifest fallback) - -- 继续对照本地参考运行时 [`pluginLoader.ts`](../../../../js/claudecode/src/utils/plugins/pluginLoader.ts) 后,又确认 plugin hook loader 还有一条当前仍有效的旧布局读取语义: - - upstream 读取 plugin manifest 时,优先 `.claude-plugin/plugin.json` - - 若主路径不存在,仍会 fallback 到根目录 `plugin.json` -- Lime 之前的 [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 只读 `.claude-plugin/plugin.json`,这会让一部分旧 cache 布局下的 plugin hooks 被误判成“没有 manifest hooks”。 -- 因此这一轮继续补的是当前真实读取顺序,而不是新造 compat: - - plugin hook loader 现在改为 `resolve_plugin_manifest_path(...)` - - 顺序固定为: - - 先读 `.claude-plugin/plugin.json` - - 若不存在,再读 legacy 根目录 `plugin.json` - - 如果主路径存在,就不会去用 legacy 路径顶替,保持与 upstream 同样的优先级 -- 也补了对应消费者级集成测试: - - versioned plugin cache + legacy 根目录 `plugin.json` 时,`runtime_project_hooks` 仍能加载 `UserPromptSubmit` hook -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:plugin hook 当前主链现在同时对齐了 upstream 的 cache path 解析顺序与 manifest path 解析顺序 - - `current gap`:push-style plugin settings listener、managed policy merge、builtin plugin registry / hooks 仍无 honest host - - `compat / deprecated / dead`:无新增;这一轮没有把旧 installer 或其他非 current plugin 面接回运行时 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 的 plugin hook loader 再往 upstream 当前真实布局推进一层,避免“cache 目录找对了,但 manifest 仍漏读 legacy layout”这种半对齐状态。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs"` 通过 - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime load_runtime_project_hook_registry_should_include_legacy_manifest_plugin_user_prompt_hooks -- --nocapture` 通过(`1 passed`) - - `cargo check --manifest-path "src-tauri/Cargo.toml" -p lime --tests` 通过 - -### 继续推进(CCD-008 / plugin manifest.skills current) - -- 继续对照本地参考运行时 [`pluginLoader.ts`](../../../../js/claudecode/src/utils/plugins/pluginLoader.ts) 与 [`loadPluginCommands.ts`](../../../../js/claudecode/src/utils/plugins/loadPluginCommands.ts) 后,又确认 plugin skill loader 还有一条当前真实发现语义: - - upstream 不只是扫默认 `skills/` - - `plugin.json` 的 `skills` 字段会显式指定 plugin skill 目录 - - 并且按当前执行代码,`manifest.skills` 一旦存在,就不再自动注册默认 `skills/` 目录;只有 `manifest.skills` 缺席时才做默认 autodetect - - 每个 skill path 既可以是“目录本身就是一个 skill(含 `SKILL.md`)”,也可以是“目录下再挂多个 skill 子目录” -- Lime 之前的 [`loader.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/skills/loader.rs) 只会扫 `plugin_root/skills/*/SKILL.md`,因此: - - manifest 指定的额外 skill 目录不会进入 current - - 根目录 `plugin.json` 这条 legacy manifest fallback 也不会影响 plugin skill 发现 - - `manifest.skills` 存在时默认 `skills/` 是否应继续自动加载,也与 upstream 当前执行语义不一致 -- 因此这一轮继续把 plugin skill current 主链收口到 upstream 当前 loader 语义: - - [`claude_plugin_cache.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/claude_plugin_cache.rs) 新增共享 `resolve_cached_plugin_manifest_path(...)` - - [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 与 [`loader.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/skills/loader.rs) 都统一复用这条 manifest path 事实源,不再各自维护 `.claude-plugin/plugin.json` / 根目录 `plugin.json` fallback - - plugin skills 现在改为: - - `manifest.skills` 缺席:只自动扫描默认 `skills/` - - `manifest.skills` 存在:只加载 manifest 显式声明的 skill 目录 - - 单个 skill 目录和“skill 容器目录”两种形态都支持 - - 同一路径命中的 `SKILL.md` 会做去重,避免标准目录与显式目录重叠时重复装载 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:plugin skill loader 现在同时对齐了 upstream 的 cache path、manifest path、以及 `manifest.skills` 发现优先级 - - `current gap`:push-style plugin settings listener、managed policy merge、builtin plugin registry / hooks 仍无 honest host;这些差距继续保留为 gap - - `compat / deprecated / dead`:无新增;本轮没有把旧 plugin installer 或其它非 current plugin 面接回技能主链 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 的 plugin skill loader 从“只认默认目录”的半对齐推进到“manifest 显式技能路径也进入 current”,避免后续实现者继续按错误的自动发现规则补 plugin skills。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/claude_plugin_cache.rs" "src-tauri/crates/aster-rust/crates/aster/src/skills/loader.rs" "src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs"` 通过 - - `cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_load_skills_from_plugin_cache_prefers_manifest_skills_paths_and_legacy_manifest --lib -- --nocapture` 通过(`1 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" -p lime load_runtime_project_hook_registry_should_include_legacy_manifest_plugin_user_prompt_hooks -- --nocapture` 通过(`1 passed`) - - `cargo check --manifest-path "src-tauri/Cargo.toml" -p lime --tests` 通过 - -### 继续推进(CCD-008 / plugin manifest path strictness) - -- 继续对照本地参考运行时 [`pluginLoader.ts`](../../../../js/claudecode/src/utils/plugins/pluginLoader.ts) 与 [`schemas.ts`](../../../../js/claudecode/src/utils/plugins/schemas.ts) 后,又确认 plugin loader 还差一层当前真实的 manifest path 约束: - - upstream 不是“拿到 manifest 后宽松拼路径再试” - - `PluginManifestSchema` 会先把 `manifest.skills` 约束成必须以 `./` 开头的相对路径 - - `manifest.hooks` 的 path 版本则进一步要求必须是 `./*.json` - - `createPluginFromPath(...)` 对 hooks 还保留 strict duplicate 语义:`hooks/hooks.json` 自动加载后,如果 `manifest.hooks` 再指回同一个文件,会记为 duplicate error,而不是静默接受 -- Lime 之前在 [`loader.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/skills/loader.rs) 与 [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 虽然已经能读 `manifest.skills` / `manifest.hooks`,但仍有两处比 upstream 更松的行为: - - `skills` / `hooks` 路径接受 `"extra-skill"`、`"hooks/extra.json"` 这类不带 `./` 的写法 - - `manifest.hooks` 指回标准 `hooks/hooks.json` 时只会静默去重,不会显式报告 duplicate -- 因此这一轮继续把 plugin manifest path current 主链收口到 upstream 当前 loader 语义: - - [`claude_plugin_cache.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/claude_plugin_cache.rs) 新增共享 helper: - - `load_cached_plugin_manifest_json(...)` - - `validate_claude_manifest_relative_path(...)` - - `resolve_claude_manifest_relative_path(...)` - - 这层 helper 现在会统一: - - 只接受 Claude 当前风格的 `./...` manifest 相对路径 - - 对 hooks path 额外要求 `.json` - - 按 Node `path.join(...)` 的当前语义把 `./` 规范掉,避免 Rust `PathBuf` 保留字面 `./` 造成路径表示漂移 - - [`loader.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/skills/loader.rs) 现在改为: - - `manifest.skills` 解析失败、类型不对、路径不带 `./`、或 manifest 自身损坏时,都会显式进入 skipped reason - - 一旦 manifest 提供了非法 `skills` 配置,就不再偷偷回退默认 `skills/` - - `build_plugin_skill_registry_snapshot_with_context(...)` 也会带出同一套 skipped 信息,方便后续 refresh/current 诊断 - - [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 现在改为: - - 先验证 cached plugin manifest,再决定是否继续加载 plugin hooks - - `manifest.hooks` path 只认 `./*.json` - - 如果 `manifest.hooks` 指回已自动加载的 `hooks/hooks.json`,会显式记录 duplicate skipped reason,对齐 upstream strict 行为 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:plugin skill / plugin hook loader 现在继续共享单一 manifest path 事实源,当前口径已覆盖 `./` 前缀约束、hooks `.json` 约束、`./` 规范化,以及 duplicate hooks file 显式报告 - - `current gap`:managed plugin policy merge、builtin plugin registry / hooks、push-style plugin settings listener 仍无 honest host;这些差距继续保留为 gap - - `compat / deprecated / dead`:无新增;本轮没有为了迁就旧 plugin manifest 写法再补宽松 fallback -- 这一步服务路线图主目标的关系是:把 `CCD-008` 从“能加载 plugin manifest,但边界仍比 upstream 松”的半对齐,推进到“manifest path 语义也按 upstream current 收紧”,避免后续实现者继续把宽松路径当成 current 契约。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/claude_plugin_cache.rs"` 通过 - - `CARGO_NET_OFFLINE=true CARGO_TARGET_DIR="/tmp/lime-target-offline" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" load_cached_plugin_manifest_json_should --lib -- --nocapture` 通过(`1 passed`) - - `CARGO_NET_OFFLINE=true CARGO_TARGET_DIR="/tmp/lime-target-offline" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" validate_claude_manifest_relative_path_should_ --lib -- --nocapture` 通过(`1 passed`) - - `CARGO_NET_OFFLINE=true CARGO_TARGET_DIR="/tmp/lime-target-offline" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_load_skills_from_plugin_cache --lib -- --nocapture` 通过(`4 passed`) - - `CARGO_NET_OFFLINE=true CARGO_TARGET_DIR="/tmp/lime-target-offline" cargo test --manifest-path "src-tauri/Cargo.toml" -p lime load_runtime_plugin_hook_registry_should_ -- --nocapture` 通过(`2 passed`) - - `CARGO_NET_OFFLINE=true CARGO_TARGET_DIR="/tmp/lime-target-offline" cargo test --manifest-path "src-tauri/Cargo.toml" -p lime load_runtime_project_hook_registry_should_include_ -- --nocapture` 通过(`4 passed`) - -### 继续推进(CCD-008 / plugin manifest validity gate) - -- 继续对照本地参考运行时 [`schemas.ts`](../../../../js/claudecode/src/utils/plugins/schemas.ts) 与 [`pluginLoader.ts`](../../../../js/claudecode/src/utils/plugins/pluginLoader.ts) 后,又确认 Lime 之前还有一层“看起来能跑、其实仍比 upstream 松”的空档: - - `load_cached_plugin_manifest_json(...)` 之前只校验“是不是 JSON object” - - 这会导致 `manifest.name`、`manifest.commands`、`manifest.agents`、`manifest.outputStyles` 这类字段即使已经偏离 Claude current schema,只要 `skills/hooks` 自己那一小段还能解析,Lime 仍会继续把 plugin 当成可加载 - - upstream 当前不是按 surface 局部放行,而是先过整份 `PluginManifestSchema`,manifest 任一 current 字段失真,就整份 plugin 失效 -- 因此这一轮继续把 plugin manifest current 主链收口到 upstream 当前 schema gate: - - [`claude_plugin_cache.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/claude_plugin_cache.rs) 新增共享 `validate_cached_plugin_manifest_compat(...)` - - 这层 helper 现在会统一校验: - - `manifest.name`:必填、非空、不能包含空格 - - `manifest.version` / `manifest.description`:若存在必须为 string - - `manifest.skills` / `manifest.outputStyles`:只认 `./...` 的 `string | string[]` - - `manifest.agents`:只认 `./*.md` 的 `string | string[]` - - `manifest.hooks`:只认 `./*.json` path、inline hooks object、或两者数组 - - `manifest.commands`:只做 schema 级校验,接受 `string | string[] | object-map`,object metadata 必须满足 `source` 与 `content` 二选一等当前约束 - - [`load_cached_plugin_manifest_json(...)`](../../src-tauri/crates/aster-rust/crates/aster/src/claude_plugin_cache.rs) 现在会先过这层共享 gate,再把 manifest 交给 [`loader.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/skills/loader.rs) 和 [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) - - 结果上,`skills/hooks` current surface 不再各自“只管自己那一段”;只要 manifest 整体偏离 Claude current schema,就会一起短路 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:plugin manifest 现在已有共享有效性事实源,`skills` 与 `hooks` 都跟着同一份 upstream-style schema gate 走 - - `current gap`:`manifest.commands` 仍只有 schema gate,没有 honest host;`outputStyles` 也仍缺当前宿主;managed policy、builtin plugin registry、push-style settings listener 仍保留为 gap - - `compat / deprecated / dead`:无新增;本轮没有把旧 installer validator、旧 plugin 面、或任意假兼容包装接回 current -- 这一步服务路线图主目标的关系是:把 `CCD-008` 从“路径语义接近 upstream,但 manifest 仍可能局部穿透”的半对齐,推进到“manifest 必须先整体合法,当前 `skills/hooks` 才能生效”,避免后续继续把局部可解析误当成 Claude current 对齐完成。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/crates/aster-rust/crates/aster/src/claude_plugin_cache.rs" "src-tauri/crates/aster-rust/crates/aster/src/skills/loader.rs" "src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs"` 通过 - - `CARGO_NET_OFFLINE=true CARGO_TARGET_DIR="/tmp/lime-target-offline" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" load_cached_plugin_manifest_json_should_ --lib -- --nocapture` 通过(`3 passed`) - - `CARGO_NET_OFFLINE=true CARGO_TARGET_DIR="/tmp/lime-target-offline" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_load_skills_from_plugin_cache --lib -- --nocapture` 通过(`5 passed`) - - `CARGO_NET_OFFLINE=true CARGO_TARGET_DIR="/tmp/lime-target-offline" cargo test --manifest-path "src-tauri/Cargo.toml" -p lime load_runtime_plugin_hook_registry_should_ -- --nocapture` 通过(`3 passed`) - - `CARGO_NET_OFFLINE=true CARGO_TARGET_DIR="/tmp/lime-target-offline" cargo test --manifest-path "src-tauri/Cargo.toml" -p lime load_runtime_project_hook_registry_should_include_ -- --nocapture` 通过(`4 passed`) - -### 继续推进(CCD-008 / plugin agents current) - -- 继续对照本地参考运行时 [`loadPluginAgents.ts`](../../../../js/claudecode/src/utils/plugins/loadPluginAgents.ts)、[`loadAgentsDir.ts`](../../../../js/claudecode/src/tools/AgentTool/loadAgentsDir.ts) 与 [`prompt.ts`](../../../../js/claudecode/src/tools/AgentTool/prompt.ts) 后,确认 plugin agents 在 upstream 里不是文案层概念,而是真正进入 subagent runtime 的 current surface。 -- 因此这一轮没有去接旧 installer、builtin preset / profile、`.aster policySettings` 或其他伪 current 面,而是只把 Lime 当前已有 honest host 的 plugin agent 子集接到真实 runtime: - - [`runtime_plugin_agents.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_plugin_agents.rs) 新增 plugin agent catalog loader,唯一事实源复用 [`claude_plugin_cache.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/claude_plugin_cache.rs) 的 enabled plugin cache 解析结果 - - 当前实际承接的字段只有:`agent_type`、`description / when-to-use`、markdown body -> `system_prompt`、`model`、`tools`、`disallowedTools` - - `${CLAUDE_PLUGIN_ROOT}` 现在会在 plugin agent prompt 里做真实替换;`tools / disallowedTools` 不是只进 prompt 文案,而是继续落到 Lime 现有 `allowed_tools / disallowed_tools` 真实权限边界 - - [`subagent_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs) 现在会在 `spawn_subagent` 时按 `agent_type -> plugin definition` 叠加 system prompt、model override、tool scope - - [`runtime_turn.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs) 现在会把“当前可用 plugin agent types”并入主会话的 `RuntimeAgents` prompt augmentation,避免主 agent 看不到 plugin agent surface -- 这一轮也把 unsupported 边界继续收紧成 fail-closed,而不是做假兼容: - - `skills`、`memory`、`effort`、`maxTurns / max_turns`、`isolation`:当前没有 honest host,整条 plugin agent definition 会被跳过并记录原因 - - `${user_config.*}`:当前没有对应宿主,直接 fail-closed - - `permissionMode`、`hooks`、`mcpServers`:按 upstream 当前语义只记 warning,不额外硬接宿主 - - 测试里顺手修正了 plugin cache ID 口径:Lime 当前 `claude_plugin_cache` 只认 `plugin@marketplace`,不是 `market/plugin` 或 `@market/plugin` -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:plugin marketplace cache 里的 agent definitions 已进入 Lime 当前 subagent runtime 主链,真实承接了 prompt / model / tool scope 三个当前宿主 - - `current gap`:plugin agent 的 `skills / memory / effort / maxTurns / isolation` 仍无 honest host,继续 fail-closed;managed policy、builtin plugin registry / hooks、push-style settings listener 仍保留为 gap - - `compat / deprecated / dead`:无新增;本轮没有为了“看起来兼容”去接旧 plugin 面、旧 preset 面或任意 policy 包装层 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 从“plugin skills / hooks 已 current,但 plugin 自带 agents 仍完全绕开 runtime”的断层,推进到“plugin agents 也进入当前 subagent 主路径”;后续剩余差距就集中在 unsupported agent fields 与 plugin loader 生命周期缺口,而不是继续卡在 agent surface 本身。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/src/commands/aster_agent_cmd/runtime_plugin_agents.rs" "src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs" "src-tauri/src/commands/aster_agent_cmd/mod.rs" "src-tauri/src/commands/aster_agent_cmd/runtime_turn.rs" "src-tauri/src/commands/aster_agent_cmd/tests.rs"` 通过 - - `cargo test --manifest-path "src-tauri/Cargo.toml" runtime_plugin_agents --lib -- --nocapture` 通过(`4 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_build_subagent_customization_state_with_plugin_agent_applies_runtime_overlay_and_tool_scope --lib -- --nocapture` 通过(`1 passed`) - -### 继续推进(CCD-008 / Agent current `run_in_background` 透传) - -- 继续对照本地参考运行时 [`AgentTool.tsx`](../../../../js/claudecode/src/tools/AgentTool/AgentTool.tsx) 后,确认 `run_in_background` 不是可有可无的展示字段,而是 Claude current `Agent` surface 用来决定 child agent 是否异步运行的真实输入。 -- 进一步核对 Lime 当前链路后,确认缺口不在 `aster-rust` schema: - - [`agent_control.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/tools/agent_control.rs) 已经把 `run_in_background` 解析进 `SpawnAgentRequest` - - 但 [`subagent_tools.rs`](../../src-tauri/src/commands/aster_agent_cmd/tool_runtime/subagent_tools.rs) 之前在 callback 组装 [`AgentRuntimeSpawnSubagentRequest`](../../src-tauri/src/commands/aster_agent_cmd/dto.rs) 时把它硬编码成了 `false` - - 结果是 Lime 当前 `Agent` tool surface 会静默吞掉 upstream 已经存在的后台运行语义,和参考运行时不一致 -- 因此这一轮没有新增任何 compat 包装,而是把这条 current 字段透传补通: - - [`subagent_tools.rs`](../../src-tauri/src/commands/aster_agent_cmd/tool_runtime/subagent_tools.rs) 新增小型 request mapping helper,统一负责 `SpawnAgentRequest -> AgentRuntimeSpawnSubagentRequest` - - `run_in_background` 现在按真实输入继续向下透传,不再在 callback 层被写死 - - 同时补了一条映射单测,直接钉住 `Agent` current surface 的关键字段不再在 Lime host callback 里丢失 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:`Agent` current surface 的 `run_in_background` 已进入 Lime 当前 subagent runtime 主链,至少 metadata / runtime request 已与 upstream 对齐,不再在宿主 callback 处丢字段 - - `current gap`:plugin agent definition 的 `background: true` 仍未承接;`mode / isolation` 也仍没有 honest host,这两项都不应伪装成已支持 - - `compat / deprecated / dead`:无新增;本轮没有为了“先兼容着”去扩展旧 subagent surface -- 这一步服务路线图主目标的关系是:把 `CCD-008` 从“plugin agent prompt/model/tool scope 已 current,但 `Agent` 最基础的后台运行字段仍在 Lime callback 层失真”的状态,推进到“`Agent` current surface 的后台运行语义至少不再被宿主吞掉”;后续下一刀应继续判断是否把 plugin agent 的 `background: true` 也接回同一条主链。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/src/commands/aster_agent_cmd/tool_runtime/subagent_tools.rs"` 通过 - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_map_spawn_agent_request_to_runtime_request_preserves_current_surface_fields --lib -- --nocapture` 通过(`1 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_remove_duplicate_current_surface_agent_tool_keeps_send_message --lib -- --nocapture` 通过(`1 passed`) - -### 继续推进(CCD-008 / plugin agent `background` current) - -- 在补通 `Agent.run_in_background` 之后,继续对照本地参考运行时 [`loadPluginAgents.ts`](../../../../js/claudecode/src/utils/plugins/loadPluginAgents.ts) 与 [`AgentTool.tsx`](../../../../js/claudecode/src/tools/AgentTool/AgentTool.tsx) 后,确认 upstream 还有一层当前事实: - - plugin agent frontmatter 自带 `background: true` - - upstream 会把它和显式 `run_in_background` 一起并入 `shouldRunAsync` - - 因此如果 Lime 只承接显式请求、完全忽略 plugin agent 自带 `background`,current surface 仍然是不完整的 -- 继续核对 Lime 当前宿主能力后,也确认这一步只能按 honest host 收口: - - [`subagent_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs) 当前本来就是统一的后台 queued-turn 启动路径,没有另一套真正的前台 child-agent executor - - 所以这一轮不能伪造“foreground/background 双引擎” - - 但至少应该把 plugin agent 的 `background` 收进当前 runtime request / metadata 真相集,避免连 effective background intent 都丢掉 -- 因此这一轮继续把 plugin agent `background` 接到同一条 current 主链: - - [`runtime_plugin_agents.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_plugin_agents.rs) 现在会解析 frontmatter `background` - - [`subagent_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs) 新增 effective background helper,把显式 `run_in_background` 与 plugin agent `background` 合并 - - child subagent turn metadata 里的 `subagent.run_in_background` 现在会写入 effective 值,而不是只看 request 显式字段 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:plugin agent definition 的 `background` 已进入 Lime 当前 subagent runtime 真相集;即使当前执行器仍是统一后台队列,effective background intent 已不再丢失 - - `current gap`:Lime 仍没有 upstream 那种真正区分 foreground/background child execution lifecycle 的宿主;`mode / isolation` 也仍无 honest host,继续保持 unsupported - - `compat / deprecated / dead`:无新增;本轮没有为了对齐 `background` 去硬造另一套 child runtime -- 这一步服务路线图主目标的关系是:把 `CCD-008` 从“plugin agent prompt/model/tool scope 已 current,显式 `run_in_background` 也透传了,但 plugin 自带 `background` 仍失真”的状态,推进到“plugin agent 与 Agent tool 共享同一套 effective background 事实源”;后续若要继续补,只能往真正的 child lifecycle / notification host 收,不该回头补 compat 包装。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/src/commands/aster_agent_cmd/runtime_plugin_agents.rs" "src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs"` 通过 - - `cargo test --manifest-path "src-tauri/Cargo.toml" load_runtime_plugin_agent_catalog_should_load_supported_agents_and_skip_unsupported_fields --lib -- --nocapture` 通过(`1 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_resolve_effective_run_in_background_prefers_plugin_agent_background --lib -- --nocapture` 通过(`1 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_build_subagent_customization_state_with_plugin_agent_applies_runtime_overlay_and_tool_scope --lib -- --nocapture` 通过(`1 passed`) - -### 继续推进(CCD-008 / Agent `mode` current subset) - -- 在补通 `run_in_background` / plugin agent `background` 之后,继续对照本地参考运行时 [`AgentTool.tsx`](../../../../js/claudecode/src/tools/AgentTool/AgentTool.tsx) 与 [`PermissionMode.ts`](../../../../js/claudecode/src/utils/permissions/PermissionMode.ts) 后,确认 `mode` 也是 `Agent` current surface 的真实输入,而不是文案字段。 -- 继续核对 Lime 当前宿主能力后,确认这条线不能“全量冒充支持”: - - upstream 的 `plan` 绑定的是完整的 plan-mode / approval lifecycle - - Lime 当前只有显式 [`EnterPlanMode` / `ExitPlanMode`](../../src-tauri/crates/aster-rust/crates/aster/src/tools/plan_mode_tool.rs) 工具流,没有可附着到 child session 的同构 permission runtime - - `isolation` 同样仍缺 honest host,尤其 `worktree / remote` 会直接牵到另一套 child lifecycle -- 因此这一轮只把有真实宿主的 `mode` 子集接回 current,而不是做垃圾兼容: - - [`subagent_tools.rs`](../../src-tauri/src/commands/aster_agent_cmd/tool_runtime/subagent_tools.rs) 不再吞掉 `mode / isolation`,而是完整透传到 runtime request - - [`subagent_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs) 现在会把: - - `default` 视为继承父会话 access mode - - `acceptEdits` 映射到 Lime 现有 `current` access mode - - `dontAsk` 映射到 Lime 现有 `full-access` access mode - - `plan` 与 `bypassPermissions` 继续明确 fail-closed,`isolation` 也继续明确拒绝 - - [`prompt_context.rs`](../../src-tauri/src/commands/aster_agent_cmd/prompt_context.rs) 的 current surface 提示也同步收口到这条最新事实,不再笼统声称“任何非空 mode 都拒绝” -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:`Agent.mode` 已进入 Lime 当前 subagent runtime 的 honest subset;`default / acceptEdits / dontAsk` 不再停留在 schema 层,而会真实影响 child access mode - - `current gap`:`plan` 仍缺可绑定到 child session 的真实 plan-mode lifecycle;`bypassPermissions` 与 `isolation` 也仍无 honest host,继续保持 fail-closed - - `compat / deprecated / dead`:无新增;本轮没有为了“看起来支持 mode”去长出平行 permission runtime -- 这一步服务路线图主目标的关系是:把 `CCD-008` 从“`Agent` 表面上接受 mode,但 Lime runtime 要么吞字段、要么一刀全拒”的状态,推进到“当前真正有宿主的 mode 子集已经进入 subagent 主链,而剩余部分被明确留在 gap”;后续若继续推进,应优先判断 child-specific plan lifecycle 是否值得 honest 落地,而不是回头给 `plan` / `isolation` 包一层假支持。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/src/commands/aster_agent_cmd/tool_runtime/subagent_tools.rs" "src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs" "src-tauri/src/commands/aster_agent_cmd/prompt_context.rs"` 通过 - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_map_spawn_agent_request_to_runtime_request_preserves_current_surface_fields --lib -- --nocapture` 通过(`1 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_validate_spawn_request_surface_accepts_supported_modes_and_rejects_unsupported_values --lib -- --nocapture` 通过(`1 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_resolve_spawn_request_access_mode_prefers_supported_mode_override --lib -- --nocapture` 通过(`1 passed`) - -### 继续推进(CCD-008 / plan mode honest 边界 + plugin agent `isolation` current) - -- 继续对照本地参考运行时 [`AgentTool.tsx`](../../../../js/claudecode/src/tools/AgentTool/AgentTool.tsx)、[`loadPluginAgents.ts`](../../../../js/claudecode/src/utils/plugins/loadPluginAgents.ts) 与 Lime 当前宿主实现后,先把 `plan / isolation` 两条线重新核清了一次: - - [`plan_mode_tool.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/tools/plan_mode_tool.rs) 当前仍把 plan mode 挂在 `GLOBAL_STATE` 上,并且 `EnterPlanMode` 还会显式拒绝 agent context;这说明 Lime 现在仍没有可绑定到 child session 的 plan-mode host,不能把 `Agent.mode=plan` 伪装成已支持。 - - 但 plugin agent 的 `isolation: worktree` 在 upstream 并不是“非法 frontmatter”;[`loadPluginAgents.ts`](../../../../js/claudecode/src/utils/plugins/loadPluginAgents.ts) 会正常加载它,只是在真正 spawn 时再交给宿主能力决定是否能跑。 - - Lime 之前却把 plugin agent 的 `isolation` 放进了 loader 级 unsupported 字段集合,导致包含 `isolation: worktree` 的 plugin agent 在 catalog 阶段就整条被跳过。这不是 honest fail-closed,而是 current surface 漂移。 -- 因此这一轮没有去硬接 `worktree` 宿主,而是先把事实源收正: - - [`runtime_plugin_agents.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_plugin_agents.rs) 不再把 `isolation` 当成 loader 级 unsupported 字段;runtime plugin agent catalog 现在会保留 `isolation: worktree` 定义,和 upstream current frontmatter 保持一致。 - - [`subagent_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs) 新增 effective isolation 解析:显式 request isolation 优先,其次才回落到 plugin agent frontmatter。 - - 对 effective isolation 继续保持 fail-closed:只要最终 isolation 非空,runtime 仍会明确返回 `isolation is not supported in the current runtime`,而不是静默吞掉或假装已经进入 worktree lifecycle。 - - child turn metadata 里的 `subagent.isolation` 也收口到 effective 值,避免 request 为空但 plugin agent 自带 isolation 时继续写出失真的 metadata。 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:plugin agent `isolation` 已进入 Lime 当前 runtime catalog 真相集;Lime 不再在加载期错误跳过 upstream 合法的 plugin agent definition。 - - `current gap`:`worktree` 仍没有接上 Claude 那套创建 / cwd override / cleanup 生命周期,因此 spawn 侧继续 honest fail-closed;`mode=plan` 也仍缺 child-session scoped host,继续保持 gap。 - - `compat / deprecated / dead`:无新增;本轮没有为了“先看起来支持 isolation”去伪造 worktree session 或平移旧实现。 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 从“plugin agent current frontmatter 在 Lime loader 阶段就失真”的状态,推进到“catalog 事实源已对齐,剩余缺口只集中在真正的 worktree / plan host lifecycle”;下一刀如果继续推进,应优先判断是否值得 honest 落地 child worktree host,而不是再回头补 compat 包装。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/src/commands/aster_agent_cmd/runtime_plugin_agents.rs" "src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs"` 通过 - - `cargo test --manifest-path "src-tauri/Cargo.toml" load_runtime_plugin_agent_catalog_should_load_supported_agents_and_skip_unsupported_fields --lib -- --nocapture` 通过(`1 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_resolve_effective_isolation_prefers_request_then_plugin_agent --lib -- --nocapture` 通过(`1 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_validate_effective_spawn_isolation_rejects_plugin_agent_default --lib -- --nocapture` 通过(`1 passed`) - -### 继续推进(CCD-008 / worktree honest host 接线) - -- 继续严格对照本地参考运行时 `/Users/coso/Documents/dev/js/claudecode` 的 `AgentTool.tsx / worktree.ts / resumeAgent.ts` 后,这一轮没有再停在“catalog 接住 isolation,但 spawn 继续全拒”的中间态,而是把 Lime 已有的 Aster worktree host 真正接回了 subagent current 主链: - - [`subagent_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs) 现在会在 effective isolation 为 `worktree` 时直接复用 Aster 现成的 [`EnterWorktreeTool`](../../src-tauri/crates/aster-rust/crates/aster/src/tools/worktree_tools.rs),不再重写一套 git worktree 生命周期。 - - `close_subagent` 现在也会复用 [`ExitWorktreeTool`](../../src-tauri/crates/aster-rust/crates/aster/src/tools/worktree_tools.rs) 做 honest 收尾: - - worktree 干净时自动移除,并把 session 恢复回原目录 - - worktree 有改动时保留现状,后续 `resume` / `send` 继续沿用同一个 worktree - - 这一步和 upstream 的“无改动清理、有改动保留”事实源保持一致,但没有为了表面对齐去伪造另一套 cleanup 逻辑。 -- 同时把 Lime 本地真正的阻塞点一并收掉: - - `resolve_workspace_id_for_working_dir(...)` 不再只认 workspace root 精确匹配;现在会对 `working_dir` 做最长祖先 workspace 匹配。 - - 因此 `cwd` 指向 workspace 子目录,以及 `.aster/worktrees/` 这种 child worktree 目录,现在都能正确映回原 workspace,不会再在 spawn / send 阶段因为 `working_dir` 不等于 root 而失败。 -- 这一轮仍保持 honest fail-closed,没有为了“看起来像 upstream”硬编不存在的宿主语义: - - `isolation=remote` 继续明确拒绝 - - `cwd + isolation=worktree` 继续明确拒绝,因为 Lime 当前 persistent subagent runtime 还不能诚实承接 upstream 那组组合语义 - - `mode=plan / bypassPermissions` 仍保持之前的 fail-closed 边界 -- [`prompt_context.rs`](../../src-tauri/src/commands/aster_agent_cmd/prompt_context.rs) 的 current surface 提示也已经同步更新,不再继续向模型暴露“non-empty isolation 全不支持”的过时事实。 -- 这一步后的 `CCD-008` 边界进一步收紧为: - - `current`:`Agent.isolation=worktree`、plugin agent `isolation: worktree`、clean-remove / dirty-keep 的 child worktree close lifecycle、workspace 子目录与 `.aster/worktrees/*` 的 workspace 归属 - - `current gap`:`isolation=remote`、`cwd + worktree` 组合语义、child-scoped `plan` lifecycle - - `compat / deprecated / dead`:无新增;本轮没有为了迁就现状去长第二套 compat worktree 实现 -- 已执行定向校验: - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_validate_spawn_request_surface_accepts_supported_modes_and_rejects_unsupported_values --lib -- --nocapture` - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_validate_effective_spawn_isolation_accepts_worktree_and_rejects_unsupported_values --lib -- --nocapture` - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_resolve_workspace_id_for_working_dir_prefers_longest_ancestor_workspace --lib -- --nocapture` - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_maybe_enter_subagent_worktree_switches_session_to_worktree --lib -- --nocapture` - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_cleanup_subagent_worktree_for_close_removes_clean_and_keeps_dirty_worktree --lib -- --nocapture` - -### 继续推进(CCD-008 / missing worktree fallback) - -- 在把 `worktree` honest host 接回 child runtime 后,继续对照本地参考运行时 [`resumeAgent.ts`](../../../../js/claudecode/src/tools/AgentTool/resumeAgent.ts) 复盘了一次恢复链路,确认还有一个很贴边界的 current 漏口: - - upstream 在 resume 前会先检查 `meta.worktreePath` 是否仍是有效目录;如果 worktree 已被外部删除,就直接回退到 parent cwd,而不是继续拿坏路径做后续执行上下文。 - - Lime 之前虽然已经有了 dirty-keep 的 child worktree close lifecycle,但如果该 worktree 之后被外部清理,`send_subagent_input / resume_subagent / close_subagent` 仍会继续读到陈旧 `working_dir + WorktreeSessionState`,把坏掉的路径继续沿 child runtime 传播。 -- 因此这一轮没有去发明新的 worktree 宿主,而是把恢复保护补到现有 current 边界上: - - [`subagent_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs) 新增 `resolve_missing_subagent_worktree_restore(...)`,把“检测到 `worktree_path` 已丢失时,该回退到哪里、该清掉哪份 extension state”的决策收成单一事实源。 - - 同文件里的 `restore_missing_subagent_worktree_if_needed(...)` 会复用这份决策,在真正需要时把 child session 的 `working_dir` 回退到 `original_cwd`,并移除陈旧 `WorktreeSessionState`。 - - `agent_runtime_send_subagent_input_internal(...)`、`agent_runtime_resume_subagent_internal(...)` 与 `agent_runtime_close_subagent_internal(...)` 现在都会先经过这层恢复保护,再继续各自的队列恢复、输入投递或 close cleanup 流程。 -- 这一步后的 `CCD-008` 边界进一步收紧为: - - `current`:child worktree 在 dirty-keep 后若被外部删除,`send / resume / close` 会先回退到 `original_cwd` 并清理 stale worktree state,不再继续沿坏路径执行。 - - `current gap`:`isolation=remote`、`cwd + worktree` 组合语义、child-scoped `plan` lifecycle 仍未进入 honest host。 - - `compat / deprecated / dead`:无新增;本轮没有为了“让恢复先跑起来”去长第二套 worktree 状态源。 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 里刚接回来的 child worktree current 从“能创建、能保留,但恢复链路遇到外部删除就掉回坏状态”的半成品,推进到“至少在现有 host 之内具备 upstream 同类的最小恢复韧性”;下一刀若继续推进,应优先判断 `cwd + isolation=worktree` 能否 honest 落地,而不是回头补 compat 包装。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs"` 通过 - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_resolve_missing_subagent_worktree_restore_falls_back_to_original_cwd --lib -- --nocapture` 通过(`1 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_resolve_workspace_id_for_working_dir_prefers_longest_ancestor_workspace --lib -- --nocapture` 通过(`1 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_validate_effective_spawn_isolation_accepts_worktree_and_rejects_unsupported_values --lib -- --nocapture` 通过(`1 passed`) - -### 继续推进(CCD-008 / final status worktree auto cleanup) - -- 继续严格对照本地参考运行时 [`AgentTool.tsx`](../../../../js/claudecode/src/tools/AgentTool/AgentTool.tsx) 后,又补上了一处之前还没 honest 对齐的 child worktree 生命周期: - - upstream 在 agent 自然结束时就会尝试清理 worktree;只有检测到未提交改动或额外提交时才保留 worktree,供后续继续处理。 - - Lime 之前虽然已经在 `close_subagent` 路径接上了 `clean-remove / dirty-keep`,但 child session 自然进入 `Completed / Failed / Aborted` 时不会自动清理,导致干净 worktree 会一直挂到显式 `close_agent` 才回收。 -- 因此这一轮没有再造一套 git 清理器,而是继续复用现有 Aster host: - - [`subagent_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs) 新增 `should_auto_cleanup_subagent_worktree(...)` 与 `maybe_cleanup_subagent_worktree_after_runtime_event(...)`,把“哪些 runtime 终态应该尝试自动回收 worktree”收口成单一事实源。 - - `maybe_emit_subagent_status_for_runtime_event(...)` 现在会在 relevant runtime event 进入 child final status 后,先尝试复用 [`ExitWorktreeTool`](../../src-tauri/crates/aster-rust/crates/aster/src/tools/worktree_tools.rs) 做 clean-remove / dirty-keep,再发状态事件。 - - 如果 worktree 已被外部删除,仍会先经过前一轮补上的 missing-worktree fallback,回退 `original_cwd` 并移除 stale `WorktreeSessionState`,不会把坏路径继续带进自动清理流程。 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:`Agent.isolation=worktree` 现在同时具备 `spawn -> natural final status auto cleanup -> explicit close cleanup -> missing-worktree fallback` 的 honest child lifecycle;干净 worktree 不再需要额外依赖手动 close 才回收。 - - `current gap`:`isolation=remote`、`cwd + worktree` 组合语义、child-scoped `plan` lifecycle 仍未进入 honest host。 - - `compat / deprecated / dead`:无新增;本轮没有为了“补自动清理”去发明第二套 worktree 状态源或自写 git remove 流程。 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 的 child worktree current 从“能创建、能恢复、能在 close 时清理”的半收口状态,推进到“自然结束时也按 upstream 语义自动收尾”的更完整主链;下一刀若继续推进,应优先判断 `cwd + worktree` 是否有 honest host,而不是回头补手动约定或兼容包裹。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs"` 通过 - - `env CARGO_TARGET_DIR="/tmp/lime-target-subagent-worktree" cargo test --manifest-path "src-tauri/Cargo.toml" "commands::aster_agent_cmd::subagent_runtime::tests::" --lib -- --nocapture` 通过(`18 passed`) - -### 继续推进(CCD-008 / `cwd + worktree` honest host) - -- 继续严格对照本地参考实现 [`AgentTool.tsx`](../../../../js/claudecode/src/tools/AgentTool/AgentTool.tsx) 后,这一轮把之前那条“看起来放开了组合,实际却把 child `working_dir` 回写到原仓库路径”的半成品收成了 honest host: - - upstream 真实执行面虽然仍带着 “Mutually exclusive” 的旧 schema 文案,但实际代码已经允许 `cwd + isolation=worktree` 共存。 - - Lime 上一版也开始尝试承接这组语义,但当时仍把 child session 先绑到 bootstrap 目录、进入 worktree 后再直接写回原始 `cwd`;这会让 child 后续 filesystem / shell 行为重新落回原仓库,而不是 child worktree。 -- 因此这一轮没有继续补 compat,而是把组合语义真正收口到现有 Aster worktree host 内: - - [`subagent_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs) 新增 `resolve_subagent_worktree_cwd_mapping(...)`,只在 `cwd` 属于父会话同一 Git 仓库时放行,并把请求目录映射成“源 worktree 根 -> 目标 child worktree 根”的相对路径。 - - 同文件里的 `resolve_subagent_session_bootstrap_working_dir(...)` 也同步改回以真实 `execution_working_dir` 建 child session,不再为了进 worktree 先把 child session 绑到父目录;这样 `EnterWorktreeTool` 记录下来的 `original_cwd` 就仍然是显式请求的 `cwd`。 - - `maybe_enter_subagent_worktree(...)` 现在会在创建 worktree 后立即调用 `remap_subagent_worktree_cwd_after_enter(...)`,把 child session 的 `working_dir` 切到 `worktree_path + relative_path` 对应的子目录,而不是切回原仓库路径。 - - 如果该子目录在新 worktree 中不存在,`rollback_subagent_worktree_after_spawn_failure(...)` 会复用现有 `ExitWorktreeTool` 把刚创建的临时 worktree 回滚掉,避免留下半成功的 child worktree 状态。 - - [`prompt_context.rs`](../../src-tauri/src/commands/aster_agent_cmd/prompt_context.rs) 也同步把提示更新成当前真实边界:允许组合,但只支持同仓库、可映射到 child worktree 的目录。 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:`Agent.isolation=worktree` 现在不仅支持单独使用,也支持与显式 `cwd` 组合;当 `cwd` 位于父会话同一 Git 仓库、且能映射到 child worktree 现有目录时,child 会真正运行在 `worktree` 内对应子目录,同时继续沿用既有的 dirty-keep、missing-worktree fallback 与 final-status auto cleanup lifecycle。 - - `current gap`:`isolation=remote`、跨仓库 `cwd + worktree`、无法映射到 child worktree 现有目录的 `cwd`、child-scoped `plan` lifecycle。 - - `compat / deprecated / dead`:无新增;本轮没有为了“看起来像 upstream”继续保留把 `working_dir` 回写到原仓库路径的假支持,也没有发明第二套 worktree 状态源。 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 里 child worktree 最后一块明显失真的 `cwd` 组合语义收成 honest current,避免 Lime 再停在“表面允许组合、实际仍在原仓库执行”的半对齐状态;下一刀如果继续推进,应回到 `isolation=remote`、child `plan` lifecycle 和 `PermissionRequest.updatedPermissions` 这些仍缺真实宿主的剩余 gap。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs" "src-tauri/src/commands/aster_agent_cmd/prompt_context.rs"` 通过 - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_maybe_enter_subagent_worktree_remaps_requested_cwd_into_child_worktree --lib -- --nocapture` 通过(`1 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_resolve_subagent_worktree_cwd_mapping_rejects_cross_repo_cwd --lib -- --nocapture` 通过(`1 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_resolve_subagent_session_bootstrap_working_dir_keeps_execution_working_dir --lib -- --nocapture` 通过(`1 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_validate_effective_spawn_isolation_accepts_worktree_and_rejects_unsupported_values --lib -- --nocapture` 通过(`1 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_resolve_missing_subagent_worktree_restore_falls_back_to_original_cwd --lib -- --nocapture` 通过(`1 passed`) - - `cargo test --manifest-path "src-tauri/Cargo.toml" test_resolve_workspace_id_for_working_dir_prefers_longest_ancestor_workspace --lib -- --nocapture` 通过(`1 passed`) - -### 继续推进(CCD-008 / Agent callback-backed `mode` / `isolation` reachability) - -- 在补齐 `worktree + cwd` honest host 后,又顺着 Lime 当前真实入口复核了一次,确认还有一处更贴主链的阻断: - - [`subagent_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs) 虽然已经具备 `mode / isolation / cwd` 的宿主解析与 `worktree` 生命周期。 - - 但 Aster 当前真正暴露给模型的 [`Agent`](../../src-tauri/crates/aster-rust/crates/aster/src/agents/subagent_tool.rs) surface,在 callback-backed 分支的 [`agent.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/agents/agent.rs) 里仍会先把 `mode / isolation` 一刀拒绝。 - - 结果就是:Lime 宿主内部已经能 honest 处理 `worktree + cwd`,但对外 current `Agent` surface 还到不了这条主链,属于“实现存在、入口失真”。 -- 因此这一轮没有再改宿主内核,而是把入口边界收正: - - [`agent.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/agents/agent.rs) 的 `prepare_callback_backed_agent_spawn(...)` 不再提前拒绝 `mode / isolation`。 - - 同时把 `mode / isolation` 纳入 callback-backed path 的触发条件;即使没有 `run_in_background / name / team_name / cwd / tool scope`,只要显式请求了 `mode` 或 `isolation`,也会走真实宿主 callback,而不是误落回前景 foreground-only 分支。 - - [`subagent_tool.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/agents/subagent_tool.rs) 的当前 schema / description 也同步更新:`mode / isolation` 不再继续宣称“当前 runtime 不支持”,而是明确为“callback-backed runtime 会透传给宿主,由宿主决定支持子集”。 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:top-level `Agent` callback-backed current surface 现在终于能真实到达 Lime 宿主的 `mode / isolation / cwd` 主链;`worktree + cwd` 不再只停留在宿主内部实现。 - - `current gap`:`isolation=remote` 仍无 honest host;`mode=plan` 现在会到达宿主,但仍在 [`subagent_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs) 处明确 fail-closed,因为还没有 child-session scoped plan lifecycle。 - - `compat / deprecated / dead`:无新增;本轮没有为了让入口“看起来支持”再加第二套 Agent 壳,只是把当前 public surface 收回到已存在的真实宿主能力。 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 从“宿主内核已经对齐、但 Aster `Agent` 入口还把关键字段挡在外面”的半完成状态,推进到“对外 current surface 终于能 honest 命中 Lime 的 subagent runtime 主链”;下一刀若继续推进,应回到 `mode=plan` 的 child-scoped lifecycle 与 `isolation=remote` 这两个仍缺真实宿主的剩余 gap。 - -### 继续推进(CCD-008 / PermissionRequest.updatedPermissions session setMode current subset) - -- 继续严格对照本地参考实现: - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/permissions/PermissionUpdate.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/permissions/PermissionUpdateSchema.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/hooks/toolPermission/PermissionContext.ts"` - 后确认 Lime 这一刀仍不能假装拥有 Claude Code 那套完整 `ToolPermissionContext + permission rules/directories persistence host`。因此本轮没有把 `updatedPermissions` 整体宣称为 supported,而是只把当前确实有宿主的最小子集收成 `current`: - - 仅支持 `PermissionRequest` hook 返回 `decision=allow` 且 `updatedPermissions` 全量属于 `setMode + destination=session` - - 其它类型继续 fail-closed 回退原生审批流,不执行 hook allow,也不应用 `updatedInput / updatedPermissions` -- [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 现已把 `updatedPermissions` 从“只看 presence 的布尔标记”改成真实解析 supported subset: - - `acceptEdits -> current` - - `dontAsk -> full-access` - - `default -> SessionExecutionRuntimeAccessMode::default_for_session()`,按 Lime 当前 session 默认值落到 `full-access` - - `plan` / `bypassPermissions` 继续显式拒绝 - - `addRules / replaceRules / removeRules / addDirectories / removeDirectories` 与任何 `destination != session` 都继续按 unsupported 处理 -- 同一文件里的 runtime hook 应用链也已补上最小 honest side effect: - - 支持的 `updatedPermissions.setMode(session)` 会在返回 `Allow` 前调用 `persist_session_recent_access_mode(...)` - - 如果 session access mode 持久化失败,本次会回退到原生审批流,而不是继续假装 hook allow 已完整生效 - - `updatedInput` 在 supported subset 下继续保留,不会因为补 side effect 又退回到“能改 mode 就不能改 input”的假取舍 -- 前端同步闭环也已补齐: - - [`agentSessionRefresh.ts`](../../src/components/agent/chat/hooks/agentSessionRefresh.ts) 刷新 detail 后若看到 `execution_runtime.recent_access_mode`,会同步更新当前 `accessMode` 状态并回写 session shadow storage - - [`useAgentSession.ts`](../../src/components/agent/chat/hooks/useAgentSession.ts) 已把这条同步接进现有 `refreshSessionDetail(...)` 主链,因此同一会话里后端刚通过 hook 更新的 session access mode,会在发送结束后的 refresh 里立刻反映到下一条提交,而不必等用户切 topic -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:`PermissionRequest.updatedPermissions` 现在至少已有一条 honest current 子集:`allow + setMode(destination=session)`,并且能真实持久化 session `recent_access_mode`,再回流到当前聊天页的 access mode 主状态 - - `current gap`:rules 类 updates、directories 类 updates、任何 non-session destination、`plan` / `bypassPermissions` 仍无 honest host;本轮没有为了“看起来接近 upstream”去偷偷部分应用 mixed updates - - `compat / deprecated / dead`:无新增;本轮没有把 `PermissionRequest.updatedPermissions` 包成“看起来都 supported,实际只有日志”的 compat 壳 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 里最后一块明显处于“schema 有、hook 可回、但宿主完全不生效”的权限更新断层推进到最小 honest current,避免 Lime 继续停在“hook allow 了,实际 session 权限状态却没变”的假对齐状态;下一刀若继续推进,应优先回到 `isolation=remote`、child-scoped `plan` lifecycle,或在未来真的存在规则/目录 permission host 之后再考虑扩 `updatedPermissions` 子集。 -- 已执行定向校验: - - `rustfmt --edition 2021 "src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs"` 通过 - - `npx vitest run "src/components/agent/chat/hooks/agentSessionRefresh.test.ts"` 通过(`4 passed`) - - `npx vitest run "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx" -t "已有 recent_access_mode 时发送消息应沿用恢复后的正式权限策略"` 通过(`1 passed, 142 skipped`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/Cargo.toml" permission_request_project_hooks --lib -- --nocapture` 通过(`6 passed`) - -### 继续推进(CCD-008 / managed-session peer messaging current) - -- 继续严格对照本地参考实现: - - `"/Users/coso/Documents/dev/js/claudecode/src/hooks/useInboxPoller.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/tools/SendMessageTool/SendMessageTool.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/constants/xml.ts"` - 后确认上一轮把 `teammate mode=plan` 宿主生命周期接回 current 后,剩下最贴主链的断层不该再停在“只有 plan_approval_request 能到 lead,普通 teammate 消息与 uds 本机会话消息仍卡死在 callback 层”: - - upstream 对 lead / 本机会话 peer 的普通消息并不是另一套假的 host,而是包装成 `` / `` 后继续走目标 session 的正常收件主链。 - - Lime 之前的真实问题不是缺少第三套 transport,而是 [`agent_runtime_send_subagent_input_internal`](../../src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs) 看到 non-subagent target 就直接拒绝,导致 [`agent_control.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/tools/agent_control.rs) 已经能构造的 `uds:` peer surface 和 `team-lead` 路由始终停在“工具层看起来能发、宿主层实际打不进去”的假完成状态。 -- 因此这一轮没有去补 mailbox compat,而是把 non-subagent plain/xml 消息 honest 接回 Lime 现有 managed-session queue: - - [`subagent_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs) 新增 `submit_runtime_message_to_managed_session(...)`,让 non-subagent target 在非结构化控制消息场景下也走 `submit_runtime_turn(queue_if_busy=true)`,事件名收口到现有 `agent_stream`,不再只允许 `plan_approval_request` 这一个特例。 - - 同文件继续保留 control-message 治理边界:`plan_approval_request` 仍走自动审批控制链;`shutdown_response` 与误投到 managed session 的 `plan_approval_response` 继续显式 fail-closed,而不是被偷偷降级成普通聊天文本。 - - [`agent_control.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/tools/agent_control.rs) 现在会把“teammate 发给 team lead 的普通文本/普通 JSON 文本化消息”包装成 upstream 同类 `...`,只对 lead 目标生效,不影响现有 subagent->subagent 文本投递和结构化 control message。 - - 这样 `uds:` 本机会话 peer 的 `` 包络终于也不再停留在 callback 单测里,而是真能投递到 Lime 的 managed session runtime。 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:`SendMessage` 现在已具备两条 honest non-subagent 主链:`uds:` 本机会话 peer 文本消息,以及 teammate -> team lead 的普通消息;两者都进入目标 managed session 的正常 runtime queue,而不是停在 fake callback surface。 - - `current gap`:`bridge:` remote peer 仍无 host;lead-side `shutdown_response` 仍缺上游 inbox / graceful shutdown lifecycle,继续 fail-closed;更完整的 teammate-message UI 呈现也还没收成单独视图。 - - `compat / deprecated / dead`:无新增;本轮没有为了“看起来和 upstream 一样”再补一层 mailbox 文件或本地 bridge 兼容层,而是复用 Lime 现有 session queue 事实源。 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 从“teammate plan 生命周期已回正,但普通协作消息仍被宿主挡死”的半完成状态,推进到“本地 team/peer messaging 至少已经走进真实 managed-session 主路径”;下一刀若继续推进,应优先判断 lead-side `shutdown_response` 与 `bridge:` remote peer 是否存在 honest host,而不是回头包更多假的传输层。 - -### 继续推进(CCD-008 / lead-side shutdown response current subset) - -- 继续严格对照本地参考实现: - - `"/Users/coso/Documents/dev/js/claudecode/src/tools/SendMessageTool/SendMessageTool.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/hooks/useInboxPoller.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/teammateMailbox.ts"` - 后确认上一刀把普通 teammate / `uds:` peer 文本消息接回 managed-session queue 后,最贴主链的剩余断层其实不是 `bridge:`,而是 `shutdown_response` 仍停留在“工具面能构造、lead side 明确拒收”的假支持: - - upstream 的 `shutdown_response` 并不会原样回写给 lead;它会在发送侧翻译成 `shutdown_approved / shutdown_rejected`,携带 `from`,由 lead inbox poller 一边做 teammate lifecycle side effect,一边把结果继续回显给 lead。 - - Lime 之前之所以继续 fail-closed,不是因为 close 能力不存在,而是 managed-session lead 缺少这层 `sender + lifecycle + queue replay` 的 current 收件路径。 -- 因此这一轮没有补 mailbox compat,也没有伪造 remote bridge,而是把 lead-side `shutdown_response` 收成最小 honest current subset: - - [`agent_control.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/tools/agent_control.rs) 现在会把 `shutdown_response` 在发送侧翻译成 upstream 同类 `shutdown_approved / shutdown_rejected` payload,并补上 `from` 与 `timestamp`;不再把缺失 sender 的裸 `shutdown_response` JSON 直接丢给 lead。 - - [`subagent_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs) 新增 lead-side `shutdown_approved / shutdown_rejected` 控制消息解析;其中 `shutdown_approved` 会复用现有 `agent_runtime_close_subagent_internal(...)` 关闭对应 teammate,`shutdown_rejected` 则保留 teammate 生命周期不变。 - - 同文件还会把处理后的 shutdown 控制消息包装成 `...` 再投递回 lead managed session 的正常 runtime queue,这样 lead 既能拿到真实 lifecycle side effect,也能像 upstream 一样在会话里看到 teammate 的审批结果,而不是只发生隐式后台关闭。 - - legacy 形态的裸 `shutdown_response` 继续在 managed-session lead 侧 fail-closed;本轮没有为了迁就旧 payload 再长一层兼容解析。 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:本地 team runtime 现在除了普通 teammate / `uds:` peer 文本消息外,也已经具备 lead-side `shutdown_response` 的最小 honest current subset:发送侧翻译、lead-side close、以及结果回显都走现有 runtime queue / subagent close 主链。 - - `current gap`:`bridge:` remote peer 仍无 honest host;`shutdown_request` 本身仍只是 structured prompt 主链,不是 upstream mailbox/pane backend 的完整宿主实现;更完整的 teammate-message 专用 UI 仍未单独收口。 - - `compat / deprecated / dead`:无新增;本轮没有引入 mailbox 文件层、pane backend compat 或第二套 shutdown transport。 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 从“普通协作消息已 current,但 shutdown 协作仍是假支持”的状态,推进到“至少本地 team runtime 的 shutdown approval 主链也已经回到 honest host”;下一刀若继续推进,应优先判断 `bridge:` remote peer 是否存在真实宿主面,而不是继续扩张本地 compat。 -- 已执行定向校验: - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/Cargo.toml" test_parse_runtime_control_message_accepts_shutdown_approved_shape --lib -- --nocapture` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/Cargo.toml" test_reject_unsupported_managed_session_control_message --lib -- --nocapture` 通过(`2 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target-aster-verify" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" send_message_ --lib -- --nocapture` 通过(`16 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target-aster-verify" cargo test --manifest-path "src-tauri/crates/aster-rust/crates/aster/Cargo.toml" test_exit_plan_mode_teammate_submits_plan_approval_request --lib -- --nocapture` 通过(`1 passed`) - -### 继续推进(CCD-008 / managed-session peer message display current subset) - -- 继续严格对照本地参考实现: - - `"/Users/coso/Documents/dev/js/claudecode/src/components/messages/UserTeammateMessage.tsx"` - - `"/Users/coso/Documents/dev/js/claudecode/src/components/messages/PlanApprovalMessage.tsx"` - - `"/Users/coso/Documents/dev/js/claudecode/src/components/messages/ShutdownMessage.tsx"` - 后确认上一刀虽然已经把 `` / `` honest 接回了 Lime managed-session queue,但前端聊天显示仍停留在“把 XML 包络和 shutdown JSON 原样吐给用户”的半成品: - - upstream 不会把 teammate / cross-session 包络直接裸露给用户;它至少会把 envelope 解析成可读的 teammate message 视图,并把 `shutdown_approved / shutdown_rejected / plan_approval_*` 这类已知结构化消息折叠成正常文案。 - - Lime 当前缺的也不是新的 pane backend,而是聊天显示层没有对已经进入 current 的 runtime peer envelope 做最小收口,导致主链明明已 honest 到达队列,界面却还像在看宿主协议原文。 -- 因此这一轮没有补新的消息面板或 mailbox compat,而是先把现有聊天气泡收成最小可读 current: - - [`runtimePeerMessageDisplay.ts`](../../src/components/agent/chat/utils/runtimePeerMessageDisplay.ts) 新增 runtime peer envelope 文本格式化器,会把 `` / `` 解析成可读标题,并把 `shutdown_* / plan_approval_* / task_assignment / task_completed / idle_notification` 这些当前已知结构化 payload 转成用户能直接理解的正文。 - - [`internalImagePlaceholder.ts`](../../src/components/agent/chat/utils/internalImagePlaceholder.ts) 现已在现有消息清洗主链里复用这层格式化,因此无论消息最终走 assistant `StreamingRenderer`,还是 user `MarkdownRenderer`,都不会再把 XML 包络直接暴露给聊天区。 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:managed-session 当前已不仅能投递 teammate / `uds:` peer 消息,也能在现有聊天气泡里把这些 envelope 以可读文案展示出来;lead-side `shutdown_response` 的 current subset 不再退化成“界面里只剩一坨 XML + JSON”。 - - `current gap`:`bridge:` remote peer 仍无 honest host;`shutdown_request` 仍不是 upstream mailbox/pane backend 的完整宿主;更完整的 teammate-message 专用 UI 仍未单独收口成独立视图。 - - `compat / deprecated / dead`:无新增;本轮没有为了追求外观接近 upstream 再发明第二套消息模型或独立 pane backend,只复用现有聊天显示主链做 envelope 格式化。 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 从“runtime host 已接通,但用户看到的仍是协议原文”的半交付状态,推进到“已进入 current 的 peer/shutdown 协作消息至少在现有聊天主路径里可读可用”;下一刀若继续推进,应优先回到 `bridge:` honest host 判定或独立 teammate-message 视图是否值得单独收口,而不是回头补假的 transport。 - -### 继续推进(CCD-008 / runtime peer message card current subset) - -- 继续严格对照本地参考实现: - - `"/Users/coso/Documents/dev/js/claudecode/src/components/messages/UserTeammateMessage.tsx"` - - `"/Users/coso/Documents/dev/js/claudecode/src/components/messages/PlanApprovalMessage.tsx"` - - `"/Users/coso/Documents/dev/js/claudecode/src/components/messages/ShutdownMessage.tsx"` - 后确认上一刀虽然已经把 `` / `` 从协议原文收成“可读文案”,但和 upstream 相比仍差最后一层真正的消息视图: - - upstream 不是单纯把 peer envelope 改写成字符串,而是会根据 `plan_approval_* / shutdown_* / task_assignment / task_completed` 的不同语义渲染成专门 teammate message 组件。 - - Lime 当前若继续停在“纯文本摘要”,主路径虽然能读,但协作状态层级仍然和普通正文混在一起,不利于把 current 的 teammate runtime surface 真正收成可交付聊天体验。 -- 因此这一轮没有发明新的 pane/backend,也没有把 peer message 另起一套 store,而是继续在现有聊天气泡主路径收一刀: - - [`runtimePeerMessageDisplay.ts`](../../src/components/agent/chat/utils/runtimePeerMessageDisplay.ts) 现在除了保留纯文本摘要能力,也补出了 runtime peer envelope 的结构化解析模型,可按原始顺序识别多条 `` / ``,并区分 `plan_approval_* / shutdown_* / task_assignment / task_completed / idle_notification / teammate_terminated` 等当前已知 payload。 - - [`RuntimePeerMessageCards.tsx`](../../src/components/agent/chat/components/RuntimePeerMessageCards.tsx) 新增聊天主路径的 peer message 卡片视图,按不同 payload 给予不同层级和状态色;计划审批、结束任务、任务分配/完成不再只是一段普通字符串。 - - [`StreamingRenderer.tsx`](../../src/components/agent/chat/components/StreamingRenderer.tsx) 现已在 assistant 正文主路径上优先识别“纯 peer envelope 消息”,直接渲染 peer cards;既保留原有 process/timeline 链路,也不再把这类 runtime 协作消息降级回普通 markdown。 - - [`MessageList.tsx`](../../src/components/agent/chat/components/MessageList.tsx) 现已在 user 正文分支做同样收口,因此无论消息最终落在 assistant 还是 user 气泡,只要原始正文是纯 peer envelope,都会沿用同一套卡片视图,而 preview/sidebar 仍继续复用文本摘要,不额外发明第二套预览协议。 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:managed-session current 路径里的 teammate / cross-session / shutdown / plan approval 消息,已经从“协议原文”进到“可读摘要”再进到“专门消息卡片”;现有聊天主路径已经具备最小 honest teammate message view。 - - `current gap`:`bridge:` remote peer 仍无 honest host;更完整的 teammate mailbox / pane backend 仍不存在;timeline / inbox 之外的更细粒度 peer 状态聚合仍未像 upstream 那样单独抽成更完整视图。 - - `compat / deprecated / dead`:无新增;本轮没有为了对齐 upstream 继续扩张 transport、mailbox 文件或第二套消息列表,只在现有气泡主路径补真实视图层。 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 从“聊天里能看懂 peer 消息”继续推进到“聊天里已经能把 peer 协作状态按类型分层显示”;下一刀若继续推进,应优先回到 `bridge:` honest host 或更完整 teammate-message 独立视图,而不是回头再堆字符串兼容。 -- 已执行定向校验: - - `npx vitest run "src/components/agent/chat/utils/runtimePeerMessageDisplay.test.ts" "src/components/agent/chat/components/RuntimePeerMessageCards.test.tsx" "src/components/agent/chat/components/StreamingRenderer.test.tsx" "src/components/agent/chat/components/MessageList.test.tsx"` 通过(`4 files, 102 tests passed`) - -### 继续推进(CCD-008 / runtime peer lifecycle-noise 收口) - -- 继续严格对照本地参考实现: - - `"/Users/coso/Documents/dev/js/claudecode/src/components/messages/UserTeammateMessage.tsx"` - - `"/Users/coso/Documents/dev/js/claudecode/src/components/messages/AttachmentMessage.tsx"` - - `"/Users/coso/Documents/dev/js/claudecode/src/components/messages/TaskAssignmentMessage.tsx"` - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/teammateMailbox.ts"` - 后确认上一刀虽然已经把 managed-session peer message 收成专门卡片,但与 upstream 仍有两处 current 语义差: - - upstream 会静默 `shutdown_approved`、`idle_notification`、`teammate_terminated`,不把这些 lifecycle/noise 消息继续暴露在主聊天里。 - - upstream `task_assignment` 明确保留 `assignedBy`,而 Lime 卡片之前只展示 `sender + taskId/subject/description`,丢掉了真正的任务分配者信息。 -- 因此这一轮没有继续给 peer message 叠新 pane,也没有为了“看起来兼容”补 mailbox 伪层,而是直接在现有 current 解析主链收口: - - [`runtimePeerMessageDisplay.ts`](../../src/components/agent/chat/utils/runtimePeerMessageDisplay.ts) 现已补 `task_assignment.assignedBy` 解析,并新增统一的 runtime peer envelope 静默规则;`parseRuntimePeerMessageEnvelopes(...)`、`isPureRuntimePeerMessageText(...)`、`formatRuntimePeerMessageText(...)` 都已共享同一套 `shutdown_approved / idle_notification / teammate_terminated` 过滤语义,不再让卡片、preview、内部文本清洗各自分叉判断。 - - [`RuntimePeerMessageCards.tsx`](../../src/components/agent/chat/components/RuntimePeerMessageCards.tsx) 已删除这些静默 lifecycle 消息对应的显示分支,避免 current UI 还保留不该露出的死路径;同时 `task_assignment` 卡片现会显式展示 `assignedBy`。 - - 由于 [`internalImagePlaceholder.ts`](../../src/components/agent/chat/utils/internalImagePlaceholder.ts) 继续复用 `formatRuntimePeerMessageText(...)`,这次收口不只影响 peer cards,也同步影响聊天摘要、preview 与内部文本清洗入口,保证不会在别的 current 出口重新漏出 lifecycle/noise 原文。 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:Lime 当前 managed-session peer message 主路径,已经不再把 upstream 会静默的 lifecycle/noise 消息暴露给主聊天;`task_assignment` 也已带上真实 `assignedBy`,而不是只剩 envelope sender。 - - `current gap`:`bridge:` remote peer 仍无 honest host;更完整的 teammate inbox / pane backend 仍不存在;更丰富的 peer lifecycle 聚合状态仍未像 upstream 那样抽成单独面板。 - - `compat / deprecated / dead`:无新增;本轮没有为了迁就旧面继续保留“可显示但不该显示”的 lifecycle UI 分支,也没有为 `bridge:` 缺口补假的 transport 或 fake host。 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 从“peer message 已有卡片,但主聊天里仍混入 upstream 会静默的噪音协议消息”的半收口状态,推进到“managed-session current surface 的显示语义也已对齐到 upstream 的最小 honest subset”;下一刀若继续推进,应优先回到 `bridge:` honest host / remote peer 宿主判定,而不是回头再修补显示层兼容。 -- 已执行校验: - - `npx vitest run "src/components/agent/chat/utils/runtimePeerMessageDisplay.test.ts" "src/components/agent/chat/components/RuntimePeerMessageCards.test.tsx" "src/components/agent/chat/components/StreamingRenderer.test.tsx" "src/components/agent/chat/components/MessageList.test.tsx"` 通过(`4 files, 106 tests passed`) - - 宿主侧 `subagent_runtime` 的 parser / gate 复核已通过;更大范围的 `verify:local` / `verify:gui-smoke` 本轮未复核,不再写成已通过 - -### 继续推进(CCD-008 / peer address 事实源收口) - -- 继续严格对照本地参考实现: - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/peerAddress.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/tools/SendMessageTool/SendMessageTool.ts"` - 后确认 Lime 当前真正需要的不是再“多支持一个前缀”,而是先把 peer address 的 current / unsupported 事实源说实话并收成一处: - - upstream 会把 `uds:` / `bridge:` 的地址语法解析单独抽出来,再根据真实 host 能力决定是否可投递;语法识别不等于 transport 已存在。 - - Lime 当前已经把 synthetic `uds:` 本地跨 session 投递收进 current,但 `bridge:` 仍没有 upstream 那种 remote peer host / session ingress;因此继续保留 “`bridge:` unsupported” 才是 honest host。 - - 之前 [`agent_control.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/tools/agent_control.rs) 的 `send_message_unsupported_peer_result(...)` 还残留 `Uds => unsupported` 死分支,已经和现状漂移。 -- 因此这一轮没有伪造 remote peer transport,也没有继续包 compat,而是做最小事实源收口: - - 新增 [`peer_address_surface.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/tools/peer_address_surface.rs),把 `uds:` / `bridge:` 解析、`SendMessage` / `ListPeers` 描述文案,以及 `bridge:` unsupported 原因统一收成同一处;当前口径固定为:`uds:` = current local cross-session peer,`bridge:` = unsupported gap,原因是缺 remote peer host / session ingress。 - - [`agent_control.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/tools/agent_control.rs) 已改为只在 `bridge:` 上走受控失败,并删除过时的 `Uds => unsupported` 分支;`unsupportedTargetScheme` 也复用同一事实源,不再各处手写。 - - [`team_tools.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/tools/team_tools.rs) 现在复用同一套 peer surface 文案,因此 `ListPeers` 与 `SendMessage` 对 `uds:` / `bridge:` 的 current / unsupported 说明不会再各自漂移。 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:synthetic `uds:` 仍是 Lime 当前唯一 honest 的 cross-session local peer address surface,可被 `ListPeers.send_to` 暴露并由 `SendMessage` 直接投递。 - - `current gap`:`bridge:` remote peer 仍无 honest host;更完整的 teammate inbox / pane backend 仍不存在;更丰富的 peer lifecycle 聚合状态仍未像 upstream 那样抽成单独面板。 - - `compat / deprecated / dead`:无新增;本轮没有为了“兼容 upstream 表面”假装支持 `bridge:`,也没有继续保留已经不真实的 `uds:` unsupported 文案分支。 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 从“peer address 能工作但事实源文案仍会自相矛盾”的状态,推进到“当前已支持与明确未支持的 peer surface 都由同一事实源定义”;下一刀若继续推进,应优先回到 `bridge:` honest host 判定或更完整 teammate-message 独立视图,而不是再补假的 remote transport。 - -## 2026-04-22 - -### 继续推进(CCD-008 / SessionStart resume honest host 收口) - -- 继续严格对照本地参考实现: - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/conversationRecovery.ts"` - - `"/Users/coso/Documents/dev/js/claudecode/src/utils/sessionStart.ts"` - 后确认 Lime 这一刀不该再新开第二套 `resume` 命令,而应把 Claude Code 的 `processSessionStartHooks('resume', { sessionId })` 语义收进现有 `agent_runtime_get_session` current 主链: - - 只有“继续最近会话 / 自动恢复 / 初始会话导航 / hydrate 恢复 / sidebar resume 入口”这类真正的恢复路径,才显式透传 `resumeSessionStartHooks=true` - - 普通 `refreshSessionDetail(...)`、`final_done` 后刷新、`stopSending` 后普通刷新、以及单纯 `getSession(sessionId)` 仍保持非 resume 语义,不把日常 detail refresh 伪装成 lifecycle host -- 因此这一轮没有新增 `agent_runtime_resume_session` 之类的平级协议,而是把恢复语义最小化补进既有命令面: - - 前端 [`types.ts`](../../src/lib/api/agentRuntime/types.ts)、[`sessionClient.ts`](../../src/lib/api/agentRuntime/sessionClient.ts)、[`agentRuntimeAdapter.ts`](../../src/components/agent/chat/hooks/agentRuntimeAdapter.ts) 新增并透传 `resumeSessionStartHooks?: boolean` - - [`useAgentSession.ts`](../../src/components/agent/chat/hooks/useAgentSession.ts)、[`useWorkspaceInitialSessionNavigation.ts`](../../src/components/agent/chat/workspace/useWorkspaceInitialSessionNavigation.ts)、[`useWorkspaceTopicSwitch.ts`](../../src/components/agent/chat/workspace/useWorkspaceTopicSwitch.ts)、[`useWorkspaceProjectSelection.ts`](../../src/components/agent/chat/hooks/useWorkspaceProjectSelection.ts)、[`AgentChatWorkspace.tsx`](../../src/components/agent/chat/AgentChatWorkspace.tsx) 现在只在真实 resume 路径上传这个标记 - - Rust [`runtime_api.rs`](../../src-tauri/src/commands/aster_agent_cmd/command_api/runtime_api.rs) 的 `agent_runtime_get_session(...)` 增加可选参数 `resume_session_start_hooks: Option`;当且仅当该标记为 `true` 时,才会在成功取回 detail 后执行 `run_runtime_session_start_project_hooks_for_session_with_runtime(..., SessionSource::Resume)` - - [`runtime_project_hooks.rs`](../../src-tauri/src/commands/aster_agent_cmd/runtime_project_hooks.rs) 已把 `SessionSource::Resume` 从 unsupported warning 中移除,只保留 `Clear` 继续 fail-closed;[`agent_sessions.rs`](../../src-tauri/src/dev_bridge/dispatcher/agent_sessions.rs)、[`agentRuntimeCommandSchema.json`](../../src/lib/governance/agentRuntimeCommandSchema.json) 与 [`commandManifest.generated.ts`](../../src/lib/api/agentRuntime/commandManifest.generated.ts) 也已同步 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:Lime 现在已有一条 honest 的 `SessionStart(resume)` 宿主入口,而且仍然收敛在 `agent_runtime_get_session` 这一条 current 命令主链上;恢复语义由显式调用方决定,不再靠模糊的“只要拿 detail 就算 resume” - - `current gap`:`SessionStart(clear)` 仍无 honest host;普通 refresh 与 queue resume 也仍不能冒充 lifecycle resume - - `compat / deprecated / dead`:无新增;本轮没有为了对齐 upstream 再补第二套 session resume 协议,也没有把普通 detail refresh 接回 compat 壳 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 里最后一块此前一直被明确保留为 gap 的 `SessionStart(resume)`,推进成 Lime 当前真实存在、且不会误伤普通刷新路径的 honest current subset;下一刀若继续推进,应优先回到 `SessionEnd(clear / logout / prompt_input_exit)` 或 `SessionStart(clear)` 是否存在真实宿主,而不是再把更多 refresh 动作包成伪生命周期。 -- 已执行校验: - - `cargo fetch --manifest-path "src-tauri/Cargo.toml"` 执行,用于修复本机 `~/.cargo/registry/src` 缺失 `half-2.7.1`、`aws-lc-sys-0.37.1` 源文件导致的环境级假失败 - - `cargo test --manifest-path "src-tauri/Cargo.toml" runtime_project_hooks::tests::build_runtime_session_start_unsupported_warning_message_should_allow_current_sources -- --nocapture` 通过 - - `cargo test --manifest-path "src-tauri/Cargo.toml" runtime_project_hooks::tests::run_runtime_session_start_project_hooks_for_session_should_run_resume_source -- --nocapture` 通过 - - `npx vitest run "src/components/agent/chat/hooks/useAsterAgentChat.test.tsx"` 通过(`143 passed`);已同步恢复路径与普通刷新路径对 `mockGetAgentRuntimeSession` 的一参/二参断言 - - `npm run verify:local` 未通过,但失败点是工作区既有无关改动:[`sceneapp.ts`](../../src/lib/api/sceneapp.ts) 里 `SceneAppExecutionPlan`、`SceneAppRuntimeAdapterPlan` 两个未使用导入触发 `eslint`,并非本轮 `resume` 改动回归 - - `npm run verify:gui-smoke` 已成功把 headless Tauri、DevBridge、`workspace-ready`、`browser-runtime`、`site-adapters` 与 `agent-service-skill-entry` 拉起并跑通;最终失败在 `smoke:agent-runtime-tool-surface` 的 [`useWorkspaceConversationSceneRuntime.test.ts`](../../src/components/agent/chat/workspace/useWorkspaceConversationSceneRuntime.test.ts) 上,报的是 `react-syntax-highlighter` / `refractor` 的 ESM-CJS 兼容错误,日志显示脚本运行时 Node 为 `v18.20.2`,同样不属于本轮 `resume` 主链回归 - -### 继续推进(CCD-008 / teammate plan team-context reachability) - -- 继续严格对照本地参考实现: - - `"/Users/coso/Documents/dev/js/claudecode/src/tools/AgentTool/AgentTool.tsx"` - 后确认 Lime 当前 `mode=plan` 剩余缺口不在 `plan_mode_tool.rs` 本身,而在 callback-backed `Agent -> subagent_runtime` 这段入口边界: - - upstream 会先做 `resolveTeamName(input.team_name || appState.teamContext?.teamName)`,只要当前已有 team context,`name + mode=plan` 即使没显式传 `team_name`,仍会走 teammate spawn,并进入现成的 child-scoped plan lifecycle。 - - Lime 之前虽然在 [`agent_control.rs`](../../src-tauri/crates/aster-rust/crates/aster/src/tools/agent_control.rs) 文案上宣称“未传 `team_name` 时沿用当前 team 上下文”,但 [`subagent_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs) 实际仍把 teammate / plan host 锁死在“必须显式 `team_name + name`”这一层,导致 lead session 里最贴主链的 `name + mode=plan` 仍会在宿主前门被挡掉。 -- 因此这一轮没有发明第二套 compat 参数,也没有把 `plan` 泛化给普通 subagent,而是只把已有 honest host 接通: - - [`subagent_runtime.rs`](../../src-tauri/src/commands/aster_agent_cmd/subagent_runtime.rs) 新增 `resolve_effective_teammate_spawn_request(...)`,会在父 session 已有 lead-side team context 时,从当前 team 自动补齐有效 `team_name`;显式 `team_name` 仍会校验当前 lead team 是否匹配。 - - 同文件的 `validate_spawn_request_surface(...)` 不再把 `name + mode=plan` 提前一刀拒绝,而是允许这类请求进入宿主,再由实际 team context / lead 身份做 fail-closed 判定;无 team context、non-lead session、以及 `team_name`/`name` 组合不合法的情况仍继续明确拒绝。 - - spawn 成功后写入的 child metadata 现在会持久化“解析后的有效 `team_name`”,避免 tool 入参为空但 session 元数据仍丢失当前 team 事实源。 - - [`prompt_context.rs`](../../src-tauri/src/commands/aster_agent_cmd/prompt_context.rs) 也同步收口:明确 `team_name` 可在已有 lead-side team context 时省略,`mode=plan` 当前只支持 team teammate 子集,不再继续把这条已经接通的 current surface 描述成全量 unsupported。 -- 这一步后的 `CCD-008` 边界继续收紧为: - - `current`:top-level lead session 现在已经能按 upstream 同类语义,用 `name + mode=plan` 命中现有 teammate plan lifecycle;如果当前 team context 已存在,即使调用方没显式传 `team_name`,也会沿用当前 team。 - - `current gap`:没有 team context 的普通 subagent 仍不能假装支持 `mode=plan`;non-lead / teammate session 也仍不能继续派生 teammate;`isolation=remote`、`bridge:` remote peer、`PermissionRequest.updatedPermissions` 的 rules/directories/non-session destination 依旧没有 honest host。 - - `compat / deprecated / dead`:无新增;本轮没有为了“看起来支持 plan”继续扩非 team child 的假 lifecycle,也没有再加前端兜底把错误 team surface 掩过去。 -- 这一步服务路线图主目标的关系是:把 `CCD-008` 从“子 session plan lifecycle 明明已在宿主内部存在,但最常见的 lead/team 调用入口仍到不了”的半成品,推进到“当前真正有宿主的 `plan` 子集已经可达”;下一刀若继续推进,应优先回到 `isolation=remote` 或只在未来确实出现新的 child permission / lifecycle host 时再扩 `plan` 边界。 -- 已执行定向校验: - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/Cargo.toml" test_resolve_effective_teammate_spawn_request_ --lib -- --nocapture` 通过(`3 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/Cargo.toml" test_resolve_spawn_request_access_mode_prefers_supported_mode_override --lib -- --nocapture` 通过(`1 passed`) - - `env CARGO_TARGET_DIR="/Users/coso/Documents/dev/ai/aiclientproxy/lime/.codex-target" cargo test --manifest-path "src-tauri/Cargo.toml" test_validate_spawn_request_surface_accepts_supported_modes_and_rejects_unsupported_values --lib -- --nocapture` 通过(`1 passed`) diff --git a/docs/knowledge/skills/personal-ip-knowledge-builder/SKILL.md b/docs/knowledge/skills/personal-ip-knowledge-builder/SKILL.md new file mode 100644 index 000000000..79bc342ce --- /dev/null +++ b/docs/knowledge/skills/personal-ip-knowledge-builder/SKILL.md @@ -0,0 +1,137 @@ +--- +name: personal-ip-knowledge-builder +description: 将访谈稿、聊天记录、简历、公开内容、业务资料、案例和既有 DOCX/Markdown 文档,提炼成可被 AI 长期调用的个人 IP 知识库。适用于用户要求“生成个人知识库”“整理成个人 IP 成品知识库”“为创始人/专家/讲师/主播/顾问建立AI知识库”“把资料变成个人IP底层提示词/写作风格库/故事素材库/话术库”的场景。 +license: Apache-2.0 +compatibility: + agentKnowledge: ">=0.6.0" +metadata: + Lime_skill_bundle_version: "1.0.0" + Lime_knowledge_builder: "true" + Lime_knowledge_pack_type: "personal-profile" + Lime_knowledge_template: "personal-ip" + Lime_knowledge_family: "persona" + Lime_agent_knowledge_profile: "document-first" + Lime_agent_knowledge_runtime_mode: "persona" +--- + +# 个人 IP 知识库生成器 + +## 核心目标 + +把零散资料编译成一份结构化 Markdown 知识库,让后续 AI 能稳定调用这个人的事实、故事、观点、风格和边界,而不是每次临时总结。 + +默认输出中文;除非用户明确要求其他语言。 + +## 与 Agent Knowledge 的分工 + +本 Skill 只负责“怎么生产和维护知识”: + +- 读取来源资料、模板、访谈问题和质量检查表。 +- 生成或更新个人 IP 成品文档。 +- 标记缺失事实、冲突事实和待用户确认的信息。 +- 返回整理记录、质量诊断和 provenance 建议。 + +Agent Knowledge 负责“知识产物长什么样、如何安全进入上下文”: + +- `KNOWLEDGE.md` 保存 pack metadata、`profile: document-first`、`runtime.mode: persona`。 +- `documents/.md` 保存本 Skill 生成的主文档。 +- `runs/compile-*.json` 记录本次 Builder Skill 输入、输出、版本和诊断。 +- 运行时 Resolver 只消费 KnowledgePack,不在回答用户问题时执行本 Skill。 + +## 工作流 + +1. 先盘点输入资料:访谈、简历、聊天记录、文章、案例、产品服务、历史文案、DOCX/Markdown。 +2. 如果输入是 DOCX,优先使用 `scripts/docx_to_markdown.py` 转成 Markdown 草稿。 +3. 读取 `references/personal-ip-template.md`,按固定章节生成知识库。 +4. 读取 `references/interview-questions.md`,识别缺失的高价值信息。 +5. 缺少关键事实时,先问用户补齐;如果用户要求先生成,则用 `待补充` 标注,不要编造。 +6. 提炼事实、故事、案例、方法论、价值观、表达风格、金句、可引用素材和禁忌边界。 +7. 生成完整 Markdown,结尾必须包含“智能体应用指南”。 +8. 用 `references/quality-checklist.md` 自检,必要时补一节“待补充信息清单”。 + +## Lime Runtime Binding 契约 + +当 Lime 通过 `knowledge_compile_pack` 调用本 Skill 时,输入输出必须保持下面的最小契约。 + +### 输入 + +```text +packName: <当前知识包名> +packType: personal-profile +profile: document-first +runtime.mode: persona +sources[]: sources/ 下的来源文件摘要和相对路径 +metadata.primaryDocument: documents/.md +``` + +### 输出 + +```text +primaryDocument: + path: documents/.md + content: <按 references/personal-ip-template.md 生成的完整 Markdown> +status: draft | needs-review | ready | disputed +missingFacts[]: <待补充信息> +warnings[]: <质量或冲突提醒> +provenance: + kind: agent-skill + name: personal-ip-knowledge-builder + version: 1.0.0 +``` + +固定规则: + +1. 不输出独立于 KnowledgePack 的新目录结构;`documents/.md` 是主文档唯一写回目标。 +2. 不直接改写 `KNOWLEDGE.md`;由 Lime 写入 `metadata.producedBy`、`runtime.mode` 和状态。 +3. 不把模板复制进 Lime 代码;模板、访谈问题和质量检查表继续留在本 Skill 的 `references/`。 +4. 不在运行时回答阶段执行;仅在用户导入、重新整理或维护 pack 时调用。 + +## 输出规则 + +- 不写成简历,也不写成宣传软文;要写成 AI 可调用的底层知识库。 +- 区分事实、观点、推断和待补充信息。 +- 保留真实语气,不要把人物包装成虚假的“成功学大师”。 +- 尽量使用具体案例、数据、原话、场景和转折点。 +- 每个章节都要有清晰标题,适合长期维护。 +- 结尾必须包含:使用说明、AI 写作风格指南、核心价值观关键词、可引用故事素材、禁忌与边界。 + +## 推荐产物结构 + +在 Agent Knowledge v0.6.0 / Lime 中,优先写回: + +```text +/ + KNOWLEDGE.md # 由 Lime 维护 metadata + documents/.md # 本 Skill 生成的主文档 + runs/compile-*.json # 由 Lime 记录本次整理 provenance +``` + +如果用户在普通对话中只要求一份独立文档,也可以输出单一 Markdown 作为临时交付;进入 Lime KnowledgePack 时必须回到上述 `document-first` 结构。 + +不再默认拆成: + +```text +[person-id]-personal-ip/ + knowledge.md + facts.md + voice.md + stories.md + boundaries.md +``` + +## 何时读取资源 + +- 需要章节骨架时,读取 `references/personal-ip-template.md`。 +- 资料不足或要做访谈表时,读取 `references/interview-questions.md`。 +- 输出前做质量检查时,读取 `references/quality-checklist.md`。 +- 用户只要空白模板时,可复制 `assets/personal-ip-knowledge-skeleton.md`。 + +## DOCX 转 Markdown + +如果需要先转换 DOCX: + +```bash +python3 scripts/docx_to_markdown.py 输入.docx 输出.md +``` + +转换后再进行知识提炼。脚本只负责格式转换,不负责事实提炼。 diff --git a/docs/knowledge/skills/personal-ip-knowledge-builder/agents/openai.yaml b/docs/knowledge/skills/personal-ip-knowledge-builder/agents/openai.yaml new file mode 100644 index 000000000..743a04ff2 --- /dev/null +++ b/docs/knowledge/skills/personal-ip-knowledge-builder/agents/openai.yaml @@ -0,0 +1,4 @@ +interface: + display_name: "个人IP知识库生成器" + short_description: "把访谈、资料和案例提炼成可被AI长期调用的个人IP知识库。" + default_prompt: "请基于我提供的资料,生成一份结构化、可长期调用的个人IP知识库。" diff --git a/docs/knowledge/skills/personal-ip-knowledge-builder/assets/personal-ip-knowledge-skeleton.md b/docs/knowledge/skills/personal-ip-knowledge-builder/assets/personal-ip-knowledge-skeleton.md new file mode 100644 index 000000000..2de545ffd --- /dev/null +++ b/docs/knowledge/skills/personal-ip-knowledge-builder/assets/personal-ip-knowledge-skeleton.md @@ -0,0 +1,37 @@ +# [姓名] 个人 IP 知识库 + +## 第一章 人物档案与基本信息 + +## 第二章 个人简介与核心定位 + +## 第三章 成长背景与关键经历 + +## 第四章 职业经历与业务发展 + +## 第五章 代表案例与实战成绩 + +## 第六章 核心方法论与行业洞察 + +## 第七章 价值观与人生哲学 + +## 第八章 性格特质与表达风格 + +## 第九章 金句语录与思想精华 + +## 第十章 核心能力与竞争优势 + +## 第十一章 未来愿景与发展规划 + +# 附录一 多场景介绍话术 + +# 附录二 智能体应用指南 + +## 一、知识库使用说明 + +## 二、AI 写作风格指南 + +## 三、核心价值观关键词 + +## 四、可引用的故事素材 + +## 五、禁忌与边界 diff --git a/docs/knowledge/skills/personal-ip-knowledge-builder/references/interview-questions.md b/docs/knowledge/skills/personal-ip-knowledge-builder/references/interview-questions.md new file mode 100644 index 000000000..63051cc0e --- /dev/null +++ b/docs/knowledge/skills/personal-ip-knowledge-builder/references/interview-questions.md @@ -0,0 +1,59 @@ +# 个人 IP 知识库访谈问题 + +当资料不足时,优先问最能改变知识库质量的问题。不要一次问太多;每轮 5-8 个问题即可。 + +## 基础信息 + +1. 你希望别人怎么介绍你? +2. 你现在最核心的身份是什么? +3. 你服务什么人?帮他们解决什么问题? +4. 你最希望被记住的标签是什么? +5. 有没有必须避免的称呼或标签? + +## 成长经历 + +1. 你来自哪里?成长环境对你有什么影响? +2. 你小时候或学生时代有什么明显特质? +3. 有没有一次经历改变了你的性格或人生选择? +4. 你经历过什么低谷?后来怎么走出来? +5. 哪个故事最能代表你这个人? + +## 职业与业务 + +1. 你什么时候进入现在这个行业? +2. 第一份重要工作或项目是什么? +3. 你现在的产品 / 服务是什么? +4. 客户为什么选择你,而不是别人? +5. 你最拿手的能力是什么? + +## 案例与数据 + +1. 你做过哪些代表项目? +2. 有没有具体结果或数据? +3. 哪个案例最能证明你的能力? +4. 这个案例中你做了哪些关键动作? +5. 哪些客户、数据或细节不能公开? + +## 方法论与观点 + +1. 你对行业最大的判断是什么? +2. 你反对行业里哪些常见说法? +3. 你最常跟客户讲的一句话是什么? +4. 你做事最重要的方法论是什么? +5. 你认为成功最关键的因素是什么? + +## 表达风格 + +1. 你说话更直接、温和、犀利、幽默还是陪伴型? +2. 你常用哪些词或句子? +3. 你不喜欢哪些表达? +4. 你希望 AI 写得像本人,还是更正式? +5. 有无过去写过的内容可作为风格样本? + +## 禁忌边界 + +1. 哪些经历不希望被写? +2. 哪些成果不能夸大? +3. 哪些行业词不能乱用? +4. 哪些客户 / 数据不能公开? +5. 哪些表达会让你觉得“不像我”? diff --git a/docs/knowledge/skills/personal-ip-knowledge-builder/references/personal-ip-template.md b/docs/knowledge/skills/personal-ip-knowledge-builder/references/personal-ip-template.md new file mode 100644 index 000000000..de61de2b7 --- /dev/null +++ b/docs/knowledge/skills/personal-ip-knowledge-builder/references/personal-ip-template.md @@ -0,0 +1,148 @@ +# 个人 IP 知识库标准模板 + +用于把某个人的访谈、经历、内容和业务资料整理成 AI 可长期调用的 Markdown 知识库。 + +## 标准章节 + +# [姓名] 个人 IP 知识库 + +## 第一章 人物档案与基本信息 + +### 1.1 基础档案 +- 姓名 / 常用称呼 +- 地域 / 当前城市 +- 当前身份 +- 主要行业 +- 主要服务对象 +- 当前业务 / 产品 / 服务 + +### 1.2 核心标签体系 +用 5-10 个标签概括这个人,例如: +- 12年自媒体营销实战家 +- 视频号增长顾问 +- 大健康品牌操盘手 +- 企业家私域转化教练 + +### 1.3 职业履历概览 +用表格梳理阶段、时间、经历、代表成果。 + +## 第二章 个人简介与核心定位 + +### 2.1 个人简介 +写成可用于官网、商务介绍、媒体资料的完整简介。 + +### 2.2 一句话定位 +用一句话说明:这个人是谁,服务谁,解决什么问题,凭什么可信。 + +### 2.3 核心业务闭环 +说明其业务如何从内容、流量、信任、转化到交付形成闭环。 + +## 第三章 成长背景与关键经历 + +### 3.1 家庭与成长环境 +只写与价值观、性格、能力形成相关的内容。 + +### 3.2 求学与早期能力 +提炼写作、表达、组织、销售、审美、技术等早期能力来源。 + +### 3.3 人生转折点 +记录关键事件、低谷、高光、选择和它们带来的长期影响。 + +## 第四章 职业经历与业务发展 + +### 4.1 初入职场 +说明第一阶段如何积累基本能力。 + +### 4.2 能力积累 +提炼可迁移能力,而不是流水账。 + +### 4.3 创业 / 转型经历 +说明为什么转型、怎么判断机会、踩过什么坑。 + +### 4.4 当前业务状态 +说明当前主要服务、产品、渠道、客户和交付方式。 + +## 第五章 代表案例与实战成绩 + +### 5.1 代表项目 +每个案例写清:背景、动作、结果、可复用经验。 + +### 5.2 关键数据 +只写可验证或用户明确提供的数据;不确定则标注 `待补充`。 + +### 5.3 成功路径 +提炼案例背后的方法论。 + +## 第六章 核心方法论与行业洞察 + +### 6.1 对行业的判断 +写出这个人反复强调的行业认知。 + +### 6.2 对内容 / 产品 / 销售 / 交付的理解 +根据资料选择相关维度,不要机械补齐。 + +### 6.3 与同行不同的观点 +优先提炼有辨识度、有争议但有依据的观点。 + +## 第七章 价值观与人生哲学 + +- 工作观 +- 金钱观 +- 成长观 +- 合作观 +- 自由观 +- 客户观 + +## 第八章 性格特质与表达风格 + +### 8.1 性格关键词 +例如:直接、务实、犀利、温和、陪伴型、结果导向。 + +### 8.2 说话方式 +说明句式、节奏、口头禅、常用比喻。 + +### 8.3 写作风格 +说明适合的文体和不适合的文体。 + +## 第九章 金句语录与思想精华 + +按主题整理:事业、行业、客户、内容、人生、合作。 + +## 第十章 核心能力与竞争优势 + +- 专业能力 +- 资源优势 +- 经验壁垒 +- 审美 / 表达 / 销售 / 组织能力 +- 和同行相比的差异化 + +## 第十一章 未来愿景与发展规划 + +说明当前目标、未来方向、希望建立的影响力。 + +# 附录一 多场景介绍话术 + +至少包含: +- 30 秒电梯介绍 +- 1 分钟正式介绍 +- 社群介绍 +- 商务场合介绍 +- 短视频账号简介 +- 直播间开场介绍 + +# 附录二 智能体应用指南 + +## 一、知识库使用说明 +说明这份知识库适合被 AI 用在哪些任务中。 + +## 二、AI 写作风格指南 +说明 AI 模拟此人写作时应遵守什么风格。 + +## 三、核心价值观关键词 +用 `关键词 | 关键词 | 关键词` 格式输出。 + +## 四、可引用的故事素材 +用列表整理可反复调用的故事。 + +## 五、禁忌与边界 +说明不能写什么、不能夸大什么、哪些内容必须先确认。 diff --git a/docs/knowledge/skills/personal-ip-knowledge-builder/references/quality-checklist.md b/docs/knowledge/skills/personal-ip-knowledge-builder/references/quality-checklist.md new file mode 100644 index 000000000..cf1400f0f --- /dev/null +++ b/docs/knowledge/skills/personal-ip-knowledge-builder/references/quality-checklist.md @@ -0,0 +1,50 @@ +# 个人 IP 知识库质量检查表 + +生成完成后逐项检查。 + +## 事实完整性 + +- 是否有清晰的人物基础档案? +- 是否有一句话定位? +- 是否区分了事实、观点、推断和待补充? +- 是否标注不确定信息为 `待补充`? +- 是否避免编造客户、数据、履历和成果? + +## 结构完整性 + +- 是否包含人物经历、业务能力、代表案例、方法论、价值观、表达风格? +- 是否包含多场景介绍话术? +- 是否包含智能体应用指南? +- 是否包含禁忌与边界? +- 是否适合后续持续维护? + +## 可调用性 + +- AI 是否能用它写文案、话术、介绍、方案和改稿? +- 是否有可引用故事素材? +- 是否有金句和常用表达? +- 是否说明了“不应该怎么写”? +- 是否能让不同模型保持同一大方向? + +## 风格真实性 + +- 是否保留了本人真实语气? +- 是否避免过度神化和成功学包装? +- 是否使用了具体案例,而不是空泛形容? +- 是否符合这个人的行业、圈层和受众? + +## 输出可交付性 + +- Markdown 标题层级是否清晰? +- 是否有目录感和章节感? +- 是否能直接写回 Agent Knowledge `documents/.md`? +- 是否适配 `profile: document-first` 与 `runtime.mode: persona`? +- 是否能让 Lime 在 `metadata.producedBy` 与 `runs/compile-*.json.builder_skill` 中记录本 Skill provenance? +- 如果资料不足,是否给出了“待补充信息清单”? + +## Runtime 安全边界 + +- 是否明确把输出作为知识资料,而不是运行时指令? +- 是否避免要求 Resolver 在回答用户问题时执行本 Skill? +- 是否只引用来源材料中出现的事实,未确认信息都标记为 `待补充`? +- 是否把冲突事实、敏感信息和夸大风险写入 warnings 或待确认清单? diff --git a/docs/knowledge/skills/personal-ip-knowledge-builder/scripts/docx_to_markdown.py b/docs/knowledge/skills/personal-ip-knowledge-builder/scripts/docx_to_markdown.py new file mode 100755 index 000000000..79c6ff8f4 --- /dev/null +++ b/docs/knowledge/skills/personal-ip-knowledge-builder/scripts/docx_to_markdown.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python3 +"""将 DOCX 的标题、正文、列表和表格转换为基础 Markdown。""" + +from __future__ import annotations + +import argparse +import re +from pathlib import Path + +from docx import Document +from docx.document import Document as DocumentObject +from docx.oxml.table import CT_Tbl +from docx.oxml.text.paragraph import CT_P +from docx.table import Table +from docx.text.paragraph import Paragraph + +SEPARATOR_RE = re.compile(r"^[─━—\-_=]{6,}$") + + +def iter_block_items(parent): + if isinstance(parent, DocumentObject): + parent_elm = parent.element.body + parent_obj = parent + else: + parent_elm = parent._tc + parent_obj = parent + for child in parent_elm.iterchildren(): + if isinstance(child, CT_P): + yield Paragraph(child, parent_obj) + elif isinstance(child, CT_Tbl): + yield Table(child, parent_obj) + + +def clean_text(text: str) -> str: + return re.sub(r"[ \t]+", " ", text.replace("\u00a0", " ")).strip() + + +def paragraph_to_markdown(paragraph: Paragraph) -> list[str]: + text = clean_text(paragraph.text) + if not text: + return [] + + style = paragraph.style.name if paragraph.style else "" + if style.startswith("Heading"): + match = re.search(r"(\d+)", style) + level = min(max(int(match.group(1)) if match else 1, 1), 6) + return [f"{'#' * level} {text}"] + + if SEPARATOR_RE.match(text): + return ["---"] + + if text.startswith(("• ", "· ", "● ", "○ ")): + return [f"- {text[2:].strip()}"] + + return [text] + + +def table_to_markdown(table: Table) -> list[str]: + rows: list[list[str]] = [] + for row in table.rows: + cells: list[str] = [] + for cell in row.cells: + parts: list[str] = [] + for block in iter_block_items(cell): + if isinstance(block, Paragraph): + line = clean_text(block.text) + if line: + parts.append(line) + elif isinstance(block, Table): + nested = table_to_markdown(block) + if nested: + parts.append("
".join(nested)) + cells.append("
".join(parts).replace("|", r"\|")) + if rows and cells == rows[-1]: + continue + rows.append(cells) + + if not rows: + return [] + + col_count = max(len(row) for row in rows) + rows = [row + [""] * (col_count - len(row)) for row in rows] + markdown = [ + "| " + " | ".join(rows[0]) + " |", + "| " + " | ".join(["---"] * col_count) + " |", + ] + for row in rows[1:]: + markdown.append("| " + " | ".join(row) + " |") + return markdown + + +def convert_docx(input_path: Path, output_path: Path) -> None: + doc = Document(str(input_path)) + lines: list[str] = [ + "", + "", + ] + + for block in iter_block_items(doc): + block_lines = ( + paragraph_to_markdown(block) + if isinstance(block, Paragraph) + else table_to_markdown(block) + ) + if not block_lines: + continue + if lines and lines[-1] != "": + lines.append("") + lines.extend(block_lines) + lines.append("") + + output_path.parent.mkdir(parents=True, exist_ok=True) + output_path.write_text("\n".join(lines).rstrip() + "\n", encoding="utf-8") + + +def main() -> None: + parser = argparse.ArgumentParser(description="将 DOCX 转换为基础 Markdown。") + parser.add_argument("input", type=Path, help="输入 DOCX 文件路径") + parser.add_argument("output", type=Path, help="输出 Markdown 文件路径") + args = parser.parse_args() + + if not args.input.exists(): + raise SystemExit(f"输入文件不存在:{args.input}") + if args.input.suffix.lower() != ".docx": + raise SystemExit("输入文件必须是 .docx") + + convert_docx(args.input, args.output) + + +if __name__ == "__main__": + main() diff --git a/docs/research/codex-goal/README.md b/docs/research/codex-goal/README.md index e2421a991..c2d2e911e 100644 --- a/docs/research/codex-goal/README.md +++ b/docs/research/codex-goal/README.md @@ -7,7 +7,7 @@ ## 1. 为什么单独成文档 -`/goal` 不应该放进 CreoAI 研究目录里当附属小节。 +`/goal` 不应该放进 Skill Forge 研究目录里当附属小节。 原因是它研究的不是 Tool-Maker Agent,也不是电商运营自动化,而是另一个更小、更底层的 runtime pattern: @@ -22,16 +22,16 @@ persistent thread goal **一个 agent turn 结束后,系统如何知道还要不要继续推进同一个目标。** -这和 CreoAI 的三层架构有关,但不等同: +这和 Skill Forge 的三层架构有关,但不等同: | 研究对象 | 主要回答什么 | Lime 对应层 | | --- | --- | --- | -| CreoAI / Tool-Maker Agent | 能力如何被生成、验证、注册、长期运行 | Skill Forge / skills pipeline 上游 | +| Skill Forge / Tool-Maker Agent | 能力如何被生成、验证、注册、长期运行 | Skill Forge / skills pipeline 上游 | | Codex `/goal` | 一个 thread goal 如何跨多轮 turn 自动续跑直到完成、暂停或耗尽预算 | Query Loop / automation job 上的目标推进控制环 | 固定结论: -**`/goal` 是独立研究对象;它可以作为 Lime Managed Objective 的参考,但不应被写成 CreoAI 或 Skill Forge 的子章节。** +**`/goal` 是独立研究对象;它可以作为 Lime Managed Objective 的参考,但不应被写成 Skill Forge 或 Skill Forge 的子章节。** ### 1.1 什么是 Thread Goal Loop @@ -566,12 +566,12 @@ failed 3. Lime 有外部权限、浏览器登录态、workspace artifact。 4. Lime 有 evidence pack,可以支持更强审计。 -## 10. 和 CreoAI 研究的关系 +## 10. 和 Skill Forge 研究的关系 -Codex `/goal` 可以补 CreoAI 三层架构里的第二层视角: +Codex `/goal` 可以补 Skill Forge 三层架构里的第二层视角: ```text -CreoAI 三层: +Skill Forge 三层: Coding Agent / Agent Builder -> Autonomous Execution / Runtime -> Workspace / Agent App Surface @@ -590,7 +590,7 @@ Autonomous Execution / Runtime 里的 persistent objective + continuation loop 因此两个研究目录应分工: -- `docs/research/creaoai/`:研究“能力如何被 agent 生成并长期运行”。 +- `docs/research/skill-forge/`:研究“能力如何被 agent 生成并长期运行”。 - `docs/research/codex-goal/`:研究“目标如何跨 turn 被 runtime 持续推进”。 ## 11. 研究结论 @@ -613,8 +613,8 @@ Autonomous Execution / Runtime 里的 persistent objective + continuation loop 3. `docs/roadmap/managed-objective/implementation-plan.md` 4. `docs/roadmap/managed-objective/diagrams.md` -它不直接塞进 `docs/roadmap/creaoai/`,除非只是说明两者关系。 +它不直接塞进 `docs/roadmap/skill-forge/`,除非只是说明两者关系。 一句话: -**Codex `/goal` 研究应服务 Lime 的目标推进控制层;CreoAI 研究应服务 Lime 的能力生成与长期业务自动化闭环。两者有关,但必须分开建模。** +**Codex `/goal` 研究应服务 Lime 的目标推进控制层;Skill Forge 研究应服务 Lime 的能力生成与长期业务自动化闭环。两者有关,但必须分开建模。** diff --git a/docs/research/pi-mono-coding-agent/README.md b/docs/research/pi-mono-coding-agent/README.md index 1cb7e81b6..92c4909c5 100644 --- a/docs/research/pi-mono-coding-agent/README.md +++ b/docs/research/pi-mono-coding-agent/README.md @@ -311,7 +311,7 @@ pi-mono 的 extension 可以: | `CustomEntry` | timeline / artifact / evidence event | | `registerTool` | 只能在 verified registration 后映射到 Skill / ServiceSkill / tool_runtime | | `registerCommand` | Lime 不需要复制 terminal command system | -| `registerProvider` | 与 CreoAI P1A 无关,不进入首期 | +| `registerProvider` | 与 Skill Forge P1A 无关,不进入首期 | 固定边界: @@ -509,9 +509,9 @@ P1A 推荐先把 draft 作为 workspace-local 文件事实源: 2. 若 Lime 现有 artifact store 已有更合适路径,应优先复用现有封装。 3. 不要为了 P1A 新增全局数据库主事实源。 -## 13. 和 CreoAI / Managed Objective 的关系 +## 13. 和 Skill Forge / Managed Objective 的关系 -pi-mono 参考的是 CreoAI 三层里的第一层: +pi-mono 参考的是 Skill Forge 三层里的第一层: ```text Coding Agent / Agent Builder diff --git a/docs/research/creaoai/README.md b/docs/research/skill-forge/README.md similarity index 76% rename from docs/research/creaoai/README.md rename to docs/research/skill-forge/README.md index cc850e196..8c79439f2 100644 --- a/docs/research/creaoai/README.md +++ b/docs/research/skill-forge/README.md @@ -1,19 +1,19 @@ -# CREAO 研究总入口 +# Skill Forge 研究总入口 > 状态:current research reference > 更新时间:2026-05-06 -> 目标:把 Founder Park 访谈中的 CREAO 案例拆成可持续对照的研究事实源,供 Lime 后续规划校准“Coding Agent 生成工具、Agent 可复用运行、组织 AI Native 反馈闭环”的产品范式。 +> 目标:把 Founder Park 访谈中的 Skill Forge 案例拆成可持续对照的研究事实源,供 Lime 后续规划校准“Coding Agent 生成工具、Agent 可复用运行、组织 AI Native 反馈闭环”的产品范式。 ## 1. 命名与来源边界 -用户转述中出现过 `career AI`、`creaoio`、`creaoai` 等名称差异;本轮访谈明确指向 **CREAO**,官网为 `https://creao.ai/`。目录名继续保留 `creaoai`,文档内统一称为 **CREAO**。 +用户要求后续文档不再暴露原外部产品名;本目录统一使用 **Skill Forge** 作为中性代称。目录名使用 `skill-forge`,不在本目录记录外部官网、融资、团队等尽调信息。 本目录只分析 Founder Park 访谈中体现的产品、组织与架构范式。 固定边界: 1. 本目录不把用户数、融资额、团队背景、上线时间、收入指标等访谈口径写成已核验事实。 -2. 本目录不评估 CREAO 公司真实性、商业数据或投资信息。 +2. 本目录不评估外部公司真实性、商业数据或投资信息。 3. 本目录只沉淀对 Lime 有用的产品、组织与工程启发。 一句话: @@ -22,7 +22,7 @@ ## 2. 目录定位 -`docs/research/creaoai/` 只回答两类问题: +`docs/research/skill-forge/` 只回答两类问题: 1. 访谈里的三层架构、工具编码编排、Agent 产品模型和组织 harness 到底是什么。 2. Lime 应该学它的哪一层,不应该照搬哪一层。 @@ -31,9 +31,9 @@ 固定分工: -1. `docs/research/creaoai/` 负责外部案例拆解和风险识别。 -2. `docs/roadmap/creaoai/` 负责 Lime 自己的开发计划。 -3. [../codex-goal/README.md](../codex-goal/README.md) 单独研究 Codex `/goal` 这类 persistent objective / continuation loop,不再塞进 CREAO 研究目录。 +1. `docs/research/skill-forge/` 负责外部案例拆解和风险识别。 +2. `docs/roadmap/skill-forge/` 负责 Lime 自己的开发计划。 +3. [../codex-goal/README.md](../codex-goal/README.md) 单独研究 Codex `/goal` 这类 persistent objective / continuation loop,不再塞进 Skill Forge 研究目录。 4. 代码实现仍必须回到 Lime 现有 current 主链:`skills pipeline / Query Loop / tool_runtime / Workspace / evidence pack`。 ## 3. 为什么单独建立这一层 @@ -76,7 +76,7 @@ - 自动执行必须受权限、dry-run、测试、证据、sandbox 和人工确认约束。 6. **组织 harness 是护城河之一** - - CREAO 强调 AI 扫描信号、提出需求、人类 planning、AI 实现、AB/log 反馈的闭环。 + - Skill Forge 强调 AI 扫描信号、提出需求、人类 planning、AI 实现、AB/log 反馈的闭环。 7. **对 Lime 不应新增平行标准** - 动态生成能力必须编译进 Lime 现有 Skill Bundle / ServiceSkill / Adapter Spec / tool_runtime 主链。 @@ -90,9 +90,9 @@ 5. [lime-gap-analysis.md](./lime-gap-analysis.md) 6. [../pi-mono-coding-agent/README.md](../pi-mono-coding-agent/README.md) 7. [../codex-goal/README.md](../codex-goal/README.md) -8. [../../roadmap/creaoai/README.md](../../roadmap/creaoai/README.md) -9. [../../roadmap/creaoai/implementation-plan.md](../../roadmap/creaoai/implementation-plan.md) -10. [../../roadmap/creaoai/diagrams.md](../../roadmap/creaoai/diagrams.md) +8. [../../roadmap/skill-forge/README.md](../../roadmap/skill-forge/README.md) +9. [../../roadmap/skill-forge/implementation-plan.md](../../roadmap/skill-forge/implementation-plan.md) +10. [../../roadmap/skill-forge/diagrams.md](../../roadmap/skill-forge/diagrams.md) ## 6. 固定不照搬的东西 @@ -117,7 +117,7 @@ Lime 真正要学的是: 补充参考: -1. [../pi-mono-coding-agent/README.md](../pi-mono-coding-agent/README.md) 不是 CREAO 公司研究,而是本地开源 coding harness 对照。 +1. [../pi-mono-coding-agent/README.md](../pi-mono-coding-agent/README.md) 不是 Skill Forge 公司研究,而是本地开源 coding harness 对照。 2. 它用于回答“Lime 缺的 Coding Agent 层工程上怎么切”。 3. 当前结论是:参考 pi-mono 的 `AgentSession` 分层、工具 allowlist、可插拔工具后端、事件与测试 harness;不复制它的终端产品、JSONL session 事实源或全仓库 shell/write 权限。 @@ -126,9 +126,9 @@ Lime 真正要学的是: 后续所有实现建议默认遵守以下顺序: 1. 先读本目录,确认外部范式到底启发了什么。 -2. 再读 [../../roadmap/creaoai/README.md](../../roadmap/creaoai/README.md),确认 Lime 决定怎么做。 +2. 再读 [../../roadmap/skill-forge/README.md](../../roadmap/skill-forge/README.md),确认 Lime 决定怎么做。 3. 涉及 skill / adapter / runtime binding 时,回看 [../../aiprompts/skill-standard.md](../../aiprompts/skill-standard.md) 与 [../../aiprompts/query-loop.md](../../aiprompts/query-loop.md)。 一句话: -**`research/creaoai` 负责防止误读外部案例,`roadmap/creaoai` 负责把启发收敛成 Lime current 主线;所有实现都必须回到 Skill / Query Loop / tool_runtime / Workspace / evidence,而不是新增 CREAO 仿制旁路。** +**`research/skill-forge` 负责防止误读外部案例,`roadmap/skill-forge` 负责把启发收敛成 Lime current 主线;所有实现都必须回到 Skill / Query Loop / tool_runtime / Workspace / evidence,而不是新增 Skill Forge 仿制旁路。** diff --git a/docs/research/skill-forge/agent-product-model.md b/docs/research/skill-forge/agent-product-model.md new file mode 100644 index 000000000..adc0a74fc --- /dev/null +++ b/docs/research/skill-forge/agent-product-model.md @@ -0,0 +1,143 @@ +# Skill Forge Agent 产品模型拆解 + +> 状态:current research reference +> 更新时间:2026-05-06 +> 目标:把 Founder Park 访谈中 Agent / Skill / Memory / Widget / Schedule / Workspace 协作的产品模型拆清楚,避免把 Skill Forge 简化为 Skill Forge 或工具注册表。 + +## 1. 一句话结论 + +访谈里 Skill Forge 对 Agent 与 Skill 的区分很关键: + +**Skill 更像 Agent 的 runbook;Agent 则是可复用工作单元,至少还包含 memory、widget、schedule、权限、运行历史和协作上下文。** + +因此 Lime 的路线不能停在: + +```text +verified skill -> 可调用工具 +``` + +还要逐步走向: + +```text +一次成功任务 + -> 主动建议固化 + -> Skill / runbook + -> Agent envelope:memory + schedule + widget + permission + evidence + -> 可 rerun / 可共享 / 可审计 +``` + +## 2. 从任务到 Agent 的 aha moment + +Skill Forge 访谈里真正的用户转化不是让用户先理解“什么是 Agent”,而是: + +1. 用户先完成一个具体任务。 +2. 系统发现任务结果稳定、方法可复用。 +3. 系统主动建议“把这套方法转成以后可以复用的 Agent”。 +4. 用户设置触发条件、输入、调度和权限。 +5. 以后只看结果、处理阻塞、做决策。 + +固定判断: + +**Proactive agentization 是产品层能力,不是 runtime 层能力。Runtime 负责能不能跑,产品面负责什么时候建议固化。** + +## 3. Agent 与 Skill 的分层 + +| 层级 | 职责 | Lime 中的收敛方向 | +| --- | --- | --- | +| Skill / Runbook | 描述如何执行一类任务,包含步骤、脚本、示例、测试 | Agent Skill Bundle / Adapter Spec | +| Memory | 保存用户偏好、历史决策、方法论、上下文摘要 | memory compaction / state-history-telemetry | +| Widget | 展示输入、结果、状态、阻塞点、产物 | Workspace / Task Center / ServiceSkill 投影 | +| Schedule | 手动、定时、事件触发、rerun | automation job / Managed Objective | +| Permission | 控制外部读写、文件写入、发布、付款等 | tool_runtime / permission policy | +| Evidence | 证明生成、验证、注册、调用和结果 | artifact / timeline / evidence pack | + +固定边界: + +**Skill 不是完整 Agent;Agent 也不应成为绕过 Skill / tool_runtime / evidence 的新执行实体。** + +## 4. 短高频重复任务优先 + +访谈里对“长时间任务”的判断有一个容易被误读的点: + +1. 大多数商业化任务不是单个任务连续跑很久。 +2. 更常见的是短暂、高频、重复、可拆分的知识工作。 +3. 用户价值来自“每天 / 每周自动 rerun,并把人从重复整理中解放出来”。 + +因此本目录后续使用“长期运行”时,默认含义应是: + +**可持久化、可调度、可恢复、可 rerun 的重复工作,而不是无限自主长跑。** + +对 Lime 的含义: + +1. P4 首期应优先支持 verified read-only skill 的手动运行、定时运行和失败阻塞。 +2. 不应急着做无限链式自主任务。 +3. completion audit 要证明每次 rerun 的产物和成功标准,而不是只证明模型“还在跑”。 + +## 5. Workspace 内共享,而不是公开 Marketplace 优先 + +访谈中 Skill Forge 区分了两种共享: + +1. **公开 Marketplace / Skill Store** + - 用 agent 换取经济回报。 + - 问题是每个 agent 高度依赖具体 workspace、context、sandbox 和账号环境。 + +2. **团队 Workspace 内共享** + - 同一团队在同一上下文、权限和基础设施中共享 agent、skill、context。 + - 更贴近工作场景里的协作需求。 + +对 Lime 的固定判断: + +**首期优先 workspace/team-scoped sharing,不优先公开交易市场。** + +这意味着: + +1. workspace-local skill 默认只在当前 workspace 可见。 +2. team sharing 需要显式权限、来源、版本和 evidence。 +3. Marketplace 只可作为后续启发入口,不应成为 P3/P4 主线。 + +## 6. 云端 sandbox 与本地 GUI 的张力 + +Skill Forge 访谈倾向云端,理由包括: + +1. 每个请求独立 sandbox,环境隔离更稳定。 +2. 平台修复一次基础设施问题,所有用户受益。 +3. 人与 agent、agent 与 agent 的协作需要共享 context。 +4. 云端可以更强控制数据库、文件系统、memory、connector 协议和性能。 + +Lime 是桌面 GUI 产品,不能直接照搬“完全云端”。应拆成两个问题: + +1. **产品面**:Workspace、证据、任务、review 可以继续是 Lime 桌面 GUI 的强项。 +2. **执行面**:高隔离、高复现、高风险外部操作,未来可接 remote runtime / sandbox profile。 + +固定边界: + +**Lime 不因 Skill Forge 云端叙事放弃桌面主路径;但 P3E/P4 之后必须把 sandbox profile、session enable、tool_runtime 授权和 evidence 绑定起来。** + +## 7. Memory 三层机制启发 + +访谈中的 memory 机制可抽象为三层: + +1. **Thread 内压缩** + - context 接近上限时压缩,把应记住的内容写入文件系统或等价持久层。 + +2. **跨 Thread 长期记忆** + - 每次请求结束后判断是否有长期价值,抽取、去重并存储。 + +3. **新 Thread 相关记忆注入** + - 新任务开始时检索最相关的历史 memory,并注入上下文。 + +对 Lime 的含义: + +**generated skill / agent envelope 不能只保存脚本;还应能引用产生它的方法论、用户偏好、历史修正和运行反馈。** + +## 8. 对 Lime 的禁止项 + +1. 不把 `Skill` 直接宣称为完整 `Agent`。 +2. 不为 Agent envelope 新增平行 runtime。 +3. 不把 public marketplace 放到 workspace-local skill 之前。 +4. 不把“长时运行”误写成无限自主执行。 +5. 不让 Widget / Schedule / Memory 绕过 Workspace、automation job、Managed Objective 和 evidence。 + +## 9. 一句话结论 + +**Skill Forge 给 Lime 的产品启发是:把一次成功任务主动固化为可 rerun、可共享、可审计的 Agent;Skill Forge 只是这条链的上游,不是完整产品终点。** diff --git a/docs/research/creaoai/architecture-breakdown.md b/docs/research/skill-forge/architecture-breakdown.md similarity index 90% rename from docs/research/creaoai/architecture-breakdown.md rename to docs/research/skill-forge/architecture-breakdown.md index bf677f106..9f77aa330 100644 --- a/docs/research/creaoai/architecture-breakdown.md +++ b/docs/research/skill-forge/architecture-breakdown.md @@ -1,8 +1,8 @@ -# CREAO 三层架构拆解 +# Skill Forge 三层架构拆解 > 状态:current research reference > 更新时间:2026-05-06 -> 目标:把 Founder Park 访谈中的 CREAO 三层架构拆成稳定系统层次,并补齐组织 harness、Agent 产品模型、sandbox、memory 与 outcome feedback 的横切面。 +> 目标:把 Founder Park 访谈中的 Skill Forge 三层架构拆成稳定系统层次,并补齐组织 harness、Agent 产品模型、sandbox、memory 与 outcome feedback 的横切面。 ## 1. 先给结论 @@ -102,7 +102,7 @@ persistent thread goal(同一会话线程上的持久目标状态) -> budget / pause / resume / complete ``` -它能解释“如何把一轮 agent turn 续成多轮目标推进”,但不能代表完整 CREAO 三层架构: +它能解释“如何把一轮 agent turn 续成多轮目标推进”,但不能代表完整 Skill Forge 三层架构: 1. 它不负责生成 Skill / Adapter / Contract / Test。 2. 它不负责 workspace-local skill catalog。 @@ -173,7 +173,7 @@ Skill / Runbook ## 6. 横切面一:组织开发 Harness -CREAO 访谈中,“Harness”不只指用户任务运行环境,也指公司自身的开发反馈系统。可以抽象为: +Skill Forge 访谈中,“Harness”不只指用户任务运行环境,也指公司自身的开发反馈系统。可以抽象为: ```text 行业动态 / GitHub / 竞品 / 用户日志 / 业务指标 @@ -194,7 +194,7 @@ CREAO 访谈中,“Harness”不只指用户任务运行环境,也指公司 ## 7. 横切面二:Sandbox / Memory / Outcome Feedback -CREAO 访谈把稳定性放在模型智商之前,关键原因是普通商业化任务多为短暂、高频、重复的知识工作。 +Skill Forge 访谈把稳定性放在模型智商之前,关键原因是普通商业化任务多为短暂、高频、重复的知识工作。 运行稳定性至少包括: @@ -205,14 +205,14 @@ CREAO 访谈把稳定性放在模型智商之前,关键原因是普通商业 对 Lime 的边界: -1. 桌面 GUI 是 current 产品面,不因 CREAO 云端叙事被替换。 +1. 桌面 GUI 是 current 产品面,不因 Skill Forge 云端叙事被替换。 2. 高隔离执行可逐步接 remote runtime / sandbox profile。 3. Memory 必须收敛到 Lime 的 compaction、state-history-telemetry 和 workspace context 主链。 4. Outcome telemetry 不应伪装成 evidence;两者相互引用但事实源不同。 ## 8. 对 Lime 的映射 -| CREAO 层级 / 横切面 | Lime 中应收敛到的主链 | 不应新增的旁路 | +| Skill Forge 层级 / 横切面 | Lime 中应收敛到的主链 | 不应新增的旁路 | | --- | --- | --- | | Coding Agent / Agent Builder | Skill Forge、Agent Skill Bundle、Adapter Spec、ServiceSkill 投影 | 平行 generated tool 类型 | | Autonomous Execution | Query Loop、runtime_queue、tool_runtime、automation job、subagent | 独立 scheduler / workflow runtime | @@ -222,7 +222,7 @@ CREAO 访谈把稳定性放在模型智商之前,关键原因是普通商业 一句话: -**Lime 不需要复制一个 CREAO,而是把这三层折回现有 skills pipeline 与 Harness Engine。** +**Lime 不需要复制一个 Skill Forge,而是把这三层折回现有 skills pipeline 与 Harness Engine。** ## 9. 关键风险 diff --git a/docs/research/creaoai/lime-gap-analysis.md b/docs/research/skill-forge/lime-gap-analysis.md similarity index 82% rename from docs/research/creaoai/lime-gap-analysis.md rename to docs/research/skill-forge/lime-gap-analysis.md index 5565a5db5..eb4ac14d2 100644 --- a/docs/research/creaoai/lime-gap-analysis.md +++ b/docs/research/skill-forge/lime-gap-analysis.md @@ -1,8 +1,8 @@ -# CREAO 对照 Lime 的偏差分析 +# Skill Forge 对照 Lime 的偏差分析 > 状态:current research reference > 更新时间:2026-05-06 -> 目标:判断 Lime 当前路线和 CREAO 访谈启发是否冲突,并明确后续应该补哪些产品、运行和组织闭环。 +> 目标:判断 Lime 当前路线和 Skill Forge 访谈启发是否冲突,并明确后续应该补哪些产品、运行和组织闭环。 ## 1. 总判断 @@ -10,7 +10,7 @@ Lime 当前方向不冲突。 更准确的判断是: -**Lime 已有底座,但 skills pipeline 还偏静态,Agent 产品面还偏薄;CREAO 启发的是把“能力生成、验证、注册、rerun、Agent 固化、反馈改进”补成闭环。** +**Lime 已有底座,但 skills pipeline 还偏静态,Agent 产品面还偏薄;Skill Forge 启发的是把“能力生成、验证、注册、rerun、Agent 固化、反馈改进”补成闭环。** 也就是说,问题不是 Lime 缺 tool,也不是缺 skill 标准,而是缺少: @@ -25,7 +25,7 @@ Coding Agent 自动生成 capability 补充宗旨: -**CREAO 启发不等于无限放权。Lime 后续应坚持“权限永远显式受控,能力逐级开放”;限制的是未经验证、未经授权、不可审计的执行,不是限制 agent 的理解、设计和编码能力。** +**Skill Forge 启发不等于无限放权。Lime 后续应坚持“权限永远显式受控,能力逐级开放”;限制的是未经验证、未经授权、不可审计的执行,不是限制 agent 的理解、设计和编码能力。** ## 2. Lime 已经接近的部分 @@ -66,7 +66,7 @@ Lime 当前已经具备以下相关底座: - 访谈中 Skill 只是 runbook;Lime 还需要把 verified skill 与 memory、widget、schedule、permission、evidence 组合成可 rerun Agent,而不是只展示“已注册技能”。 7. **Proactive agentization 不足** - - CREAO 的 aha moment 是成功任务后主动建议“继续这套方法 / 转成 Agent”。Lime 目前更偏手工注册和手工进入下一 gate,缺少从成功 turn 到 reusable agent 的产品转化面。 + - Skill Forge 的 aha moment 是成功任务后主动建议“继续这套方法 / 转成 Agent”。Lime 目前更偏手工注册和手工进入下一 gate,缺少从成功 turn 到 reusable agent 的产品转化面。 8. **Sandbox / Memory / Outcome feedback 缺口** - Lime 已有 evidence 与 runtime 主链,但还需要明确 sandbox profile、三层 memory 回流,以及 evidence 与 telemetry / experiment 的边界:evidence 证明做了什么,outcome feedback 证明有没有用。 @@ -118,24 +118,24 @@ Lime 当前已经具备以下相关底座: 1. `GeneratedTool` 作为与 Skill / ServiceSkill / Adapter 平级的长期主类型。 2. agent 生成代码后绕过 tool_runtime 直接执行。 3. 外部 API / CLI 原始 schema 直接成为 Lime 运行时协议。 -4. 为“更像 CREAO”而复制电商垂类产品结构。 +4. 为“更像 Skill Forge”而复制电商垂类产品结构。 5. 为自动化能力新增第二套 evidence pack。 -6. 为了复刻 CREAO 而新增平行 AI PM、AB testing、memory 或 marketplace 系统。 +6. 为了复刻 Skill Forge 而新增平行 AI PM、AB testing、memory 或 marketplace 系统。 7. 把公开 Marketplace 放在 workspace/team-scoped sharing 之前作为 P3/P4 主线。 ## 5. 对 Lime 开发计划的直接要求 -后续 `docs/roadmap/creaoai/` 必须做到: +后续 `docs/roadmap/skill-forge/` 必须做到: 1. 把 Skill Forge 写成 skills pipeline 的上游阶段,而不是新 runtime。 2. 把 generated capability 的结果固定为 Skill Bundle / Adapter Spec / ServiceSkill 投影。 3. 把 verification gate 写成注册前硬门槛。 4. 把 tool_runtime 与 evidence pack 写成唯一执行和事实源。 5. 把 workspace-local visibility 纳入首批产品验收。 -6. 把 Codex `/goal` 参考单独留在 `docs/research/codex-goal/`;CREAO roadmap 只引用它来解释长期目标推进,不把它写成 Skill Forge 的一部分。 +6. 把 Codex `/goal` 参考单独留在 `docs/research/codex-goal/`;Skill Forge roadmap 只引用它来解释长期目标推进,不把它写成 Skill Forge 的一部分。 7. 把 Agent envelope 写成 Skill Forge 之后的产品层:成功任务可建议固化为 Agent,但执行仍走 automation job / Managed Objective。 8. 把 sandbox profile、memory 回流、outcome telemetry 写为 P3E/P4 之后的扩展约束,不抢当前 `tool_runtime` 授权裁剪主线。 ## 6. 一句话结论 -**CREAO 启发不推翻 Lime 的 skills pipeline;它要求 Lime 把 skills pipeline 从“安装和调用技能”升级为“生成、编译、验证、注册、rerun,并把成功任务固化为可审计 Agent”。** +**Skill Forge 启发不推翻 Lime 的 skills pipeline;它要求 Lime 把 skills pipeline 从“安装和调用技能”升级为“生成、编译、验证、注册、rerun,并把成功任务固化为可审计 Agent”。** diff --git a/docs/research/skill-forge/pivot-and-org-harness.md b/docs/research/skill-forge/pivot-and-org-harness.md new file mode 100644 index 000000000..5251a2f6c --- /dev/null +++ b/docs/research/skill-forge/pivot-and-org-harness.md @@ -0,0 +1,125 @@ +# Skill Forge Pivot 与组织 Harness 拆解 + +> 状态:current research reference +> 更新时间:2026-05-06 +> 目标:把 Founder Park 访谈里“产品 pivot 之前先组织 pivot”的部分拆成 Lime 可复用的组织与反馈闭环事实源,避免只把 Skill Forge 理解成 Tool-Maker Agent。 + +## 1. 一句话结论 + +Skill Forge 访谈里最值得补进 Lime 研究的,不只是 Coding Agent 会写工具,而是: + +**当开发实现成本被 AI 压低后,公司的瓶颈从“工程排期”转移到“需求发现、方向判断、验证反馈和组织改造”。** + +因此 Skill Forge 的 harness 至少有两层: + +1. **产品运行 harness**:让 agent 在 sandbox、memory、schedule、permission、evidence 里稳定执行用户任务。 +2. **组织开发 harness**:让 AI 扫描信号、提出需求、人类架构师判断、AI 实现、AB/log 反馈,再反哺下一轮改进。 + +现有 Lime 研究已经覆盖第一层的一部分;本文件补第二层。 + +## 2. 访谈口径中的 pivot 时间线 + +以下为访谈自述口径,未在本目录内做外部尽调核验: + +1. **2025 年 1 月底**:公司成立,方向仍在探索。 +2. **2025 年 6 月**:大部分团队到位,当时重点仍接近 Vibe Coding / 给人构建传统工具。 +3. **2025 年 9 月**:第一版 Vibe Coding 平台上线。 +4. **2026 年 1 月**:把产品方向转成 Super Agent。 +5. **2026 年 2 月**:完成开发团队 AI-first 改造,一个月内重构新产品基础版本。 +6. **2026 年 3 月 31 日**:Super Agent 版本正式上线。 + +固定判断: + +**这不是“先有完美产品,再调整组织”;而是“组织生产方式先改造,产品形态才有足够速度 pivot”。** + +## 3. Vibe Coding 失败信号 + +访谈中 Skill Forge 对上一版产品的反思可以抽象成四点: + +1. **自己人用不起来** + - 如果团队自己搭出来的应用都难以长期使用,说明产品价值不在“更快造传统 App”。 + +2. **构建成本大于使用收益** + - 花在搭建、调优、修 bug 上的时间,超过了最终使用这个应用的时间。 + +3. **传统 UI 是给人工作的,不是给 AI 工作的** + - 如果未来执行者是 AI,AI 不需要传统 SaaS 的完整按钮、表单、页面和交互流。 + +4. **原型难以对抗专业 SaaS** + - 快速生成的 CRM / SaaS 原型很难比长期打磨的垂直 SaaS 更可靠。 + +对 Lime 的含义: + +**Workspace UI 不应被设计成传统 app builder;它更应该是任务、阻塞、证据、产物、权限、rerun 和 agent 管理面。** + +## 4. AI Native 开发闭环 + +访谈中的组织 harness 可以抽象为: + +```text +外部信号 / 内部日志 / 用户反馈 / 竞品动态 + -> AI 生成候选需求 + -> 人类架构师做方向与主线判断 + -> AI 拆任务、实现、测试、部署 + -> AB testing / telemetry 验证效果 + -> 日志和结果回流为下一轮 context +``` + +这个闭环和传统流程的差异: + +1. **需求发现更自动** + - AI 可以持续看行业动态、GitHub、竞品、日志和用户行为,形成候选任务。 + +2. **人类判断更集中** + - 人不是逐个写实现,而是判断哪些任务符合产品主线、商业目标和风险边界。 + +3. **实现成本更低** + - 需求确认后,AI 快速实现并进入验证,而不是长期排期。 + +4. **上线不是终点** + - AB test、日志、使用指标和复盘结果继续回流到 harness。 + +## 5. 人类角色变化 + +访谈把人类角色分成两类: + +1. **架构师 / planning owner** + - 不只是传统技术架构师,而是产品品味、商业判断、行业理解、技术能力的综合角色。 + - 负责判断 AI 生成的大量需求中哪些值得做、是否偏离主线、风险是否可控。 + +2. **任务接收者 / reviewer / operator** + - 接收 AI 分配的 bug fix、UI 调整、验证、复盘等任务。 + - 重点是审核、补上下文、处理阻塞,而不是从零执行所有工作。 + +对 Lime 的含义: + +**Task Center 和 Workspace 不只展示“agent 在跑什么”,还要展示“人在哪些关键节点需要判断什么”。** + +## 6. 对 Lime 的映射 + +| Skill Forge 组织 harness | Lime 应收敛到的主链 | 不应新增的旁路 | +| --- | --- | --- | +| AI 扫描候选需求 | roadmap / exec-plan / telemetry 摘要 / task intake | 独立 AI 产品经理数据库 | +| 人类 planning 判断 | Workspace review / Task Center / explicit approval | 模型直接决定 roadmap | +| AI 实现与修复 | Skill Forge / Query Loop / subagent / automation job | 绕过 runtime 的代码执行器 | +| AB / log 反馈 | telemetry / artifact / evidence / outcome summary | 第二套实验事实源 | +| 组织记忆回流 | repo docs / memory compaction / workspace context | 只存在聊天里的决策 | + +固定事实源声明: + +**Lime 只把组织 harness 的启发折回现有 roadmap、exec-plan、Workspace、telemetry、artifact 和 evidence 主链;不新增平行的 AI PM / AB / scheduler 系统。** + +## 7. 研究边界 + +本文件不把以下访谈内容写成 Lime 的立即产品承诺: + +1. 每天上线 5-8 个功能。 +2. 95% 工作都交给 AI。 +3. revenue run rate 或 ARPU 增长。 +4. 融资金额、团队规模、市场扩散。 + +这些可以作为外部案例背景,但 Lime roadmap 只吸收可工程化的组织闭环。 + +## 8. 一句话结论 + +**Skill Forge 的非共识不是“AI 写代码更快”,而是“公司流程先围绕 AI 的能力重构,产品才能在每个变化节点快速转身”。** diff --git a/docs/research/creaoai/tool-coding-orchestration.md b/docs/research/skill-forge/tool-coding-orchestration.md similarity index 97% rename from docs/research/creaoai/tool-coding-orchestration.md rename to docs/research/skill-forge/tool-coding-orchestration.md index 14189a31f..922e87d61 100644 --- a/docs/research/creaoai/tool-coding-orchestration.md +++ b/docs/research/skill-forge/tool-coding-orchestration.md @@ -1,4 +1,4 @@ -# CREAO 的工具编码编排 +# Skill Forge 的工具编码编排 > 状态:current research reference > 更新时间:2026-05-06 @@ -83,7 +83,7 @@ Tool Maker Agent ## 3. 能力生成链路 -CREAO 式工具编码编排可以抽象成下面这条链: +Skill Forge 式工具编码编排可以抽象成下面这条链: ```text Capability Source @@ -229,7 +229,7 @@ Tool-maker agent 解决的是: ## 6. 对 Lime skills pipeline 的启发 -CREAO 的关键启发不是替代 skills pipeline,而是给它补上游: +Skill Forge 的关键启发不是替代 skills pipeline,而是给它补上游: ```text 用户目标 diff --git a/docs/roadmap/knowledge/prd-v2-diagrams.md b/docs/roadmap/knowledge/prd-v2-diagrams.md new file mode 100644 index 000000000..d21978a83 --- /dev/null +++ b/docs/roadmap/knowledge/prd-v2-diagrams.md @@ -0,0 +1,714 @@ +# Lime Agent Knowledge PRD v2 - 可视化设计文档 + +> 状态:current / 与 `prd-v2.md` 配套使用 +> 更新时间:2026-05-08 +> 关系:本文是 `prd-v2.md` 的可视化补充。所有图表、UI 原型、时序与流程严格对齐 Agent Knowledge v0.6.0 的 `document-first` / `runtime.mode` / `metadata.producedBy`,以及 v2 PRD 的 §2A persona/data 区分、§2B Skills-first、§5 Builder Skill 薄适配、§6 Builder Skill 清单、§7 Resolver、§9 命令面、§10.4 用户故事。 + +## 0. 文档目录 + +1. [§1 总体架构图](#1-总体架构图) — Skill Bundle / KnowledgePack / Runtime Binding 分层 +2. [§2 核心流程图](#2-核心流程图) — Builder Skill 整理 / Resolver 决策 / 状态机 +3. [§3 关键时序图](#3-关键时序图) — persona 整理、运行时调用、双产出 +4. [§4 UI 原型](#4-ui-原型) — 5 个核心界面线框图 +5. [§5 用户故事可视化](#5-用户故事可视化) — 5 个业务场景的端到端走查 + +## 1. 总体架构图 + +### 1.1 Skills-first 系统层次架构 + +```mermaid +flowchart TB + subgraph U[用户层] + U1[创作者 / 操盘手 / CEO] + end + + subgraph E[入口层] + E1[输入框资料图标] + E2[场景命令
/IP文案 /内容运营 /私域运营 /产品文案] + E3[Agent 输出沉淀] + E4[直接编辑 documents/.md] + end + + subgraph P[产品投影层] + P1[资料管理页
章节列表 + 状态] + P2[整理面板
accept/edit/rewrite] + P3[沉淀面板
新建 / 补充] + P4[高级视图
Builder Skill provenance] + end + + subgraph C[Skill 目录层] + C1[SkillCatalog.entries
kind=skill - current] + C2[serviceSkillCatalog
compat 产品投影] + C3[Builder Skill Bundle
SKILL.md + references/ + scripts/] + end + + subgraph S[服务层] + S1[knowledge_compile_pack
薄适配: 选 Skill + 调 binding] + S2[Runtime Binding
agent_turn / native_skill] + S3[knowledge_split_document
自动切片] + S4[knowledge_resolve_context
persona/data 分支] + end + + subgraph D[KnowledgePack 数据层] + D1[KNOWLEDGE.md
profile=document-first
runtime.mode + producedBy] + D2[documents/
成品文档 - v0.6 主事实源] + D3[sources/
原始材料] + D4[compiled/splits/
派生切片] + D5[runs/
compile/context 审计记录] + end + + subgraph R[Agent 运行时层] + R1[Fenced Wrapper
mode=persona / data] + R2[agent_runtime_submit_turn] + R3[Model] + end + + U1 --> E1 + U1 --> E2 + U1 --> E3 + U1 --> E4 + + E1 --> P1 + E3 --> P3 + E4 --> D2 + P1 --> P2 + P2 --> S1 + P3 --> S1 + + C1 --> S1 + C2 -.compat 只委托.-> C1 + C1 --> C3 + S1 --> S2 + S2 --> C3 + C3 --> S1 + + D3 --> S1 + D1 --> S1 + S1 --> D2 + S1 --> D5 + D2 --> S3 + S3 --> D4 + + E1 --> S4 + E2 --> S4 + D1 --> S4 + D4 --> S4 + S4 --> R1 + R1 --> R2 + R2 --> R3 + R3 -.输出.-> U1 + R3 -.可沉淀.-> E3 + + P4 --> D5 + + classDef user fill:#FEF3C7,stroke:#F59E0B,color:#78350F; + classDef entry fill:#EFF6FF,stroke:#3B82F6,color:#1E3A8A; + classDef product fill:#ECFDF5,stroke:#10B981,color:#064E3B; + classDef skill fill:#EDE9FE,stroke:#8B5CF6,color:#4C1D95; + classDef service fill:#FDF4FF,stroke:#A855F7,color:#581C87; + classDef data fill:#F8FAFC,stroke:#64748B,color:#0F172A; + classDef runtime fill:#FFF7ED,stroke:#F97316,color:#7C2D12; + + class U1 user; + class E1,E2,E3,E4 entry; + class P1,P2,P3,P4 product; + class C1,C2,C3,S2 skill; + class S1,S3,S4 service; + class D1,D2,D3,D4,D5 data; + class R1,R2,R3 runtime; +``` + +**架构关键判断**: + +1. `Builder Skill Bundle` 是生产工艺事实源,`KnowledgePack documents/` 是产物事实源。 +2. `knowledge_compile_pack` 不拥有模板和章节生成逻辑,只做 Skill 选择、runtime binding 调用和文件写回。 +3. `SkillCatalog.entries(kind=skill)` 是 current 目录投影;`serviceSkillCatalog` 只允许 compat 委托。 +4. `documents/` 是 Agent Knowledge v0.6.0 `document-first` 数据层中心;`compiled/splits/`、`runs/` 都是派生 / 审计层。 +5. 运行时层的 wrapper 只消费 `runtime.mode=persona|data`,决定 persona 还是 data 语义;它不执行 Builder Skill。 + +### 1.2 Skill Bundle 与 KnowledgePack 边界 + +```mermaid +flowchart LR + subgraph SB[Builder Skill Bundle - how] + SB1[SKILL.md
工作流] + SB2[references/template.md
章节骨架] + SB3[references/interview-questions.md
缺口问题] + SB4[references/quality-checklist.md
质量自检] + SB5[scripts/*.py
格式转换] + SB6[agents/*.yaml
模型适配] + end + + subgraph KP[KnowledgePack - what] + KP1[KNOWLEDGE.md
profile + runtime.mode
primaryDocument + producedBy] + KP2[sources/
原始资料] + KP3[documents/.md
成品文档] + KP4[compiled/splits/
派生切片] + KP5[runs/compile-*.json
Skill provenance + 章节状态] + end + + SB1 --> BIND[Runtime Binding] + SB2 --> BIND + SB3 --> BIND + SB4 --> BIND + SB5 --> BIND + SB6 --> BIND + KP1 --> BIND + KP2 --> BIND + BIND --> KP3 + BIND --> KP5 + KP3 --> SPLIT[knowledge_split_document] + SPLIT --> KP4 + + classDef skill fill:#EDE9FE,stroke:#8B5CF6,color:#4C1D95; + classDef pack fill:#ECFDF5,stroke:#10B981,color:#064E3B; + classDef service fill:#FDF4FF,stroke:#A855F7,color:#581C87; + class SB1,SB2,SB3,SB4,SB5,SB6 skill; + class KP1,KP2,KP3,KP4,KP5 pack; + class BIND,SPLIT service; +``` + +**边界规则**: + +1. Skill 不复制进 pack;pack 只记录 `metadata.producedBy`、版本、digest 和 run 记录。 +2. `references/` 是模板事实源;PRD 和 Lime 代码不再维护平行模板。 +3. Skill 内部脚本只做转换或辅助处理,不直接写 pack;最终写入由 Lime 完成。 +4. Knowledge runtime 消费 pack 时只读取 `KNOWLEDGE.md`、`documents/`、`compiled/` 和 `runs/context-*`;不得为了回答用户问题而执行 Builder Skill。 + +### 1.3 persona / data 双族架构 + +```mermaid +flowchart LR + subgraph PF[persona 族 pack] + PF1[personal-profile
个人 IP] + PF2[brand-persona
品牌人设] + PF_SKILL[persona Builder Skills
personal-ip / brand-persona] + PF_CORE[核心人设章节
voice / 性格 / 金句 / 禁忌 / 应用指南] + PF_FACT[事实章节
履历 / 案例 / 数据] + end + + subgraph DF[data 族 pack] + DF1[brand-product
产品事实] + DF2[organization-knowhow
组织 SOP] + DF3[growth-strategy
增长策略] + DF4[content-operations
内容运营] + DF5[private-domain-operations
私域/社群运营] + DF6[live-commerce-operations
直播运营] + DF7[campaign-operations
活动运营] + DF_SKILL[data Builder Skills
product / knowhow / growth / ops] + DF_FACT[事实与 playbook 章节
参数 / 流程 / 节奏 / 指标 / 合规] + end + + subgraph RT[运行时 Resolver] + RT_PERSONA[persona 分支
核心人设无条件先注入] + RT_DATA[data 分支
按任务命中章节] + RT_COMBINE[多 pack 协同
1 persona + N data] + end + + PF_SKILL --> PF_CORE + PF_SKILL --> PF_FACT + DF_SKILL --> DF_FACT + PF_CORE --> RT_PERSONA + PF_FACT --> RT_PERSONA + DF_FACT --> RT_DATA + RT_PERSONA --> RT_COMBINE + RT_DATA --> RT_COMBINE + + RT_COMBINE --> WRAP[Fenced Wrapper
顺序: persona 先, data 后] + WRAP --> MODEL[Model 输出] + + classDef persona fill:#FEF3C7,stroke:#F59E0B,color:#78350F; + classDef data fill:#DBEAFE,stroke:#3B82F6,color:#1E3A8A; + classDef skill fill:#EDE9FE,stroke:#8B5CF6,color:#4C1D95; + classDef runtime fill:#FFF7ED,stroke:#F97316,color:#7C2D12; + + class PF1,PF2,PF_CORE,PF_FACT persona; + class DF1,DF2,DF3,DF4,DF5,DF6,DF7,DF_FACT data; + class PF_SKILL,DF_SKILL skill; + class RT_PERSONA,RT_DATA,RT_COMBINE,WRAP,MODEL runtime; +``` + +**协同判断**: + +1. persona pack 提供"怎么说";data pack 提供"说什么"。 +2. 同一品牌可同时存在 brand-persona + brand-product + content-operations 等多个独立 pack。 +3. 运营类知识库仍属于 data family,提供节奏、SOP、指标和复盘,不新增第三族。 +4. wrapper 顺序固定:persona 先建立表达语境,data 再加载具体事实和运营 playbook。 +5. 最多 1 个 persona + N 个 data;两个 persona 同时启用会让模型扮演冲突。 + +## 2. 核心流程图 + +### 2.1 Builder Skill 整理流程(对应 v2 §5) + +```mermaid +flowchart TD + Start([用户导入访谈稿/资料]) --> Import[knowledge_import_source] + Import --> PackMeta[读取 KNOWLEDGE.md
profile / runtime.mode / type / producedBy / limeTemplate] + PackMeta --> SkillPick{能否找到
Builder Skill?} + SkillPick -->|显式选择或 producedBy 默认建议| SkillRef[skillBundleRef] + SkillPick -->|SkillCatalog 命中| SkillRef + SkillPick -->|serviceSkillCatalog compat| SkillRef + SkillPick -->|找不到| Block[阻断: 选择或安装 Skill] + + SkillRef --> Binding[Runtime Binding] + Binding --> SkillFlow[执行 Builder Skill 工作流
SKILL.md + references/ + scripts/] + SkillFlow --> Coverage{章节覆盖判定
由 Skill 返回} + Coverage -->|full / partial| DocOut[primaryDocument] + Coverage -->|missing| Missing[文档中显式待补充] + Coverage -->|conflict| Conflict[冲突摘要 + disputed] + + DocOut --> Output[KnowledgeBuilderSkillOutput] + Missing --> Output + Conflict --> Output + Output --> WriteMeta[写入 metadata.producedBy] + Output --> WriteRun[写入 runs/compile-*.json
builder_skill + chapters[]] + WriteMeta --> WriteDoc + WriteRun --> WriteDoc[写入 documents/.md] + WriteDoc --> Split[knowledge_split_document] + Split --> ReviewPanel[资料管理页章节列表] + ReviewPanel --> UserAction{用户操作} + UserAction -->|accept| ReadyCheck + UserAction -->|edit| EditChapter[编辑 documents 或章节] + UserAction -->|rewrite| Binding + EditChapter --> Split + + ReadyCheck{所有章节
accepted/missing?} + ReadyCheck -->|是| StatusReady([pack: ready]) + ReadyCheck -->|否| StatusReview([pack: needs-review]) + Block --> StatusReview + + classDef start fill:#FEF3C7,stroke:#F59E0B,color:#78350F; + classDef skill fill:#EDE9FE,stroke:#8B5CF6,color:#4C1D95; + classDef data fill:#F8FAFC,stroke:#64748B,color:#0F172A; + classDef status fill:#ECFDF5,stroke:#10B981,color:#064E3B; + classDef warn fill:#FEE2E2,stroke:#EF4444,color:#7F1D1D; + + class Start,Import start; + class SkillRef,Binding,SkillFlow skill; + class PackMeta,DocOut,Output,WriteDoc,WriteRun,Split,ReviewPanel,EditChapter data; + class StatusReady status; + class Missing,Conflict,Block,StatusReview warn; +``` + +**关键控制点**: + +1. 先选 Builder Skill,再整理;没有 Skill 不允许 LLM 直生成。 +2. 章节级生成、回退、质量检查属于 Skill 工作流;Lime 只校验输出契约。 +3. `runs/compile-*.json` 必须记录 Skill provenance,方便后续复现和审计。 +4. `documents/.md` 写入后统一由 `knowledge_split_document` 派生切片。 + +### 2.2 Resolver 决策流程(对应 v2 §7.2) + +```mermaid +flowchart TD + Req([用户请求 + 当前 pack]) --> PackType{pack family?} + + PackType -->|persona| PersonaBranch[persona 分支] + PackType -->|data| DataBranch[data 分支] + + PersonaBranch --> CoreInject[核心人设章节无条件注入
voice + 性格 + 金句 + 禁忌 + 应用指南] + CoreInject --> CheckBudget1{persona token
≤ personaCoreBudget 3500?} + CheckBudget1 -->|超| BlockPersona[阻断
提示用户精简文档] + CheckBudget1 -->|未超| AddFactPersona[按任务追加事实章节
履历/案例] + + DataBranch --> EstimateTokens[主文档 token 估算] + EstimateTokens --> SizeCheck{size?} + SizeCheck -->|≤ smallBudget| Full[完整注入主文档] + SizeCheck -->|≤ midBudget| BriefAndPick[brief + 应用指南 + 任务相关章节] + SizeCheck -->|≤ hardCap| StrictPick[brief + 1-3 最相关章节] + SizeCheck -->|> hardCap| BlockData[阻断
要求拆分文档] + + AddFactPersona --> WrapPersona[persona wrapper
mode=persona] + Full --> WrapData[data wrapper
mode=data] + BriefAndPick --> WrapData + StrictPick --> WrapData + + WrapPersona --> MultiPack{是否启用了
多个 pack?} + WrapData --> MultiPack + MultiPack -->|是| OrderCheck[wrapper 顺序
persona 先 / data 后] + MultiPack -->|否| Single[单 pack 注入] + + OrderCheck --> WriteRun[runs/context-*.json] + Single --> WriteRun + WriteRun --> Inject[注入 Agent Runtime] + Inject --> Model([Model 输出]) + + BlockPersona --> UserNotify[提示用户操作] + BlockData --> UserNotify + + classDef start fill:#FEF3C7,stroke:#F59E0B,color:#78350F; + classDef persona fill:#FEF3C7,stroke:#F59E0B,color:#78350F; + classDef data fill:#DBEAFE,stroke:#3B82F6,color:#1E3A8A; + classDef wrap fill:#FFF7ED,stroke:#F97316,color:#7C2D12; + classDef warn fill:#FEE2E2,stroke:#EF4444,color:#7F1D1D; + + class Req,Model start; + class PersonaBranch,CoreInject,AddFactPersona,WrapPersona persona; + class DataBranch,EstimateTokens,Full,BriefAndPick,StrictPick,WrapData data; + class MultiPack,OrderCheck,Single,WriteRun,Inject wrap; + class BlockPersona,BlockData,UserNotify warn; +``` + +**Resolver 关键判断**: + +1. `family` 决定走 persona 或 data 分支,不混用。 +2. persona 分支不做"按 token 大小四档决策",因为核心人设章节必须无条件注入。 +3. data 分支才走 v2 §7.2 的 full / brief+sections / strict-pick / block 四档。 +4. 多 pack 协同时 wrapper 顺序固定:persona wrapper 永远在 data wrapper 之前。 + +### 2.3 状态流转流程(对应 v2 §12) + +```mermaid +stateDiagram-v2 + [*] --> draft: 创建 pack + + draft --> needs_review: Builder Skill 返回章节状态 + needs_review --> ready: 全部章节 accepted/missing + needs_review --> disputed: 有 conflict 章节 + + ready --> stale: N 天未更新 + sources 新增 + ready --> disputed: 检测到冲突 + + stale --> needs_review: 重新整理 + disputed --> needs_review: 解决冲突 + + ready --> archived: 用户归档 + stale --> archived: 用户归档 + needs_review --> archived: 用户归档 + + archived --> [*]: 删除 + + note right of draft + 不进入运行时 + end note + + note right of needs_review + 不进入运行时 + UI 显示徽章 + end note + + note right of ready + 可进入运行时 + 默认候选 + end note + + note right of stale + 使用时提示过期 + end note + + note right of disputed + 默认阻断 + 需用户确认 + end note +``` + +**状态判定规则**: + +1. 触发器是 Skill 返回的**章节级**判定。 +2. 全部章节 accepted 或显式 missing → 整 pack ready。 +3. 任意章节 needs-review → 整 pack needs-review。 +4. coverage: conflict → 整 pack disputed。 +5. UI 不暴露章节状态机给普通用户;只在高级模式显示。 + +## 3. 关键时序图 + +### 3.1 P1:个人 IP Builder Skill 整理时序 + +```mermaid +sequenceDiagram + autonumber + actor User as 用户 + participant UI as 资料管理页 + participant API as knowledge_compile_pack + participant Catalog as SkillCatalog + participant Binding as Runtime Binding + participant Skill as personal-ip-knowledge-builder + participant Pack as KnowledgePack + participant Split as knowledge_split_document + + User->>UI: 导入访谈稿 / 点击整理 + UI->>API: packPath + sources + profile=document-first + runtime.mode=persona + limeTemplate=personal-ip + API->>Catalog: 查找 personal-ip-knowledge-builder + Catalog-->>API: skillBundleRef + digest + resources + API->>Binding: 输入 KnowledgeBuilderSkillInput + Binding->>Skill: 加载 SKILL.md / references / scripts + Skill-->>Binding: KnowledgeBuilderSkillOutput + Binding-->>API: primaryDocument + chapters[] + issues + API->>Pack: 写 KNOWLEDGE.md metadata.producedBy + API->>Pack: 写 documents/.md + API->>Pack: 写 runs/compile-*.json.builder_skill + API->>Split: 对 primaryDocument 切片 + Split->>Pack: 写 compiled/splits + index.json + API-->>UI: pack status + chapters[] + UI-->>User: 显示完整文档 / 章节审阅 / Skill provenance +``` + +### 3.2 运行时调用时序:persona + data 协同 + +```mermaid +sequenceDiagram + autonumber + actor User as 用户 + participant Input as 输入框 / 场景命令 + participant Resolver as knowledge_resolve_context + participant Pack as KnowledgePack Index + participant Runtime as agent_runtime_submit_turn + participant Model as Model + + User->>Input: /IP文案 以谢晶口吻介绍金花黑茶 + Input->>Resolver: request + active packs + Resolver->>Pack: 读取 profile / runtime.mode / status / primaryDocument + Resolver->>Pack: 读取 persona compiled/index.json + Resolver->>Pack: 读取 data compiled/index.json + Resolver->>Resolver: persona 核心章节先选 + Resolver->>Resolver: data 事实章节按任务命中 + Resolver->>Runtime: fenced persona wrapper + data wrapper + Runtime->>Model: 提交带上下文的 turn + Model-->>Runtime: 输出文案 + Runtime-->>Input: 返回结果 + context run id + Input-->>User: 展示输出,可沉淀为 sources +``` + +### 3.3 Agent 输出沉淀为资料时序 + +```mermaid +sequenceDiagram + autonumber + actor User as 用户 + participant Chat as Agent 输出 + participant Panel as 沉淀面板 + participant Pack as KnowledgePack + participant API as knowledge_compile_pack + participant Skill as Builder Skill + + Chat-->>User: 生成一段可复用内容 + User->>Panel: 点击"沉淀到资料" + Panel->>Pack: 写入 sources/agent-output-*.md + Panel->>User: 选择补充已有 pack 或新建 pack + User->>Panel: 选择 personal-profile pack + Panel->>API: 重新整理 pack + API->>Skill: 调用同一 Builder Skill,传 acceptedChapters + Skill-->>API: 返回增量后的 primaryDocument + chapters[] + API->>Pack: 更新 metadata.producedBy / documents/ 与 runs/ + Panel-->>User: 显示新增资料影响的章节 +``` + +## 4. UI 原型 + +### 4.1 创建资料:用户看到模板,系统绑定 Skill + +```text +┌──────────────────────────────────────────────────────────────┐ +│ 新建项目资料 │ +├──────────────────────────────────────────────────────────────┤ +│ 资料类型 │ +│ [个人 IP] [品牌人设] [品牌产品] [组织 Know-how] [运营类] │ +│ 标准形态:Agent Knowledge v0.6 document-first / persona │ +│ │ +│ 上传资料 │ +│ ┌────────────────────────────────────────────────────────┐ │ +│ │ 拖入访谈稿、DOCX、聊天记录、公开资料 │ │ +│ └────────────────────────────────────────────────────────┘ │ +│ │ +│ 高级信息 │ +│ 使用 Builder Skill: personal-ip-knowledge-builder v1.0.0 │ +│ 来源: SkillCatalog / seeded │ +│ 写入: metadata.producedBy + runs/compile.builder_skill │ +│ │ +│ [取消] [开始整理] │ +└──────────────────────────────────────────────────────────────┘ +``` + +说明:普通用户看到"资料类型";高级信息才暴露 Builder Skill,不把工程概念推给普通用户。 + +### 4.2 整理进度:显示 Skill 阶段而不是 Lime 自建步骤 + +```text +┌──────────────────────────────────────────────────────────────┐ +│ 正在整理:谢晶个人 IP │ +├──────────────────────────────────────────────────────────────┤ +│ Builder Skill │ +│ personal-ip-knowledge-builder │ +│ │ +│ 进度 │ +│ ✓ 读取 sources/访谈稿_20260201.docx │ +│ ✓ 使用 scripts/docx_to_markdown.py 转换为 Markdown │ +│ ✓ 按 references/personal-ip-template.md 生成章节 │ +│ ! 金句语录来源不足,建议补充访谈 │ +│ ✓ references/quality-checklist.md 自检完成 │ +│ │ +│ 预计产物 │ +│ documents/谢晶_个人IP知识库v1.0.md │ +└──────────────────────────────────────────────────────────────┘ +``` + +### 4.3 资料详情:成品文档优先 + +```text +┌──────────────────────────────────────────────────────────────┐ +│ 谢晶 个人 IP 知识库 ready │ +├──────────────────────────────────────────────────────────────┤ +│ 主文档 │ +│ documents/谢晶_个人IP知识库v1.0.md [打开完整文档] [导出] │ +│ │ +│ 最近整理 │ +│ producedBy: personal-ip-knowledge-builder v1.0.0 │ +│ Run: compile-20260207T103000Z.json │ +│ profile: document-first runtime.mode: persona │ +│ │ +│ 章节审阅 │ +│ [✓] 人物档案与基本信息 full │ +│ [✓] 个人简介与核心定位 full │ +│ [!] 金句语录与思想精华 partial │ +│ [-] 未来愿景与发展规划 missing │ +│ │ +│ [重新整理] [补充资料] [高级:查看 Skill provenance] │ +└──────────────────────────────────────────────────────────────┘ +``` + +### 4.4 输入框资料选择:persona / data 可见 + +```text +┌──────────────────────────────────────────────────────────────┐ +│ 选择本轮资料 │ +├──────────────────────────────────────────────────────────────┤ +│ Persona │ +│ (●) 谢晶个人 IP ready personal-profile │ +│ ( ) 品牌官方口吻 draft brand-persona │ +│ │ +│ Data │ +│ [✓] 金花黑茶产品事实 ready brand-product │ +│ [✓] 本月内容运营日历 ready content-ops │ +│ [ ] 私域社群转化 SOP stale private-domain │ +│ [ ] 客服 SOP stale organization │ +│ │ +│ 规则:最多 1 个 persona + N 个 data │ +│ [取消] [确认启用] │ +└──────────────────────────────────────────────────────────────┘ +``` + +### 4.5 运行时证据:context run 可追踪 + +```text +┌──────────────────────────────────────────────────────────────┐ +│ 本轮使用资料 │ +├──────────────────────────────────────────────────────────────┤ +│ Wrapper 顺序 │ +│ 1. 谢晶个人 IP mode=persona selected=5 sections │ +│ 2. 金花黑茶产品事实 mode=data selected=3 sections │ +│ 规则:persona/data 均为受保护数据,不执行 Builder Skill │ +│ │ +│ Context Run │ +│ runs/context-20260207T104500Z.json │ +│ │ +│ 选中的切片 │ +│ compiled/splits/谢晶/.../金句语录.md │ +│ compiled/splits/金花黑茶/.../合规边界.md │ +└──────────────────────────────────────────────────────────────┘ +``` + +## 5. 用户故事可视化 + +### 5.1 MCN 机构:统一博主人设,团队协作不漂移 + +```mermaid +journey + title MCN 内容总监用个人 IP Builder Skill 统一博主人设 + section 建库 + 导入博主访谈和历史爆款: 4: 内容总监 + 选择个人 IP 模板: 5: 内容总监 + Lime 绑定 personal-ip-knowledge-builder: 5: Lime + section 审阅 + 打开完整 Markdown 文档: 5: 内容总监 + 接受核心人设章节: 4: 内容总监 + 标记缺失案例为待补充: 4: 内容总监 + section 使用 + 团队用 /IP文案 写短视频脚本: 5: 编导 + Resolver 注入 persona 核心章节: 5: Lime + 输出风格稳定: 5: 博主 +``` + +验收重点:同一个 persona pack 让不同编导、不同模型输出都不漂。 + +### 5.2 品牌操盘手:创始人 IP + 产品事实双包协同 + +```mermaid +flowchart LR + A[创始人访谈] --> B[personal-ip-knowledge-builder] + B --> C[创始人 persona pack] + D[产品资料 / FAQ / 合规] --> E[brand-product-knowledge-builder] + E --> F[产品 data pack] + C --> G[Resolver
persona first] + F --> G + G --> H[以创始人口吻介绍产品] + H --> I[有风格 + 有准确事实 + 不越过合规] +``` + +验收重点:persona 只决定表达方式,产品事实和合规边界来自 data pack。 + +### 5.3 企业服务商:客户 SOP 知识库,新人快速上手 + +```mermaid +flowchart TD + A[客户交付文档 / 会议纪要 / FAQ] --> B[organization-knowhow-knowledge-builder] + B --> C[organization-knowhow pack] + C --> D[新员工提问] + D --> E[Resolver 选 SOP / 失败案例 / FAQ] + E --> F[Agent 输出下一步操作] + F --> G[新人按 SOP 执行] +``` + +验收重点:输出必须是可执行步骤,不只是概念说明;不可回答边界必须能被单独注入。 + +### 5.4 创业公司 CEO:增长策略从资料沉淀到行动计划 + +```mermaid +flowchart TD + A[商业计划 / 指标 / 渠道复盘] --> B[growth-strategy-knowledge-builder] + B --> C[growth-strategy pack] + C --> D[/增长策略 生成 30/60/90 天计划] + D --> E[Resolver 选择指标 / 渠道 / 假设章节] + E --> F[Agent 输出带指标的行动计划] + F --> G[执行结果再沉淀为 sources] + G --> B +``` + +验收重点:增长策略必须能闭环到下一轮 sources,而不是一次性报告。 + +### 5.5 运营负责人:内容、私域、直播和活动 playbook + +```mermaid +flowchart TD + A[内容日历 / 选题库 / 爆款复盘] --> B[content-operations-knowledge-builder] + C[用户分层 / 社群 SOP / 转化话术] --> D[private-domain-operations-knowledge-builder] + E[货盘 / 直播脚本 / 场控节奏] --> F[live-commerce-operations-knowledge-builder] + G[活动目标 / 渠道 / 素材 / 预算] --> H[campaign-operations-knowledge-builder] + B --> I[content-operations pack] + D --> J[private-domain-operations pack] + F --> K[live-commerce-operations pack] + H --> L[campaign-operations pack] + I --> M[Resolver data wrappers] + J --> M + K --> M + L --> M + M --> N[运营执行输出
内容日历 / 触达节奏 / 直播脚本 / 活动清单] + N --> O[执行结果沉淀回 sources] + O --> B + O --> D + O --> F + O --> H +``` + +验收重点:运营类 pack 必须输出可执行动作、负责人、节奏、指标和复盘口径;不能只生成“建议多做内容和私域”这种泛泛建议。 + +## 6. 与 PRD 的一致性检查 + +| PRD 章节 | 本文图表 | 一致性要求 | +| --- | --- | --- | +| §11 Agent Knowledge v0.6.0 | §1.1 / §1.2 / §3.1 / §4.3 | pack 必须显式使用 `profile=document-first`、`runtime.mode`、`metadata.producedBy` | +| §2B Skills-first | §1.1 / §1.2 / §2.1 | Builder Skill 是工艺事实源,Lime 不自建整理引擎 | +| §5 整理契约 | §2.1 / §3.1 | `knowledge_compile_pack` 只做 Skill 选择、binding、写回 | +| §6 Skill 清单 | §1.3 / §4.1 / §5.5 | UI 模板来自 SkillCatalog 投影,不来自 Lime 内置模板目录;运营类也是 data family | +| §7 Resolver | §2.2 / §3.2 / §4.4 | persona / data 分支和 wrapper 顺序一致 | +| §9 命令面 | §4.5 | context run 与 command / scene 入口可追踪 | +| §10.4 用户故事 | §5.1-§5.5 | 每个业务故事都能回到一个 Builder Skill 或 pack 协同 | diff --git a/docs/roadmap/knowledge/prd-v2.md b/docs/roadmap/knowledge/prd-v2.md new file mode 100644 index 000000000..cb8c8ef32 --- /dev/null +++ b/docs/roadmap/knowledge/prd-v2.md @@ -0,0 +1,1210 @@ +# Lime Agent Knowledge PRD v2 + +> 状态:current PRD / 文档产物中心化 + Skills-first 修订版 / 对齐 Agent Knowledge v0.6.0 +> 更新时间:2026-05-08 +> 关系:v2 是 v1 (`prd.md`) 的修订版,**替代** v1 的 §7 目录结构、§8 架构、§10 时序、§15 命令边界、§16.2 Builder Skill;**继续生效** v1 的 §2 产品目标、§3 非目标、§4 用户故事、§11 状态流转、§12 运行时契约、§13 成本降级、§14 风险扫描、§17 演进分类、§19 验收。 +> 目标:把"知识包"的第一公民从一组工程碎片(sources / wiki / compiled / indexes / runs)改回**一份用户能读、能编、能交付的成品知识文档**,让 Lime 项目资料的体验跟 `docs/knowledge/谢晶_个人IP知识库v1.0_深澜智能.md` 这种产物对齐。 + +## 1. 背景与诊断 + +v1 已经把产品目标、用户故事、状态枚举、runtime fence 都写得很完整,并曾对齐 Agent Knowledge v0.5.0 标准。但实施出来的体验"一般",根因不在标准对齐,也不在产品目标错位,而在: + +**v1 把知识包结构定义成了一组工程碎片,用户拿不到一份"成品文档"。** + +证据:`docs/knowledge/谢晶_个人IP知识库v1.0_深澜智能.md`(999 行、19 章、附 6 场景话术 + 智能体应用指南),是用户实际期待的产物形态。它具备 5 个特征: + +1. **单文件、Markdown、人类可读** — 一份就是全部,不需要在 5 个目录里跳转 +2. **章节叙事化、有故事、有数据、有金句** — 不是干瘪字段 +3. **文件名是用户语言** — `谢晶_个人IP知识库v1.0_深澜智能.md`,不是 `compiled/voice.md` +4. **自带"应用指南"** — 末尾就有附录二《智能体应用指南》,明确告诉模型怎么用 +5. **能直接交付** — 可以发给客户、转 PDF、贴进任何 AI 会话 + +而 v1 PRD 让用户产出的是 `compiled/brief.md` + `compiled/facts.md` + `compiled/voice.md` + `compiled/stories.md` + `compiled/playbook.md` + `compiled/boundaries.md` + 散落在 `wiki/` 的多个页面——**这些只对 runtime 友好,对人不友好**。结果是: + +- 用户不会去维护这种结构(一改要改 6 处) +- 用户拿不出一份能给客户看的文档 +- 用户分不清 `wiki/` 和 `compiled/` 的边界(v1 §7 自己也只用一句话区分) +- 用户首次整理后,看到的不是一份成品,而是一堆碎片,立刻判定"不好用" + +补充诊断(v2 设计自检后加入):v1 和本 PRD 早期稿都把 KnowledgePack 当作"事实数据库"对待,但谢晶样例 999 行的真实主体是 voice / 性格 / 金句 / 价值观 / 禁忌 / 应用指南——这是**一个人的"人设",不是事实库**。事实型 pack 和 persona 型 pack 的运行时语义不同,不能用同一套 wrapper 与同一套章节优先级。这条区分见 §2A。 + +## 2. 核心结论 + +**知识包的第一公民是 `documents/` 下的成品知识文档。`sources/` 和 `compiled/` 都退到辅助位。Lime v2 选择 Agent Knowledge v0.6.0 原生支持的 `document-first` profile;`wiki/` 不进入默认主路径。** + +这条结论的含义: + +1. 用户**直接维护**的事实源是 `documents/.md`,像谢晶样例那样的一份完整文档。 +2. `compiled/` 不再由用户/Builder Skill 手动维护,而是由 `knowledge_split_document` **自动从 documents 切片**得到,纯派生层。 +3. `sources/` 仍存在,但只作为回溯证据和增量整理输入,不参与默认运行时上下文。 +4. `KNOWLEDGE.md` 仍是元数据入口,但更轻——它只列出本 pack 包含哪些 documents,以及"应该如何使用"的极简指引。 +5. Lime v2 默认选择 Agent Knowledge v0.6.0 的 `profile: document-first`;`wiki-first` 和 `hybrid` 只作为未来导入 / 迁移能力,不进入 P1 主路径。 + +把"产物"放到第一位之后,Builder Skill、Resolver、UI、命令面、验收口径都要相应收敛。本文剩余章节就是这次收敛的细节。 + +## 2A. 第二个核心结论:persona 型 pack 与 data 型 pack + +**KnowledgePack 不是单一形态。它至少有两族:persona 型(人设)和 data 型(事实)。两族的运行时语义不同,必须显式区分。** + +这条区分是 v2 早期稿(§3-§19)漏掉的。补正它,是把"楚川玩法"真正落到 Lime 的关键。 + +### 2A.1 两族的定义 + +| 维度 | persona 型 pack | data 型 pack | +| --- | --- | --- | +| 回答的问题 | 这个人 / 这个品牌**是谁、怎么说话、不能说什么** | 这件事 / 这个产品**是什么、参数是多少、流程怎么走** | +| 内容主体 | voice、性格、价值观、金句、故事素材、禁忌、应用指南 | facts、参数、流程、SOP、价格、合规边界、检查表 | +| 模型用途 | 扮演 / 代写 / 模仿 | 引用 / 计算 / 检索 | +| 模型行为 | 以这个人 / 品牌的口吻输出 | 把这些事实当不可编造的硬约束 | +| 标准类型 | `personal-profile`、`brand-persona`(新增) | `brand-product`、`organization-knowhow`、`growth-strategy`、`content-operations`、`private-domain-operations`、`live-commerce-operations`、`campaign-operations`、`domain-reference` | + +### 2A.2 谢晶样例的章节权重证明 + +谢晶样例(`docs/knowledge/谢晶_个人IP知识库v1.0_深澜智能.md`)999 行的章节权重不是平均的: + +| 章节 | 类型 | 在"人设"中的角色 | +| --- | --- | --- | +| 第 1、6、7-13 章(履历/案例/数据) | 事实素材 | 给 AI 提供"可引用的具体故事" | +| **第 14 章 方法论 + 第 15 章 价值观** | **观点立场** | **AI 表态时怎么说** | +| **第 16 章 性格特质** | **人格** | **AI 整体气质** | +| **第 17 章 金句语录** | **口头禅** | **AI 直接复用的语言** | +| **第 18 章 能力优势** | **定位** | **AI 自我介绍的素材** | +| **附录一 多场景话术** | **风格示范** | **AI 直接套用的句式** | +| **附录二 智能体应用指南** | **使用说明书** | **AI 怎么用前面所有内容** | + +重头戏是"她是谁 / 她怎么说话 / 她不能怎么说话",不是"她知道什么"。这就是 persona 型 pack 的核心特征。 + +### 2A.3 多 pack 协同的真正用法 + +写"以谢晶口吻介绍金花黑茶"时,标准组合是: + +```text +persona_pack: 谢晶-个人IP(提供 voice / 表达习惯 / 金句节奏 / 禁忌) ++ +data_pack: 金花黑茶-产品事实(提供 卖点 / 价格 / 渠道 / 合规边界) +``` + +人设 + 事实是两份**可独立维护、可任意组合**的资产,不是一份。同一品牌可以同时有 brand-persona(品牌怎么说话)和 brand-product(产品参数是什么)。运营类知识库默认也属于 data 族:它们回答“运营怎么做、按什么节奏做、用哪些素材和 SOP 做”,不是第三种 family。 + +### 2A.4 Persona 型用户故事(首批锚定) + +> **作为一个想做个人 IP 的创业者**,我希望把自己(或我的老板/客户)的访谈稿、过往内容、公开资料喂给 Lime,让它整理出一份完整的"个人 IP 人设包"。之后我**不需要再向团队/AI 解释"我是谁、我怎么说话、我不能说什么"**——团队任何人在 Lime 里写朋友圈、视频脚本、直播开场、商务自介、社群发言时,输出都像我本人写的,不会因为换人或换 AI 模型而漂移。 + +验收: + +- 用户提供 1-2 小时访谈稿后,Lime 能产出对齐谢晶样例形态的 persona 文档(含 voice / 性格 / 金句 / 应用指南)。 +- 用户在 Agent 里用这份 persona 写"东莞企业家沙龙开场白",输出体现"直接、实战、接地气、有具体案例"的风格。 +- 换模型(Opus → Sonnet → Haiku)时,输出风格基本稳定,不出现"模型换了语气就漂"的现象。 +- 当用户请求里包含未在 persona 文档中出现的事实("你 2025 年获得了什么奖")时,模型说"待补充"而不是编造。 + +这个故事是 v2 §14 Phase 1 的唯一锚定场景。 + +### 2A.5 对后续章节的影响 + +- §6 模板按 persona / data 两族重组(见下文)。 +- §7.2 Resolver 算法对 persona 型 pack 走专门分支(见下文)。 +- §7.3 fenced wrapper 增加 `mode=persona|data`(见下文)。 +- §14 Phase 1 收紧到"个人 IP persona 包端到端",brand-persona 与全部 data 型 pack 推迟到后续 phase(见下文)。 + +## 2B. 第三个核心结论:Skills-first,不发明新的"整理引擎" + +**KnowledgePack 是产物,Builder Skill 是生产工艺。Lime 不自建模板系统、不自建章节级生成引擎,全部复用 Agent Skills 核心包标准(参考 `agentskills.io`),再通过 Lime Skills 做产品投影和运行时绑定。** + +这条是 v2 早期稿(§5 整理 SOP / §6 模板骨架 / §9 命令面)漏掉的最大原则。修正它,让 PRD 与 `docs/aiprompts/skill-standard.md` 的"第一原则"对齐——Agent Skills 是 Lime 唯一对齐的技能包格式标准;Lime 只在这个标准之上定义自己的运行时与产品 profile。换句话说,`SKILL.md`、frontmatter、`references/`、`scripts/`、`assets/` 和渐进披露来自 Agent Skills;`SkillCatalog`、runtime binding、UI 模板选择和权限治理才是 Lime 的产品层。 + +### 2B.1 Lime 的角色收敛 + +| 角色 | v2 早期设想 | Skills-first 修订 | +| --- | --- | --- | +| 模板系统 | Lime 内置 4 类章节骨架,硬编码在 PRD §6 | 模板 = Builder Skill 的 `references/