Replies: 4 comments
|
补充验证(比正文里那两条更强): 1. 整包测试全绿,不只是我改的两个 spec: 2. 类型检查零增量。 该包在未跑 63 条全部落在 也就是说:这个补丁在类型和 lint 两个维度上都不引入新问题;仓库既有的那批错误是缺少生成契约导致的,与本改动无关。 3. 分支:https://github.com/zh0122/deepseek-harness/tree/fix/welcome-notice-error-copy (commit 未能完成的验证:仓库的 |
|
再补一条状态更新,方便维护者取用。 1. 该缺陷在当前 master 上仍然存在。 我核对了 行号与正文里给的完全一致,未被修掉。 2. 分支基线是发布 tag 3. 上游 master 在我 clone 之后前进了 258 个提交,但没有一个动过 4. 我确实变基到当前 master 并复跑了全部验证,结论与正文一致: 5. 但变基后的那个提交我推不上去,所以 fork 上的分支仍停在 rc.2 基线( 给 考虑到本仓库 Pull requests 功能已关闭( |
|
补一条:我把正文末尾那句「同类问题可能不止这一处」实际查了,结论是没有同类需要一起改的,补丁是完整的。把边界记在这里,免得维护者以为我漏查。 判据用正文那条:可区分的失败原因被压成单句通用文案,且运行在不可关闭的容器里。两条都要满足——只满足前一条是 UX 取舍,只满足后一条不构成"卡死"。 先确认容器这一条成立。 它只有两个使用方,逐个查: 1. 2. 然后是容器外那几处,逐个说明为什么不该跟着改: 3. {state.error === null ? null : <span className={css.error} role="alert">{t('openDocument.error')}</span>}形状看着一模一样,但 store 的字段注释写明了这是有意的设计决定: // settings-document-store.ts:16
/** Last metadata/native-open diagnostic; UI exposes only localized copy. */
error: string | null宿主原始诊断( (若维护者认为宿主诊断值得露出,那是独立的 i18n 取舍:宿主消息是英文的,直接渲染会牺牲本地化。 4.
顺带一提,仓库里已有正确写法的先例,我的改法就是照它来的: // ui-user-questions/src/client/QuestionComposer.tsx:609
{error === null ? null : 'key' in error ? t(error.key) : error.text}判别联合 + 按键取文案,和本补丁的 结论:不需要扩大改动范围。8 文件 +56/-15 就是全部。 |
|
最后补一块证据缺口:前面所有验证跑的都是源码(vitest 直接吃 对产物
最后两行是重点:用户在界面上实际看到的那句字符串,在构建产物里已经完全不存在;新键名出现 3 次说明「原因 → 文案」的映射没有被打包过程消解掉。 至此四条独立验证全部闭合:源码单测(304 全绿)、lint 与 tsc 相对基线零增量、双语配对一致、构建产物携带新文案且旧文案归零。 唯一的局限仍是正文和第一条评论里说过的那条:仓库 |
Uh oh!
There was an error while loading. Please reload this page.
现象
dsh 0.2.0-rc.2 / Windows 11 /
dsh web(profileweb,监听 127.0.0.1)。每次打开 Web 界面都弹出「预览版说明」模态框,并带一行红色错误:
点「继续」无效,刷新无效,重启无效。该模态框无法被关闭(
OnboardingModal屏蔽 Escape、遮罩点击,并把背景置为inert),因此引导流程被完全卡死,拿不到任何可据以行动的信息。根因
失败原因在 store 里已经区分好了,但渲染层把它丢掉了。
packages/client/ui-settings-models/src/client/welcome-store.ts有两个不同的失败来源:而
packages/client/ui-settings-models/src/client/WelcomeNotice.tsx:64只判断了null,随后硬编码渲染同一个键:state.error的值从未被读取。于是两种语义完全相反的失败——结构性的、重试永远不会成功的(宿主没暴露 namespace)和瞬时的、值得再试一次的(写入被拒)——对用户呈现为同一句「请重试」。进一步说,这两句字符串是机器可读的原因标识,却既没有类型约束也没有被消费;
WelcomeNoticeState.error声明为string | null,任何拼写漂移都不会被发现。信息丢失链
宿主其实返回了更细的信号,一路被逐层丢弃:
settings-mirror.ts捕获了宿主的错误消息(response.error.message)→ 存入mirror.errorconfig-form-types.ts的ConfigFormSnapshot没有 error 字段 → 消息在此丢失,只剩status: 'unavailable'welcome-store.ts自己另编两个自由字符串WelcomeNotice.tsx连state.error都不看第 2 步要动
dsh-client-ui-settings的公开契约、影响所有设置页,范围过大。但第 3、4 步完全可以在ui-settings-models包内闭合,已经足够把「不可行动」变成「可行动」。复现
最可靠的一条是走
unavailable分支:让宿主的settings.describe()返回不含ui-settings-general的 namespace 列表即可。仓库现有测试已经覆盖到这个状态:packages/client/ui-settings-models/tests/welcome-store.client.spec.ts→reports a missing namespace as an error instead of a silent skip该用例断言 store 进入
status: 'error',但没有任何用例断言此时弹窗渲染了什么——渲染层丢弃原因这件事因此不在覆盖范围内。现场触发条件(我这边的实际情况):
~/.dsh/profiles/web/cordis.patch.yml自创建起一直是[],即该确认从未被持久化过。建议修复
已实现并推到 fork 分支(本仓库 PR 功能已关闭,故只给分支):
https://github.com/zh0122/deepseek-harness/tree/fix/welcome-notice-error-copy
commit
42c4499aa,8 文件 +56/-15:welcome-store.ts:error由string | null收窄为闭合联合WelcomeNoticeErrorReason | null('settings-unavailable' | 'not-persisted')WelcomeNotice.tsx:文案映射{ [Reason in WelcomeNoticeErrorReason]: keyof typeof en }对该联合是全射,因此新增一个原因若没配套文案就无法通过类型检查,不会再退化成静默走通用文案locales.ts:en/zh 各两条可行动文案——不可达时明说重试无益并指回 dsh 启动时打印的地址;写入被拒时仍提示可再试docs/i18n契约重录README.i18n.yaml配对哈希验证:
staged oxlint 干净;全包 oxlint 与
git stash基线逐条对比 81 = 81,findings 完全相同(该包在未build:lib:host时本就有 81 条no-unsafe-*类型感知告警);verify-translation-pairing重录后复检通过。环境
npx @deepseek-ai/dsh@latest web)web,bundles =dsh-base/dsh-web-app/dsh-plugin@1.4.8/dsh-better-sidebar@0.16.1备注
同类问题可能不止这一处:任何把宿主错误压成单句通用文案、又运行在不可关闭容器里的界面,都会产生同样"卡死且无从下手"的效果。若维护者认为值得,可以把「模态不可关闭 ⇒ 错误文案必须可行动」作为一条约定。
All reactions