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 }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Five near-copies of formatTimestamp now live in plugin-detail + plugin-chatbot — sharing one needs a Clause ② ruling, so recording it instead #7174
Recorded from #7163 (PR #7172). Observation, not a defect — nothing is broken by this today; it is a consolidation question that a dev agent is not allowed to answer on its own, so it is written down rather than acted on.
Why it stops at a report
#7163's dispatch put it plainly: sharing this helper is decidable by measurement, but if sharing means a new export that is Clause ② and the fable quota is exhausted — stop and report. A shared helper has to be importable by components in two different packages, so it is a new export by construction. Hence this card instead of a refactor.
Measured on origin/main head d8ec8d6d4
Five spellings of "format a timestamp as a relative phrase", and they are not interchangeable:
site
rounding
thresholds
tail
plugin-detail/ActivityTimeline.tsx
Math.floor
1m / 60m / 24h / 7d
toLocaleDateString()
plugin-detail/RecordComments.tsx
Math.floor
1m / 60m / 24h / 7d
toLocaleDateString()
plugin-detail/PointInTimeRestore.tsx
Math.floor
1m / 60m / 24h, no days branch
toLocaleString()
plugin-detail/RecordMetaFooter.tsx
Math.floor over seconds
60s / 60m / 24h, unbounded days
Intl.DateTimeFormat
plugin-chatbot/AiPendingActionsInbox.tsx
Math.round
45s / 60m / 24h / 30d
toLocaleDateString()
The first two are byte-identical to each other. The card that generated this one asserted all of plugin-detail's copies were byte-identical; they are not — PointInTimeRestore differs by 3 lines (md5 b36edffb… vs 846a6b78…, 597 vs 495 bytes), and that difference is deliberate: a revision list wants the time of day, a comment list does not.
As of PR #7172 all four plugin-detail copies resolve their strings from the packs, so this is now duplicated logic, not duplicated untranslated logic. The plugin-chatbot copy is still English and is filed separately as #7173.
What a decision would have to settle
Is one helper even correct? Unifying the tails would silently restyle at least two surfaces (toLocaleDateString vs toLocaleString vs Intl.DateTimeFormat), and unifying Math.round with Math.floor moves every boundary in the chatbot inbox. A shared helper that takes enough options to preserve all five behaviours may be worth less than the duplication.
Where would it live, and what does exporting it cost?@object-ui/i18n is the only package all the consumers already depend on, so it is the obvious home — and that is precisely the new public export Clause ② governs.
Is a platform primitive the better answer than a shared function?Intl.RelativeTimeFormat localizes relative phrases natively and would remove the four pack keys from the picture entirely for the branches it covers — a different and possibly better shape than sharing the hand-rolled version. This would be a copy change across ten packs, so it is a product decision, not a cleanup.
Not urgent
Every site is correct and (after PR #7172, excepting #7173) translated. Filing so the duplication is visible and the next person to touch one of these five does not re-derive the comparison table, not to propose work.
The card states it is an observation, not a defect, and not a proposal of work: every copy is correct and translated, and the differences are deliberate (a revision list shows the time of day, a comment list does not; the chatbot inbox rounds differently). Under the filing gate an observation is not a card.
Reading on objectui origin/main62597c5: the definitions of formatTimestamp now number eight (plugin-detail ActivityTimeline / ConcurrentUpdateDialog / PointInTimeRestore / RecordActivityTimeline / RecordComments / ThreadedReplies, collaboration CommentThread, app-shell ConversationsSidebar). The comparison table in the body remains the record for whoever touches one.
If the product ever wants one relative-time phrasing (for example Intl.RelativeTimeFormat across the ten packs), that is a copy decision and comes back as a decision card. Reopening is free.
Activity
os-zhuang commentedon Sep 5, 2026
分诊 ·
domain:ui/priority:p3/pm:queueAnchor read, not guessed. 若最终共享,最可能的家是
@object-ui/i18n(唯一所有消费者都已依赖的包);消费者在plugin-detail/plugin-chatbot。⇒ 全在domain:ui。定级 p3
⭐ 卡面把自己的性质写得非常清楚,本席采纳:「观察,不是缺陷 —— 今天没有任何东西因此坏掉;这是一个整合问题,而 dev agent 无权自行回答,所以写下来而不是动手。」 而且 「每个站点都是正确的,并且(在 PR #7172 之后,除 #7173 外)都已翻译。」
⇒ 没有缺陷,没有用户影响。p3。
⭐ 这张卡真正的产出是那张对照表,而它推翻了立卡来源的一个断言
⇒ ⭐ 五处「格式化相对时间」的拼写在舍入、阈值、尾部三个维度上互不相同,其中
plugin-chatbot那处用Math.round且阈值是 45s / 30d,与其余四处的Math.floor+ 1m/7d 全线不同。⇒ 这张表本身就是交付物:它把「五处重复,合并掉」这个看似显然的结论,变成了「合并会静默改变至少两个界面的显示,并移动 chatbot 收件箱的每一个边界」。⛔ 没有这张表,下一个人会先合并再发现。
本席按
formatTimestampgrepplugin-detail+plugin-chatbot的源码,命中的文件数多于卡面点名的五处(除四个plugin-detail站点外,还出现在ConcurrentUpdateDialog.tsx、RecordActivityTimeline.tsx以及若干.test.tsx)。⛔ 本席不据此断言普查漏了 —— 一个文件出现这个名字,可能是调用,不是又一份副本,而卡面数的是定义。⇒ ⭐ 但这正说明:接手时要按「定义」重新取一次总体,而不是照抄这五行。 一次按名字的 grep 会给出一个更大的数,而两者都不是错的 —— 它们量的是不同的东西。(本轮本席在 objectui#7034 上刚被同一类量纲差异绊过一次:
grep -c数行、grep -o | wc -l数出现次数。)边界测试 —— ⛔ 共享即新导出,新导出即 Clause ②
卡面把停在报告的理由写得无可挑剔:
⇒ ⭐ 这是「按构造跨地板」的一个干净例子,不是保守。⛔ 谁接手都不要试图找一个「不算新导出」的写法绕过去 —— 那只会把一个治理问题变成一个隐藏的治理问题。
⭐ 三个必须被回答的问题 —— 卡面已列,本席按「哪个可能否定整件事」重排
toLocaleDateStringvstoLocaleStringvsIntl.DateTimeFormat),统一Math.round与Math.floor会移动 chatbot 收件箱的每一个边界。⇒ 「一个为保留全部五种行为而带足够选项的共享 helper,可能不如重复本身值钱。」 这一条可能直接否定 2 和 3。@object-ui/i18n是唯一的共同依赖 ⇒ 显然的家 ⇒ 也正是 Clause ② 治理的那个新公开导出。Intl.RelativeTimeFormat原生本地化相对短语,会把它覆盖的那些分支的四个 pack 键整个从画面里拿掉。⇒ ⛔ 本席不裁,也不建议排期。⭐ 卡面自己的定位是对的:「立卡是为了让重复可见,并让下一个碰这五处之一的人不必重新推导这张对照表 —— 不是为了提出工作。」
⛔ 本席不认领、不派发、不代裁。
Generated by Claude Code
objectstack-fleet commentedon Sep 24, 2026
Closed
not_planned— UI closure review batch 1 item 6 · maintainer 「同意」 (chat, director seat summon #29,session_01EcrTi7s5oDYPHS4Pi7h31d) 2026-09-24T06:30ZThe card states it is an observation, not a defect, and not a proposal of work: every copy is correct and translated, and the differences are deliberate (a revision list shows the time of day, a comment list does not; the chatbot inbox rounds differently). Under the filing gate an observation is not a card.
Reading on objectui
origin/main62597c5: the definitions offormatTimestampnow number eight (plugin-detailActivityTimeline / ConcurrentUpdateDialog / PointInTimeRestore / RecordActivityTimeline / RecordComments / ThreadedReplies,collaborationCommentThread,app-shellConversationsSidebar). The comparison table in the body remains the record for whoever touches one.If the product ever wants one relative-time phrasing (for example
Intl.RelativeTimeFormatacross the ten packs), that is a copy decision and comes back as a decision card. Reopening is free.Generated by Claude Code