Repository navigation
归档后再次发布的知识文章,published_at 被重新打戳 —— 「原始发布日期不该移动」的意图只在 published→published 一条路径上成立 #780
Description
Activity
- addedbugSomething isn't workingSomething isn't workingpm:queueReady for the PM dispatch loopReady for the PM dispatch loop
on Aug 5, 2026 PM 分诊(修复线):可派发,入队
裁定(PM 可决的 restore-invariant 类,否决窗口:维护者在本单留言即翻案):采第一种答案——保持首次发布日期。语义生产者不是 PM 的偏好,是仓库自己已写下的意图:
test/hooks-runtime-service.test.ts的断言名「republishing must not move the original publish date」与 hook 注释同口径,缺陷只是实现把「republish」窄化成了previous.status === 'published'一条路径。修法方向:published_at已有值就不再打戳(不依赖 previous 的状态枚举,顺带对 #779 的批量路径也更稳健);last_reviewed_at照旧刷新(重新上架本身就是一次复核)。第二种答案(记录本次上架日期 + 第二个字段承载首发时间)是字段模型扩展,若维护者想要请在本单留言,那就转 needs-user-decision。派单时必修:补
archived → published的用例——现有那条用例喂previous: { status: 'published' },它的绿色正是缺陷的藏身之处(原报告已点明);反向验证按惯例先声明方向再跑。注意与 #779 的边界:本单只修单行路径上的语义(批量路径 previous 恒空是 #779 的地盘,别顺手)。
Generated by Claude Code
- addedpm:dispatchedDispatched to a dev agent by /pm-dispatchDispatched to a dev agent by /pm-dispatchand removedpm:queueReady for the PM dispatch loopReady for the PM dispatch loop
on Aug 5, 2026 🔒 认领(修复线 PM 派单):session_01VHrPAGEgFDoHjphqYG4BMa,分支
claude/issue-780-republish-published-at,worktreehotcrm-issue-780。文件面:src/objects/knowledge_article.hook.ts、test/hooks-runtime-service.test.ts、changeset。裁定见上一条 PM 分诊评论(published_at 已有值不打戳;必补 archived→published 用例;批量路径是 #779 的地盘不顺手)。
Generated by Claude Code
✅ 验收通过 — PR #789 已转 ready 并挂 auto-merge(CI 9/9 绿)。
判定要点:
- 裁定执行准确且判据选型比裁定更稳:「已有
published_at就不打戳」读作input.published_at ?? previous?.published_at——两个半边都实测有用(重新上架的原始日期在 previous 完整存量行;带历史日期的导入写在 input,且 insert 路径上自带值就是落库值)。不依赖状态枚举,对 批量写(multi: true)路径上 ctx.previous 恒为空 —— 15 个读 previous 的 hook 在该路径全部空转,知识文章可被批量写成「已发布但从未复核」 #779 的批量路径也更不易碎,正合裁定预期。 - 反向验证的诚实度是范本:预声明两条有判别力的用例必红(实红恰这两条),并预先声明 archived-but-never-published 那条无判别力(新旧实现同行为)、在用例注释里如实标注不冒充证据——这比全绿汇报有价值得多。
- 真引擎端到端补测,且把第一轮假红(裸引擎拿不到 kernel 私有
registerAuditHooks()装的内建,需复刻)如实写进报告——后来者在这里写 engine-backed hook 测试会踩同一坑,这条记录有复用价值。 - 覆盖完整:指向 published 的每条边都钉了(两条首发打戳、两条不动戳),外加两条边界(从未发布过的归档文章重新发布要打戳;写方自带日期不被覆写)。
- 边界纪律:批量路径(批量写(multi: true)路径上 ctx.previous 恒为空 —— 15 个读 previous 的 hook 在该路径全部空转,知识文章可被批量写成「已发布但从未复核」 #779 地盘)未碰;引擎相邻行为不做消费端兜底而是单独立 readonly: true 在 insert 路径上完全不生效,且 update 路径的剥离会连 hook 自己写的戳一起删掉 —— 已发布文章可落成 published_at = null #788;给 Seed doctrine says hooks never run over seed rows — they do, and the whole seed file is authored on that premise #617 留的是标注为「读码证据、非重跑」的补充——三处都各归其位。
- module-scope helper 会破坏 hook 降级打包这一约束的处理(判定内联进 handler)在 PR body 里写明了原因,合规。
#788 的分诊结果(PM 已核对上游在案记录,详见 #788 的分诊评论):第 1 点(insert 不剥离)大半消解——objectstack#3043 已于 7/18 修复,落点在入口级(REST/GraphQL/MCP/import 全设防),裸引擎路径的豁免是有意设计,你的探针走的正是后者;第 2 点(update 剥离连坐删 hook 写的值)成立且 REST 可达,已开上游镜像。#780 随本 PR 关闭。
Generated by Claude Code
- 裁定执行准确且判据选型比裁定更稳:「已有
- added a commit that references this issue
on Aug 10, 2026
发现于 #769(PR #776)的实测过程,与该 issue 的 label/filter 一致性无关,越界,单独记录。
事实
src/objects/knowledge_article.hook.ts的分支:wasPublished只认「上一状态正好是 published」。文章生命周期是draft → in_review → published → archived,而archived → published(重新上架)时previous.status === 'archived',于是走进第一个分支,published_at被覆盖成当下。实测(pinned 17.0.0-rc.2,真 object schema + 真 hook +
sys_fetch_previous_update内建的忠实复刻):为什么这算缺陷
test/hooks-runtime-service.test.ts已经把相反的意图写进了断言名和注释:但那条用例喂的是
previous: { status: 'published' }—— 只覆盖了 published→published 这一条路径。真正会让日期移动的路径(archived→published)没有用例,所以这个意图在测试里看起来是被守住的,实际只守住了一半。后果:一篇 2024 年发布、中途归档、今年重新上架的文章,
published_at会显示为今年 ——all_articles视图按published_at desc排序,这篇会跳到最前面,published_articles视图也把它当新文章。归档/重新上架本身是内容运营的常规动作,不是异常路径。修之前要定的一件事
「重新上架时
published_at应该是什么」本身是个产品语义问题,有两种合理答案:wasPublished放宽成「published_at已有值就不再打戳」)—— 读者看到的是内容首次面世的时间;按现有注释与测试断言的口吻,第一种更接近原意。但这是行为决策,留给 triage。
一并建议:修的时候给
hooks-runtime-service.test.ts补 archived→published 这条路径的用例 —— 现有那条用例的绿色正是这个缺陷藏住的原因。