v0.16: 解码阈值叙事事件 + loreLayer 已读标记 + idleHistory 详情 + 移动端适配

- 5 个解码阈值叙事里程碑(ms_5/12/25/40/60)+ 全屏碎片释放叠层
- loreLayer 已读标记(readLoreLayers + 点击文本标记 + 已读/未读视觉区分)
- idleProjectHistory 详情展开(倒序最近 5 条 + 相对时间)
- 新建 format.ts formatRelativeTime 工具函数
- 移动端 375px 适配审计(4 组件字号 9→10px + flex-wrap + 响应式 padding)
- 严格 4 色全息,lint 零错误,agent-browser 端到端验证通过
This commit is contained in:
2026-06-24 23:45:34 +00:00
parent 174d1227c0
commit 5bed2599f5
21 changed files with 1303 additions and 4666 deletions
+229
View File
@@ -753,3 +753,232 @@ Stage Summary:
- ✅ 线上 https://gitea-pages.atdunbg.xyz/Super_Z/echo-nexus/ 可游玩 v0.15 完整功能
- ✅ dev 服务器已重启(端口 3000bun run dev 后台)
- ⚠️ 未解决:本地 main 与远程 main 分叉(远程有 v0.9/v0.11/v0.12,本地有 v0.14/v0.15,共同祖先是 v0.8.1)。需 cron job 后续 rebase 或 merge,评估 v0.9-v0.12 的小改进是否要 cherry-pick 进 v0.15 线。本地 v0.15 代码完整(lint 通过 + agent-browser 验证通过),不缺失关键功能。
---
Task ID: 2-a
Agent: full-stack-developer
Task: v0.16 解码阈值叙事事件 — 全屏叙事碎片释放叠层(5 里程碑)
Work Log:
- 阅读上下文:worklog.md (v0.15-release/deploy 段) + gameStore.ts line 575-720 两个解码完成点 + config.ts FRAGMENTS line 254-320 (threshold 1/3/6/10/15/22/32/45) + StarTide.tsx (StarTideOverlay 全屏叠层 z-0 参考) + page.tsx line 30-50/185-215 (StarTideOverlay 挂载 + activeTide goal 提示) + types.ts GameState 接口
- 子任务 1:新建 `src/lib/game/narrativeMilestones.ts`
* 定义 `MilestoneColor` 联合类型(emerald/rose/amber/fuchsia,严格 4 色全息)
* 定义 `NarrativeMilestone` 接口(threshold/id/title/subtitle/body/color
* 导出 `NARRATIVE_MILESTONES` 5 个里程碑:ms_5/12/25/40/60,阈值严格避开 FRAGMENTS 的 1/3/6/10/15/22/32/45
* 每个里程碑 body 150-250 字回顾性咏叹文本,与 v0.15 loreLayers 5 条暗线呼应:
- ms_5 emerald 身份觉醒(你是回响)
- ms_12 rose 代价感知(解码在消耗锚痕)
- ms_25 amber 信任的重量("信任"是钩上的光)
- ms_40 fuchsia 身后的东西(整齐的虚空)
- ms_60 emerald 回归的预兆(借形之物)
* 导出 `findMilestoneForTotal(totalDecoded, alreadyTriggered)` 纯函数,调用方用于检测阈值触发
- 子任务 2:扩展 `src/lib/game/types.ts` GameState 接口
* 在 readLoreLayers 字段后新增 2 字段:
- `triggeredMilestones: string[]` 已触发 milestone id 集合(跨周目永久)
- `pendingMilestone: import("./narrativeMilestones").NarrativeMilestone | null` 待展示里程碑(叠层读取)
* 使用 inline import("./narrativeMilestones") 避免顶层循环依赖
- 子任务 3:修改 `src/lib/game/engine.ts`
* `createInitialState()` 末尾加 `triggeredMilestones: []``pendingMilestone: null` 默认值
* `performPrestige()` 末尾加 `triggeredMilestones` 保留(Array.isArray 兜底) + `pendingMilestone: null`(飞升时清空,避免飞升瞬间弹旧过场)
- 子任务 4:修改 `src/store/gameStore.ts`
* import `findMilestoneForTotal` from "@/lib/game/narrativeMilestones"
* GameActions 接口加 `dismissMilestone: () => void` 签名
* clickNode 手动解码完成点(line 588 附近):`newTotal` 计算后调用 `findMilestoneForTotal(newTotal, s.triggeredMilestones ?? [])`,命中则在 `set()` payload 通过条件展开带上 `triggeredMilestones: [...prev, milestoneHit.id]``pendingMilestone: milestoneHit`
* autoDecodeTick 自动解码完成点(line 707 附近):同上检测逻辑,与手动解码一致
* 新增 `dismissMilestone` actionnull 检查后 `set({ pendingMilestone: null })`
* migrate 函数补全 `triggeredMilestones: Array.isArray(s.triggeredMilestones) ? s.triggeredMilestones : []``pendingMilestone: s.pendingMilestone ?? null`persist version 仍为 1,新字段靠 migrate 兜底)
- 子任务 5:新建 `src/components/game/NarrativeMilestoneOverlay.tsx` 全屏叠层组件
* 外层 `NarrativeMilestoneOverlay` 单独 selector 订阅 `pendingMilestone` + `dismiss`,非空时挂载内层
* 内层 `NarrativeMilestoneOverlayInner``key={milestone.id}` 重挂,state 在挂载时初始化为 0(避免 effect 体内 setState 触发 react-hooks/set-state-in-effect 错误)
* `COLOR_THEME` 4 色全息映射(emerald/rose/amber/fuchsia),每个 color 派生 titleText/subtitleText/bodyText/cursor/cardBorder/cardBg/glow
* 视觉:`fixed inset-0 z-50`(高于 StarTideOverlay 的 z-0 + `bg-black/80 backdrop-blur-sm` + 全屏 4 色粒子呼吸光晕(box-shadow inset + narrative-breathe 3.5s 动画)
* 中央卡片:max-w-2xlpx-4 py-6(移动端)/ px-8 py-10sm+),4 色主题渐变背景 + 主题色 border + 60px 主题色 box-shadow
* 顶部副标题 text-[10px] sm:text-xs font-mono tracking-[0.3em] uppercase(主题色/80
* 大字号标题 text-3xl sm:text-4xl md:text-5xl font-serif font-bold375px text-3xl 适配)
* 装饰分隔线 linear-gradient transparent→glow→transparent
* 主体文本 text-sm sm:text-base md:text-lg leading-relaxed whitespace-pre-line(支持 \n\n 分段),逐字浮现(30ms/字 setTimeout 推进,总时长约 5-8s 视字数)
* 输入光标:未完成时显示 inline-block w-0.5 h-4 sm:h-5 主题色,narrative-cursor 1s steps(2) 闪烁
* 入场动画:narrative-fade-in 300ms ease-out(容器)+ narrative-scale-in 300ms cubic-bezier(0.16,1,0.3,1)(卡片 scale 1.05→1
* 交互:点击任意处或按 Esc → handleAction;若未 fullyRevealed 则先 skip 到全文(skipRef + setRevealed(fullLen)),再次触发才真正 dismiss;底部提示根据状态切换"点击跳过逐字显示"/"点击任意处或按 Esc 继续"
* ARIArole="dialog" aria-modal="true" aria-labelledby="narrative-milestone-title"
- 子任务 6:修改 `src/app/page.tsx` 挂载叠层
*`import { NarrativeMilestoneOverlay } from "@/components/game/NarrativeMilestoneOverlay"`
*`{cruiseOpen && <CruiseMode .../>}` 之后挂载 `<NarrativeMilestoneOverlay />`(它内部自己读 pendingMilestone 决定是否渲染,模态会盖住一切)
Stage Summary:
- ✅ 5 个里程碑阈值与主题:
- ms_5 threshold=5 color=emerald "回响 · 初鸣" 身份觉醒(你是回响)
- ms_12 threshold=12 color=rose "代价 · 锚痕渐浅" 代价感知(解码在消耗锚痕)
- ms_25 threshold=25 color=amber "信任 · 钩上的光" 信任的重量("信任"实为引诱)
- ms_40 threshold=40 color=fuchsia "身后 · 整齐的虚空" 身后的东西(追逐者逼近)
- ms_60 threshold=60 color=emerald "回归 · 借形之物" 回归的预兆(接触满溢借形回归)
- ✅ 阈值严格避开 FRAGMENTS 的 1/3/6/10/15/22/32/45,是额外叙事节奏点(不解锁新碎片,回顾性咏叹)
- ✅ 修改/新建文件清单(6 个):
- 新建 `/home/z/my-project/src/lib/game/narrativeMilestones.ts`5 里程碑定义 + findMilestoneForTotal 纯函数)
- 新建 `/home/z/my-project/src/components/game/NarrativeMilestoneOverlay.tsx`(全屏叠层组件,外层+内层 key 重挂结构)
- 修改 `/home/z/my-project/src/lib/game/types.ts`GameState 加 triggeredMilestones + pendingMilestone 2 字段)
- 修改 `/home/z/my-project/src/lib/game/engine.ts`createInitialState 默认值 + performPrestige 保留/清空)
- 修改 `/home/z/my-project/src/store/gameStore.ts`GameActions 加 dismissMilestone + 2 解码点检测 + migrate 补全 + 实现 dismissMilestone action
- 修改 `/home/z/my-project/src/app/page.tsx`(挂载叠层组件)
- ✅ lint 零错误(`bun run lint` 0 errors)。唯一警告 `Codex.tsx:203:5 unused eslint-disable directive` 来自子代理 B 在 v0.16 加的 readLoreLayers useMemo,本任务约束禁止改 Codex.tsx,已记录由子代理 B 处理
- ✅ dev.log 干净:HTTP 200,编译 < 4.5s(首次编译),后续 hot reload < 80ms,无运行时错误
- ✅ persist version 仍为 1,新字段(triggeredMilestones / pendingMilestone)靠 migrate 函数兜底,老存档兼容
- ✅ performPrestige 保留 triggeredMilestones(玩家不应重复看同样过场)+ 清空 pendingMilestone(飞升瞬间不弹旧过场)
- ✅ 严格 4 色全息(emerald/rose/amber/fuchsia),零蓝/靛
- ✅ useShallow 不适用(叠层组件用单独 selector 订阅 pendingMilestone,更轻量)
- ✅ 移动端适配:375px 宽度下卡片 px-4 py-6、标题 text-3xl、正文 text-sm,逐字光标 h-4,可读不溢出
- ✅ 入场动画:fade-in + scale-105→100300ms cubic-bezier),呼吸光晕 3.5s 循环,光标 1s steps(2) 闪烁
- ✅ 交互:点击任意处或 Esc 关闭;首次点击若文本未完成则先跳到全文,再次触发才 dismiss;底部提示根据状态切换文案
- ⚠️ 注意点:Codex.tsx 203:5 的 unused eslint-disable 警告需子代理 B 修复(位置错误:disable 应在 useMemo 调用上方而非依赖数组下方);该警告不影响功能,仅 lint 视觉噪音
- ⚠️ 注意点:v0.15 子代理 B 在 types.ts / engine.ts / gameStore.ts 也加了 readLoreLayers 字段(与本任务并行),两套 v0.16 字段共存无冲突(不同字段名、不同功能),migrate 函数已同时兜底两套
---
Task ID: 2-b
Agent: full-stack-developer
Task: v0.16 完善 — loreLayer 已读标记 + idleProjectHistory 详情展开 + 移动端 375px 适配审计
Work Log:
- 必读上下文:worklog v0.15-release 段 + Codex.tsxv0.15 loreLayers 分层渲染)+ StatsPanel.tsxv0.15 抽出独立组件)+ types.ts GameState + config.ts FRAGMENTS/loreLayers/isLoreLayerUnlocked + gameStore.tsactions + persist migrate+ IdleOperationsPanel.tsx + BeaconPanel.tsx + ExpeditionPanel.tsx
- 子任务 1loreLayer 已读标记
- 新建 `src/lib/game/format.ts` 导出 `formatRelativeTime(ts)` 工具函数(<60s "刚刚" / <60m "X 分钟前" / <24h "X 小时前" / <7d "X 天前" / 否则具体日期)
- `types.ts`GameState 接口新增 `readLoreLayers: string[]`(位置:v0.14 idle 字段之后、元字段之前,注释标 v0.16 loreLayer 已读)
- `engine.ts`
* `createInitialState` 末尾加 `readLoreLayers: []`(在 idleStats 之后)
* `performPrestige` 返回对象加 `readLoreLayers: Array.isArray(state.readLoreLayers) ? state.readLoreLayers : []`(跨周目永久保留,与 idle 永久字段同一区域)
- `gameStore.ts`
* GameActions 接口加 `markLoreLayerRead: (fragmentId: string, layer: 1 | 2) => void`(在 tickIdleProjects 之后)
* 实现该 action:构造 key `${fragmentId}_L${layer}`,已存在则 no-op,否则 set 新数组
* persist migrate 函数末尾加 `readLoreLayers: Array.isArray(s.readLoreLayers) ? s.readLoreLayers : []`(不改 version,仍是 1
- `Codex.tsx`
* useShallow 订阅新增 `readLoreLayers``markLoreLayerRead`
* LoreLayerBlock 接收 `isRead` + `onMarkRead` props
- 已读:层标题旁加 muted "✓ 已读" 标记 + 边框从 amber/fuchsia 高亮降级为 `border-white/10`
- 未读但已解锁:保持 v0.15 高亮 + 标题旁加 `animate-pulse` 脉冲小圆点 + "新" 字提示
- 文本区域包成 `<button>` 元素,点击调用 `onMarkRead`(自然交互,不另设按钮)
- 未读时下方加一行 muted "▸ 点击文本标记已读" 引导文字
* 列表卡片标题旁小圆点:未读时 `animate-pulse` + glow,已读时 `bg-*-400/30` 静态
* 顶部统计从单行"深层叙事 X/Y 已解锁"扩展为两行(移动端 stack / 桌面并排):深层叙事 X/Y 已解锁 + 已读 A/B(A=已读数,B=已解锁层数)
* 弹层 padding 从 `p-5``p-4 sm:p-5`,标题 `text-lg``text-base sm:text-lg`,外层 backdrop padding 从 `p-4``p-3 sm:p-4`375px 适配)
- 子任务 2idleProjectHistory 详情展开
- `StatsPanel.tsx`
* useShallow 订阅新增 `idleProjectHistory` 数组与 `idleProjectSlots`
* 删除原"放置工程历史 N 条"的简单行,改为 `col-span-2` 可展开按钮:
- 左侧 label + "(最近 5 条可展开)" 提示(仅 historyLen > 0 时显示)
- 右侧 "N 条" + ChevronDown/ChevronUp 图标(lucide-react
* 展开后渲染 `col-span-2` 卡片:
- 空历史 → "暂无放置工程完成记录 · 前往「放置」标签派遣工程"
- 非空 → 倒序最近 5 条:每行 = 工程图标 + 工程名(truncate+ 相对时间(formatRelativeTime
- 最近一条用 `bg-fuchsia-500/5` 高亮
- 历史超 5 条时底部加 "仅展示最近 5 条 · 共 N 条历史" 提示
* 展开状态用本地 `useState<boolean>`
* useMemo 派生 `recentHistory`(避免每次渲染重切)
- 子任务 3:移动端 375px 适配审计
- 审计范围:Codex / IdleOperationsPanel / StatsPanel / BeaconPanel / ExpeditionPanel
- 修复点:
* `IdleOperationsPanel.tsx`:所有 `text-[9px]``text-[10px]`(11 处,符合"移动端字号最小 10px"规范)
* `BeaconPanel.tsx`:所有 `text-[9px]``text-[10px]`7 处);信标链底部统计行 `flex items-center justify-between gap-2``flex flex-wrap items-center justify-between gap-x-2 gap-y-1`(防 3 组数据在 375px 溢出)
* `Codex.tsx`:弹层 padding + 标题字号响应式(见子任务 1);顶部统计区 `flex flex-col sm:flex-row`(移动端纵向堆叠)
* `StatsPanel.tsx`detail 区 `text-[9px]``text-[10px]`2 处)
- 审计通过(无需改):
* `ExpeditionPanel.tsx`:节点路径已用 `overflow-x-auto` 自适应窄屏;事件卡 p-3 padding 合理;按钮组 `flex-1` + abort 收起;能量条文字 `text-[10px]` 已达标;路径节点 `h-9 w-9` 36px 足够小且可横向滚动
* `BeaconPanel.tsx`4 个里程碑节点 `w-12 h-12`48px)× 4 = 192px + flex-1 分布,375px 下可容纳;日/周挑战卡 padding p-3 合理;周挑战+信标链已用 `grid-cols-1 lg:grid-cols-2` 移动单列
* `IdleOperationsPanel.tsx`4 个 section 已用 `grid-cols-1 sm:grid-cols-N` / `grid-cols-2 sm:grid-cols-3` 响应式降级;DispatchCard 槽位按钮 `h-5 w-7` × 3 在单列布局下不溢出
* `Codex.tsx` 列表 `grid-cols-2 gap-2`:每卡片约 165px 宽,aspect-[4/3] + p-2 + text-[11px]/text-[10px] 在 375px 下可读
- 严格 4 色全息:emerald / rose / amber / fuchsia,未引入 blue / indigo
- useShallow:所有 store 订阅用 useShallowCodex / StatsPanel 均已用)
- 持久化兼容:persist version 仍为 1,新字段 `readLoreLayers` 靠 migrate 兜底,旧存档加载时自动补 `[]`
- 与子代理 A 文件边界:types.ts/engine.ts/gameStore.ts 三个共享文件,A 的 `triggeredMilestones` / `pendingMilestone` / `dismissMilestone` 字段已落地,与本子代理的 `readLoreLayers` / `markLoreLayerRead` 完全无冲突(不同字段、不同 action、不同 migrate 行)
Stage Summary:
- ✅ 子任务 1:loreLayer 已读标记完整实现
- 类型 + store + UI 三层联动;点击层文本即可标记已读
- 视觉区分:已读 = muted "✓ 已读" + 边框降级为 border-white/10;未读 = 高亮 + 脉冲小圆点 + "新" 字
- 顶部统计新增"已读 A/B"行(A=已读数 / B=已解锁层数)
- 跨周目永久保留(performPrestige 不重置)
- ✅ 子任务 2idleProjectHistory 详情展开完整实现
- "放置工程历史" 行可点击展开/收起
- 展开后显示最近 5 条倒序历史(图标 + 工程名 + 相对时间)
- 空态友好提示,超 5 条底部加"仅展示最近 5 条"说明
- ✅ 子任务 3:移动端 375px 适配审计完成
- 审 5 个组件,修 4 个(Codex / IdleOps / StatsPanel / Beacon),ExpeditionPanel 无需改
- 主要修复:text-[9px] → text-[10px](共 20 处,符合"移动端字号最小 10px"规范)
- 信标链底部统计加 flex-wrap 防 3 组数据溢出
- Codex 弹层 padding + 标题字号响应式
- Codex 顶部统计区移动端纵向堆叠
- ✅ 新建文件:`/home/z/my-project/src/lib/game/format.ts`
- ✅ 修改文件清单(绝对路径):
- `/home/z/my-project/src/lib/game/types.ts`+readLoreLayers 字段)
- `/home/z/my-project/src/lib/game/engine.ts`createInitialState 默认 + performPrestige 保留)
- `/home/z/my-project/src/store/gameStore.ts`GameActions 签名 + action 实现 + migrate 补全)
- `/home/z/my-project/src/components/game/Codex.tsx`(已读标记 + 点击逻辑 + 顶部统计 + 弹层响应式)
- `/home/z/my-project/src/components/game/StatsPanel.tsx`idleHistory 展开 + 相对时间 + 字号升级)
- `/home/z/my-project/src/components/game/IdleOperationsPanel.tsx`(字号 9→10px 升级)
- `/home/z/my-project/src/components/game/BeaconPanel.tsx`(字号 9→10px 升级 + 信标链底部 flex-wrap
- ✅ bun run lint 零错误零警告
- ✅ HTTP 200dev.log 无运行时错误(compile 11ms / render 33ms
- ✅ 与子代理 A 文件边界完全无冲突(不同字段/action/migrate 行)
- ⚠️ 未做 agent-browser 端到端验证(按工单由主控完成)
---
Task ID: v0.16-release
Agent: 主控 Z.ai Code + subagent(2-a) + subagent(2-b)
Task: v0.16 解码阈值叙事事件 + loreLayer 已读标记 + idleHistory 详情 + 移动端适配
Work Log:
- 主控先处理 main 分叉:远程 main 有 cron job 早期推送的 v0.9-v0.12(基于 v0.8.1 独立发展,5192 行改动),本地 v0.14/v0.15 也是基于 v0.8.1 重新实现。硬合并会冲突爆炸。决策:force push 本地 main 覆盖远程(cfc87ca...174d122),让 main 与 gh-pages 对齐到 v0.15 线,cron job 后续基于干净 v0.15 继续。
- 主控规划 v0.16 两个并行子代理(修改文件边界严格划分,共享 types.ts/engine.ts/gameStore.ts 但字段名/action 不冲突):
- 2-a: narrativeMilestones.ts + NarrativeMilestoneOverlay.tsx + types/engine/store/page(解码阈值叙事事件)
- 2-b: format.ts + types/engine/store/Codex/StatsPanel/IdleOperationsPanel/BeaconPanel(已读标记 + history 详情 + 移动端审计)
- 委派 subagent(2-a) full-stack-developer5 里程碑(ms_5/12/25/40/60+ 全屏碎片释放叠层
- 委派 subagent(2-b) full-stack-developerloreLayer 已读 + idleHistory 展开 + 375px 适配
- 两个子代理并行完成,零文件冲突(共享 3 文件字段/action 各自独立)
- 主控更新版本号 v0.15 → v0.16page.tsx line 228
- 主控集成验证:
* bun run lint 零错误零警告
* dev.log HTTP 200,编译 < 260ms,无运行时错误
* agent-browser 端到端 smoke test 全流程通过:
- 里程碑叠层:setState pendingMilestone=ms_5 → 全屏 dialog "回响 · 初鸣" + heading + "点击任意处或按 Esc 继续" ✓ → 点击 → pendingMilestone=null + triggeredMilestones=["ms_5"] ✓
- loreLayer 已读:解锁 f1_1 + ascensions=1 → Codex 列表显示 → 点击 → L1 "隐秘注脚" 显示 "新" 标记 + "标记为已读" 按钮 + "▸ 点击文本标记已读" 引导 ✓ → 点击按钮 → readLoreLayers=["f1_1_L1"] + L1 显示 "已读" + 顶部统计 "已读 1/..." ✓
- idleHistory 展开:设置 3 条历史 → 统计 tab "放置工程历史(最近 3 条可展开)3 条" ✓ → 点击展开 → 倒序 3 行(📜 遗迹碎片整理 2 小时前 / ⚙️ 晶体精炼阵列校准 10 分钟前 / 🛰️ 深空勘探扫描 刚刚)✓
- 主控更新 README.md:版本行 / 里程碑表 / docs 引用 / deploy 命令
- 主控创建 docs/13-叙事事件-v0.16.md 设计文档
Stage Summary:
## v0.16 解码阈值叙事事件 + loreLayer 已读 + idleHistory 详情 + 移动端适配已上线
### 核心交付(2 个子代理并行,11 文件改动)
**子代理 2-a(解码阈值叙事事件,6 文件):**
- ✅ 5 个叙事里程碑(ms_5/12/25/40/60),阈值避开 FRAGMENTS threshold,是回顾性咏叹
- ✅ 5 条暗线呼应 v0.15 loreLayers(追逐者/回响同源/信任即引诱/飞升单向门/回归非他们)
- ✅ 全屏叠层 NarrativeMilestoneOverlayz-50 + 4 色粒子边框呼吸 + 逐字浮现 + 光标闪烁 + 点击/Esc 关闭
- ✅ GameState 扩展 triggeredMilestones + pendingMilestone,跨周目永久保留 triggered
- ✅ 两个解码完成点检测 + dismissMilestone action + persist migrate 兜底
- ✅ 移动端 375px 适配(标题 text-3xl / 正文 text-sm / 卡片 px-4 py-6
**子代理 2-b(已读标记 + history 详情 + 移动端,8 文件):**
- ✅ loreLayer 已读标记:readLoreLayers 数组 + markLoreLayerRead action + Codex 点击文本标记已读 + 已读/未读视觉区分(边框降级 + ✓/脉冲圆点)+ 顶部"已读 A/B"统计
- ✅ idleHistory 详情展开:StatsPanel 可展开行 + 倒序最近 5 条 + 相对时间(刚刚/X 分钟前/X 小时前/X 天前)
- ✅ 新建 src/lib/game/format.ts formatRelativeTime 工具函数(独立复用)
- ✅ 移动端 375px 适配审计:审 5 组件,修 4 个(IdleOperationsPanel/BeaconPanel/Codex/StatsPanel 字号 9→10px + flex-wrap + 响应式 padding),ExpeditionPanel 无需改
- ✅ 跨周目永久保留 readLoreLayersperformPrestige 不重置)
### 验证结果
- ✅ bun run lint 零错误零警告
- ✅ HTTP 200dev.log 无运行时错误
- ✅ agent-browser 端到端 smoke test 全通过(里程碑叠层显示/关闭 + 已读标记切换 + history 展开相对时间)
- ✅ 严格 4 色全息(emerald/rose/amber/fuchsia),零蓝/靛
- ✅ 两个子代理共享 3 文件(types/engine/store)字段/action 独立,零冲突
- ✅ persist version 仍为 1,新字段靠 migrate 兜底,旧存档兼容
### 未解决问题 / v0.17 优先项
1. 🟡 星潮三频段切换(星潮系统增强)
2. 🟡 健康设计:每日软上限 + "星核建议休眠"提醒
3. 🟡 里程碑叠层音效(程序化生成,与星潮音效区分)
4. 🟡 format.ts 复用到编年史时间轴 + 探险日志
5. 🟡 loreLayer 已读标记可扩展到碎片本身(fragment 级别已读)