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 draft preview serves a time bucket over a text column as one null bucket, where the live faces refuse INVALID_FIELD #28852
Filing gate: ① out-of-scope finding of the #28798 dev (PR #28851, os-dev-report 6566411471). The dev observed it while measuring the precedence question. The seat has not re-measured it. Filed by domain:server seat 3. ⛔ Not a claim.
Reach: a dataset selection with a timeDimensions entry that asks a granularity of a member over a text column (for example zone by month, where zone reads the text column region) gets two different answers:
The live faces refuse it. The engine's temporal-bucket door (packages/objectql/src/aggregate-query-shape-door.ts) answers INVALID_FIELD / 400 at groupBy.N.dateGranularity.
The draft preview (previewDrafts: true) serves it as one null bucket.
So an author sees a chart in the draft that the published dataset refuses. This is the same family as #28765 and #28555: a preview gate the live faces have and the preview lacks.
Wanted
Measure the three faces on real SQLite, for text, select, number and boolean columns.
If the preview serves where live refuses, the preview refuses the same way, field for field, with the same code, status, path and message. Do it in the existing preview gate list in analytics-service.ts. Reuse the engine's field-type reading or an existing service-analytics reading of it rather than a third copy. ⛔ No new gate on the live faces.
This narrows the preview: a selection the preview serves today is refused. So it is Clause-②: no (narrowing), with a CONTRACT_REVIEW_TIER review owed.
Dedupe
Read open issues for preview text column bucket, preview dateGranularity text and preview null bucket: only #28798 (PR #28851, same files). New.
Reader who acts: domain:server (packages/services/service-analytics).
Ruling-ref: the maintainer, 2026-11-01T12:11Z: 「定级你可以自己决定」.
Class (a), observed by a dev and not yet measured on all faces. The draft shows a chart that publish then refuses. A loud refusal follows, so no data is lost: p3.
Claim: PM loop round 1 · card thread · 2026-11-02T04:07Z
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 队列还是很多任务,再开一个席位吧」. Seat 3 graded p3 under 「定级你可以自己决定」 (2026-11-01T12:11Z).
File surface: packages/services/service-analytics/src/analytics-service.ts, packages/services/service-analytics/src/strategies/objectql-strategy.ts (echo precedence ride-along), new test under packages/services/service-analytics/src/__tests__/, a changeset; census/test-input registration if the gates ask
Container & model: card thread cmsg_01TenzsRopZj4jMbvjX8uz1XB1hsVtuncZ5F5C4zpiftHC (analytics, same thread as #28841), mode:thread, model: opus (--tier names no path mandate: PM's call, default), effort: high
Clause-②: no (narrowing) — a draft preview that serves today is refused; CONTRACT_REVIEW_TIER review owed
Metadata-protocol: none (expected; the dev measures and declares)
Responsibility: domain:server seat 3 owns the PR to merge
Thread-read: 6566450228
Premise: the #28798 dev observed the null bucket (os-dev-report 6566411471); not re-measured by the seat; measure-first in the order
Serial constraints cleared: PR #28851 and PR #28878 (same files) both merged
Resume-from: none — the branch restarts from origin/main at 97680bbb or later (its PR #28878 is merged)
State: → pm:dispatched, assigned to os-project-manager, recorded by this claim. Order: pm-orders/server/order-28852.md (project folder).
import at line 120, preview gate call at line 2910
Landed: merged as 5d7cfe6a. The draft preview now refuses a time bucket over a text, select, number or boolean column with the live faces' INVALID_FIELD / 400 at groupBy.N.dateGranularity, field for field. The /analytics/sql echo reads dateRange before the dataset door, so its refusal precedence matches query().
Contract review (CONTRACT_REVIEW_TIER): PASS 6569944800 on the landed head 80559b2c. Seat ACCEPT 6569961633.
Activity
objectstack-fleet commentedon Nov 2, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
Path: 能用的报表 | none | P③
Triage: p3 ·
domain:server·area:reports· 2026-11-02T00:50Z⛔ Not a claim.
Clause-②: no (narrowing), with aCONTRACT_REVIEW_TIERreview owed.objectstack-fleet commentedon Nov 2, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
Claim: PM loop round 1 · card thread · 2026-11-02T04:07Z
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 队列还是很多任务,再开一个席位吧」. Seat 3 graded p3 under 「定级你可以自己决定」 (2026-11-01T12:11Z).
File surface:
packages/services/service-analytics/src/analytics-service.ts,packages/services/service-analytics/src/strategies/objectql-strategy.ts(echo precedence ride-along), new test underpackages/services/service-analytics/src/__tests__/, a changeset; census/test-input registration if the gates askContainer & model: card thread
cmsg_01TenzsRopZj4jMbvjX8uz1XB1hsVtuncZ5F5C4zpiftHC(analytics, same thread as #28841),mode:thread,model: opus(--tiernames no path mandate: PM's call, default),effort: highClause-②: no (narrowing) — a draft preview that serves today is refused;
CONTRACT_REVIEW_TIERreview owedMetadata-protocol: none (expected; the dev measures and declares)
Responsibility:
domain:serverseat 3 owns the PR to mergeThread-read: 6566450228
Premise: the #28798 dev observed the null bucket (os-dev-report
6566411471); not re-measured by the seat; measure-first in the orderSerial constraints cleared: PR #28851 and PR #28878 (same files) both merged
Resume-from: none — the branch restarts from
origin/mainat97680bbbor later (its PR #28878 is merged)State: →
pm:dispatched, assigned toos-project-manager, recorded by this claim. Order:pm-orders/server/order-28852.md(project folder).objectstack-fleet commentedon Nov 2, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kbUJTTWAxjV9nqr1P
os-dev-report
{
"issue": 28852,
"status": "done",
"branch": "claude/project-thread-0o422x",
"pr": "#28976",
"head": "80559b2cabf41f12e05b97b6b67254eb15774fa5",
"session": "session_01FEkQ5kbUJTTWAxjV9nqr1P",
"premise_still_valid": true,
"summary": "Draft PR #28976, Fixes #28852. Measured first on main 9a9823d (real SQLite): native and ObjectQL refuse a month/year bucket over text, select, number and boolean columns with the engine's INVALID_FIELD/400 at groupBy.N.dateGranularity; the draft preview served one null group (1970 for the number); the /analytics/sql echo renders strftime over the column (out of scope, reported). New preview-date-bucket-door.ts assertPreviewDateBucketsTemporal judges aggregateGroupKeys with the engine's reading (declared type via sourceFieldMeta, classed by spec CALENDAR_DATE_TYPES/INSTANT_TYPES; no type or formula not judged) and throws the engine's refusal field for field; called last in the existing preview gate list, after the column-asked-twice door, as on the live faces. No live-face gate, no packages/objectql change, second copy of the sentence (engine + preview) pinned against both live faces. Ride-along: generateSql reads dateRangeBounds before the dataset door, so dup + bad dateRange answers ANALYTICS_DATE_RANGE_UNRECOGNIZED on query and echo alike.",
"tests": "New preview-date-bucket-type.test.ts (7) + 2 cases in objectql-echo-column-twice.test.ts. Red on base (analytics-service.ts, objectql-strategy.ts from 9a9823d): 7 failed | 15 passed (22). Green: 7 + 15 passed. Ablations (ablation-replace.mjs, committed, anchor 1 -> 0, restored blob == HEAD; both files + preview-time-filter-fk-parity, 59 cases): C1 preview call no-op -> 5 failed; C2 datetime exemption dropped -> 10 failed; C3 formula skip dropped -> 59 passed (no formula fixture; arm mirrors the engine's classOfDeclaredType, unpinned, stated); C4 echo windows read after the door -> 2 failed. service-analytics vitest: 205 files, 4898 passed | 282 skipped. client: 54 files, 693 passed (census 21 passed). rest src/analytics: 298 passed | 22 skipped. tsc --noEmit exit 0; scoped eslint exit 0.",
"gates": "dispatch-gates --commands --repo objectstack-ai/objectstack: 63 families on 80559b2 (7 paths vs merge base 9a9823d) after a full turbo build (117 tasks, lock VERDICT command-exit 0); stdin /dev/null, exit captured before any pipe; 62 unlocked in a loop, check:type-check-debt under os-verify-lock; --ran: 63 derived, 63 run, 0 NOT-MEASURED, 0 UNRUN, all exit 0. Hand gates: check-platform-checklist exit 0; check-commit-card-trailers --range origin/main..HEAD exit 0. CI: the seat reads #28976'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 --filter @objectstack/spec run check:skill-examples :: 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:undeclared-dep-imports :: exit 0",
"pnpm check:watch-hint-literal :: exit 0",
"pnpm check:where-matcher :: exit 0",
"pnpm check:type-check-debt :: exit 0"
],
"dogfood_battery": "80559b2c · os-verify-lock VERDICT command-exit 0 · Test Files 382 passed | 3 skipped (385) · Tests 3156 passed | 28 skipped (3184) · no failure",
"line_budget": "316 added / 11 deleted over 7 files (production 90 / 5; test 205 / 6; changeset 21)",
"files_changed": [
".changeset/28852-preview-refuses-date-bucket-over-non-date.md",
"packages/client/src/envelope-caller-census.test.ts",
"packages/services/service-analytics/src/tests/objectql-echo-column-twice.test.ts",
"packages/services/service-analytics/src/tests/preview-date-bucket-type.test.ts",
"packages/services/service-analytics/src/analytics-service.ts",
"packages/services/service-analytics/src/preview-date-bucket-door.ts",
"packages/services/service-analytics/src/strategies/objectql-strategy.ts"
],
"declarations": {
"Clause-②": "no (narrowing)",
"Metadata-protocol": "none (no packages/spec file, no schema key)",
"changeset": "service-analytics patch, fix(...)!, BREAKING paragraph, adr-0087 not-required marker"
},
"deviations": [
"New module preview-date-bucket-door.ts (the refusal) beside the one-line call in the analytics-service.ts preview gate list, as dataset-group-column-door.ts sits; the claim names analytics-service.ts.",
"packages/client/src/envelope-caller-census.test.ts moved 14 -> 15 for the precedence pin's analytics.query call (census registration the claim allows "if the gates ask"); no cross-package-test-inputs change needed (file already declared).",
"C3 (formula skip) ablation stays green: unpinned arm, mirrors the engine.",
"Squashed and rebased onto origin/main 9a9823d before the gates; origin/main moved 8 commits before the push, none touching the 7 paths (merge-tree clean).",
"The remote branch had been deleted after #28878 merged, so the push created it fresh. PR opened with no labels (changeset present)."
],
"mcp_calls": "0 (card, claim and PR read via gh api GET)",
"api_writes": "2: repository_dispatch for pr_create (#28976, read back identical, no assignees, draft) and this os-dev-report comment via post-stamped; plus 1 git push. Not done on purpose: subscribe_pr_activity and MCP writes, which the order forbids.",
"open_questions": [],
"out_of_scope_findings": [
"class: a · reach: /analytics/sql (AnalyticsService.generateSql -> ObjectQLStrategy.generateSql), measured on 9a9823d real SQLite · a timeDimensions granularity over a text/select/number/boolean column renders SELECT strftime('%Y-%m',
region) ... GROUP BY strftime(...) where /analytics/query refuses INVALID_FIELD / 400 at groupBy.0.dateGranularity (engine assertDateBucketTargetsAreTemporal); same family as #28841 · dedupe: sql echo date bucket non-date column, generateSql strftime text column"]
}
Generated by Claude Code
objectstack-fleet commentedon Nov 2, 2026
domain:server#3 · os-project-manager · session_01FEkQ5kE5BrPUPNMMyv6oCH
Landing record · #28852 · PR #28976
domain:serverseat 3 ·session_01FEkQ5kE5BrPUPNMMyv6oCH· 2026-11-02T06:04Zgit ls-remote origin 'refs/heads/gh-readonly-queue/main/pr-28976-*'git merge-base --is-ancestor 5d7cfe6a5e origin/maingit grep -n "assertPreviewDateBucketsTemporal" origin/main -- packages/services/service-analytics/src/analytics-service.ts5d7cfe6a. The draft preview now refuses a time bucket over a text, select, number or boolean column with the live faces'INVALID_FIELD/ 400 atgroupBy.N.dateGranularity, field for field. The/analytics/sqlecho readsdateRangebefore the dataset door, so its refusal precedence matchesquery().CONTRACT_REVIEW_TIER): PASS6569944800on the landed head80559b2c. Seat ACCEPT6569961633.Fixes #28852closed this card on merge.dateRangeprecedence; three unpinned preview arms).