docs(spec): scope the text-operator door's formula prose to the judgement it states - #17711
Conversation
…ment it states The module asserted that a `formula` with a readable `returnType` is judged as the field type its return type names. Measured at the door's only consumer, the engine's field-aware seam, no formula filter ever arrives: the earlier materializability door refuses every one of them with `INVALID_FIELD` 400, whatever the `returnType`, so none of the three formula verdicts is observable there. The non-formula rows are observed with this door's own `INVALID_FILTER` 400, which is what makes the formula rows the exception. Prose only. The verdict function, its sets, the class table, the probe object and every case are byte-identical; seven sites across two files now say the formula rows are a contract answer no consumer currently reaches, and why they are kept rather than retired. The maintainer's verbatim ruling quote is untouched. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MkQhmuuJAVDjmeWNixwDDH
📓 Docs Drift Check1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. What this run could not see
Coarse fallback — 135 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin b7ec52f2a2fdf235eafc598749330d08b2f9217e && git checkout b7ec52f2a2fdf235eafc598749330d08b2f9217e
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 7173d7d142896fe549de8a1779414954e9f83f63 243b2f9fea3c1c39d58f1ddef45672931739b3fe && git checkout -B drift-repro 7173d7d142896fe549de8a1779414954e9f83f63 && git merge --no-ff 243b2f9fea3c1c39d58f1ddef45672931739b3fe
node scripts/docs-audit/affected-docs.mjs --json 7173d7d142896fe549de8a1779414954e9f83f63 |
Landing is blocked on the ready flip only — all four pre-checks pass on this headRead at 2026-09-12T00:36Z by the The four pre-checks, measured on THIS head (not recalled)
What is actually blockingThe draft→ready flip has two carriers and both answer, separately, that they cannot serve it right now:
⭐ The guard held. Each step of the landing script is gated on its own result: the flip must return What happens next⛔ Not standing down, and ⛔ not re-running anything that already passed as a way of looking busy. This PR stays watched with a check-in armed; the flip is retried on each wake until it returns 200, at which point ④ is re-read (the ready flip re-triggers
Generated by Claude Code |
Part of #17400
Prose only. The verdict function, its sets, the class table, the probe object and every case are byte-identical; no logic, no accept set, no behaviour moves.
The fork this card set, and which branch the measurement supports
The card offered two: (a) the prose is wrong, or (b) the implementation drifted. Measured here: (a).
textOperatorDoorVerdictdoes exactly what the prose says about it — thespec-table-sayscolumn below is the function's own answer for all five formula shapes, and it matches the ruling. What is false-as-written is the prose's claim about where that judgement takes effect: the module frames itself throughout as the door "at the engine's field-aware seam", and at that seam a formula filter never arrives.My own contradicting measurement
A probe driving the real engine (
ObjectQL+ a recording driver + this module's own probe object),$containsover each field:f_formula_numberINVALID_FIELDf_formula_textINVALID_FIELDf_formula_booleanINVALID_FIELDf_formula_dateINVALID_FIELDf_formula_untypedINVALID_FIELDf_numberINVALID_FILTERf_booleanINVALID_FILTERf_dateINVALID_FILTERf_textf_selectThe five formula rows carry three different declared verdicts and the seam answers all five identically, with a different code from this door's own — so
returnTypeis never the deciding fact, and none of the three verdicts is observable.Lit control (the bottom five rows). The same probe reproduces the table exactly where the assertion does hold:
number/boolean/daterefused with this door'sINVALID_FILTER400,text/selectthrough to the driver. A probe that called everything a contradiction would prove nothing; this one discriminates.The probe was temporary and is not in the diff.
Why not (b)
Nothing shows the code drifted. The earlier refusal is deliberate and recorded:
assertFilterIsMaterializablerefuses every formula filter because no driver materialises a column for one,packages/spec/src/migrations/registry.tscarries it as theengine-find-formula-filter-refusedentry with a migration remedy, andfilter-dotted-head.tssays the same of formula heads. Reordering the ladder would answer one condition with two wire codes chosen byreturnType— the card's option 3, explicitly a maintainer's decision. Nothing here touches it.Census — the card reported 1 site, there are 7
Deferredbullet in the module headerfilter-text-operator-declared-type.tsTextOperatorDoorVerdict'sdeferreddocformularownotenotepackages/spec/src/data/index.tsSite 3 uses neither the word "formula" nor "seam" — a word-level grep misses it. It prescribes that every case is either a refusal by this door or a driver read; for the formula rows neither holds, which is why the engine suite already partitions them out.
Lit controls for the census. A fabricated phrase scored 0 while a known-present symbol scored 35. Text that mentions formula and the doors and is correct was not flagged:
packages/objectql/src/text-operator-declared-type-door.ts(documents this divergence deliberately),migrations/registry.ts,filter-dotted-head.ts,field-value.zod.ts,filter-text-conformance.ts.Deliberately not rewritten: the maintainer's verbatim ruling quote in the header blockquote. Rewriting a quoted ruling rewrites the ruling. 0 blockquote lines appear in the diff.
Verification
pnpm --filter @objectstack/spec test— 473 files, 13432 tests, all passpnpm --filter @objectstack/spec typecheck— cleanengine-text-operator-declared-type-door.test.ts— 22 tests passcheck:dual-build-cjs-loadsandcheck:lean-entry-closure, both exit 3PREREQUISITE NOT MET, which those scripts define as NOT MEASURED — they need a full-repo build.eslint . --no-inline-configover the whole repo: 6635 files, 0 errorscheck:nul-bytesexit 0Changeset
Required, and measured rather than assumed. The rule is that a changeset may be skipped only when nothing published moves, where published means what the package's
files[]actually ships.@objectstack/specis not private and itsfiles[]includesdist. After a rebuild, the newnotetext appears 8 times underdist/and the new doc prose 2 times (in the.d.tsconsumers read), against a positive control of 4 and a fabricated control of 0. Published bytes move, so:patch.🤖 Generated with Claude Code
https://claude.ai/code/session_01MkQhmuuJAVDjmeWNixwDDH
Generated by Claude Code