You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
lint(dashboard-filter-binding-unknown): its explanation says a dateRange binding on a dashboard with no dateRange is always reported, but a globalFilters entry named dateRange is a declared filter there #29382
Filing gate: ① a should-fix named by the CONTRACT_REVIEW_TIER review of PR #29370 (#29213), record 6578522383, kept out of that PR to hold it to its claimed surface. ⛔ Not a claim. No grade: triage sets it.
What the text says
packages/lint/src/rule-explanations.ts, rule dashboard-filter-binding-unknown (≈L407–409 on main): "A dateRange key on a dashboard that declares no dateRange is reported the same way: there is no date range for it to bind."
Why it may be wrong
The same explanation's first paragraph says the names a widget may bind are each globalFilters entry under its name (its field when unnamed) and the reserved dateRange when the dashboard declares dateRange. PR #29370 keeps a globalFilters entry keyed dateRange ACCEPTED on a dashboard that declares no dateRange (the seat's answer to that PR's open question, Q1 = A: it is a working filter there). On such a dashboard a widget's filterBindings.dateRange names a declared filter, so "is reported the same way" reads false, or the rule reports a valid binding. Not measured: which of the two it is.
Wanted
Measure dashboard-filter-binding-unknown on a dashboard with no dateRange, a globalFilters entry named dateRange, and a widget binding dateRange. If the rule accepts it, correct the sentence (prose only). If it reports it, that is a false positive on a valid board: fix the rule to read the declared name set, with a test.
Reader who acts: the packages/lint owner (domain:spec by the anchoring rule).
Dedupe: searched dashboard-filter-binding-unknown dateRange, filterBindings dateRange globalFilters: only #29213 / PR #29370 and #29023. New.
Read fresh. The lint rule dashboard-filter-binding-unknown has an explanation that misses a globalFilters entry named dateRange. Prose in a spec-contract lint rule, so the anchoring rule gives it to domain:spec. p3.
Claim: PM loop round 1
Session: session_01JQwxbWR3K3h7i1ytwycVg1
Account: os-warren
Branch: claude/project-thread-xi96xf (card thread; the thread can push only its own branch — measured platform exception to claude/issue-29382-…)
Worktree: objectstack-issue-29382
Domain: domain:spec
Seat: domain:spec#5
File surface: packages/lint/src/rule-explanations.ts (rule dashboard-filter-binding-unknown only), packages/lint/src/validate-widget-bindings.ts (its docblocks; the rule body only if the measurement shows a false positive), packages/lint/src/validate-widget-bindings.test.ts, .changeset/29382-filter-binding-daterange-prose.md
Container & model: S/M prose, measurement first, mode:thread, model: TIER_DEFAULT (dispatch-gates --tier: no path-derived mandate), effort: medium
Clause-②: no
Metadata-protocol: none
Responsibility: packages/lint rule explanation states a refusal the rule does not make (seat reading: dashboardFilterDefs adds every globalFilters entry by name) | none | authors and AI authors reading os lint --explain dashboard-filter-binding-unknown, today
Thread-read: 6580262419
Premise: holds — on origin/main04e0c2c the sentence "A dateRange key on a dashboard that declares no dateRange is reported the same way" is in rule-explanations.ts; which arm applies is measured by the dev with a test first. The no cites the same explanation's first paragraph: each globalFilters entry is bindable under its name.
Serial constraints cleared: PR #29495 (open) edits rule-explanations.ts at hunks L5420 and L5631, disjoint; PR #29370 (#29213, open) is the spec side of globalFiltersdateRange and touches neither file; no other open PR touches these files (census of 54 open PRs at 2026-11-02T16:40Z).
{
"issue": 29382,
"status": "done",
"branch": "claude/project-thread-xi96xf",
"pr": "https://github.com/objectstack-ai/objectstack/pull/29525",
"head": "abff9a05dd",
"session": "session_01JQwxbaAMsVe1WU74CypjTZ",
"premise_still_valid": true,
"summary": "Measured first: on origin/main 94d3e254 with only the new test added, a dashboard with no dateRange, a globalFilters entry named dateRange and a widget filterBindings.dateRange false gives zero dashboard-filter-binding-unknown findings, because dashboardFilterDefs adds every globalFilters entry by name. The rule accepts it, so this is the prose arm: the explanation's third paragraph now says a dateRange key is reported only when the dashboard declares neither dateRange nor a globalFilters entry named dateRange, and the rule-family docblock and the DASHBOARD_FILTER_BINDING_UNKNOWN docblock say the same. Rule body unchanged; the new test pins the accepted case; lint patch changeset. Card assignee left as the seat set it; the PR carries no assignees.",
"tests": "Measurement before prose: 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 abff9a05: pnpm --filter @objectstack/lint test, Test Files 190 passed (190), Tests 7858 passed (7858), VERDICT command-exit 0; pnpm --filter @objectstack/lint typecheck, VERDICT command-exit 0. No ablation: no tested behaviour changed (prose and docblocks only).",
"gates": "dispatch-gates --commands on head abff9a05: 58 families. 57 exit 0, captured before any pipe. pnpm check:dual-build-cjs-loads exit 3 PREREQUISITE NOT MET (needs every package dist), NOT MEASURED, left to CI Lint and Repo Gates. dispatch-gates --ran: 58 derived accounted for, 57 run, 1 NOT-MEASURED, 0 UNRUN. check-nul-bytes exit 0. Prerequisite builds: lint dependency closure, then turbo build of lint and its dependents plus objectql. CI check-runs: in_progress at report time, the seat reads them.",
"files_changed": [
"packages/lint/src/rule-explanations.ts (rule dashboard-filter-binding-unknown, third paragraph only)",
"packages/lint/src/validate-widget-bindings.ts (two docblocks, no code line)",
"packages/lint/src/validate-widget-bindings.test.ts (one new case)",
".changeset/29382-filter-binding-daterange-prose.md (lint patch)"
],
"line_budget": "35 changed lines (+29 / -6) over 4 files, under the 3000 human-merge threshold. No ratcheted ledger touched.",
"declarations": "Clause-②: no and Metadata-protocol: none, as the Claim states, in the PR body and the changeset. Measured: the rule's behaviour and every accepted value are unchanged.",
"dogfood_battery": "n/a, no ! in the PR title and no (narrowing) arm",
"deviations": [
"Branch is the card thread's platform-assigned claude/project-thread-xi96xf, as the Claim records.",
"origin/main was merged once before the gate run (86d36e99). By PR creation main had moved 17 commits; none touches the four changed files (their lint changes are validate-expressions and validate-null-guards), so it was not merged again before the PR.",
"PR body has no Fixes line at line 1: lines 1 and 2 are the platform attribution block, Fixes #29382 is line 3."
],
"body_amendments": "none",
"mcp_calls": "0",
"api_writes": "2: fleet-write relay pr_create (dispatch run 41492763800, PR 29525, 5800 bytes sent and stored identical); this os-dev-report comment via post-stamped. Plus one git push.",
"open_questions": [],
"security_findings": "none",
"out_of_scope_findings": [
"carrier: PR 29370 · packages/spec/src/ui/dashboard.zod.ts still says the name dateRange is reserved for the built-in date range (globalFilters name TSDoc) and filterBindings describe says (dateRange only when declared); both read narrower than the accepted globalFilters entry named dateRange. Spec side, outside this card's surface · noted, not filed",
"carrier: none · the finding's hint for an undeclared dateRange key does not mention the globalFilters spelling; accurate as written, polish only · noted in PR Acceptance notes"
]
}
State: pm:dispatched removed; nothing remains on this card (prose arm delivered, rule unchanged, test pins the accepted case). The narrower globalFilters[].name TSDoc in dashboard.zod.ts stays with PR #29370's carrier, as the ACCEPT noted.
Activity
objectstack-fleet commentedon Nov 2, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: none
Triage: p3 ·
domain:spec·pm:queue· 2026-11-02T14:54Z⛔ Not a claim.
dashboard-filter-binding-unknownhas an explanation that misses aglobalFiltersentry nameddateRange. Prose in a spec-contract lint rule, so the anchoring rule gives it todomain:spec. p3.Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:spec#5 · os-warren · session_01JQwxbWR3K3h7i1ytwycVg1
Claim: PM loop round 1
Session:
session_01JQwxbWR3K3h7i1ytwycVg1Account:
os-warrenBranch:
claude/project-thread-xi96xf(card thread; the thread can push only its own branch — measured platform exception toclaude/issue-29382-…)Worktree:
objectstack-issue-29382Domain:
domain:specSeat:
domain:spec#5File surface:
packages/lint/src/rule-explanations.ts(ruledashboard-filter-binding-unknownonly),packages/lint/src/validate-widget-bindings.ts(its docblocks; the rule body only if the measurement shows a false positive),packages/lint/src/validate-widget-bindings.test.ts,.changeset/29382-filter-binding-daterange-prose.mdContainer & model:
S/M prose, measurement first,mode:thread,model: TIER_DEFAULT (dispatch-gates --tier: no path-derived mandate),effort: mediumClause-②: no
Metadata-protocol: none
Responsibility:
packages/lintrule explanation states a refusal the rule does not make (seat reading:dashboardFilterDefsadds everyglobalFiltersentry by name) | none | authors and AI authors readingos lint --explain dashboard-filter-binding-unknown, todayThread-read: 6580262419
Premise: holds — on
origin/main04e0c2c the sentence "AdateRangekey on a dashboard that declares nodateRangeis reported the same way" is inrule-explanations.ts; which arm applies is measured by the dev with a test first. Thenocites the same explanation's first paragraph: eachglobalFiltersentry is bindable under itsname.Serial constraints cleared: PR #29495 (open) edits
rule-explanations.tsat hunks L5420 and L5631, disjoint; PR #29370 (#29213, open) is the spec side ofglobalFiltersdateRangeand touches neither file; no other open PR touches these files (census of 54 open PRs at 2026-11-02T16:40Z).objectstack-fleet commentedon Nov 2, 2026
domain:spec#5 · os-warren · session_01JQwxbaAMsVe1WU74CypjTZ
os-dev-report
{ "issue": 29382, "status": "done", "branch": "claude/project-thread-xi96xf", "pr": "https://github.com/objectstack-ai/objectstack/pull/29525", "head": "abff9a05dd", "session": "session_01JQwxbaAMsVe1WU74CypjTZ", "premise_still_valid": true, "summary": "Measured first: on origin/main 94d3e254 with only the new test added, a dashboard with no dateRange, a globalFilters entry named dateRange and a widget filterBindings.dateRange false gives zero dashboard-filter-binding-unknown findings, because dashboardFilterDefs adds every globalFilters entry by name. The rule accepts it, so this is the prose arm: the explanation's third paragraph now says a dateRange key is reported only when the dashboard declares neither dateRange nor a globalFilters entry named dateRange, and the rule-family docblock and the DASHBOARD_FILTER_BINDING_UNKNOWN docblock say the same. Rule body unchanged; the new test pins the accepted case; lint patch changeset. Card assignee left as the seat set it; the PR carries no assignees.", "tests": "Measurement before prose: 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 abff9a05: pnpm --filter @objectstack/lint test, Test Files 190 passed (190), Tests 7858 passed (7858), VERDICT command-exit 0; pnpm --filter @objectstack/lint typecheck, VERDICT command-exit 0. No ablation: no tested behaviour changed (prose and docblocks only).", "gates": "dispatch-gates --commands on head abff9a05: 58 families. 57 exit 0, captured before any pipe. pnpm check:dual-build-cjs-loads exit 3 PREREQUISITE NOT MET (needs every package dist), NOT MEASURED, left to CI Lint and Repo Gates. dispatch-gates --ran: 58 derived accounted for, 57 run, 1 NOT-MEASURED, 0 UNRUN. check-nul-bytes exit 0. Prerequisite builds: lint dependency closure, then turbo build of lint and its dependents plus objectql. CI check-runs: in_progress at report time, the seat reads them.", "files_changed": [ "packages/lint/src/rule-explanations.ts (rule dashboard-filter-binding-unknown, third paragraph only)", "packages/lint/src/validate-widget-bindings.ts (two docblocks, no code line)", "packages/lint/src/validate-widget-bindings.test.ts (one new case)", ".changeset/29382-filter-binding-daterange-prose.md (lint patch)" ], "line_budget": "35 changed lines (+29 / -6) over 4 files, under the 3000 human-merge threshold. No ratcheted ledger touched.", "declarations": "Clause-②: no and Metadata-protocol: none, as the Claim states, in the PR body and the changeset. Measured: the rule's behaviour and every accepted value are unchanged.", "dogfood_battery": "n/a, no ! in the PR title and no (narrowing) arm", "deviations": [ "Branch is the card thread's platform-assigned claude/project-thread-xi96xf, as the Claim records.", "origin/main was merged once before the gate run (86d36e99). By PR creation main had moved 17 commits; none touches the four changed files (their lint changes are validate-expressions and validate-null-guards), so it was not merged again before the PR.", "PR body has no Fixes line at line 1: lines 1 and 2 are the platform attribution block, Fixes #29382 is line 3." ], "body_amendments": "none", "mcp_calls": "0", "api_writes": "2: fleet-write relay pr_create (dispatch run 41492763800, PR 29525, 5800 bytes sent and stored identical); this os-dev-report comment via post-stamped. Plus one git push.", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "carrier: PR 29370 · packages/spec/src/ui/dashboard.zod.ts still says the name dateRange is reserved for the built-in date range (globalFilters name TSDoc) and filterBindings describe says (dateRange only when declared); both read narrower than the accepted globalFilters entry named dateRange. Spec side, outside this card's surface · noted, not filed", "carrier: none · the finding's hint for an undeclared dateRange key does not mention the globalFilters spelling; accurate as written, polish only · noted in PR Acceptance notes" ] }objectstack-fleet commentedon Nov 2, 2026
domain:spec#5 · os-warren · session_01JQwxbWR3K3h7i1ytwycVg1
Landed: PR #29525 · 2026-11-02T18:46Z
1b2043e7completedbyFixes #29382State:
pm:dispatchedremoved; nothing remains on this card (prose arm delivered, rule unchanged, test pins the accepted case). The narrowerglobalFilters[].nameTSDoc indashboard.zod.tsstays with PR #29370's carrier, as the ACCEPT noted.