v0.1.15: 深度审计加固(7 P0 + 20+ P1 歼灭)

【引擎层 P0】
- GameEngine.restore 双重时钟注册(回档后整月双跑)→ restore 重建内核+回置 rng 状态
- engineFromSnapshot 必崩(globalThis.__state 从未设)→ 修正带 seed 重建
- DEV 性能分支二次执行整月管线 → 只读告警(绝不重跑)
- 引擎 advance 遇待决事件死锁 → resolvePending(idx) 通道(自动化/测试推进)

【WorldSim 大修】
- NPC 换代文案垃圾(n-danxin行情降50%)→ 换代快讯专属文案
- secretQi 假闭环(纯写无读)→ 全秘境初始化+missions 统一 consumeSecretQi
- 快讯节流自锁(lastNewsMonth 恒 1 月)→ totalTicks%24
- power 月度收敛坍塌(1400±3)→ 换代/年首化+年度成长
- relation 双重拉零(4 家全 0)→ 交还外交年度漂移
- 市场基准 5 处重复 → POOL_BASE 单一权威;灾年 stale 清理;drift 各池独立噪声
- worldsim 能力卡补全 + normalize 兜底(worldSim/stats 子字段)

【UI/动效/存储】
- ModalShell 三条 CSS 规则真正落地(close 定位/body 滚动/footer 独立底排)——0.1.12 声明未实施项
- fx-canvas:resize 监听移除/mistTimer 清零/reduced 联动/soft 档无雾 + drift 走 gate(过滤器)
- 档位 density 脱钩修复;顶栏“止”钮补 onClick;版本号三处统一 0.1.15
- importAll 清 chronicle 表;自动推进季度落盘(手动逐次)
- 性能:LogFeed memo / Genealogy computeGenealogy memo / Chronicle deps 修正;死码清除(lastPhaseStats/clockFromKernel/哨兵函数等 12 处)
- 删除误入库的“p”游离文件

【测试】979 全绿(36 套件);金钟罩三档 0.1.15 基线固化;
typecheck/build 通过
This commit is contained in:
2026-08-23 13:52:51 +08:00
parent 26bd61fba0
commit c5fa2a3357
26 changed files with 220 additions and 208 deletions
+16 -12
View File
@@ -65,13 +65,23 @@ describe('Kernel 三合一', () => {
})
})
function runEngine(e: GameEngine, months: number): void {
for (let i = 0; i < months; i++) {
if (e.view().gameOver) break
e.advance()
// 引擎语义:遇到待决事件停下来等处理;自动化直接取第一个选项继续
let guard = 0
while (e.view().pendingEvent && guard < 4) {
e.resolvePending(0)
guard++
}
}
}
describe('WorldSim 世界健康(长跑)', () => {
it.each(['ws-1', 'ws-2', 'ws-3'].map((s) => [s] as const))('%s:1000 月市场池/灵气在界、世界不崩', (seed) => {
const e = new GameEngine({ seed })
for (let i = 0; i < 1000; i++) {
if (e.view().gameOver) break
e.advance()
}
runEngine(e, 1000)
const ws = e.view().worldSim as (Record<string, unknown> & {
marketPool: Record<string, number>
secretQi: Record<string, number>
@@ -88,20 +98,14 @@ describe('WorldSim 世界健康(长跑)', () => {
it('NPC 换代至少发生一次(世界在演化)', () => {
const e = new GameEngine({ seed: 'ws-evolve' })
for (let i = 0; i < 720; i++) {
if (e.view().gameOver) break
e.advance()
}
runEngine(e, 1200)
const ws = e.view().worldSim as { npcSuccessions?: number } | undefined
expect(ws?.npcSuccessions ?? 0).toBeGreaterThan(0)
})
it('快讯持有且裁剪符合 N(≤120', () => {
const e = new GameEngine({ seed: 'ws-news' })
for (let i = 0; i < 400; i++) {
if (e.view().gameOver) break
e.advance()
}
runEngine(e, 400)
const ws = e.view().worldSim as { newsFeed?: unknown[] } | undefined
expect(ws?.newsFeed.length ?? 0).toBeLessThanOrEqual(WORLDSIM.newsKeep)
})