Repository navigation
[finding][drivers] driver-mongodb cannot take a structured GroupByNode at all — the object stringifies into a "[object Object]" $group._id #6850
Description
Activity
Triage state repair: +
finding(the title already declared it; the label was missing, which left the card invisible to the queue view AND the findings round — the half-labelled state the sweep disjuncts exist to catch).- Classification: observation-class as filed — the structured-
GroupByNodehalf of the union has no lowering in a package under the [裁决] driver-memory / driver-mongodb 投入冻结 —— 维护者 2026-08-05 口径(跨单锚点) #5499 investment freeze, the defect is recorded as a measured DEBT row in the conformance matrix by [finding][drivers]GroupByNode.alias只有内存分桶认,三个 SQL 面一律忽略 —— 同一个 aggregate 走下推与走回退拿到不同的列键 #6401, and the filing itself says recording-not-claiming. Grading stays with the findings round; the freeze is the standing hold reason. - Routing:
domain:drivers(already on the card) is correct — fix facepackages/drivers/driver-mongodb/src/mongodb-aggregation.ts:38(groupBy?: string[]),:66-69/:85-88(the stringifying loops) andmongodb-driver.ts:512(theas anypass-through) all verified live onorigin/main@41610f6. Note per single-producer discipline the routing label should have been left to the triage seat; it happens to be right, so it stands. - Dedup: [drivers] driver-memory / driver-mongodb disagree with the SQL family on
count_distinct— the two AGGREGATION_CASES cells #6409 left open #6814 (count_distinct, same frozen pair) and [finding][drivers]DriverQuery收窄之外:aggregate/distinct/analyzeQuery等驱动自有查询方法仍要求把对象名写两遍 #6212 (driver-turso's loud version of the same shape, closed) are siblings, not duplicates — the filing already delimits them.
本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
- Classification: observation-class as filed — the structured-
Findings triage round: held (
findingstays) — first formal grading; the earlier comment was a label-state repair.Premises re-verified on
origin/main@3e8e669:mongodb-aggregation.ts:38still declaresgroupBy?: string[](half of the declared union) andmongodb-driver.ts:512still passes the value through(query as any).groupBy, so a structuredGroupByNodestill stringifies into a"[object Object]"$group._id. The hold reason is unchanged: #5499 (investment freeze) is still open and standing, and the defect is carried as a measured DEBT row in the conformance matrix (driver-mongodb×AGGREGATION_CASES, per #6401) — the freeze will be lifted against a measured list, which is exactly what this card is a line of.Restart conditions: #5499 lifts, or the maintainer green-lights the
driver-mongodbAGGREGATION_CASEScell — the closing PR needs the structured-node destructure first (alias alone is unreachable), a server-free suite half per #5517, and the ledger-row deletion in the same PR.本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
huangyiirene commented
on Aug 11, 2026 CollaboratorMore actionsClaim: PM loop round 2 (drivers seat, post-unfreeze batch 1)
Session:session_013ZU38vNzLXCscgdFZjKd53
Branch:claude/issue-6850-mongodb-structured-groupby
Worktree:objectstack-issue-6850
Domain:domain:drivers
File surface:packages/drivers/driver-mongodb/src/mongodb-aggregation.ts,packages/drivers/driver-mongodb/src/mongodb-driver.ts(the:512as anypass-through), a NEW server-free aggregation suite in the same package,scripts/check-driver-conformance.mjs(thedriver-mongodb×AGGREGATION_CASESDEBT row),.changeset/*(stop on breach; explain in the report)
Container & model: M,mode:cloud,model: opus
Serial constraints cleared: file-disjoint from the #5346/#5376 dispatch riding in the same batch (filter faces vs aggregation faces — no shared file); hot-filesql-driver.tsuntouched; no other in-flight claims in the lane.Authorization: maintainer unfroze driver-mongodb 2026-08-11 (verbatim on #5499, comment
5249019855). The findings-round grading on this card named its restart condition as "#5499 lifts" — it has. This card rides with the mongodb half of #6814 (same file, same new suite, same conformance cell): PR carriesFixes #6850+Part of #6814(the driver-memory half of #6814 stays frozen).Premises re-verified by the PM on
origin/main@76d74ecb4:mongodb-aggregation.ts:38stillgroupBy?: string[],:142still$addToSet: fieldRef ?? null,mongodb-driver.ts:512still(query as any).groupBy. Per the grading comment: the closing PR needs the structured-node destructure first (alias alone is unreachable), a server-free suite half per #5517, and the ledger-row deletion in the same PR.
Generated by Claude Code
huangyiirene commented
on Aug 11, 2026 CollaboratorMore actionsos-dev report — #6850 + the driver-mongodb half of #6814
Branch
claude/issue-6850-mongodb-structured-groupbypushed; draft PR #7550 open (Fixes #6850,Part of #6814— deliberately NOTFixes #6814, whose driver-memory half stays frozen).Premises: all three held, and the card under-counted
Re-verified on
origin/main@76d74ecb4before the first edit:Premise Verdict mongodb-aggregation.ts:38declaresgroupBy?: string[]held :66-69/:85-88stringify a structured nodeheld :142lowerscount_distinctvia$addToSet: fieldRef ?? nullheld mongodb-driver.ts:512carries(query as any).groupByheld check-driver-conformance.mjsDEBT row, spelled as describedheld (at :446-486on this tree)One premise the cards did not carry:
count(col)ignoredfieldentirely and emitted{ $sum: 1 }for both spellings, socount(stage)answered 6 whereAGGREGATION_CASESsays 4 — the numbercount(*)already has. Found by executing the case-set rather than reading the file, and it is mandatory for the cell: neither issue names it. This is the case-set's own stated purpose ("three different numbers over one column") catching the collapse it was built for.What landed
normalizeGroupByreads the declared union first (the destructure the grading comment required — alias alone was unreachable).$group._idkeys onalias ?? fieldwith the FIELD as value; the bare-string emission is byte-identical and pinned.count_distinctsizing excludes null, inpostProcessAggregation.count(col)counts non-null values via$cond/$ifNull;count(*)unchanged.dateGranularity→ refused,NOT_IMPLEMENTED/ 501, ADR-0112 envelope, message mirroringdriver-sql/driver-tursosentence for sentence. A malformed entry →INVALID_QUERY/ 400. Both refusal tests assertcodeandstatus, nottoThrow()alone.mongodb-driver.tsspells the declared type. Probed that this is a real guard: assigningDriverQuery['groupBy']tostring[]now failstscagainst the full union.- New server-free suite
mongodb-aggregation-translation.test.ts; thedriver-mongodb×AGGREGATION_CASESDEBT row deleted in the same commit.
Route choices (rejecting the card's own sketch, with reasons)
$ne: nullbefore the$addToSet— rejected as unsound, not merely inferior: as a$matchit drops the row from the whole pipeline, so acount(*)orsum()sharing that pipeline silently loses the null rows. Correct only for a single-aggregation pipeline, which the builder cannot assume.$sizeof$setDifferenceagainst[null]— sound, and better on wire size; needs a$projectstage the builder does not emit withoutgroupBy, i.e. a pipeline-shape change nothing here can execute. Recorded in-code as the right move once the cell has a live half.dateGranularity— measured what the SQL faces lower it to before deciding, per the suggestion. A faithful lowering must emit the engine's bucket LABELS ('2026-01','2026-Q1', ISO'2026-W03'), publishsupports.queryDateGranularity, and be held todate-bucket-parity.test.ts— a card of its own. Refusal chosen; silently ignoring a declared key was never an option.
Gates (local)
driver-mongodbtests 266 passed / 143 skipped (opt-in real-mongod halves) ·driver-mongodbtypecheck clean ·spectypecheck clean ·check:driver-conformanceOK — 37 covered, 3 DEBT, 0 exempt (cell flipped took; driver-memory's row stands) · eslint on all changed files clean · build closure clean. CI: in_progress — not polled; the PM owns convergence.Honest bound on the coverage this cell now claims
The suite holds the LOWERING to the table. It does not answer "does MongoDB agree?" —
$cond/$ifNull/$addToSetare modelled from documentation, not observed, because this environment cannot fetch a mongod binary (proxy 403), and a suite nobody has executed is a claim rather than a check. That bound is written into the suite header, theAGGREGATION_CASESenrolment list and the ledger note rather than left to be discovered.packages/drivers/driver-memoryuntouched. The deadstring_aggarm untouched.
Generated by Claude Code
huangyiirene commented
on Aug 11, 2026 CollaboratorMore actionsACCEPT — PR #7550, MERGED at
f067930(record of the step-7 review that preceded the ready-flip).- Path surface: 6 files — the four claimed (aggregation source, driver cast, new server-free suite, conformance ledger) + changeset + one UNDECLARED file,
packages/spec/src/data/aggregation-conformance.ts, verified comment-only by this seat (DEBT rows struck through, enrolled list updated, freeze paragraph corrected). Cross-seat declaration posted to the spec-surface seat per the UnknownFilterTokenError 漏诊:含非 word 字符的类占位符串({TODAY()}、{current-user-id}、{30 days ago})绕过诊断,原样下发按字面串比较(17.0.0-rc.2) #5586/fix(rest,objectql): the import dry run asks the engine for its verdict instead of predicting it (#4633) #6532 precedent ([PM seat] domain:spec-surface — 🔀 merged into #6017 #6298 comment5249310176). - Beyond-the-cards find:
count(col)ignoredfieldand emitted{ $sum: 1 }(6 where the standard says 4) — caught by EXECUTING the case-set, named by neither card, fixed as mandatory for the cell. The case-set doing what it was built for. - Two PM-sketch rejections reviewed and upheld:
$ne:nullpre-$addToSetrejected as unsound (a$matchdrops null rows from the whole shared pipeline);dateGranularityrefused loudly (NOT_IMPLEMENTED/501, ADR-0112 envelope) rather than implemented or silently dropped — a faithful$dateTrunclowering is measured as a card of its own (bucket labels + capability record +date-bucket-parityenrollment). - Gate rule honored: suite + DEBT-row deletion in the same PR; coverage bound (lowering-only, no live mongod — proxy blocks the binary) stated in the suite header, enrolment list and ledger note rather than left to be discovered.
- CI: 26/26 completed; ESLint and TypeScript Type Check both
completed: successread individually before the flip.
Part of #6814behaved as intended — that card stays open and returns topm:on-holdfor its driver-memory half.
Generated by Claude Code
- Path surface: 6 files — the four claimed (aggregation source, driver cast, new server-free suite, conformance ledger) + changeset + one UNDECLARED file,
- added a commit that references this issue
on Aug 17, 2026 - added a commit that references this issue
on Oct 7, 2026
Found while implementing #6401 (
GroupByNode.aliason the SQL faces). Adjacent to it, not created by it. Filed unassigned, recording not claiming —driver-mongodbis inside the #5499 investment freeze.The finding
GroupByNodeSchemadeclares a UNION: a bare field name, or a structured{ field, dateGranularity?, alias? }node.driver-mongodbcan only take the first half.packages/drivers/driver-mongodb/src/mongodb-aggregation.ts:A structured node is an object in that loop.
groupId[field]stringifies it, so the$group._idkey becomes the literal"[object Object]"and its value the literal"$[object Object]"— a field path that matches nothing. The$projectstage mirrors the same key.So the aggregation does not refuse and does not throw: it returns rows grouped by a nonexistent field path, under a column named
[object Object].Why
tscnever saw itpackages/drivers/driver-mongodb/src/mongodb-driver.ts:512passes the value through ananycast:so the declared
GroupByNode[]union never meets thatstring[]annotation. The annotation is a restatement of the protocol that drifted from it — the same shape #6212 closed fordriver-turso's remote transport, which readgroupByasstring[]and died on"[object Object]"as an unsafe identifier. That one at least failed loudly; this one answers.Scope note — this is NOT the
aliasdivergence#6401 converged the three SQL faces onto
alias ?? fieldfor the projected column.driver-mongodbis not a fourth face of that divergence: the alias is unreachable here rather than ignored, because the whole structured half of the union is. Fixingaliasalone would not help — the node has to be destructured first.Recorded as a measured DEBT row in
scripts/check-driver-conformance.mjs(thedriver-mongodb×AGGREGATION_CASEScell) by #6401, so the conformance matrix carries the verdict rather than an omission.Relationship to #6814
#6814 is the
count_distinctdisagreement for the same frozen pair — a wrong NUMBER from a lowering that exists. This is a different defect: a declared SHAPE that has no lowering at all. Same package, same freeze, separate cells; filing separately so the freeze is lifted against a measured list rather than one line item.Verdict
Read from the source; not executed — this package has no server-free aggregation suite for the cell, which is part of the debt (the real-mongod suites are opt-in since #5517, so whatever closes this needs a server-free half like
mongodb-filter-logic-translation.test.tshas).Not fixed here: #5499 freezes the package, and #6401's ruling kept mechanical alignment out of the enforce change on principle — a frozen driver gets an honest row or a mechanical alignment, never a flip.
Related: #6401, #6814, #6212, #5499, ADR-0049.
Generated by Claude Code