<feed xmlns='http://www.w3.org/2005/Atom'>
<title>living-village.git/src/LivingVillage.Kernel/WorldSave.fs, branch main</title>
<subtitle>Unnamed repository; edit this file 'description' to name the repository.
</subtitle>
<id>http://git.somhairle.bid/living-village.git/atom?h=main</id>
<link rel='self' href='http://git.somhairle.bid/living-village.git/atom?h=main'/>
<link rel='alternate' type='text/html' href='http://git.somhairle.bid/living-village.git/'/>
<updated>2026-09-28T16:24:08+00:00</updated>
<entry>
<title>p55: 当日任务经济闭环——设计口径物品报酬入账(夜捕鱼×2/送粮食物×1, 其余不发) + 连续完成天数(streak 跨日保留/漏完成清零) + v3 streak 尾段与 save(None) 兼容 + LV_P55_SHOT 证据</title>
<updated>2026-09-28T16:24:08+00:00</updated>
<author>
<name>Somhairle H. Marisol</name>
<email>muqiu-han@outlook.com</email>
</author>
<published>2026-09-28T16:24:08+00:00</published>
<link rel='alternate' type='text/html' href='http://git.somhairle.bid/living-village.git/commit/?id=a59a4bbe1ab45adb29d1367995230d3f09847d9b'/>
<id>urn:sha1:a59a4bbe1ab45adb29d1367995230d3f09847d9b</id>
<content type='text'>
</content>
</entry>
<entry>
<title>p51: 职业系统实现首切片——开局钱/体力/背包侧车 + 当日任务/跨日刷新 + StartNewGameWith 读回(design §2.4-1)</title>
<updated>2026-09-28T14:38:52+00:00</updated>
<author>
<name>Somhairle H. Marisol</name>
<email>muqiu-han@outlook.com</email>
</author>
<published>2026-09-28T14:38:52+00:00</published>
<link rel='alternate' type='text/html' href='http://git.somhairle.bid/living-village.git/commit/?id=aa3baa953ea5c4f99f5f23cb3eef9400338b61ec'/>
<id>urn:sha1:aa3baa953ea5c4f99f5f23cb3eef9400338b61ec</id>
<content type='text'>
</content>
</entry>
<entry>
<title>feat(kernel,desktop): P31 step3 story annals + identity entry + glyph atlas</title>
<updated>2026-09-22T08:33:03+00:00</updated>
<author>
<name>Somhairle H. Marisol</name>
<email>muqiu-han@outlook.com</email>
</author>
<published>2026-09-22T08:33:03+00:00</published>
<link rel='alternate' type='text/html' href='http://git.somhairle.bid/living-village.git/commit/?id=9821b54ff2a77539898b62471d79dc4685b59cad'/>
<id>urn:sha1:9821b54ff2a77539898b62471d79dc4685b59cad</id>
<content type='text'>
- Sim.AnnalKind gains StoryAnnal (summary lives in the existing Summary
  field); WorldSave v3 serializes it with the new 'story' token. v1/v2
  saves never contain the token and stay byte-identical; v3 save -&gt; load
  -&gt; save roundtrips byte-for-byte (tested).
- Occupation.Story.identitySummaryOf: plain chronicle-style identity line
  written to the yearbook at game start (design section 3), e.g. yi-da-yu-wei-sheng.
- Desktop: story summaries render in the chronicle panel; StartNewGame
  appends the identity annal; chooseIntent now routes responses through
  Occupation.biasResponse and advances the storyline (one stage per
  player dialogue) with the summary appended as a StoryAnnal.
- M5View gains Seed (world seed source for the story start-day hash).
- Chinese copy synced into requiredUiLabels; cjk-glyphs.txt +
  CjkGlyphAtlas.characterTable extended 238 -&gt; 307 glyphs (384x480),
  atlas regenerated with the deterministic script.
- 4 new kernel tests (115 -&gt; 119); performance digest unchanged.
</content>
</entry>
<entry>
<title>perf(kernel): P27 第二步 — Rumor 扫描去装箱 + 裁剪判定 O(1)</title>
<updated>2026-09-22T02:46:16+00:00</updated>
<author>
<name>Somhairle H. Marisol</name>
<email>muqiu-han@outlook.com</email>
</author>
<published>2026-09-22T02:46:16+00:00</published>
<link rel='alternate' type='text/html' href='http://git.somhairle.bid/living-village.git/commit/?id=a0597455629618a282b582d13c23bfeab786e7d2'/>
<id>urn:sha1:a0597455629618a282b582d13c23bfeab786e7d2</id>
<content type='text'>
两条互相独立、均不改变保留集合与查询结果的优化：

1) 扫描去装箱：latestRumorFor / rumorIsDuplicate 用 `=` 比较 [&lt;Struct&gt;] 的
   NpcId/RumorId（含 RumorId option）会走泛型结构相等并逐条装箱（实测 ~24 B/条，
   Sim.chat 单独测得 N=16000 时 393,736 B/次、随 N 线性）。改为先解构底层
   int/int64 再比较；Parent 用 int64 option 比较替代 RumorId option 结构相等。
   语义完全等价，扫描不再逐条分配。

2) 裁剪判定 O(1)：World 新增派生镜像 RumorCount/RumorOldestDay（不参与存档，
   读档由列表经 rumorWorkingSetStats 重建）。appendRumor 用「count+1&gt;capacity
   或 min(oldest,day)&lt;cutoff」O(1) 判定，仅真需裁剪时才走 trimRumors；旧 consRumor
   每次追加都 rumorsNeedTrim 全表扫一遍。条件与 needTrim 逐字等价，保留集合相同。

等价性验证：5 天 2000 聊天/天跑两遍 WorldSave.save 逐字节相同，
RumorCount/RumorOldestDay 与对列表重算一致（count=8000、oldest_day=1）。

Kernel 长跑基准 30 NPC × 2000 聊天/天（--rumor-bench D 30 2000）：
 days  修复前 alloc / ms        修复后 alloc / ms
  3    930,716,456 / 1626.7     482,716,192 / 1511.3
 30  13,419,045,864 / 12182.5  4,884,067,640 / 8879.6
 60  27,297,668,608 / 23769.7  9,774,660,360 / 17078.2
60 天分配 -64%、耗时 -28%，retained_id_checksum=927964000 前后一致。

门槛：final_digest=953775FAEB2F... 三次一致、performance_determinism=PASS；
Kernel 92 / Desktop 143 全绿；--cost-probe 1/5 天 18.7s/18.8GB、90.4s/94.6GB
（全模拟分配由逐 tick NPC 快照主导，谣言子系统占比很小，故全模拟基本持平）。
</content>
</entry>
<entry>
<title>feat(sim): M6a 谣言工作集容量上界+按天淘汰——DayIndex 派生字段/纯函数 trim/窗口化扫描/O(1) nextId</title>
<updated>2026-09-21T15:12:20+00:00</updated>
<author>
<name>Somhairle H. Marisol</name>
<email>muqiu-han@outlook.com</email>
</author>
<published>2026-09-21T15:12:20+00:00</published>
<link rel='alternate' type='text/html' href='http://git.somhairle.bid/living-village.git/commit/?id=d94ec2dc875c6c45973c6d6d6730b4a57fadeb3e'/>
<id>urn:sha1:d94ec2dc875c6c45973c6d6d6730b4a57fadeb3e</id>
<content type='text'>
</content>
</entry>
<entry>
<title>feat(occupation): P15 补齐货郎/书生各 2 条每日任务模板 + 既有事件通道信号桥（Kernel 纯函数 TDD）</title>
<updated>2026-09-21T14:55:01+00:00</updated>
<author>
<name>Somhairle H. Marisol</name>
<email>muqiu-han@outlook.com</email>
</author>
<published>2026-09-21T14:55:01+00:00</published>
<link rel='alternate' type='text/html' href='http://git.somhairle.bid/living-village.git/commit/?id=0222501162d18447aa162e9c53e000bc42ccbbd9'/>
<id>urn:sha1:0222501162d18447aa162e9c53e000bc42ccbbd9</id>
<content type='text'>
- TaskTemplateId 扩出 BuyGoods(收货)/Resell(转卖)/ObserveNotes(观察记事)/ReasonDebate(论理)，
  taskPoolOf 货郎=[收货,转卖]、书生=[观察记事,论理]，四职业池均非空。
- TaskSignal 增 Purchased(玩家买入)/Observed(观察)，satisfiesCompletion 给出四模板完成判定；
  新增 occupationSeedOf/refreshToday（跨日才重生成，同日含 Done/Failed 终态保留）。
- signalOfInteraction/advanceTask：仅 playerId 发起的 DialogueEvent/TradeEvent 产生信号，
  NPC 互动不派任务；Offered 须先 acceptTask，终态不可复活。WorldSave 模板 token 双向同步。
- 测试 83 全绿（新增 6：池非空、货郎书生逐日池内确定、模板中文名、完成信号正负、
  事件桥含玩家买/卖与 NPC 忽略、既有 DialogueEvent→accept→Done 全链路、refreshToday 逐日）。
- 不动 Sim.step 数值路径；旧档 v3 模板 token 仅新增合法值，未知模板仍拒绝。
</content>
</entry>
<entry>
<title>feat(occupation): P11 存档 v3 today-task 尾段（annals 后追加）+ 双向兼容</title>
<updated>2026-09-21T10:49:50+00:00</updated>
<author>
<name>Somhairle H. Marisol</name>
<email>muqiu-han@outlook.com</email>
</author>
<published>2026-09-21T10:49:50+00:00</published>
<link rel='alternate' type='text/html' href='http://git.somhairle.bid/living-village.git/commit/?id=27f0ca0597e2799e2a1ed431aadeb559c6dfbcf2'/>
<id>urn:sha1:27f0ca0597e2799e2a1ed431aadeb559c6dfbcf2</id>
<content type='text'>
Occupation.State 增 Today: DailyTask option（State 声明移至 DailyTask 之后；TaskToken 保留为 v3 前缀占位扩展位）。WorldSave：saveWith 有任务时在 annals 之后追加尾段 task-today|&lt;template&gt;|&lt;state&gt;|&lt;offered&gt;|&lt;due&gt;|npc-none/some|tile-none/some；无任务/无职业不追加（默认 None = 旧行为，v2 逐字节不变）。load 重构为内部 parse 返回 (World, Occupation.State option)：尾段可选——旧 v3（P10 版式无尾段）新 reader 读出 Today=None；v1/v2 无任务；尾段后多余 token 或未知模板 token 拒绝（不吞档）。loadFromFileWith 顺手修正：不再经 stateOf 重置，前缀 task/stage 与 Today 全量保真。5 例测试：尾段位置（marker 在 annal 之后）+ 全字段 round-trip + 重存逐字节一致、无任务 v3 旧版式、v1/v2 无尾段 + 未知模板拒绝、尾段后垃圾拒绝、字节级双跑一致。
</content>
</entry>
<entry>
<title>feat(occupation): 职业系统第一片 — Kernel 结构 / bootstrap 注入 / 存档 v3</title>
<updated>2026-09-21T09:18:11+00:00</updated>
<author>
<name>Somhairle H. Marisol</name>
<email>muqiu-han@outlook.com</email>
</author>
<published>2026-09-21T09:18:11+00:00</published>
<link rel='alternate' type='text/html' href='http://git.somhairle.bid/living-village.git/commit/?id=cf214889490a62ba4fe84fb0055bc2133776e8a2'/>
<id>urn:sha1:cf214889490a62ba4fe84fb0055bc2133776e8a2</id>
<content type='text'>
Occupation.fs（Kind/Profile/State + 农夫/渔夫/货郎/书生 中文名常量，按设计 §1 表给初始 Money/Energy/Inventory）；ItemKind 扩出 Fish/Spice/Scroll（basePrice 分支补齐，Food 10.0f 数值路径不变 → 无职业 digest 不动）；WorldBootstrap.initialWorldWithOccupation 默认 None = 旧行为（Money/Energy 覆盖，库存字段先留数据侧、物理挂接留交易单——取舍见 design §2-C 反对加字段）；WorldSave: v3 头仅在有职业时写入（保存 saveToFileWith / loadFromFileWith，v1/v2/v3 无职业类型默认，token 顺序 version|w|h|kind|task|story|…），默认路径 save 输出逐字节等同现行 v2；P10 测试 5 例（§1 表值、v3 round-trip、v1/v2 不吞档、双 seed 逐字节、中文名）；Kernel.Tests 引用 Desktop 以驱动 WorldBootstrap（取舍：不做测试专用 shim）。TaskToken/StoryStage 为 v3 占位（任务系统后续单实现）。
</content>
</entry>
<entry>
<title>feat(kernel): 地图边界参数化与存档 v2</title>
<updated>2026-09-21T06:55:37+00:00</updated>
<author>
<name>Somhairle H. Marisol</name>
<email>muqiu-han@outlook.com</email>
</author>
<published>2026-09-21T06:55:37+00:00</published>
<link rel='alternate' type='text/html' href='http://git.somhairle.bid/living-village.git/commit/?id=ab19df0ebad8da972cd30f89f7cfd8ef38b8c0ae'/>
<id>urn:sha1:ab19df0ebad8da972cd30f89f7cfd8ef38b8c0ae</id>
<content type='text'>
Sim 地图边界由常量 52 改为可配置（configureBounds，默认 64x48 = 与全部基线一致）；Sim.step 裁剪、initialWorld 中心出生时点按当前边界读取；WorldSave 升级 V2 头携带 width/height 两字段，V1 旧存档照常读入并自动回退到 64x48；回归：512x384 边界裁剪/初界转正/双份存档往返/案例 v1 档兼容读。修复前一段中报错已修正的测试代码（Ensure saved-file timeouts）。
</content>
</entry>
<entry>
<title>feat(m6a): add file save acceptance smoke</title>
<updated>2026-09-20T12:58:23+00:00</updated>
<author>
<name>Somhairle H. Marisol</name>
<email>muqiu-han@outlook.com</email>
</author>
<published>2026-09-20T12:58:23+00:00</published>
<link rel='alternate' type='text/html' href='http://git.somhairle.bid/living-village.git/commit/?id=5cb4970e2410a43e528b4b3e44dda15fac0a219a'/>
<id>urn:sha1:5cb4970e2410a43e528b4b3e44dda15fac0a219a</id>
<content type='text'>
[Change Nature]
This commit adds the bounded M6a file-save acceptance path.

[New Capability]
- Add file-level round-trip and deterministic continuation coverage.
- Add Headless --m6a-smoke with digest checks and explicit PASS/FAIL output.

[Implementation]
- Reject non-finite numeric values and negative inventory quantities.
- Exercise dialogue, chat/rumor, trade, events, annals, time, and RNG state.

[Impact]
- Affects Kernel save parsing, Kernel tests, and Headless smoke tooling.
- Preserves the existing save format and M5 smoke behavior.
</content>
</entry>
</feed>
