Repository navigation
refactor(devx): move the four inline ESLint rule plugins into a private workspace package - #26177
Conversation
…s/eslint-plugin eslint.config.mjs carried slot-lookup, query-options, verify-stand-in and comment-swallow as inline plugin objects plus a self-assert block. They now live in a private workspace package with RuleTester tests; the config imports them by relative path and keeps only configuration. The slot lists and the verify guarded set stay in the config and reach the rules as required options. Rule ids, messages and the names the ratchet scripts import are unchanged. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CHC483oAMSwyfmTu1xajpZ
…port Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CHC483oAMSwyfmTu1xajpZ
📓 Docs Drift CheckThis PR changes 1 package(s): 26 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 8 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 98638dc8e84f38923ed98630b9e5f9eeaa8baee5 && git checkout 98638dc8e84f38923ed98630b9e5f9eeaa8baee5
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin c7aa9cde24ca7d17563caa4e01037f3ab1b9e990 025d3287b74dd8c3fe4adeefe525e5fb4c3d1e2e && git checkout -B drift-repro c7aa9cde24ca7d17563caa4e01037f3ab1b9e990 && git merge --no-ff 025d3287b74dd8c3fe4adeefe525e5fb4c3d1e2e
node scripts/docs-audit/affected-docs.mjs --json c7aa9cde24ca7d17563caa4e01037f3ab1b9e990
|
席位核对 · REVISE · devx seat 2 · 2026-10-26T14:51ZSeat
One item blocks:
Not blocking, ruled by the seat:
Push to the same branch, re-run the derived families (including the self-test), and report the new head. Generated by Claude Code |
…/eslint-plugin The two rules both ratchets measure moved out of eslint.config.mjs (a root-config path that runs every family) into packages/eslint-plugin/src/*.mjs, which the workspace arm skipped as non-TS source. A rule-only edit now selects both families again; the self-test pins it. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CHC483oAMSwyfmTu1xajpZ
席位核对 · ACCEPT · devx seat 2 · 2026-10-26T15:15ZSeat
Generated by Claude Code |
⛔ merge queue 构建失败 — 先分诊,再决定要不要重排队列构建 40352585826 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集), 分类: 失败的 job(日志抽取,best effort):
跨 PR 相同签名(24h,按失败测试文件聚合):
历史信号:
分诊清单:
Generated by Claude Code · merge-queue-triage workflow (#4859) |
Requested by Steve · project thread
Fixes #26093
Clause-②: no
Metadata-protocol: none
What changed
The four inline rule plugins in
eslint.config.mjs(slot-lookup, query-options, verify-stand-in, comment-swallow) move into a private workspace package,packages/eslint-plugin(@objectstack/eslint-plugin,"private": true, no build step). The root config imports it by relative path and keeps only configuration.pnpm lintloads the config with nativeimport, and the repo'senginesfloor is Node 22.0; a.tssource would need Node 22.18 type stripping.tsconfig.jsonsetsallowJs+checkJs, sotscreads the rule sources too (JSDoc types; AST helpers are deliberately untyped, documented in each file).slot-lookup/…etc.), so the ratchet scripts and their rule-id / message matching see the same thing.SLOT_LOOKUPS,UNCONTRACTED_SLOTSandVERIFY_STAND_IN_CHECKSstay ineslint.config.mjs(the slot-lookup selectors read the first two, and both the message text andcheck:verify-stand-insay they live there). Those two rules now get the lists as required options: a config that drops them fails ESLint's schema validation instead of running against an empty set (pinned in the tests).eslint.config.mjsis kept. Every named export the scripts import is still exported (re-exported from the package). The only one dropped isCOMMENT_SWALLOW_CASES, which nothing imported. It moved into the tests.assertCommentSwallow()and its 17 pinned cases becametest/comment-swallow.test.ts, along with the "files glob must cover plain JS" assertion.pnpm-lock.yaml: only the new importer (+18 lines, frompnpm install). No new resolutions.pnpm-workspace.yamluntouched (packages/*glob). No baseline file changed.Behaviour preserved: before / after
Before =
origin/maind1ea236, after = head 4d18cf1, same worktree:pnpm lint(exact root script)pnpm check:slot-lookuppnpm check:query-options-erasurepnpm check:verify-stand-inpnpm linthas nothing to report on either side, so the empty diff is weak evidence by itself. The three ratchets are the strong reading: they import this config, lift its grandfathering, and count each rule's reports per file, and their self-tests drive the live rules through the config ("reports all 5 erasure shapes"). Their outputs are byte-identical before and after.Comments: moved, not rewritten (#25919 ruling A)
Of the 635 non-blank lines removed from
eslint.config.mjs, 585 appear verbatim in the package. Each plugin file has a short header saying the history moved from the config, so "above" / "below" in it refer to that file. The other 50 lines are accounted for:export, or read options instead of the config constants;assertCommentSwallow()function body, rewritten as vitest assertions;assertCommentSwallow(one in the package, one left in the config) now point at the test;Config-block comments that justify configuration (scope, ignores, the lists) stay where they were. The query-options block's "dedicated plugin rule, not selectors" + known-residual paragraphs moved, since they describe the rule. Three new one-line pointers name the rule file.
Acceptance
pnpm lintidentical before/after: 0 errors, same (empty) warning set. Table above.wc -l eslint.config.mjsunder about 400: 649 (was 1,271). Deviation, see below.packages/lintruns in.scripts/partition-test-shards.mjsoverturbo ls --affectedputs@objectstack/eslint-pluginon Test Core shard 1/8. Locally:pnpm --filter @objectstack/eslint-plugin testgives 4 files, 73 tests, all pass.pnpm typecheckcovers the new package.turbo run typecheck --filter=@objectstack/eslint-pluginrunstsc --noEmitwith exit 0.--listFilesshows all 5src/*.mjs, all 5test/*.tsandvitest.config.ts.check:type-check-coverageandcheck:type-check-debtare green.Why 649 and not about 400
The card's estimate takes 1,271 minus the "906 lines of plugins". But lines 1–120 of the old file are the lint-script header (
--stack-sizerationale, ~85 lines) and the subpath / defineX constants, and several constants in the 1–906 range are configuration that has to stay (slot lists, both baselines,QUERY_OPTIONS_TEST_GLOBS,VERIFY_STAND_IN_CHECKS, the rule ids). What remains is 225 code lines and 402 comment lines. All of those comments explain configuration, not rule history. Under ruling A ("存量不横扫") and the dispatch's "其它注释不改", getting to ~400 would mean sweeping them. That is not done here. If the seat wants the number, it is a separate comment-budget decision.Gates
Derived with
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackat 4d18cf1: 68 families. Each was run on that head, with its exit captured before any pipe. All 68 exit 0.--ranreconciliation: "68 derived, 68 run, 0 NOT-MEASURED, 0 UNRUN". Build-reading gates (check:dts-closure,check:dual-build-cjs-loads,check:lean-entry-closure,check:sourcemap-no-sources-content) ran after a fullpnpm build(119/119 tasks). The plugin-teardown self-test ran aftergit fetch --unshallow.The first run had two reds, both from one string: a moved comment-swallow case contains the example line
* import { createHonoApp } from "@objectstack/hono";.check:cross-package-test-inputsandcheck:test-source-aliasscan test source text and read that string as an undeclared workspace import. The test now splits the specifier across a+(the runtime string is byte-identical; the original case list already split/a*+/the same way). Fixed in 4d18cf1.Acceptance notes
scripts/ci/select-gate-families.shruns theslot_lookupandquery_options_erasurefamilies for apackages/*path only when it is TS source (is_ts_source). Before, these rules lived ineslint.config.mjs, a root-config path that runs every family. Now they live inpackages/eslint-plugin/src/*.mjs, so a later PR that edits only a rule file would skip both ratchet re-measures in CI. Their CI coverage would then bepnpm lint(always runs) and the package's own RuleTester suite in Test Core. This PR itself toucheseslint.config.mjs, so every family runs on it. Suggested fix for the seat to file: addpackages/eslint-plugin/*to those two families' trigger set.@objectstack/eslint-pluginis private and has nodist; it ships nothing, henceskip-changeset.Generated by Claude Code