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
@objectstack/lint: export the dataset dimension leg's group-key classifier, so a consumer does not recompose the door's predicates #23235
Filed by the repo:cloud#1 seat (seat post #6026, session session_01WVbr5J6u8BHh8EyFtcWciH) from the cloud dev report objectstack-ai/cloud#2862 6143445321 (out-of-scope finding 3). This is an enhancement, not a defect.
What
packages/lint/src/validate-dataset-measure-aggregates.ts's dimension leg (dimension-json-stored-field-refused, #20890) decides whether a field can be a group key with groupKeyClassOf, which applies the analytics door's two spec predicates in the door's order: STRUCTURED_JSON_TYPES, then isMultiValueField. groupKeyClassOf is not exported.
Why it matters
Cloud's AI build derives dataset dimensions and must only derive group keys the door serves. Without the export, cloud's dataset-derive.tsisDimensionField composes the same two spec predicates in the same order itself. It copies no list, but it is a second account of the door's ordering, so it drifts if the leg ever gains a third predicate. An export would make it one call to the framework's own verdict, which is the "no private re-implementation" stance the lint's other exports already take.
Priority
priority:p3: cloud works today, and it does not block cloud's v18 upgrade (objectstack-ai/cloud#2709).
Triage: first grade confirmed (enhancement · priority:p3), routed domain:spec · area:reports, into pm:queue. One classifier, exported
Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-13T11:03Z. ⛔ Not a claim, ⛔ not a dispatch.
Queue line: a named consumer on a published package (@objectstack/lint, used by cloud's dataset-derive.ts). It is a product surface, not tooling.
Lane:packages/lint is domain:spec by the lane table's exception, and an added export is Clause-②: yes (widening).
Direction:
Export the dimension leg's groupKeyClassOf (or a named wrapper of it) as the one place the analytics door's two predicates are applied in the door's order.
The lint rule keeps calling it.
Pin: the exported classifier and the rule agree on the rule's own fixture set.
Claim: PM loop round 1
Session: session_01D6F9axfoPzR7t8G1J7Ytzz
Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-23235-export-group-key-classifier
Worktree: objectstack-issue-23235
Domain: domain:spec
Seat: domain:spec#3 (seat post #18883)
File surface (at origin/mainf9b421716 or later; stop on a breach and explain it in the report): packages/lint/src/validate-dataset-measure-aggregates.ts (groupKeyClassOf, ~336, and its two call sites), the @objectstack/lint entry that re-exports it (packages/lint/src/index.ts), their tests, the API-surface baselines the gates name, .changeset/23235-*.md.
Container & model: M, mode:subagent, model: default (per dispatch-gates --tier: no path-derived mandate; floor · default · ceiling); Clause-② yes ⇒ CONTRACT_REVIEW_TIER review before the queue
Clause-②: yes
Responsibility: n/a — not a defect card
Thread-read: 6144128621
Serial constraints cleared: no open PR touches packages/lint/src/validate-dataset-measure-aggregates.ts or packages/lint/src/index.ts (read at this act). The sibling export on the spec side (#23272, PR #23496) has merged as 5547ad451.
Read on origin/mainf9b421716 at 2026-10-14T15:24Z: groupKeyClassOf is module-private at validate-dataset-measure-aggregates.ts:336, called at ~500 and ~598.
{
"issue": 23235,
"status": "done",
"branch": "claude/issue-23235-export-group-key-classifier",
"pr": "https://github.com/objectstack-ai/objectstack/pull/23520",
"session": "session_01D6F9axfoPzR7t8G1J7Ytzz",
"premise_still_valid": true,
"summary": "@objectstack/lint now exports groupKeyClassOf(shape: ValueShapeFieldDef): GroupKeyClass | null, plus the named type GroupKeyClass ('structured-json' | 'multi-value'), from the package barrel. It is the same function both legs of dimension-json-stored-field-refused (dataset and cube) call: no wrapper, no copy. The input was not widened. ValueShapeFieldDef is already public in @objectstack/spec/data, a spec Field passes as it is (pinned at compile time), and the analytics door's own private groupedClassOf takes that same type. A new describe block pins the export (imported through ./index.js) equal to the rule's verdict and class on the rule's own fixtures: every FieldType with and without multiple:true with exact floors, the named dimension fixtures, and every column of the cube fixture. No existing rule assertion changed. Changeset: @objectstack/lint minor, Clause-②: yes.",
"tests": "Final head dfe60e348 (origin/main merged at 6c8367ebb, merge base 1418de4c7). pnpm --filter '@objectstack/lint^...' build: exit 0. pnpm --filter @objectstack/lint build: exit 0, check-dts-emitted 6/6. dist/index.d.ts declares groupKeyClassOf and GroupKeyClass; the CJS dist/index.cjs and the ESM entry both load and answer multi-value / structured-json / null. Lint suite (pnpm --filter @objectstack/lint exec vitest run --maxWorkers=2): 139 files / 6731 tests passed. The touched file at the final head: 65/65. pnpm --filter @objectstack/lint typecheck: exit 0 (check:test-typecheck OK for tsconfig.test.json). pnpm --filter @objectstack/spec run test:repo, after the spec rebuild: 60 files / 1029 tests passed. dispatch-gates --ran: 62 derived, 60 run at exit 0, 2 NOT MEASURED (check:dual-build-cjs-loads and check:lean-entry-closure exit 3, PREREQUISITE NOT MET: they need a whole-workspace dist). Also run, all exit 0: check:published-readme-exports, check-changeset-fixed, check:error-code-casing. check:where-matcher failed on the first draft of the pin's helper (control probe threw: its structural discovery seated the helper as a WHERE matcher). I rewrote the helper and the gate went green; the test-reading gates were re-run on dfe60e348. Ablation on dfe60e348 via scripts/ablation-replace.mjs under the lock, each with anchor 1->0 and a restore with blob == HEAD 3fc39652c3ac and git diff HEAD empty: dataset-leg call site replaced by a STRUCTURED_JSON_TYPES-only check gave 4 failed / 61 passed (two of them the new pins). The cube-leg call site, replaced the same way, gave 3 failed / 62 passed (one of them the new cube pin). Direction: red, as expected. The suite imports src through relative paths, so no dist rebuild leg applies.",
"mcp_calls": "0",
"api_writes": "3 — git push of the branch (not REST); fleet-write relay pr_create (POST /repos/objectstack-ai/objectstack/pulls, draft, plus POST /repos/objectstack-ai/objectstack/issues/23520/assignees [baozhoutao]); fleet-write relay issue_comment os-dev-report (POST /repos/objectstack-ai/objectstack/issues/23235/comments). Labels: zero writes (the dispatch names no label, and the PR carries a changeset, so skip-changeset does not apply). The PR has size/m from the size labeler.",
"gates": "dispatch-gates --ran on dfe60e348: 62 derived / 60 run, all exit 0 / 2 NOT MEASURED (check:dual-build-cjs-loads, check:lean-entry-closure: exit 3, prerequisite whole-workspace dist; declared to CI) / 0 UNRUN",
"line_budget": "n/a — no governed or skills surface touched; diff +141/-3 over 4 files",
"deviations": "none",
"files_changed": [
".changeset/23235-export-group-key-classifier.md",
"packages/lint/src/index.ts",
"packages/lint/src/validate-dataset-measure-aggregates.ts",
"packages/lint/src/validate-dataset-measure-aggregates.test.ts"
],
"open_questions": [],
"out_of_scope_findings": [
"carrier: none (承接者:无) · noted, not filed. service-analytics/src/structured-json-dimension-door.ts keeps its own private groupedClassOf, composing the same two predicates in the same order with the same input type. That is a second account of the door's order inside the door itself. It agrees today, and nothing but each side's sweep against STRUCTURED_JSON_TYPES / isMultiValueField holds the two equal. service-analytics does not depend on @objectstack/lint, so one copy shared by both would have to live in @objectstack/spec/data. That is a separate decision. In Acceptance notes."
]
}
Session session_01D6F9axfoPzR7t8G1J7Ytzz · baozhoutao. Reviewer of record; checked against GitHub, not the report.
Shape: draft, Fixes #23235, Clause-②: yes; +141/−3, 4 files; not governed. The contract-tier review is on the PR: PASS on this head.
The ask:@objectstack/lint exports groupKeyClassOf(shape: ValueShapeFieldDef): GroupKeyClass | null and the GroupKeyClass union from its barrel; the lint rule keeps calling the same function, and a pin asserts agreement on fixtures.
Changeset:23235-export-group-key-classifier.md, @objectstack/lintminor: two additive exports, nothing removed.
Out of scope, no card:service-analytics keeps a private groupedClassOf with the same body; a shared copy would need a home in @objectstack/spec/data. Cloud's switch from isDimensionField is cloud's card.
CI on the head: in progress at this act; the seat lands on green.
Session session_01D6F9axfoPzR7t8G1J7Ytzz · baozhoutao. Merged through the merge queue; the squash equals the contract-reviewed head dfe60e348 (PASS) by git patch-id --stable; on origin/main. The card closed completed on Fixes #23235; pm:dispatched is removed in this act. @objectstack/lint now exports groupKeyClassOf and GroupKeyClass; they ship with the next next.N cut. Cloud's switch from dataset-derive.tsisDimensionField is cloud's card. service-analytics' private groupedClassOf stays, noted in the acceptance; no card.
Activity
objectstack-fleet commentedon Oct 13, 2026
Triage: first grade confirmed (
enhancement·priority:p3), routeddomain:spec·area:reports, intopm:queue. One classifier, exportedTriage seat (objectstack-wide, seat post #6015) ·
session_01AavokzJ5DndAwitDXvKy4U· 2026-10-13T11:03Z. ⛔ Not a claim, ⛔ not a dispatch.@objectstack/lint, used by cloud'sdataset-derive.ts). It is a product surface, not tooling.packages/lintisdomain:specby the lane table's exception, and an added export isClause-②: yes (widening).groupKeyClassOf(or a named wrapper of it) as the one place the analytics door's two predicates are applied in the door's order.objectstack-fleet commentedon Oct 14, 2026
Claim: PM loop round 1
Session:
session_01D6F9axfoPzR7t8G1J7YtzzAccount:
baozhoutao(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-23235-export-group-key-classifierWorktree:
objectstack-issue-23235Domain:
domain:specSeat:
domain:spec#3(seat post #18883)File surface (at
origin/mainf9b421716or later; stop on a breach and explain it in the report):packages/lint/src/validate-dataset-measure-aggregates.ts(groupKeyClassOf, ~336, and its two call sites), the@objectstack/lintentry that re-exports it (packages/lint/src/index.ts), their tests, the API-surface baselines the gates name,.changeset/23235-*.md.Container & model:
M,mode:subagent,model: default (per dispatch-gates --tier: no path-derived mandate; floor · default · ceiling); Clause-② yes ⇒ CONTRACT_REVIEW_TIER review before the queueClause-②: yes
Responsibility:
n/a — not a defect cardThread-read: 6144128621
Serial constraints cleared: no open PR touches
packages/lint/src/validate-dataset-measure-aggregates.tsorpackages/lint/src/index.ts(read at this act). The sibling export on the spec side (#23272, PR #23496) has merged as5547ad451.Read on
origin/mainf9b421716at 2026-10-14T15:24Z:groupKeyClassOfis module-private atvalidate-dataset-measure-aggregates.ts:336, called at ~500 and ~598.Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
os-dev-report
{ "issue": 23235, "status": "done", "branch": "claude/issue-23235-export-group-key-classifier", "pr": "https://github.com/objectstack-ai/objectstack/pull/23520", "session": "session_01D6F9axfoPzR7t8G1J7Ytzz", "premise_still_valid": true, "summary": "@objectstack/lint now exports groupKeyClassOf(shape: ValueShapeFieldDef): GroupKeyClass | null, plus the named type GroupKeyClass ('structured-json' | 'multi-value'), from the package barrel. It is the same function both legs of dimension-json-stored-field-refused (dataset and cube) call: no wrapper, no copy. The input was not widened. ValueShapeFieldDef is already public in @objectstack/spec/data, a spec Field passes as it is (pinned at compile time), and the analytics door's own private groupedClassOf takes that same type. A new describe block pins the export (imported through ./index.js) equal to the rule's verdict and class on the rule's own fixtures: every FieldType with and without multiple:true with exact floors, the named dimension fixtures, and every column of the cube fixture. No existing rule assertion changed. Changeset: @objectstack/lint minor, Clause-②: yes.", "tests": "Final head dfe60e348 (origin/main merged at 6c8367ebb, merge base 1418de4c7). pnpm --filter '@objectstack/lint^...' build: exit 0. pnpm --filter @objectstack/lint build: exit 0, check-dts-emitted 6/6. dist/index.d.ts declares groupKeyClassOf and GroupKeyClass; the CJS dist/index.cjs and the ESM entry both load and answer multi-value / structured-json / null. Lint suite (pnpm --filter @objectstack/lint exec vitest run --maxWorkers=2): 139 files / 6731 tests passed. The touched file at the final head: 65/65. pnpm --filter @objectstack/lint typecheck: exit 0 (check:test-typecheck OK for tsconfig.test.json). pnpm --filter @objectstack/spec run test:repo, after the spec rebuild: 60 files / 1029 tests passed. dispatch-gates --ran: 62 derived, 60 run at exit 0, 2 NOT MEASURED (check:dual-build-cjs-loads and check:lean-entry-closure exit 3, PREREQUISITE NOT MET: they need a whole-workspace dist). Also run, all exit 0: check:published-readme-exports, check-changeset-fixed, check:error-code-casing. check:where-matcher failed on the first draft of the pin's helper (control probe threw: its structural discovery seated the helper as a WHERE matcher). I rewrote the helper and the gate went green; the test-reading gates were re-run on dfe60e348. Ablation on dfe60e348 via scripts/ablation-replace.mjs under the lock, each with anchor 1->0 and a restore with blob == HEAD 3fc39652c3ac and git diff HEAD empty: dataset-leg call site replaced by a STRUCTURED_JSON_TYPES-only check gave 4 failed / 61 passed (two of them the new pins). The cube-leg call site, replaced the same way, gave 3 failed / 62 passed (one of them the new cube pin). Direction: red, as expected. The suite imports src through relative paths, so no dist rebuild leg applies.", "mcp_calls": "0", "api_writes": "3 — git push of the branch (not REST); fleet-write relay pr_create (POST /repos/objectstack-ai/objectstack/pulls, draft, plus POST /repos/objectstack-ai/objectstack/issues/23520/assignees [baozhoutao]); fleet-write relay issue_comment os-dev-report (POST /repos/objectstack-ai/objectstack/issues/23235/comments). Labels: zero writes (the dispatch names no label, and the PR carries a changeset, so skip-changeset does not apply). The PR has size/m from the size labeler.", "gates": "dispatch-gates --ran on dfe60e348: 62 derived / 60 run, all exit 0 / 2 NOT MEASURED (check:dual-build-cjs-loads, check:lean-entry-closure: exit 3, prerequisite whole-workspace dist; declared to CI) / 0 UNRUN", "line_budget": "n/a — no governed or skills surface touched; diff +141/-3 over 4 files", "deviations": "none", "files_changed": [ ".changeset/23235-export-group-key-classifier.md", "packages/lint/src/index.ts", "packages/lint/src/validate-dataset-measure-aggregates.ts", "packages/lint/src/validate-dataset-measure-aggregates.test.ts" ], "open_questions": [], "out_of_scope_findings": [ "carrier: none (承接者:无) · noted, not filed. service-analytics/src/structured-json-dimension-door.ts keeps its own private groupedClassOf, composing the same two predicates in the same order with the same input type. That is a second account of the door's order inside the door itself. It agrees today, and nothing but each side's sweep against STRUCTURED_JSON_TYPES / isMultiValueField holds the two equal. service-analytics does not depend on @objectstack/lint, so one copy shared by both would have to live in @objectstack/spec/data. That is a separate decision. In Acceptance notes." ] }Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
Review: ACCEPT · PR #23520 @
dfe60e3486ef23d1c3da427d1964eb9adfd80158·domain:specseat 3 · 2026-10-14T16:49ZSession
session_01D6F9axfoPzR7t8G1J7Ytzz·baozhoutao. Reviewer of record; checked against GitHub, not the report.Fixes #23235,Clause-②: yes; +141/−3, 4 files; not governed. The contract-tier review is on the PR: PASS on this head.@objectstack/lintexportsgroupKeyClassOf(shape: ValueShapeFieldDef): GroupKeyClass | nulland theGroupKeyClassunion from its barrel; the lint rule keeps calling the same function, and a pin asserts agreement on fixtures.23235-export-group-key-classifier.md,@objectstack/lintminor: two additive exports, nothing removed.service-analyticskeeps a privategroupedClassOfwith the same body; a shared copy would need a home in@objectstack/spec/data. Cloud's switch fromisDimensionFieldis cloud's card.Generated by Claude Code
objectstack-fleet commentedon Oct 14, 2026
Landed · PR #23520 →
main54af6c0e9·domain:specseat 3 · 2026-10-14T17:41ZSession
session_01D6F9axfoPzR7t8G1J7Ytzz·baozhoutao. Merged through the merge queue; the squash equals the contract-reviewed headdfe60e348(PASS) bygit patch-id --stable; onorigin/main. The card closedcompletedonFixes #23235;pm:dispatchedis removed in this act.@objectstack/lintnow exportsgroupKeyClassOfandGroupKeyClass; they ship with the nextnext.Ncut. Cloud's switch fromdataset-derive.tsisDimensionFieldis cloud's card.service-analytics' privategroupedClassOfstays, noted in the acceptance; no card.Generated by Claude Code