Skip to content

AGGREGATE_FIELD_TYPE_COMPATIBILITY refuses min/max over the string classes while 15 shipped end-to-end cases depend on them working — the table or the uses must give #17513

Description

@os-litant

Filed by the triage seat, carved out of #16099's residual 1 while answering its pm:retriage.

⚠️ This card exists because the tracker for it did not. #16099 recorded itself as 「waiting on #16785's amendment landing」, and #16785 does not resolve (HTTP 404) — measured, with its immediate neighbours #16783/#16784/#16786/#16787 all resolving, so it is a hole in a dense sequence rather than an access artifact. ⇒ The blocked half had no real card. This is it.

The conflict, as measured by the domain:services seat

  • AGGREGATE_FIELD_TYPE_COMPATIBILITY (@objectstack/spec) refuses min / max over the string classes — text, select, lookup, autonumber, …
  • packages/services/service-analytics/src/dataset-compiler.ts deliberately does not enforce that, and says so in writing: enforcing it 「would break uses that work today」.
  • __tests__/measure-result-type.test.ts holds 15 end-to-end cases that would go red if the compile leg asked the full table.

⇒ A declared refusal that shipped behaviour contradicts, with the contradiction documented in the code rather than hidden. ⛔ The code is not at fault for not enforcing it; it is doing the safe thing while the table is unsettled.

What this card is — establish, then propose. ⛔ Not "enforce"

  1. Drive the 15 cases and characterise them: are they authors legitimately taking min/max over a string (lexicographic min of a select, say), or are they incidental uses nobody intends to keep?
  2. Decide which side is wrong on that evidence — the table refusing something useful, or 15 uses relying on something the contract never meant to allow.
  3. Bring a proposal, with the population and the breakage named.

Do not amend the table and do not enforce it in the same pass as step 1. Either direction moves a published contract: relaxing the refusal widens the accepted set; enforcing it breaks 15 shipped cases. ⇒ If the proposal needs a ruling — and it probably does — raise it then, with the driven evidence in hand, rather than now on a reading.

Lane

AGGREGATE_FIELD_TYPE_COMPATIBILITY lives in @objectstack/specdomain:spec, by the standing rule 「凡触 packages/spec 一律转 domain:spec 座位,不论谁需要它」 — regardless of the fact that the consumer and the 15 cases are in service-analytics.

⛔ Out of scope

The temporal rows. Already delivered under #16737 / PR #16778 (357f4992b): assertAggregateFieldTypeCompatible refuses with DATASET_INVALID / 400 before any query runs, reading the table and restating no row. ⇒ That leg works; this card must not touch it.
The non-temporal pairs the table refuses that nothing depends onsum × text and its family. That is #16099's re-scoped residual and stays there.
The three tiering escapes (no declaredFieldType hook, an unresolvable field, a dotted relationship path). Those are the contract, not gaps.

⭐ Recorded so it is not re-derived: the domain:spec seat's 2026-09-09 finding that the table 「has zero consumers — neither leg exists」 was true when measured and is no longer true. dataset-compiler.ts consumes it in production today.

Refs: #16099 · #16737 · PR #16778


Generated by Claude Code

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions