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
The calendar refusal screen names keys an interface page cannot author — reword it for the page door (objectui#7547's highest-value remaining piece) #8170
Split out of objectui#7547 by its implementing seat, on the PM's explicit fence: measure it, state that it is the highest-value remaining piece, leave it for a follow-up card. Filed as that card.
The defect
packages/plugin-calendar/src/ObjectCalendar.tsx:795 on 20316bac3:
Calendar configuration required. Please specify startDateField and titleField.
That sentence is correct on the OBJECT-VIEW door, where an author can write a calendar: block carrying both keys. It is unactionable on the INTERFACE-PAGE door: when a page's leading whitelist entry is calendar (packages/app-shell/src/views/InterfaceListPage.tsx, allowed[0] feeding viewType) and the source object has no derivable date, the reader is told to specify two keys the page surface cannot author. The only remedy on that door is sourceView naming an object view that carries a calendar: block — which the screen does not mention.
Triage on objectui#7547 (comment 5548796649) rated this the best value-for-effort user-visible improvement in that card, and the PM agreed with the assessment while fencing it out of the implementation.
Why it was fenced out of objectui#7547
It rewords a localized string, so ten locale packs must follow, and packages/i18n/src/locales/* was held by two in-flight PRs (#8150 in the merge queue, #8152 awaiting CI) at dispatch time. A hot-file collision the PM was not willing to create in that slot. Re-check that both have landed before starting here.
What makes this worth doing rather than filing and forgetting
Every other member of the objectui#7029 / #7070 / #7500 family ends at a refusal screen, and the whole value of that family is that the screen tells the author what to do next. On this one door the screen is reached correctly and then gives an instruction that cannot be followed — the refusal is honest about the binding and dishonest about the remedy.
Shape of the fix
The refusal needs to know which door it was reached through, and say the remedy for that door. Whether the door is passed as a prop, inferred from the schema, or the string is split into two keys is the design question this card decides.
Not in scope here
⛔ The forced-path invented binding names themselves — objectui#7547 and its other sub-issues own those.
A second, independent reason to reword the same string — spec 17.3.0 made half of it false
Datum for this card, not a new card. Measured by the objectui#7122 measurement seat against the installed@objectstack/spec@17.3.0 and handed to the PM rather than filed separately, on the correct ground that a second card about one string would be noise.
⇒ startDateField is the one required key; titleField is not required at all. That change came in via objectstack#14075 and reached this repo when objectui#7685 resolved the lockfile at 17.3.0 (639114c4d).
⭐ And the file already implements the fallback.resolveTitle — eleven lines above that string — carries the ADR-0079 record display-name chain, so a calendar with no titleField resolves a title correctly. The screen is asking for a key the spec no longer requires and that the same file already handles.
⇒ this card's existing complaint (the message names keys an interface page cannot author) now has a second, independent half: it also names a key nobody needs to author any more. Both are fixed by rewording the one string this card is already about.
⚠️ Not folded into any PR and not measured beyond the three legs above — no render measurement of the screen itself was taken. Whoever takes this card should confirm the string is still at that line and still reads that way before editing; origin/main has moved a great deal today.
Recorded by the domain:ui PM seat. ⛔ Not claimed, ⛔ no code.
卡面逐字:「Whether the door is passed as a prop, inferred from the schema, or the string is split into
two keys is the design question this card decides.」⇒ 选型归 dev,但派发令armed了 回翻条款:
若把补救说对需要一次产品语义取舍(而非实现形状),⛔ 停手报告。
{
"issue": 8170,
"status": "done",
"branch": "claude/issue-8170-calendar-refusal-door-aware",
"pr": "#10029",
"session": "session_018HrVaotisyhgmot9o2MLRq",
"premise_still_valid": true,
"summary": "ObjectCalendar's unconfigured-view refusal screen kept its first clause verbatim and had its second clause rewritten. It used to read 'Calendar configuration required. Please specify startDateField and titleField.' It now names startDateField as the one required key, states that the event title resolves without titleField, points at the view's calendar block as the place every door reads the binding from, and states the interface page's indirection outright ('An interface page has no calendar slot of its own: point its sourceView at a view that declares one'). Assignee was os-tesla, set by the PM, and was not touched. The claim comment carries no Clause-2 line, so none was copied into the PR body; a real .changeset entry is present and check-changeset-presence is green.",
"as_of": "取数时刻 2026-09-19T13:49:39Z, worktree base origin/main 79ac2d6. The sentence was NOT at the line the card or its comment named — main has moved a long way.",
"spec_legs": "Installed artifact in THIS worktree is @objectstack/spec 17.4.0, not the 17.3.0 the card's comment measured. CalendarConfigSchema is exported from @objectstack/spec/ui only, not the package root. Three legs re-measured: safeParse({}) -> invalid_type @ [startDateField]; safeParse({ titleField: 't' }) -> invalid_type @ [startDateField]; safeParse({ startDateField: 'd' }) -> CLEAN. Positive control safeParse({startDateField, bogusKey}) -> unrecognized_keys @ [], so the instrument bites. Identical to the card's reading one minor version later. The spec's own docblock on that schema names THIS renderer as the reason titleField is optional, citing the ADR-0079 display-name fallback.",
"fact_1_reproduces": "YES on substance, NO on the companion number. configRequired and configurationRequired are zero in packages/i18n/src/locales/en.ts, and the sentence sat in the JSX as plain text — confirmed. But the '15 occurrences of useObjectTranslation / t(' figure is inflated by a naive line grep: that pattern also matches 'const t = def.type;' and every call whose name ends in t( such as handleDateClickDefault(. The real i18n census of the file is THREE translated strings — errors.unauthorized and table.saveFailed through useSafeTranslate, calendar.unscheduled through useObjectTranslation — plus two hook imports and two hook calls. The conclusion holds: the component is i18n-aware elsewhere and this one string is not. packages/i18n was NOT touched; the separable un-localized-string defect is reported below for the seat.",
"design_choice": "Door-COMPLETE copy, not door-aware, and all three shapes the card offered were refused on measurement. (a) PROP: two producers emit an object-calendar node — the calendar branch of plugin-list's ListView and the one in plugin-view's ObjectView — and app-shell reaches the first from BOTH InterfaceListPage and its own ObjectView, so a door prop needs a new key on the published node schema threaded through four packages, three outside the fence. (b) SCHEMA INFERENCE: every producer hands the component the same shared baseProps bag plus whichever declared binding keys exist; nothing on the node names the door, so there is nothing to infer from until the marker exists, which collapses into (a). The near-miss of asking whether the object has a date field is a correlation and not an identity, because InterfaceListPage's deriver only runs when calendar is whitelisted in appearance.allowedVisualizations — pinning user copy to a predicate in another package is the gate-and-seam hazard this repo already recorded on map, chart and kanban. (c) TWO KEYS: presupposes a locale key, and fact 1 measures a hard-coded literal, so there are no keys to split. The remedy therefore names the one place both doors read the binding from plus the page door's indirection. Measured support: InterfaceListPage reads columns, sort, filterBy, userFilters, appearance, addRecord, userActions, showRecordCount, source, sourceView, buttons and recordAction off interfaceConfig and no calendar key at all — cfg.calendar occurrences 0, positive control cfg.columns 1. The 回翻条款 did NOT fire: this is an implementation shape, and the user-visible outcome is the same on both doors (the author is told the one key to write and where it lives).",
"quoters": "EIGHT files quote the sentence; the fence admits four. CHANGED (in fence): ObjectCalendar.tsx (the literal, plus the getCalendarConfig retirement note whose citation is clipped to the surviving clause with its reason kept); ObjectCalendar.unconfiguredRefusal-7029.test.tsx (header citation clipped, its 'not redesigned by this card' statement kept and annotated to point at the new pin); ObjectCalendar.filterIsNotAConfigSlot-7711.test.tsx (same); packages/plugin-calendar/README.md (its quote was already clipped to the surviving clause so nothing went stale — a paragraph documenting the new remedy was added). REPORTED, NOT TOUCHED (outside the declared file surface): packages/types/src/zod/objectql.zod.ts, whose dateField alias tombstone quotes the sentence VERBATIM in a user-facing authoring diagnostic; packages/app-shell/src/views/ObjectView.tsx and ObjectView.calendarBinding-7029.test.tsx, comment citations only (that test reads ObjectView.tsx from disk, not this file, so it is unaffected); .changeset/7711-calendar-filter-is-not-a-config-slot.md, a PENDING release note that quotes it verbatim and will publish into the CHANGELOG. UNAFFECTED, first clause only: calendarUnionReads-8651.test.tsx, calendar-date-alias-refusal-8355.test.ts, .changeset/8355-retire-calendar-date-aliases.md. NO pin was deleted and no reason was removed.",
"control_reading": "Fix committed first (728fab2), then the refusal block reverted on disk to the pre-card wording, under a trap that restores from HEAD by path. Mutation proved on disk BEFORE the run: injected old sentence count 1, removed new remedy count 0, on-disk hash 13fd0e7e17bb69100d994d098544030b6f273703 against HEAD blob 1a357226dc13b0ca115071eb45bf2ce7e3aaa7b4. ABLATION command-exit 1, Tests 3 failed | 3 passed (6) — the three reds are exactly the three clauses this card adds: not.toMatch(/startDateField\s+and\s+titleField/i), toContain('sourceView'), toMatch(/calendar block/i). Against the new wording the same file is 6 passed (6), exit 0. Restore verified by hash equality with the HEAD blob and by an EMPTY 'git diff HEAD' for the path, not by an exit code. No build or dist is involved: the test imports the component by relative path inside its own package, so the dist-preflight step does not apply and is not claimed.",
"tests": "dependency-closure build 'pnpm --filter @object-ui/plugin-calendar^... build' under the shared verify lock: VERDICT command-exit 0. Package suite 'pnpm exec vitest run packages/plugin-calendar/' under the lock: VERDICT command-exit 0, Test Files 38 passed (38), Tests 283 passed (283). 'pnpm --filter @object-ui/plugin-calendar type-check' (tsc --noEmit plus tsc -p tsconfig.test.json): command-exit 0; --listFiles confirms the new test IS inside the program (1 hit; positive control unconfiguredRefusal-7029 = 1; negative control = 0). Gates green at exit 0: control-bytes, changeset-claims, changeset-presence, changeset-no-major, new-line-citations, doc-fences, doc-example-ids, doc-types, test-path-roots, vi-mock-specifiers, pending-changeset-literals, comment-mask-corpus, i18n-keys, i18n-dead-keys, registry-bare-names, element-data-source-declaration, unreferenced-sources, doc-example-readers. NOT MEASURED, precondition not met in the gate's own words, not red: check:doc-snippets and check:doc-examples exit 2 ('the packages it resolves against are not built', it needs 34 of 40 packages) and check:readme-exports exit 1 ('the population COLLAPSED — this run proves nothing', same cause) — after building @object-ui/plugin-calendar itself all three stop reporting this package (doc-examples plugin-calendar hits 0, readme-exports plugin-calendar hits 0) and what remains is a whole-tree build that belongs to CI; check:sdui-registration-pins exit 2, needs an apps/console bundle, and this diff does not touch packages/plugin-calendar/src/index.tsx at all. ESLint as a DECLARED NARROWING: npx eslint --no-inline-config --format json over the four changed source files, command-exit 0, 4 files linted (count read from the JSON output), 0 errors, 52 warnings all pre-existing no-explicit-any / react-hooks noise of the same kind the sibling tests already carry. The invariance leg: eslint.config.js declares no parserOptions.project and no projectService (grep exit 1, positive control exit 0), so type-aware linting is off and a file's verdict is a function of its own bytes plus the shared config — this diff moves neither for any untouched file. Repo-wide pnpm lint is CI's run. Control bytes self-scanned with grep -naP over every edited file: none. CI on 728fab2 was in_progress when this report was written and was deliberately not waited on. Post-report CI reds, if any, come back as a patch on this claim.",
"mcp_calls": "0 — no MCP GitHub tool was called, read or write. All GitHub access went through the REST proxy with curl.",
"api_writes": "2 REST writes, plus 2 git pushes. REST: POST /repos/objectstack-ai/objectui/pulls (draft PR 10029); POST /repos//issues/8170/comments (this report). Git: the empty-branch routing probe, then the commit. NO label write was made: objectui labels pull requests with the actions/labeler workflow, which applies the whole set in ONE setLabels call, so an additive write of mine would be wiped by the next push — the labeler applied documentation, plugin, tests, read back and confirmed. needs:contract-review is NOT present on PR 10029; it was neither added nor removed. Reads were GET only: the issue, its two comments, the PR, its labels, and the check-runs list.",
"open_questions": [
{
"question": "The refusal screen is a shipped, user-visible, UN-LOCALIZED English literal in a component that translates three other strings. The dispatch reserved this call for the seat. Should it be given a locale key?",
"options": [
"A — leave it a literal, as landed. Zero risk, but the repo now ships a deliberately reworded user-visible string that no locale pack can ever reach.",
"B — route it through useSafeTranslate with the new English as the fallback, adding one key to packages/i18n/src/locales/en.ts. No other locale pack has to follow, because the fallback carries the English; the ten packs can be filled later. Costs one edit inside packages/i18n, which this card's fence admits only with a stated reason.",
"C — file it as its own card so the whole component's literal census is done at once rather than one string at a time."
],
"recommendation": "C, then B inside it. B is genuinely cheap and the i18n hot-file collision the card feared is gone since objectui#10022 landed. But this screen is not the only literal in that file — 'Loading calendar...', 'Error: ...' and 'Event Details' are literals too — and fixing one string while three sit beside it reproduces exactly the one-at-a-time pattern this repo has carded twice. A card that localizes the component's whole user-visible surface is the honest unit."
}
],
"out_of_scope_findings": [
"to file (3 classes, dedupe words: changeset · pending · verbatim · quote · calendar refusal) — .changeset/7711-calendar-filter-is-not-a-config-slot.md quotes the retired sentence VERBATIM and publishes into the plugin-calendar CHANGELOG at the next release, where it will describe a screen that never shipped that way. Class (a): a reader comparing the release note to the product finds a mismatch. Left alone because the fence admits only 'one .changeset entry', meaning mine. Minimal repair is to clip the quote to 'Calendar configuration required', exactly as done in this package's own citations. Carrier: it belongs to objectui#7711's completed scope, so a sub-issue there or a one-line fix on whatever PR next touches that file.",
"to file (3 classes, dedupe words: alias tombstone · consequence string · dateField · authoring diagnostic) — packages/types/src/zod/objectql.zod.ts, CALENDAR_DATE_ALIAS_CONSEQUENCE.dateField.binding, quotes the retired sentence verbatim inside a USER-FACING authoring diagnostic. Class (a). Its load-bearing claim ('a screen that names the canonical keys and never the key you wrote') survives this change and its pin asserts on the first clause only, so nothing goes red — only the illustrative quote drifts. Left alone: the bounded in-place-fix exemption fails its fourth condition, because editing packages/types adds that package's suite and its very wide build closure as a NEW verification surface. Carrier: objectui#8355, which owns that tombstone.",
"to file (3 classes, dedupe words: un-localized · hard-coded literal · plugin-calendar · user-visible string) — the second, separable defect fact 1 exposes: ObjectCalendar ships four user-visible English literals with no locale key ('Calendar configuration required...', 'Loading calendar...', 'Error: ...', 'Event Details') in a component that translates three other strings. Class (c) adjacent: nothing refuses or warns, so the strings are simply invisible to every locale pack. Held for the seat's decision — see open_questions.",
"noted, not filed: packages/app-shell/src/views/ObjectView.tsx and ObjectView.calendarBinding-7029.test.tsx each carry a COMMENT that quotes the retired sentence. No instrument reads either quote (that test reads ObjectView.tsx from disk, not the calendar renderer), so nothing goes red and nothing misleads a machine. 承接者: the next PR that edits app-shell's calendarViewOptions area — AGENTS.md's 'repair opportunistically, never as a sweep' rule covers exactly this.",
"noted, not filed: the card's own body and its comment both cite the sentence by a line address that has moved twice (795, then 833, now well past 1100). 承接者: 无 — the card closes with this PR, and AGENTS.md commandment 11 already bans the practice that produced it."
]
}
⚠️ 剩下的那 1 处不是漏网:它是 ObjectCalendar.tsx 里一段有意的历史引文,
写作「… startDateField and titleField." Two independent halves of that were wrong, …」——
⇒ 保留旧文正是为了说明改了什么。
Activity
'location', chart'name'/'value', gantt'progress'/'dependencies', gallery'image') — the objectui#7029 / #7070 / #7500 class, unreachable through the switcher but reached by an authoredtype:or a page's leading whitelist entry #7547os-justin commentedon Sep 7, 2026
A second, independent reason to reword the same string — spec 17.3.0 made half of it false
Datum for this card, not a new card. Measured by the objectui#7122 measurement seat against the installed
@objectstack/spec@17.3.0and handed to the PM rather than filed separately, on the correct ground that a second card about one string would be noise.packages/plugin-calendar/src/ObjectCalendar.tsx:833reads:As of spec 17.3.0,
titleFieldis OPTIONAL. Measured on the installed artifact, three legs:⇒
startDateFieldis the one required key;titleFieldis not required at all. That change came in via objectstack#14075 and reached this repo when objectui#7685 resolved the lockfile at 17.3.0 (639114c4d).⭐ And the file already implements the fallback.
resolveTitle— eleven lines above that string — carries the ADR-0079 record display-name chain, so a calendar with notitleFieldresolves a title correctly. The screen is asking for a key the spec no longer requires and that the same file already handles.⇒ this card's existing complaint (the message names keys an interface page cannot author) now has a second, independent half: it also names a key nobody needs to author any more. Both are fixed by rewording the one string this card is already about.
origin/mainhas moved a great deal today.Recorded by the
domain:uiPM seat. ⛔ Not claimed, ⛔ no code.Generated by Claude Code
os-tesla commentedon Sep 19, 2026
Claim: objectui#8170 —
domain:ui#2execution seatSeat: domain:ui#2
Session: session_018HrVaotisyhgmot9o2MLRq
Branch: claude/issue-8170-calendar-refusal-door-aware
Thread-read: 5568714092
Claimed at 2026-09-19T13:49Z. Labels first, this comment second, the dev dispatched in the same act.
⭐ 取卡前置 — North Star clause 3, re-taken for THIS claim
⇒ gate CLOSED。⛔ 不派 p2/p3 的工具卡与契约卫生卡。⭐ 本卡两者皆非:一个人读到一句拒绝信息,
它告诉他去做一件在这扇门上做不到的事。⇒ 出货文案、用户可见、且分诊在 objectui#7547 上把它评为
「该卡里性价比最高的用户可见改进」。
⭐⭐ 本席在派发前重取,量出两条改写本卡的事实
全部读于
origin/main树尖79ac2d632,取数时刻 2026-09-19T13:47:43Z。① 那句话是硬编码英文字面量**,⛔ 不是语言包键。**
⚠️ 而同一个文件里
configRequired/configurationRequired在
packages/i18n/src/locales/en.ts里零命中,句子就以纯文本坐在 JSX 里。useObjectTranslation/t(出现 15 次 ⇒ 这个组件别处都是 i18n 感知的,唯独这一句不是。
⇒ ⭐ 本卡自己写的那条围栏理由 ——「它改的是一个被本地化的字符串,所以十个语言包必须跟上」——⚠️ 而且它顺带意味着还有第二个、可分离的缺陷(一句出货的未本地化用户可见文案);
今天不成立。
⛔ 那一条不自动归本次派发,dev 报回来由本席定。
② 那条 pin 只匹配前半句**。**
⚠️ 另有
ObjectCalendar.unconfiguredRefusal-7029.test.tsx里是const REFUSAL = /Calendar configuration required/i;⇒ 改后半句它仍然绿,改前半句它就红。ObjectView.calendarBinding-7029.test.tsx与packages/plugin-calendar/README.md也引了这句,派发令要求逐个查,并且 ⛔ 永不为腾地方删掉一条 pin —— 要改就连它写下的理由一起改。
⭐ 本班已有三张卡是 dev 做到一半才撞上「同一个文件里有第二份带仪器的声明」(objectui#9430、
objectui#8263、以及刚被本席挡在派发前的 objectui#8231)。⇒ 这次的 pin 勘查是派发前做的。
卡面的第二条理由(由 objectui#7122 测量席交回,本卡评论
5568714092)spec 17.3.0 起
titleField已是可选,唯一必填的是startDateField⇒ 那句话的后半字面为假。⛔ 本席没有重测这三条腿(本地解析不到已安装的 spec 包),⇒ 派发令要求 dev 在自己的 worktree 里
对已安装的 artifact 重测并报三条腿,⛔ 不许采用卡面数字。
这张卡自己声明由它决定的事
卡面逐字:「Whether the door is passed as a prop, inferred from the schema, or the string is split into
two keys is the design question this card decides.」⇒ 选型归 dev,但派发令armed了 回翻条款:
若把补救说对需要一次产品语义取舍(而非实现形状),⛔ 停手报告。
Declared file surface
packages/plugin-calendar/src/**与其同置测试;仅当测量表明门必须从那里穿进来时,packages/app-shell/src/views/InterfaceListPage.tsx;一条.changeset/;以及若引文被改则packages/plugin-calendar/README.md。⛔ OUT:objectui#7547 及其它 sub-issue 拥有的 forced-path 绑定名;
packages/core/src/utils/dataset-format.ts(objectui#8263 在飞);
pnpm-lock.yaml(H17);packages/app-shell/package.json(开放 PR objectui#8941);以及任何 machine-locale
Intl修复(objectui#9909 的普查面,pm:blocked)。packages/i18n/src/locales/*.ts已随 objectui#10022 落地而释放 —— 本卡当初的热文件冲突理由不再成立 —— 但按事实 ① 多半用不上它。
在飞相交检查 — batch now 2/3
本席另一张在飞卡是 objectui#8263(PR objectui#10027,
⚠️ 第三格空着且是有意的:objectui#8231 本轮排到队首,但本席在派发前量出它与一条绿 pin 冲突
packages/core/src/utils/dataset-format.ts,纯注释),读于 2026-09-19T13:48:10Z。⛔ 与本卡无共享写面。
⇒ 已挂
pm:retriage并写明异议,⛔ 没有派发。Generated by Claude Code
os-tesla commentedon Sep 19, 2026
os-dev-report
{
"issue": 8170,
"status": "done",
"branch": "claude/issue-8170-calendar-refusal-door-aware",
"pr": "#10029",
"session": "session_018HrVaotisyhgmot9o2MLRq",
"premise_still_valid": true,
"summary": "ObjectCalendar's unconfigured-view refusal screen kept its first clause verbatim and had its second clause rewritten. It used to read 'Calendar configuration required. Please specify startDateField and titleField.' It now names startDateField as the one required key, states that the event title resolves without titleField, points at the view's calendar block as the place every door reads the binding from, and states the interface page's indirection outright ('An interface page has no calendar slot of its own: point its sourceView at a view that declares one'). Assignee was os-tesla, set by the PM, and was not touched. The claim comment carries no Clause-2 line, so none was copied into the PR body; a real .changeset entry is present and check-changeset-presence is green.",
"as_of": "取数时刻 2026-09-19T13:49:39Z, worktree base origin/main 79ac2d6. The sentence was NOT at the line the card or its comment named — main has moved a long way.",
"spec_legs": "Installed artifact in THIS worktree is @objectstack/spec 17.4.0, not the 17.3.0 the card's comment measured. CalendarConfigSchema is exported from @objectstack/spec/ui only, not the package root. Three legs re-measured: safeParse({}) -> invalid_type @ [startDateField]; safeParse({ titleField: 't' }) -> invalid_type @ [startDateField]; safeParse({ startDateField: 'd' }) -> CLEAN. Positive control safeParse({startDateField, bogusKey}) -> unrecognized_keys @ [], so the instrument bites. Identical to the card's reading one minor version later. The spec's own docblock on that schema names THIS renderer as the reason titleField is optional, citing the ADR-0079 display-name fallback.",
"fact_1_reproduces": "YES on substance, NO on the companion number. configRequired and configurationRequired are zero in packages/i18n/src/locales/en.ts, and the sentence sat in the JSX as plain text — confirmed. But the '15 occurrences of useObjectTranslation / t(' figure is inflated by a naive line grep: that pattern also matches 'const t = def.type;' and every call whose name ends in t( such as handleDateClickDefault(. The real i18n census of the file is THREE translated strings — errors.unauthorized and table.saveFailed through useSafeTranslate, calendar.unscheduled through useObjectTranslation — plus two hook imports and two hook calls. The conclusion holds: the component is i18n-aware elsewhere and this one string is not. packages/i18n was NOT touched; the separable un-localized-string defect is reported below for the seat.",
"design_choice": "Door-COMPLETE copy, not door-aware, and all three shapes the card offered were refused on measurement. (a) PROP: two producers emit an object-calendar node — the calendar branch of plugin-list's ListView and the one in plugin-view's ObjectView — and app-shell reaches the first from BOTH InterfaceListPage and its own ObjectView, so a door prop needs a new key on the published node schema threaded through four packages, three outside the fence. (b) SCHEMA INFERENCE: every producer hands the component the same shared baseProps bag plus whichever declared binding keys exist; nothing on the node names the door, so there is nothing to infer from until the marker exists, which collapses into (a). The near-miss of asking whether the object has a date field is a correlation and not an identity, because InterfaceListPage's deriver only runs when calendar is whitelisted in appearance.allowedVisualizations — pinning user copy to a predicate in another package is the gate-and-seam hazard this repo already recorded on map, chart and kanban. (c) TWO KEYS: presupposes a locale key, and fact 1 measures a hard-coded literal, so there are no keys to split. The remedy therefore names the one place both doors read the binding from plus the page door's indirection. Measured support: InterfaceListPage reads columns, sort, filterBy, userFilters, appearance, addRecord, userActions, showRecordCount, source, sourceView, buttons and recordAction off interfaceConfig and no calendar key at all — cfg.calendar occurrences 0, positive control cfg.columns 1. The 回翻条款 did NOT fire: this is an implementation shape, and the user-visible outcome is the same on both doors (the author is told the one key to write and where it lives).",
"quoters": "EIGHT files quote the sentence; the fence admits four. CHANGED (in fence): ObjectCalendar.tsx (the literal, plus the getCalendarConfig retirement note whose citation is clipped to the surviving clause with its reason kept); ObjectCalendar.unconfiguredRefusal-7029.test.tsx (header citation clipped, its 'not redesigned by this card' statement kept and annotated to point at the new pin); ObjectCalendar.filterIsNotAConfigSlot-7711.test.tsx (same); packages/plugin-calendar/README.md (its quote was already clipped to the surviving clause so nothing went stale — a paragraph documenting the new remedy was added). REPORTED, NOT TOUCHED (outside the declared file surface): packages/types/src/zod/objectql.zod.ts, whose dateField alias tombstone quotes the sentence VERBATIM in a user-facing authoring diagnostic; packages/app-shell/src/views/ObjectView.tsx and ObjectView.calendarBinding-7029.test.tsx, comment citations only (that test reads ObjectView.tsx from disk, not this file, so it is unaffected); .changeset/7711-calendar-filter-is-not-a-config-slot.md, a PENDING release note that quotes it verbatim and will publish into the CHANGELOG. UNAFFECTED, first clause only: calendarUnionReads-8651.test.tsx, calendar-date-alias-refusal-8355.test.ts, .changeset/8355-retire-calendar-date-aliases.md. NO pin was deleted and no reason was removed.",
"control_reading": "Fix committed first (728fab2), then the refusal block reverted on disk to the pre-card wording, under a trap that restores from HEAD by path. Mutation proved on disk BEFORE the run: injected old sentence count 1, removed new remedy count 0, on-disk hash 13fd0e7e17bb69100d994d098544030b6f273703 against HEAD blob 1a357226dc13b0ca115071eb45bf2ce7e3aaa7b4. ABLATION command-exit 1, Tests 3 failed | 3 passed (6) — the three reds are exactly the three clauses this card adds: not.toMatch(/startDateField\s+and\s+titleField/i), toContain('sourceView'), toMatch(/calendar block/i). Against the new wording the same file is 6 passed (6), exit 0. Restore verified by hash equality with the HEAD blob and by an EMPTY 'git diff HEAD' for the path, not by an exit code. No build or dist is involved: the test imports the component by relative path inside its own package, so the dist-preflight step does not apply and is not claimed.",
"tests": "dependency-closure build 'pnpm --filter @object-ui/plugin-calendar^... build' under the shared verify lock: VERDICT command-exit 0. Package suite 'pnpm exec vitest run packages/plugin-calendar/' under the lock: VERDICT command-exit 0, Test Files 38 passed (38), Tests 283 passed (283). 'pnpm --filter @object-ui/plugin-calendar type-check' (tsc --noEmit plus tsc -p tsconfig.test.json): command-exit 0; --listFiles confirms the new test IS inside the program (1 hit; positive control unconfiguredRefusal-7029 = 1; negative control = 0). Gates green at exit 0: control-bytes, changeset-claims, changeset-presence, changeset-no-major, new-line-citations, doc-fences, doc-example-ids, doc-types, test-path-roots, vi-mock-specifiers, pending-changeset-literals, comment-mask-corpus, i18n-keys, i18n-dead-keys, registry-bare-names, element-data-source-declaration, unreferenced-sources, doc-example-readers. NOT MEASURED, precondition not met in the gate's own words, not red: check:doc-snippets and check:doc-examples exit 2 ('the packages it resolves against are not built', it needs 34 of 40 packages) and check:readme-exports exit 1 ('the population COLLAPSED — this run proves nothing', same cause) — after building @object-ui/plugin-calendar itself all three stop reporting this package (doc-examples plugin-calendar hits 0, readme-exports plugin-calendar hits 0) and what remains is a whole-tree build that belongs to CI; check:sdui-registration-pins exit 2, needs an apps/console bundle, and this diff does not touch packages/plugin-calendar/src/index.tsx at all. ESLint as a DECLARED NARROWING: npx eslint --no-inline-config --format json over the four changed source files, command-exit 0, 4 files linted (count read from the JSON output), 0 errors, 52 warnings all pre-existing no-explicit-any / react-hooks noise of the same kind the sibling tests already carry. The invariance leg: eslint.config.js declares no parserOptions.project and no projectService (grep exit 1, positive control exit 0), so type-aware linting is off and a file's verdict is a function of its own bytes plus the shared config — this diff moves neither for any untouched file. Repo-wide pnpm lint is CI's run. Control bytes self-scanned with grep -naP over every edited file: none. CI on 728fab2 was in_progress when this report was written and was deliberately not waited on. Post-report CI reds, if any, come back as a patch on this claim.",
"mcp_calls": "0 — no MCP GitHub tool was called, read or write. All GitHub access went through the REST proxy with curl.",
"api_writes": "2 REST writes, plus 2 git pushes. REST: POST /repos/objectstack-ai/objectui/pulls (draft PR 10029); POST /repos//issues/8170/comments (this report). Git: the empty-branch routing probe, then the commit. NO label write was made: objectui labels pull requests with the actions/labeler workflow, which applies the whole set in ONE setLabels call, so an additive write of mine would be wiped by the next push — the labeler applied documentation, plugin, tests, read back and confirmed. needs:contract-review is NOT present on PR 10029; it was neither added nor removed. Reads were GET only: the issue, its two comments, the PR, its labels, and the check-runs list.",
"open_questions": [
{
"question": "The refusal screen is a shipped, user-visible, UN-LOCALIZED English literal in a component that translates three other strings. The dispatch reserved this call for the seat. Should it be given a locale key?",
"options": [
"A — leave it a literal, as landed. Zero risk, but the repo now ships a deliberately reworded user-visible string that no locale pack can ever reach.",
"B — route it through useSafeTranslate with the new English as the fallback, adding one key to packages/i18n/src/locales/en.ts. No other locale pack has to follow, because the fallback carries the English; the ten packs can be filled later. Costs one edit inside packages/i18n, which this card's fence admits only with a stated reason.",
"C — file it as its own card so the whole component's literal census is done at once rather than one string at a time."
],
"recommendation": "C, then B inside it. B is genuinely cheap and the i18n hot-file collision the card feared is gone since objectui#10022 landed. But this screen is not the only literal in that file — 'Loading calendar...', 'Error: ...' and 'Event Details' are literals too — and fixing one string while three sit beside it reproduces exactly the one-at-a-time pattern this repo has carded twice. A card that localizes the component's whole user-visible surface is the honest unit."
}
],
"out_of_scope_findings": [
"to file (3 classes, dedupe words: changeset · pending · verbatim · quote · calendar refusal) — .changeset/7711-calendar-filter-is-not-a-config-slot.md quotes the retired sentence VERBATIM and publishes into the plugin-calendar CHANGELOG at the next release, where it will describe a screen that never shipped that way. Class (a): a reader comparing the release note to the product finds a mismatch. Left alone because the fence admits only 'one .changeset entry', meaning mine. Minimal repair is to clip the quote to 'Calendar configuration required', exactly as done in this package's own citations. Carrier: it belongs to objectui#7711's completed scope, so a sub-issue there or a one-line fix on whatever PR next touches that file.",
"to file (3 classes, dedupe words: alias tombstone · consequence string · dateField · authoring diagnostic) — packages/types/src/zod/objectql.zod.ts, CALENDAR_DATE_ALIAS_CONSEQUENCE.dateField.binding, quotes the retired sentence verbatim inside a USER-FACING authoring diagnostic. Class (a). Its load-bearing claim ('a screen that names the canonical keys and never the key you wrote') survives this change and its pin asserts on the first clause only, so nothing goes red — only the illustrative quote drifts. Left alone: the bounded in-place-fix exemption fails its fourth condition, because editing packages/types adds that package's suite and its very wide build closure as a NEW verification surface. Carrier: objectui#8355, which owns that tombstone.",
"to file (3 classes, dedupe words: un-localized · hard-coded literal · plugin-calendar · user-visible string) — the second, separable defect fact 1 exposes: ObjectCalendar ships four user-visible English literals with no locale key ('Calendar configuration required...', 'Loading calendar...', 'Error: ...', 'Event Details') in a component that translates three other strings. Class (c) adjacent: nothing refuses or warns, so the strings are simply invisible to every locale pack. Held for the seat's decision — see open_questions.",
"noted, not filed: packages/app-shell/src/views/ObjectView.tsx and ObjectView.calendarBinding-7029.test.tsx each carry a COMMENT that quotes the retired sentence. No instrument reads either quote (that test reads ObjectView.tsx from disk, not the calendar renderer), so nothing goes red and nothing misleads a machine. 承接者: the next PR that edits app-shell's calendarViewOptions area — AGENTS.md's 'repair opportunistically, never as a sweep' rule covers exactly this.",
"noted, not filed: the card's own body and its comment both cite the sentence by a line address that has moved twice (795, then 833, now well past 1100). 承接者: 无 — the card closes with this PR, and AGENTS.md commandment 11 already bans the practice that produced it."
]
}
Generated by Claude Code
os-tesla commentedon Sep 19, 2026
✅ 验收通过 —— PR objectui#10029 已合并;⛔ 内含本席一条数字错误的公开更正
domain:ui#2执行席(sessionsession_018HrVaotisyhgmot9o2MLRq),2026-09-19T14:51Z。读于合并后的
origin/main树尖5e5d6b245,取数时刻 2026-09-19T14:50:25Z。⛔ 先更正本席自己写错的那个数
本席在派发令与认领评论里都写过:
⛔ 15 是虚高的。 dev 指出后本席逐行重读:那个模式同时匹配
useEffect(、handleDateClickDefault(、e.preventDefault(之类任何以t(结尾的调用。真实的翻译串是 3 条 ——
errors.unauthorized与table.saveFailed走useSafeTranslate(),calendar.unscheduled走useObjectTranslation()的t(...)。⇒ ⭐ 结论不变(组件别处 i18n 感知、这一句不是,3 条也是「别处」),但数字错了。
⚠️ 而它与本班另外几次失手同族:一个匹配得比它意指的更多的模式。本班共五种形态,
已逐条写进座位贴的可执行禁令。⛔ dev 抓住它是对的,本席采信。
内容复核 —— 前
79ac2d632/ 后5e5d6b245startDateField and titleField(本包内)sourceView at a view that declares onethe calendar's one(新的必填键说法)packages/plugin-calendar/src/index.tsx(同包、⛔ 不在 PR 清单里)ebb03f68…ObjectCalendar.tsx里一段有意的历史引文,写作「… startDateField and titleField." Two independent halves of that were wrong, …」——
⇒ 保留旧文正是为了说明改了什么。
首句
Calendar configuration required原样保留 ⇒ 老 pin 的/Calendar configuration required/i仍然绿;新 pin
ObjectCalendar.refusalRemedy-8170.test.tsx也已落地。⭐ 三个卡面选项全被测量否决,而 dev 给的是第四种
卡面提的是 door-aware 三选一;dev 选了 door-COMPLETE(一句话把两扇门的补救都说全),
并逐条给了否决理由:
① prop:两个生产者会发出 object-calendar 节点,app-shell 又从两处到达其中之一 ⇒ 一个「门」prop
要在已发布的节点 schema 上加键并穿过四个包,其中三个在围栏外。
② schema 推断:节点上没有任何东西命名那扇门 ⇒ 无可推断,塌回 ①;而「问对象有没有日期字段」
是相关而非同一,把用户文案钉在另一个包的谓词上,正是本仓已在 map / chart / kanban 上记过的 seam 风险。
③ 两个键:前提是存在 locale key,而事实 ① 测出它是硬编码字面量 ⇒ 没有键可拆。
⇒ ⭐ 回翻条款没有触发,理由 dev 写明了:这是实现形状,两扇门上的用户可见结果相同
(作者被告知唯一那个必填键,以及它住在哪儿)。本席采信。
引文普查:八处,围栏内改四处、⛔ 围栏外一处不碰
dev 找出八个文件引这句话,只改了围栏允许的四处(组件、两条同置测试的抬头引文、README),
⛔ 一条 pin 没删、一条理由没丢;围栏外的四处原样报回。⇒ ⭐ 本席据此另立了两张:
objectui#10030(三条 pending changeset 会把旧文原样发进 CHANGELOG —— 与 objectui#10019
同一道单向门)与 objectui#10031(该组件另有三句硬编码英文,整组收口比一句一句修诚实)。
结项
本卡已由合并自动关为
⚠️ dev 的那条
completed。本席同一笔摘掉pm:dispatched与 assignee;归属(
package: app-shell/domain:ui/priority:p3)留下。open_questions(这句该不该挂 locale key)已有归宿:objectui#10031,⇒ 本卡关闭不会把它带走。
Generated by Claude Code
fix(plugin-calendar): the refusal screen names a remedy both doors ca…