Skip to content

docs(lint): dashboard-filter-binding-unknown explanation counts a globalFilters entry named dateRange as declared - #29525

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-xi96xf
Nov 2, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-xi96xf

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Warren · project thread
Fixes #29382

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:os explain dashboard-filter-binding-unknown 的一句说明,和 validate-widget-bindings.ts 里两段注释;规则代码不变,新增一个测试。
  • 为什么改:旧说明称「没声明 dateRange 的仪表盘上,dateRange 绑定一律报错」;实测规则接受名为 dateRange 的 globalFilters 条目,说明与行为不符。
  • 风险与回滚:只改说明文字与注释,行为零变化;回滚即 revert 本 PR。
  • 先看:packages/lint/src/rule-explanations.ts(第 407–410 行那句)、packages/lint/src/validate-widget-bindings.test.ts(新测试)。
  • 两分钟验证:pnpm --filter @objectstack/lint exec vitest run src/validate-widget-bindings.test.ts -t dashboard-filter-binding-unknown,预期 13 个用例全绿。
  • 需要你做的:无,席位落地。

What changes

  • packages/lint/src/rule-explanations.ts, rule dashboard-filter-binding-unknown only: the third paragraph said "A dateRange key on a dashboard that declares no dateRange is reported the same way". It now says a dateRange key is reported only when the dashboard declares neither dateRange nor a globalFilters entry named dateRange, because either one is a declared filter under that name.
  • packages/lint/src/validate-widget-bindings.ts: the rule family docblock and the DASHBOARD_FILTER_BINDING_UNKNOWN docblock say the same. No code line changed.
  • packages/lint/src/validate-widget-bindings.test.ts: one new case in the dashboard-filter-binding-unknown block. The dashboard has no dateRange, a globalFilters entry { name: 'dateRange', field: 'signed_at', type: 'date' }, and a widget with filterBindings: { dateRange: false }. It expects zero findings.
  • .changeset/29382-filter-binding-daterange-prose.md: a patch for @objectstack/lint, because the explanation text ships in its dist/.

Why

The card asked for a measurement first. The rule takes its declared names from dashboardFilterDefs, which adds every globalFilters entry under its name. So a globalFilters entry named dateRange is declared even when the dashboard has no dateRange. The new test measured it on origin/main 94d3e25 before any prose edit: the case passed with zero findings. The rule accepts the binding, so this PR takes the prose-only arm and leaves the rule body alone. The runtime agrees: objectui resolveDashboardFilterDefs (ui/packages/core/src/utils/dashboard-filters.ts) builds the same name set.

Tests

  • Measurement, before any prose edit, tree 94d3e25 plus the new test only: pnpm --filter @objectstack/lint exec vitest run --maxWorkers=2 src/validate-widget-bindings.test.ts -t 'dashboard-filter-binding-unknown': Tests 13 passed | 178 skipped (191), lock VERDICT command-exit 0.
  • Final head: see Verification.

Acceptance notes

Verification

All readings are on head abff9a05 (b6d1ad0e plus a merge of origin/main 86d36e9).

Package tests and typecheck
  • pnpm --filter @objectstack/lint test: Test Files 190 passed (190), Tests 7858 passed (7858), lock VERDICT command-exit 0.
  • pnpm --filter @objectstack/lint typecheck: lock VERDICT command-exit 0.
Derived gates (dispatch-gates --commands, 58 families)
  • 57 of 58 exit 0, each captured before any pipe.
  • pnpm check:dual-build-cjs-loads: exit 3, PREREQUISITE NOT MET (it needs every package's dist/). NOT MEASURED locally; CI's Lint & Repo Gates runs it on a full build.
  • dispatch-gates --ran: "58 derived famil(ies) accounted for, 57 run, 1 NOT-MEASURED".
  • node scripts/check-nul-bytes.mjs: exit 0.

Repo-wide pnpm lint and every other CI family: read from this PR's check-runs.

Human Minimum

  • 1. Schemas start as Zod; packages/spec holds no runtime logic. (no spec change)
  • 2. Every name I added uses the casing for its kind.
  • 3. No formatter ran; pnpm lint passes. (repo-wide lint is CI's run)
  • 4. One issue, one branch off an up-to-date main, one pull request.
  • 5. A change that publishes carries a changeset, and both declaration lines are filled in here and in the changeset.
  • 6. packages/spec touched: not touched.
  • 7. No hand edits to content/docs/references/, packages/*/CHANGELOG.md or content/docs/releases/.
  • 8. Title, body and comments are in English (the maintainer brief is Chinese by the repo's communication rule).

Branch claude/project-thread-xi96xf is the card thread's platform-assigned branch, as the Claim records. Written by domain:spec#5 · os-warren · session_01JQwxbaAMsVe1WU74CypjTZ.


Generated by Claude Code

…alFilters entry called dateRange as a declared filter

The explanation said a dateRange binding on a dashboard without dateRange is
always reported. The rule reads every globalFilters entry's name as declared,
so a globalFilters entry named dateRange makes the binding valid. Correct the
sentence and the two docblocks, and pin the accepted case with a test.

Claude-Session: https://claude.ai/code/session_01JQwxbaAMsVe1WU74CypjTZ
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added the size/s label Nov 2, 2026
@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️ 1 changed file(s) yielded no anchor (packages/lint/src/validate-widget-bindings.ts), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)).

What this run could not see
  • 1 changed file(s) yielded no anchor (packages/lint/src/validate-widget-bindings.ts) — pages documenting those are invisible to this run
  • 1 name(s) were too generic to anchor anything (single lowercase words)
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 4 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 399df5bba888ff7cf7531d01d8dcb61d7690438a → packageMentionDocs.

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests tooling labels Nov 2, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#5 · os-warren · session_01JQwxbWR3K3h7i1ytwycVg1

维护者速读

  • 改了什么:os explain dashboard-filter-binding-unknown 第三段的一句,和 validate-widget-bindings.ts 两段注释;规则代码不变,新增一个测试钉住被接受的情形。
  • 为什么改:旧说明称「没声明 dateRange 的仪表盘上,dateRange 绑定一律报错」;实测规则把名为 dateRange 的 globalFilters 条目当已声明过滤器,绑定被接受,说明与行为不符。
  • 风险与回滚:只改说明文字与注释(+29 / -6),行为零变化;回滚即 revert。
  • 先看:packages/lint/src/rule-explanations.ts 那一句,和测试文件新增的一例。
  • 两分钟验证:pnpm --filter @objectstack/lint exec vitest run src/validate-widget-bindings.test.ts -t dashboard-filter-binding-unknown,预期 13 例全绿。
  • 需要你做的:无,席位落地。
  • 席位意见:先测后改,测量在 main 上做、只加测试;走的是卡给的「文案」分支,规则本体未动,与 objectui 的 resolveDashboardFilterDefs 一致。

席位核对

ACCEPT · domain:spec#5 · head abff9a05ddc76014c8cfe2004f56841ddc774a3b · 2026-11-02T18:01Z

  1. Shape: four files, all inside claim 6582670981's surface: rule-explanations.ts (rule dashboard-filter-binding-unknown, third paragraph only), validate-widget-bindings.ts (two docblocks, no code line), validate-widget-bindings.test.ts (one case), .changeset/29382-filter-binding-daterange-prose.md (@objectstack/lint patch). Draft, base main, Fixes #29382.
  2. Premise, measured: the seat read dashboardFilterDefs on origin/main (validate-widget-bindings.ts ~L652–671): every globalFilters entry is set by name (else field), so a dateRange-named entry is a declared name without dashboard.dateRange. The dev measured the same on 94d3e254 with only the new test added: zero findings (report 6583951847). Prose arm taken, per the card's Wanted.
  3. Gates: check-runs on this head: 63, 54 success, 9 skipped (Lint UI, Dogfood Verify CLI, UI Published Artifacts, Temporal Conformance, Dogfood Regression Gate, Build Docs, 18.x upgrade harness, Schedule gate, Packed-tarball smoke: path- or opt-in-scheduled, none touched by a packages/lint prose diff); Lint & Repo Gates and TypeScript Type Check success. Local: 58 derived, 57 exit 0, 1 NOT MEASURED (check:dual-build-cjs-loads, prerequisite dists; CI's Lint & Repo Gates covers it).
  4. Accepted deviations: none. Changeset sentences checked against the diff: the old quote, "every globalFilters entry's name is a declared filter", and "the rule's behaviour is unchanged; a new test pins the accepted case" all hold.
  5. Out of scope: packages/spec/src/ui/dashboard.zod.ts globalFilters[].name TSDoc and the filterBindings describe still read narrower; carrier = PR fix(spec)!: refuse a dashboard globalFilters entry keyed dateRange beside a declared dateRange #29370 (spec(dashboard): a globalFilters entry named dateRange parses and silently replaces the built-in date range's binding #29213), which edits that file. Skills-docs: n/a (Metadata-protocol: none).
  6. Landing: not governed (check-governed-merges --pr 29525: NOT governed, 35 changed lines ≤ 3000); Clause-②: no and no packages/spec/src/** path, so no contract review owed. Seat lands it: pr_ready + automerge_enable.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 2, 2026 18:03
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 2, 2026
@github-actions

github-actions Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

⛔ merge queue 构建失败 — 先分诊,再决定要不要重排

队列构建 41498916863 红了。队列跑的是全量套件(PR 侧 CI 只跑 affected 子集),
所以失败的测试可能在本 PR 没碰过的包里 —— 那不是重排能修的。每次盲目重排都会让排在后面的所有 PR 重建一轮。

分类:failure —— 按下面的日志分诊。

失败的 job(日志抽取,best effort):

  • Test Core (2/8) — 失败步骤: Run this shard's tests

    @objectstack/spec:test:  FAIL   local  scripts/dropped-refinements.test.ts > the committed ledger > names at least one site per entry, and its header totals match its body
      ↳ 失败原因: @objectstack/spec:test: AssertionError: expected 993 to be 998 // Object.is equality
    

↳ 失败原因 是判读的关键:超时(Test timed out in … / Hook timed out in …)多半是负载/时序,不是本 PR 的回归;
断言(AssertionError: …)才指向真实的行为改变。两者的 FAIL 行长得一模一样,只有这一行能区分。

⚠️ 断言这一侧有一类例外,判据是断言在测什么,不是它是不是 AssertionError。 断言的对象是产品行为(一个值、一个形状、一次拒收)⇒ 照上面读:真实的行为改变,去查,⛔ 不要重排掉;
断言的对象是这次实验自身的有效性前提(跑完的耗时、负载下的先后、任何只在时间预算内才成立的条件)⇒ 它跟超时是同一类,同样对负载敏感,重排一次是合法的判别手段。
识别是机械的:断言的消息或它比较的值本身点名了一段时长、一个时间戳、一个耗时计数。实测过的一对 —— AssertionError: SecurityPlugin.init() ran: expected false to be true 测的是产品行为(真回归);
AssertionError: this run took over a second, so second-precision stamps could have differed too: expected 1006 to be less than 1000 测的是实验前提:它守护的那条不变式当时是绿的,同一个 head 原样重排一次即成功。
穿着 AssertionError 外衣的时间测量,仍然是时间测量。(⛔ 这只改「怎么读一次红」,不改「哪些测试可以重排」——后者由别处管。)

跨 PR 相同签名(24h,按失败测试文件聚合):

历史信号:

  • 本 PR 过去 24h 无队列失败记录(首次)。
  • 过去 24h 队列共有 29 个失败构建(不含本次)。

分诊清单:

  1. 失败测试在本 PR 改动的包里 → 真回归,修 PR。
  2. 失败测试与本 PR 无关 → 看上面的「跨 PR 相同签名」;已有汇总 issue ⇒ flaky/环境问题实锤,去那张 issue 上谈,修好前重排只会再烧一轮全队列。
  3. 两者都不是 → 可能与同组 PR 语义冲突;等前面的 PR 落地或失败出队后再重排一次即可,不要连续重排。

Generated by Claude Code · merge-queue-triage workflow (#4859)

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

Labels

documentation Improvements or additions to documentation size/s tests tooling

Projects

None yet

1 participant