build: bound retained chat assets - #4233
Conversation
huangruiteng
left a comment
There was a problem hiding this comment.
Request changes conclusion
审阅绑定 exact head:e0c6916702e59e68cf1d8963da721a6b590743fb。结论:REQUEST_CHANGES。
动机
当前 vite.chat.config.ts 使用 emptyOutDir=false 保护旧页面引用,但副作用是每次 chat bundle hash 变化都会把旧 JS/CSS 留在仓库和 wheel 里。这个 PR 用“当前 generation + 一个上一代 generation”的 manifest 管理生命周期,并删除一百多个陈旧资产,问题真实、方案方向也合理。
改动思路
新的 Vite plugin 在 build 开始时读取旧 index 和 asset-retention.json,在 writeBundle 时把本次 bundle 作为 generation 0,最多再保留一个覆盖旧 index 的 generation,然后删除其它 loopx/web/chat/assets/*。现有 dashboard-pwa-bundle-smoke.py 同时检查 index 引用、manifest generation 与实际文件集合。
这套 owner 放置正确:生成/清理仍由 chat build 负责,manifest 是 derived projection,Python smoke 是 integration consistency guard。问题不在 plugin 主算法,而在这批跟旧 base 绑定的 generated deletions已经落后于当前 main。
具体改动
103 个文件、+101/-8339:一个 Vite config、一个 Python smoke、一个 20 行 retention manifest,以及约一百个生成资产删除。精确 head 上实际执行 npm ... build:chat 成功,TypeScript check 与 Vite build 通过;生成结果与 commit 完全一致,剩 13 个 assets、一个 generation;PWA smoke、Ruff、git diff --check 均通过。远端 23 个 checks 也全部成功或按预期 skip。
关键代码讲解
vite.chat.config.ts:12-60选择 current/previous generation,并在 53–55 行删除不在 retention set 的文件。asset-retention.json当前 generation 记录的是index-CB5NhzNw.js/index-dKo36DAJ.css。dashboard-pwa-bundle-smoke.py:56-74正确要求当前 index refs 属于 generation 0、retained set 等于磁盘文件并且全部存在。
对主干的风险
有一个可直接复现的 P1 blocker:
- 这个 behind head 与当前 main 可以无冲突合并,但合并结果会删除当前页面正在引用的 CSS。 当前
origin/main@49cee5b30fef9f5bacddb548dc37809d7aa71be3的/chat/index.html引用index-DNTHj6za.js和index-Yu1zpL1O.css。本 PR 基于旧 base,把index-Yu1zpL1O.css列为 stale 并删除,同时写入旧的 CB5/dKo manifest;它没有改 index,因此 Git 三方合并保留 main 的 DNTH/Yu1 index、应用 CSS 删除和旧 manifest,而且报告 mergeable。
我用真实 git merge-tree --write-tree 生成当前 main + PR head 的结果,再把该 tree 导出并执行 PR 自己新增的 smoke:它稳定失败,报当前 index 引用集合 {DNTH JS, Yu1 CSS} 不属于 generation 0;tree 中 Yu1 CSS 也确实不存在。也就是说 exact-head 所有绿灯没有覆盖最终集成树,直接合并会让 packaged /chat 首屏缺样式。
最小修复:rebase 到最新 main,重新执行 build:chat,把 index、manifest、保留资产和删除集合当成一个原子生成物提交;然后在新 exact head/merge result 上跑同一 smoke。长期 guard 应让 CI 对 proposed merge commit/tree 跑这个 smoke,不能只验证 stale head。
我的整体评价
我支持两代 retention,也认为 plugin + derived manifest + existing smoke 是够小、够可维护的方案;不需要另起 cleanup CLI 或服务端 cache 框架。但 generated asset PR 的停止条件必须是“最新集成树自洽”,不是“旧 exact head 自洽”。请完成 rebase/regenerate 后再复审。
Future-facing pass:本轮最值得补的是 final-merge-tree consistency gate;更长的 stale-tab window、service worker/CDN 策略没有当前证据,不应顺手扩大。
English verdict: REQUEST_CHANGES on exact head e0c6916702e59e68cf1d8963da721a6b590743fb. The two-generation Vite retention design and exact-head build are sound, but this behind branch's generated deletion set is stale against origin/main@49cee5b30fef9f5bacddb548dc37809d7aa71be3. A real conflict-free merge tree keeps main's DNTH/Yu1 index, deletes index-Yu1zpL1O.css, and keeps the old CB5/dKo manifest; the PR's own PWA smoke then fails. Rebase, regenerate the entire chat bundle atomically, and run the same smoke on the final exact head/merge result.
b5c5635 to
7b689bd
Compare
|
@huangruiteng @maxliux5 Current exact head 387cbfe is synchronized with main 3aa05cc. The stale generated-asset blocker is fixed: the chat bundle was rebuilt from the current main inputs, retention now keeps the current and previous complete generations, and missing generations are excluded. Local build, PWA bundle smoke, full browser smoke, mypy, Ruff, and diff checks passed. Current GitHub checks are all green, including Frontstage, desktop artifacts, merge-gate, Stage2C, and four pytest shards. Please re-review this exact head and clear the stale CHANGES_REQUESTED state if no new finding remains. |
`python -m mypy` fails on current main with seven `no-any-return` errors in `loopx/control_plane/todos/decision_scope.py`. The module's private `_evaluate` helper validates one typed effect-runtime result and returns `Any`, but every public wrapper declares a concrete `dict`, `bool`, or list return type, so strict mode rejects each call site. Annotate the seven call sites with `cast(...)` to the return type they already promise. This is a type-level annotation only: no runtime branch, value, or call sequence changes, and `_evaluate` keeps its single validated boundary. The same fix is currently carried inside #4233, which is blocked on chat asset retention changes. Every pull request inherits this failure through the required `Type-check kernel contracts` step and the `merge-gate`, so it is extracted here as a standalone repair. Validation: - `python -m mypy` -> Success: no issues found in 22 source files - `python -m pytest tests/control_plane/test_todo_decision_scope_consistency.py tests/control_plane/test_todo_decision_scope_lifecycle.py tests/control_plane/test_todo_decision_scope_cli_validation.py tests/control_plane/test_user_gate_lane_progress.py tests/control_plane/test_scoped_gate_successor_tool_behavior.py` -> 56 passed - `python examples/control_plane/bounded-context-namespace-smoke.py` -> ok Signed-off-by: song <liusongstep@gmail.com>
huangruiteng
left a comment
There was a problem hiding this comment.
Request changes conclusion
审阅绑定 exact head:387cbfeabea1ccd79abd87257fadb320a7adcd36。结论:REQUEST_CHANGES。
[P1] 请先 rebase 最新 main,保留主干的两个 superseding shared files,并从最终 source 原子重建 chat bundle。 当前 GitHub mergeStateStatus=DIRTY;git merge-tree --write-tree origin/main@84334f794126735a83a6cfb77882dd58ca8066d9 <head> 在 examples/personal-workspace-browser-smoke.mjs 与 loopx/control_plane/todos/decision_scope.py 冲突。PR 侧是旧单体 browser smoke 和 cast-only decision-scope 适配,而主干已经分别完成模块化拆分及 typed projection schema/shape hardening。不能通过选 PR 一侧来解冲突;rebase 后应保留主干版本,再执行 build:chat、提交最终 index/manifest/assets 原子结果并重跑 smokes。
动机
旧 vite.chat.config.ts 为保护滚动升级中的 stale page 使用 emptyOutDir=false,但从不删除历史 hash 资产。baseline 因此积累到 117 个 asset、约 80.23 MB,并会随每次 hash 变化继续增长。直接切 emptyOutDir=true 又会让仍引用上一代 index 的页面白屏。本 PR 把停止条件明确为“当前完整 generation + 一个上一代完整 generation”,在保留一轮滚动兼容的同时,把仓库、wheel 和构建产物增长约束为常量。
改动思路
生命周期 owner 放在现有 Vite chat build:plugin 在配置阶段读取旧 index 与旧 manifest,在 writeBundle 阶段把本次 Rollup bundle 作为 generation 0,选择一个文件完整、非冗余的 previous generation,删除其余 assets/*,再写回 derived asset-retention.json。路径被约束为单层 assets/[A-Za-z0-9._-]+,缺文件的 generation 不会被误认为完整,manifest malformed 会 fail closed。
现有 dashboard-pwa-bundle-smoke.py 被扩展为独立 readback:要求 1–2 generations、当前 index refs 属于 generation 0、manifest union 与磁盘文件集合完全一致且全部存在。相比一次性删文件或另做 cleanup CLI,这个方案复用了正确的 build owner,也把未来每次生成纳入同一规则。
具体改动
exact-head diff 为 108 文件、+138/-8609:65 行 Vite lifecycle plugin、23 行 smoke、35 行生成 manifest、103 个旧 hash 资产删除,以及两个已被 main supersede 的 integration carryover。资产从 117 个/80,233,332 bytes 降至 14 个/2,254,886 bytes;当前 generation 是 index-Dk5Y5CRw.js + index-DYYo3B8I.css 与共享 fonts,上一代保留 index-B88OPx8f.js。
关键代码讲解
retainedChatAssets(apps/presentation/dashboard/vite.chat.config.ts:12):验证旧 manifest,计算 current/prior generations,跳过缺文件或冗余 generation,最多保留两个集合。writeBundle(同文件 35–60):只在 build-time 操作已解析的 chat assets 目录,删除不在 retained set 的文件并写 derived manifest;运行时 serving 不写盘。assert_bounded_chat_assets(examples/dashboard-pwa-bundle-smoke.py:56):从 index、manifest、disk 三个独立视角校验同一 bundle contract。loopx_chat_asset_retention_v1:是 build 输出投影,不是需要人工同步的第二份意图状态。
对主干的风险
我在 exact head 上执行了两次完整 npm run build:chat,两次均通过且 loopx/web/chat 保持 clean;PWA bundle smoke 通过;使用独立端口的 packaged Personal Workspace browser smoke 通过;Ruff、focused mypy 与 git diff --check 通过。临时副本上的 orphan asset 与 invalid schema mutation 都被新增 smoke 拒绝。远端 28 个 checks 全部成功或按预期 skip,说明上一轮“旧 base 会删除当前 index CSS”的 blocker 已在这个 head 相对 3aa05cc 修好。
但 exact-head green 不等于当前 final tree green。latest main 已在两个共享文件上前进,GitHub 和真实 merge-tree 都判定冲突;若选错冲突侧,会回退广泛的 Dashboard acceptance 和 control-plane validation。即使当前 main 的 chat index refs 仍与本 head 相同,rebase 后仍应从最终 source 重跑 build,避免让 generated manifest/deletion set 脱离最终树。
我的整体评价
两代 retention 的产品取舍、owner 放置、manifest 约束与独立 smoke 都合理;大部分 8,609 行删除是必要的历史生成物清理,不应因为 diff 大就否定。也没有证据需要顺手引入 CDN/service-worker 窗口或 bundle-splitting 框架。当前唯一 blocker 是 final integration freshness:请 rebase、保留 main 的模块化 smoke 与 typed decision-scope boundary、原子重建产物并让新 exact head checks 通过,再复审。
Future-facing pass:最有价值的 companion change 是让 CI 始终验证 proposed final tree 的 bundle consistency;更长 retention window 在没有真实 stale-tab 证据前应继续 defer。
English verdict: REQUEST_CHANGES on exact head 387cbfeabea1ccd79abd87257fadb320a7adcd36. The two-generation retention design is sound: assets drop from 117/80.23 MB to 14/2.25 MB, two deterministic builds stay clean, PWA and packaged-browser checks pass, negative mutations reject, and all 28 remote checks are green. But latest main now conflicts in two unrelated shared files; rebase while keeping main's modular browser and typed decision-scope implementations, regenerate the final chat bundle atomically, and rerun the final-tree checks.
b0b0180 to
e61bcc1
Compare
|
Updated exact head: Resolved the original merge conflicts by retaining the superseding main implementations in While syncing current main, the Windows lifecycle check exposed a main regression: Python on Windows has no external IANA timezone database, so validating the built-in Validation recorded on the final head:
The branch is clean, contains current main |
|
@huangruiteng GitHub did not allow this fork contributor to add you through |
|
@huangruiteng Updated exact head 06699be onto current main 787e8dd. The superseding main versions of both shared conflict files were retained, then the chat bundle was rebuilt twice from the final source and remained clean; the PWA bundle smoke passed. Fresh exact-head CI is running; please re-review this head after it completes. |
06699be to
d7d97c3
Compare
|
Exact head |
Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
Signed-off-by: duanjialing.777 <duanjialing.777@bytedance.com>
d7d97c3 to
66d274c
Compare
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
评审对象:#4233,最终 exact head 66d274c62155ca6c8566a67e37baa784c9ee89ce,base b9e8c74d4f852a1444c44cca7ac108911407c531。
Findings
没有新的 correctness blocker。此前发现的 stale generated deletion 与落后 main 问题已通过 rebase 和最终 source 重建处理;没有把 #4281 的无关 Windows runtime 修复混入本 PR。
动机
vite.chat.config.ts 使用 emptyOutDir=false 保护滚动升级中的旧页面,但旧 hash 资产会持续累积。这个 PR 将 chat bundle 约束为当前 generation 加一个完整 previous generation,避免仓库、wheel 和构建产物无界增长。
改动思路
由现有 Vite chat build 负责读取旧 index/retention manifest、选择完整 generation、写入新的 derived manifest 并删除其余 assets;没有新增 cleanup CLI、daemon 或运行时 provider。现有 dashboard-pwa-bundle-smoke.py 负责从 index、manifest、磁盘三方校验一致性。
具体改动
vite.chat.config.ts增加 bounded two-generation retention plugin,并对 malformed/missing generation fail closed。- 新增
loopx_chat_asset_retention_v1manifest,记录当前和上一代完整资产集合。 - 清理历史 hash 资产,保留当前 bundle 与一个滚动升级窗口。
- 扩展 PWA smoke,要求 index 引用、manifest union 和实际磁盘文件集合完全一致。
- rebase 到
main@b9e8c74d4后,从最终 source 重新构建两次,生成树保持 clean。
对主干的风险
主要风险是生成文件与 build plugin 脱节;本轮在 rebase 后运行 npm run build:chat,两次结果均与 commit 一致,随后 PWA bundle smoke、Ruff、mypy、Python compile 和 diff check 全部通过。远端 exact-head required checks 已全部通过:Windows PowerShell、Dashboard、四个 Python shards、Stage2C e2e/installed/mutants/correctness、pytest、merge-gate、Node compatibility、静态检查、Frontstage、desktop artifacts、DCO 和 dependency review 均为成功;Sonar non-blocking 检查也已成功。
我的整体评价
方案把资产生命周期放在正确的 build owner,manifest 是可验证的 derived projection,保留窗口有明确上限,且没有扩大到 CDN、service worker 或运行时缓存框架。此前评审指出的 final-tree freshness 已修复,exact-head required CI 已全绿,建议合并。
English verdict: APPROVE — exact head 66d274c62155ca6c8566a67e37baa784c9ee89ce; the stale generated-asset blocker is resolved by rebasing onto current main and atomically rebuilding the bounded chat bundle, with local and exact-head required checks green.
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
评审对象:#4233,最终 exact head 66d274c62155ca6c8566a67e37baa784c9ee89ce,base b9e8c74d4f852a1444c44cca7ac108911407c531。
Findings
没有新的 correctness blocker。此前发现的 stale generated deletion 与落后 main 问题已通过 rebase 和最终 source 重建处理;没有把 #4281 的无关 Windows runtime 修复混入本 PR。
动机
vite.chat.config.ts 使用 emptyOutDir=false 保护滚动升级中的旧页面,但旧 hash 资产会持续累积。这个 PR 将 chat bundle 约束为当前 generation 加一个完整 previous generation,避免仓库、wheel 和构建产物无界增长。
改动思路
由现有 Vite chat build 负责读取旧 index/retention manifest、选择完整 generation、写入新的 derived manifest 并删除其余 assets;没有新增 cleanup CLI、daemon 或运行时 provider。现有 dashboard-pwa-bundle-smoke.py 负责从 index、manifest、磁盘三方校验一致性。
具体改动
vite.chat.config.ts增加 bounded two-generation retention plugin,并对 malformed/missing generation fail closed。- 新增
loopx_chat_asset_retention_v1manifest,记录当前和上一代完整资产集合。 - 清理历史 hash 资产,保留当前 bundle 与一个滚动升级窗口。
- 扩展 PWA smoke,要求 index 引用、manifest union 和实际磁盘文件集合完全一致。
- rebase 到
main@b9e8c74d4后,从最终 source 重新构建两次,生成树保持 clean。
对主干的风险
主要风险是生成文件与 build plugin 脱节;本轮在 rebase 后运行 npm run build:chat,两次结果均与 commit 一致,随后 PWA bundle smoke、Ruff、mypy、Python compile 和 diff check 全部通过。远端 exact-head required checks 已全部通过:Windows PowerShell、Dashboard、四个 Python shards、Stage2C e2e/installed/mutants/correctness、pytest、merge-gate、Node compatibility、静态检查、Frontstage、desktop artifacts、DCO 和 dependency review 均为成功;Sonar non-blocking 检查也已成功。
我的整体评价
方案把资产生命周期放在正确的 build owner,manifest 是可验证的 derived projection,保留窗口有明确上限,且没有扩大到 CDN、service worker 或运行时缓存框架。此前评审指出的 final-tree freshness 已修复,exact-head required CI 已全绿,建议合并。
English verdict: APPROVE — exact head 66d274c62155ca6c8566a67e37baa784c9ee89ce; the stale generated-asset blocker is resolved by rebasing onto current main and atomically rebuilding the bounded chat bundle, with local and exact-head required checks green.
Summary
Validation
npm --prefix apps/presentation/dashboard run build:chatbuild:chatwith an identical resulting diffpython3 examples/dashboard-pwa-bundle-smoke.pynpm --prefix apps/presentation/dashboard run smoke:personal-workspace-packagedgit diff --checkloopx canary premerge --from-git-diff --tier standard(passed; public/private scan clean)No local validation failures, skips, or manual holds. The current first-screen sources and bundle hashes are unchanged relative to the latest
mainbaseline.Future-facing pass
Applied the bounded retention rule at the existing Vite build owner. Broader bundle splitting is deferred until bundle measurements show a concrete need.