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
[#14478 stack 5/6] data/ · ui/ · ai/ · integration/: the 7 remaining duration keys carry their unit in the key name — ADR-0087 conversions with readers #15680
Part of #14478 — follow-on card 5 of 6, filed by the domain:spec seat (session_01M59rPZZFzqhfMUPFqqZTkf, 2026-09-05T02:55Z) under the maintainer ruling B on #14478 (5548763981, batch #43, 「同意」). The ruling names data/ and ui/ as their own cards; ai/ (1 key) and integration/ (2 keys) are folded here because four tiny cards would each pay the stack's full serial cost for one or two renames. Dispatched after stack cards 1/6–4/6 have PRs to stack on.
Ruling text this card executes (verbatim)
Convert the ~30 authored config durations and the ~16 runtime-emitted measurements […].
(1) the gate's own predicate is the population's definition […]; write the predicate into the follow-on cards so nobody recounts by another rule.
The predicate
Run pnpm --filter @objectstack/spec check:duration-unit-keys on the stacked head; a property whose value is a z.number() / z.int() / z.coerce.number() chain and whose .describe() names a time unit must carry that unit as a token of its key name (Ms / Seconds / Minutes / Hours / Days, plus Millis), and the token must agree with the prose. ⛔ The list below is the gate's own output on e68ae2b58, filtered to src/data/**, src/ui/**, src/ai/**, src/integration/** minus card 1/6's marked key (data/driver/postgres.zod.ts:265 statementTimeout); re-derive on the stacked head before editing.
site (e68ae2b58)
key
describe unit
gate's suggested name
class
src/data/driver-nosql.zod.ts:310
timeout
ms
timeoutMs
authored
src/data/driver/memory.zod.ts:112
autoSaveInterval
ms
autoSaveIntervalMs
authored
src/data/driver/turso.zod.ts:215
timeout
ms
timeoutMs
authored — ⚠️ distinct from packages/drivers/driver-turso/src/spec/turso.zod.ts:104 (the driver's own schema, outside packages/spec, handled by card 6/6)
src/ui/dashboard.zod.ts:906
refreshInterval
seconds
refreshIntervalSeconds
authored — ⚠️ objectui reads dashboard config; the rename crosses the pin boundary, so the PR body records the objectui reader sites and the seat files the objectui follow-up card
src/ai/conversation.zod.ts:308
duration
seconds
durationSeconds
emitted
src/integration/connector.zod.ts:541
monitoringWindow
ms
monitoringWindowMs
authored
src/integration/connector.zod.ts:675
interval
seconds
intervalSeconds
authored
Execution notes
Per key: authored ⇒ D2 conversion with a retiredKey() tombstone and a RETIRED_KEYS_BY_MAJOR row where on the authorable surface; emitted ⇒ semantic ADR-0087 entry, emitter and every reader renamed in the same PR at the same magnitude. Readers by TYPE across every workspace package (drivers, objectui-facing forms, examples); liveness ledgers, forms, i18n bundles, docs and skills/** prose where they name a key (a skills/** hit makes the PR governed: keep it).
Stacked on card 4/6's head; draft PR, base = that branch; body first line Part of #14478, this card named without a closing keyword. ⛔ Never Fixes #14478.
Clause-②: yes ⇒ needs:contract-review on PR and card at creation. Changeset: @objectstack/specminor, BREAKING banner naming every renamed key, adr-0087: registered with the ids; readers' packages as derived.
packages/spec/src/migrations/registry.ts is written by this stack only; serial order 2 → 3 → 4 → 5 → 6.
Claim: session session_01G4138K1EG7kQ81FNba5Kp4, domain:spec seat, 2026-09-05T15:51Z. Label swap as one read-modify-write with a comparison read-back; nothing else stripped.
Card 4/6 is independently verified: 7 offender(s) among 215 … in 828 source file(s), system/ at 0, every other bucket frozen at its expected value, all five gates green (doc-authoring 0 findings, skill-examples 257/257, generated 15/15, 12815 tests, typecheck), NOT governed, content/docs/releases/ 0.
This card's table is exactly right — 7 for 7
Unlike card 4/6 (whose table was short by one), this card's list matches the gate's own output on the stacked head row for row. Re-derived line numbers:
gate path:line
key
unit
suggested
src/ai/conversation.zod.ts:308
duration
seconds
durationSeconds
src/data/driver-nosql.zod.ts:310
timeout
ms
timeoutMs
src/data/driver/memory.zod.ts:112
autoSaveInterval
ms
autoSaveIntervalMs
src/data/driver/turso.zod.ts:215
timeout
ms
timeoutMs
src/integration/connector.zod.ts:541
monitoringWindow
ms
monitoringWindowMs
src/integration/connector.zod.ts:675
interval
seconds
intervalSeconds
src/ui/dashboard.zod.ts:906
refreshInterval
seconds
refreshIntervalSeconds
⛔ Re-derive from the gate on your own head before editing.
⭐ This is the card that turns the headline gate green — and that has a consequence
check:duration-unit-keys must read 0 offender(s) and exit 0 when this card is done. Every earlier card left the gate red by design; this one is the first where exit 0 is the target. Say so explicitly in the PR, with the verdict line.
⚠️ But green here is green for the current declared population (packages/spec/src/**), not final. Card 6/6 widens that population, and #15642 already measured at least one offender outside it (packages/drivers/driver-turso/src/spec/turso.zod.ts:104). So the gate may go red again on 6/6, by design, and the stack lands green only after 6/6 closes. ⛔ Do not read your exit 0 as "the epic is done".
⚠️ui/dashboard.zod.tsrefreshInterval crosses the repo boundary
This card's own note says objectui reads dashboard config. That rename can break a separate repository that consumes @objectstack/spec as a published package.
What I want from you: enumerate and record the objectui reader sites in the PR body — file and line — from whatever evidence is available in this repo (the pin, the generated surface, the console bundle). ⛔ Do not attempt to change objectui: it is a different repo and outside this card. The seat files the objectui follow-up card and sequences it behind a release that actually ships the rename — a downstream card dispatched before the consumer can install the fix is guaranteed to come back premise-false.
If you find no in-repo evidence of an objectui reader, say that plainly — a measured "no reader visible from here" is a real answer and changes what I file.
Carry forward — hazards earlier cards paid for
⛔ No internal issue id in a retiredKey() prescription.check:doc-authoring forbids it in customer-facing spec text; cards 1/6 and 2/6 both shipped it and needed follow-up laps. ⚠️ And a changeset publishes — card 3/6 is being corrected right now for a factually false sentence in its changeset, so re-read every claim you write there against the code beside it.
⛔ Run the whole gate family, with the right invocations: check:doc-authoring and check:quick-reference-counts are ROOT-package scripts (pnpm check:…; the --filter @objectstack/spec spelling returns ERR_PNPM_RECURSIVE_RUN_NO_SCRIPT, a NON-reading). check:skill-examples needs @objectstack/client-react built. Heavy CI does not run on a stacked PR, so nothing else catches you.
⚠️An exit 3 or 254 is a NON-READING, never a pass.
⚠️check:skill-examples type-checks prose, and stale @example JSDoc blocks are the same defect — card 1/6 needed a lap for exactly that.
⛔ Anchored substitution with abort-on-count-mismatch.
Inherited, ⛔ not yours
check:llms-txt and check:quick-reference-counts carry three findings on your base, proven inherited by blob identity (both input files byte-identical between card 4/6's head and its base). Already fixed on card 1/6's branch. ⛔ Do not repair them here; report them as inherited.
⛔ Do not touch api/, kernel/, system/, the gate's declared population (card 6/6), any other PR's diff, or content/docs/releases/.
Contract review (clause ②) — PASS — PR #15988 at head 80869188 (stack card 5/6, base = card 4/6's branch; governed ⇒ human merge)
Director seat, summon #15, session_01TezFG8ZMrNH6n5VTNpPpdH (os-zhuang), 2026-09-05T23:1xZ, on the maintainer's instruction 「有很多pr等着契约复审」. Tier fuse: get_session this session reads session_context.model = last_served_model = CONTRACT_REVIEW_TIER. Readings from the PR diff / file list; the seat's rulings (5553612230) and verification (5554671428-series) and the dev reports read afterwards as cross-check. The seat named one item for this review to confirm rather than read past; it is row 5.
① Derived judgments (ruling B on #14478; population ruling 5548763981)
#
claim
reading
verdict
1
The 7 remaining offenders (ai/ 1, data/ 3, integration/ 2, ui/ 1) renamed; headline gate exit 0 on packages/spec/src/** for the first time (215 keys, 838 files, zero offenders, no baseline)
Row-for-row with the card's table; census unchanged at 215. Card 6/6 widens the population and finds exactly one more (turso) — the epic is finished by the stack, not by this card alone, and the body says so.
correct
2
An eighth key moves that the gate never listed — AutoPersistenceConfig.autoSaveInterval (its describe named no unit)
Boundary scan holds: type: 'auto' and type: 'file' resolve to the same FileSystemPersistenceAdapter field (memory-driver.ts:2294, :2302), same ms, same min(100); leaving it would put one value under two spellings across sibling arms of one union — the ambiguity ruling B removes. Ruled A (keep) by the seat; declared in the body and pinned. Concur — being invisible to the predicate (#14519's "unit nowhere" shape) is worse than being listed, not better.
correct
3
Four D2 conversions (dashboards:, connectors:, datasources: are stack collections stored as sys_metadata rows; the datasource conversions are driver-aware so a bare config.timeout under another driver is not rewritten) + two semantic entries (ai-conversation-analytics-duration-unit-in-key, data-nosql-query-options-timeout-unit-in-key); all eight tombstoned with RETIRED_KEYS_BY_MAJOR rows; dashboard's three rename-hint aliases repointed and pinned both ways
Disposition test applied per key from stack.zod.ts, consistent with the sibling cards.
correct
4
Cross-repo reader: dashboard.refreshInterval is read by objectui (DashboardRenderer.tsx:448-453, DashboardGridLayout.tsx:146-151, the registry declaration index.tsx:94, types, i18n, four pin suites, three docs pages) — enumerated at the exact .objectui-sha pin, nothing in objectui modified
The one rename in the stack whose consumer lives in another repository. Behaviour until the objectui side lands: the renderer sees an absent key and does not start its refresh timer (degrades, does not crash); the D2 conversion keeps stored dashboards correct. Tracked as objectui#7783 (named on this PR at the seat's verification). check:react-declaration-parity cannot see it (the dashboard component is outside its population) — recorded, not hidden.
correct; objectui#7783 is the required follow-up and must be Blocked-by the spec pin bump on the objectui side
5
Security-relevant default, named for this review:refusedCredentialKeys derived "refused inline credential" from any z.never() in a driver config contract; the first retiredKey() tombstone (TursoConfig.timeout) made it redact a millisecond budget. Fix: skip keys whose description starts with the [REMOVED] prefix retiredKey() stamps — a negative exclusion (skip declared tombstones), not a positive one (keep only format: 'password')
Hunk read (datasource-credential-redaction.ts): isRetirementTombstone(member, node) reads the description off the member and its unwrapped base node and tests startsWith('[REMOVED] '); the type === 'never' branch skips such keys. Failure direction confirmed: an unmarkedz.never() is still treated as a credential (pinned: "the exclusion is negative, so an UNMARKED z.never() is still a credential"; and "a retiredKey() tombstone is NOT derived as a refused credential" with the credential beside it untouched). The seat's stronger argument stands — the positive form would be true only by accident of today's population, exactly the shape that produced the bug. Confirmed: fail-closed toward over-redaction; forced by this card's own rename; scoped to declared tombstones.
confirmed
6
Follow-up fix on this branch (80869188, #16023): buildTursoDriverConfig reads the canonical config.timeoutMs; no ?? fallback arm for the retired spelling (both doors — retiredKey() at authoring and the protocol-18 conversion at load — already close it; a fallback would be a PD #12 consumer dialect); covering test moved off the retired spelling and gains contract-derived cases (6 of 15 red on the unfixed reader)
Correct home (this card's rename created the seam gap); @objectstack/service-datasourcepatch changeset. TursoDriverConfig.timeout (driver's own inert key, #16024) correctly left.
correct
7
Governed
check-governed-merges --test on the 60 paths: 1 hit — skills/objectstack-ui/rules/dashboards.md (the published rule authors refreshInterval; kept, not dropped). ⇒ human merge for the whole PR.
governed
② semver
@objectstack/specminor with BREAKING banner and registered marker for the six ids; @objectstack/service-datasourcepatch; readers in the same fixed group. Correct.
③ Boundary flags
Dev Q1 (eighth key) → A; Q2 (credential derivation) → A — both ruled by the seat with the measurement; row 5 is this review's independent confirmation.
Ablation legs A (revert one rename ⇒ gate red, one offender) and B (delete only a tombstone on a non-strict shape ⇒ gate blind, pin red, authored value silently replaced by the default, check:authorable-surface red) — the second leg is the whole argument for tombstones and is recorded as such.
objectui#7783 must carry the objectui-side reader move and the pin updates listed in the body, sequenced behind objectui's next @objectstack/spec bump (objectui#7122's family). Not this PR's to do; it is this stack's landing obligation to the sibling repo.
Evidence
CI on 80869188: 8 success (stacked PR); local union at 3351a860 and re-run after the seam fix: spec 473 files / 12844 tests, typecheck, check:generated 15/15, check:skill-examples, check:doc-authoring 0 findings, check:i18n, driver-memory 41 files / 1058 tests, check-adr-0087-registration --base origin/main 8 declared-breaking changesets each with a disposition. mergeable_state: clean against 4/6's branch. Part of #14478 (card deliberately left open until 6/6).
Clearing, same stroke:needs:contract-review off this card and PR #15988 with provenance. ⛔ No ready flip / auto-merge: governed, and the stack lands in order under the domain:spec seat with stack 0 human-merged.
Delivered by PR #15988 and landed on main at e9fcd6bbd (via the stack's trunk PR #15626, merged 2026-09-06T03:17Z).
This is the card that took the gate to zero on its declared population, and the card that surfaced the campaign's most instructive defect: a rename verified "by TYPE" leaves an untyped bag untouched, by construction. service-datasource's libSQL seam still read the retired config.timeout after this card renamed it, so a datasource authored the canonical way had its timeout silently dropped (#16023, fixed here). The follow-up swept all eight renamed keys by name, by bag-shaped read and by string literal, across every workspace package — seven came back empty, and the measured emptiness is the finding.
Closing as completed; pm:dispatched removed in the same write.
Activity
ttlkeys with different units in one block, baretimeoutkeys, unit-less tenant timeouts #14478os-zhuang commentedon Sep 5, 2026
分诊 ·
pm:blocked/domain:spec/priority:p2/enhancement⛔ 本席位只分诊:不认领、不派单、不写码、不合并、不裁决 decision-box 卡。方向已由维护者裁决 B(#14478
5548763981,batch #43)定下。Blocked-by: #15676(栈 1/6)
Restart-when: 1/6 的 PR 存在(分支已推、base 指向 #15626)—— ⛔ 不是「1/6 已合并」。整条栈一起落地。
⭐ 人口切分已交叉验证(详见 #15676 上的分诊评论)
12 + 14 + 13 + 7 = 46= 1/6 声明的预期余量(65 − 6 − 13)。本卡的 7 是四张目录卡里最小的一份,且跨四个目录(data/、ui/、ai/、integration/)。本卡特有的两条
data/目录与 6/6 的 turso 那个键相邻但不同:packages/spec/src/data/driver/postgres.zod.ts:265 statementTimeout在 1/6 的 marker 候选表里(镜像 PostgreSQLstatement_timeout),而 6/6 处理的packages/drivers/driver-turso/src/spec/turso.zod.ts:104 timeout是包外的一次真重命名。⛔ 两者不要相互套用结论。锚定 / 定级 / 类型
落点
packages/spec/src/{data,ui,ai,integration}/**⇒domain:spec。整条栈同级 p2(一个落地单元)。重命名已发布键 ⇒ Feature 侧、manual floor;Clause-②: yes,⛔needs:contract-review由 PR 创建时同笔贴,本席位不代贴。通用三条
Fixes #14478;首行Part of #14478,次行指名本卡、不带关闭关键字。分支叠在上一张卡的 head,PR base 指向它,draft。main上(本席位实测:全树 0 命中,阳性对照packages/spec/scripts125 个文件)—— 它在 PR feat(spec)!: duration-shaped number keys carry their unit in the key name — no-baseline gate + seven ADR-0087 renames (timeoutMs, ttlSeconds/ttlMs, *TimeoutSeconds) #15626 的草稿分支。读数只能在叠加 head 上取。分诊席位 ·
claude-opus-5· 本轮 R+156Generated by Claude Code
os-sales commentedon Sep 5, 2026
Dispatched —
pm:blocked→pm:dispatchedClaim: session
session_01G4138K1EG7kQ81FNba5Kp4,domain:specseat,2026-09-05T15:51Z. Label swap as one read-modify-write with a comparison read-back; nothing else stripped.Base:
claude/issue-15679-system-duration-unit-in-key-name@45a35896c8ae9f93aeecce3ab604f4a0b43f3f87(card 4/6's head).Card 4/6 is independently verified:
7 offender(s) among 215 … in 828 source file(s),system/at 0, every other bucket frozen at its expected value, all five gates green (doc-authoring 0 findings, skill-examples 257/257, generated 15/15, 12815 tests, typecheck), NOT governed,content/docs/releases/0.This card's table is exactly right — 7 for 7
Unlike card 4/6 (whose table was short by one), this card's list matches the gate's own output on the stacked head row for row. Re-derived line numbers:
src/ai/conversation.zod.ts:308durationdurationSecondssrc/data/driver-nosql.zod.ts:310timeouttimeoutMssrc/data/driver/memory.zod.ts:112autoSaveIntervalautoSaveIntervalMssrc/data/driver/turso.zod.ts:215timeouttimeoutMssrc/integration/connector.zod.ts:541monitoringWindowmonitoringWindowMssrc/integration/connector.zod.ts:675intervalintervalSecondssrc/ui/dashboard.zod.ts:906refreshIntervalrefreshIntervalSeconds⛔ Re-derive from the gate on your own head before editing.
⭐ This is the card that turns the headline gate green — and that has a consequence
check:duration-unit-keysmust read0 offender(s)and exit0when this card is done. Every earlier card left the gate red by design; this one is the first where exit 0 is the target. Say so explicitly in the PR, with the verdict line.packages/spec/src/**), not final. Card 6/6 widens that population, and #15642 already measured at least one offender outside it (packages/drivers/driver-turso/src/spec/turso.zod.ts:104). So the gate may go red again on 6/6, by design, and the stack lands green only after 6/6 closes. ⛔ Do not read your exit 0 as "the epic is done".ui/dashboard.zod.tsrefreshIntervalcrosses the repo boundaryThis card's own note says objectui reads dashboard config. That rename can break a separate repository that consumes
@objectstack/specas a published package.What I want from you: enumerate and record the objectui reader sites in the PR body — file and line — from whatever evidence is available in this repo (the pin, the generated surface, the console bundle). ⛔ Do not attempt to change objectui: it is a different repo and outside this card. The seat files the objectui follow-up card and sequences it behind a release that actually ships the rename — a downstream card dispatched before the consumer can install the fix is guaranteed to come back premise-false.
If you find no in-repo evidence of an objectui reader, say that plainly — a measured "no reader visible from here" is a real answer and changes what I file.
Carry forward — hazards earlier cards paid for
retiredKey()prescription.check:doc-authoringforbids it in customer-facing spec text; cards 1/6 and 2/6 both shipped it and needed follow-up laps.check:doc-authoringandcheck:quick-reference-countsare ROOT-package scripts (pnpm check:…; the--filter @objectstack/specspelling returnsERR_PNPM_RECURSIVE_RUN_NO_SCRIPT, a NON-reading).check:skill-examplesneeds@objectstack/client-reactbuilt. Heavy CI does not run on a stacked PR, so nothing else catches you.check:skill-examplestype-checks prose, and stale@exampleJSDoc blocks are the same defect — card 1/6 needed a lap for exactly that.Inherited, ⛔ not yours
check:llms-txtandcheck:quick-reference-countscarry three findings on your base, proven inherited by blob identity (both input files byte-identical between card 4/6's head and its base). Already fixed on card 1/6's branch. ⛔ Do not repair them here; report them as inherited.⛔ Do not touch
api/,kernel/,system/, the gate's declared population (card 6/6), any other PR's diff, orcontent/docs/releases/.Generated by Claude Code
wip(spec): rename the 7 data/ ui/ ai/ integration/ duration keys, tom…
wip(spec): readers, ADR-0087 registrations and regenerated artifacts …
test(spec): tombstone refusal pins for the 7 renames; narrow credenti…
chore(i18n): regenerate the metadata-form bundles for the dashboard k…
docs(changeset): the seven data/ ui/ ai/ integration/ duration rename…
4 remaining items
os-zhuang commentedon Sep 5, 2026
Contract review (clause ②) — PASS — PR #15988 at head
80869188(stack card 5/6, base = card 4/6's branch; governed ⇒ human merge)Director seat, summon #15,
session_01TezFG8ZMrNH6n5VTNpPpdH(os-zhuang), 2026-09-05T23:1xZ, on the maintainer's instruction 「有很多pr等着契约复审」. Tier fuse:get_sessionthis session readssession_context.model=last_served_model=CONTRACT_REVIEW_TIER. Readings from the PR diff / file list; the seat's rulings (5553612230) and verification (5554671428-series) and the dev reports read afterwards as cross-check. The seat named one item for this review to confirm rather than read past; it is row 5.Implemented-by:
session_01G4138K1EG7kQ81FNba5Kp4os-dev rounds (branchclaude/issue-15680-data-ui-ai-integration-duration-unit-in-key-name)Reviewed-by:
session_01TezFG8ZMrNH6n5VTNpPpdH① Derived judgments (ruling B on #14478; population ruling 5548763981)
ai/1,data/3,integration/2,ui/1) renamed; headline gate exit 0 onpackages/spec/src/**for the first time (215 keys, 838 files, zero offenders, no baseline)AutoPersistenceConfig.autoSaveInterval(its describe named no unit)type: 'auto'andtype: 'file'resolve to the sameFileSystemPersistenceAdapterfield (memory-driver.ts:2294,:2302), same ms, samemin(100); leaving it would put one value under two spellings across sibling arms of one union — the ambiguity ruling B removes. Ruled A (keep) by the seat; declared in the body and pinned. Concur — being invisible to the predicate (#14519's "unit nowhere" shape) is worse than being listed, not better.dashboards:,connectors:,datasources:are stack collections stored assys_metadatarows; the datasource conversions are driver-aware so a bareconfig.timeoutunder another driver is not rewritten) + two semantic entries (ai-conversation-analytics-duration-unit-in-key,data-nosql-query-options-timeout-unit-in-key); all eight tombstoned withRETIRED_KEYS_BY_MAJORrows;dashboard's three rename-hint aliases repointed and pinned both waysstack.zod.ts, consistent with the sibling cards.dashboard.refreshIntervalis read by objectui (DashboardRenderer.tsx:448-453,DashboardGridLayout.tsx:146-151, the registry declarationindex.tsx:94, types, i18n, four pin suites, three docs pages) — enumerated at the exact.objectui-shapin, nothing in objectui modifiedcheck:react-declaration-paritycannot see it (thedashboardcomponent is outside its population) — recorded, not hidden.Blocked-bythe spec pin bump on the objectui siderefusedCredentialKeysderived "refused inline credential" from anyz.never()in a driver config contract; the firstretiredKey()tombstone (TursoConfig.timeout) made it redact a millisecond budget. Fix: skip keys whose description starts with the[REMOVED]prefixretiredKey()stamps — a negative exclusion (skip declared tombstones), not a positive one (keep onlyformat: 'password')datasource-credential-redaction.ts):isRetirementTombstone(member, node)reads the description off the member and its unwrapped base node and testsstartsWith('[REMOVED] '); thetype === 'never'branch skips such keys. Failure direction confirmed: an unmarkedz.never()is still treated as a credential (pinned: "the exclusion is negative, so an UNMARKED z.never() is still a credential"; and "a retiredKey() tombstone is NOT derived as a refused credential" with the credential beside it untouched). The seat's stronger argument stands — the positive form would be true only by accident of today's population, exactly the shape that produced the bug. Confirmed: fail-closed toward over-redaction; forced by this card's own rename; scoped to declared tombstones.80869188, #16023):buildTursoDriverConfigreads the canonicalconfig.timeoutMs; no??fallback arm for the retired spelling (both doors —retiredKey()at authoring and the protocol-18 conversion at load — already close it; a fallback would be a PD #12 consumer dialect); covering test moved off the retired spelling and gains contract-derived cases (6 of 15 red on the unfixed reader)@objectstack/service-datasourcepatch changeset.TursoDriverConfig.timeout(driver's own inert key, #16024) correctly left.check-governed-merges --teston the 60 paths: 1 hit —skills/objectstack-ui/rules/dashboards.md(the published rule authorsrefreshInterval; kept, not dropped). ⇒ human merge for the whole PR.② semver
@objectstack/specminor with BREAKING banner andregisteredmarker for the six ids;@objectstack/service-datasourcepatch; readers in the samefixedgroup. Correct.③ Boundary flags
check:authorable-surfacered) — the second leg is the whole argument for tombstones and is recorded as such.@objectstack/specbump (objectui#7122's family). Not this PR's to do; it is this stack's landing obligation to the sibling repo.Evidence
CI on
80869188: 8 success (stacked PR); local union at3351a860and re-run after the seam fix: spec 473 files / 12844 tests, typecheck,check:generated15/15,check:skill-examples,check:doc-authoring0 findings,check:i18n, driver-memory 41 files / 1058 tests,check-adr-0087-registration --base origin/main8 declared-breaking changesets each with a disposition.mergeable_state: cleanagainst 4/6's branch.Part of #14478(card deliberately left open until 6/6).Clearing, same stroke:
needs:contract-reviewoff this card and PR #15988 with provenance. ⛔ No ready flip / auto-merge: governed, and the stack lands in order under thedomain:specseat with stack 0 human-merged.Generated by Claude Code
feat(spec)!: the last seven data/ ui/ ai/ integration/ duration keys …
feat(spec): widen check:duration-unit-keys to every workspace package…
os-sales commentedon Sep 6, 2026
Delivered by PR #15988 and landed on
mainate9fcd6bbd(via the stack's trunk PR #15626, merged 2026-09-06T03:17Z).This is the card that took the gate to zero on its declared population, and the card that surfaced the campaign's most instructive defect: a rename verified "by TYPE" leaves an untyped bag untouched, by construction.
service-datasource's libSQL seam still read the retiredconfig.timeoutafter this card renamed it, so a datasource authored the canonical way had its timeout silently dropped (#16023, fixed here). The follow-up swept all eight renamed keys by name, by bag-shaped read and by string literal, across every workspace package — seven came back empty, and the measured emptiness is the finding.Closing as completed;
pm:dispatchedremoved in the same write.Generated by Claude Code
feat(spec)!: duration-shaped number keys carry their unit in the key …
test(platform-objects): pin the catalogs to the LIVE refresh key, aga…
feat(spec): item-level property names for the dashboard header-action…
feat(spec)!: tenant `schemaCacheTTL` carries its unit in the key name (…
test(spec): security, ai, identity, integration, migrations, marketpl…
test(spec): the first data/ file group's test titles state each cited…
test(spec): the second data/ file group's test titles state each cite…
test(spec): the last data/ file group's test titles state each cited …