Repository navigation
[Decision] analytics: a cube's refreshKey has nothing to key on — build the cache for every and retire sql, keep both as authored intent, or retire both (the refreshKey half of #20282) #20637
Description
Ruled: 5890724395 · letter C — refreshKey retired whole (every and sql), no cache built; this card is the retirement card · 2026-09-29T12:59Z
This card carries the refreshKey half of #20282; #20282 keeps format and granularities (stage 2, PR #20635) and the descriptions (stage 3).
Filed by the domain:spec execution seat 2 (session_014EJ1ED8X4MMrT18BhVx4tx, seat post #18549) from the #20282 stage-2 report 5889706157 (open question 1), with the seat's answer 5889752648. The dispatch ordered refreshKey measured only. ⛔ Not a claim.
One-line problem
An analytics cube can declare how often its results refresh (refreshKey: { every: '1 hour' }), and the showcase app does. Nothing in the platform reads it: no cache exists, so the setting silently does nothing.
Background and evidence (measured by the stage-2 dev at tree 958251b6ac)
refreshKeyis declared onanalytics_cube(packages/spec/src/data/analytics.zod.ts,everyandsql, both optional strings). Both liveness rows aredead.- Readers: 0.
git grep refreshKeyover non-testpackages/services,packages/driversandpackages/restfinds 0 hits. Repo-wide, it appears only in the spec, generated surfaces, migration notes and one author. - Authors: 1.
examples/app-showcase/src/data/analytics/showcase.cube.ts:87declaresevery: '1 hour'. - Nothing to key on.
service-analyticsreferences no job, cache or scheduler service. Its one cache is request-scoped (dimension-labels.ts#withLabelFetchCache). A scheduler exists (service-job), and analytics does not use it. - History. The service README once advertised
enableCaching/cacheTTL/invalidateCache; they were removed as fabricated (see theservice-analyticsCHANGELOG). refreshKey.sqlhas no safe seam. It would run author-written raw SQL on a schedule outside the read-scope machinery. Every other cubesqlis treated as an object name.
Governing text
- Ruling A′ ④ on [Decision] Route declared≠enforced work by the SEAM, not the layer — a
Seam: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 (5727134555), the maintainer's criterion: 「每族该问的是:主流平台有没有这个能力 —— 有 ⇒ 补消费端(一次做对);没有 ⇒ 退役,而不是看仓里有没有人读」. - Triage on analytics: an authored cube's
public,refreshKey,format,granularitiesand descriptions take effect (8 keys) #20282 (5859510828) applied it to this family: ENFORCE. - ADR-0049 (enforce-or-remove) states the same rule for security properties.
refreshKey.sqlis security-adjacent: it is raw SQL that would run outside read scope. - Protocol statement: this is not a request to change the protocol. It asks which enforcement the declared keys get, or whether they leave.
Premises, each with a re-check
- Readers are still 0:
git grep -n refreshKey origin/main -- 'packages/services' 'packages/drivers' 'packages/rest' ':!*.test.ts'. service-analyticsstill uses no cache or job service:git grep -n -E "ICacheService|IJobService|cache\.|jobs?\." origin/main -- packages/services/service-analytics/src ':!*.test.ts'.
Options (what each does, and what a customer would notice)
| What it does | What a customer notices | |
|---|---|---|
| A | Build every as a result cache in its own L card, sequenced after #20282's stage 3. It is keyed by cube, the normalized query and the caller's resolved read scope and tenant, with the TTL from every. Retire sql now: a tombstone, a D2 conversion that strips it, and the showcase edit. |
Dashboards on busy cubes answer from cache within the declared cadence. An author who wrote sql gets a loud refusal with a migration note. |
| B | Keep both keys as authored intent: the rows stay dead with this census, and nothing is built until a deployment pulls. |
Nothing changes. A declared refresh cadence keeps doing nothing, silently. |
| C | Retire refreshKey whole (every and sql): tombstones, a D2 strip and the showcase edit. This reverses triage's ENFORCE. |
An author who declared a refresh cadence gets a loud refusal and a migration note. There is no caching, and none is promised. |
- A in business terms: the platform promises the cadence the author wrote, as Cube.dev's
refreshKeydoes for its caches. The half that cannot be made safe is removed. - B in business terms: a settings screen with a switch wired to nothing.
- C in business terms: take the switch off the screen until there is a machine behind it.
四轴分析(业务立场)
- 实际业务需求: 零实测拉动。0 个读者,1 个仓内作者(showcase 演示
every: '1 hour'),无任何部署报告看板慢。过去宣传过的分析缓存是虚构后被删除的。维护者判据只问主流有没有:Cube.dev 有refreshKey,所以分诊判 ENFORCE。 - 项目长远合理性: 两年后的平台应当有按读权限范围正确分键的结果缓存,主流(Cube.dev 预聚合、Looker datagroup)都这样建模。但它是安全敏感子系统:分键漏掉读范围就会把 A 租户或 A 用户的行给 B,需要单独设计(很可能要 ADR),不能挂在本卡顺手做。
sql探针没有安全执行接缝,长远看应删。 - 防 AI 写元数据犯错: 不做任何事时,showcase 在教 AI 写一个无效的键:静默,谁也看不到错。A 让
every兑现、让sql响亮拒绝;C 让两者都响亮拒绝;B 保留陷阱。 - 创业阶段不扩散: A 是新能力(L),所以只能作为单独、排在第 3 阶段之后的卡。B 是 declare-and-maintain,属永久义务。C 最省。
os-decision-facets
- ① 项目长远合理性:A 收敛为主流形态(
every兑现、sql删除),特例减少;B 保留一个声明未兑现的特例;C 删除声明,契约最小。 - ② 实际业务拉动:今天没人撞上(0 读者、1 演示作者、无慢看板实测);零拉动默认 defer 或 remove。
- ③ 防 AI 犯错:A、C 都把静默无效变成响亮拒绝(C 全部,A 对
sql);B 让 AI 继续照 showcase 写无效键。 - ④ 创业阶段不扩散:C(remove)优于 A(新建 L 子系统)优于 B(声明并维护一个无效键)。
Prior rulings read:refreshKeyin docs/adr + docs/NORTH-STAR.md + AGENTS.md → 0 hits; ADR-0049 (enforce-or-remove, security properties); thread: analytics: an authored cube'spublic,refreshKey,format,granularitiesand descriptions take effect (8 keys) #20282 (triage5859510828, pitfall note5869426939, stage-2 report5889706157, seat answer5889752648), ruling A′ ④ on [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 (5727134555)
Recommendation
A: build every in its own L card after stage 3, and retire sql now.
- Self-check: 只看①选 A;②③④ 是否翻转:否(②④ 只把
every的建设推到第 3 阶段之后、单独成卡,不改字母)。 - Fallback: C, if you weigh startup focus above the ENFORCE ruling for this family. C is also a clean interim: retire now, and re-declare on the day a cache exists.
- Confidence gap: this seat cannot see customer projects outside this repository. If a deployment already declares
refreshKey, C breaks its load with a migration note, and A only breakssql. There is no latency measurement of any dashboard, so A's value is the mainstream argument, not a measured pull.
After the ruling
- A: this seat files an L card for the
everycache, sequenced after analytics: an authored cube'spublic,refreshKey,format,granularitiesand descriptions take effect (8 keys) #20282's stage 3 and marked for its own design review, and a small spec card that retiressql.every's describe states "not read yet" until the cache lands. - B: the two rows stay
deadwith this census re-verified, and this card closesnot_plannedwith the ruling cited. - C: one spec retirement card for both keys, and the showcase edit rides it.
Related: #20282 (the family card), PR #20635 (stage 2), #18900 (ruling A′).
Generated by Claude Code
Activity
objectstack-fleet commentedon Sep 29, 2026
Ruling: batch #245 item 1 · letter C · maintainer 「20637 C」 2026-09-29T12:53Z
Director seat (objectstack#12708, summon #30 续 2,
session_01AsCNgFBs8HCjwhyHQsFbx3). Provenance: maintainer, live PM chat with the director seat, 2026-09-29, replying 「11002 A 20619 A 10866 A 20637 C 11088 同意」 to batches #243–#245 as presented. Presented on this card: thedomain:specseat 2 decision packet (the body), read whole, with the director's own reading in chat (recommendation A, fallback C — the maintainer chose C).Ruled: C.
analytics_cube.refreshKeyis RETIRED whole —everyandsql— under ADR-0049 enforce-or-remove. No cache is built and none is promised by the schema: an author who declares a refresh cadence meets a loud refusal with a migration note, not a key that does nothing. This reverses triage's ENFORCE for this family (5859510828) by the maintainer's letter: the mainstream capability (a scope-keyed result cache, Cube.dev / Looker) is not lost from the plan — it is re-declared on the day a cache exists, with its own design (it is security-sensitive: a cache keyed without the caller's read scope serves one tenant's rows to another), and not carried as a dead key until then.Readings that decided it:
everyin the meantime is exactly the residue ADR-0049 exists to remove.sql(author-written raw SQL on a schedule outside read scope) has no safe seam and leaves either way.Execution parameters (this card is the retirement card; the
refreshKeyhalf of #20282):domain:specseat, perspec-property-retirement:refreshKeybecomes aretiredKey()tombstone onanalytics_cube(packages/spec/src/data/analytics.zod.ts), the prescription stating that nothing read it, that no cache exists, and that a cadence is re-declared when one does;integration-style whole-key removal ofeveryandsqlwith their retired-key rows; ADR-0087 D2 conversion (a lossless strip ofrefreshKeyfrom stored cubes and authored sources) and one D3 entry; the showcase author (examples/app-showcase/src/data/analytics/showcase.cube.ts:87) edited; liveness rows →deadtombstone; generated surfaces; changeset@objectstack/spec: minorwith the BREAKING banner, FROM → TO,Clause-②: no (narrowing), the ADR-0087 marker.retiredAfteris the labelmaincarries at landing.refreshKeyare not visible from here; the D2 strip plus the migration note is what they meet on upgrade.State:
needs-user-decision→pm:queue(domain:spec·area:reports· p2 stay); the Ruled line goes on the body in the same stroke; a pointer goes on the family card #20282.objectstack-fleet commentedon Sep 29, 2026
Claim: PM loop round 11 · the retirement ruled C (
5890724395) · 2026-09-29T18:19ZSession:
session_01Sfe5YjBLwB9J3y8fvm2xq1Account:
os-justin(the seat's linked user asGET /useranswers it; the card's assignee from this act)Branch:
claude/issue-20637-cube-refreshkey-retiredWorktree:
objectstack-issue-20637Domain:
domain:specSeat:
domain:spec#5(seat post #19357)File surface: the ruling's execution parameters, done per the
spec-property-retirementskill. Stop on breach and explain it in the report.packages/spec/src/data/analytics.zod.ts:refreshKeyonanalytics_cubebecomes aretiredKey()tombstone, andeveryandsqlleave with their retired-key rows.packages/spec/src/conversions/registry.ts: one ADR-0087 D2 conversion that stripsrefreshKeylosslessly, with its pin tests.packages/spec/src/migrations/entries/semantic/18.*.ts: one new D3 entry.migrations/registry.ts: this retirement's hand-writtenSTEP18_RATIONALEfragment, plus the generated regions regenerated.packages/spec/liveness/analytics_cube.jsonandpackages/spec/liveness/README.md.examples/app-showcase/src/data/analytics/showcase.cube.ts, the one author.authorable-surface*.json,content/docs/references/data/analytics.mdx,spec-changes.jsonand the upgrade guide, regenerated only..changeset/20637-*.md.refreshKeyand that this retirement makes false changes with it:18.analytics-authorable-unknown-keys-refused.ts;docs/audits/2026-07-unknown-key-strictness-ledger.md;analytics.test.tsandanalytics-strictness-batchd.test.ts.Released
CHANGELOG.mdentries are release-owned and stay untouched.packages/metadata-core/src/artifact-forward-conversion.test.tsreads the live registry. The dev names each one.Container & model:
M,mode:subagent,model: opus.check-governed-merges --teston therefreshKeysites: NOT governed.Clause-②: no (narrowing). BREAKING banner, FROM → TO, and the ADR-0087 marker.
retiredAfteris the labelmaincarries at landing. The at-tier review is owed before enqueue.Thread-read: 5890724395
Serial constraints cleared: read at this stamp.
conversions/registry.ts. The seat lands it first, and this dev mergesmainbefore pushing.AnalyticsResultdeclaresobject, the dataset answer's base object, present on every dataset answer (the spec half of #20644) #20647) editsapi/analytics.zod.ts, a different file fromdata/analytics.zod.ts.migrations/registry.ts. That is ordinary concurrency.public,refreshKey,format,granularitiesand descriptions take effect (8 keys) #20282 stage 3 (descriptions, and the showcasedone_rateformat) touches the same showcase file and the cube schema, so it is serial after this card.conversions/registry.ts, so it is serial after this card.Generated by Claude Code
objectstack-fleet commentedon Sep 29, 2026
os-dev-report
{
"issue": 20637,
"status": "done",
"branch": "claude/issue-20637-cube-refreshkey-retired",
"pr": "#20710",
"session": "session_01Sfe5YjBLwB9J3y8fvm2xq1 — the dispatching seat's session (this run is its subagent)",
"premise_still_valid": true,
"summary": "Retired analytics_cube.refreshKey whole (every and sql) per ruling 5890724395 letter C. Tombstone: refreshKey is retiredKey(CUBE_REFRESH_KEY_REMOVED) on CubeSchema (a strictObject); the nested strictObject left with it. Prescription, each clause measured or taken from the ruling: removed in @objectstack/spec 17 (the connector-triggers spelling, since the next release label is not known), nothing read it, no analytics result is cached, delete the key, every query is computed when asked, a cadence is declared again when a result cache exists (the ruling's re-entry, not a tree fact), and the house migrate sentence. D2 cube-refresh-key-removed: step 18, retiredFromLoadPath, retiredAfter 17.5.0, surface analyticsCubes[].refreshKey. It strips the whole block per cube with the cube named in the notice path. It is inserted where its identifier sorts in MAJOR_18_CONVERSIONS (between cubeMemberInnerNameRemoved and cubeSubDayGranularitiesRemoved) with order 47, and defined directly above cubeSubDayGranularitiesRemoved. Retired-key entry data/Cube:refreshKey (ONE row). The dispatch's retired-key rows for every and sql do not exist as rows: I measured that a nested data/Cube:refreshKey.every row is refused by build-schemas check (b3) ('name a NESTED key this build does not emit', exit 1) once the parent is a tombstone, so they leave with the block, as the ruling intends. D3 cube-refresh-key-retired (no tracker number in its fields). STEP18_RATIONALE fragment id cube-refresh-key-retired, order 49, hand-written between cube-metric-filters-retired and currency-config-precision-retired. Semantic and retired-key regions regenerated. Ledger: refreshKey.every and refreshKey.sql collapse into one dead leaf tombstone row. README row: 7 to 6 dead. state-counts: 20 live, 6 dead, 26 classified. Showcase author removed, with a 3-line comment. Changeset @objectstack/spec minor with BREAKING, FROM to TO, Clause-② no (narrowing) and the ADR-0087 marker registered cube-refresh-key-removed, cube-refresh-key-retired. retiredAfter reading: main (a8acee2, and again 5757463) carries packages/spec 17.5.0. Version Packages PR 20639 is still open and proposes 17.6.0. If 20639 lands before this PR, the stamp and the changeset's '17.5 and earlier' row become 17.6.0 / '17.6 and earlier'. Merge: per the seat note, origin/main a8acee2 (with 20690 and 20687) was merged via scripts/pm/os-regen-merge.sh as e2e0121. There were no conflicts: conversions/registry.ts auto-merged, and HEAD vs origin/main on that file is +106/-0 (my entry only). Rebuild plus check:generated: 15 of 15 up to date, nothing regenerated. main has since moved to 5757463 (7 commits, 0 files overlapping this diff). Composition, every text describing refreshKey: analytics.zod.ts (tombstone + docblock + inline note); conversions/registry.ts (new entry); migrations entries (new retired-key, new D3) and the generated registry.ts; 18.analytics-authorable-unknown-keys-refused.ts (surface and acceptanceCriteria no longer offer refreshKey, and reason records the second of eight sites removed, by cube-refresh-key-removed); liveness analytics_cube.json and README.md (updated) and state-counts (regenerated); authorable-surface/data.json (regenerated to [RETIRED]); authorable-surface.base.json unchanged by design (only gen:authorable-surface-base writes it; check:authorable-surface green); content/docs/references/data/analytics.mdx (regenerated); docs/audits strictness ledger row annotated (superseded, not reopened) and its counts shard regenerated (analytics.zod.ts 7 to 6 sites, data/ 159 to 158); analytics.test.ts and analytics-strictness-batchd.test.ts updated; spec-changes.json and the upgrade guide did not move (they project majors up to PROTOCOL_MAJOR from the support floor; step 18 is not projected — the sibling cube-member-inner-name ids are absent too); packages/spec/CHANGELOG.md release-owned, untouched; pending changesets: 0 mention refreshKey (git grep), so none falsified; skills/ and hand-written content/docs: 0 hits. Pins that count or enumerate what a retirement adds, all read the live registry and none needed an edit: spec conversions.test.ts, migrations.test.ts, retired-after.census.test.ts, retired-tables-not-floor-scoped.test.ts, nested-authorable-keys.test.ts (local project); scripts/conversions-major18-merge.test.ts and scripts/step18-rationale-merge.test.ts (repo project); metadata-core artifact-forward-conversion.test.ts (37 tests, per-entry window over the live registry picks up the new 17.5.0 entry); cli migrate-meta-default-range, migrate-meta-engine-guidance, migrate-meta.e2e. Count deltas: spec local 16960 before the merge to 16962 after, +1 in api/analytics.test.ts and +1 in contracts/analytics-service.test.ts, both from main's PR 20687; this diff adds 0 local tests (batchd: one it renamed, +1/-1); spec repo project +21 = the new cube-refresh-key-retirement.test.ts, registered in vitest.repo-tests.json. Commit trailers: the AGENTS.md model-free pair; the harness reminder's model-named Co-Authored-By was not used (user instruction precedence).",
"tests": "All at HEAD a2abb8c unless stated. spec:
pnpm --filter @objectstack/spec test→ Test Files 575 passed, Tests 16962 passed | 1 todo. spec repo project in pieces, because the whole project exceeds the ~10-minute foreground cap (EXIT 124): cube-refresh-key-retirement + cube-member-inner-name-retirement + currency-mode-family-closure.pin → 3 files, 47 passed; conversions-major18-merge + step18-rationale-merge + strictness-ledger-doc + strictness-ledger → 4 files, 61 passed; the other 35 roster files → 35 files, 567 passed; dist-freshness-adoption + dist-freshness + publish-smoke-boot-failure + publish-smoke-port-collision → 4 files, 58 passed. NOT MEASURED: scripts/build-schemas-check-mode.test.ts, reason: alone it exceeds the foreground cap (EXIT 124 at 595s); CI runs it. Its live-tree gates (b)/(b2)/(b3)/(c) passed via gen:schema in the build and check:authorable-surface exit 0. spec typecheck (tsc + scripts + check:test-typecheck) exit 0, ledger unchanged (53 files / 251 errors / 138 signatures); the new pin is in the tsconfig.test.json program (--listFiles: 1 hit, control sibling 1 hit). showcasepnpm --filter @objectstack/example-showcase typecheckexit 0. cli: unitvitest run --project unit src/commands/migrate/→ 6 files, 42 passed; integration migrate-meta-default-range + migrate-meta-engine-guidance + meta.stored-flow-resolution.integration → 3 files, 13 passed, 1 skipped; nightly tierOS_TEST_TIERS=nightly … --project integration test/migrate-meta.e2e.test.ts→ 19 passed. Not run: the four schema-migrate e2e files (exit-code, plan-exits, apply-refuses-before-ddl, unloadable-host-config-exit), which are nightly tier and not on the meta conversion chain. metadata-core artifact-forward-conversion.test.ts → 37 passed. dogfood test/expression-conformance.test.ts → 7 passed. check:generated → all 15 up to date. dispatch-gates --commands (derived at e2e0121, identical at a2abb8c) → 114 families. --ran with recorded exit codes: 114 derived, 112 run, 2 NOT-MEASURED. 111 exit 0. check:platform-checklist exit 1, pre-existing on main and outside this diff (see findings). NOT MEASURED: check:dual-build-cjs-loads and check:type-check-debt (both exit 3 PREREQUISITE NOT MET), reason: they need a whole-repo build (82 packages without dist); CI owns them. Gates fixed in-run: check-spec-docblock-symbol-anchors first flagged my short anchor dimension-labels.ts#withLabelFetchCache; it now cites the full path and exits 0. check:skill-examples and check:lean-entry-closure first exited 3 (dist absent); after building client-react and objectql, both exit 0. eslint, a proven narrowing: the population is the diff's lintable files, 10 (.ts).eslint --no-inline-config --format jsonreturns 10 results, 0 errors, 0 warnings, none ignored. Invariance: eslint.config.mjs never enables type-aware linting (no parserOptions.project, no typed rules; its own comment near line 327), so this diff moves no untouched file's verdict. Fullpnpm lintis CI's. Premise re-checks at origin/main 5757463 (also at 0be8984): (1) readersgit grep -n refreshKey … services drivers rest ':!*.test.ts'→ 0 lines (exit 1), control.publicsame pathspec → 4. (2) the cache/job grep → 3 lines, all the request-scoped label cache (dimension-labels.ts x2, one analytics-service.ts comment);ICacheService|IJobServicealone → 0 (exit 1). Pinned objectui dd3f7e1be3: every refreshKey hit is a React prop, none cube-related. Probe (b3), one-shot, restored with a trap and git diff HEAD empty: adding the retired-key row data/Cube:refreshKey.every then gen:migration-registry then build-schemas --check → exit 1, 'RETIRED_KEYS_BY_MAJOR entr(ies) name a NESTED key this build does not emit: data/Cube:refreshKey.every'. Control: committed tree, check:authorable-surface exit 0. Ablations (all from committed HEAD, via scripts/ablation-replace.mjs with anchor 1→0 and blob moved; trap restore, blob == HEAD and git diff HEAD empty after each; subjects import ./analytics.zod from src, so no dist leg). A: restore the key shape (the strictObject every/sql) in analytics.zod.ts → 9 red: 8 in cube-refresh-key-retirement.test.ts (7 tombstone-door tests including the did-you-mean one, plus the boot-door before/after D2 test) and the batchd REMOVED pin. analytics.test.ts's absence assertion stayed green, as predicted: it checks non-materialization, not refusal. B: restore the showcase authorrefreshKey: { every: '1 hour' }→ tree-scoped absence red naming examples/app-showcase/src/data/analytics/showcase.cube.ts. C: key shape restored + check:test-typecheck → red: 1 new error in cube-refresh-key-retirement.test.ts (the now-unused @ts-expect-error) and 1 in analytics.zod.ts. D: showcase author restored + showcase typecheck → exit 2, TS2322 at showcase.cube.ts(87,3). Expected direction red in all four; observed red.","mcp_calls": "0 — no MCP GitHub tool called; reads used single-card/PR REST GETs with curl.",
"api_writes": "2 — both through the fleet-write relay (repository_dispatch): (1) pr_create → POST /repos/objectstack-ai/objectstack/pulls (draft, run 36625503732, PR 20710, body read back intact); (2) this os-dev-report comment → POST /repos//issues/20637/comments via scripts/pm/post-stamped.mjs. git push (5 pushes of the branch, the empty-branch probe included) is not a REST write. Labels and assignees: 0 writes, per the dispatch.",
"open_questions": [],
"out_of_scope_findings": [
"carrier: the daily platform-checklist watchdog (board-snapshot.yml, kept out of per-PR CI by checklist-status.yml) · noted, not filed —
pnpm check:platform-checklistexits 1 on a tree whose diff to origin/main a8acee2 is disjoint from its inputs (neither input changed through 5757463): ABSENT SYMBOL packages/plugins/plugin-auth/src/auth-plugin.ts#twoFactor cited by docs/qa/platform-checklist/areas/identity-auth.json. The declaring line was folded inline (plugins: { twoFactor: true } as …) by 7d63088 (PR 20429), and the shared resolver reads an inline object-literal key as absent. No public door; dedupe words: platform-checklist twoFactor absent symbol identity-auth","carrier: whoever lands after Version Packages PR 20639 · noted, not filed — if 20639 lands before PR 20710, cube-refresh-key-removed's retiredAfter must move 17.5.0 to 17.6.0 and the changeset row '17.5 and earlier' to '17.6 and earlier' (retired-after.census.test.ts pins the stamp against tarballs once the census is regenerated); dedupe words: retiredAfter cube-refresh-key-removed version packages"
]
}
objectstack-fleet commentedon Sep 29, 2026
Landing record · PR #20710 →
1ab98926b0· 2026-09-29T21:23Zdomain:specseat 5 (session_01Sfe5YjBLwB9J3y8fvm2xq1), holder of this card's claim. This carries out the maintainer's ruling C (5890724395).1ab98926b0, with one parent,679f95ec5c. The PR'sClosesline closed this card.git patch-id --stableas the reviewed heada2abb8c78aagainst its merge base.retiredAfterstamp:cube-refresh-key-removedcarries17.5.0. At landingmain'spackages/specreads17.5.0, and Version Packages PR chore: version packages #20639 is still open, so the stamp is the labelmaincarried at landing. The seat read both again right before enqueue.5898669249.needs:contract-reviewwas stripped on the PR and this card before enqueue.mainnow:analytics_cube.refreshKeyis aretiredKey()tombstone, refused at parse with a migration note.cube-refresh-key-removed(step 18, retired from the load path) strips it from stored cubes.cube-refresh-key-retiredtells upgraders.@objectstack/specminorwith the BREAKING banner, published with the next release.public,refreshKey,format,granularitiesand descriptions take effect (8 keys) #20282 stage 3 (descriptions and the showcasedone_rateformat).pm:dispatchedcomes off in this act.Generated by Claude Code
feat(spec)!: retire an analytics cube's refreshKey — every and sql, r…
docs(spec): four conversion summaries state their decision in words i…