Ver código fonte

fix(ci): admit any `.css` refusal for the dockkit corpus exemption

The built-bundle import sweep pinned the Dockkit exemption to
`packages/client/ui-dockkit/lib/components/dockkit.module.css`, but the built
bundle imports `@deepseek-ai/dsh-client-ui-primitives` before its own
stylesheet, and the tsx launcher resolves that specifier through tsconfig
`paths` into the dependency's `src` tree. The sweep therefore reports
`packages/client/ui-primitives/src/StateDot.module.css`, so the pinned path can
never match where client build output exists; the Windows complete-gate
inventory reports the exempt bundle as an unexpected baseline failure.

Admit Node's unknown-`.css`-extension refusal for any stylesheet and keep every
other failure a finding. The classification controls cover an admitted Dockkit
stylesheet, the dependency's source stylesheet, another extension, an arbitrary
message, another error code, and a stale exemption.

Agent Note: .agents/notes/implemented/bug-fix/2026-09-10-built-bundle-css-exemption.md
turtle1999 1 semana atrás
pai
commit
529434e1df

+ 6 - 0
.agents/notes/implemented/bug-fix/2026-09-10-built-bundle-css-exemption.i18n.yaml

@@ -0,0 +1,6 @@
+# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
+# side as of the last confirmed-consistent state. Both languages carry equal authority;
+# after editing either side, bring the other along and re-record with:
+#   pnpm run verify-translation-pairing --write .agents/notes/implemented/bug-fix/2026-09-10-built-bundle-css-exemption.md
+2026-09-10-built-bundle-css-exemption.md: 81ff2770c675675cc43b34ecbad2b03fb1b2e34b
+2026-09-10-built-bundle-css-exemption.zh.md: 77de7138017ca053eda0ed0d6b16f2e32c5a5857

+ 27 - 0
.agents/notes/implemented/bug-fix/2026-09-10-built-bundle-css-exemption.md

@@ -0,0 +1,27 @@
+# Agent Note: Built-bundle exemption for a failing stylesheet
+
+Status: implemented
+
+English | [中文](2026-09-10-built-bundle-css-exemption.zh.md)
+
+## Problem
+
+The [Node import sweep](../../../../packages/experimental/webworker-runtime/tests/compile/transform-corpus-check.ts) exempts the Dockkit bundle because Node cannot load its stylesheets, and admitted one exact stylesheet path as the evidence: `packages/client/ui-dockkit/lib/components/dockkit.module.css`. The built bundle imports the workspace package `@deepseek-ai/dsh-client-ui-primitives` before its own stylesheet, and the `tsx` launcher resolves that specifier through tsconfig `paths` into the dependency's `src` tree, so the sweep reports `ERR_UNKNOWN_FILE_EXTENSION` for `packages/client/ui-primitives/src/StateDot.module.css`. The pinned path cannot match on a tree with client build output, and the Windows complete-gate inventory reported the exempt bundle as an unexpected baseline failure.
+
+## Decision
+
+The Dockkit exemption admits Node's unknown-`.css`-extension refusal for any stylesheet. Another extension, another error code, and an unrelated error message stay findings, as does an exempt bundle that imports cleanly.
+
+## Alternatives considered
+
+**Admit the dependency's source stylesheet alongside the pinned one.** That file is what the sweep reports, but the bundle's import order and the launcher's path mapping select it. Pinning it would certify those two details instead of the `.css` exemption.
+
+**Classify every CSS exemption by the same rule.** The Dockkit pin is the recorded evidence this change corrects; the other two stylesheet exemptions were never classified, and tightening them would change what they admit beyond the reported defect.
+
+**Drop the classification and admit any failure.** A bundle that stopped importing for an unrelated reason would then hide inside the exemption total.
+
+## Consequences
+
+The sweep reports the Dockkit bundle when it stops importing for any reason other than a `.css` import, and the entry no longer asserts which stylesheet fails. [Scoped resolve/load hooks](../../../../packages/experimental/webworker-runtime/tests/compile/transform-corpus.spec.ts) exercise an admitted Dockkit stylesheet, the dependency's source stylesheet, another extension, an arbitrary message, another error code, and a stale exemption without modifying shared build artifacts.
+
+The [CI observation decision](../testing/2026-09-08-ci-completion-observations.md) keeps the fixture completion and isolation decisions it owns; its built-client classification paragraph keeps the sweep summary and links here for the admitted evidence.

+ 27 - 0
.agents/notes/implemented/bug-fix/2026-09-10-built-bundle-css-exemption.zh.md

@@ -0,0 +1,27 @@
+# Agent Note: 构建产物豁免以失败的样式表为准
+
+Status: implemented
+
+[English](2026-09-10-built-bundle-css-exemption.md) | 中文
+
+## 问题
+
+[Node import sweep](../../../../packages/experimental/webworker-runtime/tests/compile/transform-corpus-check.ts)因 Node 无法加载 Dockkit bundle 的样式表而豁免该 bundle,并曾以一个精确的样式表路径作为接受证据:`packages/client/ui-dockkit/lib/components/dockkit.module.css`。该已构建 bundle 在导入自身样式表之前先导入 workspace 包 `@deepseek-ai/dsh-client-ui-primitives`,`tsx` 启动器又通过 tsconfig `paths` 把这个说明符解析进依赖的 `src` 树,因此 sweep 报告的是 `packages/client/ui-primitives/src/StateDot.module.css` 的 `ERR_UNKNOWN_FILE_EXTENSION`。固定路径在带有 client 构建输出的树上无法匹配,Windows 完整门禁的清单于是把这个豁免 bundle 报告为意外的基线失败。
+
+## 决策
+
+Dockkit 豁免接受 Node 对任意样式表因未知 `.css` 扩展名而拒绝加载。其他扩展名、其他错误码和无关的错误消息仍计为发现,能顺利完成导入的豁免 bundle 同样计为发现。
+
+## 考虑过的替代方案
+
+**在固定路径之外同时接受依赖的源样式表。** sweep 报告的正是该文件,但选中它的是 bundle 的导入顺序和启动器的路径映射。固定该路径认定的将是这两处细节,而非 `.css` 豁免。
+
+**用同一规则分类每个 CSS 豁免。** Dockkit 固定路径是本次修改所纠正的已记录证据;另外两个样式表豁免从未被分类,收窄它们会在所报告缺陷之外改变其接受的内容。
+
+**放弃分类,接受任何失败。** 届时因无关原因停止导入的 bundle 会隐藏在豁免总数之内。
+
+## 后果
+
+只要 Dockkit bundle 因 `.css` 导入之外的任何原因停止导入,sweep 就会报告它,该条目也不再断言失败的是哪个样式表。[限定范围的 resolve/load hook](../../../../packages/experimental/webworker-runtime/tests/compile/transform-corpus.spec.ts)覆盖被接受的 Dockkit 样式表、依赖的源样式表、其他扩展名、任意消息、其他错误码和陈旧豁免,不修改共享构建产物。
+
+[CI 观察决策](../testing/2026-09-08-ci-completion-observations.zh.md)保留其拥有的 fixture 完成与隔离决策;其已构建 Client 导入分类段落保留 sweep 摘要,并就被接受的证据链接到本文。

+ 2 - 2
.agents/notes/implemented/testing/2026-09-08-ci-completion-observations.i18n.yaml

@@ -2,5 +2,5 @@
 # side as of the last confirmed-consistent state. Both languages carry equal authority;
 # after editing either side, bring the other along and re-record with:
 #   pnpm run verify-translation-pairing --write .agents/notes/implemented/testing/2026-09-08-ci-completion-observations.md
-2026-09-08-ci-completion-observations.md: 8af4685a5e2c51c1edf4a41b47088916223e7a6c
-2026-09-08-ci-completion-observations.zh.md: e3147bb7ac39877b46820862e9af4645803a37a2
+2026-09-08-ci-completion-observations.md: e3de87a70419778407b5eb230cec64ce088dd0c0
+2026-09-08-ci-completion-observations.zh.md: 4e95d6fb9dc9b1ecac2e3d0dfa262b819de16261

+ 1 - 1
.agents/notes/implemented/testing/2026-09-08-ci-completion-observations.md

@@ -30,7 +30,7 @@ The [LSP backpressure test](../../../../packages/lsp/lsp-stdio/tests/instance.sp
 
 ### Built-client import classification
 
-The [Node import sweep](../../../../packages/experimental/webworker-runtime/tests/compile/transform-corpus-check.ts) admits the Dockkit bundle only when Node reports `ERR_UNKNOWN_FILE_EXTENSION` for its exact `dockkit.module.css` path. Other errors and unexpectedly successful exempt imports fail. Scoped resolve/load hooks exercise expected CSS failure, arbitrary failure, another stylesheet, another error code, and stale exemption without modifying shared build artifacts.
+The [Node import sweep](../../../../packages/experimental/webworker-runtime/tests/compile/transform-corpus-check.ts) admits the Dockkit bundle only when Node reports `ERR_UNKNOWN_FILE_EXTENSION` for a `.css` file, and fails every other error and every unexpectedly successful exempt import; the [stylesheet exemption decision](../bug-fix/2026-09-10-built-bundle-css-exemption.md) owns which stylesheets that covers. Scoped resolve/load hooks exercise expected CSS failure, another stylesheet, another extension, arbitrary failure, another error code, and stale exemption without modifying shared build artifacts.
 
 ## Alternatives considered
 

+ 1 - 1
.agents/notes/implemented/testing/2026-09-08-ci-completion-observations.zh.md

@@ -30,7 +30,7 @@ Status: implemented
 
 ### 已构建 Client 的导入分类
 
-[Node import sweep](../../../../packages/experimental/webworker-runtime/tests/compile/transform-corpus-check.ts)只有在 Node 针对准确的 `dockkit.module.css` 路径报告 `ERR_UNKNOWN_FILE_EXTENSION` 时才接受 Dockkit bundle。其他错误以及意外成功的豁免导入都会失败。限定范围的 resolve/load hook 覆盖预期 CSS 失败、任意失败、其他 stylesheet、其他错误码和过期豁免,不修改共享构建产物。
+[Node import sweep](../../../../packages/experimental/webworker-runtime/tests/compile/transform-corpus-check.ts)只有在 Node 针对某个 `.css` 文件报告 `ERR_UNKNOWN_FILE_EXTENSION` 时才接受 Dockkit bundle,其他每个错误以及每个意外成功的豁免导入都会失败;该豁免覆盖哪些样式表由[样式表豁免决策](../bug-fix/2026-09-10-built-bundle-css-exemption.zh.md)拥有。限定范围的 resolve/load hook 覆盖预期 CSS 失败、其他样式表、其他扩展名、任意失败、其他错误码和陈旧豁免,不修改共享构建产物。
 
 ## 考虑过的替代方案
 

+ 2 - 2
packages/experimental/webworker-runtime/README.i18n.yaml

@@ -2,5 +2,5 @@
 # side as of the last confirmed-consistent state. Both languages carry equal authority;
 # after editing either side, bring the other along and re-record with:
 #   pnpm run verify-translation-pairing --write packages/experimental/webworker-runtime/README.md
-README.md: 67604adeb60f83953bc7c6841aa5d3d85ca38448
-README.zh.md: 985345efc3bc4fe63226a3e76b3432fa4bde06fa
+README.md: 072194713d3038fd714855c13a05dc213d20f4b1
+README.zh.md: 79f17edb958516dab94b42869a3a6d6cf11cb8b9

+ 1 - 1
packages/experimental/webworker-runtime/README.md

@@ -32,7 +32,7 @@ Three build artifacts and one source-owned process layer:
 
 Acceptance lives in `apps/web/tests/preview-boot.e2e.ts`, which serves the real built pages and drives the pre-boot chooser plus Worker activation in headless Chromium. The empty selection exercises first-run startup. The `vfs-example` overlay supplies ordinary workspace files and plaintext persistence artifacts for cold Workspace/Session discovery, tool presentation, subagent navigation, and history paging without a model request. The fixture generator owns current-generation logs and the projection cache; committed predecessor logs remain byte-identical alongside them. The chooser reserves WebFS as a separate user-authorized source; that provider does not read the built-in fixture.
 
-The [built-bundle import sweep](tests/compile/transform-corpus-check.ts) checks bare Node imports after the library build. Its Dockkit exception accepts only Node’s unknown-extension error for the expected stylesheet; other failures and unexpectedly successful exempt imports remain errors. See the [CI observation decision](../../../.agents/notes/implemented/testing/2026-09-08-ci-completion-observations.md).
+The [built-bundle import sweep](tests/compile/transform-corpus-check.ts) checks bare Node imports after the library build. Its Dockkit exception accepts Node’s unknown-`.css`-extension refusal for any stylesheet rather than one pinned path; another extension or error code, and an unexpectedly successful exempt import, remain errors. See the [stylesheet exemption decision](../../../.agents/notes/implemented/bug-fix/2026-09-10-built-bundle-css-exemption.md).
 
 -----
 

+ 1 - 1
packages/experimental/webworker-runtime/README.zh.md

@@ -32,7 +32,7 @@ kind: "package-library"
 
 验收在 `apps/web/tests/preview-boot.e2e.ts`:静态服务真实构建页面,在 headless Chromium 里驱动 pre-boot 选择面板与 Worker 激活。空白选择验证首次启动;`vfs-example` overlay 提供普通 workspace 文件与明文 persistence 产物,无需模型请求即可验证 Workspace/Session 冷发现、工具呈现、subagent 导航和历史分页。fixture 生成器负责当前代日志与投影缓存;已提交的前代日志逐字节保持不变,与它们并存。选择面板为 WebFS 保留独立的用户授权来源;该 provider 不读取内置 fixture。
 
-[已构建 bundle 导入检查](tests/compile/transform-corpus-check.ts)在库构建后检查裸 Node 导入。Dockkit 例外仅接受 Node 针对预期样式表报告的未知扩展名错误;其他失败以及意外成功的豁免导入仍然报错。参见 [CI 观察决策](../../../.agents/notes/implemented/testing/2026-09-08-ci-completion-observations.zh.md)。
+[已构建 bundle 导入检查](tests/compile/transform-corpus-check.ts)在库构建后检查裸 Node 导入。Dockkit 例外接受 Node 针对任意样式表报告的未知 `.css` 扩展名错误,而不限定某一固定路径;其他扩展名或错误码,以及意外成功的豁免导入,仍然报错。参见 [样式表豁免决策](../../../.agents/notes/implemented/bug-fix/2026-09-10-built-bundle-css-exemption.zh.md)。
 
 -----
 

+ 16 - 5
packages/experimental/webworker-runtime/tests/compile/transform-corpus-check.ts

@@ -24,7 +24,6 @@ import { fileURLToPath, pathToFileURL } from 'node:url'
 
 const repositoryRoot = fileURLToPath(new URL('../../../../../', import.meta.url))
 const DOCKKIT_BUNDLE = 'packages/client/ui-dockkit/lib/index.js'
-const DOCKKIT_CSS = join(repositoryRoot, 'packages/client/ui-dockkit/lib/components/dockkit.module.css')
 
 /**
  * Files Node's ESM loader cannot import in this repository. None is a finding:
@@ -34,6 +33,11 @@ const DOCKKIT_CSS = join(repositoryRoot, 'packages/client/ui-dockkit/lib/compone
  * imports the win32-process package earlier in the serial sweep (a distinct
  * module instance under its node_modules URL), so win32-process's own file-URL
  * import re-registers koffi's type names and fails as the second load.
+ *
+ * The Dockkit entry admits only Node's refusal of a `.css` import, not one
+ * exact stylesheet: the swept bundle's first unresolvable stylesheet depends on
+ * its import graph and on how the launcher resolves workspace packages, so a
+ * pinned path would certify an import order instead of the `.css` exemption.
  */
 const BASELINE_EXEMPT: ReadonlyMap<string, string> = new Map([
   [DOCKKIT_BUNDLE, 'imports .css, which bare Node cannot load'],
@@ -95,6 +99,16 @@ function discover(): string[] {
  */
 const relative = (path: string): string => path.slice(repositoryRoot.length).replaceAll('\\', '/')
 
+/**
+ * @param reason - the value the corpus import rejected with.
+ * @returns whether bare Node refused a `.css` import, the failure the Dockkit
+ * exemption admits.
+ */
+const isUnknownCssExtension = (reason: unknown): boolean =>
+  reason instanceof Error
+  && 'code' in reason && reason.code === 'ERR_UNKNOWN_FILE_EXTENSION'
+  && reason.message.startsWith('Unknown file extension ".css" for ')
+
 const files = process.argv.slice(2).length > 0
   ? process.argv.slice(2).map(path => (path.startsWith('/') ? path : join(process.cwd(), path)))
   : discover()
@@ -111,10 +125,7 @@ if (files.length === 0) {
     try {
       await import(pathToFileURL(file).href)
     } catch (reason) {
-      const expectedDockkitCss = reason instanceof Error
-        && 'code' in reason && reason.code === 'ERR_UNKNOWN_FILE_EXTENSION'
-        && reason.message === `Unknown file extension ".css" for ${DOCKKIT_CSS}`
-      if (exemption === undefined || (key === DOCKKIT_BUNDLE && !expectedDockkitCss)) {
+      if (exemption === undefined || (key === DOCKKIT_BUNDLE && !isUnknownCssExtension(reason))) {
         // A bundle that stopped being importable is a real finding, so it
         // fails rather than joining a tolerated total.
         fail(`- UNEXPECTED BASELINE FAILURE ${key}: ${(reason as Error).message.split('\n')[0]}`)

+ 14 - 4
packages/experimental/webworker-runtime/tests/compile/transform-corpus.spec.ts

@@ -32,19 +32,29 @@ test('every built bundle imports under Node', (context) => {
 }, 900_000)
 
 // The hook replaces only the chosen bundle; shared build artifacts stay intact.
+// The admitted evidence is Node's unknown-`.css`-extension refusal whatever
+// stylesheet it names; another extension, error code, or message is a finding.
 test.each([
   ['expected-css', 0, 'baselineExempt=1 unexpectedBaselineFailure=0'],
+  ['other-css', 0, 'baselineExempt=1 unexpectedBaselineFailure=0'],
+  ['other-extension', 1, '- UNEXPECTED BASELINE FAILURE'],
   ['error', 1, '- UNEXPECTED BASELINE FAILURE'],
-  ['other-css', 1, '- UNEXPECTED BASELINE FAILURE'],
   ['other-code', 1, '- UNEXPECTED BASELINE FAILURE'],
   ['clean', 1, '- STALE EXEMPTION'],
 ] as const)('classifies dockkit import: %s', (mode, status, finding) => {
   const root = new URL('../../../../../', import.meta.url)
   const bundle = 'packages/client/ui-dockkit/lib/index.js'
-  const css = fileURLToPath(new URL('packages/client/ui-dockkit/lib/components/dockkit.module.css', root))
+  const cssBase = fileURLToPath(new URL('packages/client/ui-dockkit/lib/components/dockkit.module', root))
+  const extension = mode === 'other-extension' ? '.wasm' : '.css'
+  // The other stylesheet is the dependency's, which the launcher resolves into
+  // its source tree: the sweep reports it where an exact-path admission would
+  // reject the bundle.
+  const file = mode === 'other-css'
+    ? fileURLToPath(new URL('packages/client/ui-primitives/src/StateDot.module.css', root))
+    : `${cssBase}${extension}`
   const message = mode === 'error'
     ? 'dockkit-negative-control'
-    : `Unknown file extension ".css" for ${mode === 'other-css' ? `${css}.other.css` : css}`
+    : `Unknown file extension "${extension}" for ${file}`
   const source = mode === 'clean'
     ? 'export {}'
     : `throw Object.assign(new Error(${JSON.stringify(message)}), { code: ${JSON.stringify(mode === 'other-code' ? 'ERR_OTHER' : 'ERR_UNKNOWN_FILE_EXTENSION')} })`
@@ -74,7 +84,7 @@ test.each([
   expect(finished.signal).toBeNull()
   expect(finished.status, output).toBe(status)
   expect(output).toContain(finding)
-  if (mode === 'error' || mode === 'other-css' || mode === 'other-code') {
+  if (finding.startsWith('- UNEXPECTED BASELINE FAILURE')) {
     expect(output).toContain(`- UNEXPECTED BASELINE FAILURE ${bundle}: ${message}\n`)
   }
 })