Skip to content

includes refuses a field the schema says is a scalar - #74

Merged
rmichaelthomas merged 1 commit into
mainfrom
fix/includes-refuses-a-known-scalar
Sep 12, 2026
Merged

rmichaelthomas merged 1 commit into
mainfrom
fix/includes-refuses-a-known-scalar

Conversation

@rmichaelthomas

Copy link
Copy Markdown
Owner

A defect #72 introduced, found while porting.

What happened

includes is a list-membership probe, and a non-list operand evaluates to false at runtime by decision — test_includes_with_scalar_left_operand_is_false pins it. That is right where the operand's type is whatever the value turned out to be.

It is wrong at analysis time, where the record schema has already said what the field holds:

filter the orders where title includes "roof"

validated clean, emptied a two-record list, and reported success.

Reachable only since #72 admitted includes after where. The refusal that change replaced was safe and described the wrong problem — "I couldn't parse the condition after 'where'" — and what replaced it described nothing and was wrong. A misleading refusal beats a silent wrong answer, so this is mine and this is the fix.

The rule

Answer where the type is known; defer where it is not.

  • string / number / date → refused
  • unknown → runtime, unchanged

A list-valued field is unknown statically, so filter the orders where tags includes "urgent" — the case #72 exists for — still works, and is tested alongside.

The message names what is absent

'includes' tests whether a list holds a value, and 'title' is text.
Liminate has no text-contains test.

That is the honest answer to a downstream consumer asking for contains, and it is the answer rather than a new word because v27 §56's locked meta-finding says so: the era of new verbs is ending; the era of new positions is beginning. between — the structurally identical case — was put on the operator-extensibility pack frontier by the same ruling, and packs today extend verbs and nouns only.

Verified

  • 1748 passed, 2 skipped
  • a corpus case pins the refusal, so the TypeScript port inherits it rather than the silence
  • grammar projections regenerated

🤖 Generated with Claude Code

https://claude.ai/code/session_01E6qcDj1e1dEYvc8jLnpGZy

`includes` is a list-membership probe, and a non-list operand evaluates
to false at runtime by decision (`test_includes_with_scalar_left_operand
_is_false`). That is right where the type is whatever the value turned
out to be. It is wrong at analysis time when the record schema has
already said the field holds text:

    filter the orders where title includes "roof"

validated clean, emptied a two-record list, and reported success.

Reachable only since #72 admitted `includes` after `where`. The refusal
that change replaced was safe and described the wrong problem — "I
couldn't parse the condition after 'where'" — and what replaced it
described nothing and was wrong. A misleading refusal beats a silent
wrong answer, so this is the one I introduced and the one to fix.

The analyzer now answers where the type is known and defers where it is
not. A list-valued field is `unknown` statically, so it still reaches
runtime and nothing that worked before stops working — the list-field
case is tested alongside.

The message says what is absent rather than what is malformed:
"'includes' tests whether a list holds a value, and 'title' is text.
Liminate has no text-contains test." That is the honest answer to a
downstream consumer asking for `contains`, and v27 §56's locked
meta-finding — the era of new verbs is ending — is why the answer is not
to add one.

A corpus case pins it, so the TypeScript port inherits the refusal rather
than the silence. 1748 passed, 2 skipped; grammar projections regenerated.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E6qcDj1e1dEYvc8jLnpGZy
@rmichaelthomas
rmichaelthomas merged commit c594c6d into main Sep 12, 2026
3 checks passed
@rmichaelthomas
rmichaelthomas deleted the fix/includes-refuses-a-known-scalar branch September 12, 2026 06:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant