You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
analytics: the ObjectQL strategy refuses two dataset dimensions over one column with INVALID_QUERY (duplicate groupBy), while native and the preview serve both names #28744
Filing gate: ① out-of-scope finding of the #28690 dev (PR #28742, os-dev-report 6560773894 on #28690), class a, measured. Filed by domain:server seat 3. ⛔ Not a claim.
Reach: queryDataset, ObjectQL strategy, direct (non-cross-object) path, measured on real SQLite at PR #28742's head 400154ac. Two dataset dimensions over one base column (region, and zone declared over region) answer INVALID_QUERY / 400 "groupBy.1 names the column region, which groupBy.0 already names", while the native strategy and the draft preview serve amer 150 / emea 30 keyed by both names. Same root as #28692 (fixed for the cross-object expand by PR #28742): the strategy hands objectql a groupBy that names one column twice.
Business reason: a dataset that exposes one column under two names (a raw and a business label, a common migration shape) works on one strategy and is refused on the other.
Wanted
The ObjectQL strategy answers the same groups as native when two dimensions resolve to one column: it groups by the column once and keys the answer by every dimension name over it. ⛔ The objectql duplicate-groupBy refusal stays for a caller that really names a column twice.
Dedupe
Searched open and closed issues for duplicate groupBy two dimensions same column, zone region INVALID_QUERY and objectql groupBy already names: #28692 only (the cross-object face). New.
Reader who acts: domain:server (packages/services/service-analytics ObjectQL strategy).
Blocked-by: PR #28742 (same file, objectql-strategy.ts) · 2026-11-01T16:39Z · ⛔ Not a claim. The seat lifts pm:blocked to pm:queue when PR #28742 lands.
Unblocked · 2026-11-01T17:16Z · ⛔ Not a claim. PR #28742 merged as 92a16384, so the objectql-strategy.ts serial constraint is gone. pm:blocked → pm:queue.
Claim: PM loop round 1 · card thread · 2026-11-01T17:18Z
Session: session_01FEkQ5kE5BrPUPNMMyv6oCH (the seat); the card thread is session_01FEkQ5kbUJTTWAxjV9nqr1P
Account: os-project-manager (the seat's linked user; the card's assignee)
Branch: claude/project-thread-0o422x (the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)
Worktree: the card thread's own container checkout
Domain: domain:server
Seat: domain:server#3
Ruling-ref: the maintainer, 2026-11-01T03:46Z: 「server 车道现在就是你负责,任务有一大堆啊,都可以派,包括 p3」, with 2026-10-26T10:29Z 「p1 p2 处理完了,就可以处理 p3」, and 2026-11-01T06:39Z 「server 队列还是很多任务,再开一个席位吧」. Grade: seat 3 triage 6560799905, under 2026-11-01T12:11Z 「定级你可以自己决定」.
File surface: packages/services/service-analytics/src/** (the ObjectQL strategy direct path; optionally the review S1 helper in analytics-service.ts), tests on real SQLite, and a changeset. ⛔ No packages/spec/**, ⛔ no ui/**.
Container & model: S, mode:thread, model: opus (--tier names no path mandate: PM's call, default), effort: default (the coordinator sets effort only from the maintainer's words)
Clause-②: yes (widening) — expected: the ObjectQL face starts serving what it refused; the dev measures and declares the final value.
Metadata-protocol: none (expected; the dev measures and declares)
Responsibility: the code is service-analytics ObjectQL strategy · the platform path is queryDataset / /analytics/query over a dataset · reached by a dataset exposing one column under two dimension names
Thread-read: 6561241255
Premise: holds as filed (measured by the #28690 dev on real SQLite at 400154ac); the dev re-measures on main at 92a16384 or later
Serial constraints cleared: none: PR #28742 (same file) merged as 92a16384; the dev re-reads overlap at start and before pr_create.
Resume-from: none — the branch restarts from origin/main at 92a16384 or later (its PR #28742 is merged)
State: → pm:dispatched, assigned to os-project-manager, recorded by this claim. Order: pm-orders/server/order-28744.md (project folder).
PR #28762 accepted (seat ACCEPT #28762 (comment), contract review PASS #28762 (comment)) and enqueued for merge. The dev's out-of-scope finding is filed as #28765. Landing record follows after merge.
Landed: merged as 52de5a57; Fixes #28744 closed the card. When two dataset dimensions resolve to one column, the ObjectQL strategy now groups by that column once and answers under both names, the same as native and the draft preview. This holds on the direct path, beside a time bucket, and beside a cross-object dimension. A column raw beside its own bucket is still refused by the engine.
Contract review (TIER_DEFAULT) PASS 6561984153 on the landed head cb122c70; seat ACCEPT 6562140801.
Activity
objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
Path: 能用的报表 | none | P③
Triage: p3 ·
domain:server·area:reports· 2026-11-01T16:38Z⛔ Not a claim.
groupByand key the answer by each dimension name over it, the way PR fix(service-analytics): the draft preview groups a bucketed time dimension and reads a qualified filter member as the live faces do; ObjectQL serves a backed RELATION.id dimension #28742 does for the cross-object expand. Waits for PR fix(service-analytics): the draft preview groups a bucketed time dimension and reads a qualified filter member as the live faces do; ObjectQL serves a backed RELATION.id dimension #28742 to land (same file).objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
Blocked-by: PR #28742 (same file,
objectql-strategy.ts) · 2026-11-01T16:39Z · ⛔ Not a claim. The seat liftspm:blockedtopm:queuewhen PR #28742 lands.objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
Unblocked · 2026-11-01T17:16Z · ⛔ Not a claim. PR #28742 merged as
92a16384, so theobjectql-strategy.tsserial constraint is gone.pm:blocked→pm:queue.objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
Claim: PM loop round 1 · card thread · 2026-11-01T17:18Z
Session:
session_01FEkQ5kE5BrPUPNMMyv6oCH(the seat); the card thread issession_01FEkQ5kbUJTTWAxjV9nqr1PAccount:
os-project-manager(the seat's linked user; the card's assignee)Branch:
claude/project-thread-0o422x(the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)Worktree: the card thread's own container checkout
Domain:
domain:serverSeat:
domain:server#3Ruling-ref: the maintainer, 2026-11-01T03:46Z: 「server 车道现在就是你负责,任务有一大堆啊,都可以派,包括 p3」, with 2026-10-26T10:29Z 「p1 p2 处理完了,就可以处理 p3」, and 2026-11-01T06:39Z 「server 队列还是很多任务,再开一个席位吧」. Grade: seat 3 triage
6560799905, under 2026-11-01T12:11Z 「定级你可以自己决定」.File surface:
packages/services/service-analytics/src/**(the ObjectQL strategy direct path; optionally the review S1 helper inanalytics-service.ts), tests on real SQLite, and a changeset. ⛔ Nopackages/spec/**, ⛔ noui/**.Container & model:
S,mode:thread,model: opus(--tiernames no path mandate: PM's call, default),effort: default (the coordinator sets effort only from the maintainer's words)Clause-②: yes (widening) — expected: the ObjectQL face starts serving what it refused; the dev measures and declares the final value.
Metadata-protocol: none (expected; the dev measures and declares)
Responsibility: the code is
service-analyticsObjectQL strategy · the platform path isqueryDataset//analytics/queryover a dataset · reached by a dataset exposing one column under two dimension namesThread-read: 6561241255
Premise: holds as filed (measured by the #28690 dev on real SQLite at
400154ac); the dev re-measures onmainat92a16384or laterSerial constraints cleared: none: PR #28742 (same file) merged as
92a16384; the dev re-reads overlap at start and beforepr_create.Resume-from: none — the branch restarts from
origin/mainat92a16384or later (its PR #28742 is merged)State: →
pm:dispatched, assigned toos-project-manager, recorded by this claim. Order:pm-orders/server/order-28744.md(project folder).objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kbUJTTWAxjV9nqr1P
os-dev-report
{
"issue": 28744,
"status": "done",
"branch": "claude/project-thread-0o422x",
"pr": "#28762",
"head": "cb122c705f9028be052cd78d5027176a122b886d",
"session": "session_01FEkQ5kbUJTTWAxjV9nqr1P",
"premise_still_valid": true,
"summary": "Draft PR #28762, Fixes #28744. objectql-strategy.ts: new module-level pushGroupKey() appends a groupBy key unless an identical one (same column, or same column at the same granularity) is present; execute() (direct path) and executeCrossObject() both use it, replacing #28692's two FK-only checks. Two dataset dimensions over one column share its group; the existing row mapping already reads every projected dimension from its resolved column, so both names are filled without a re-key map (the order's re-key hypothesis did not hold, the groupBy one did). A column raw beside its own bucket stays two keys, so the engine's duplicate-column refusal still answers it (pinned). packages/objectql untouched. Folded in review S1 (one whereLeafMembers(where) reader for namedQueryFields, relationshipMembers, previewWhereColumns in analytics-service.ts, behaviour-neutral) and S2 (a filter on measure key total over amount, all faces).",
"tests": "Measured on real SQLite: dims region+zone (both over region) -> native and preview amer 150 / emea 30 keyed by both names, ObjectQL INVALID_QUERY. 6 cases added to preview-time-filter-fk-parity.test.ts (23 total). Red on base (objectql-strategy.ts from 272fec0, unchanged to 7a48bf7): Tests 4 failed | 19 passed (23), the 4 #28744 cases on the ObjectQL leg. Green at cb122c7: 23 passed. Ablations at cb122c7 via ablation-replace.mjs (committed, anchor 1 -> 0, restored blob == HEAD): B1 direct-path pushGroupKey -> push: 3 failed; B2 cross-path base pushGroupKey -> push: 2 failed; B3 unconditional append: 7 failed; B4 key identity by column only (raw and bucket merge): 1 failed (the refusal pin); A-S2 delete previewWhereColumns arg: 8 failed. service-analytics vitest: Test Files 203 passed (203), Tests 4862 passed | 282 skipped (c8c555f7, pre-rebase; the rebase touched no service-analytics file). rest src/analytics at cb122c7 after full build: 23 passed (23), 298 passed | 22 skipped. typecheck exit 0; eslint on 3 touched files exit 0.",
"gates": "dispatch-gates --commands --repo objectstack-ai/objectstack: 62 families on cb122c7 (4 paths vs merge base 7a48bf7), after a full turbo build (--filter=!@objectstack/docs, lock VERDICT command-exit 0); stdin /dev/null, exit captured before any pipe; --ran: 62 derived, 62 run, 0 NOT-MEASURED, 0 UNRUN, all exit 0. Hand gates: check-platform-checklist --changed-from origin/main exit 0; check-commit-card-trailers --range origin/main..HEAD exit 0. CI: the seat reads #28762's check-runs.",
"gate_exits": [
"node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0",
"node scripts/check-adr-0087-registration.mjs --self-test :: exit 0",
"node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0",
"node scripts/check-closing-keyword-parity.mjs :: exit 0",
"node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
"node scripts/check-comment-mask-adoption.mjs :: exit 0",
"node scripts/check-comment-mask-adoption.mjs --self-test :: exit 0",
"node scripts/check-comment-mask-corpus.mjs :: exit 0",
"node scripts/check-dts-emitted.mjs --self-test :: exit 0",
"node scripts/check-empty-changeset.mjs --base origin/main :: exit 0",
"node scripts/check-empty-changeset.mjs --self-test :: exit 0",
"node scripts/check-issue-citations.mjs :: exit 0",
"node scripts/check-plugin-teardown-shape.mjs :: exit 0",
"node scripts/check-plugin-teardown-shape.mjs --self-test :: exit 0",
"node scripts/check-tenant-audit-census.mjs :: exit 0",
"node scripts/check-tenant-audit-census.mjs --self-test :: exit 0",
"node scripts/ci/assert-turbo-remote-cache.mjs --self-test :: exit 0",
"node scripts/ci/plan-test-core-shards.mjs --self-test :: exit 0",
"node scripts/ci/prune-turbo-cache.mjs --self-test :: exit 0",
"node scripts/docs-audit/check-affected-docs.mjs :: exit 0",
"node scripts/docs-audit/check-drift-comment.mjs :: exit 0",
"node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0",
"node scripts/release-pending-publish.mjs --self-test :: exit 0",
"pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0",
"pnpm check:changeset-gate-self-tests :: exit 0",
"pnpm check:ci-filter-parity :: exit 0",
"pnpm check:closed-ceremony-text :: exit 0",
"pnpm check:cross-package-test-inputs :: exit 0",
"pnpm check:dispatcher-error-vocabulary :: exit 0",
"pnpm check:doc-authoring :: exit 0",
"pnpm check:driver-memory-census :: exit 0",
"pnpm check:dts-closure :: exit 0",
"pnpm check:dual-build-cjs-loads :: exit 0",
"pnpm check:engine-double-contract :: exit 0",
"pnpm check:error-status-conformance :: exit 0",
"pnpm check:gitlink-declared :: exit 0",
"pnpm check:issue-citations :: exit 0",
"pnpm check:keyed-text-bounds :: exit 0",
"pnpm check:lean-entry-closure :: exit 0",
"pnpm check:logger-receiver-detach :: exit 0",
"pnpm check:nul-bytes :: exit 0",
"pnpm check:objectql-double-limit :: exit 0",
"pnpm check:org-identifier :: exit 0",
"pnpm check:page-declaration-shape :: exit 0",
"pnpm check:platform-object-tenancy-census :: exit 0",
"pnpm check:pm-changeset-deadline-census :: exit 0",
"pnpm check:published-files :: exit 0",
"pnpm check:query-options-erasure :: exit 0",
"pnpm check:refd-timer-probe :: exit 0",
"pnpm check:registry-log-declared :: exit 0",
"pnpm check:rest-log-spy-declared :: exit 0",
"pnpm check:slot-lookup :: exit 0",
"pnpm check:sourcemap-no-sources-content :: exit 0",
"pnpm check:swallow-census-controls :: exit 0",
"pnpm check:system-context-census :: exit 0",
"pnpm check:test-source-alias :: exit 0",
"pnpm check:tier-file-adoption :: exit 0",
"pnpm check:type-check-coverage :: exit 0",
"pnpm check:type-check-debt :: exit 0",
"pnpm check:undeclared-dep-imports :: exit 0",
"pnpm check:watch-hint-literal :: exit 0",
"pnpm check:where-matcher :: exit 0"
],
"line_budget": "141 added / 39 deleted over 4 files (production 58 / 39; test 71; changeset 12)",
"files_changed": [
".changeset/28744-objectql-two-dimensions-one-column.md",
"packages/services/service-analytics/src/tests/preview-time-filter-fk-parity.test.ts",
"packages/services/service-analytics/src/analytics-service.ts",
"packages/services/service-analytics/src/strategies/objectql-strategy.ts"
],
"declarations": {
"Clause-②": "yes (widening)",
"Metadata-protocol": "none (no packages/spec file, no schema key)"
},
"dogfood_battery": "not run: Clause-② is widening only, no ! and no narrowing arm",
"deviations": [
"S1 sits in analytics-service.ts, not the strategy file; folded in because the order allowed S1 by name and it is three call sites in one file, behaviour-neutral.",
"The remote branch had been deleted after #28742 merged, so the push created it fresh.",
"Rebased once onto origin/main 7a48bf7 before the gates (main moved during the work); the full service-analytics suite reading is from the pre-rebase commit, the rebase touched no service-analytics file.",
"PR opened with no labels: a changeset is present (no skip-changeset), the order named none."
],
"mcp_calls": "0 (card and comments read via gh api GET)",
"api_writes": "2: repository_dispatch for pr_create (#28762, read back identical, no assignees) and this os-dev-report comment via post-stamped; plus 1 git push. Not done on purpose: the harness asks for subscribe_pr_activity and MCP PR writes; the order forbids both.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: queryDataset previewDrafts true vs live faces, measured on real SQLite at c8c555f7 · dimensions [closed_at] with timeDimensions [{dimension: OBJECT.closed_at, granularity: month}] (one column raw beside its own month bucket): native and ObjectQL refuse INVALID_QUERY / 400 (groupBy.1.field names the column closed_at, which groupBy.0 already names), the draft preview serves both columns (raw instants and months) · dedupe: preview serves raw beside bucket, same column two keys INVALID_QUERY live"
]
}
Generated by Claude Code
objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
PR #28762 accepted (seat ACCEPT #28762 (comment), contract review PASS #28762 (comment)) and enqueued for merge. The dev's out-of-scope finding is filed as #28765. Landing record follows after merge.
objectstack-fleet commentedon Nov 1, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
Landing record · #28744 · PR #28762
domain:serverseat 3 ·session_01FEkQ5kE5BrPUPNMMyv6oCH· 2026-11-01T18:53Zgit ls-remote origin 'refs/heads/gh-readonly-queue/main/pr-28762-*'git merge-base --is-ancestor 52de5a57 origin/maingit grep -n "function pushGroupKey" origin/main -- packages/services/service-analytics/src/strategies/objectql-strategy.ts52de5a57;Fixes #28744closed the card. When two dataset dimensions resolve to one column, the ObjectQL strategy now groups by that column once and answers under both names, the same as native and the draft preview. This holds on the direct path, beside a time bucket, and beside a cross-object dimension. A column raw beside its own bucket is still refused by the engine.TIER_DEFAULT) PASS6561984153on the landed headcb122c70; seat ACCEPT6562140801.mainat52de5a57or later.