# The aggregation corpus `mongodb/specifications` has no aggregation suite. The thirteen `aggregate-*.json` files this project runs come from `crud` and test the aggregate *command* — cursors, read concern, the write stages, collation, `let`. They touch stages barely and expressions not at all: `$lookup`, `$unwind`, `$facet`, `$addFields` and `$replaceRoot` appear nowhere in the pinned corpus. That is PLAN amendment A6, and this directory is its consequence: M2.5 has to bring its own gate. ## The one rule **Inputs are authored here; expectations are measured against a real mongod.** A corpus we write is a corpus that can encode our own bugs as expectations, and it would then agree with us forever. So `sources/*.json` holds documents and pipelines and nothing else, and `record.js` asks mongod 8.3.7 what each pipeline answers. It is the same discipline that corrected three assumptions in M1's session work and every error code in M2 — the alternative, in both cases, would have shipped. ## Running it ```sh node tests/spec/run.js --suite-dir tests/spec/aggregate ``` The same runner as the crud corpus, pointed elsewhere. Sharing it is the point: the entity model, the matchers, the skip accounting and `expectEvents` come for free, and a second runner would drift from the first exactly where it mattered. `--scorecard` is refused with `--suite-dir`: `tests/spec/scorecard.txt` is the crud corpus's record and the milestones are compared against it. ## Re-recording ```sh mongod --port 27099 --dbpath /tmp/mongo-corpus & node tests/spec/aggregate/record.js --mongod-port 27099 ``` Writes `.json` for every `sources/.json`. The generated files are committed: they *are* the corpus, and regenerating them is how a disagreement with mongod gets re-measured rather than argued about. Two things to know when adding cases: - **End a `$group` pipeline with a `$sort`.** Group output order is unspecified, and a case that depended on it would fail for the wrong reason on either server. - **Errors record the code, not the message.** Message text is mongod's to change between releases; a corpus that pinned it would break for the wrong reason. Leave out any case whose answer depends on a server newer than the 4.4 this server reports — recording it from mongod 8.x and judging it against a 4.4 answer measures the version gap, not the engine. ## Where it stands Recorded against mongod 8.3.7. At the M2 tip it read 9 pass / 10 fail; with the accumulators in: ``` group-accumulators.json 18 pass 1 fail 0 skip ``` The one that remains is the compound `_id`, which needs the expression evaluator and is the next tier. The corpus found its first real disagreement on the way there: `$avg` over a group with no numeric value is `null`, not `0`, and a divisor that counted documents rather than numbers would have passed every test anybody would think to write by hand.