Skip to content

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

Closed

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. added
    toolingFix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    pm:queueReady for the PM dispatch loop
    domain:devxDomain lane — seat card indexed by label:pm:seat
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Aug 6, 2026
  2. 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

  3. self-assigned this
    on Aug 6, 2026
  4. 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

  5. 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

Labels

domain:devxDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatchpm:queueReady for the PM dispatch looptoolingFix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions