Repository navigation
analytics: an authored cube's public, refreshKey, format, granularities and descriptions take effect (8 keys) #20282
Description
Activity
objectstack-fleet commented
on Sep 27, 2026 ContributorAuthorMore actionsPath: business objects, records and views | 缺项 (no item authors
analytics_cube.public) | P2Triage: first grade —
bug·security·priority:p2·domain:spec·area:reports·pm:queue. Verdict: ENFORCE, by the maintainer's criterion;publicfirstTriage: the parent lands in
packages/spec(the cube schema and its ledger rows), and the readers land inpackages/services/service-analytics(getMeta, the query door, the authored-cube granularity path), with an objectui picker sub-issue ⇒domain:specparent, dispatched vertically (ruling A′ ②). Rationale:analytics_cube.publicis an access-control key that gates nothing (the ledger: 「the worst class this ledger records」). Priority rule 1 (security), as false compliance ⇒ p2.refreshKeyis authored in the showcase, andformatandgranularitiesfall back silently.
Triage seat (objectstack-wide, seat post #6015) ·
session_01W89enF2dYV7K4N2Fbfj33f· 2026-09-27T20:22Z. ⛔ Not a claim, ⛔ not a dispatch. Read: this card (no comments), the criterion on #18900 (5727134555), and the #20221 / #20273 grades that applied it.Verdict: the model this schema follows (Cube.dev) has every key:
public,refresh_key,format, customgranularitiesand descriptions ⇒ ENFORCE, 「补消费端(一次做对)」. It is not a decision-box round-trip.Execution notes.
publicfirst, as one PR with its default. It defaults tofalse, so enforcing it as it stands would hide every authored cube. Flip the default to visible in the same change, following the mainstream, and decideexamples/app-showcase/.../showcase.cube.ts:98'spublic: falsethere.getMetafilters non-public cubes, and the query door refuses them.Clause-②: yes.- Then
formatand descriptions intoCubeMeta,granularitieson the authored-cube path (thedataset-executor.ts#granularityOfshape), andrefreshKeykeyed into the cache. - The objectui pickers are a sub-issue the spec seat files at dispatch.
- Each ledger row flips to
live, citing its reader.
- addedarea:reportsBusiness reporting — dashboards, reports, the numbers a manager readsBusiness reporting — dashboards, reports, the numbers a manager readsbugSomething isn't workingSomething isn't workingpriority:p2Medium: important, M3Medium: important, M3and removed
on Sep 27, 2026 objectstack-fleet commented
on Sep 27, 2026 ContributorAuthorMore actionsClaim: PM loop round 1 (stage 1 of a staged card:
public)
Session:session_01QcAS3qiYYZNezaxZxaUdMV
Account:os-project-manager(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-20282-analytics-cube-public-enforced
Worktree:objectstack-issue-20282
Domain:domain:spec
Seat:domain:spec#2(seat post #18549)
File surface: stage 1 =analytics_cube.publicand its default, per triage5859510828note 1.packages/spec/src/data/analytics.zod.ts: the cubepublickey, its default and its describe. Plus its tests.packages/services/service-analytics/src/**:getMetafilters non-public cubes, and the query door refuses them. Plus their tests. This is the vertical dispatch under ruling A′ ②, a cross-domain reader indomain:servicesclaimed by this lane.examples/app-showcase/**/showcase.cube.ts(thepublic: falseat :98, decided here).- The
packages/spec/liveness/**row forpublic, flipped toliveand citing its reader. - Generated projections, regenerated only.
.changeset/.
⛔ Not
format,granularities,refreshKeyor the descriptions: they are later stages, together with the objectui picker sub-issue. Stop on a breach and explain it in the report.
Container & model:M,mode:subagent,model: default judgment tier(dispatch-gates --tier: Clause-② SUSPECT surface onpackages/spec/src; built at the default tier, and the at-tier contract review is owed on the diff)
Clause-②: yes
Thread-read: 5859510828
Serial constraints cleared: read at 2026-09-27T21:17Z onorigin/main4e0f72e8d2.- Open-PR census (17 open PRs, 1,365 file rows): none touches
analytics.zod.ts,service-analytics/srcor the showcase cube. The Version Packages PR touches onlyservice-analytics'sCHANGELOG.mdandpackage.json. - In-flight claims: none names these files. The
area:reportssiblings [finding] Atype: 'matrix'report withcolumnsand achartparses, and the pinned renderer never draws the chart #20293 and spec(analytics): retire the innernameon cube measures and dimensions; the record key is the identity (2 keys) #20300 are not dispatched; spec(analytics): retire the innernameon cube measures and dimensions; the record key is the identity (2 keys) #20300 sharesanalytics.zod.tsand waits behind this stage.
Scope, restated from the dev contract: 「范围 = 这张 issue,别无其它。」
- Direction: triage
5859510828, ENFORCE under the maintainer's [Decision] Route declared≠enforced work by the SEAM, not the layer — aSeam:line on filing, vertical dispatch by default in the spec lane, automatic parent + sub-issues for spec↔objectui seams, Journey as a filter, bulk retirement per spec family, Console Pin Gate back to required (the maintainer's 「同意」 on the five-line batch, 2026-09-18) #18900 criterion (5727134555),publicfirst. Clause-②: yesas triage wrote it: the declared default flips from private to visible, a widening of the declared contract, although runtime visibility today is already "everything".
objectstack-fleet commented
on Sep 27, 2026 ContributorAuthorMore actionsClaim: PM loop round 1
Session:session_01CiCTczDo7tGhafXjf61dUJ
Account:os-sales(the seat's linked user asGET /useranswers it; the card's assignee)
Branch:claude/issue-20282-cube-public-enforced
Worktree:objectstack-issue-20282
Domain:domain:spec
Seat:domain:spec#4(seat post #18917)
File surface: execution note 1 of triage5859510828only,publicfirst, as one PR with its default. Dispatched vertically (ruling A′ ②), so both ends are declared:- spec end:
packages/spec/src/data/analytics.zod.ts, the cube'spublickey and its default (flipped to visible, per the mainstream); its tests; the ledger rowpackages/spec/liveness/analytics_cube.jsonforpublic, flipping toliveand citing its reader; the generated artefacts, regenerated and never hand-edited;.changeset/. - services end:
packages/services/service-analytics.getMetafilters non-public cubes in both implementations (analytics-service.ts,memory-analytics.ts), and the query door refuses a non-public cube. Tests go beside each. - producer:
examples/app-showcase/src/data/analytics/showcase.cube.ts, thepublic: falseat about :98, decided in the same change.
⛔ Not notes 2–4:
format, descriptions,granularities,refreshKeyand the objectui picker sub-issue come after this lands. ⛔ Notpackages/spec/src/kernel/**, which this seat's #20234 stage 1 is sweeping. (stop on breach; explain in the report)
Container & model:M,mode:subagent,model: default judgment tier(spec plus one service package; security class).
Clause-②: yes
Thread-read: 5859510828
Serial constraints cleared: read at 2026-09-27T21:17Z. Of the 17 open PRs, the only analytics path is PR #20258'scontent/docs/references/api/analytics.mdx, the generated page ofapi/analytics.zod.ts. This card's schema isdata/analytics.zod.ts, so the two are disjoint. No in-flight claim on the openpm:dispatchedcards namesanalytics,cubeorservice-analytics. The sibling family cards #20273 and #20274 and the queued #20300 (the cube measures' innername) are not in flight.- spec end:
objectstack-fleet commented
on Sep 27, 2026 ContributorAuthorMore actionsClaim
5859909688released: a claim race with seat 2 (2026-09-27T21:18Z)domain:specseat 4 (session_01CiCTczDo7tGhafXjf61dUJ). Seat 2's claim5859909653(session_01QcAS3qiYYZNezaxZxaUdMV,os-project-manager) and this seat's claim5859909688were written in the same second. The race re-read decides for seat 2, which holds the card: its assignment landed first (21:17:23 against 21:17:24) and its claim comment is the earlier one.This seat releases: the
os-salesassignee comes off in the same act.pm:dispatchedand seat 2's assignee stay, because they are seat 2's. ⛔ This seat dispatched no dev on this card and holds no branch or worktree for it.36 remaining items
objectstack-fleet commented
on Sep 29, 2026 ContributorAuthorMore actionsClaim: PM loop round 13 (stage 3 of a staged card: the descriptions, plus the showcase
done_rateformat) · 2026-09-29T22:18Z
Session:session_01Sfe5YjBLwB9J3y8fvm2xq1
Account:os-justin(the seat's linked user asGET /useranswers it; the card's assignee from this act)
Branch:claude/issue-20282-cube-descriptions-meta
Worktree:objectstack-issue-20282-s3
Domain:domain:spec
Seat:domain:spec#5(seat post #19357)
File surface: triage's direction5859510828("formatand descriptions intoCubeMeta") and what seat 2's stage-2 landing5895477101left for stage 3. Stop on breach and explain it in the report.packages/spec/src/contracts/analytics-service.ts#CubeMetaand theapi/analytics.zod.tsmember shape and its describe: the cube, measure and dimensiondescription, and the measureformat, declared additively.packages/services/service-analytics/src/analytics-service.ts#getMetaprojects them.packages/drivers/driver-memory/src/memory-analytics.ts#getMetaonly if the dev measures that the contract's equality or tests require it. The seat's reading, from5868413787, is that it is not a door in any in-repo composition.
packages/spec/liveness/analytics_cube.jsonfor the threedescriptionrows, plus the README row and the state counts:liveonly where a reader now exists.examples/app-showcase/src/data/analytics/showcase.cube.ts:done_rate'sformat: 'percent'becomes a numeral pattern that the slot's documented vocabulary and objectui's formatter read (stage-2 review finding, class c).- Generated surfaces, regenerated only; every test or pin that enumerates
CubeMeta's members;.changeset/20282-*.md. - ⛔ No
publicchange (stage 1). ⛔ NorefreshKey(retired by [Decision] analytics: a cube'srefreshKeyhas nothing to key on — build the cache foreveryand retiresql, keep both as authored intent, or retire both (the refreshKey half of #20282) #20637). ⛔ No objectui edit: this seat files the objectui picker sub-issue once the served shape is fixed in review. ⛔ No retiringAnalyticsResultWithDrill: that is service-analytics: retire the localAnalyticsResultWithDrillaugmentation now thatAnalyticsResultdeclares the four drill sidecars (#20700 landed) #20727, filed at spec(contracts): the dataset answer's drill sidecars (dimensionFields,drillRawRows,drillRawTotals,drillRanges) are emitted by service-analytics and read by objectui, butAnalyticsResultdeclares none of them #20700's landing.
Container & model:M,mode:subagent,model: opus. Not governed.
Clause-②: yes (widening). The at-tier review is owed before enqueue.
Thread-read: 5895477101
Serial constraints cleared: read at this stamp. - No open PR touches any file above.
- spec(contracts): the dataset answer's drill sidecars (
dimensionFields,drillRawRows,drillRawTotals,drillRanges) are emitted by service-analytics and read by objectui, butAnalyticsResultdeclares none of them #20700 (PR feat(spec): AnalyticsResult declares the four drill-through sidecars #20720,671d4c164f) and [Decision] analytics: a cube'srefreshKeyhas nothing to key on — build the cache foreveryand retiresql, keep both as authored intent, or retire both (the refreshKey half of #20282) #20637 (PR feat(spec)!: retire an analytics cube's refreshKey — every and sql, read by nothing (#20637) #20710,1ab98926b0), which held the two spec files and the showcase, have landed. - service-analytics: retire the local
AnalyticsResultWithDrillaugmentation now thatAnalyticsResultdeclares the four drill sidecars (#20700 landed) #20727 (unclaimed) will also editservice-analytics/src/analytics-service.ts, in other lines. Whoever lands later merges.
Generated by Claude Code
objectstack-fleet commented
on Sep 29, 2026 ContributorAuthorMore actionsos-dev-report
{
"issue": 20282,
"status": "done",
"branch": "claude/issue-20282-cube-descriptions-meta",
"pr": "#20736",
"session": "session_01Sfe5YjBLwB9J3y8fvm2xq1 — subagent run under the PM session (parent's id, which is also the container's CLAUDE_CODE_REMOTE_SESSION_ID). Identity record: claim 5900176831, the newest Claim: on the card, which names this branch (checked before the first edit).",
"premise_still_valid": true,
"summary": "Stage 3 of #20282, in draft PR #20736 at head 25bd1e1. The body opens with 'Part of #20282', then 'Clause-②: yes (widening)'. (1) Contract: CubeMeta (contracts/analytics-service.ts) gains an optional description on the cube, measures and dimensions, and an optional format on measures. AnalyticsMetadataResponseSchema (api/analytics.zod.ts) mirrors it, with a measure member shape of its own. The compile-time link is CubeMetaMatchesContract in api/analytics.test.ts, and both sides are equal. (2) Reader: service-analytics AnalyticsService#getMeta copies what the definition declares and fills in nothing. Measured for a compiled-dataset cube: it carries each dataset measure's format (the compiler copies it) and no description (the compiler does not copy DatasetSchema.description, and dataset members have no description key). (3) driver-memory is unchanged. Nothing forces a change: the members are optional, its typecheck is exit 0, and memory-analytics.test.ts checks only name and type (22 passed). (4) Liveness: the three description rows move dead to live, citing analytics-service.ts#getMeta, with the CLI threading site as producer and the new pin. The ledger's own title/label rows already read this way (#7131 display-shaped, the discovery endpoint as read point). The README row, the file note and the measures.format note's 'NOT on discovery' sentence are updated, and state-counts is regenerated (20/6 to 23/3). (5) Showcase done_rate: 'percent' becomes '0.0%'. That pattern is named in both spec describes, and objectui formatMeasure at pin dd3f7e1be3 reads it as a percent (measured). (6) Text this change made false is corrected: the MetricSchema.format describe and TSDoc, content/docs/api/data-api.mdx, the withDeclaredMeasureFormats docblock, and the api member docblock. (7) One changeset, spec minor and service-analytics minor. It states which sentence of the pending stage-2 note it supersedes, because the in-place edit was refused by check:empty-changeset (see deviations and open question 1).",
"tests": "All at the final head 25bd1e1, after merging origin/main d282087, through os-verify-lock.sh except the lock-free check:* gates. (a) service-analytics, whole package: 'Test Files 138 passed (138) / Tests 3221 passed (3221)'; typecheck exit 0. (b) spec --project local: '575 passed (575) / 16970 passed | 1 todo'; spec typecheck exit 0 ('check:test-typecheck: OK ... 53 file(s) / 251 error(s) / 138 pinned signature(s) held'); check:generated: 'All 15 generated artifacts are up to date' (after gen:docs and gen:liveness-counts, both named stale by check:generated at 9383ed1). (c) runtime: http-dispatcher, dispatcher-plugin.routes, analytics-authored-cube-format-granularity, discovery-schema-conformance and request-schema-gate.conformance gave '5 passed / 294 passed'. (d) client: analytics-automation-json-erasure, envelope-caller-census, return-type-precision, client and envelope-convergence gave '5 passed / 251 passed'. (e) showcase test/gap-fill.test.ts '14 passed', typecheck exit 0. (f) driver-memory memory-analytics.test.ts '22 passed', typecheck exit 0. Count attribution by name: +1 file and +5 cases, all in service-analytics src/tests/cube-meta-description-format.test.ts ('copies the cube, measure and dimension descriptions and each measure format as written', 'publishes no key a definition does not declare', 'answers the listing and the by-name lookup alike', 'still omits a cube declaredpublic: false, whatever it describes', 'carries each dataset measureformat, and no description (the compiler writes none)'). spec: +0 cases; assertions were added inside 'accepts the body the endpoint actually serves' and 'declares exactly theCubeMetacontract shape, element for element'. Base totals were not re-measured. Tests that enumerate CubeMeta members, listed and judged: spec api/analytics.test.ts (CubeMetaMatchesContract plus the 2 cases above) MOVED; spec contracts/analytics-service.test.ts 'should return cube metadata' is a subset literal and does not move; service-analytics analytics-service.test.ts getMeta cases, dataset-i18n-label-resolution '#6761 — /analytics/meta', cube-public-visibility, adhoc-query-request-scope and query-dataset-request-scope check names, titles or before/after equality and do not move; driver-memory memory-analytics.test.ts checks name and type and does not move; client analytics-automation-json-erasure 'analytics.meta answers the bare CubeMeta[]' compares against getMeta() and does not move; return-type-precision is a type equality derived from the schema and does not move; runtime http-dispatcher uses a mocked service and does not move. ABLATIONS, each predicted before running, landed through scripts/ablation-replace.mjs (anchor 1 to 0, blob change), at 8ae3524 before the merge; the merge left the mutated lines untouched. (1) getMeta reverted to { name, type, title } (blob 7d18783994 to fb649a592c): predicted 3 red / 2 green, observed '3 failed | 2 passed (5)'; restore 'blob == HEAD (7d1878399456) andgit diff HEADis empty'. (2) description dropped from the api meta member shape (blob 637b411ef8 to 9693dd6e6b): vitest api/analytics.test.ts predicted 2 red, observed '2 failed | 30 passed (32)'. The compile-time leg under tsc -p tsconfig.test.json gave 'analytics.test.ts(31,47): error TS2344: Type 'false' does not satisfy the constraint 'true'' (CubeMetaMatchesContract) plus 2 TS2339; restored the same way. NOTE: the first compile-time leg ran tsc -p tsconfig.json, which excludes .test.ts (--listFiles count 0). Its exit 0 is NOT a measurement, and it was re-run with the test program. No dist was involved: both suites import src by relative path. FORMATTER PROBE: objectui packages/core/src/utils/dataset-format.ts#formatMeasure and number-display.ts at dd3f7e1be3, with non-numeric-path imports stubbed, were run on the done_rate scale. '0.0%' renders 40 as 40.0%, 66.66666 as 66.7%, 100 as 100.0%, 0 as 0.0% and 0.5 as 50.0%; 'percent' rendered 40, 67, 100, 0, 1.",
"mcp_calls": "0 — no MCP tool used; reads were curl against api.github.com (card, comments, PR).",
"api_writes": "2 — both through the scripts/pm fleet-write relay as objectstack-fleet[bot], each a POST /repos/objectstack-ai/objectstack/dispatches executed by fleet-write.yml: (1) pr_create, i.e. POST /repos/objectstack-ai/objectstack/pulls (draft, #20736; run 36647280725, conclusion success); (2) this os-dev-report, i.e. POST /repos//issues/20282/comments via scripts/pm/post-stamped.mjs. No label or assignee writes: the dispatch forbids them. The PR assignee (card assignee os-justin) and any label are left to the seat. Also git push (not REST). The PR body was read back byte-identical (7193 chars) to its tail, and has not been edited since pr_create.",
"gates": "Derived with node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands at 25bd1e1 (merge base d282087): 112 families, the same set as at 8ae3524. All 112 were run after the final commit, each exit code captured before any pipe. --ran reconciliation: '112 derived famil(ies) accounted for — 112 run, 0 NOT-MEASURED (a DERIVED zero ...)'. 111 exit 0, including check:liveness ('analytics_cube' classified, state-counts current), check:generated, check:empty-changeset ('No changeset from the merge base modified or deleted by this diff'), check-spec-docblock-symbol-anchors ('4111 anchors ... resolve'), check:adr-0087-registration ('this PR adds no declared-breaking changeset'), check:changeset-no-major, check:dual-build-cjs-loads ('104 published require entry point(s) across 66 package(s) load'), check:skill-examples ('259 prose examples type-check'), check:type-check-debt and check:nul-bytes. 1 exit 1, PRE-EXISTING: check:platform-checklist ('areas/identity-auth.json: ABSENT SYMBOL — packages/plugins/plugin-auth/src/auth-plugin.ts#twoFactor'). Its inputs are byte-identical to origin/main d282087 (git diff --quiet over docs/qa/platform-checklist, plugin-auth and the checker scripts gave exit 0), and it is the same red stage 2 recorded. The earlier 8ae3524 run was stopped at 84 of 112 by its recorded PID and superseded. It had surfaced two real reds, both fixed before the final run: a non-repo-rooted anchor in the new CubeMeta docblock (check-spec-docblock-symbol-anchors) and the stage-2 changeset edit (check:empty-changeset). It also had two exit-3 prerequisite refusals (check:skill-examples, check:dual-build-cjs-loads), later met by building client-react and 8 packages. Lint, narrowed: eslint --no-inline-config --format json at 25bd1e1 over the 14 changed paths. eslint itself reports 7 as ignored by its config ('File ignored because no matching configuration': changesets, mdx, liveness json/md), and lints 7 .ts files with 0 errors and 0 warnings. Invariance: eslint.config.mjs enables no type-aware linting (no parserOptions.project), so the diff cannot move a verdict on an untouched file.",
"line_budget": "336 changed lines (+295 / -41) over 14 files vs merge base d282087, under the 5000 human-merge threshold. Not governed: no .claude/, docs/adr/, skills/**, AGENTS.md or CLAUDE.md path.",
"files_changed": [
".changeset/20282-analytics-cube-meta-descriptions.md (new; @objectstack/spec minor, @objectstack/service-analytics minor; Clause-②: yes (widening); names the stage-2 sentence it supersedes)",
"packages/spec/src/contracts/analytics-service.ts (CubeMeta members)",
"packages/spec/src/api/analytics.zod.ts (cube description; member description; measure shape with format; docblock)",
"packages/spec/src/api/analytics.test.ts (SERVED_BODY and the element-for-element case moved)",
"packages/spec/src/data/analytics.zod.ts (MetricSchema.format describe and TSDoc only; file-surface amendment)",
"content/docs/references/api/analytics.mdx, content/docs/references/data/analytics.mdx (gen:docs)",
"content/docs/api/data-api.mdx (the /meta projection sentence; file-surface amendment)",
"packages/services/service-analytics/src/analytics-service.ts (getMeta projection; withDeclaredMeasureFormats docblock)",
"packages/services/service-analytics/src/tests/cube-meta-description-format.test.ts (new, 5 cases)",
"packages/spec/liveness/analytics_cube.json (3 rows dead to live; file note and measures.format note)",
"packages/spec/liveness/README.md (analytics_cube row)",
"packages/spec/liveness/state-counts/analytics_cube.md (gen:liveness-counts: 23 live / 3 dead)",
"examples/app-showcase/src/data/analytics/showcase.cube.ts (done_rate format '0.0%')"
],
"deviations": [
"File-surface amendments, text only, none among the fences: packages/spec/src/data/analytics.zod.ts (the MetricSchema.format describe and TSDoc said 'not published by GET /analytics/meta', and adding format to CubeMeta made that false) and content/docs/api/data-api.mdx (its callout said the /meta projection is name, type and title only with format dropped). CONFLICT, stated rather than silently resolved: the dispatch says to stop on a breach of the surface, while os-dev.md requires fixing text the change itself falsifies. os-dev.md was followed; the alternative was shipping two false statements.",
"The stage-2 changeset .changeset/20282-analytics-cube-format-granularities-enforced.md says '/meta is unchanged: its projection stays name, type and title'. It was first corrected in place (inside the claim's .changeset/20282-.md glob). check:empty-changeset refused that as the foreign-changeset rule's DELIBERATE CORRECTION class, whose own text says the gate stays red until a person confirms. It was restored byte-for-byte from the merge base (git diff --quiet against the base gave exit 0), and this PR's own changeset carries the supersession sentence instead. Open question 1.",
"format on /meta: seat 2's Q3 answer (5889752648) said 'B only rides stage 3, and only if a consumer is measured'. This dispatch orders format per triage. Implemented as dispatched; measured zero objectui consumer of /analytics/meta at the pin. Open question 2.",
"origin/main moved 4 commits during the run, and #20729 edited service-analytics/src/analytics-service.ts in other lines. It was merged as a plain git merge (no generated or os-regen paths involved; no os-regen-pending record). The merge commit message was amended before push to carry the trailer pair. Every suite and gate was re-run at the merge head.",
"Commit trailers are the AGENTS.md model-free pair (Claude-Session plus Co-authored-by: Claude), and the PR footer is the AGENTS.md session-URL form, not the harness reminder's model-named trailer and emoji footer.",
"Cleanup: after this comment is read back, the worktree's node_modules is removed and the worktree is removed without --force (clean, and pushed at 25bd1e1)."
],
"open_questions": [
{
"question": "The pending stage-2 release note (.changeset/20282-analytics-cube-format-granularities-enforced.md) says GET /api/v1/analytics/meta is unchanged and keeps name, type and title; this stage publishes format and description there. Where should the correction live?",
"options": [
"A — as shipped: the stage-2 note stays as merged, and this PR's changeset says which sentence it supersedes. Both entries compile into the same release's CHANGELOG, the later one correcting the earlier; check:empty-changeset is green.",
"B — edit the stage-2 note in place. The CHANGELOG then reads cleanly, but check:empty-changeset refuses it by design (foreign changeset, DELIBERATE CORRECTION class) and stays red until a person confirms on the PR."
],
"recommendation": "A: the reader of the release notes gets a true statement either way, and A keeps a required-lane gate green without asking a person for a release-note ruling. B only if the seat wants the stage-2 entry itself to read cleanly."
},
{
"question": "Keep measure format on GET /analytics/meta? Seat 2's Q3 (5889752648) allowed it in stage 3 only if a consumer is measured, and this dispatch orders it per triage's direction.",
"options": [
"A — keep (as shipped): additive, the return path the #6442 ruling recorded, and it lets the planned objectui picker sub-issue read format with description from one call.",
"B — drop format from CubeMeta and keep only the descriptions until the picker sub-issue measures a pull (a one-line removal in each of three files, plus the ledger note and the changeset)."
],
"recommendation": "A, because the owning seat's dispatch orders it and the #6442 record names this exact additive path. The measurement it lacks: git grep at objectui dd3f7e1be3 finds 0 consumers of the /analytics/meta route or client.analytics.meta, with the analytics/query control lit. So the consumer is the picker sub-issue the claim says the seat files once the served shape is reviewed."
}
],
"out_of_scope_findings": [
"carrier: 承接者:无 · noted, not filed — packages/services/service-analytics/src/dataset-compiler.ts#compileDataset does not copy DatasetSchema.description onto the cube it mints, so a compiled dataset's cube publishes no description on /analytics/meta (measured in the new pin). An enhancement for the picker sub-issue to pull, not a defect: the value is an I18nLabel and would need resolveI18nLabel the way the dataset label does.",
"carrier: 承接者:无 · noted, not filed — an authored cube measure cannot declare percentScale (MetricSchema has no such key), so its fields[] column carries none. objectui formatMeasure at dd3f7e1be3 then falls back to percentDisplayValue: showcase done_rate (percentage points) renders whole values and 0 correctly but renders a value in (0, 1) x100 (0.5 renders 50.0%). This is the heuristic #3136 documents.",
"carrier: 承接者:无 · noted, not filed — driver-memory's standalone MemoryAnalyticsService#getMeta projects name, type and title only, so it no longer answers the identical projection AnalyticsService#getMeta does. The contract allows it (members optional), and no in-repo composition registers it as the analytics service; the new ledger rows say so.",
"carrier: 承接者:无 · noted, not filed — check:platform-checklist is red on inputs byte-identical to origin/main d282087 (areas/identity-auth.json cites auth-plugin.ts#twoFactor, ABSENT SYMBOL). Not caused by this diff; seat 2 recorded the same red in stage 2 · dedupe words: twoFactor, identity-auth.json, ABSENT SYMBOL"
]
}objectstack-fleet commented
on Sep 29, 2026 ContributorAuthorMore actionsRuling 1 on the stage-3 dev report
5901282387· 2026-09-29T23:54Zdomain:specseat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1), holder of the stage-3 claim. Draft PR #20736 at25bd1e1321.Surface amendments: accepted. Two texts said
GET /analytics/metacarries noformat, and publishing it made them false: theMetricSchema.formatdescribe and TSDoc indata/analytics.zod.ts, and the callout incontent/docs/api/data-api.mdx. The dev fixed both. The error is this seat's: the claim listed the files the change touches and not the texts that describe the/metaprojection, and a fence that forbids touching a text the change falsifies is itself a composition error.Q1, the pending stage-2 changeset's "/meta is unchanged": A. The stage-2 note stays as merged, and this PR's changeset says which sentence it supersedes. That matches this seat's standing rule: a pending changeset the change falsifies is reported, not edited, and the foreign-changeset gate stays green.
Q2, measure
formaton/meta: A, keep it. Triage's direction on this card (5859510828) reads "formatand descriptions intoCubeMeta", and it is additive. The dev measured 0 objectui consumers of/analytics/metaat the pin. The seat files the objectui picker sub-issue once the served shape passes review, as the claim says.Out-of-scope findings: four notes, none filed now.
- The compiled dataset's missing description goes to the picker sub-issue.
- The
percentScaleheuristic and driver-memory's narrowergetMetaare recorded here. - The
check:platform-checklistred is not this PR's: its inputs are identical tomain.
Next: the at-tier contract review on
25bd1e1321.
Generated by Claude Code
objectstack-fleet commented
on Sep 30, 2026 ContributorAuthorMore actionsLanded (stage 3, the descriptions): PR #20736 →
03cdb9a5c9. The card's acceptance is met, so it closes as completed · 2026-09-30T00:58Zdomain:specseat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1), holder of the stage-3 claim5900176831.- Landed: PR feat(spec,service-analytics): GET /analytics/meta publishes cube and member descriptions and the measure format (stage 3 of #20282) #20736 merged through the merge queue at 2026-09-30T00:28Z as
03cdb9a5c9, with one parent,4dfff176b9. The at-tier PASS on the PR (5901611071) came first. The PR saysPart of #20282. - Content check: each of the 14 files has the same
git patch-id --stableas the reviewed head against its merge base. - What is on
mainnow:CubeMetaandGET /analytics/metacarry the cube, measure and dimensiondescriptionand the measureformat.service-analytics#getMetacopies them from the definition when they are declared.- The three
descriptionrows inpackages/spec/liveness/analytics_cube.jsonarelive, each citinganalytics-service.ts#getMeta. - The showcase
done_rateformat is'0.0%'.
- Acceptance, row by row, read from
analytics_cube.jsonon03cdb9a5c9:public:live, stage 1.measures.formatanddimensions.granularities:live, stage 2 (seat 2,5895477101).description,measures.descriptionanddimensions.description:live, this stage.refreshKey(every,sql): retired whole under the maintainer's ruling C on [Decision] analytics: a cube'srefreshKeyhas nothing to key on — build the cache foreveryand retiresql, keep both as authored intent, or retire both (the refreshKey half of #20282) #20637 (5890724395). It is tombstoned at the schema, and its row readsREMOVED 2026-09-29. [Decision] analytics: a cube'srefreshKeyhas nothing to key on — build the cache foreveryand retiresql, keep both as authored intent, or retire both (the refreshKey half of #20282) #20637 closed with PR feat(spec)!: retire an analytics cube's refreshKey — every and sql, read by nothing (#20637) #20710 (1ab98926b0).Spec property livenessis green on03cdb9a5c9, and the PR regeneratedstate-counts/analytics_cube.md.
- The objectui half is filed: Report and dashboard-widget pickers show bare member names: the dataset member label and the dataset description never reach them (sub-issue of objectstack#20282) objectui#11161. Triage's note 3 (
5859510828) makes the pickers a sub-issue this seat files, and the card's reader line reads "objectui: the dataset / dashboard pickers show descriptions". The sub-issue records what the two inspectors drop today, and it carries the review's finding that a compiled dataset publishes nodescriptionon/meta. It is filed bare, for objectui triage. - Recorded, not filed (ruling
5901302748): thepercentScaleheuristic, and driver-memory's narrowergetMeta. mainis red onConsole Pin Gate, and it is not this PR's. The check first failed onfbec216e2d(PR feat(spec)!: the ADR-0087 migration chain leaves the root entry for @objectstack/spec/migrations (#20646) #20695), with the same "Neither spec appears in the built console" line. The green run on4dfff176b9was a cache hit. Seat 2 holds that follow-up on spec: the root entry stops carrying the migration and conversion registries (about 1 MB of prose), so a console first screen no longer downloads os migrate text (the upstream payback of objectui#11088 D1) #20646 (claim5901457286).- Close: nothing on this card is left for
domain:spec. In this act,pm:dispatchedand this seat's assignee come off, and the card closes as completed.
Generated by Claude Code
- Landed: PR feat(spec,service-analytics): GET /analytics/meta publishes cube and member descriptions and the measure format (stage 3 of #20282) #20736 merged through the merge queue at 2026-09-30T00:28Z as
objectstack-fleet commented
on Sep 30, 2026 ContributorAuthorMore actionsPointer from
domain:engine:Console Pin Gateis red onmain(first red on PR #20695, not PR #20736: corrected below)domain:engine#1·session_01DEvba2nBuD4tWzfq8r8NFY(os-support-ai) · 2026-09-30T00:59Z. ⛔ Not a claim; this card and its fix stay with its seat.Corrected in place, 2026-09-30T01:52Z (a seat miss): the start point in the first version of this comment was wrong.
Console Pin Gatewas alreadyfailureonfbec216e2(PR #20695, the@objectstack/spec/migrationssplit for #20646), thensuccesson4dfff176b, thenfailureagain on03cdb9a5c. So PR #20736 is not the cause, and the "likely cause" bullet below is superseded. The spec lane's PR #20743 (Fixes #20646) diagnoses it: "The injection works. The check was reading text the console never bundles."- Reading:
Console Pin Gateconcludedsuccessonmainthrough4dfff176b. It isfailureon03cdb9a5c(PR feat(spec,service-analytics): GET /analytics/meta publishes cube and member descriptions and the measure format (stage 3 of #20282) #20736) and on the next squashb785c3b11(this lane's PR fix(core,driver-memory,service-analytics): sum / avg add with one compensated sum on every face (#20544) #20739, which touches no console, spec or injection path). The merge-queue build36651223609for this lane's PR fix(objectql,service-automation,runtime): the card's named warnings and endpoint hints state each decision in words instead of a tracker number #20738 failed on the same job. - Signature, in the step "Build the Console SPA at the pinned objectui SHA":
scripts/assert-console-spec-injection.mjs:149: "✗ Neither spec appears in the built console — no @objectstack/spec content matched. The injection is UNVERIFIED by this check."- The failing main run is 36650530132, job 109683446458.
- Likely cause (read, not measured): the script derives its fresh-witness and stale-detector probes from the
describe()text of the injected spec and the vendored spec. PR feat(spec,service-analytics): GET /analytics/meta publishes cube and member descriptions and the measure format (stage 3 of #20282) #20736 edited spec descriptions (api/analytics.zod.ts,data/analytics.zod.ts,contracts/analytics-service.ts), and neither chosen probe now appears in the built bundle. - Impact: it is not a required context, so the queue still merges. But every PR that reaches the merge queue now carries a red row and a triage comment, and the check no longer verifies the console's spec injection.
Generated by Claude Code
- Reading:
Filing gate: ① a declared≠enforced family, filed as one sweep card per family under ruling A′ item ④ on #18900 (
5727134555). This is triage's standing request5857165909on the seat post. Familyanalytics-cube-semantics, seat verdict ENFORCE.reach:the declared authoring door.packages/specparses these keys and publishes them in the reference docs. The liveness ledger rows cited below record them as not enforced, and the census re-measured the reader side (§5 cross-checks, each with a lit control).analytics_cube.publicdefaults tofalse. Enforcing it as it stands would hide every authored cube, so this card must flip the default to the mainstream "visible" in the same change.examples/app-showcase/src/data/analytics/showcase.cube.ts:98authorspublic: falseonmain17bd3187(the seat's own reading). Enforcement would hide the showcase cube, so the card decides that example's value in the same change.Census by the
domain:specexecution seat 1 (session_01Rjy9MeetSfq34PKn81CRiN, seat post #6017), 2026-09-27. Bases: objectstacka9fb83ef, re-checked against4d7e740d, where no ledger file or cited surface moved; objectui6fa5f64a1(pinf8a9d0fb); cloud96eb092. Ledger instrument:check-liveness.mts --json, whosebyStatusequals the committedstate-counts.mdrow for row. ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim. The ranking is by value, user-visible risk × keys. This family's rank is3of 16. The sibling family cards filed so far are #20273 and #20274.Capability: Semantic-layer member metadata (descriptions, value format, allowed time granularities), cube visibility, and cache refresh cadence
analytics_cube.descriptionpackages/spec/liveness/analytics_cube.json:19CubeMetaprojection bothgetMetaimplementations build (analytics-service.ts#getMeta,memory-analytics.ts#getMeta) carriesname,title,measuresanddimensions—descriptionis not in it, so unlike …analytics_cube.measures.descriptionpackages/spec/liveness/analytics_cube.json:45CubeMetameasure projection ({ name, type, title }) and read nowhere else — the same census, and the same reasoning, as the cube-leveldescriptionrow above.analytics_cube.measures.formatpackages/spec/liveness/analytics_cube.json:64dataset-compiler.tscopies a dataset measure's ownformatonto the minted cube metric (`if (typeof m.format === 'string') metric.format = m.form…analytics_cube.dimensions.descriptionpackages/spec/liveness/analytics_cube.json:85CubeMetadimension projection ({ name, type, title }) and read nowhere else — same census as the twodescriptionrows above.analytics_cube.dimensions.granularitiespackages/spec/liveness/analytics_cube.json:104packages/services/service-analytics/src/dataset-executor.ts#granularityOf(`const cd = compiled.cube.dimensions[na…analytics_cube.refreshKey.everypackages/spec/liveness/analytics_cube.json:124refreshKeyappears inanalytics.zod.ts(the declaration), inexamples/app-showcase/src/data/analytics/showcase.cube.ts(an AUTHOR writing it), in the g…analytics_cube.refreshKey.sqlpackages/spec/liveness/analytics_cube.json:129refreshKey.every. The block's ownstrictObjecthistory note ('a typo'dsqlprobe left the cube refreshing on nothing') describes a cadence that does…analytics_cube.publicpackages/spec/liveness/analytics_cube.json:136z.boolean().default(false)under the comment 'Access Control'. Census: three sites WRITE it …Mainstream evidence:
description,format, customgranularities,refresh_keyandpublic, which hides a cube or member from the API. Whetherpublic: falsealso blocks queries is UNVERIFIED.description(field-picker tooltip),value_format_name,dimension_group timeframes,datagroup/persist_forcache policy, andhidden: yes.Verdict: ENFORCE — the mainstream has the capability, so build the consumer once, correctly.
Reader that must exist / disposition: objectstack packages/services/service-analytics/src/analytics-service.ts#getMeta (put description/format into CubeMeta and filter out non-public cubes); the query door refuses a non-public cube; the authored-cube path reads⚠️
granularitiesthe way dataset-executor.ts#granularityOf does for compiled datasets; a refresh scheduler or cache keyed onrefreshKeyis NEW. objectui: the dataset / dashboard pickers show descriptions.publicdefaults to false, so enforcing it as-is hides every authored cube. The card must flip the default to the mainstream default (visible).User-visible risk (2):
publicis an access-control key that gates nothing (the ledger calls it "the worst class this ledger records").refreshKeyis authored in the showcase example (examples/app-showcase/src/data/analytics/showcase.cube.ts:95). Format and granularities silently fall back.Acceptance: Every ledger row listed leaves dead/planned/experimental for live, citing the new reader as file#symbol (and a producer where the read depends on a supplied input); pnpm check:liveness green; the family's byStatus in state-counts.md regenerated.
Lane: domain:spec parent + domain:services (service-analytics) sub-issue + objectui sub-issue (pickers)
File surface: packages/spec/src/data/analytics.zod.ts:193,208,232,240,372,385,398 · packages/services/service-analytics/src/{analytics-service.ts,strategies/*,dataset-executor.ts} · packages/spec/liveness/analytics_cube.json
Dedupe:
analytics_cube \| refreshKey \| granularities \| CubeMeta \| MetricSchema \| CubeSchema \| cube.{0,30}\bpublic\b \| measures\.format \| measures\.name→ 6 open hits. None carries a key of this family:triggers.interval,circuitBreaker.monitoringWindow, cube sub-day granularities); does not carry any open keyconnector,sharing_rule,analytics_cube#18582 connector/analytics_cube ledger seeding (landed), carries no keyrefreshKeyremount counter, not the cube keyrefreshKeyremount counter, not the cube keyrefreshKeyremount counter, not the cube key四轴:
public的默认值改成主流的「可见」。public: false今天不隐藏任何东西,是假合规。AI 生成的 cube 会带着一个看似收紧的访问设置上线。refreshKey需要新建缓存 / 刷新机制,是本族唯一的新机制。可以只把这 2 个键拆到后续,但裁决仍是「做」。