Repository navigation
Commit f05919b
docs(design): predicate compilation convergence — design and cost account (#20732)
Part of #5930. This PR lands the investigation's deliverable. The build
decision (the document's §6, D1–D7) goes to the maintainer on #5930
after it merges, so merging must not close the card.
Clause-②: no
This PR is the investigation's whole deliverable:
`docs/design/predicate-compilation-convergence.md`. It is a design and a
cost account for shape A (a shared semantic tree, with compilers that
own only their dialect), measured on `3711e0b763`.
⛔ It is not a build. The diff adds one document and edits no source,
test, schema, gate or skill file. The document proposes; the build
decision is the maintainer's.
## What the document measures
- **Census (H1).**
- 11 faces in 15 source files turn a `FilterCondition` into SQL, a query
document or a boolean. The card counted 5 plus a half.
- Faces the card never named:
- `TursoDriver.toRemoteFilter`, a lowering pass in front of the remote
transport;
- the three `driver-memory` faces: the query path, a reference matcher
with no production caller, and the cube face;
- `driver-mongodb`;
- the analytics draft-preview evaluator;
- the per-aggregation `filter` half of `having`.
- The #5499 freeze was dissolved on 2026-08-11, so it excludes nothing.
- **The shared layer.**
- About ten shared doors in spec, core and objectql decide what a filter
may say. They run at six seams.
- What a filter *means* is still copied. The NULL-polarity quartet
exists in 4 copies (293 code lines), and the whole-day upper bound is
called from 10 face files (41 call sites).
- **The measured tax (H2).**
- The `$empty` ruling took 4 cards, 4 PRs and 13 dev rounds, and edited
13 distinct face files.
- The last-supported-day ruling (#20600, then #20661) took 2 cards, 2
PRs and 3 rounds, and edited 10 distinct face files.
- The temporal comparand door (#20549 with #20480) is enforced at the
engine seam. It took 1 PR and 1 round, and edited 0 face files.
- Between 2026-08-14 and `3711e0b763`, 22 commits edited 3 or more face
files. By subject, 18 of them are filter semantics.
- **The #6050 re-check.** At the faces' own entry points, four faces
still answer an `undefined` comparand, each in its own way, and
`driver-mongodb` passes it through. Every production path I traced
refuses it at a shared door, except the `driver-memory` cube face, which
runs no door.
- **Shape A (H3) and the cost account (H4).** The document covers:
- what the tree holds and what stays per dialect;
- the bounded output vocabulary the census forces;
- two representations and the seams;
- the per-face migration table and the conformance net;
- the order of work and the risks.
- **Recommendation, against the four axes: a smaller first slice.**
- Build one shared `FilterCondition` → `FilterCondition` lowering, and
run it at the seams that already run the doors.
- It would hold `$between`, the whole-day bound and the NULL-polarity
guards. Per-face deletions follow.
- It is not the full typed-IR build, and it adds no gate. It requires an
ADR-0053 D-D1 amendment.
- Section 6 lists seven decisions for the maintainer.
## Verification
- **Gates.** `node scripts/pm/dispatch-gates.mjs --commands` on
`c814d60164` derived 12 families, and `--ran` reconciled them: 12 run, 0
NOT MEASURED, every exit code recorded. All 12 exit 0.
- `check:doc-formula-expressions` first answered PREREQUISITE NOT MET
(exit 3), because `@objectstack/lint` was not built. After the build it
exits 0.
- **Probes.** The probes behind sections 2.4 and 2.5 are scratch
scripts, not committed. Appendix A describes them.
- **NOT MEASURED:** PostgreSQL and MySQL, a live mongod, a live Turso
remote server, every HTTP door, and the sibling repositories.
- **Changeset.** `docs/design/` ships in no package, so this PR carries
none and takes the `skip-changeset` label.
## Acceptance notes
The census found these candidate defects. The dev report handed them to
the seat, and nothing is filed from this PR itself. The seat filed items
1 and 2 as bare findings; items 3–5 stay notes.
1. The read-scope compiler `compileScopedFilterToSql` applies no
whole-day upper bound and binds temporal comparands exactly as written
(section 2.5, item 1). Filed as #20733.
2. `MemoryAnalyticsService` runs neither shared comparand door, so `{d:
undefined}` reads as `{d: null}` (section 2.5, item 2). Filed as #20734.
3. The draft-preview evaluator's `$contains` folds case (section 2.5,
item 3).
4. `memory-matcher.ts` `match()` has no production caller (section 2.5,
item 4).
5. `.claude/skills/pm-dispatch/references/compile-surfaces.md` has
drifted from the code it lists (section 5, option C).
---
_Generated by [Claude
Code](https://claude.ai/code/session_01DEvba2nBuD4tWzfq8r8NFY)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent d282087 commit f05919b
1 file changed
Lines changed: 570 additions & 0 deletions
0 commit comments