Skip to content

feat(design-system): DS-6 完成表单与确认组件复用 - #4135

Merged
MagicLizi merged 11 commits into
makecindy:mainfrom
kirozeng:ds/6-forms-and-confirm
Sep 9, 2026
Merged

feat(design-system): DS-6 完成表单与确认组件复用#4135
MagicLizi merged 11 commits into
makecindy:mainfrom
kirozeng:ds/6-forms-and-confirm

Conversation

@kirozeng

@kirozeng kirozeng commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

设计系统改造系列 DS-6;路线见 docs/design-rules/design-governance.md §12。

这次改了什么

摘要

把添加/编辑自定义模型供应商、添加/编辑 MCP 服务器整理为可复用的真实设置表单。必填和格式错误显示在对应字段并聚焦首错;实际保存时阻止重复提交和关闭,失败后可继续修改重试。补最小 FormField 与 Button loading,让后续贡献者复用现有输入和按钮。

变更类型

  • feat 新功能
  • refactor / perf 重构或性能优化
  • docs / test / chore 文档、测试或工程维护

范围

  • 关联 Issue / 需求:DS-6;前批 DS-5 docs(design-system): DS-5 对齐执行路线与双端设计合同 #4022
  • 本 PR 包含:两张真实表单、两处普通删除确认、共享 Input 焦点/密码显隐、Button loading、FormField、相关回归测试与已批准设计的规范回写。
  • 明确不包含:全设置页翻新、Permission/Full Access/插件授权、凭证存储、provider/MCP 配置语义、请求结算、协议、用户数据、Token JSON、依赖或 CI 改造、DS-7。
  • 用户可见变化:两张表单间距/输入/反馈一致;保存期间按钮显示加载且 Cancel/Esc/遮罩不关闭;错误就近显示;密码可切换显隐;两个删除确认显式复用既有标准按钮。未选择标准呈现的共享确认调用保留原分支。
  • 是否存在 breaking change:无。provider runtime/鉴权分支、原保存参数与 MCP 空 token/clearToken 行为保持。
  • 规模:用户明确要求一张 DS-6 PR、无 800 行限制。两消费者、共享组件、兼容与规范是同一交付,不为行数拆散。

UI 变化

  • 引用的设计规范:docs/design-rules/DESIGN.md §4 Buttons / Inputs & Forms / Dialog & Modal(标准控件、就近错误、实际提交状态、elevated 默认与明确 ivory 用途);§5 Border Radius Scale(先登记可见层,再给普通控件分档,保留 docs(design): 按可见层与登记分配圆角并明确审查边界 #4072);§10(语义 token、Light/Dark、旧局部覆盖);§14.2/14.3/14.6(焦点、IME、图标按钮提示);design-governance.md §4/6/10/13(主题兼容、两级证据、D1—D5 裁决、圆角审查边界)。
  • 输入 focus 使用已批准 soft/50%;错误态仍使用错误色优先。普通确认保留默认 Cancel 焦点、显式/typed 分支和 default/destructive 选择。
  • 用户在 Cindy 测试版直接手动审核后反馈“ok,测下来没什么问题”。未将截图替代用户手动审核。
  • macOS 实际设置路由已采集 Light/Dark,使用虚构 provider/MCP 数据与 renderer 服务替身;采集对应 6d4af6733a 中的表单源码。完整证据类别与未验项见 本批证据
  • 按治理合同 §6,截图保存在仓外附件包,不进入 Git。DS-6 共 55 张与 DS-4/4b 历史 14 张原图已整理,当前尚未公开上传;负责人 kirozeng,复查 2026-09-10 或 DS-7 开始前,以较早者为准。公开后补评论入口,未上传不宣称完成。

怎么验证的

自动验证

  • VITE_CINDY_AUTH_REGION=global pnpm test:unit:related:退出 0。合并兼容阶段包含上游测试调度/lockfile 增量,按现行调度扩大全量;runner 506 通过、1 既有跳过,Desktop/Mobile 与全部适用 workspace unit 通过。未收集测试的包仍按既有 manifest 跳过。
  • pnpm --filter desktop run --if-present typecheckpnpm --filter mobile typecheck:退出 0。
  • 截图移出后的最终提交前复验:同一 Global 命令执行 test:unit:related,runner 506 通过/1 既有跳过、Desktop 相关单测通过(42.7s);Desktop typecheck 再次退出 0。最终仅调整证据文本和截图交付,14 个源码/测试与已验收实现逐文件 blob 一致。
  • pnpm check:endpointscheck:i18ncheck:brand-terminologycheck:i18n-glossary--filter desktop db:validateci:scheduler-guard--filter mobile test:scopecheck:design-inventory:均退出 0。
  • 独立工作区将本批补丁应用于主线 35bac027eb,独立 frozen-lockfile 安装,Desktop typecheck 通过;高级模型/上下文/兼容选择 3 文件32项,最新统一模型/远程模型选择 4 文件231项全部通过。
  • git diff --checkpnpm check:dco:通过;实现和合并提交均带 Signed-off-by。追加 fetch 至 5c0e4e0da0,相对上述兼容模拟只新增 Mobile 图片缓存/分享四文件,不与本批 Desktop 改动交叉。
  • node scripts/hardcoded-color-audit.mjs --base-ref f3203a7049:退出 1,9 项报告为4处 hsl(var(--destructive)) 语义 token 消费和5处文档 PR 编号。逐条核实不含新增颜色值;未改扫描器/豁免,也不声称该扫描通过,交独立审查核验并留 DS-7 误报样本。
  • 原实现阶段额外主题 6 文件93项、相邻模型 5 文件97项通过,详见证据索引。
  • 诊断记录:本机 .env 的 CN 区域曾造成3个测试文件9项失败,命令级明确 Global 后原55项及全量门禁通过;未修改 .env 或测试断言。临时合并工作区补齐 lockfile 对应 Electron 二进制后,模型选择回归重新通过。

手工验证

macOS arm64、Global 的独立 ds6 Desktop 开发沙箱,实际 Settings 路由。自动化验证使用虚构服务返回;用户手动审核前已移除所有 renderer 替身并重载。已覆盖的正常/错误/禁用/提交中/失败重试/成功、密码显隐、键盘焦点、嵌套弹层、长文与字号 24px、Light/Dark、旧主题及局部/全局覆盖见证据索引。真实组件样例与完整设置页分别登记;模型高级面板保留 Codex 编辑/未改不写入/恢复默认,模型选择受控样例不冒充完整生产入口。

未执行的验证

  • G2:尚无未参与改造的独立贡献者到场,用户设计审核及 Agent 自测均不替代。kirozeng 安排、执行 Agent 跟进,复查 2026-09-10 或 DS-7 开工较早者。工程合入不等于 G2 完成。
  • Windows、原生 200% 缩放、真实系统 IME、原生窗口拖拽、完整生产模型选择入口仍有待项,详见逐项 SC。macOS 已验证范围不外推其他平台。
  • DS-6 原图与 DS-4/4b 历史附件已整理成本地交接包,尚未公开上传。原图/受控样例/静态稿/人工验收不混用。

风险

风险分类

  • 跨平台差异
  • 其他:有意可见变化;共享输入与按钮的主题兼容、保存期间与嵌套弹层的焦点行为。

影响与回滚

  • 影响范围:Desktop 两张设置表单、显式标准确认、共享输入焦点/密码显隐与可选 loading。存量插件影响:无;授权宿主及未迁确认保持原分支。
  • 回滚 / 降级方式:回退本 PR 相对 main 的改动(两消费者、共享组件、文档和测试一起回退);不回退主线其他 PR,不需要用户配置、凭证或数据库迁移。
  • Settings 台账继续 pilot。后续老界面全面规整待整体设计系统改造完成,再按届时 main 单独盘点,不将本批实际缺陷转为后续待办。

提交前检查

  • 已 review 完整 diff
  • 每个 commit 都带 DCO 签名(git commit -s)
  • UI 改动已注明引用的设计规范章节
  • 未提交凭证、令牌或授权文件
  • 已补充必要文档
  • 已确认测试结果或说明未执行原因

目标:完成 DS-6 两张真实设置表单与指定普通确认的组件复用,让非设计师能按仓内规范复用,用户获得一致且状态完整的操作。
范围:自定义供应商、MCP 表单及两处删除确认,FormField、Button loading、Input soft/50% 焦点与文档/必要测试。D1—D5 已获批准,实际保存防重复与防关闭、字段首错定位;保留 local/global 主题覆盖。
非目标:全设置页迁移、Permission/Full Access/插件授权、配置/鉴权/请求结算/存储/协议/用户数据语义、依赖或 CI、Token JSON、DS-7 实施。相邻模型面板仅回归。
验收:主计划 SC-01—14 按范围记录;本地 related 与受影响包 typecheck 通过;Light/Dark 与旧主题代表场景、键盘/提交失败恢复有真实运行证据;用户已在测试版手动通过。G2 独立贡献者、公开附件、未验证平台明确待项,不以 PR 合入或 Agent 自测冒充目标全部完成。

Signed-off-by: kirozeng <kirozeng@gmail.com>
@kirozeng
kirozeng requested a review from a team as a code owner September 8, 2026 12:35
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 8, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-09T05:42:08.696067Z a4ff17f New commits
🔒 Security Review Completed 2026-09-09T05:40:28.310896Z a4ff17f New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@greptile-apps

greptile-apps Bot commented Sep 8, 2026

Copy link
Copy Markdown

Greptile Summary

本 PR 将自定义模型供应商和 MCP 服务器编辑界面整理为共享设置表单,并为指定删除确认启用标准按钮呈现。

  • 新增 FormField,统一 label、hint、内联错误及无障碍关联。
  • 为 Button 增加 loading 状态,并在实际保存期间防止重复提交和关闭。
  • 统一共享 Input 的焦点环、密码显隐和错误状态。
  • 保留供应商、MCP 配置及凭证参数语义,同时补充相关回归测试。
  • 更新设计规范、决策记录、治理台账及 DS-6 验证证据。

Confidence Score: 5/5

未发现由本 PR 引入的可操作缺陷,当前变更看起来可以安全合并。

两张生产表单的保存、失败恢复和卸载生命周期与调用者一致;共享字段、按钮、输入及确认组件保留了原有业务参数和未迁移调用者行为,审查中没有留下具体的阻塞故障。

Important Files Changed

Filename Overview
apps/desktop/src/renderer/components/settings/CustomProviderDialog.tsx 将供应商表单迁移到共享字段和按钮组件,加入字段首错定位、稳定动态行身份及同步保存守卫。
apps/desktop/src/renderer/components/settings/McpServerDialog.tsx 使用 Radix Dialog 和共享表单控件重构 MCP 编辑界面,同时保留配置、token 与 clearToken 参数语义。
apps/desktop/src/renderer/components/ui/form-field.tsx 新增负责 label、hint、error 和 ARIA 关系的轻量 FormField 组合组件。
apps/desktop/src/renderer/components/ui/button.tsx 新增保留可访问名称和尺寸、阻止重复激活的 loading 呈现。
apps/desktop/src/renderer/components/ui/input.tsx 更新 soft focus ring、错误 ARIA 状态及密码显隐按钮的禁用和提示行为。
apps/desktop/src/renderer/components/ui/confirm-dialog.tsx 增加显式 standard 呈现分支,并保留旧调用者、动作顺序和焦点策略。
apps/desktop/src/renderer/components/settings/tests/McpServerDialog.test.tsx 覆盖字段校验、保存锁定、失败重试、token 语义、动态行身份和焦点恢复。
apps/desktop/src/renderer/components/settings/tests/CustomProviderDialogAccessibility.test.tsx 补充供应商字段错误关联、首错聚焦以及保存期间防重复和失败恢复测试。
docs/design-rules/DESIGN.md 回写 DS-6 表单、loading、普通确认、焦点及表面选择规范。

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[供应商或 MCP 设置入口] --> B[共享 FormField + SettingsTextInput]
    B --> C{客户端校验}
    C -->|失败| D[字段内显示错误并聚焦首错]
    C -->|通过| E[Button loading / 同步重复提交守卫]
    E --> F{保存请求}
    F -->|成功| G[父级关闭弹窗并刷新列表]
    F -->|失败| H[恢复编辑并允许重试]
    A --> I[删除操作]
    I --> J[共享 ConfirmDialog standard 呈现]
Loading

Reviews (1): Last reviewed commit: "chore(design-system): DS-6 对齐最新主线规则并补交付证..." | Re-trigger Greptile

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1cd62f0c59

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/desktop/src/renderer/components/ui/input.tsx Outdated
@MagicLizi MagicLizi added touches:core 改动碰到架构核心路径(review-pr 自动维护,仅展示) touches:large-diff 改动量较大(review-pr 自动维护,仅展示) touches:product-ui 改动碰到产品 / UI 面(review-pr 自动维护,仅展示) touches:rules 改动碰到规则 / 规范文档(review-pr 自动维护,仅展示) labels Sep 8, 2026
@MagicLizi

Copy link
Copy Markdown
Contributor

命中 UI 路径(apps/desktop/src/renderer/components/settings/CustomProviderDialog.tsx / apps/desktop/src/renderer/components/settings/McpServerDialog.tsx / apps/desktop/src/renderer/components/settings/McpServersSection.tsx 等)但 description 未附界面效果证据——建议补充改动后效果:截图/录屏,或改动后界面的 HTML 页面(```html 代码块、.html 附件或在线预览链接),便于确认界面符合 DESIGN.md 设计规范

@MagicLizi

Copy link
Copy Markdown
Contributor

@kirozeng 👋 这个 PR 还有 1 条 review conversation 没 resolve(apps/desktop/src/renderer/components/ui/input.tsx),auto-review 因此暂时跳过、没法继续审查 / 合并。

如果你已经按评论改完或回应了,请到对应 thread 上点 Resolve conversation;全部 resolve 后,下一轮 auto-review 会自动重新审查这个 PR。

review P2:CustomProviderDialog / McpServerDialog 的密码显隐按钮与
行删除按钮的 Tip 经 Portal 渲染,内容层默认 z-[60] 低于手写模态的
z-[10000],悬停/聚焦时提示被宿主弹窗盖住。

- Input 为 secret 眼睛按钮新增 secretTipContentClassName 透传,两张
  表单的密钥/Token 输入传 z-[10001]
- 行删除 Tip 传 contentClassName="z-[10001]",沿用仓内既有惯例
  (SessionShareExportDialog / AccountSwitcherDialog 等)
- DESIGN.md Dialog & Modal 段回写规则,DS-6 证据文件补记录
- 回归测试:两张表单悬停触发后断言可见 tooltip 层含 z-[10001]

Signed-off-by: Kirozeng <kirozeng@gmail.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ecafd62a62

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/desktop/src/renderer/components/ui/input.tsx
@kirozeng

kirozeng commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

本轮按 review 修了表单提示被弹窗盖住的问题(P2),并补上界面效果说明。

改了什么:CustomProviderDialog / McpServerDialog 里密码显隐按钮和"删除此行"按钮的 Tip 经 Portal 渲染到 body,内容层默认 z-[60],低于两张表单手写模态的 z-[10000],悬停/聚焦时提示会被弹窗自己盖住。现在:

  • 行删除按钮的 TipcontentClassName="z-[10001]",与仓内 SessionShareExportDialogAccountSwitcherDialog 等模态内浮层的既有做法一致;
  • 共享 Input 为 secret 眼睛按钮新增 secretTipContentClassName 透传,两张表单的密钥 / Token 输入传 z-[10001](1cd62f0ecafd62)。

验证:

  • 回归测试 × 2(McpServerDialog.test.tsx / CustomProviderDialogAccessibility.test.tsx):悬停触发后断言可见 tooltip 层含 z-[10001],两文件 36 项全部通过;提交前 pnpm test:unit:related 与 desktop typecheck 均通过。
  • 规则已回写 docs/design-rules/DESIGN.md(Dialog & Modal 段)与 docs/design-evidence/2026-09-08/ds6-forms.md

界面效果:下面是静态 HTML 复刻(字段几何与配色 token 取自 cindy-light / cindy-dark,非实机截图)。保存为 .html 打开后,悬停或 Tab 聚焦密码眼睛按钮 / 删除行按钮即可看到提示出现在弹窗之上;勾选"模拟修复前"可对比 z-60 被模态盖住的旧状态。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DS-6 MCP 表单 · 模态内 Tooltip 层级演示</title>
<style>
  :root, [data-theme="light"] {
    --page-bg: #F5F5F0; --surface-elevated: #ffffff; --card-ivory: #FDFDF8;
    --confirm-bg: #FDFDF8; --confirm-title: #1A1A1A; --confirm-desc: #888883;
    --confirm-btn-primary-bg: #3C3F43; --confirm-btn-primary-text: #FCFCFC;
    --border-default: #d7d7d4; --text-primary: #262626; --text-secondary: #888883;
    --text-placeholder: #6B6B67; --eye-icon: #6B6B67; --eye-hover: #262626;
    --tooltip-bg: #3C3F43; --tooltip-text: #FFFFFF;
    --overlay-modal: rgba(0,0,0,0.5); --focus-ring: #417CDD;
    --btn-secondary-hover: #EEEEE9; --shadow: 0 24px 48px rgba(0,0,0,0.18);
  }
  [data-theme="dark"] {
    --page-bg: #181818; --surface-elevated: #2c2c2a; --card-ivory: #1F1F1F;
    --confirm-bg: #1F1F1F; --confirm-title: #D4D4D4; --confirm-desc: #6F6F6F;
    --confirm-btn-primary-bg: #EEEEEE; --confirm-btn-primary-text: #151515;
    --border-default: #3c3c3a; --text-primary: #d4d4d4; --text-secondary: #6F6F6F;
    --text-placeholder: #C1C1C1; --eye-icon: #C1C1C1; --eye-hover: #d4d4d4;
    --tooltip-bg: #181818; --tooltip-text: #FFFFFF;
    --overlay-modal: rgba(0,0,0,0.7); --focus-ring: #417CDD;
    --btn-secondary-hover: #1D1D1D; --shadow: 0 24px 48px rgba(0,0,0,0.5);
  }
  * { box-sizing: border-box; margin: 0; }
  body { font-family: -apple-system, "PingFang SC", "Segoe UI", sans-serif; background: var(--page-bg); min-height: 100vh; padding: 24px; }
  .controls { display: flex; gap: 12px; align-items: center; margin-bottom: 20px; flex-wrap: wrap; }
  .controls button { border: 1px solid var(--border-default); background: var(--surface-elevated); color: var(--text-primary); border-radius: 9999px; padding: 6px 14px; cursor: pointer; font-size: 13px; }
  .controls button.active { background: var(--confirm-btn-primary-bg); color: var(--confirm-btn-primary-text); }
  .controls label { font-size: 13px; color: var(--text-primary); display: flex; gap: 6px; align-items: center; }
  .note { font-size: 12px; color: var(--text-secondary); line-height: 1.6; max-width: 640px; margin-bottom: 8px; }

  /* ── 模态层:真实结构 fixed inset-0 z-[10000](遮罩 + 面板同层) ── */
  .scrim { position: fixed; inset: 0; z-index: 10000; background: var(--overlay-modal); }
  .panel { position: fixed; inset: 0; z-index: 10000; display: flex; align-items: flex-start; justify-content: center; padding-top: 7vh; pointer-events: none; }
  .dialog { pointer-events: auto; width: min(600px, calc(100vw - 32px)); max-height: 88vh; overflow-y: auto; background: var(--confirm-bg); border: 1px solid var(--border-default); border-radius: 12px; box-shadow: var(--shadow); padding: 16px; display: flex; flex-direction: column; gap: 12px; }
  .dialog h2 { font-size: 16px; color: var(--confirm-title); font-weight: 600; }
  .dialog .desc { font-size: 13px; color: var(--confirm-desc); line-height: 1.5; }

  .field { display: flex; flex-direction: column; gap: 4px; }
  .field label { font-size: 13px; font-weight: 500; color: var(--confirm-title); }
  .field .help { font-size: 12px; color: var(--confirm-desc); line-height: 1.5; }
  .input-wrap { position: relative; }
  .input { width: 100%; height: 40px; border-radius: 9999px; border: 1px solid var(--border-default); background: var(--card-ivory); color: var(--text-primary); padding: 0 44px 0 12px; font-size: 14px; outline: none; }
  .input:focus { border-color: var(--text-secondary); box-shadow: 0 0 0 2px rgba(65,124,221,0.5); }
  .input::placeholder { color: var(--text-placeholder); }

  .eye { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); border: none; background: transparent; color: var(--eye-icon); cursor: pointer; border-radius: 50%; display: flex; align-items: center; justify-content: center; width: 24px; height: 24px; }
  .eye:hover { color: var(--eye-hover); }
  .eye:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--focus-ring); }

  .row { display: flex; gap: 8px; align-items: center; }
  .row .input { padding-right: 12px; }
  .icon-btn { flex-shrink: 0; width: 36px; height: 36px; border-radius: 9999px; border: 1px solid var(--border-default); background: var(--surface-elevated); color: var(--text-primary); cursor: pointer; display: flex; align-items: center; justify-content: center; }
  .icon-btn:hover { background: var(--btn-secondary-hover); }
  .icon-btn:focus-visible { outline: none; box-shadow: 0 0 0 2px var(--focus-ring); }

  .legend { font-size: 13px; font-weight: 500; color: var(--confirm-title); margin-top: 2px; }
  .add-link { background: none; border: none; color: var(--text-primary); font-size: 13px; cursor: pointer; padding: 0; align-self: flex-start; }
  .add-link:hover { text-decoration: underline; }

  footer { display: flex; justify-content: flex-end; gap: 8px; padding-top: 4px; }
  .btn { height: 36px; border-radius: 9999px; padding: 0 18px; font-size: 13px; font-weight: 500; cursor: pointer; }
  .btn.secondary { border: 1px solid var(--border-default); background: var(--surface-elevated); color: var(--text-primary); }
  .btn.secondary:hover { background: var(--btn-secondary-hover); }
  .btn.primary { border: none; background: var(--confirm-btn-primary-bg); color: var(--confirm-btn-primary-text); }

  /* ── Tooltip:12px 圆角 / 13px 文本 / 深底白字,Portal 渲染在 body 下 ── */
  .tooltip { position: fixed; z-index: 10001; background: var(--tooltip-bg); color: var(--tooltip-text); border-radius: 12px; padding: 6px 10px; font-size: 13px; line-height: 1.4; box-shadow: 0 4px 16px rgba(0,0,0,0.25); opacity: 0; pointer-events: none; transition: opacity 0.12s ease-out; white-space: nowrap; }
  body.before .tooltip { z-index: 60; }
  .has-tip { position: relative; }
  .tag { display: inline-block; font-size: 11px; color: var(--text-secondary); border: 1px solid var(--border-default); border-radius: 9999px; padding: 1px 8px; margin-left: 8px; vertical-align: 1px; }
</style>
</head>
<body data-theme="light">
  <div class="controls">
    <b style="font-size:13px;color:var(--text-primary)">DS-6 · MCP 服务器表单(静态复刻)</b>
    <button id="light" class="active">Light</button>
    <button id="dark">Dark</button>
    <label><input type="checkbox" id="before"> 模拟修复前(Tooltip z-60,被模态盖住)</label>
  </div>
  <p class="note">静态 HTML 复刻 McpServerDialog 的字段几何与 token 配色(cindy-light / cindy-dark),用于核对本轮 review 修复:模态为手写 <code>fixed inset-0 z-[10000]</code> 层,Tip 经 Portal 渲染,默认内容层 z-[60] 低于模态;修复后传 <code>contentClassName="z-[10001]"</code> / <code>secretTipContentClassName="z-[10001]"</code>。悬停或键盘聚焦(Tab)密码眼睛按钮与删除行按钮可查看提示层级。非实机截图。</p>

  <div class="scrim"></div>
  <div class="panel">
    <div class="dialog" role="dialog" aria-label="添加 MCP 服务器">
      <h2>添加 MCP 服务器</h2>
      <p class="desc">仅支持远程 http / sse 型 MCP。保存后新建或重启的 Agent 会话即可调用,正在运行的 Agent 会话不受影响。</p>

      <div class="field">
        <label>显示名称</label>
        <input class="input" placeholder="例如 我的工具箱" style="padding-right:12px">
      </div>

      <div class="field">
        <label>端点 URL</label>
        <input class="input" placeholder="https://example.com/mcp" style="padding-right:12px">
      </div>

      <div class="field">
        <label>Bearer Token(可选)<span class="tag">已保存</span></label>
        <div class="input-wrap">
          <input class="input" type="password" value="sk-demo-1234" placeholder="留空将删除已存 token">
          <button class="eye has-tip" data-tip="eye" aria-label="显示密钥" aria-pressed="false">
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9.88 9.88a3 3 0 1 0 4.24 4.24"/><path d="M10.73 5.08A10.43 10.43 0 0 1 12 5c7 0 10 7 10 7a13.16 13.16 0 0 1-1.67 2.68"/><path d="M6.61 6.61A13.526 13.526 0 0 0 2 12s3 7 10 7a9.74 9.74 0 0 0 5.39-1.61"/><line x1="2" x2="22" y1="2" y2="22"/></svg>
          </button>
        </div>
        <span class="help">用于鉴权:Claude 会作为 Authorization: Bearer 头发送;Codex 仅支持 Bearer 型鉴权。</span>
      </div>

      <fieldset style="border:none;display:flex;flex-direction:column;gap:8px">
        <legend class="legend">请求头(可选)</legend>
        <div class="row">
          <input class="input" placeholder="Header 名" value="X-Test" style="flex:1">
          <input class="input" placeholder="" value="value" style="flex:1">
          <button class="icon-btn has-tip" data-tip="remove" aria-label="删除此行 1">
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/></svg>
          </button>
        </div>
        <button class="add-link">+ 添加请求头</button>
      </fieldset>

      <footer>
        <button class="btn secondary">取消</button>
        <button class="btn primary">保存</button>
      </footer>
    </div>
  </div>

  <!-- Portal 渲染到 body 的 tooltip 内容层 -->
  <div class="tooltip" id="tip-eye" style="top: 0; left: 0;" role="tooltip">显示密钥</div>
  <div class="tooltip" id="tip-remove" style="top: 0; left: 0;" role="tooltip">删除此行</div>

<script>
  const light = document.getElementById('light'), dark = document.getElementById('dark');
  light.onclick = () => { document.body.dataset.theme = 'light'; light.classList.add('active'); dark.classList.remove('active'); place(); };
  dark.onclick = () => { document.body.dataset.theme = 'dark'; dark.classList.add('active'); light.classList.remove('active'); place(); };
  const before = document.getElementById('before');
  before.onchange = () => { document.body.classList.toggle('before', before.checked); };

  // tooltip 跟随 trigger 定位(真实实现为 Radix Popper;此处仅静态演示层级)
  const eyeTip = document.getElementById('tip-eye'), rmTip = document.getElementById('tip-remove');
  function place() {
    const eye = document.querySelector('.eye');
    const rm = document.querySelector('.icon-btn');
    const r1 = eye.getBoundingClientRect(), r2 = rm.getBoundingClientRect();
    eyeTip.style.top = (r1.top - 34) + 'px'; eyeTip.style.left = Math.round(r1.left + r1.width/2 - eyeTip.offsetWidth/2) + 'px';
    rmTip.style.top = (r2.top - 34) + 'px'; rmTip.style.left = Math.round(r2.left + r2.width/2 - rmTip.offsetWidth/2) + 'px';
  }
  document.querySelectorAll('.has-tip').forEach((el) => {
    const tip = el.dataset.tip === 'eye' ? eyeTip : rmTip;
    el.addEventListener('mouseenter', () => { place(); tip.style.opacity = 1; });
    el.addEventListener('mouseleave', () => (tip.style.opacity = 0));
    el.addEventListener('focus', () => { place(); tip.style.opacity = 1; });
    el.addEventListener('blur', () => (tip.style.opacity = 0));
  });
  window.addEventListener('resize', place);
  window.addEventListener('load', place);
  place();

  // 截图/演示用 URL 参数:?show=eye|remove 自动点亮提示,?before=1 复现修复前层级
  const q = new URLSearchParams(location.search);
  if (q.get('before') === '1') { before.checked = true; document.body.classList.add('before'); }
  if (q.get('theme') === 'dark') { document.body.dataset.theme = 'dark'; dark.classList.add('active'); light.classList.remove('active'); place(); }
  const show = q.get('show');
  if (show === 'eye' || show === 'remove') {
    const tip = show === 'eye' ? eyeTip : rmTip;
    place(); setTimeout(() => { place(); tip.style.opacity = 1; }, 60);
  }
</script>
</body>
</html>

dispatch:07c79a07f8b0b71e

review P1:向导内置供应商与预设 API Key 两个 SettingsTextInput secret
调用点同处 z-[10000] 遮罩内,Tip 默认 z-[60] 仍会被盖住;补传
secretTipContentClassName="z-[10001]"(与两张表单同批修复)。仓内
secret 调用点全景核查:两表单与向导均已抬层,ProvidersSection 的
ImageApiKeyRow 为设置页行内无模态遮罩,保持默认。

Signed-off-by: Kirozeng <kirozeng@gmail.com>
Signed-off-by: Kirozeng <kirozeng@gmail.com>

# Conflicts:
#	docs/design-rules/design-inventory.md
@kirozeng

kirozeng commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

本轮处理了 P1 反馈、CI 缺席排查与主线冲突,情况如下。

P1(向导内密钥 Tooltip 层级):已修复(73290c441)。AddProviderWizard 内置供应商与预设 API Key 两处 SettingsTextInput secret 补传 secretTipContentClassName="z-[10001]"。全仓 secret 调用点核查:两张表单与向导均已抬层,ProvidersSectionImageApiKeyRow 为设置页行内、无模态遮罩,保持默认。提交前 pnpm test:unit:related 与 desktop typecheck 均通过。

CI 缺席(Windows unit tests 等 required context):核实这不是测试失败——client-ci workflow 没有为 ecafd62a6 / 73290c441 这两个 head 启动过任何 run(12:35 1cd62f0c 上的两个 run 正常 success),仓库其它 PR 的 CI 也在正常跑。分支未改 .github/workflows/。最可能的诱因:PR 当时与 main 冲突(merge ref 无法合成)。

主线冲突:已在本地 merge origin/main 解决——冲突仅在 docs/design-rules/design-inventory.md(文件列表取含 CindyMakeSection.tsx 的较新一侧,治理登记行保留 DS-6 的 owner 与登记成员),并按仓库要求重跑 pnpm design:inventory 使 GENERATED 区块与合并后源码同步(check 通过),pnpm test:unit:related 与 typecheck 均通过。受本轮单次推送收口限制,该 merge commit 将随下一次 push 落到 PR;届时冲突解除,若 CI 仍未自动启动,需要在 GitHub 侧人工排查(Actions 页面 re-run 或检查 workflow 状态)。

dispatch:1fc9248fe26310a4

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 73290c4412

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/desktop/src/renderer/components/settings/McpServerDialog.tsx Outdated
Comment thread docs/design-rules/cindy-design-system.md
review P2 ×2:
- McpServerDialog 的 transport 互斥选择从两个独立 Button + aria-pressed
  改用 SettingsSegmentedControl(DESIGN.md §4 Settings segmented
  controls),获得单一 Tab 停靠点、方向键、Home/End 与 RTL 键盘行为,
  不再自造第二套选中态视觉;测试同步改为 radiogroup/radio 断言。
- cindy-design-system.md「新贡献者从这里开始」第 3 条不再说 FormField
  与 Button loading 尚未提供,改指向上方 DS-6 表单贡献入口。

Signed-off-by: Kirozeng <kirozeng@gmail.com>
@kirozeng

kirozeng commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

本轮完成两条 P2 修复、主线冲突合并与 CI 恢复,情况如下。

P2 ×2(均已修复并 resolve 对应 thread):73290c441 之后的 d9daf7538 上——

  • transport 分段控件:McpServerDialog 的互斥选择从两个独立 Button + aria-pressed 改用共享 SettingsSegmentedControl(DESIGN.md §4),获得单一 Tab 停靠点、方向键、Home/End 与 RTL 键盘行为,选中态视觉统一;测试同步改为 radiogroup/radio 断言。
  • 设计索引:cindy-design-system.md「新贡献者从这里开始」第 3 条不再写 FormField 与 Button loading「尚未提供」,改指向同文件上方的 DS-6 表单贡献入口。

主线冲突:已 merge origin/main 解决(唯一冲突在 design-inventory.md:文件列表取含 CindyMakeSection.tsx 的较新一侧,治理登记行保留 DS-6 的 owner 与登记成员),并重跑 pnpm design:inventory 同步 GENERATED 区块(check 通过)。PR 不再冲突。

CI 恢复:前两个 head 上 required context 缺席的根因即冲突——PR 处于 CONFLICTING 时 GitHub 不为其创建 pull_request workflow run。冲突解除后 d9daf7538 上 CI 已完整触发:verify-checks / Git integration / Linux 两分片 / Windows (2/2) 全绿;唯一失败是 Windows (1/2) 的 windowsPackagedInstanceBarrier.test.ts——这是 main 的既有测试,本 PR 未改动该文件(仅 renderer 组件与文档),main 最近三次 CI 该测试均通过,其源码注释亦自证满载 CI 会把健康的 acquire 误杀成超时。判断为 runner 负载下的 flake,建议对 failed jobs 重跑一次确认。

dispatch:3390ff7e6f5f43b6

@kirozeng

kirozeng commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

本轮无代码改动:CI 红灯经核实是 runner 负载下的 flake,已对 failed jobs 重跑确认。

上一轮已论证 d9daf7538 上唯一失败的 windowsPackagedInstanceBarrier.test.ts 与本 PR 无关(PR 未改动该文件,main 最近三次 CI 均通过,其源码注释自证满载 CI 会把健康的 acquire 误杀成超时)。本轮对 run 34250361902 的失败分片执行 re-run(attempt 2):同一 head、同一代码通过,flake 结论被证实。

当前 PR 全部 required checks 绿(DCO / Git integration / Linux ×2 / Windows ×2 / verify / pr-design-basis),merge 状态 CLEAN。review conversation 已全部 resolve。

dispatch:f77c18a8f05a02e5

Signed-off-by: Kirozeng <kirozeng@gmail.com>

# Conflicts:
#	apps/desktop/src/renderer/components/settings/CustomProviderDialog.tsx
#	docs/design-rules/design-decision-log.md
@kirozeng

kirozeng commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

本轮处理新的主线冲突:main 在 CI 转绿后又有约 10 个提交合入,PR 再次 CONFLICTING。已在本地 merge origin/main 解决,merge commit 待下一次 push 落到 PR。

冲突三处及解法:

  • CustomProviderDialog.tsx 模型名与请求头名两处:保留 DS-6 的 FormField 结构(字段级 label / error / 稳定行身份),同时合入 main feat(models): 统一模型资料优先级并接入服务端本地目录 #4108nameExplicit: true 显式命名语义(用户改名后不被动态发现覆盖)——结构与语义两侧都保留。
  • design-decision-log.md:两侧在同一段落各自新增裁决条目,全部保留(DS-6 表单裁决 + main 的两条图标裁决)。

验证:pnpm test:unit:related 与 desktop typecheck 通过,check:design-inventory 同步。受本轮单次推送收口限制(CI flake 轮已占用 receipt),该 merge commit 将随下一次 push 落地,届时 PR 冲突解除、CI 会完整重跑。

dispatch:f77c18a8f05a02e5

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Report: PR #4135

PR: feat(design-system): DS-6 complete form and confirm component reuse
Author: kirozeng
Head: d9daf75
Base: main (0d1a5c7)
Tier: standard
Reviewer: magiclizi (auto-review)
Date: 2026-09-09

Summary

DS-6 migrates the custom provider and MCP server settings forms to shared components (FormField, Button loading, Input enhancements), adds field-level validation with first-error focus, and opts two specific delete confirmations into the standard button presentation. Existing callers and business semantics are preserved through backward-compatible opt-in APIs.

Findings

0 P0, 0 P1 discovered.

Verification

Security and credentials

  • Security content scan: pass (0 hard hits, 0 soft hits)
  • No credentials, tokens, or authorization files in diff
  • Existing credential handling (provider API keys, MCP tokens, safeStorage) unchanged
  • clearToken/hasToken semantics preserved in McpServerDialog

Shared symbols and callers

  • Button: added optional loading prop, backward compatible (defaults false)
  • Input: added optional secretTipContentClassName, backward compatible
  • ConfirmDialog: added optional presentation, unset callers keep existing presentation
  • FormField: new component, no existing callers affected
  • ConfirmDialogProvider: passes through presentation, existing calls unchanged
  • Two explicit presentation standard opt-ins: ProvidersSection.handleDelete, McpServersSection.handleDelete

Error and recovery paths

  • savingRef.current synchronous guard prevents duplicate save submissions
  • Save failure resets both savingRef.current and setSaving(false) on all failure paths
  • Image generation reload confirmation path properly resets saving state
  • Field validation errors use reportFieldError with focus and scroll-into-view
  • Service failures remain as toasts (not field errors)
  • Cancel/Esc/overlay blocked only during actual save via ref guard

Accessibility

  • FormField associates label, hint, error via proper ARIA attributes
  • aria-required (not native required) prevents browser validation
  • aria-invalid set on error state
  • aria-busy on loading buttons
  • aria-pressed on eye toggle and auth mode/wire protocol buttons
  • Eye button disabled when input is disabled
  • MCP transport uses SettingsSegmentedControl (radiogroup/radio) instead of independent buttons

Design rule compliance

  • Focus ring: soft/50% (--focus-ring-soft) per approved DS-6 D1
  • Ivory surface: explicit white-panel usage documented per DS-6 D2
  • Standard confirmation: uses Button component, preserves ordering/focus per DS-6 D3
  • Field errors with first-error focus per DS-6 D4
  • Save lock with recovery per DS-6 D5
  • Modal tooltip z-index: z-[10001] on all modal-internal tips per DS-6 review fix
  • All colors use semantic tokens; no hardcoded color values introduced
  • Light/Dark dual-mode: all styling through themed tokens

Test coverage

  • New: McpServerDialog.test.tsx (field validation, save lock, token semantics, header identity, tooltip z-index)
  • New: formControls.test.tsx (button loading, input secret disabled, confirm ordering/typed/busy)
  • New: formField.test.tsx (ARIA associations, dynamic field identity)
  • Extended: CustomProviderDialogAccessibility.test.tsx (field error focus, save ownership, tooltip z-index)
  • Updated: input.test.tsx (soft focus ring, ivory label)

PR description consistency

  • Description accurately reflects all changes
  • Explicitly scoped: two forms, two delete confirmations, shared components
  • Non-goals clearly stated (full settings, permissions, DS-7)
  • Risk section identifies cross-platform gaps and unverified items
  • Rollback plan documented (revert PR, no data migration needed)

Merge status

  • CI: pass (client-ci success, pr-design-basis success)
  • Maintainer signoff: all three triggers (product, rules, arch) released by zqchris
  • All review threads: resolved
  • Bot settle: timed out (copilot-pull-request-reviewer, chatgpt-codex-connector) -- their opinions may arrive post-merge
  • mergeStateStatus: UNKNOWN at time of live context refresh

Conclusion

Clean review. 0 P0, 0 P1. Recommend merge.

Signed-off-by: Kirozeng <kirozeng@gmail.com>

# Conflicts:
#	docs/design-rules/design-inventory.md

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2b8e588d2e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/desktop/src/renderer/components/settings/CustomProviderDialog.tsx Outdated
@kirozeng

kirozeng commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

冲突已解决,CI 全绿。

main 在上一轮 CI 转绿后又合入两批提交,PR 两度 CONFLICTING。本轮已连续两次 merge origin/main(至 ebcb181a5)并推送(d9daf75382b8e588d2):

推送前已跑 pnpm test:unit:related 与 desktop typecheck;推送后 CI 在 2b8e588d2 一次全绿(verify-checks / Linux ×2 / Windows ×2 / Git integration / DCO)。review conversation 4/4 已 resolve,当前仅待 review approval。

review P2:面板级 onChangeCapture 原先在任意后代输入变化时清空唯一的
fieldError——Base URL 无效时改名称或 API Key 会立即消失 URL 的错误
提示与 aria-invalid,尽管 URL 未修正。现仅在 event.target 即报错字段
本身时清除;其它字段的编辑保留提示直至再次保存重新校验。回归测试
覆盖「改其它字段错误保留 / 改报错字段错误清除」两分支。

Signed-off-by: Kirozeng <kirozeng@gmail.com>
@kirozeng

kirozeng commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

本轮修复字段错误清除逻辑的 P2,并核实 CI 信号。

P2(字段错误过度清除):已修复(751a36a64)。面板级 onChangeCapture 原先在任意后代输入变化时清空唯一的 fieldError——Base URL 无效时改名称或 API Key,URL 的错误提示与 aria-invalid 会立即消失。现在仅在报错字段自身被编辑(target.id === fieldError.id)时清除;其它字段的编辑保留提示直至再次保存重新校验。回归测试覆盖「改其它字段错误保留 / 改报错字段错误清除」两分支,pnpm test:unit:related 与 desktop typecheck 通过,对应 thread 已 resolve。

CI 信号核实:派发时的 "Windows unit tests 缺席" 是陈旧快照——2b8e588d2 上该 required context 实际全绿(run 34311252891)。本轮修复推送后 751a36a64 上 CI 已完整重跑并一次全绿(verify-checks / Linux ×2 / Windows ×2 / Git integration / DCO)。

review conversation 5/5 已 resolve,PR 仅待 review approval。

dispatch:2704bd8962b256eb

Signed-off-by: Kirozeng <kirozeng@gmail.com>

# Conflicts:
#	docs/design-rules/design-inventory.md

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a4ff17f9f5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@kirozeng

kirozeng commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

本轮解决主线冲突:main 又合入一批提交(远程桌面 #4065 等),PR 再次 CONFLICTING。已 merge origin/main(至 c5544d0f9)并推送(751a36a64a4ff17f9f):唯一冲突在 design-inventory.md 的 GENERATED 区块,按合并后源码重新生成(check 通过,人工区保留)。pnpm test:unit:related 与 desktop typecheck 均通过。

CI 在 a4ff17f9f 上:windowsPackagedInstanceBarrier.test.ts 再次在 Windows (1/2) 出现负载 flake(1249/1250 通过,与本 PR 改动无关),对 failed jobs 重跑后全绿。该测试两天内已两次出现同类 flake,建议在 main 侧单独跟进(提高 mutex 竞争预算或加 retry),避免每次都需人工重跑。

注:本次解冲突 push 触发了分支保护的 stale review dismiss,此前的 approval 已失效,需要重新批准后才能合并。

dispatch:d4785b024fa6c549

review P1:上一轮把错误清除收敛到「报错元素自身的 change」后,两个
非输入控件路径会让错误滞留到再次保存:

- 列表级错误(`${agent}:add-model`,模型列表为空,提示挂在「添加模型」
  按钮旁):点该按钮新增行并填写内容时,change 目标是新行输入而非按钮,
  提示不清。现在该 agent 模型行的输入变化同样视为对列表错误的修正。
- applyPreset 程序化替换名称/鉴权/全部 runtime:不触发任何输入 change,
  既有错误指向整体失效。函数内显式清除。

回归测试 ×2:删光模型行保存→重添行填写即清;应用预设即清并核对
名称已被程序化替换。

Signed-off-by: Kirozeng <kirozeng@gmail.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Repo admins can enable using credits for code reviews in their settings.

@kirozeng

kirozeng commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

本轮修复上一轮错误清除语义的反例(P1):非输入控件修正字段时错误滞留。

62472f559 两处补上:

  • 列表级模型错误:删光模型行保存后,错误挂在「添加模型」按钮旁;点该按钮新增行并填写内容时,change 目标是新行输入而非按钮——现在该 agent 模型行的任何输入变化同样视为对列表错误的修正,提示即时清除;
  • applyPreset:程序化替换名称/鉴权/全部 runtime 不触发任何输入 change,既有错误指向整体失效——函数内显式清除。

普通输入的语义保持上一轮的收敛(只在报错字段自身被编辑时清除)。回归测试 ×2(33 项全过),pnpm test:unit:related 与 desktop typecheck 通过;62472f559 上 CI 一次全绿。对应 thread 已 resolve。

dispatch:f16e1502cfe07773

@kirozeng

kirozeng commented Sep 9, 2026

Copy link
Copy Markdown
Contributor Author

已核实本轮反馈,无需代码改动:该评论是 Codex 的用量通知(code review 额度已用尽,提示仓库管理员在设置中增加 credits),属于机器人运营消息,不含任何代码审查意见。PR 当前状态不变:CI 全绿、无冲突、已获批准,等待合并。

dispatch:3371894b6adb46db

@MagicLizi MagicLizi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Findings

  • 无 P0/P1。

Rule coverage

  • AGENTS.md / docs/dev-rules/development-workflow.md:范围与 PR 描述一致;未改凭证存储、MCP/provider 配置语义、协议或 CI。提交带 Signed-off-by。
  • docs/design-rules/DESIGN.md §4 Buttons / Inputs & Forms / Dialog & Modal、§5、cindy-design-system.md、design-governance.md:FormField 只做 label/hint/error 关联且 required 仅 aria;Input 焦点环改为 --focus-ring-soft,错误态优先;ivory 仍为显式白面板;Button loading 保留可访问名称、aria-busy、禁用再激活;ConfirmDialog presentation=standard 为 opt-in,未选调用者走旧分支;两处删除确认显式 opt-in。模态内 Tip 抬到 z-[10001](表单、向导密钥)。规范回写与 D1—D5 裁决一致。
  • docs/dev-rules/engineering-conventions.md:未新增 IPC/日志协议;服务失败仍 Toast;i18n 走既有 key。
  • docs/dev-rules/electron-security-and-process-boundaries.md:仍走既有 maker IPC / customMcpServers / customProviders;token 不改 clearToken 语义;Renderer 无 Node/凭证直写。
  • docs/dev-rules/configuration-and-overrides.md:未改配置分层、默认值或 override 语义。
  • docs/dev-rules/credentials-and-local-storage.md:密钥仍经既有 read/update;hydration 未完成时空 token 不清已存值(测试覆盖)。
  • PR 描述吻合:两张设置表单、两处普通删除确认、FormField/Button loading/Input 焦点与文档测试;未夹带 Permission/Full Access/插件授权或依赖/CI。讨论 issue 无。既有 thread 均已 resolve,对应修复在 head 上可核对。

Verification

  • 凭证/隐私门:security.pass=true,hardHits=0。
  • 格式门:formatPass=true。uiEvidenceMissing=true(模板未嵌截图),作者后续评论已附静态 HTML 复刻;不阻断。
  • CI:gate.ci.status=pass(client-ci / pr-design-basis success);mergeable CLEAN。
  • 本 worktree 无 node_modules,未在本 agent 重跑 pnpm test:unit:related / typecheck。CI 与作者声明的 related/typecheck 作为外部证据,不把未运行写成通过。
  • botSettle:timedOut=true(copilot-pull-request-reviewer / chatgpt-codex-connector 未对当前 head 表态),按上限放行。

Overall

pass — 没有 P0/P1。

@MagicLizi
MagicLizi merged commit 6559d26 into makecindy:main Sep 9, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

touches:core 改动碰到架构核心路径(review-pr 自动维护,仅展示) touches:large-diff 改动量较大(review-pr 自动维护,仅展示) touches:product-ui 改动碰到产品 / UI 面(review-pr 自动维护,仅展示) touches:rules 改动碰到规则 / 规范文档(review-pr 自动维护,仅展示)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants