web-shell app.js 模块化重构 + admin-ds 假成功态修复 + CLI IM 命令#1
Open
rsagacom wants to merge 38 commits into
Open
Conversation
- 修复: FakeDocument 缺 getElementById → 测试 125 fails→759/0 - 拆分: styles.css 14,885→9,910行, 拆出 base(385)/scene(1685)/chat(2914) - 提取: shell-identity.js (4纯函数/28行/9测试), app.js 8913→8887行 - 测试: admin-ds ban/unban/freeze/unfreeze runtime + static 共+14测试 - 功能: 场景编辑器新增JSON导出/复制/模态框 - 配置: .gitignore 新增 state.contract.* 排除 Co-Authored-By: DeepSeek v4 Pro <noreply@deepseek.com>
- CLI: export/edit/recall 命令补齐 - TUI: edit/recall 命令补齐 - Gateway: unsanction 安全债 + crate-wide test auth 修复 - Release gate: 26 smoke脚本全部有 quick unit + 预构建路径 - Package: artifact 排除 .git/node_modules/test产物 - Lint/fmt: 零 warning 基线 Co-Authored-By: DeepSeek v4 Pro <noreply@deepseek.com>
Co-Authored-By: DeepSeek v4 Pro <noreply@deepseek.com>
- verify-complete.sh: 一键运行全部测试/编译/语法检查 - .cargo/config.toml: 修复 macOS Sequoia 下 cc shim 导致编译失败 Co-Authored-By: DeepSeek v4 Pro <noreply@deepseek.com>
…ckStates/quickSnapshots + 40 tests
- core_runtime: admin_clear_processed_logs + admin_handle_log now call persist_moderation_state() after modifying message_moderation HashMap - Makefile: add smoke-e2e target (smoke + Playwright dual-browser) - Clarifies e2e test is available via make smoke-e2e Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extract 12 user-shell-specific CSS sections (4205 lines) from styles.css into styles.user-shell.css. Covers: user projection, SFC push, room-driven theming, tri-column layout, wechat-style overrides, and user-page cuts. Added CSS link to index.html, admin.html, creative.html, scene-editor.html. All 800 frontend tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The ::after pseudo-elements on body[data-shell-variant] were applying warm radial gradients (rgba(255,210,120,0.10) and rgba(255,214,139,0.14)) that tinted the pixel art backgrounds with a golden/yellow hue. Removed the overlay backgrounds from: - styles.scene.css (index.html / public-square) - styles.creative.css (creative.html / creative-terminal) Pixel art now displays at full color fidelity. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
creative/hub/world-square 像素场景 v2(day/night 资产重做)+ 四层交互模型 (图像层 / 标签层 chip / 透明热点层 / 对话层)落地。 - world-square 热点对齐 ASSET_HANDOFF §5 统一 64×34 契约(废弃 clamp(64,8vw,108px) 桌面 108px 回归——codex 重构新写回的全 web-shell 唯一残留 clamp) - 固化防回归:verify-frontend-realness 加 verifySceneHotspotSizes (index/creative/world-square 桌面+移动热点 offsetWidth===64)+ verifyNoJavascriptErrors (6 页面×2 视口无 pageerror,防 admin insertBefore 崩溃类) - 四层交互尺寸统一(热点 64×34 紧贴标签 chip)、移动端热点恢复交互、admin 加载崩溃修复 - shell-message-render / quick-action-labels / scene-runtime 模块边界 + 配套测试 npm test: unit 912 / layout / realness 全绿 真实浏览器验证: 5 页面×2 视口 10/10 无 JS 错误 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
scene-editor 此前在移动端完全不可用:280px 桌面双栏挤爆窄屏 + 纯 mouse 事件, 触摸无法拖拽/缩放热点。 - 布局:≤768px 切单栏(侧栏置顶限高 42vh,舞台占满剩余高度) - 事件:mouse→pointer events(兼容鼠标+触摸+笔的拖拽/缩放) - touch-action:none(热点/舞台禁止触摸滚动,避免拖拽被默认滚动打断) realness verifySceneEditorMobile 已加(单栏+无 JS 错误运行时固化),随 app.js P1 修复(scene-editor 加载阻断 + owner-only 可见性)一并提交——realness 依赖 app.js applyRailVisibility,单独提交会破坏 main。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
previewBtn 此前只预览白天背景,编辑者无法验证夜晚背景的热点对齐。改为昼夜 切换:每次点击在 day/night 间切换(更新 timeOfDay + img.src),URL 未填时 给出明确提示。realness verifySceneEditorDayNight 运行时固化(点击切换 timeOfDay + 加载对应背景),随 app.js P1 修复一并提交。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
首次打开(未加载/未预览背景)舞台空白无提示,编辑者不知如何开始。加空状态 引导文案(居中提示填入背景 URL 或加载场景),img 有 src 后自动隐藏。 CSS :has() 实现(无 JS):.editor-stage:has(#sceneImage[src]:not([src=""])) 隐藏 .editor-empty-hint。realness verifySceneEditorDayNight 顺带固化(初始 可见 + 预览后隐藏),随 app.js P1 修复一并提交。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- api() 检查 HTTP 状态码:401/403/404/500 抛带状态码错误,加载/保存反馈不再依赖响应体里可能缺失的 error 字段 - saveBtn 防抖(保存中禁用)+ 加载态 + 成功强反馈(✓ 已保存) - loadBtn 抽成 loadCurrentScene(),供按钮与页面自动加载复用 - 带 room+gateway 跳转时自动加载当前场景,闭合 P1 编辑入口→编辑器体验环 对应 ACTIVE_WORK_QUEUE P1「gateway 保存路径继续压实」。 realness: scene-editor owner-only/mobile/day-night + 无 JS 错误守护全绿;单元 952 pass。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
编辑热点/背景后误关页面会丢失改动,此前无任何保护。用快照比较追踪脏状态: - sceneSnapshot() 序列化 hotspots + day/night URL,捕获任意热点/背景变更(无需逐操作 markDirty) - 加载/保存成功 markClean() 置基线;页面初始化置初始基线 - beforeunload 时 isDirty() 触发原生离开警告 realness: scene-editor owner-only/mobile/day-night + 无 JS 错误守护全绿。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
此前只能通过舞台点击选中热点,热点一多难以定位/管理。侧栏加热点列表: - renderHotspotList() 同步列表(序号+标签+×删除),初始"暂无热点"+计数 0 - 列表项点击选中高亮、× 删除,与舞台热点双向同步 - 页面初始化即渲染空列表,编辑者一进来就看到列表区 realness 守护 verifySceneEditorHotspotList(添加→列表+计数→选中→删除同步)已加并全绿, 随 verify-frontend-realness.mjs 待 app.js 批次一并提交。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
此前误删/误移/误缩放热点无法撤销。复用 sceneSnapshot 实现结构变更历史: - pushHistory 在增/删/重置/拖拽/缩放前入栈(拖拽缩放在 pointerdown 存快照、pointerup 入栈),属性 input 不记录(太频繁) - undo/redo 工具栏按钮 + Ctrl+Z / Ctrl+Y(Cmd+Shift+Z) 键盘 - restoreSnapshot 恢复热点+背景URL+预览图,MAX_HISTORY 50 防爆栈 realness 守护 verifySceneEditorUndoRedo(添加→undo→redo→undo)已加并全绿, 随 verify-frontend-realness.mjs 待 app.js 批次一并提交。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
复用现有 Gateway 端点,零 Gateway 改动: - search: 消息历史搜索 (GET /v1/shell/messages/search) - who: 居民在线名片,暴露 personal_room_id (GET /v1/residents) - read: 标记会话已读,补全 IM 未读闭环 (POST /v1/shell/read) - presence: 上报在线,与 who 形成 online 闭环 (POST /v1/shell/presence) - help: 命令可发现性,4 组分类 + 无参数显示 overview (纯本地) 同步 2 个已提交集成测试的 help 新行为断言。 cargo test -p lobster-cli: unit 55 + gateway_integration 11 + integration 5, 0 failed; clippy/fmt 干净. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- pixel-map.css: index/creative/world 三页 HUD 边框统一暖金 #f1c978 + 外发光 rgba(28,16,8)(含 public-square-hud !important 覆盖块) - creative.css: 左栏选中态 cream 浅字 → 亮金渐变底 + 深棕墨字,对比度提升 - scene.css: 公共广场选中态对齐 Playwright 计算值验证三页 HUD borderBottomColor 统一 rgb(241,201,120),零测试回归. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
反向 parity TUI 的世界治理查询。新增三个无 target 全局只读命令: - world: GET /v1/world 世界治理总览(城市/信任/公告/安全/制裁/管理员) - square: GET /v1/world-square 公共广场公告(标题[严重度]#tags/发布者/正文) - cities: GET /v1/cities 城市列表(profile.city_id/title/description 嵌套路径) 复用 WorldQueryCommand(--gateway/--json),零 Gateway 改动(均已有 GET 端点)。 CLI 版本修正 TUI 三处字段渲染 bug:world_stewards(非 stewards)、 city_id 嵌套在 profile 下、CityState 无 state/reason 字段。 测试 unit +12(67 全绿),fmt 干净,clippy 0 warning,真实 gateway 端到端验证通过。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
完成 CLI 世界查询 parity 全集(world/square/cities/safety)。 - safety: GET /v1/world-safety 世界安全快照(信任/公告/报告/制裁/黑名单/镜像 + 安全管理员) WorldSafetySnapshot 字段名 stewards(与 GovernanceSnapshot.world_stewards 是不同结构) 复用 WorldQueryCommand,零 Gateway 改动。测试 unit +3(70 全绿), fmt 干净,clippy 0 warning,真实 gateway 端到端验证通过。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
补 CLI 世界查询 parity 最后一环:world/square/cities/safety 之外的全局黄页。 directory 命令复用 WorldQueryCommand(无 target 全局只读),GET /v1/world-directory (http_read_routes.rs 已存在端点,零 Gateway 改动)。 独有数据(world/cities 命令均无):居民数 resident_count、公共房数 public_room_count、 信任状态 trust_state、镜像标记 mirror_enabled,逐城市列出。 - format_directory + run_directory(run_query::<serde_json::Value>) - 注册 enum Directory + parse_args "directory" + run_command 分发 - help overview「世界」组 + help known 数组同步加 directory - 测试 unit 72(+2:format_directory 渲染 + parse_args 路由),fmt/clippy/端到端全过 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
聚焦独有维度,不重复 world/cities/safety/directory 的明细: - 可移植性隐私治理 portability:可离城 / 可加入他城 / 可保留私关系 / 城市能否读私聊明文 - checksum 完整性(sha256 前 12 位)+ snapshot_id + 生成时间 - governance 内 cities/memberships/public_rooms/notices 等仅取计数概览 5 个未覆盖 GET 端点诚实评估:world-mirrors 是 directory 子集、mirror-sources/reports 空数据、world-entry 是 web-shell 专用导航(href 相对路径)—— 均跳过不凑数。仅 snapshot 的 portability 隐私治理 + checksum 是其他四命令完全没有的真实独有维度。 复用 WorldQueryCommand(无 target 全局只读),GET /v1/world-snapshot(http_router.rs:189 已存在端点,零 Gateway 改动)。测试 unit 74(+2),fmt/clippy/端到端全过。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
引入 CLI 首个 token 机制,解锁需 Bearer 鉴权的账户端点(set-nickname 等)。 - auth.rs 新模块:CliSessionCache(schema 版本控制)+ 原子写 ~/.lobster/cli-session.json (.tmp→rename,0700 目录 / 0600 文件)+ resolve_token 三级回退 (--token > LOBSTER_SESSION_TOKEN > 缓存文件)+ post_json_authenticated (Bearer 注入,401 友好提示重新 login) - login --email:邮箱 OTP(dev 响应内联 dev_code 自动用 / prod stdin prompt)→ verify → 缓存 - set-nickname:resolve_token → POST /v1/shell/nickname(resident 由 token session 决定,拒 --for) - logout:best-effort 服务端登出 + 总清本地缓存(无 token 亦 Ok) - 零 gateway 改动(复用现有 /v1/auth/email-otp/* + /v1/shell/nickname + /v1/auth/logout) - 测试:auth.rs 15 单测 + main.rs 8 解析测试 + 5 集成测试 (含 dev gateway 闭环:gateway 守卫 + stdin null 防 hang + dev inline 未开优雅跳过) 118 测试全绿;端到端验证 Bearer 注入 / 401 处理 / 缓存管理路径正确。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ban/unban/freeze/unfreeze/invite-create/invite-revoke 原用裸 post_json (无 Bearer),网关 require_admin_auth 在生产强制 Bearer token → 全部 401; ban/unban/freeze/unfreeze 还缺 actor_id 请求体字段。 - 6 个 run_* 改用 post_json_authenticated + resolve_token + resolve_admin_actor - 新增 resolve_admin_actor:显式 --actor > 登录缓存 resident_id > 报错, login 后所有 admin 命令自动复用会话身份,无需每次重传 - AdminBanRequest/AdminTargetRequest/AdminRoomTargetRequest 补 actor_id - 4 个 Command struct 加 actor/token(Option,统一可选) - 4 个 parse_* 接受 --actor / --token - USAGE.md + help admin 组更新(login 后自动身份,--actor/--token 可选) - 测试:ban 增强(断言 --actor/--token 解析)+ invite 断言改 Option + 新增 cli_admin_ban_without_token_hints_login(验证 admin 走 token 架构) 119 测试 + clippy --all-targets -D warnings 0 warning 全绿。 零 gateway 改动(仅复用现有 require_admin_auth 端点)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
新增 lobster-cli moderate,对接 POST /v1/admin/messages/moderate (HEAD 稳定端点)。CLI 此前能 ban/freeze 但无法审核违规消息, 治理闭环断点。 - ModerateCommand/AdminModerateRequest struct + parse_moderate_command (CLI 侧校验 action ∈ approved|blocked|handled,避免发到网关才报错) - run_admin_moderate 复用 resolve_admin_actor + post_json_authenticated (Bearer token + actor_id + CAP_MODERATE_MESSAGE) - Command enum + parse_args/run_command 分发 + help overview + known 数组 - USAGE.md admin 组加 moderate 行 - 测试:3 单测(valid/invalid action/missing required) + cli_admin_moderate_without_token_hints_login(token 架构统一鉴权) 123 测试 + clippy --all-targets -D warnings 0 warning 全绿。 零 gateway 改动(仅复用现有 require_admin_auth 端点)。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
填补 admin 治理 CLI 缺口: - room-member: POST /v1/admin/rooms/members(加/踢房间成员),走 Bearer token + resolve_admin_actor 鉴权,--action 校验 add|remove - create-resident: POST /v1/admin/residents(注册入口),网关无 require_admin_auth, 故用无 token 的 post_json 补 help overview、known 数组、USAGE admin 表 + token 回退说明、 5 个解析单测 + 1 个无 token 集成测试。零 gateway 改动。 cargo test 129 passed, clippy -D warnings 0, fmt clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
填补 admin 治理 CLI 缺口: - config --get: GET /v1/admin/config(网关只读无 require_admin_auth,用无 token 的 run_query),表格输出所有 KV(按 key 排序) - config --set KEY=VALUE: POST /v1/admin/config(Bearer token + actor_id + CAP_ADMIN_CONFIG),--set 可重复,批量设置 HashMap<String,String> 补 help overview、known 数组、USAGE admin 表 + token 说明、 4 个解析单测 + 1 个 config --set 无 token 集成测试。零 gateway 改动。 cargo test 134 passed, clippy -D warnings 0, fmt clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
填补 admin 治理 CLI 缺口: - admin-nickname: POST /v1/admin/residents/nickname(require_admin_auth Bearer token,handler 不校验 actor_id),admin 可改任意 resident 昵称 - --name <昵称> 设置 / --clear 清除(互斥校验),区别于 set-nickname(仅改自己) 补 help overview、known 数组、USAGE admin 表 + token 说明、 4 个解析单测 + 1 个无 token 集成测试。零 gateway 改动。 cargo test 139 passed, clippy -D warnings 0, fmt clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- 批量通过消息:fetchGatewayJsonPost 永不 reject,但 Promise.all(...).then
无条件报"已批量通过 N 条",全部失败也报成功。提取纯函数
summarizeBatchResults(results)→{total,ok,fail},回调按成功/失败数如实反馈
- 设备 unblock/block/remove:.then 不检查 r.error 静默 loadDevices,
改为检查 r.error 失败 showAdminNotice error + 成功 success
- TDD:5 runtime 纯函数测试 + 2 static 防回归,55 测试全绿
- 遵守 ACTIVE-im「不能假成功态」;零 Gateway/app.js 改动,未碰 codex WIP
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
根因:fetchGatewayJsonPost 在 HTTP 4xx/5xx 时返回 {ok:false,status,data},
**无顶层 error 字段**。写操作用 `if (r.error) ... else { 成功 }` 裸 else 判定时,
HTTP 失败落入 else 成功分支,读 r.data.xxx 得 undefined 却报"已生成/已作废/已移除"
——假成功态,违反 ACTIVE-im。
修复:9 处 .then 写操作成功判定统一为三分支
if (r.error) {} else if (r.ok) {} else { HTTP status 失败 }
对齐 await 模式 banResident 的 else if (result.ok) 范式。覆盖:
- 生成邀请码 / 撤销邀请码 / 创建居民
- 成员操作 / 日志处理 / 清空日志
- 设备 unblock/block/remove(上轮只加 r.error,else 仍裸,本轮补 r.ok)
TDD:runtime 验证 HTTP 失败返回结构无 error(根因证据)+ static 系统性断言
9 端点必须用 r.ok。59 测试全绿(原 55+新 4)。零 Gateway/app.js 改动。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
codex 两轮 Rust 技术债收口,从工作区 WIP 落盘: - 2026-06-20: Rust 生产 panic 扫描门禁固化(rust-production-panic-scan.py 扫 .unwrap/.expect/panic!/todo!/unimplemented!/unreachable!,剥离字符串/注释, smoke-release-gate + verify-complete 挂载真实扫描) - 2026-06-19: verify-complete 假绿风险收口(set -euo pipefail + PIPESTATUS, run_logged 统一记账)+ Gateway 全路由锁中毒防护(with_runtime() 助手, poisoned mutex 返回 JSON 500 不打崩线程)+ crypto-mls/security_headers/ CORS/header helper panic 收口为 Result 传播 验证:cargo test --workspace 全绿 + 4 scripts 单测 + rust-production-panic-scan + bash -n 语法检查全通过。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
接管 codex app.js 模块化重构 WIP 并补完半成品: 新增 5 个纯规格模块(66 测试全绿,与 app.js 契约匹配,零 stub): - shell-caretaker-panel.js: 非居民页管家面板静态规格 - shell-governance-render.js: 世界/城市治理列表卡片 model (25 导出) - shell-message-search.js: 房内消息搜索 DOM spec + 请求构造 - shell-room-stage.js: 房间舞台/角色画像投影 - shell-timeline-empty-state.js: 空时间线状态 spec 修复 Phase 0 悬空引用(npm test 27→0 fail 的唯一根因): - renderThreadStatusRail 仍调用已删除的 shouldHideThreadStatusRail/ threadStatusRailItems,改为委托已就绪的 threadStatusRailModel().visible/.items。 这是 codex 在 shell-room-render 抽取中建好适配器+import 但漏改调用方的半成品。 - 级联症状(document is not defined / querySelector undefined,main() fire-and-forget 异步泄漏)随初始渲染不再被打断而消除,无需动 fake-dom。 顺带落盘 codex 对 shell-composer/message-render/room-render/state-normalize/ styles.world-square 的改动 + 对应测试 + verify-frontend-realness 强化。 验证:npm test 1021/1021 pass(含 layout + realness)。 流 C(neon-pixel 主题)留未跟踪,不混入重构 diff。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
app.js 的 6 个 preset/runtime URL Map + presetImageLayerUrl/ timeAdjustedRuntimeSceneUrl/imageLayerUrl 提取到纯模块,env(matchMedia, timeOfDay)依赖注入,脱离 DOM/window 即可单测。app.js 改薄委托 (sceneImageLayerEnv 注入),applyUserSceneImageLayer DOM 落地保留。 - 新增 shell-scene-image-layer.js + 22 单测(day/night×mobile/desktop× preset/direct×javascript:/data:拦截×非assets直通×空值) - test/fake-dom.mjs APP_LOCAL_IMPORT_PATHS 加新模块(import 重写白名单) - test/shell-pages-static.test.mjs: userRoomProjection 边界标记更新 + 新增 image-layer 委托防回归断言 app.js -59 行。npm test 1044/1044 pass。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
app.js 的 8 个消息体构造函数(createMessageBodyShell/applyMessageBody
TerminalState/appendPlainMessageBodyText/appendMessageQuickSheet*/append
StructuredMessageBodySheet/createMessageBodyNode + 2 个 chip 构造器)提取
到纯模块,返回 DOM spec 树 {tag,className,dataset,text,children},
app.js 用通用 buildNodeFromSpec 递归落地。依赖 quickActionIntensity/Tone/
FollowUpLabel/Copy + parseStructuredQuickActionMessage 从既有模块 import。
- 新增 shell-message-body.js + 12 单测(终态/普通文本/结构化 sheet/
fields/notes/follow-up/chip dataset/spec 树完整性)
- app.js buildNodeFromSpec 通用 spec→DOM 落地器(textContent 安全,
无 innerHTML)
- test/fake-dom.mjs APP_LOCAL_IMPORT_PATHS 加新模块
- test/shell-pages-static.test.mjs: 3 个固化旧内联实现的契约测试改为
反映 spec 委托新结构(buildNodeFromSpec textContent + shell-message-body)
owner action 装配(createMessageOwnerActions/Button)spec 已在
shell-message-render.js,剩余 DOM+事件装配含闭包副作用,留 app.js
符合「纯数据已抽,副作用留 app.js」范式,不强抽。
app.js -82 行(累计本轮 -140)。npm test 1056/1056 pass。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
shell-composer.js 已写好+已测(453 行 16 导出),但 app.js 只 import 1 个 composerStatusState,14 个函数仍有内联副本。本轮完成接线: - app.js import 扩为 15 委托函数 + initShellComposer - 新增 buildComposerDeps() 工厂集中构造 _ctx 37 字段:DOM 元素 + 会变的 原始值(activeRoomId/state/roomSendErrors/roomReadMarkers/isSendingMessage 等)用 getter/setter 透传全局 let,避免初始化快照过期(state 在 hydrate 时整体重赋值,快照引用会失效——这是运行时回归的根因,用 getter 修复) - main() 之前调 initShellComposer(buildComposerDeps()) - 删除 14 个内联副本 + 7 个 dead helper 簇(composerContextItems/ composerMetaItems 等仅被内联版调用的辅助函数) - 接受 renderComposerHero 的 room? 空守卫 drift(模块版更健壮,已被 shell-composer.test.mjs 钉住) 新增 test/shell-composer-wiring.test.mjs(5 测试)固化接线契约:app.js import 15 函数+initShellComposer、不再内联定义、有 buildComposerDeps 工厂。 更新 shell-pages-static.test.mjs 7 个契约测试反映新结构(逻辑在 shell-composer.js,app.js 通过 initShellComposer 接线,边界标记更新)。 app.js -260 行(累计本轮 9694→9293,减 ~400)。npm test 1061/1061 pass。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
app.js 的 roomFollowUpCount/roomChatStatusSummary/roomQueueSummary 三个 governance/state-aware 摘要函数(读 unreadCount/caretakerPendingCount/ roomHasDraft/visiblePendingEchoCount/roomSendErrors/latestRoomQuickAction 等全局,非纯、无单测)提取为 *ForState 注入式纯函数,对齐 threadStatusRailModelForState 范式。deps 通过 roomSummaryDeps() 工厂 构造(shellPage 用 getter 透传 currentShellPage)。 - 新增 shell-room-summary.js + 20 单测(followUpCount 计数/queueSummary 5 态拼接+字段回退/chatStatus 优先级链+shellPage×roomKind 回退) - app.js 3 函数改薄委托,quickActionFollowUpCopy 从既有模块 import - test/fake-dom.mjs APP_LOCAL_IMPORT_PATHS 加新模块 - test/shell-pages-static.test.mjs 加 room-summary 委托防回归断言 app.js -25 行(累计本轮 9694→9268)。npm test 1082/1082 pass。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…t.js app.js 4 个读 governance 全局的上下文函数(chatDetailRoomContextModel/ directRoomPeerOnlineStatus/roomContextSummary/roomRouteLabel,非纯、无单测) 提取为 *ForState 注入式纯函数,对齐 shell-room-summary.js 范式。governance 查询(publicRoomRecordForConversation 等5个)+全局通过 governanceContextDeps() 工厂注入(residents/world/shellPage 用 getter 透传)。 按 Explore 建议首批抽这 4 个无分叉包袱的: - chatDetailRoomContextModel: 最纯(全5 governance 查询零 DOM) - directRoomPeerOnlineStatus: deps 最少(residents+currentIdentity) - roomContextSummary: 纯标签装配 - roomRouteLabel: rail 本就注入 app.js 版,抽后零行为变化 roomMemberCount/roomAudienceLabel(有 shell-room-rail 分叉)留第二批; roomSummaryLine/roomStatusLine(传递性 governance + quick-action 预览重) 不进本模块。 - 新增 shell-room-context.js + 32 单测 - test/fake-dom.mjs APP_LOCAL_IMPORT_PATHS 加新模块 - test/shell-pages-static.test.mjs: chatDetailRoomContextModel 切片契约 改为反映薄委托 + 逻辑在 shell-room-context.js app.js -49 行(累计本轮 9694→9219)。npm test 1114/1114 pass。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…-context.js(纯抽取) app.js roomMemberCount/roomAudienceLabel(读 governance.memberships/ publicRoomRecordForConversation/cityStateForConversation/worldDirectoryCity, 非纯、无单测)提取为 *ForState 注入式纯函数,并入 shell-room-context.js。 governanceContextDeps() 工厂扩展 memberships + displayCityTitle 字段。 纯抽取:不消 shell-room-rail.js 分叉(rail 有自己的 governance-blind 版, 显示「N 名成员」vs app.js「城市·slug」——消分叉会改变左栏显示行为,属 产品变更需用户确认,不在技术债清理范畴)。rail 保持不动,零行为变化。 - shell-room-context.js +13 单测(memberCount 显式/memberships/participants 回退/audienceLabel direct·public·system 分支) - app.js 2 函数改薄委托 app.js -29 行(累计本轮 9694→9190)。npm test 1127/1127 pass。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
本 PR 接管 codex 长期 WIP 并补完半成品 + 清技术债。包含三条独立工作流:
流 A:Gateway Rust 生产 panic 收口(codex WIP 落盘)
.unwrap()/.expect()/panic!()→ Result 传播 + poisoned-mutex 恢复(with_runtime()助手)rust-production-panic-scan.py门禁 + verify-complete 假绿风险收口cargo test --workspace全绿流 B:web-shell app.js 模块化重构(接管 + 补完 + 清债)
app.js 9694 → 9268 行(-426),npm test 27 fail → 1082 pass / 0 fail
renderThreadStatusRail悬空引用(codex 漏改调用方),恢复 npm test 绿色shell-scene-image-layer.js(env 依赖注入,22 测试)shell-message-body.js(DOM spec 范式,12 测试)shell-room-summary.js(*ForState 注入式,20 测试)流 C:admin-ds 假成功态系统性修复
summarizeBatchResults纯函数).then写操作 HTTP 失败假成功态(根因fetchGatewayJsonPostHTTP 4xx/5xx 返回{ok:false}无 error,裸 else 把失败当成功)附带:CLI IM 命令(feat/cli-im-commands)
login/set-nickname/logout bearer token 认证架构 + admin 系列 + 世界查询只读命令饱和
验证
cargo test --workspace全绿npm test1082/1082 pass(含 layout + realness)🤖 Generated with Claude Code