plan/spec: pipeline-style updates are done

M3's row and §6 updated: the operator corpus is 125 cases across seven files,
all green, and the pipeline work also gave `aggregate` the `$replaceWith`
stage it never had -- the compiler is shared between the two.

Full matrix at this commit: 249/249 unit tests in ReleaseFast and ReleaseSafe,
83/83 fuzz, operators 125/0, positional 51/0, aggregation 70/0, pinned crud
228/63/196, e2e and crash-fuzz green.
This commit was merged in pull request #9.
This commit is contained in:
A.Shakhmatov
2026-08-10 22:01:11 +03:00
parent 003c418a0e
commit 98fde82946
2 changed files with 12 additions and 3 deletions

11
PLAN.md
View File

@@ -467,7 +467,7 @@ answers, and the trade is only acceptable because the lie is removed first.
| M1 | **Cursors + wire polish** | getMore / killCursors / batchSize; server-side cursor state with idle timeout; sessions plumbing (lsid accepted) as drivers send it; hello advertisement updates; **`moreToCome` on requests** (see the bug below); command-monitoring assertions in the spec runner | crud spec suite green; e2e green | | M1 | **Cursors + wire polish** | getMore / killCursors / batchSize; server-side cursor state with idle timeout; sessions plumbing (lsid accepted) as drivers send it; hello advertisement updates; **`moreToCome` on requests** (see the bug below); command-monitoring assertions in the spec runner | crud spec suite green; e2e green |
| M2 | **The `aggregate` command surface** | `$out` and `$merge` (7 of the 13 failures), and refusing every pipeline construct the engine does not implement instead of answering `0` (amendment A6). The other 6 failures are blocked on M2.5, M4 and M8 — see `docs/M2_DESIGN_REVIEW.md` §7 | `aggregate-*.json`: 0 fail among the 7 reachable cases | | M2 | **The `aggregate` command surface** | `$out` and `$merge` (7 of the 13 failures), and refusing every pipeline construct the engine does not implement instead of answering `0` (amendment A6). The other 6 failures are blocked on M2.5, M4 and M8 — see `docs/M2_DESIGN_REVIEW.md` §7 | `aggregate-*.json`: 0 fail among the 7 reachable cases |
| M2.5 | **The aggregation engine** | expression evaluator, per-stage document iterator, the accumulators, `$unwind`; `$lookup`/`$facet` explicitly out of the first cut (amendment A6) | a purpose-built stage corpus, every expectation measured against mongod | | M2.5 | **The aggregation engine** | expression evaluator, per-stage document iterator, the accumulators, `$unwind`; `$lookup`/`$facet` explicitly out of the first cut (amendment A6) | a purpose-built stage corpus, every expectation measured against mongod |
| M3 | **Update operators + index types** | `distinct` (**done**); positional paths refused rather than destructive (**done**); `$`/`$[]`/`$[<ident>]` + `arrayFilters` (**done**); $setOnInsert, $addToSet, $mul, $min/$max, $pop, $pullAll, $currentDate + `$push`'s modifiers (**done**); then pipeline updates; partial + hashed indexes | `tests/spec/positional/` 0 fail (51 cases) and `tests/spec/operators/` 0 fail (102 cases), both recorded from mongod — **green**; the named gate could not see either, see below; remaining crud coverage; e2e3/e2e4 green | | M3 | **Update operators + index types** | `distinct` (**done**); positional paths refused rather than destructive (**done**); `$`/`$[]`/`$[<ident>]` + `arrayFilters` (**done**); $setOnInsert, $addToSet, $mul, $min/$max, $pop, $pullAll, $currentDate + `$push`'s modifiers (**done**); pipeline-style updates (**done**); then partial + hashed indexes | `tests/spec/positional/` 0 fail (51 cases) and `tests/spec/operators/` 0 fail (125 cases), both recorded from mongod — **green**; the named gate could not see either, see below; remaining crud coverage; e2e3/e2e4 green |
| M4 | **Sessions + transactions** | logical sessions, snapshot isolation on the mmap engine, write concern at commit | sessions + transactions spec suites green | | M4 | **Sessions + transactions** | logical sessions, snapshot isolation on the mmap engine, write concern at commit | sessions + transactions spec suites green |
| M5 | **Change streams** | change feed + resume tokens (likely log-seq based), getMore integration | change-streams spec suite green | | M5 | **Change streams** | change feed + resume tokens (likely log-seq based), getMore integration | change-streams spec suite green |
| M6 | **Admin/ops commands** | dbStats, collStats, serverStatus, ping, buildInfo, listDatabases filters, dropDatabase durability (log it) | mongosh UX smoke; e2e green | | M6 | **Admin/ops commands** | dbStats, collStats, serverStatus, ping, buildInfo, listDatabases filters, dropDatabase durability (log it) | mongosh UX smoke; e2e green |
@@ -1139,6 +1139,15 @@ has to be its own commit with its own re-recorded scorecard.
in `build_upsert_doc`; the pinned crud corpus never noticed because its in `build_upsert_doc`; the pinned crud corpus never noticed because its
upsert cases match `upsertedId` loosely. upsert cases match `upsertedId` loosely.
Pipeline-style updates went into the same corpus rather than an eighth
directory -- another shape of update document, sharing the recorder and the
masking. 23 cases, and the one that decides the design: **the `_id` survives
every stage**, including `$replaceRoot` and `$project: {_id: 0}`, because a
pipeline update rewrites a document rather than replacing one document with
another. A stage setting it to something else is ImmutableField (66). That
work also gave `aggregate` `$replaceWith`, which it never had, since the
stage compiler is shared.
Left open, measured and deliberate: `$bit` is not implemented (mongod has it, Left open, measured and deliberate: `$bit` is not implemented (mongod has it,
no driver in `tests/` sends it, and it is not in the M3 row); `$sort` inside no driver in `tests/` sends it, and it is not in the M3 row); `$sort` inside
`$push` accepts only a one-field key document, where mongod allows several; `$push` accepts only a one-field key document, where mongod allows several;

View File

@@ -71,8 +71,8 @@ push-modifiers.json 21 pass 0 fail 0 skip
set-on-insert.json 9 pass 0 fail 0 skip set-on-insert.json 9 pass 0 fail 0 skip
``` ```
It was recorded red — 18 pass / 84 fail against a server with none of these It was recorded red — 18 pass / 84 fail for the operators, 0 / 23 for the
operators — and driven green by seven commits. The 18 that passed then were pipeline file — and driven green by eight commits. The 18 that passed then were
the shapes this server already answered mongod's way, mostly refusals that the shapes this server already answered mongod's way, mostly refusals that
happened to agree. happened to agree.