Skip to content

fix(native): 被忽略生成文件快照会匹配 node_modules,大型 JS 项目中固定为「不完整」;修复时需同时考虑 dev server 持续改写 .next #501

Closed

Description

@i229587

🔎 Existing issue check

  • I have searched the existing issues.

🎯 Affected area

Native workflow runtime (domains/comet-native)

📦 Comet version

0.5.0

💥 Current behavior

native-portable-checks.js 的 nativeIgnoredCheckInputSnapshot(),用 :(glob)<dir>/** 和 :(glob)**/<dir>/** 匹配生成目录(build、dist、out、target、.next 等),再执行 git ls-files --others --ignored --exclude-standard 收集文件。

**/dist/**、**/build/** 会深入已被忽略的 node_modules,把每个依赖包的产物也匹配进来。我们的 Next.js 项目中命中约 39 万个文件(其中约 38.8 万个在 node_modules 下,项目自身只有约 1,700 个,主要在 .next/dev),超过 NATIVE_IGNORED_INPUT_MAX_FILES = 20_000,因此这部分快照固定为 { complete: false, files: [] }。

影响:

  1. 生成产物实际没有被绑定:项目自己的 .next/**、dist/** 不会进入指纹,「生成文件变化即视为输入变化」的保护在大型 JS 项目中不生效,且没有任何提示。
  2. 不完整快照仍然允许复用旧检查结果:快照不完整时,快速复用指纹(gate)为 null,但完整指纹仍然稳定地算出同一个值,复用判断没有因为 gate === null 拒绝复用。实测结果:在 node_modules/pkg/dist 下放 20,001 个文件,检查读取 dist/input.txt,通过后把内容改坏,再执行时 Runtime 仍然复用之前的 passed 结果。代码注释里写的「强制重新执行」与实际行为不符。后果是生成产物变化后,可能用旧的通过结果去验收新的候选。
  3. 每次计算指纹都要额外花费数秒:git ls-files --others --ignored 会遍历整个被忽略的 node_modules。在本项目中单次约 8 秒(热缓存下也一样),每次预留和校验检查都会调用多次。

修复时需要注意的隐患:上面的问题目前恰好掩盖了另一个问题。一旦生成目录快照不再超限,.next/** 就会真正被绑定:

  • Next.js 的类型检查确实依赖其中一部分:tsconfig.json 默认包含 .next/types/**/*.ts,next-env.d.ts 引用 .next/dev/types/*.d.ts,这两处都由 Next.js 自动生成和维护。
  • 但 next dev 运行期间会持续改写 .next/cache、.next/trace、.next/dev/**。只要 dev server 开着,「检查结束」到「Verifier 提交」之间指纹就会变化,native-sdk-checks 的输入漂移校验会报 NativeSdkCheckInputDriftError,重现 Question: native 模式阶段交接也不顺畅,希望规则更简明直白,让流程少折腾 #455(.pytest_cache)那样的 refreshChecks 死循环。这一点根据代码推断,尚未在 dev server 运行时实际复现。

✅ Expected behavior

被忽略生成文件的快照只覆盖项目自身的生成产物,不深入 node_modules 等依赖目录,也不因遍历依赖目录拖慢指纹计算;绑定的范围只包含会影响检查结果的文件,不因 dev server 写缓存而漂移;快照不完整时不复用已有检查结果,并给出原因。

🔁 Steps to reproduce

在任何带 node_modules 的中大型 JS 项目根目录执行:

P=""; for d in build dist gen generated out target .next .nuxt .output .svelte-kit; do P="$P :(glob)$d/** :(glob)**/$d/**"; done
git ls-files --others --ignored --exclude-standard -- $P | wc -l     # 本项目约 390,000,单次约 8 秒

复用问题的最小复现:临时 Git 项目忽略 dist/ 和 node_modules/,在 node_modules/pkg/dist 下创建 20,001 个文件;检查命令读取 dist/input.txt,内容为 good 时退出 0。第一次执行通过后把文件改为 bad,再次执行 executeNativePortableCheckPlan,结果仍复用之前的 passed;没有 node_modules 文件时,同样操作会重跑并失败。

🖥️ Environment

  • OS: Windows 11 Pro 10.0.26100
  • Shell: Git Bash
  • Node: v24.16.0
  • Package manager: pnpm(node_modules/.pnpm 布局)
  • Install scope: global
  • Skill language: zh
  • Target AI platform(s): Claude Code

💡 建议修复

  1. 不要用 **/<dir>/** 深入任意层级,改为只匹配项目根目录或检查 cwd 下的生成目录(<cwd>/<dir>/**)。实测只加 :(exclude)**/node_modules/** 能把数量降到 1,666 个,但耗时仍有约 11 秒;只保留顶层匹配后,耗时降到 0.16 秒,匹配 1,739 个文件。确实需要嵌套目录时,再显式排除 node_modules、vendor、.venv 等依赖目录。
  2. 生成目录不要整目录绑定:排除已知的缓存类子目录(如 .next/cache、.next/trace),或者允许项目在配置中声明生成输入的包含 / 排除规则,只绑定会影响检查结果的部分(如 .next/types、.next/dev/types)。
  3. 快照不完整时,在诊断信息中说明原因(超出文件数上限、超出大小上限、遇到敏感文件)。
  4. 快照不完整(gate 为 null)时禁止复用已有检查结果,并修正相关注释。

🧩 Additional context

相关:#455(被忽略的生成文件导致指纹漂移)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:cliCLI commands and user interactionarea:nativeNative workflow runtime and changes

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions