Skip to content

feat(devx): 根 dev 入口新增构建完整性前置 check:dev-prereqs —— 一个前置条件一句修法 (#5795) - #5863

Merged
os-zhuang merged 4 commits into
mainfrom
claude/issue-5795-dev-prereq-check
Aug 6, 2026
Merged

feat(devx): 根 dev 入口新增构建完整性前置 check:dev-prereqs —— 一个前置条件一句修法 (#5795)#5863
os-zhuang merged 4 commits into
mainfrom
claude/issue-5795-dev-prereq-check

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes #5795

dev / dev:* 此前唯一的前置是 check:console-sha,工作区未构建时直接放行进 boot。本 PR 加一道廉价前置:一个前置条件、一句修法,与 #5217check-i18n-bundles 侧的形态同构。

前置核对(Prime Directive #6)

实现前先按 origin/main 核对,前提成立且未过期:

判据:声明即强制

凡工作区包的解析入口(exports["."],否则 main)落在 dist/ 下,该文件就必须在盘上。按自己的声明未构建的包,修法恰好就是 pnpm build

成员名单读 pnpm-workspace.yaml,不硬编码路径 —— 这是承重的,不是整洁:packages/drivers/* 的内容跨分支不同,手写驱动路径会正好漏掉 #5726 真正出事的那个包。本轮 67 个包受判,并已逐个交叉核对全部build 脚本(即 turbo run build 会构建),所以那句修法对每个能被点名的包都成立。

结构性排除,而非按名排除(三类都不声明 dist/ 下的入口,天然不受判):

为什么必须排除
packages/console dist 由 build-console.sh 构建,turbo run build 不管 —— pnpm build 不是它的修法,点名它就是又一句错误建议
@objectstack/docs pnpm build--filter=!@objectstack/docs 过滤掉
examples 入口是 .ts 源文件,不是构建产物

明确的非目标:只探存在性,不探陈旧。比对 src/dist/ 的 mtime 会在每次 git worktree add 后对所有人误报(检出会重写源文件 mtime),那是门禁被无视的经典死法;陈旧那半边是 AGENTS.md §9 的常备处方。也只探 JS 入口、不探 .d.ts,所以 OS_SKIP_DTS=1 的快构建仍绿(dev boot 要的是 JS)。

为什么排在 check:console-sha 之前

未构建的 worktree 里,check:console-sha 会退出 0 并打出 ℹ No console dist … Build it with: pnpm objectui:build —— 对它自己的主题正确,对本成因是竞争性的错误修法。先跑本门禁,开发者读到一个前置条件、一句修法就停下。实测 pnpm dev:crm 在未构建 worktree 里出现 objectui:build 的次数为 0

接线

dev 链直接 node scripts/check-dev-prereqs.mjs(实测 0.05s),不走 pnpm check:dev-prereqs:pnpm 每跳约 0.7s(同链上既有的 pnpm check:console-sha 实测 0.722s,其中自身工作约 0.04s),而本门禁的全部价值就是廉价。pnpm check:dev-prereqs 保留仓内 --self-test && 惯例形态,供人工与将来非 dev 调用。既有的 check:console-sha 那一跳不动,不是本次的事。

四个入口全部接上(dev / dev:showcase / dev:crm / dev:todo):check:console-sha 当年就是同时硬门禁这几个入口的,只补一个等于半道门。

验证

场景 结果
未构建 worktree(无 node_modules 无 dist) 红,67 of 67,修法给出 pnpm install && pnpm build(缺依赖时 pnpm build 根本跑不起来)
pnpm install && pnpm build 绿,67 package build artifacts present,0.05s
pnpm dev 未构建 链在门禁处停住,不进 boot,objectui:build 未出现
pnpm dev 已构建 门禁绿 → check:console-sha → 真实 boot 到 ✓ Server is ready(自用随机端口 41797,已按 PID 收干净)
仅挪走 packages/drivers/driver-sql/dist(#5726 原始触发点) 红,1 of 67,逐名点出 @objectstack/driver-sql,修法 pnpm build —— 门禁抓的是精确的偏构建形态,不只是空 worktree
--self-test 七例 绿;两个方向都可达 + 三类排除 + 嵌套成员 glob + 无法展开的 pattern 必须响亮失败
eslint / check:nul-bytes 绿(nul-bytes 在提交后重跑,扫描面从 5692 升到 5693,确认新文件确实进了扫描面)

反向验证:方向与预设相反,如实报告

预先写下的预期是「把门禁绕开、驱动 dist 挪走,应当重现 #5726 的现场」。实跑结果只对了一半,措辞按实测改了:

  • 12 段 MODULE_NOT_FOUND 已不可复现,实测 0 段 —— PR fix(cli): load driver-sql's schema-work classifier lazily (#5726) #5789 的惰性 import 已经把这个放大器拆掉了。
  • datasource 那半边仍然逐字活着:✗ datasource 'default': connect failed — Cannot find module '…/@objectstack/driver-sql/dist/index.mjs',后面跟着 Fix the datasource configuration, or set OS_ALLOW_DRIVER_CONNECT_FAILURE=1 to boot anyway —— 对「dist 没构建」这个成因两条都是错的。

所以脚本的红色输出不再声称会刷 MODULE_NOT_FOUND(那会变成本门禁自己要防的那种误导),改为如实描述今天的残留;12 段那段历史移进文件头注释并标注已由 #5789 消除。datasource 消息本身的修正是 #5726 拆出的 services 车道单,本门禁只是让 dev 在抵达它之前就停下。

CI 零变化

changeset

非发布面(scripts/ + 根 package.json 脚本链,无包版本变化),走 skip-changeset 标签路线,不出 changeset 文件。

同族同构(#5217)

失败措辞与修法提示按「1 个前置条件 + 修法」对齐:单行 判定 + 受影响项(截断到 3 条 + … and N more)+ 唯一一条 Fix: 命令。本条落地时 #5217 的 worktree 尚未动工,故未能逐字对齐它的实现;本 PR 的形状写在文件头,--self-test 里有一条断言把「红输出里恰好只有一条命令」钉死,两侧谁后落地都可据此对齐。⛔ 未改对方文件。


🤖 Generated with Claude Code

https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE


Generated by Claude Code

claude added 2 commits August 6, 2026 09:43
`dev` / `dev:*` 此前唯一的前置是 `check:console-sha`,工作区未构建时直接
放行进 boot。#5726 记下了那个现场:一个未满足的前置条件被呈现成十几个互不
相关的问题,而唯一可执行的建议指向错误的修法(改 datasource 配置 / 设
OS_ALLOW_DRIVER_CONNECT_FAILURE=1),一次 30 秒的构建被包装成一场追查。

判据取「声明即强制」:凡工作区包的解析入口(`exports["."]`,否则 `main`)
落在 `dist/` 下,该文件就必须在盘上 —— 按自己的声明未构建的包,修法恰好
就是 `pnpm build`。成员名单读 pnpm-workspace.yaml 而非硬编码路径:
`packages/drivers/*` 的内容跨分支不同,手写驱动路径会正好漏掉 #5726 真正
出事的那个包。67 个包受判,全部有 build 脚本(即 turbo 会构建),因此那句
修法对每个能被点名的包都成立。

结构性排除而非按名排除:`packages/console`(dist 由 build-console.sh 构建、
`turbo run build` 不管,故 `pnpm build` 不是它的修法)、`@objectstack/docs`
(被 `pnpm build` 过滤掉)、examples(入口是 .ts 源文件)都不声明 dist 下的
入口,天然不受判。只探 JS 入口不探 .d.ts,`OS_SKIP_DTS=1` 的快构建仍绿。
陈旧(非缺失)明确不在判据内:比对 src/ 与 dist/ 的 mtime 会在每次
`git worktree add` 后误报 —— 那半边是 AGENTS.md §9 的常备处方。

排在 `check:console-sha` 之前:未构建的 worktree 里后者会打出
「Build it with: pnpm objectui:build」,对本成因是竞争性的错误修法。先跑本
门禁,开发者读到一个前置条件、一句修法就停下。`dev` 链直接用 node 调用
(约 0.05s),不走 `pnpm check:dev-prereqs`(pnpm 每跳约 0.7s);后者保留
仓内 `--self-test &&` 惯例形态供人工与将来非 dev 调用。

`--self-test` 七例把两个方向都钉死(#4690:只见过绿的门禁与什么都不匹配的
门禁无法区分),并钉死上述三类排除、嵌套成员 glob 展开,以及无法展开的
成员 pattern 必须响亮失败而不是静默少覆盖。

CI 零变化:未接入任何 workflow;`.github/` 无一处引用 `pnpm dev` / `dev:*` /
`check:dev-prereqs`,showcase 冒烟走 `working-directory: examples/app-showcase`,
且 CI 一律先构建,该条件在 CI 不可能成立。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE
@vercel

vercel Bot commented Aug 6, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
objectstack Ignored Ignored Aug 6, 2026 9:56am

Request Review

@github-actions github-actions Bot added size/m dependencies Pull requests that update a dependency file labels Aug 6, 2026
@os-zhuang os-zhuang added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 6, 2026 — with Claude

Copy link
Copy Markdown
Contributor Author

范围外发现,已另立不派单(观察类,finding,无 pm:queue):#5864 —— 本 PR 的判据只管 dist 存在性,#5726 的「陈旧 dist」那半边仍无门禁,而本 PR 新增的绿灯 ✓ Workspace is built 对那个场景会构成反向保证(开发者刚被告知工作区没问题,更容易把随后的假漂移当真 bug 去修)。

净效果仍是正的 —— 缺失是远更常见的形态 —— 但这个副作用是本 PR 新增的,所以留了档而不是埋在文件头注释里。#5864 里记了三条可能方向(构建时打戳照抄 check-console-sha.mjs 的形状 / 只对 packages/spec 这类放大器做判定 / 什么都不做但把绿灯措辞收紧成「产物存在」而非「产物最新」),交分诊定级,本 PR 不动。


Generated by Claude Code

原措辞写「It fails at 'datasource: connect failed'」,像是任何缺失都会这样。
不成立:门禁在任一 dist 入口缺失时就会红,而只缺 `packages/lint/dist` 时
boot 可能根本不碰 datasource。把一个只在部分场景成立的症状许诺成普遍规律,
正是本 PR 要治的那种误导的缩小版。

改为归因而非许诺:「Where that led once it was chased (#5726)」。判定、点名与
那一句修法都不变;`--self-test` 里「红输出中恰好只有一条命令」的断言仍然绿。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE

Copy link
Copy Markdown
Contributor Author

补一条证据(正文验证表里只举了 dev 一例,但接线动了四个入口,不该只证一个):把 packages/drivers/driver-sql/dist 挪走后逐个实跑四个入口,全部在门禁处停住,Development Mode / Server is ready 两个 boot 标记出现次数均为 0。

dev:          GATE FIRED, stopped before boot (boot markers=0)
dev:showcase: GATE FIRED, stopped before boot (boot markers=0)
dev:crm:      GATE FIRED, stopped before boot (boot markers=0)
dev:todo:     GATE FIRED, stopped before boot (boot markers=0)

另外两条顺手落实的核对:

  • OS_SKIP_DTS=1 仍绿不是推断:枚举全部受判入口,67 个全是 .js / .mjs,.d.ts 命中 0 —— 门禁不可能探到声明文件(@objectstack/spec -> dist/index.js@objectstack/driver-sql -> ./dist/index.mjs)。
  • check:generated --reconcile-only 不适用:那本账册是 packages/spec 的「门禁 → 生成器 → 签入产物」配对(spec-changes.jsonapi-surface.jsoncontent/docs/references/** 等)。本脚本不生成任何产物、也不是 spec 门禁,不该进那本账。

Generated by Claude Code

判据只管产物存在性,绿灯却写成 `✓ Workspace is built`。对**陈旧** dist 的场景
这是反向保证:开发者刚被告知工作区是好的,紧随其后的假漂移就更像真 bug ——
正是 #5726 警告过的「在正确的代码上改出真的 bug」,只是多了一句绿灯替它作证。

改为 `✓ N package build artifacts present (existence, not freshness)`,只说
verify 过的事。陈旧那半边已另立观察类单 #5864(含三条方向),文件头的非目标
一节现在指向它,而不是把这个缺口留成隐含知识。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GX3sL71LFq8m2usg6VqTSE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

dev 脚本没有任何一步确认工作区已构建 —— 前置检查只有 check:console-sha,未构建时放行进入 12 段噪音现场

2 participants