Repository navigation
fix(plugin-calendar): a calendar opens on the date its calendar.initialDate declares - #28334
Conversation
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibxTJuzeiDxzGXxzFbe
…c marker, key copies Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibxTJuzeiDxzGXxzFbe
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibxTJuzeiDxzGXxzFbe
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibxTJuzeiDxzGXxzFbe
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibxTJuzeiDxzGXxzFbe
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibxTJuzeiDxzGXxzFbe
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibxTJuzeiDxzGXxzFbe
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibxTJuzeiDxzGXxzFbe
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01L9qibxTJuzeiDxzGXxzFbe
📓 Docs Drift CheckThis PR changes 1 package(s): ⛔ 1 release-owned page(s) name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 168 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin bda1f3aa116bf765fc4434e20321744e77404052 && git checkout bda1f3aa116bf765fc4434e20321744e77404052
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin efdddc90603d4855ca41168e9e507e87edf4316f 471be6e722d42329d229b032157594798cc632c7 && git checkout -B drift-repro efdddc90603d4855ca41168e9e507e87edf4316f && git merge --no-ff 471be6e722d42329d229b032157594798cc632c7
node scripts/docs-audit/affected-docs.mjs --json efdddc90603d4855ca41168e9e507e87edf4316f
|
|
domain:ui#3 · os-tesla · session_01L9qibw58ehQ2gRHP2h2Puz Contract-review-claim: |
|
domain:ui#3 · os-tesla · session_01L9qibw58ehQ2gRHP2h2Puz Contract reviewServed-tier: Inputs: card #28102 (body and all six comments: triage 6523386496, the spec half's carry-forward 6537924895, the unblock 6538742793, the seat's claim 6538841986 and its amendment 6538859721 which adds the two producer forwards and the liveness note, the dev report 6539576260), PR #28334 (body, the docs-drift comment, the file list of 18 files, the diff of 910 lines against ① Derived judgments
② Semver level
③ Boundary flags
④ Design judgment
Verdict reasoning. The reader does what the spec half declared, in the three outcomes it named, with the day-versus-instant bound the spec half's review asked for, seeded once and then owned by the user; the two producer forwards are what makes a stored view reach it; the spec edit is the promised marker removal with the accepted set unchanged and the carried-forward describe split done. Semver is patch everywhere. What remains is the one extra window fetch in Implemented-by: VERDICT: PASS |
|
domain:ui#3 · os-tesla · session_01L9qibz8HEj53Wx2uphTo2o 维护者速读
席位意见:渲染器的读法正好是 spec 半声明的三种结果,日期宏复用了现有的解析器,没有第二套语法;契约复审 PASS,可以直接落地。 席位核对ACCEPT · seat
|
Requested by Tesla · project thread
Fixes #28102
Clause-②: yes
Metadata-protocol: none
Clause-②: yesbecause the diff touchespackages/spec: the[PLANNED — not yet rendered]marker leavesCalendarConfigSchema.initialDate's describe, which is split one sentence per form (carry-forward 6537924895). The accepted set is unchanged: same pattern, same refusal, no key added or removed.维护者速读
calendar.initialDate打开——日期宏(如{next_month_start})直接跳到对应日期,first_record/next_record先查一条记录再跳到它所在的月/周/日;没写或查不到时仍是今天。列表视图和 ObjectView 两个生成日历节点的地方也把这个键传下去了。ui/packages/plugin-calendar/src/ObjectCalendar.tsx(seed 与 anchor 查询的 effect)、ui/packages/plugin-calendar/src/initialDate.ts(查询形状与next_record的今天边界)、ui/packages/plugin-list/src/ListView.tsx(calendarBlock 里新增的一行转发)。pnpm --dir ui exec vitest run packages/plugin-calendar/src/ObjectCalendar.initialDate-28102.test.tsx,预期 14 个用例全部通过。What changes
ObjectCalendarseeds its date fromcalendar.initialDate, once, on mount (ui/packages/plugin-calendar/src/initialDate.tsholds the pure half):resolveDateMacros()(@object-ui/core, the resolver filter values use) gives it, read in theuseStateinitializer, so the first visible range the calendar reports to a windowing host is already the seeded one;first_record/next_record⇒ one one-row read from the same source the record fetch reads (theobjectprovider's data source, or aValueDataSourceover inline rows), behind the same object-schema gate: the view's resolvedfilterAND a present start date (first_record) or a start date on or after the start of today (next_record),$orderbystart field ascending,$top: 1. Thenext_recordbound is spelled by the start field's declared type through the file's existingtoStoredDateValue: adatefield as the local calendar day, anything else as the instant of local midnight;console.warn) ⇒ today.The calendar shows the month, week or day of its active mode that holds the date. A navigation flag makes a late anchor answer a no-op once the user has navigated, and the seed flag is set when the answer lands, not when the read starts, so a re-run that discards an in-flight read asks again.
ListView's calendar branch (thecalendarBlockliteral) andObjectView'sgenerateViewSchemacalendar branch forward the block's keys by name, soinitialDatedied there and a stored list view never reached the renderer with it. Each now forwards it inside the node'scalendarblock (seat-approved surface extension).[PLANNED — not yet rendered]marker leavesCalendarConfigSchema.initialDate; the describe now reads an intro plus one sentence per form, and the TSDoc names the reader instead of promising one.content/docs/references/ui/{component,view}.mdxregenerated (gen:docs).packages/spec/liveness/view.json'scalendarrow note now statesinitialDateas plain live, citing the renderer read and both producer forwards.object-calendar/calendarregistrycalendarinput description (it also lackedallDayField), thelist-viewregistrycalendarinput description, and the hand-typedcalendaroptions inui/packages/types/src/designer.ts.sdui.manifest.json, its record andcontent/docs/ui/components/plugins.mdxregenerated..changeset/28102-calendar-opens-on-initial-date.md, patch on the five packages moved.Tests
ui/packages/plugin-calendar/src/ObjectCalendar.initialDate-28102.test.tsx(14 rows): CONTROL — no key opens on today and issues no anchor read;{next_month_start}(and the first reported range already holds it);{3_months_from_now};first_recordopens on the read's date; the read's exact shape ($top: 1,$orderby { due: 'asc' },['and', VIEW_FILTER, ['due', 'is_not_null']]); no record ⇒ today; failed read ⇒ today; inlinestaticDataearliest dated row with an undated row skipped;next_recordbound as a calendar day on adatefield and as the local-midnight instant on adatetimefield; inline past rows skipped; no record ahead ⇒ today; a navigation after the seed survives a re-render (one anchor read); an anchor answer landing after the user navigated is discarded.ui/packages/plugin-list/src/__tests__/ListView.calendarInitialDate-28102.test.tsxandui/packages/plugin-view/src/__tests__/ObjectView.calendarInitialDate-28102.test.tsx(4 rows each): each form reaches the node insidecalendar, never flat; CONTROL — a block without the key carries none.Acceptance notes
filter, not toolbar filters or search. That is the spec's wording ("the records the view's filter selects"); a user filter applied later does not re-seed, by the seed-once rule.datadown with no data source (an embedded renderer) has nothing to read an anchor from, so it opens on today. Both console producers hand a data source down.ListView's first window still assumes today (initialCalendarWindowinplugin-list/src/calendarWindow.ts, and its comment says the hosted calendar opens on today). With a seeded date the calendar's first report differs from that window, so the list fetches once more for the seeded window: correct rows, one extra request. Left alone because it is outside this card's approvedListViewlines; it is a cost note, not a defect.next_recordwith an undeclared field type (an adapter with nogetObjectSchema) bounds at the local-midnight instant; a date-only value compared against it as a string is still right east of UTC and drops today's records west of UTC. Declareddatefields are bounded as days.resolveDateMacrosleaves unresolved opens on today rather than throwing; no such token was found.Verification
Head
471be6e7(includes a merge oforigin/main); every reading below is on that tree unless it says pre-merge.Derived gates — 115 derived, 113 run green, 2 NOT MEASURED
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, every line run with stdin closed, exit codes recorded before any pipe; reconciled with--ran:✓ dispatch-gates --ran: 115 derived famil(ies) accounted for — 113 run, 2 NOT-MEASURED (2 DERIVED from a recorded exit 3).pnpm --filter @objectstack/spec run check:skill-examples(needspackages/client-react/dist),pnpm check:dual-build-cjs-loads(needs a fullpnpm build). Neither reads a file this diff touches; CI runs both.node scripts/check-plugin-teardown-shape.mjs --self-testfirst refused (exit 3, shallow clone could not read its pinned fixture commit); after fetching that one commit it ran green (exit 0, 48 cases).check-sdui-manifest,check:sdui-reference,check:liveness,check:issue-citations,check:doc-authoringall exit 0.Tests and type-check
pnpm --dir ui exec vitest run packages/plugin-calendar/ packages/plugin-list/src/__tests__/ListView.calendar packages/plugin-view/src/__tests__/ObjectView.calendaron the merged tree:Test Files 74 passed (74),Tests 530 passed | 95 skipped (625)(the skips are pre-existing in plugin-calendar).pnpm --dir ui exec vitest run packages/plugin-list/src/__tests__/ListView.calendar packages/plugin-view/src/__tests__/ObjectView.calendar packages/types/→392 passed; specsrc/ui/calendar-config-initial-date.test.ts src/ui/view.test.ts→537 passed.pnpm --filter @object-ui/plugin-calendar --filter @object-ui/plugin-list --filter @object-ui/plugin-view --filter @object-ui/types run type-check→ all fourDone, VERDICT command-exit 0.pnpm --filter @objectstack/spec build && check:generatedon the merged tree →✓ All 14 generated artifacts are up to date.node scripts/gen-sdui-manifest-node.mjs+node scripts/gen-sdui-reference.mjsre-run on the merged tree.Reverse verification — five ablations, direction predicted before running
Each through
node scripts/ablation-replace.mjs(anchor must hit; restore proven by blob == HEAD and an emptygit diff HEAD). The tests import the source directly, so no build sits between the mutation and the run.ListViewforward: 3 forward rows red, CONTROL green.ObjectViewforward: 3 forward rows red, CONTROL green.useStatewithnew Date()only: the two macro rows red, 12 green.setCurrentDate(anchorDate): 5 anchor rows red (incl. the navigation-survives row, which waits for the seed), the shape / no-record / failure rows green.Human Minimum
packages/specholds no runtime logic.pnpm lintpasses. (Repo-wide lint is CI's run.)main, one pull request.packages/spectouched: its generated artifacts are regenerated and committed.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Generated by Claude Code