Skip to content

fix(spec,service-analytics): the matrix's token axis + its sixth consumer, and the dropped $between it found (ADR-0053 D-A3.1) - #4109

Merged
os-zhuang merged 6 commits into
mainfrom
claude/adr-0053-temperature-consistency-akyja5
Jul 30, 2026
Merged

fix(spec,service-analytics): the matrix's token axis + its sixth consumer, and the dropped $between it found (ADR-0053 D-A3.1)#4109
os-zhuang merged 6 commits into
mainfrom
claude/adr-0053-temperature-consistency-akyja5

Conversation

@os-zhuang

@os-zhuangos-zhuang commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

#4081(ADR-0053 D-A3)的补完。矩阵本体已由 #4098 先行落地;本 PR 与其合流,补上 #4098 的 ADR 附录里明确记为仍然开放的两处覆盖,并修掉补覆盖时矩阵当场抓到的缺陷——以及顺着成因挖出的一整类。

一、relative-token 轴(#4098 附录记为开放)

四次事故都发生在 token 解析之下,但作者实际书写的就是 {today} / {90_days_ago} / {current_month_end},而没有任何测试证明解析后的比较值在各后端落到同一批行。

  • TemporalCase 新增 tokenFilter?dateRange?,加上钉死的参考瞬间 TEMPORAL_NOW
  • 能触达 @objectstack/core 的消费者把 token 拼写解析后必须落在与字面量拼写相同的行集——resolver 漂移与 evaluator 漂移由此可分。formula 依赖刻意止于 spec,只跑字面量。
  • 同时补:TemporalRow.writerForm(D-E4 混合写入者播种)、负 epoch 行、date 的相等与 $in[P2] Provide a declarative time-relative trigger (avoid fragile date-equality on record-change) #1874 起源形态)、driver-sqlite-wasm 继承护栏、driver-sql 未回填 legacy 双扫。

二、第六个消费者:NativeSQLStrategy

它正是 #3650 事发的那个面,也是唯一手工拼 SQL、不走驱动编译器的后端,却在矩阵的后端表里没有消费者。原因很说明问题:它现有的套件断言的都是 SQL 字符串,而谓词被丢掉对字符串断言完全隐形——SQL 依然合法,只是更宽。新消费者用真实引擎(sql.js)执行并断言行 id

三、它当场抓到的缺陷:$between 谓词凭空消失

首跑即红:$between 返回全表。成因在共享的 filter-normalizer——MONGO_TO_CUBE_OP 里没有 $between,未映射的算子被 continue 掉,谓词直接从 WHERE 消失。两条策略都吃这个归一化器,所以都中招。用户侧症状就是 #3650:带区间过滤的图表画出整个数据集。

修法:$between下降为它的两个界gte + lte),上界自动继承各策略已有的整日日历规则,不需要第二份实现——与 #4098 修 preview 的做法一致。

四、收口成因本身(Closes#4128

只修 $between 等于只修实例。按同一把尺子把整个可授权词汇过了一遍,又挖出两处比「丢弃」更糟的——语义被悄悄写反

算子修复前修复后
$startsWith / $endsWith静默丢弃 → 全表带锚点的 LIKE 'x%' / LIKE '%x';ObjectQL 侧透传规范算子,锚点不依赖 regex 方言
$null静默丢弃 → 全表。这是 Console「为空/不为空」筛选器产生的形状,即这类 widget 一直在显示全部行按布尔值编译为 IS NULL / IS NOT NULL
$exists与取值无关地映射成 set{$exists: false} 编译成 IS NOT NULL——与语义完全相反$null 一起显式解析:键→名的映射表表达不了「含义随取值翻转」的算子,这正是反转的成因
$notContainsObjectQLStrategy 没有 case,落到 default: return v0 返回裸值——「不包含 x」被编译成「等于 x透传 $notContains
未知算子归一化层 continue 丢弃;ObjectQL 层当成相等两处都抛错#3948 先例)

$or / $not 仍跳过(需要递归 WHERE 构建器),但这一条现在写进模块文档作为已声明的缺口,不再是隐性的。

顺带更正我在 #4128 里的一处错误:原文把 $regex 列为 spec 词汇,实际是我 grep 时把注释当成了声明——可授权词汇里没有它。

验证(本地全绿)

结果
spec6987
service-analytics413(原 360)
driver-sql矩阵 43(16 字面 + 11 token + 16 legacy)
driver-sqlite-wasm / driver-memory / formula27 / 27 / 16

两个新套件都用 git stash 实测过修复前的行为:$between 4 例红、算子覆盖 6 例红。mongodb 套件本沙箱无二进制而 skip,CI 真实执行。spec 八个生成物 gate 全 PASS。

Refs #4081Closes#4128

🤖 Generated with Claude Code

https://claude.ai/code/session_01TqqZmPS5a4gJGBoCTwipFr

…atetime backends (ADR-0053 D-A3) (#4081)
The temporal seam broke four times (#3650 window dropped entirely, #3773
epoch-as-Julian-day NULL buckets, #3777 bare-day upper bound losing the
final day, #4047 type-bracket comparison returning nothing on memory/mongo),
and each break was found by accident: every fix left a suite proving its own
issue against its own fixture, with no shared standard to hold the six
evaluation surfaces together.
This adds the standard — the temporal twin of filter-logic-conformance
(#3774), and the one ADR-0053 decision (D-A3) that had never been built:
- `packages/spec/src/data/temporal-conformance.ts` exports
`TEMPORAL_CONFORMANCE_ROWS` (one fixture spanning exact-midnight,
intra-day, next-midnight, month-end last-millisecond, leap-day and
pre-epoch instants, each tagged with a writer form for the D-E4
mixed-writer axis) and `TEMPORAL_CONFORMANCE_CASES`
({ name, fieldType, operator, filter, tokenFilter?, dateRange?, expected,
note }) — field-type × operator × bound-semantics (D-D2) × relative-token
cells, asserting row-id sets, never emitted SQL. Each note names the
incident the case guards.
- Six thin consumers: driver-sql (canonical + un-backfilled legacy storage;
live PG/MySQL via the existing CI temporal job), driver-sqlite-wasm
(inheritance guard), driver-memory and driver-mongodb (mixed-writer
seeds), formula's matchesFilterCondition (RLS write-side check),
and the analytics preview evaluator (where + timeDimensions.dateRange,
the #3650 surface).
- The token axis runs end-to-end: consumers that can reach
@objectstack/core resolve each case's tokenFilter/dateRange against the
pinned TEMPORAL_CONFORMANCE_NOW and must land on the same rows as the
literal spelling, so resolver drift and evaluator drift are
distinguishable at a glance.
Deliberate scope, same discipline as the filter-logic table: a case belongs
here only if every backend must agree on it. The schema-aware-only cells
(bare-day $eq/$in on datetime, $gt at an exact stored midnight, Field.time)
stay pinned in the per-driver suites and are documented as exclusions.
Closes#4081.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TqqZmPS5a4gJGBoCTwipFr
@vercel

vercelBot commented Jul 30, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredJul 30, 2026 11:12am

Request Review

…n top
Main landed its own D-A3 matrix (#4098: TEMPORAL_ROWS/TEMPORAL_CASES + the
preview $between fix) while this branch was in flight. Resolution keeps
main's landed table, naming and consumers as the base, and re-applies this
branch's increments — exactly the coverage #4098's ADR addendum recorded as
still open:
- the relative-token axis: TemporalCase.tokenFilter/dateRange + TEMPORAL_NOW,
resolved via @objectstack/core resolveFilterTokens in the five
core-reachable consumers (formula stays literal-only by dependency stance)
- TemporalRow.writerForm: mixed writer-population seeding (D-E4) in the
sql/wasm/memory/mongo consumers
- a pre-epoch fixture row, and the date equality/$in cells (#1874's shape)
- a driver-sqlite-wasm consumer pinning the inherited SqlDriver seam
- a legacy-storage sweep in the driver-sql consumer (un-backfilled mixed
epoch/naive column through the read-repair path)
The duplicate preview consumer from this branch is dropped in favour of
main's preview-temporal-conformance.test.ts, extended with the token and
timeDimensions.dateRange sweeps; this branch's changeset is rewritten as the
increment (.changeset/temporal-conformance-token-axis.md) alongside #4098's.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TqqZmPS5a4gJGBoCTwipFr
@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation protocol:data tests size/m tooling labels Jul 30, 2026
@github-actions

github-actionsBot commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): packages/services, @objectstack/spec.

108 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/ai/agents.mdx(via @objectstack/spec)
  • content/docs/ai/skills-reference.mdx(via @objectstack/spec)
  • content/docs/ai/skills.mdx(via @objectstack/spec)
  • content/docs/api/client-sdk.mdx(via @objectstack/spec)
  • content/docs/api/environment-routing.mdx(via @objectstack/spec)
  • content/docs/api/error-catalog.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-client.mdx(via @objectstack/spec)
  • content/docs/api/error-handling-server.mdx(via @objectstack/spec)
  • content/docs/api/index.mdx(via @objectstack/spec)
  • content/docs/automation/approvals.mdx(via packages/spec)
  • content/docs/automation/flows.mdx(via @objectstack/spec)
  • content/docs/automation/hook-bodies.mdx(via packages/spec)
  • content/docs/automation/hooks.mdx(via @objectstack/spec)
  • content/docs/automation/index.mdx(via @objectstack/spec)
  • content/docs/automation/webhooks.mdx(via packages/services, @objectstack/spec)
  • content/docs/automation/workflows.mdx(via @objectstack/spec)
  • content/docs/concepts/architecture.mdx(via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx(via packages/spec)
  • content/docs/concepts/index.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx(via packages/spec)
  • content/docs/concepts/north-star.mdx(via packages/spec)
  • content/docs/data-modeling/analytics.mdx(via @objectstack/spec)
  • content/docs/data-modeling/drivers.mdx(via @objectstack/spec)
  • content/docs/data-modeling/external-datasources.mdx(via @objectstack/spec)
  • content/docs/data-modeling/field-types.mdx(via @objectstack/spec)
  • content/docs/data-modeling/fields.mdx(via @objectstack/spec)
  • content/docs/data-modeling/formulas.mdx(via @objectstack/spec)
  • content/docs/data-modeling/index.mdx(via @objectstack/spec)
  • content/docs/data-modeling/objects.mdx(via @objectstack/spec)
  • content/docs/data-modeling/queries.mdx(via @objectstack/spec)
  • content/docs/data-modeling/schema-design.mdx(via @objectstack/spec)
  • content/docs/data-modeling/seed-data.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation-rules.mdx(via @objectstack/spec)
  • content/docs/data-modeling/validation.mdx(via @objectstack/spec)
  • content/docs/deployment/cli.mdx(via @objectstack/spec)
  • content/docs/deployment/troubleshooting.mdx(via @objectstack/spec)
  • content/docs/deployment/validating-metadata.mdx(via @objectstack/spec)
  • content/docs/getting-started/build-with-claude-code.mdx(via @objectstack/spec)
  • content/docs/getting-started/common-patterns.mdx(via @objectstack/spec)
  • content/docs/getting-started/examples.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-reference.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx(via @objectstack/spec)
  • content/docs/getting-started/your-first-project.mdx(via @objectstack/spec)
  • content/docs/kernel/cluster.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/auth-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/cache-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/data-engine.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/index.mdx(via @objectstack/spec)
  • content/docs/kernel/contracts/metadata-service.mdx(via packages/spec)
  • content/docs/kernel/contracts/storage-service.mdx(via packages/spec)
  • content/docs/kernel/index.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/audit-service.mdx(via packages/services)
  • content/docs/kernel/runtime-services/email-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/index.mdx(via packages/services, packages/spec)
  • content/docs/kernel/runtime-services/queue-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/settings-service.mdx(via packages/services)
  • content/docs/kernel/runtime-services/sharing-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/sms-service.mdx(via packages/spec)
  • content/docs/kernel/runtime-services/storage-service.mdx(via packages/spec)
  • content/docs/kernel/services-checklist.mdx(via @objectstack/spec)
  • content/docs/kernel/services.mdx(via @objectstack/spec)
  • content/docs/permissions/authorization.mdx(via @objectstack/spec)
  • content/docs/permissions/permission-sets.mdx(via @objectstack/spec)
  • content/docs/permissions/permissions-matrix.mdx(via @objectstack/spec)
  • content/docs/permissions/positions.mdx(via @objectstack/spec)
  • content/docs/permissions/rls.mdx(via @objectstack/spec)
  • content/docs/permissions/sharing-rules.mdx(via @objectstack/spec)
  • content/docs/plugins/adding-a-metadata-type.mdx(via @objectstack/spec)
  • content/docs/plugins/development.mdx(via @objectstack/spec)
  • content/docs/plugins/index.mdx(via @objectstack/spec)
  • content/docs/plugins/packages.mdx(via packages/services, @objectstack/spec)
  • content/docs/protocol/backward-compatibility.mdx(via @objectstack/spec)
  • content/docs/protocol/diagram.mdx(via packages/spec)
  • content/docs/protocol/kernel/config-resolution.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/i18n-standard.mdx(via packages/services, @objectstack/spec)
  • content/docs/protocol/kernel/index.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/lifecycle.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/plugin-spec.mdx(via @objectstack/spec)
  • content/docs/protocol/kernel/runtime-capabilities.mdx(via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/query-syntax.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx(via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/record-alert.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx(via @objectstack/spec)
  • content/docs/releases/implementation-status.mdx(via @objectstack/spec)
  • content/docs/releases/index.mdx(via @objectstack/spec)
  • content/docs/releases/v12.mdx(via @objectstack/spec)
  • content/docs/releases/v13.mdx(via @objectstack/spec)
  • content/docs/releases/v16.mdx(via @objectstack/spec)
  • content/docs/releases/v17.mdx(via @objectstack/spec)
  • content/docs/releases/v9.mdx(via @objectstack/spec)
  • content/docs/ui/actions.mdx(via @objectstack/spec)
  • content/docs/ui/create-vs-edit-form.mdx(via @objectstack/spec)
  • content/docs/ui/dashboards.mdx(via @objectstack/spec)
  • content/docs/ui/forms.mdx(via @objectstack/spec)
  • content/docs/ui/index.mdx(via @objectstack/spec)
  • content/docs/ui/public-data-collection.mdx(via @objectstack/spec)
  • content/docs/ui/setup-app.mdx(via @objectstack/spec)
  • content/docs/ui/translations.mdx(via @objectstack/spec)
  • content/docs/ui/views.mdx(via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuangos-zhuang changed the title test(spec): temporal conformance matrix — one standard for six date/datetime backends (ADR-0053 D-A3) (#4081)test(spec): the temporal conformance matrix gains its relative-token axis (ADR-0053 D-A3, #4081 follow-up)Jul 30, 2026
…$between it found (ADR-0053 D-A3.1)
NativeSQLStrategy is the surface #3650 was actually about, and it was listed
in the conformance matrix's own backend table with no consumer — because
every existing suite for it asserts the emitted SQL string, and a DROPPED
predicate is invisible to a string assertion: the SQL stays valid, just
wider. Executing the shared cases against a real engine (sql.js, the same
pure-WASM engine driver-sql falls back to) and asserting row ids is what
D-A3 asked for, and it immediately showed `$between` returning the entire
table.
The cause sat one layer below the strategy, in the shared filter-normalizer:
`$between` was absent from MONGO_TO_CUBE_OP, and an unmapped operator is
`continue`d, so the predicate vanished from the compiled WHERE clause. Both
strategies read that normalizer, so the ObjectQL aggregate path was affected
too. User-visible symptom: a widget with a range filter charts the whole
dataset, with nothing in the SQL to suggest a filter was ever requested.
`$between [min, max]` now LOWERS to its two bounds (gte + lte) rather than
gaining an operator of its own, so a range's max inherits the calendar-day
whole-day rule (#3777) from each strategy's existing upper-bound handling —
NativeSQLStrategy compiles a bare-day upper bound half-open itself, the
ObjectQL path gets the same rule from the driver — instead of needing a
second implementation to keep in step. That is how #4098 closed the same
defect on the preview evaluator. A malformed `$between` throws rather than
being dropped, the stance driver-memory took for the same shape in #3948.
The consumer runs the literal, relative-token and timeDimensions.dateRange
spellings of every shared case. Rows are seeded canonical, where the
driver's temporal hooks are identities, so the context omits them and
exercises the same "absent = identity" path Postgres takes (D-A2); the
un-backfilled mixed column stays covered where the driver truth lives.
The cause itself is NOT fully closed: `$startsWith`, `$endsWith`, `$null`
and `$regex` are still silently dropped by the same `continue`. Filed as
#4128 rather than expanded into this change, with the #3948 precedent for
turning the fallback into a throw.
service-analytics 391 green (was 360; +31 from the new consumer).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TqqZmPS5a4gJGBoCTwipFr
@os-zhuangos-zhuang changed the title test(spec): the temporal conformance matrix gains its relative-token axis (ADR-0053 D-A3, #4081 follow-up)fix(spec,service-analytics): the matrix's token axis + its sixth consumer, and the dropped $between it found (ADR-0053 D-A3.1)Jul 30, 2026
claude added 2 commits July 30, 2026 10:44
The module doc described the shape it produces but never what it actually
maps — and in a normalizer, that omission is load-bearing: an unmapped
operator is `continue`d, which does not "not support" the predicate, it
DELETES it, widening the query to rows the author excluded. That is how the
$between defect survived (see #4128 for the four operators still in that
state, and the #3948 precedent for making the fallback throw).
Mirrors the scope comment the preview evaluator carries for the same reason.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TqqZmPS5a4gJGBoCTwipFr
…query (#4128)
Closes the CAUSE behind the $between defect, not just that instance.
`normalizeAnalyticsFilters` skipped any operator missing from its map, and a
skipped predicate does not narrow a query — it widens it: the SQL stays valid
and returns rows the author excluded. Four operators from the spec's
authorable vocabulary sat in that state, and a fifth was mapped wrongly:
- $startsWith / $endsWith were dropped. Both strategies now compile them —
anchored LIKE on the raw-SQL path, the canonical operators (which every
driver implements directly) on the ObjectQL path, so an anchored match does
not depend on regex dialect.
- $null was dropped. It is what the console emits for an "is empty" filter,
so such a widget showed every row.
- $exists was mapped value-INDEPENDENTLY to `set`, so {$exists: false}
compiled to IS NOT NULL — the inverse of what it asks. It and $null are now
resolved explicitly: a key→name map cannot express an operator whose meaning
flips with its value, which is exactly how that inversion got in.
- $notContains reached ObjectQLStrategy, which had no arm for it and fell to a
`default` returning a bare value — compiling "does not contain x" as
"equals x".
- Unknown operators now THROW on both surfaces rather than being dropped
(normalizer) or reinterpreted as an equality (ObjectQL). #3948's call for
the same shape.
$or / $not remain skipped — expressing them needs a recursive WHERE builder
rather than the flat array the strategies consume. That gap is declared in the
module doc rather than silent.
filter-operator-coverage.test.ts runs the whole vocabulary against a real
SQLite engine and asserts ROW IDS; six of its cases fail without this change.
A dropped predicate is invisible to the SQL-string assertions the strategies'
other suites use, which is how these survived. service-analytics 413 green.
Closes#4128.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TqqZmPS5a4gJGBoCTwipFr
@os-zhuangClaude

Copy link
Copy Markdown
ContributorAuthor

CI 说明:Lint & Type Check 的红不是本 PR 引入的,在 base 分支上同样失败。

失败的其实不是 ESLint 步骤,而是同一 job 里的 check:wildcard-fallthrough#4116 新加的守卫),报的是 packages/adapters/hono/src/index.ts 的一个挂载——本 PR 未触及该文件,且本分支根本不含这个守卫脚本(CI 在 pull_request 下跑的是 PR 与 base 的合并树)。

在纯净的 origin/main4f30943,无任何本 PR 改动)上复现,错误逐字相同:

✗ wildcard fall-through guard (#4116)
packages/adapters/hono/src/index.ts:all `${prefix}/storage/*`
DECLARED but not found by the scan. Moved, renamed or deleted? Update MOUNTS.

成因是两个 PR 的竞态:#4112 删掉了那个挂载,#4116 在守卫账本里声明了它,先后合入未互相 rebase。已单独立项 #4140(含复现步骤与建议的销账式修法)。

本 PR 的其余检查照常,待 main 恢复后我会重跑并推进合并。


Generated by Claude Code

@os-zhuang
os-zhuang marked this pull request as ready for review July 30, 2026 11:26
@os-zhuang
os-zhuang merged commit 7a55913 into mainJul 30, 2026
18 checks passed
@os-zhuang
os-zhuang deleted the claude/adr-0053-temperature-consistency-akyja5 branch July 30, 2026 11:26
os-zhuang pushed a commit that referenced this pull request Jul 30, 2026
The temporal conformance matrix (#4109) gives every case a `tokenFilter`
spelling, and the driver + analytics suites resolve it before asserting.
This suite runs only the literal `filter`, with nothing saying why — so
the absence reads as an omission, and the next person either "fixes" a
non-gap or assumes coverage that cannot exist.
It is architecture: an RLS `check` is a CEL expression (`check` is a
string, compiled by rlsCompiler.compileFilter) where a relative date is
the function today() evaluated at compile time. A {token} string never
reaches this evaluator — resolveFilterTokens runs on the ObjectQL read
path and the write-side check does not go through it; verified that
plugin-security never calls the resolver.
Comment only; the suite is unchanged and still 13/13.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EkL3RGJrzjLEGURsLxfS2f
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationprotocol:datasize/xlteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

analytics filter-normalizer:未映射的算子被静默丢弃 → 查询放宽到全表($between 已修,还剩四个)

2 participants

@os-zhuang@claude