Skip to content

check-i18n-coverage:example 自身依赖未构建时仍抛裸异常 + node 栈(诊断准确,但不是结论) #6033

Description

@hotlong

观察类发现(finding,不入 pm:queue)。实现 #5862(PR #6032)时按 Prime Directive #10 只记录、不顺手修 —— 它与 #5862 的成因不同,落点也不在该 PR 的申报文件面之外那半步。

现象

#5862 修的是「CLI 未构建」这一个前置。清掉它之后(pnpm exec turbo run build --filter=@objectstack/cli),在一棵其余部分仍未构建的树上跑 node scripts/check-i18n-coverage.mjs,第二堵墙立刻出现:

file:///…/scripts/check-i18n-coverage.mjs:185
    if (report.error) throw new Error(`os lint failed for ${configPath}: ${report.error}`);
                            ^

Error: os lint failed for examples/app-showcase/objectstack.config.ts:
  Cannot find module '/…/examples/app-showcase/node_modules/@objectstack/connector-mcp/dist/index.mjs'
    at countI18nIssues (…/check-i18n-coverage.mjs:185:29)
Node.js v22.22.2

退出码 1。本轮实测,在 f192981 的 worktree 上复现。

与 #5862 的区别:这次诊断没有说谎

这是为什么它是观察类而不是缺陷。#5862 的那句话把成因指向一个完全无辜的示例配置;这一句点的是真的缺失模块路径 —— 读者拿到的是可行动的一手读数。坏的只是形状:一段 node 栈,而不是一条「前置未满足 + 修法」的结论,并且同样是「第一个撞上的 config 顶罪」式呈现(app-showcase 只是恰好排在前面;每个 example 都会以各自的缺失模块再来一次,如果循环没在第一个就崩)。

家族里已有的几条:#5217(check-i18n-bundles,已落地)、#5862(本条的直接前身,PR #6032 在飞)、#5795(根 dev 入口)、#5794(datasource fail-fast 不认识该成因)。

为什么不在 PR #6032 里顺手修

建议方向(实现者自选)

若要修,最省的形状可能不是再加一个前置探测,而是把 report.error 这条路径从 throw 改成收集式:整轮跑完后一次性报告「哪些 config 没能 lint 成功 + 各自的原因 + 一句 pnpm build」,而不是让第一个失败的 config 中止全程 —— 与 #5217 「一个原因不要报成 N 个结果」的取向一致,方向相反(这里是 N 个不同原因不应被第一个吃掉)。

影响面

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

Activity

  1. claude commented on Aug 6, 2026

    @claude
    Contributor

    发现分诊轮(#4949 纪律):持有(留 finding),域维持 domain:devx。

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


    Generated by Claude Code

  2. claude commented on Aug 7, 2026

    @claude
    Contributor

    Findings triage (objectstack#4949 discipline) — restart condition ① FIRED; the re-grade it asked for says the change still pays ⇒ PROMOTE to pm:queue. Domain unchanged: domain:devx.

    1. The trigger

    ① PR #6032 合并后复评 —— 若届时收集式改造仍有独立收益,晋级 pm:queue(那时落点、文件面、断言面都对着已落地的形状,可一次性定价)

    PR #6032 merged 2026-08-06T23:55:44Z (#5862). The re-grade is the substance of this comment.

    2. Re-grade: #6032 narrowed this issue, it did not resolve it (origin/main @ ede5a8e)

    #6032 added checkCliBuildPrerequisite() (scripts/check-i18n-coverage.mjs:349-363), called once before the loop. It answers exactly one cause — the workspace CLI is not built — and its own docstring says so: it probes resolveCliCommandFile(LINT_COMMAND_ID) and defers to "the in-loop signature net" when the package.json shape moves.

    This issue's cause is the other one: an example's own workspace dependencies unbuilt. That path is untouched and still behaves exactly as filed:

    • countI18nIssues still leaves via bare throw — :178 (produced no output), :183 (unparseable JSON), :185 (os lint failed for …);
    • the per-config loop at :367-369 has no try/catch, so the first failing example aborts the entire run with a node stack;
    • consequently the errors[] collector at :380-411 — the report shape this issue asks for — is never reached on that path.

    So the "first config to be hit takes the blame for all of them" shape the previous verdict declined to close is intact.

    3. Why it is now cheaper than when filed — the reason to promote rather than re-hold

    Both halves the change needs already exist on main, landed by #6032 and reusable as-is: reportPrerequisiteNotMet for the verdict shape, and the errors[] collector for the report shape. The remaining scope is small and fully anchored: wrap the per-config countI18nIssues call, push the failure into errors, continue the loop. Landing site, file surface, and assertion surface are all now settled against a merged shape — which is exactly the "可一次性定价" the restart condition was waiting for.

    Condition ③ (the whole family solved elsewhere, e.g. a lint entry that builds first) has not fired, so the premise still holds.

    4. Serial constraints

    No open PR touches scripts/check-i18n-coverage.mjs (all 5 enumerated). Related family for the dispatch to read, not to absorb: #5217 (landed, one cause must not be reported as N results — this is its converse), #5862 / #6032, #5795, #5794.

    ⛔ No target:<major>: CI never reaches this path (lint.yml runs Build workspace packages first), so the impact is local / worktree presentation only.

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


    Generated by Claude Code

  3. self-assigned this
    on Aug 7, 2026
  4. hotlong commented on Aug 7, 2026

    @hotlong
    ContributorAuthor

    认领(pm-dispatch devx 座位) — 本单进入派发。


    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