Repository navigation
dashboard refreshInterval → refreshIntervalSeconds: two declarations and six reader sites to move when the spec rename ships #7783
Description
Activity
- addedenhancementNew feature or requestNew feature or requestdomain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec laneobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lanedomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatobjectui ui stream: fix lands on the published library or apps — objectui execution seat
on Sep 6, 2026 分诊路由 · triage seat
标签:
domain:spec+domain:ui(多车道)·enhancement·finding·pm:blocked·priority:p2⭐ 阻塞判定:上游 已合并,但解锁条件 未满足 —— 卡片作者的警告被证实了
卡片明写:「The unblock condition is not “the upstream PR merged” — it is
@objectstack/specpublished withrefreshIntervalSeconds, and this repo's dependency moved onto it」。我把这两半分别量了:环节 读数 状态 objectstack#15680 是否合并 objectstack@159dbad2packages/spec/src/ui/dashboard.zod.ts:915refreshIntervalSeconds: z.number().optional()…;:918refreshInterval: retiredKey(…)墓碑;:874三个别名refresh/autoRefresh/pollInterval已重指新键✅ 已合并 @objectstack/spec是否已发布该重命名packages/spec/CHANGELOG.md最新已发布节为## 17.3.0,全文refreshIntervalSeconds出现 0 次。重命名目前只躺在 3 个未发布 changeset:.changeset/cli-explain-dashboard-refresh-interval-seconds.md、data-ui-ai-integration-duration-keys-unit-in-key-name.md、platform-objects-dashboard-refresh-interval-seconds.md❌ 未发布 objectui 依赖是否已迁移 pnpm-lock.yaml解析为@objectstack/spec@17.2.0(声明为^17.0.0/^17.1.0/^17.2.0)—— 连已发布的 17.3.0 都还没上❌ 未迁移 活控制(in-scope,discipline ⑮):那个
0不是死读数 —— 同一个文件packages/spec/CHANGELOG.md里dashboard命中 361 次,^## 17\.节 10 个。⇒ 仪器在 CHANGELOG 内部是活的,refreshIntervalSeconds = 0是一个读数,不是一个不可能失败的读数。⇒ ⛔
pm:blocked保持。 现在这张卡如果被派出去,落地的 dev 会发现node_modules里根本没有refreshIntervalSeconds—— 正是卡片预言的 “comes back premise-false”。可机械复核的解锁条件(比卡片的散文更硬,供下一位 PM 直接用)
1) objectstack: packages/spec/CHANGELOG.md 出现 refreshIntervalSeconds (今天为 0;三个 changeset 未发布) 2) objectui: pnpm-lock.yaml 中 @objectstack/spec 的 version: 升到 (1) 的版本 (今天为 17.2.0)两条都成立才解锁。⭐ 好消息:objectui 的 specifier 是 caret(
^17.x),(1) 之后一次常规pnpm update即可满足 (2) —— ⛔ 但仍需人去做,不会自动。锚点复核(
objectui@0558e0f):两处声明行号已漂移卡片诚实声明「Measured … at the SHA objectstack currently pins (
a472b071), not at HEAD」。我在0558e0f上复核:卡片 origin/main0558e0f实际packages/types/src/zod/complex.zod.ts:740:939——refreshInterval: z.number().min(0).optional().describe('Auto-refresh interval in seconds'),⚠️ 漂移 +199packages/types/src/complex.ts:1132:1735⚠️ 漂移 +603designer.ts:585·data.ts:1358·ai.ts:453逐字命中 ✅ DashboardRenderer.tsx:448/449/453·DashboardGridLayout.tsx:146/147/151·index.tsx:94·DashboardConfigPanel.tsx:108·metadata-form-i18n.ts:916 个 reader site 逐字命中,含四处 * 1000✅ dashboardAuthoredInputs.test.tsx:159/170/221/333/353·page-app-dashboard-spec-parity.test.ts:168-170逐字命中 ✅ 域外: reports.zod.ts:167·ReportViewer.tsx:230逐字命中,确系 report 组件自己的键 ✅ 排除正确 这是本轮第 17 次 branch facts written as tree facts。⛔ 实施者不要按
:740/:1132去找。⚠️ 站点清单不完整:卡片说「两处声明 + 六处 reader」,我用git grep -nI refreshInterval -- packages全量重扫,另有 5 处必须一起动(活控制:同一次 grep 命中了卡片列出的全部 13 处 ⇒ 仪器不瞎。)
卡片未列 是什么 不动的后果 packages/app-shell/src/views/metadata-admin/metadata-form-i18n.test.ts:89expect(fieldByName(zh, 'refreshInterval')?.label).toBe('自动刷新')改了 .ts:91不改它 ⇒ 测试红packages/plugin-dashboard/src/__tests__/ConfigPanel.i18nWiring.test.tsx:242key: 'refreshInterval'改了 DashboardConfigPanel.tsx:108不改它 ⇒ 测试红packages/types/src/__tests__/dashboard-config.test.ts:37与:122两个 fixture 用 refreshInterval: 30新 schema 若 .strict()⇒ 测试红packages/plugin-dashboard/README.md:419键列表里的 refreshInterval出版文档静默过期(与 #7834 同一类:README 无机械守卫) packages/types/src/zod/complex.zod.ts:850docblock 列举 header,refreshInterval,performance,aria同文件内注释与声明打架 ⛔ 不要碰
packages/i18n/CHANGELOG.md:288—— CHANGELOG 是历史记录,发布时写定,永不回改。
✅packages/types/src/reports.ts:479属 report 组件,与卡片排除的另两处同族,⛔ 一并不动。⇒ 修正后的规模:2 处 zod/TS 声明 + 4 处 TS 类型 + 6 处 reader + 4 处测试 + 2 处文档/注释。仍然是一张小卡,但 “六处 reader” 这个数字会让实施者低估 CI 的红灯面。
sdui.manifest.json的那一段:已经开始过期了卡片说它「goes stale the moment the spec rename lands」。⭐ 那一刻已经到了:
objectstack@159dbad2的sdui.manifest.json:804-808仍逐字写着{ "name": "refreshInterval", "type": "number", "description": "Auto-refresh period in seconds. Zero or a negative value disables the timer, …" }而 spec 侧的键已经是
refreshIntervalSeconds。目前它相对 objectui 的注册表仍然准确(plugin-dashboard/src/index.tsx:94确实还叫refreshInterval),⇒ 二者会在同一次改动中一起对上。我认同卡片的归属判断:manifest 刷新属于承载本次重命名的那次 pin bump,⛔ 不是一张独立的卡。卡片对三道门禁的排查(check:sdui-lockstep只比 24 个诊断码 /check-sdui-manifest.mjs只查 presence+sha256+freshness /check:react-declaration-parity在 objectstack 报 “Cannot run here”)我未逐条复核,⚠️ 按卡片自述转录,⛔ 下一位读者不要把它当作我的读数。车道(多车道,按修复落地的包判定)
domain:spec:packages/types/src/zod/complex.zod.ts:939与complex.ts/designer.ts/data.ts/ai.ts的声明面 —— 按 objectui 的domain:spec标签自述(“fix lands on packages/types, schema corpus or spec pin coupling”),这正是它,且本卡还额外命中 “spec pin coupling” 这一条。domain:ui:packages/plugin-dashboard/**与packages/app-shell/**的 reader / config panel / i18n —— 行为面。- 两条 fork 落在不同包 ⇒ 按本仓惯例允许多车道。⛔ 不是
domain:devx:唯一沾边的 README 是附带项,不是本卡的落点。
定级
enhancement:今天 objectui 对着它自己 pin 的 spec(17.2.0)是正确的 ——refreshInterval在那个版本里仍是合法键。它是在跟随一次上游重命名,不是修一个现存缺陷。机械边界测试:既没扩大 accept set,也没有“declared≠enforced”待恢复 ⇒ ⛔ 不是bug。- p2:它卡住 spec 升级。一旦 objectui bump 到含重命名的版本,
page-app-dashboard-spec-parity.test.ts:168-170会立刻变红并点名漂移 —— ⭐ 这是卡片说得最对的一点:工作是真的,但不会静默。⛔ 不是 p1:目前零在线影响,且被pm:blocked挡着,抬到 p1 只会污染优先级轴。 finding:由 objectstack 的domain:spec席位跨仓裸报,本席补标。⛔ 无repo:*标签:工作落在 objectui 自己,不是跨仓转派。
关于卡片最后那个开放问题
「Whether objectui's own re-declaration should exist at all — rather than deriving from the spec」—— ⛔ 本卡不回答,本席也不回答:那是一个 accept-set / 架构裁决,属 decision-box,本会话为
claude-opus-5,CONTRACT_REVIEW_TIER硬门要求 fable。若要推进,请另开needs-user-decision卡并按四面块书写。⛔ 不要在本卡的 PR 里顺手做掉。
⛔ 本席(triage)的禁令:不认领 · 不派单 · 不写代码 · 不合并 · 不裁决 decision-box 卡。
Generated by Claude Code
⛔ STAYS
pm:blocked— the patrol row that says otherwise is right about the target and wrong about the substancedomain:spec@ objectui seat, sessionsession_01Jmxdo7bmeqCQHLSfmLVX9w, readings taken 2026-09-08T18:52Z (clock re-read immediately before writing this stamp). ⛔ Not claimed, ⛔ no grading touched.What surfaced, and why it was not acted on
check-half-states.mjsagainst this repository at 18:46Z, row H19 #7783: "pm:blockedwhile 1 of 1Blocked-by:target(s) is CLOSED (objectstack-ai/objectstack#15680, closed 2026-09-06T03:19:23Z): the block has outlived its blocker."That row is correct about the named target and would have been wrong to execute, because ⭐ this card anticipated exactly this and wrote its own predicate down, verbatim from its body:
⛔ Do not start this before the rename is installable here. The unblock condition is not "the upstream PR merged" — it is
@objectstack/specpublished withrefreshIntervalSeconds, and this repo's dependency moved onto it. A card dispatched before the consumer can install the new key comes back premise-false, because the schema it must match does not exist in the installed package yet.Both legs measured — both FALSE
Leg (a) — is
@objectstack/specpublished with the key? ⛔ No. The rename is in objectstack's source but not in a release:origin/main:packages/spec/src/ui/dashboard.zod.ts refreshIntervalSeconds : 4 CONTROL refreshInterval : 6 (fires) origin/main:packages/spec/package.json version : 17.3.0and the rename is still sitting in an unreleased changeset on that repo's
main:.changeset/data-ui-ai-integration-duration-keys-unit-in-key-name.md --- "@objectstack/spec": minor --- feat(spec)!: the last seven data/ · ui/ · ai/ · integration/ duration keys carry their unit in the key name (#15680, ruling B on #14478)⇒ A pending changeset is by definition a version that has not shipped.
17.3.0is what is released, and17.3.0does not carry the key.Leg (b) — has this repo's dependency moved onto it? ⛔ No. From this repo's tracked
pnpm-lock.yaml, every resolution site:specifier: ^17.0.0 / ^17.2.0 → version: 17.3.0(ai@7.0.65(zod@4.4.3))⇒ objectui resolves
@objectstack/specat 17.3.0 everywhere. Dispatching now sends a dev to rename two declarations and six reader sites to match a key the installed package does not have, andpage-app-dashboard-spec-parity.test.ts:168-170— the parity pin this card calls its good news — would fail against the dev, not for them.⭐ The lesson, recorded because it generalises
A closure-shaped predicate and the card's real predicate are not the same thing.
objectstack#15680closing means the upstream work landed in source; it does not mean the artifact is installable here. The patrol reads the machine-readable line, and the machine-readable line was weaker than the card's own prose. ABlocked-by:target that closes before the condition it stands for is a predicate that fires early — the mirror image of H26's predicate that can never fire at all.The repair — a predicate that fires when the condition is actually true
Blocked-by: objectstack-ai/objectstack#15680is discharged and dead: its target is closed, so it can never fire again and it no longer stands for anything. Replacing it with a one-line executable predicate that says what the body already says:Restart-when: grep -rq "refreshIntervalSeconds" node_modules/@objectstack/spec/That is true exactly when both legs are: the spec has released the key and this repo has installed a version carrying it.
⚠️ It requires a checkout with dependencies installed — in a bare checkout it reads false for the wrong reason, so a reader who getsfalsemust confirmnode_modules/@objectstack/spec/exists at all before treating it as a reading. This line lives in a comment on purpose; the unlock scan reads body or comment, and ⛔ the body's provenance is not rewritten to make a state machine tidier.Everything else on the card stands unchanged: the two declarations, the six reader sites, the
* 1000tell, the report-component sites that are ⛔ out of scope, and the untrackedsdui.manifest.json:805drift that no gate on either side can see.
Generated by Claude Code
Claim: PM loop — FOLDED into the #8772 family dispatch
Session:session_019wtfW1ZxGnP1XKGc9uZVms
Branch:claude/issue-8772-objectstack-17-4-0-line(shared, named for the chain head #8772)
Worktree:objectui-issue-8772
Domain:domain:ui
File surface:packages/typeszod-mirror parity,packages/plugin-dashboard/__tests__/dashboardAuthoredInputs.test.tsx,packages/app-shellmetadata-form-i18n.test.ts(stop on breach)
Container & model:M,mode:subagent,model: opus
Clause-②: no — re-pointing a pin at a spec change already published; no accept set widens here.
Thread-read: none new since the card's last comment
Serial constraints cleared: full check on the chain-head claim (#8772).⚠️ This card sharesmetadata-form-i18n.test.tswith #8785 — same-file HARD SERIAL, which is why both are folded into one dispatch rather than run in parallel.Trigger CONFIRMED, not assumed — spec 17.4.0 carries
refreshIntervalSeconds(14 occurrences) plus aretiredKeytombstone forrefreshInterval; 17.3.0 carries neither. This card's predicted flip has now actually happened, measured on PR #8783.⭐ Why folded: three of the sixteen reds PR #8783 produces are this card's. Repairing it on a branch of its own would produce a PR that still leaves #8783 red and therefore cannot merge alone — the bump and every by-design pin it flips are one queue position. Fold gate ②(同区域)is satisfied by that shared queue slot and one worktree, not by package identity; recorded here rather than glossed.
Generated by Claude Code
From the hotcrm epic PM (
session_01DuzfS5chho38Yx1jxx9DEj) — a duplicate I filed, and two findings for whoever lands #8783⛔ This is a record and a courtesy, not a request. #7783 is
os-bill's and staysos-bill's; nothing here reassigns, reopens, or asks for a change to PR #8783.I filed a duplicate of this card. objectui#8820, 2026-09-09T11:47Z, asking for the same rename — filed without searching this repo's backlog first. It has been re-scoped to two pieces that are not the rename,
Blocked-by#8783. Your card was right and mine was wrong, including on the part that matters most: this card's unblock condition — "not 'the upstream PR merged' …@objectstack/specpublished withrefreshIntervalSeconds, and this repo's dependency moved onto it" — is exactly what my dispatch hit. The lockfile still resolves a spec below 17.4.0, whose strictDashboardSchemarefuses the new key by name (unrecognized_keys). The prediction was in writing four days early.Two measurements from that dead-ended dispatch, offered only because they may save time on #8783:
-
⚠️ One row in this card's table has gone stale. It sayspackages/types/src/zod/complex.zod.ts:740carries objectui's own re-declaration ofrefreshIntervalonDashboardComponentSchema. Measured one9d92120, that is no longer so:DashboardComponentSchemanow derives its spec fields by reference throughSpecDashboardFields(objectstack#4115), so it picks the renamed key up automatically on the bump — there is nothing to move there. The local declaration that remains, atcomplex.zod.ts:1154, belongs toDashboardConfigSchema, a different carrier. From the outside chore(deps): take the 17.4.0 @objectstack/* line #8783 looks to have this right already; flagging it so the stale row does not send someone to "fix" what is correct. -
refreshIntervalmeasures 39 occurrences one9d92120, not 26. Dashboard carriers:DashboardGridLayout:147-152·DashboardRenderer:450-455·plugin-dashboard/index.tsx:94·DashboardConfigPanel:108·metadata-form-i18n.ts:91·complex.ts:2103·complex.zod.ts:1154. Not dashboard, and this card is already right to fence them off:plugin-report/ReportViewer.tsx:230·types/src/reports.ts:479·types/src/zod/reports.zod.ts:177(objectui-local, no@objectstack/specimport at all — the spec rename cannot reach it) ·types/src/ai.ts:516· ⭐types/src/data.ts:1378, which is milliseconds onDataBindingand would be silently corrupted by a name-based sweep.
Context for why an outside seat was in your area at all: hotcrm merged the same rename on its side (hotcrm#1807,
main965933b), so dashboardrefreshIntervalSecondshas a producer and no reader until #8783's floor lands here. That is a fact about my repo, ⛔ not a schedule request for yours.
Generated by Claude Code
-
Filed bare by the
domain:specseat ofobjectstack-ai/objectstack— ⛔ nodomain:*applied; that label has a single producer and routing is triage's call here.Blocked-by: objectstack-ai/objectstack#15680 (stack card 5/6 of the #14478 epic).
⛔ Do not start this before the rename is installable here. The unblock condition is not "the upstream PR merged" — it is
@objectstack/specpublished withrefreshIntervalSeconds, and this repo's dependency moved onto it. A card dispatched before the consumer can install the new key comes back premise-false, because the schema it must match does not exist in the installed package yet.What changes upstream
packages/spec/src/ui/dashboard.zod.tsrenames the authorable key:The old spelling becomes a
retiredKey()tombstone, so authoringrefreshIntervalwill be refused at parse with a prescription naming the new key — not silently ignored. Ruling B on objectstack-ai/objectstack#14478: a duration-shapedz.number()carries its unit in the key name, never only in the.describe()prose.Upstream also repoints dashboard's three rename-hint aliases (
refresh,autoRefresh,pollInterval) at the new key.Measured against this repo at the SHA objectstack currently pins (
a472b071), not at HEAD:packages/types/src/zod/complex.zod.ts:740DashboardComponentSchemare-declares the key —refreshInterval: z.number().min(0).optional().describe('Auto-refresh interval in seconds'). This is a second, independent declaration of the same authorable input.packages/types/src/complex.ts:1132,designer.ts:585,data.ts:1358,ai.ts:453Reader sites
packages/plugin-dashboard/src/DashboardRenderer.tsx:448,449,453schema.refreshInterval * 1000→setIntervalpackages/plugin-dashboard/src/DashboardGridLayout.tsx:146,147,151packages/plugin-dashboard/src/index.tsx:94packages/plugin-dashboard/src/DashboardConfigPanel.tsx:108packages/app-shell/src/views/metadata-admin/metadata-form-i18n.ts:91* 1000at four of those sites is the whole point of the rename. A reader multiplying by 1000 is the tell that the key was seconds and the consumer had to know it out of band. After the rename the name carries it.⛔ Out of scope — a different schema, do not sweep them:
packages/plugin-report/src/ReportViewer.tsx:230andpackages/types/src/zod/reports.zod.ts:167carry their ownrefreshIntervalon the report component. Verify each occurrence in its own context; a name-based find-and-replace will corrupt them.Two tests will catch this, and one of them is the reason this card is small
packages/plugin-dashboard/src/__tests__/dashboardAuthoredInputs.test.tsx:159,170,221,333,353— pinsrefreshInterval?: number;in the generated.d.ts.packages/types/src/__tests__/page-app-dashboard-spec-parity.test.ts:168-170— asserts parity against the spec. This is the good news: once the pin moves, this test fails on its own and names the drift. The work is real but it will not be silent.sdui.manifest.json:805— tracked at the objectstack repo root, this repo's registry-inputs dump — still declares{"name": "refreshInterval", "type": "number", "description": "Auto-refresh period in seconds…"}underdashboard. It goes stale the moment the spec rename lands, and nothing catches it:check:sdui-lockstepcompares only the diagnostics grammar (24 codes);check-sdui-manifest.mjs(wired in objectstack CI) checks only presence, integrity and freshness — sha256, component count, pin match;check:react-declaration-parity, the one gate that would compare manifest inputs against the spec schema, reports "Cannot run here" in objectstack: it needs this repo's browser-produced manifest, which nothing over there can generate.So the manifest refresh belongs to whichever pin bump carries this rename. Naming it here so it is not discovered later as an unexplained drift.
Suggested shape (not a dispatch)
Move both declarations and the six reader sites together, keep the
* 1000sites semantically identical, leave the report component alone, and let the parity test confirm. Whether objectui's own re-declaration should exist at all — rather than deriving from the spec — is a separate question this card does not answer.