diff --git a/.blueprint/modules/agent-client-parity.md b/.blueprint/modules/agent-client-parity.md index aec4ba6..38dfd61 100644 --- a/.blueprint/modules/agent-client-parity.md +++ b/.blueprint/modules/agent-client-parity.md @@ -338,6 +338,9 @@ skill 只是五个接入面之一,兼容层覆盖全部五面。 - depends: P8e - acceptance: "agent_verify: [pnpm typecheck && pnpm test] 视图纯函数:blocked 非空时确认按钮禁用并列出文件和原因;not_installed 和 not_applicable 显示为灰色说明、不显示为红色失败;bypassPermissions 和 Codex 信任单独列出;确认时携带 expected_digest。human_verify: ① 用临时 git 仓库新建项目,弹出接入预览;② 确认后 30 秒内看到分步结果、L1 矩阵和「待你提交的 N 个文件」;③ 另试一次在预览里取消,目录零改动;④ 在该目录新开 Claude Code、Codex、DSH 桌面 GUI 会话调 LJ_PROBE_NONEXISTENT,得「开发需求未登记」。" - 说明:新建 / 模板创建成功后弹出「接入预览」,create_project 本身保持无副作用;批量添加只提供批量入口、不自动接入;BlueprintModal 的「应用接入包」改为先 plan 再 apply。 +- 实现(2026-10-04,分支 feat/agent-client-parity-p8g,统筹会话主线程直做——两次委派卡死于一次性生成大文件):onboardView.ts 视图纯函数(计划预览、确认请求、报告、L1 矩阵;判定全取后端字段);OnboardPanel.tsx 全局挂载于 App、经 useUIStore.openOnboard 打开(新建弹窗保存即卸载,面板须独立存在),状态机 planning → preview → applying → report,过期响应按请求序号丢弃、接入中不可关闭,refused 附新计划可回预览重新确认;plan.rs 的 BlockedItem 序列化附派生字段 skippable(可跳过判定只在本体,反序列化忽略、不进 digest),commands.ts 同步;入口:ProjectModal 新建且按 platform 的有效根目录非空才弹(概念占位不弹),NewProjectModal 模板创建成功自动弹、完成页可再开,BatchAddModal 添加后列出有目录的新项目逐个「一键接入」,BlueprintModal「施加 Buff」改为同一面板(buff 已激活时另给「重新检查接入」),关闭后按报告刷新 buff 与 init prompt;project-context.yaml 同步 skippable 与 UI 投影。 +- 有意偏差:"① 呈现块拆到 OnboardSections.tsx(files 外新增,控制单文件规模)。② Toast 层级 z-50 → z-[70](审查 ②,否则接入提示被面板遮住)。③ 本地 confirm 函数改名 applyConfirmed:confirmUsage.test.ts 扫描 confirm( 防同步确认框,属正确的守卫。" +- review: "2026-10-04 独立只读审查 5b6c197,结论 merge,5 条:① [低] 新建入口按任一路径非空判是否弹面板,与后端按 platform 取有效根目录不同口径 → 已修。② [低] Toast z-50 被面板 z-[60] 遮住 → 已修。③ [低] 已有 permissions 又取消 bypass 时文案称会写 default → 已改文案(如实说明两种情况)。④ [信息] L1 格子着色在前端写死 codex_project_untrusted=待你操作,轻度复制判定 → 转后续小修(L1 格子带 pending_user 字段)。⑤ [信息] onboard_project 抛错后「取消」提示仍称不写入 → 已修(错误阶段换提示)。审查核实:确认带 plan.digest 与生成计划时的选项;refused 回预览时 planned 与新计划同一组选项(apply.rs 用请求选项重算);四条 agent_verify 有实断言。" ### ✅ P9 — DSH 桌面 GUI 按工作区连项目地址(会话级插件) - status: done diff --git a/src/components/dashboard/OnboardPanel.tsx b/src/components/dashboard/OnboardPanel.tsx index 581d9ad..a50df3e 100644 --- a/src/components/dashboard/OnboardPanel.tsx +++ b/src/components/dashboard/OnboardPanel.tsx @@ -165,7 +165,7 @@ function PanelFooter({ onClick={onCancel} disabled={phase.kind === "applying"} className={`${btnCls} border-gray-200 text-gray-600 hover:bg-gray-50`} - title="取消不写入任何文件" + title={phase.kind === "error" ? "关闭面板;若错误发生在确认接入之后,可能已有部分写入,请重新计划核对" : "取消不写入任何文件"} > 取消 diff --git a/src/components/dashboard/ProjectModal.tsx b/src/components/dashboard/ProjectModal.tsx index 566722e..0e627c2 100644 --- a/src/components/dashboard/ProjectModal.tsx +++ b/src/components/dashboard/ProjectModal.tsx @@ -95,7 +95,9 @@ const pickFolder = async (field: "wsl_path" | "win_path") => { qc.invalidateQueries({ queryKey: ["tagMaps"] }); closeEdit(); // create_project 本身无副作用;选了目录的新项目弹出接入预览(P8g),由人确认后才写入。不选目录的概念占位不接入 - if (isNew && (form.win_path?.trim() || form.wsl_path?.trim())) { + // 与后端登记同口径:按 platform 只看有效根目录那一列(另一列残留不算) + const effectiveRoot = form.platform === "wsl" ? form.wsl_path : form.win_path; + if (isNew && effectiveRoot?.trim()) { openOnboard({ projectId: form.id!, projectName: form.name?.trim() }); } } catch (e) { diff --git a/src/components/dashboard/onboardView.ts b/src/components/dashboard/onboardView.ts index 3af0c27..fd7d32a 100644 --- a/src/components/dashboard/onboardView.ts +++ b/src/components/dashboard/onboardView.ts @@ -279,7 +279,8 @@ function bypassView(plan: OnboardingPlan, planned: OnboardSelection, selection: return { ...base, label: "已按项目取消 bypassPermissions", - detail: "settings.json 缺 permissions 时写显式 defaultMode=default 记住选择,之后的重注入不会补回。", + detail: + "不写入 bypassPermissions。settings.json 缺 permissions 时会写显式 defaultMode=default 记住选择(之后的重注入不会补回);已有 permissions 则原样不动。", tone: "muted", toggleable: true, }; diff --git a/src/components/ui/Toast.tsx b/src/components/ui/Toast.tsx index fbc73d5..5abe75c 100644 --- a/src/components/ui/Toast.tsx +++ b/src/components/ui/Toast.tsx @@ -7,7 +7,7 @@ export function Toast() { const isError = toast.startsWith("❌"); return ( -