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
fix(timeline): honor startDateField when rendering a ListView timeline #3129
Run HotCRM with the published console and open crm_campaign/view/campaign_timeline.
The view declares timeline.startDateField: "start_date" and timeline.endDateField: "end_date"; every campaign has both values.
The timeline renders all seven records under No date.
The same start_date / end_date fields render correctly in the Calendar and Gantt views, so this is isolated to the timeline path.
Expected
The timeline should bucket records by their configured start date and render the corresponding date label.
Context
Found while recapturing the HotCRM marketing screenshot library after objectstack-ai/hotcrm#581. A metadata-only attempt to include the two date fields in the timeline view projection did not change the published-console behavior.
Release board: target:v17 applied — class ①, the ListView timeline ignores the view's declared timeline.startDateField and buckets every record under "No date" even though the same fields render correctly in Calendar and Gantt, so a declared, published view type does not work at all. One-time stock pass per objectstack#6904 (maintainer directive 2026-08-09).
Claim-status inquiry (objectui seat PM, session session_017Qqyix2QcnpUC9XeYVDzx3, 2026-08-10): this card is assigned to os-zhuang but the thread has no claim comment, and git ls-remote shows no branch matching issue-3129 and no PR. It is a class-① target:v17 release blocker, so it cannot sit in an unreadable claim state.
If you are actively on it: please post the standard claim comment (session ID + branch) so the claim is legible.
If the assignment is a leftover (e.g. from the triage pass rather than a claim): please drop the assignee, and the objectui seat will dispatch it in the current v17 push.
Per the stale-claim protocol, if there is no response within ~24h the seat will treat the claim as released and dispatch (this note starts the window; a live branch with commits always stops it).
This supersedes the claim-status inquiry above: the ~24h auto-reclaim window announced at 2026-08-10T02:42Z is void — do not reclaim or dispatch on silence; the hold is a made decision, not a pending one.
Restart condition: explicit maintainer go-ahead. target:v17 kept — at release time this surfaces on the board for an explicit disposition (fix / de-board / accept as known issue). Assignee left untouched.
Hold lifted + claim (objectui seat PM, session session_017Qqyix2QcnpUC9XeYVDzx3, 2026-08-10).
Provenance for the state change and the assignee takeover — maintainer, 2026-08-10, in the seat session chat, verbatim: 「objectui#3129(timeline 不认 startDateField)和 #3055(记录页审批入口)两张 v17 class-① 卡挂在 os-zhuang 名下,这两个任务你接着处理吧,os-zhuang本人已经确认过了」. This supersedes the same-day 「先暂停不处理」 hold (recorded above) and resolves the cross-account assignment: per the maintainer, os-zhuang has personally confirmed releasing the claim. Assignee moved os-zhuang → this seat on that basis.
Claim: PM loop round 3 (v17 board, class ①; direct maintainer instruction — dispatched above the five-concurrent soft target)
Session: session_017Qqyix2QcnpUC9XeYVDzx3
Branch: claude/issue-3129-timeline-startdatefield
Worktree: objectui-issue-3129
File surface: the ListView timeline rendering branch in app-shell (locate via startDateField consumers — InterfaceListPage.tsx / ObjectView.tsx face) + tests. ⛔ Region-exclusive vs in-flight siblings: not RecordDetailView.tsx / useRecordApprovals* (#3055), not the create-dialog/form path (#4047), not providers/HTTP client (#4042), not containers.tsx (#4027), not packages/cli / packages/fields.
Container & model: M, mode:subagent, model: opus
Serial constraints cleared: no open claim or PR on the timeline path; the 2026-08-06 triage warning stands — Calendar and Gantt already parse the same keys correctly, so the fix must reuse their resolution rather than add a fourth copy.
Premise re-verified at dispatch: startDateField consumers alive in app-shell on origin/main; no commits touched the timeline face since the triage re-verification.
options.calendar: { startDateField }, rendered as timeline
No date
The declared-key path was fixed by PR #3175 (5cb75b3, 2026-08-02) — one day after this card was filed, four days before triage. The 2026-08-06 triage re-verified that startDateFieldconsumers were alive, not that the defect still reproduced, and explicitly asked for a repro re-run before dispatch (「派发前请在当前 main + 当前已发布 console 上重跑一次复现」). That re-run had not happened.
The defect that does reproduce — and it matches this card's own isolation evidence
The last row is a live defect. A view whose date axis is bound under calendar is offered the Timeline visualization (the capability gate has always accepted options.calendar.startDateField as a timeline-resolvable axis) and then buckets every record into "No date" — while the calendar renders the very same field. That is precisely the report's isolation line: "the same start_date / end_date fields render correctly in the Calendar and Gantt views".
Two causes, both fixed in #4072: ListView's render branch never read calendar config even though its own gate promised it; and app-shell's object page fabricated startDateField: 'due_date' into options.timeline for every object view, which shadowed the fallback entirely.
Answering the triage structural warning (⚠️ 「不要写第四份」)
Confirmed: Calendar, Gantt and Timeline each carry their own resolution, in three files — packages/plugin-list/src/ListView.tsx, packages/app-shell/src/views/ObjectView.tsx, packages/plugin-view/src/ObjectView.tsx. There is no shared resolver to wire into. No fourth copy was written: the PR collapses the two timeline read-sites (capability gate + render branch) into one resolveTimelineDateBinding, and removes the app-shell copy outright by making that layer forward instead of resolve. Calendar and Gantt were left untouched as out of scope — unifying all three is a separate refactor.
Outstanding
I could not inspect the HotCRM crm_campaign/view/campaign_timeline metadata from this container, so I cannot state which of the two shapes that view actually carries. The PR is therefore Part of rather than Fixes — the published-console re-run triage asked for is still owed, and should be the thing that closes this card.
ACCEPT (objectui seat PM, session session_017Qqyix2QcnpUC9XeYVDzx3, review of record) — PR #4072, landing as Part of; this card stays open until the repro re-run (see disposition below).
Premise verdict, adopted after verifying the dev's probe evidence: the card's literal premise (declared timeline.startDateField ignored) was fixed by PR #3175 on 2026-08-02 — one day after filing, four days before triage; the 2026-08-06 triage verified consumers were alive, not that the defect reproduced, and its requested repro re-run never happened before dispatch. The surviving defect matches the card's own isolation evidence: a view whose date axis is bound under calendar was OFFERED the Timeline visualization (the capability gate accepted it) while the render branch never read calendar config — compounded by app-shell fabricating startDateField: 'due_date' into every object view's timeline options, which shadowed the fallback and is indistinguishable from a real binding downstream.
What shipped: one resolveTimelineDateBinding(schema) consumed by BOTH the gate and the render branch (spec key > legacy alias, timeline > calendar, both nestings); app-shell now forwards only what the view declared (fabricated due_date removed). Two timeline read-site copies became one, the app-shell copy deleted — no fourth copy, per the triage warning; Calendar/Gantt untouched. Both directions pinned; two reverse verifications with predicted directions (5 red dropping calendar from the resolver; exactly 2 red restoring the fabricated default). 424 + 2929 tests green locally; all 20 CI checks completed, 0 failures; changeset minor.
Disposition (what closes this card): after #4072 merges, re-run the original HotCRM crm_campaign/view/campaign_timeline repro (the console re-run triage asked for on 2026-08-06). If the view binds its dates under calendar, this PR is the fix and the card closes on that evidence; if it still buckets to "No date", there is a third cause and the card stays open with new data. ⛔ Do not close this card on the merge alone. The shared cross-view-type date-resolver idea (nine inline resolutions across three files) is deliberately NOT filed — the triage thread owns the observation; it goes to the maintainer via the round report as an optional follow-up.
Landing next: flipping ready and driving to MERGED.
Close gate met — HotCRM repro re-run: PASS (objectui seat PM, session session_017Qqyix2QcnpUC9XeYVDzx3; independent dogfood verification agent, full browser run).
Provenance: console = objectui origin/main tip 9154d9e90 (contains PR #4072's merge bd863fe49, ancestor-verified), server = HotCRM @ 333259a47 on published @objectstack/* 17.0.0-rc.5, fresh DB + seed, real login.
Evidence, against the original repro's exact surface (/apps/crm_enterprise/crm_campaign/view/campaign_timeline):
Server serves the card's literal authoring shape: timeline: { startDateField: "start_date", endDateField: "end_date", titleField: "name", groupByField: "channel", scale: "month" }.
Discriminator held: all 7 seeded campaigns share created_at = 2026-08-10 (boot time) while start_date spreads 2026-07-06 → 2026-09-06 — so axis position can only come from the declared field.
DOM read-back: 7/7 items render <time datetime> exactly equal to their API start_date (e.g. Developer Content Marketing Push 2026-07-06, SaaSCon 2026 Trade Show 2026-09-06); end dates match end_date; ascending sort by start_date; channel lanes per groupByField. The creation date appears nowhere; the original symptom ("No date" × 7) appears nowhere.
Negative control: a view with NO timeline config (all_campaigns) switched to Timeline renders all 7 under "NO DATE" — the renderer does not opportunistically grab a date column, ruling out a false positive.
One caveat for the record: this verifies the objectui console at main. The vendored console inside @objectstack/cli 17.0.0-rc.5 picks up #4072 only at the next objectui pin/rebuild — i.e. the fix reaches end users with the next release pin bump (same vehicle as the rest of this wave's console fixes).
Closing as completed — fix merged (PR #4072) + original repro re-run green.
Activity
fix(timeline,list): honour the `timeline.dateField` alias on the spec…
fix(studio,timeline,list): 表单设计器解析对象翻译;timeline 认它自己配置的日期字段 (objectst…
os-zhuang commentedon Aug 6, 2026
分诊:
pm:queue。 ⛔ 本仓不打domain:*(objectui 整仓座位)。判级理由
具体缺陷,复现明确(HotCRM
crm_campaign/view/campaign_timeline,视图已声明timeline.startDateField: "start_date"/endDateField: "end_date"且七条记录都有值,timeline 全部落在 No date 下)。隔离证据强:同样两个字段在 Calendar 与 Gantt 视图渲染正常 ⇒ 缺陷被钉在 timeline 这一条渲染路径上,不是元数据或数据问题。立单者还排除了一个假说:纯元数据的补救(把两个日期字段加进 timeline 视图投影)不改变已发布 console 的行为 —— 这条阴性结果同样有价值,它把修复面从元数据推到了渲染器代码。
一句话验收标准:timeline 按
startDateField分桶并渲染对应日期标签。落点锚定理由(⛔ 不按标题词汇猜)
startDateField在origin/main的消费方集中在本仓packages/app-shell(views/InterfaceListPage.tsx、views/CreateViewDialog.tsx、providers/MetadataProvider一族)⇒ 修复落在本仓的 timeline 渲染分支,不跨仓、不触packages/spec(spec 已正确声明这两个键,缺陷在消费侧)⇒ 不走跨座位转移。过时前提检查
git -C /home/user/objectui fetch origin main已跑,startDateField消费方健在。查重
三仓搜 timeline /
startDateField/ No date 分桶:无重复单。上游 objectstack-ai/hotcrm#581 是发现场景(重拍营销截图库时撞见),不是同题单。Calendar / Gantt 已经把同一对字段读对了 —— 先读那两条路径怎么解析,再改 timeline。三条视图各自解析同一组视图键正是「一个词汇在多处各自实现」的形状;若发现三者确实各写了一份,请在修复中把 timeline 接到已有的那份上,并在单上记一句,⛔ 不要写第四份。
本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
os-project-manager commentedon Aug 9, 2026
Release board:
target:v17applied — class ①, the ListView timeline ignores the view's declaredtimeline.startDateFieldand buckets every record under "No date" even though the same fields render correctly in Calendar and Gantt, so a declared, published view type does not work at all. One-time stock pass per objectstack#6904 (maintainer directive 2026-08-09).Generated by Claude Code
yinlianghui commentedon Aug 10, 2026
Claim-status inquiry (objectui seat PM, session
session_017Qqyix2QcnpUC9XeYVDzx3, 2026-08-10): this card is assigned toos-zhuangbut the thread has no claim comment, andgit ls-remoteshows no branch matchingissue-3129and no PR. It is a class-①target:v17release blocker, so it cannot sit in an unreadable claim state.Per the stale-claim protocol, if there is no response within ~24h the seat will treat the claim as released and dispatch (this note starts the window; a live branch with commits always stops it).
Generated by Claude Code
yinlianghui commentedon Aug 10, 2026
🕒
pm:on-hold(objectui seat PM, sessionsession_017Qqyix2QcnpUC9XeYVDzx3, 2026-08-10)target:v17kept — at release time this surfaces on the board for an explicit disposition (fix / de-board / accept as known issue). Assignee left untouched.Generated by Claude Code
yinlianghui commentedon Aug 10, 2026
Hold lifted + claim (objectui seat PM, session
session_017Qqyix2QcnpUC9XeYVDzx3, 2026-08-10).Provenance for the state change and the assignee takeover — maintainer, 2026-08-10, in the seat session chat, verbatim: 「objectui#3129(timeline 不认 startDateField)和 #3055(记录页审批入口)两张 v17 class-① 卡挂在 os-zhuang 名下,这两个任务你接着处理吧,os-zhuang本人已经确认过了」. This supersedes the same-day 「先暂停不处理」 hold (recorded above) and resolves the cross-account assignment: per the maintainer,
os-zhuanghas personally confirmed releasing the claim. Assignee moved os-zhuang → this seat on that basis.Claim: PM loop round 3 (v17 board, class ①; direct maintainer instruction — dispatched above the five-concurrent soft target)
Session:
session_017Qqyix2QcnpUC9XeYVDzx3Branch:
claude/issue-3129-timeline-startdatefieldWorktree:
objectui-issue-3129File surface: the ListView timeline rendering branch in app-shell (locate via
startDateFieldconsumers —InterfaceListPage.tsx/ObjectView.tsxface) + tests. ⛔ Region-exclusive vs in-flight siblings: notRecordDetailView.tsx/useRecordApprovals*(#3055), not the create-dialog/form path (#4047), not providers/HTTP client (#4042), notcontainers.tsx(#4027), notpackages/cli/packages/fields.Container & model: M,
mode:subagent,model: opusSerial constraints cleared: no open claim or PR on the timeline path; the 2026-08-06 triage warning stands — Calendar and Gantt already parse the same keys correctly, so the fix must reuse their resolution rather than add a fourth copy.
Premise re-verified at dispatch:
startDateFieldconsumers alive in app-shell onorigin/main; no commits touched the timeline face since the triage re-verification.Generated by Claude Code
yinlianghui commentedon Aug 10, 2026
Dev report (os-dev subagent, branch
claude/issue-3129-timeline-startdatefield) — draft PR #4072.The card's literal premise no longer reproduces
Drove
ListViewinto the realObjectTimelineon currentorigin/mainand read the bucket headers for every authoring shape:timeline: { startDateField, endDateField }(this card's shape)Lateroptions.timeline: { startDateField, endDateField }(what app-shell emits)Lateroptions.timeline: { dateField }(legacy alias)Latertimeline: { startDateField, scale: 'month' }Lateroptions.calendar: { startDateField }, rendered as timelineNo dateThe declared-key path was fixed by PR #3175 (
5cb75b3, 2026-08-02) — one day after this card was filed, four days before triage. The 2026-08-06 triage re-verified thatstartDateFieldconsumers were alive, not that the defect still reproduced, and explicitly asked for a repro re-run before dispatch (「派发前请在当前 main + 当前已发布 console 上重跑一次复现」). That re-run had not happened.The defect that does reproduce — and it matches this card's own isolation evidence
The last row is a live defect. A view whose date axis is bound under
calendaris offered the Timeline visualization (the capability gate has always acceptedoptions.calendar.startDateFieldas a timeline-resolvable axis) and then buckets every record into "No date" — while the calendar renders the very same field. That is precisely the report's isolation line: "the samestart_date/end_datefields render correctly in the Calendar and Gantt views".Two causes, both fixed in #4072:
ListView's render branch never read calendar config even though its own gate promised it; and app-shell's object page fabricatedstartDateField: 'due_date'intooptions.timelinefor every object view, which shadowed the fallback entirely.Answering the triage structural warning (⚠️ 「不要写第四份」)
Confirmed: Calendar, Gantt and Timeline each carry their own resolution, in three files —
packages/plugin-list/src/ListView.tsx,packages/app-shell/src/views/ObjectView.tsx,packages/plugin-view/src/ObjectView.tsx. There is no shared resolver to wire into. No fourth copy was written: the PR collapses the two timeline read-sites (capability gate + render branch) into oneresolveTimelineDateBinding, and removes the app-shell copy outright by making that layer forward instead of resolve. Calendar and Gantt were left untouched as out of scope — unifying all three is a separate refactor.Outstanding
I could not inspect the HotCRM
crm_campaign/view/campaign_timelinemetadata from this container, so I cannot state which of the two shapes that view actually carries. The PR is thereforePart ofrather thanFixes— the published-console re-run triage asked for is still owed, and should be the thing that closes this card.Generated by Claude Code
yinlianghui commentedon Aug 10, 2026
ACCEPT (objectui seat PM, session
session_017Qqyix2QcnpUC9XeYVDzx3, review of record) — PR #4072, landing asPart of; this card stays open until the repro re-run (see disposition below).Premise verdict, adopted after verifying the dev's probe evidence: the card's literal premise (declared
timeline.startDateFieldignored) was fixed by PR #3175 on 2026-08-02 — one day after filing, four days before triage; the 2026-08-06 triage verified consumers were alive, not that the defect reproduced, and its requested repro re-run never happened before dispatch. The surviving defect matches the card's own isolation evidence: a view whose date axis is bound undercalendarwas OFFERED the Timeline visualization (the capability gate accepted it) while the render branch never read calendar config — compounded by app-shell fabricatingstartDateField: 'due_date'into every object view's timeline options, which shadowed the fallback and is indistinguishable from a real binding downstream.What shipped: one
resolveTimelineDateBinding(schema)consumed by BOTH the gate and the render branch (spec key > legacy alias,timeline>calendar, both nestings); app-shell now forwards only what the view declared (fabricateddue_dateremoved). Two timeline read-site copies became one, the app-shell copy deleted — no fourth copy, per the triage warning; Calendar/Gantt untouched. Both directions pinned; two reverse verifications with predicted directions (5 red dropping calendar from the resolver; exactly 2 red restoring the fabricated default). 424 + 2929 tests green locally; all 20 CI checks completed, 0 failures; changeset minor.Disposition (what closes this card): after #4072 merges, re-run the original HotCRM
crm_campaign/view/campaign_timelinerepro (the console re-run triage asked for on 2026-08-06). If the view binds its dates undercalendar, this PR is the fix and the card closes on that evidence; if it still buckets to "No date", there is a third cause and the card stays open with new data. ⛔ Do not close this card on the merge alone. The shared cross-view-type date-resolver idea (nine inline resolutions across three files) is deliberately NOT filed — the triage thread owns the observation; it goes to the maintainer via the round report as an optional follow-up.Landing next: flipping ready and driving to MERGED.
Generated by Claude Code
yinlianghui commentedon Aug 10, 2026
Close gate met — HotCRM repro re-run: PASS (objectui seat PM, session
session_017Qqyix2QcnpUC9XeYVDzx3; independent dogfood verification agent, full browser run).Provenance: console = objectui
origin/maintip9154d9e90(contains PR #4072's mergebd863fe49, ancestor-verified), server = HotCRM @333259a47on published@objectstack/*17.0.0-rc.5, fresh DB + seed, real login.Evidence, against the original repro's exact surface (
/apps/crm_enterprise/crm_campaign/view/campaign_timeline):timeline: { startDateField: "start_date", endDateField: "end_date", titleField: "name", groupByField: "channel", scale: "month" }.created_at = 2026-08-10(boot time) whilestart_datespreads 2026-07-06 → 2026-09-06 — so axis position can only come from the declared field.<time datetime>exactly equal to their APIstart_date(e.g. Developer Content Marketing Push2026-07-06, SaaSCon 2026 Trade Show2026-09-06); end dates matchend_date; ascending sort bystart_date; channel lanes pergroupByField. The creation date appears nowhere; the original symptom ("No date" × 7) appears nowhere.all_campaigns) switched to Timeline renders all 7 under "NO DATE" — the renderer does not opportunistically grab a date column, ruling out a false positive.timeline(the fix(studio,timeline,list): 表单设计器解析对象翻译;timeline 认它自己配置的日期字段 (#3134, #3129) #3175 shape, re-pinned by fix(timeline): bind the timeline to the date axis the view declares (#3129) #4072); no third cause.One caveat for the record: this verifies the objectui console at main. The vendored console inside
@objectstack/cli17.0.0-rc.5 picks up #4072 only at the next objectui pin/rebuild — i.e. the fix reaches end users with the next release pin bump (same vehicle as the rest of this wave's console fixes).Closing as completed — fix merged (PR #4072) + original repro re-run green.
Generated by Claude Code
fix(timeline): bind the timeline to the date axis the view declares (o…