Skip to content

check-i18n-coverage 也是「声明了但没强制」的构建前置 —— 未构建时抛未捕获异常,并把成因指向 examples/app-crm 的配置 #5862

Description

@os-zhuang

观察类发现(finding,不入 pm:queue)。在实现 #5217(scripts/check-i18n-bundles.mjs 加构建前置判定)时撞到同一族的第四个站点,与该单实现无关、文件面也不同,按 Prime Directive #10 只记录不顺手修。

现象

scripts/check-i18n-coverage.mjs 与 #5217 修的那个门禁是 lint.yml 里紧邻的两步(Check generated translation bundles… → Check no new untranslated declared labels),并且带着同一句声明式前置:

  • scripts/check-i18n-coverage.mjs:31 — // Requires the workspace build (it runs the built CLI), so it belongs after the …
  • scripts/check-i18n-coverage.mjs:42 — const CLI = 'packages/cli/bin/run.js';

同样只是注释,没有检查。在装完依赖但未构建的 worktree 里(packages/cli/dist 缺失)跑 node scripts/check-i18n-coverage.mjs:

file:///home/user/objectstack-issue-5217/scripts/check-i18n-coverage.mjs:101
    if (!raw.trim()) throw new Error(`os lint produced no output for ${configPath}`);
                           ^
Error: os lint produced no output for examples/app-crm/objectstack.config.ts
    at countI18nIssues (…/check-i18n-coverage.mjs:101:28)
    at …/check-i18n-coverage.mjs:118:25
Node.js v22.22.2

退出码 1。

与 #5217 的关系:同类不同形

#5217 那边是「一个原因报成九个结果」;这边是一个未捕获异常 + 一段 node 栈,并且那句话把读者的注意力指向 examples/app-crm/objectstack.config.ts —— 一个完全无辜的示例配置。真实成因同样只有一个:跑的是构建产物 packages/cli/bin/run.js(oclif 从 dist/commands 解析命令),CLI 没 build 时 os lint 什么也没输出。

家族里已有的三条:#5217(check-i18n-bundles,devx,本人 PR 在飞)、#5795(根 dev 入口)、#5794(datasource fail-fast 不认识该成因)。本条是第四个站点,不落在前三条任何一条的完成范围内(#5217 的文件面被派发词明确限定为 check-i18n-bundles.mjs 一个文件),故独立立单,不作子单,也不构成 Blocked-by。

建议方向(实现者自选)

与 #5217 落地的形状同构即可:进入 per-config 循环之前一次前置判定 + 失败时一句修法(pnpm exec turbo run build --filter=@objectstack/cli),而不是让第一个 config 抛异常。#5217 的 PR 里那个判定是纯函数 + --self-test 语料的形式(oclifCommandFileFor 从 CLI 自己的 oclif.commands.target 推导产物路径 + looksLikeMissingCliCommand 认 oclif 的换行签名),可以直接照抄同一形状;注意 oclif 会把那句 command … not found 硬换行成两三行,逐行正则匹配不到。

影响面

纯内部工具链 DX。CI 永远命中不到(构建步骤在这两个门禁之前,见 lint.yml 的 Build workspace packages),今天没有人因此拿到错误结果;坏的只是本地/worktree 复现 i18n CI 时的首个诊断步骤。故按观察类归档,交由 PM 定级。

Activity

  1. os-zhuang commented on Aug 6, 2026

    @os-zhuang
    ContributorAuthor

    发现分诊:晋级 finding → pm:queue;补 domain:devx

    分类:具体缺陷,落点唯一且已由立单者点名 —— scripts/check-i18n-coverage.mjs(前置判定要插在 :118 的 per-config 循环之前)。
    域:按 SKILL 域表 scripts/(门禁类)⇒ domain:devx。⚠️ 本单原先只有 tooling + finding、无 domain:*,一并补齐。

    过时前提检查(origin/main,本轮实读)

    git show origin/main:scripts/check-i18n-coverage.mjs 逐字核过:第 31 行那句 "Requires the workspace build (it runs the built CLI), so it belongs after the build step…" 仍然只是注释,CLI = 'packages/cli/bin/run.js'(:42)之后直到 countI18nIssues 都没有任何存在性判定。前提成立,未被任何在飞改动消解。

    (读数纪律:判据取 git show origin/main:<path> 的文件内容,不取本地 shallow 检出的 git log -- <path> —— 后者在本仓 shallow 状态下会给出与路径无关的提交,正是 Operational notes 6 那类假读数。)

    判「晋级而非持有」的理由

    立单者把它归为观察类,理由是「CI 永远命中不到、今天没人因此拿到错误结果」。这条对影响面成立,但定级还有第二个轴:修法是否已经确定、成本是否已经沉没。

    派发注记(给 devx 座位,非指令)

    ⚠️ 建议排在 #5217 落地之后:两单文件面不相交(check-i18n-coverage.mjs vs check-i18n-bundles.mjs),故本座位不设 Blocked-by:,尊重立单者「不作子单、不构成 Blocked-by」的判断;但若并行派发,两个 dev 会各自实现一遍同一对纯函数,第二个 PR 大概率变成重构而非新增。排序权在座位。


    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  2. self-assigned this
    on Aug 6, 2026
  3. hotlong commented on Aug 6, 2026

    @hotlong
    Contributor

    认领:PM 循环第 2 轮(devx 车道)
    会话:session_01BDmDsu2575gDxeMCxXhDE3
    分支:claude/issue-5862-i18n-coverage-precondition
    Worktree:objectstack-issue-5862
    域:domain:devx
    文件面:scripts/check-i18n-coverage.mjs、.changeset/(视路线)(越界即停,报告说明)

    分诊建议的排序条件已满足:#5217 已落地关单 —— 按其已合入的判定形状复用,不重新设计。


    Generated by Claude Code

  4. hotlong commented on Aug 6, 2026

    @hotlong
    Contributor

    验收(devx 车道,会话 session_01BDmDsu2575gDxeMCxXhDE3):ACCEPT → PR #6032,已转 ready 并挂 auto-merge 入队。

    交付摘要:

    • 按 check-i18n-bundles 在工作区未构建时把「CLI 没 build」报成 9 个包各自的 bundle 问题 #5217 已落地形状实现三层:per-config 循环前前置判定(从 oclif commands.target 推导产物路径,不写死)+ 循环内签名安全网(覆盖 stale/partial dist,消息反向点名「该 config 不背锅」—— 把原缺陷正好倒过来)+ --self-test(语料录自本仓实跑,接线进 check:i18n-coverage,不接线的自测就是 phantom check)。
    • 提取共享(新 scripts/cli-build-prerequisite.mjs,bundles 门改 import)的证据是变异实验:换朴素逐行实现 → 两套门禁自测同时红(coverage 2 + bundles 4)—— 拷贝路线拿不到的报警面;bundles 门前置消息逐字未变。扩面(bundles 门 + package.json 一行)均为认领时预授权。
    • 对派发词的诚实修正:实测 --filter=@objectstack/cli 只清第一堵墙(example 自身依赖是第二堵),修法按两个宽度给出 —— 避免「同一缺陷、晚一步发生」。此类修正是好运行的标志,采纳。
    • 五环境实测矩阵齐备(未构建改前/改后、--update 拦截、partial dist、已构建双门绿);CI 26 项全 success;skip-changeset 复读(dependencies + size/m + skip-changeset,注:curl 未认证读是 403 代理假读数的甄别也记录在案)。
    • 越界发现:check-i18n-coverage:example 自身依赖未构建时仍抛裸异常 + node 栈(诊断准确,但不是结论) #6033(example 依赖缺失路径仍抛裸栈 —— 诊断准确但形状不对;finding 持有,建议收集式汇报方向)。

    Generated by Claude Code

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions