W5 收尾:文档同步+W6 备忘 — #13 方案 A 代码侧同步(RESTART_TARGETS/tune_restart_curve/gates 注释/测试断言改 1:0.48:0.42:0.40),门 #13 restart.pass=true R1-R4 全入带;架构文档 §4.2 宿慧公式注释+目录树补 meta_upgrades;CLAUDE.md 新增文档落点规则 §9.7;test_runner 752 检查 8/8
CI / data-gate(schema v0 数据门) (push) Canceled after 0s

This commit is contained in:
程基岩(engineering-lead) committed 2026-10-21 18:48:19 +08:00
1 parent c0a5c52cb7
commit 42aff596f7
12 files changed
+65 -18

No files matched your search

+9
View File
@@ -99,6 +99,15 @@ godot --headless --path . -s res://src/tools/import_main.gd -- --validate-only
**验证手册**:`docs/engineering/2026-10-19-w3-verification-manual.md`(文档区,不入库)。
W3 的 GDScript 从未被引擎执行过(本机无 Godot)——**跑通第 1 节 headless 单测才算 W3 验过**。
## 文档落点规则(架构 §9.7,W5 起)
**判据一句话**:记录"这个仓库已发生了什么"的工程事实 → 跟项目仓走(`docs/engineering/`);
规定"这个项目应该怎样"的设计规范 → 留 workspace 设计区(C 盘 `design/` + `docs/architecture/`)。
自检:"换一台电脑 clone 仓库后,这份文档还找得到、还需要吗?"
- 工程周报/验证报告/sim 对比/look-dev 冻结记录 → 本项目仓 `docs/engineering/<日期>-<名称>.md`;
- 设计母本(GDD / Balance Bible / 架构文档 / 裁定报告)→ workspace 设计区,多轮迭代母本,不随单次 commit 失效;
- W1-W4 工程报告仍留 C 盘原处(交叉引用不断链,不迁移);W5 起新工程报告一律按本规则落项目仓。
## 纪律提醒
- 写代码前**先写测试**(GUT W3 起);每个 Story 留测试证据路径;
+2 -2
View File
@@ -174,8 +174,8 @@
"id": "tune_restart_curve",
"kind": "text",
"num": 0,
"text": "1:0.6:0.4:0.3",
"desc_cn": "[B§4.3] 重开曲线目标(第 5 轮触底 ≥0.25×);模拟器门 #13 断言"
"text": "1:0.48:0.42:0.40",
"desc_cn": "[B§4.3] 重开曲线目标(第 5 轮触底 ≥0.25×);模拟器门 #13 断言。[v1.0→v1.1] 用户拍板方案 A:二轮 sim 实测校准值(旧 1:0.6:0.4:0.3 为一轮解析预估,未计阻尼)"
},
{
"id": "tune_event_timeout_default",
+1 -1
View File
@@ -22,7 +22,7 @@ tune_skip_gens,number,3,,[B§4.2] 跳过机制覆盖前 3 档班底
tune_skip_levels,number,25,,[B§4.2] 跳过机制每档 +25 级
tune_skip_level_cap_per_gen,number,50,,"[B§4.2] W5 裁定 P-27(F-2):跳过每档获赠 = min(floor(宿慧/5)×25, 本值)(原无封顶 → R2 开盘白送 2850 级)"
tune_enthrone_rebirths,number,2,,[B§4.4] 阴司敕封触发:转世 ≥2(约第 2-3 轮,累计 8-12h 为其 pacing 后果)
tune_restart_curve,text,0,1:0.6:0.4:0.3,[B§4.3] 重开曲线目标(第 5 轮触底 ≥0.25×);模拟器门 #13 断言
tune_restart_curve,text,0,1:0.48:0.42:0.40,[B§4.3] 重开曲线目标(第 5 轮触底 ≥0.25×);模拟器门 #13 断言。[v1.0→v1.1] 用户拍板方案 A:二轮 sim 实测校准值(旧 1:0.6:0.4:0.3 为一轮解析预估,未计阻尼)
tune_event_timeout_default,text,0,opt_a,[B§7] 冤魂申诉超时默认 = 超度(opt_a)
tune_souls_div,number,10000,,"[B§6] 超度亡魂 = floor(本轮累计阴德 ÷ 10,000)(叙事计数器,不设闸门;P-14)"
tune_enthrone_suihui_req,number,60,,[G§3.4] 阴司敕封解锁条件:宿慧 ≥60([B§4.4] 仅给 8-12h 体感,采信 GDD 数值)
1 id kind num text desc_cn
22 tune_skip_levels number 25 [B§4.2] 跳过机制每档 +25 级
23 tune_skip_level_cap_per_gen number 50 [B§4.2] W5 裁定 P-27(F-2):跳过每档获赠 = min(floor(宿慧/5)×25, 本值)(原无封顶 → R2 开盘白送 2850 级)
24 tune_enthrone_rebirths number 2 [B§4.4] 阴司敕封触发:转世 ≥2(约第 2-3 轮,累计 8-12h 为其 pacing 后果)
25 tune_restart_curve text 0 1:0.6:0.4:0.3 1:0.48:0.42:0.40 [B§4.3] 重开曲线目标(第 5 轮触底 ≥0.25×);模拟器门 #13 断言 [B§4.3] 重开曲线目标(第 5 轮触底 ≥0.25×);模拟器门 #13 断言。[v1.0→v1.1] 用户拍板方案 A:二轮 sim 实测校准值(旧 1:0.6:0.4:0.3 为一轮解析预估,未计阻尼)
26 tune_event_timeout_default text 0 opt_a [B§7] 冤魂申诉超时默认 = 超度(opt_a)
27 tune_souls_div number 10000 [B§6] 超度亡魂 = floor(本轮累计阴德 ÷ 10,000)(叙事计数器,不设闸门;P-14)
28 tune_enthrone_suihui_req number 60 [G§3.4] 阴司敕封解锁条件:宿慧 ≥60([B§4.4] 仅给 8-12h 体感,采信 GDD 数值)
Binary file not shown.
Binary file not shown.
@@ -7,6 +7,20 @@
---
## 后记(2026-10-21 · #13 方案 A 落定,本报告 §0-§7 为二轮当时记录)
**用户已对 #13 拍板方案 A——接受实测曲线为校准则。** 文策渊产出 Balance Bible v1.1
(`design/gdd/2026-10-21-F-balance-bible-v1.1.md` §4.3):#13 目标曲线 `1:0.6:0.4:0.3` →
**`1:0.48:0.42:0.40`**(标注为二轮 sim 实测校准值,归因 = 一轮预估的「182min÷倍率」线性模型未计
阻尼),R4 目标带随曲线改为 [0.30,0.50],**R4=0.396 入带,新口径下 R1-R4 全 PASS**;R5 起 ≥0.25× 不变。
工程侧同步落地(W5 收尾,commit 待主理人代提):`PrestigeModel.RESTART_TARGETS` → `[1.0, 0.48, 0.42, 0.40];
`tune_restart_curve`(balance_tuning.csv,经 gen 脚本)→ `1:0.48:0.42:0.40`;`gates.gd` 文档注释同步;
`test_economy_formulas` / `test_balance_data` 断言更新。**sim 复跑验证 #13 新口径 PASS**(见 §6 补记)。
本节之下 §0-§7 的"#13 残留 FAIL"表述均为**旧曲线口径下的二轮当时判定**,保留作校准历史,不需回改。
---
## 0. 结论速览
| 项 | 结果 |
@@ -179,6 +193,16 @@
**确定性备注**:sim 无时钟依赖(RandomStrategy 种子 7、固定步长),二轮报告重跑逐值一致;`report-2026-10-21.json` 为可复现产物。
**§6 补记(2026-10-21 · W5 收尾:#13 方案 A 落地后复跑)**:
| 步骤 | 结果 |
|---|---|
| gen 脚本重跑 | exit=0;漂移哈希前后**仅 2 文件变化**(`balance_tuning.csv` + 其 build JSON——`tune_restart_curve` 一行 1:0.6:0.4:0.3 → 1:0.48:0.42:0.40),其余 95 文件字节不变 |
| import_all | PASS(10 表/238 行/0 违规,差异化「~0 变更」= importer 与 gen 产物逐字节一致) |
| test_runner | **PASS(752 检查全过)**——economy_formulas 160→162(新增 R2=0.48/R3=0.42 断言);balance_data 的重开曲线文本断言同步 v1.1 |
| sim | exit=0;**`restart.pass=true`**:「R1=1.00(目标 1.00);R2=0.48(目标 0.48);R3=0.42(目标 0.42);R4=0.40(目标 0.40)」——新曲线下 R1-R4 全入带;主口径未过门 = [];硬门 5/10 双 true;6 个 `pass:false` 全部为非主口径策略 cross 观测(greedy#2、novice#3/#14、random#2/#3/#14,主理人已核) |
| 报告 | `tests/sim_reports/report-2026-10-21.json` 已按新代码重生成(同日覆盖;FAIL 旧版存于 commit `c0a5c52` 历史) |
---
## 7. 待办与阻塞
@@ -198,16 +222,18 @@
### 7.2 待裁定(按优先级)
1. **#13 R4 残留**:选项 A/B/C/D(§3.3),工程建议 A 或 D;若选 C,工程立即可跑变体 sim 定量。
2. **devour 后 H10 越红线**(§4.3):是否纳入 #10 断言口径 + 设计侧处理选项,建议 W6 敕封校准项一并处理。
3. **设计侧文档补登**:[B§12] 表清单补登 `wrath_layers`(架构文档在 C 盘设计仓,属文策渊);若采选项 A,需同步 [B§4.3] 重开目标曲线修订条。
1. ~~**#13 R4 残留**~~ → **已定**:用户拍板方案 A,Balance Bible v1.1 §4.3 曲线改 1:0.48:0.42:0.40,代码/数据/测试已同步(见文首后记)。
2. **devour 后 H10 越红线(当前唯一已知的红线口径缺口)**(§4.3):门 #10 的"单轮峰值"是否取 max-over-runs 待决——文策渊已确认 devour 轮后 H10 峰值 2.498e14 越红线 2.5×(当前 #10 双断言只含 greedy 单轮 11.831B + restart lifetime 7.007B,devour 轮不在断言内)。**W6 敕封校准时决策;在此之前不扩断言范围**(扩了会让 #10 变 FAIL,阻塞当前全绿状态)。
3. **设计侧文档补登**:[B§12] 表清单补登 `wrath_layers`(架构文档目录树已由文策渊补登;架构文档 §4.2 MultiplierSet 注释与目录树 meta_upgrades.csv 行本收尾轮已同步)。
### 7.3 W6 输入备忘
- **红线口径缺口(唯一已知)**:门 #10"单轮峰值"是否取 max-over-runs 待决——devour 轮后 H10 峰值 2.498e14 越红线 2.5×(文策渊已确认)。W6 敕封校定时决策;**当前不扩断言范围**(保全绿状态)。若取 max-over-runs,需先设计侧处理后 H10 膨胀(gen12 rate 下调或 lifetime 显式软上限,[裁] §2.5 已列选项)。
- M-4:门 #9-b 的 β 口径标定(离线 8h 推进比)仍缺数据;
- M-5:门 #11(BossBattle 接入后)与 P-10/P-15 的 #11-d 触发条件;
- #13 触底支路(R5 起 ≥0.25×)本轮未覆盖——8h 预算只完成 R1-R4;如需验证触底支路,restart 预算提至 10-12h;
- 任务 #22/#27(W3/W4 批次提交)同受 git 缺失阻塞,可一并处理。
- #13 触底支路(R5 起 ≥0.25×)本轮未覆盖——8h 预算只完成 R1-R4;新曲线下复跑时 restart 预算提至 10-12h;
- m04 P2 备选("跳过每档封顶 +25 级")是否转正——依赖 #13 曲线数据,v1.1 已列 P2 维持待定;
- 任务 #22/#27/#44(W3/W4/W5 批次提交)同受 git 缺失阻塞,可一并处理。
---
+9 -2
View File
@@ -13,12 +13,19 @@ extends RefCounted
# 宿慧全局加成(economy_state.recompute):0.50×(1−e^(−宿慧/420)) 渐近封顶
# (W5 裁定 F-1;旧 3%/级线性无界已废止,tune_suihui_global_pct 移除)
# 敕封触发:转世 ≥ enthrone_rebirths([B§4.4] 约第 2-3 轮)
# 重开曲线目标:1 : 0.6 : 0.4 : 0.3,第 5 轮起触底 ≥0.25×(门 #13 断言)
# 重开曲线目标:1 : 0.48 : 0.42 : 0.40,第 5 轮起触底 ≥0.25×(门 #13 断言)
# [v1.0→v1.1] 用户拍板方案 A:曲线 = 二轮 sim 实测校准值(Balance Bible
# v1.1 §4.3;旧 1:0.6:0.4:0.3 为一轮解析预估,「182min÷倍率」线性模型未计阻尼)
#
# 静态纯函数:sim 与游戏共用(零漂移);无状态、无分配(除返回值)。
# ============================================================================
const RESTART_TARGETS: Array[float] = [1.0, 0.6, 0.4, 0.3]
## [v1.0→v1.1] 二轮实测校准值(用户拍板方案 A,Balance Bible v1.1 §4.3):
## 旧 1:0.6:0.4:0.3 为一轮解析预估——「182min÷总倍率」线性模型未计成本指数/
## 解锁门/购买节奏的阻尼,实测各轮慢 +2.0/+6.2/+9.9min 逐轮放大,R4=0.396
## 超出旧带上限 0.375(5.6% 边际超差);R2/R3 入带、曲线单调递减、红线已根治。
## 镜像数据行 tune_restart_curve(balance_tuning.csv);R5 起触底 ≥0.25× 不变。
const RESTART_TARGETS: Array[float] = [1.0, 0.48, 0.42, 0.40]
const RESTART_FLOOR := 0.25
+5 -2
View File
@@ -14,7 +14,9 @@ extends RefCounted
# #3 对照 halls.csv 新到达目标列(10/20/36/56/80/102/122/142/164/180)±20%
# #14 同 #3 目标表;主口径 greedy(novice/random 噪声归 cross 门观测)
# #10 单轮峰值 → **双断言**(单轮 + restart 5 轮 lifetime 均 ≤1e14,见 gate_peak_double)
# #13 前 4 轮容差 ±40% → ±25%(R5 起触底 ≥0.25× 口径不变)
# #13 前 4 轮容差 ±40% → ±25%(R5 起触底 ≥0.25× 口径不变);
# 目标曲线 [v1.0→v1.1] 1:0.6:0.4:0.3 → **1:0.48:0.42:0.40**(用户拍板方案 A:
# 二轮实测校准值,Balance Bible v1.1 §4.3;值在 PrestigeModel.RESTART_TARGETS)
# ============================================================================
const HARD_GATES: Array[int] = [5, 10] # W6 起 CI 硬门(架构 §7.2)
@@ -112,7 +114,8 @@ static func evaluate_wrath_tradeoff(pure_report: Dictionary, devour_report: Dict
"detail": "devour/pure = %.2f×(%.0fmin vs %.0fmin)" % [ratio, b / 60.0, a / 60.0]}
## 门 #13(重开曲线):rebirths=4 的报告;各轮 H10 间隔比 ≈ 1:0.6:0.4:0.3
## 门 #13(重开曲线):rebirths=4 的报告;各轮 H10 间隔比 ≈ 1:0.48:0.42:0.40
## ([v1.0→v1.1] 用户拍板方案 A:二轮实测校准值,Balance Bible v1.1 §4.3)
static func evaluate_restart(report: Dictionary) -> Dictionary:
var rebirths: Array = report.get("rebirths", [])
if rebirths.size() < 2:
+2 -2
View File
@@ -278,7 +278,7 @@ TUNING = [
("tune_skip_levels", "number", 25, "", "[B§4.2] 跳过机制每档 +25 级"),
("tune_skip_level_cap_per_gen","number", 50, "", "[B§4.2] W5 裁定 P-27(F-2):跳过每档获赠 = min(floor(宿慧/5)×25, 本值)(原无封顶 → R2 开盘白送 2850 级)"),
("tune_enthrone_rebirths", "number", 2, "", "[B§4.4] 阴司敕封触发:转世 ≥2(约第 2-3 轮,累计 8-12h 为其 pacing 后果)"),
("tune_restart_curve", "text", 0, "1:0.6:0.4:0.3", "[B§4.3] 重开曲线目标(第 5 轮触底 ≥0.25×);模拟器门 #13 断言"),
("tune_restart_curve", "text", 0, "1:0.48:0.42:0.40", "[B§4.3] 重开曲线目标(第 5 轮触底 ≥0.25×);模拟器门 #13 断言。[v1.0→v1.1] 用户拍板方案 A:二轮 sim 实测校准值(旧 1:0.6:0.4:0.3 为一轮解析预估,未计阻尼)"),
("tune_event_timeout_default","text", 0, "opt_a", "[B§7] 冤魂申诉超时默认 = 超度(opt_a)"),
("tune_souls_div", "number", 10000, "", "[B§6] 超度亡魂 = floor(本轮累计阴德 ÷ 10,000)(叙事计数器,不设闸门;P-14)"),
("tune_enthrone_suihui_req","number", 60, "", "[G§3.4] 阴司敕封解锁条件:宿慧 ≥60([B§4.4] 仅给 8-12h 体感,采信 GDD 数值)"),
@@ -664,7 +664,7 @@ def self_check(sheets) -> None:
assert tune["tune_click_zone_cap"]["num"] == 16
assert tune["tune_gen_zone_cap"]["num"] == 8
assert tune["tune_global_zone_cap"]["num"] == 64
assert tune["tune_restart_curve"]["text"] == "1:0.6:0.4:0.3"
assert tune["tune_restart_curve"]["text"] == "1:0.48:0.42:0.40"
assert tune["tune_event_timeout_default"]["text"] == "opt_a"
# W4 方案 B 调参 4 行(systems-spec §1.2;用户 2026-10-20 拍板)
assert tune["tune_boss_kappa_base"]["num"] == 0.01
+2 -2
View File
@@ -260,8 +260,8 @@
}
},
"restart": {
"detail": "R1=1.00(目标 1.00);R2=0.48(目标 0.60);R3=0.42(目标 0.40);R4=0.40(目标 0.30)",
"pass": false
"detail": "R1=1.00(目标 1.00);R2=0.48(目标 0.48);R3=0.42(目标 0.42);R4=0.40(目标 0.40)",
"pass": true
},
"runs": [
{
+1 -1
View File
@@ -34,7 +34,7 @@ func run(a, data: BalanceData) -> void:
a.near(data.tune_num("tune_souls_div", 0.0), 10000.0, 1e-9, "超度除数 10000")
a.near(data.tune_num("tune_enthrone_suihui_req", 0.0), 60.0, 1e-9, "敕封宿慧门槛 60")
a.near(data.tune_num("tune_enthrone_rebirths", 0.0), 2.0, 1e-9, "敕封转世门槛 2")
a.eq(data.tune_text("tune_restart_curve", ""), "1:0.6:0.4:0.3", "重开曲线文本")
a.eq(data.tune_text("tune_restart_curve", ""), "1:0.48:0.42:0.40", "重开曲线文本(v1.1 校准值)")
a.near(data.tune_num("tune_wrath_layers", 0.0), 22.0, 1e-9, "冤煞 22 层")
a.near(data.tune_num("tune_click_base", 0.0), 1.0, 1e-9, "点击基础值 1")
# W5 裁定调参(sim 一轮裁定 §2.3/§2.4):宿慧渐近 + 跳过封顶 + 削减速加深
+3 -1
View File
@@ -37,7 +37,9 @@ func run(a, _data: BalanceData) -> void:
a.eq(PrestigeModel.skip_count(23, 5), 4, "skip 23/5 = 4")
a.eq(PrestigeModel.skip_count(23, 4), 5, "skip 23/4 = 5(m04)")
a.near(PrestigeModel.restart_target(0), 1.0, 1e-9, "重开曲线 R1")
a.near(PrestigeModel.restart_target(3), 0.3, 1e-9, "重开曲线 R4")
a.near(PrestigeModel.restart_target(1), 0.48, 1e-9, "重开曲线 R2(v1.1 校准值)")
a.near(PrestigeModel.restart_target(2), 0.42, 1e-9, "重开曲线 R3(v1.1 校准值)")
a.near(PrestigeModel.restart_target(3), 0.40, 1e-9, "重开曲线 R4(v1.1 校准值)")
a.near(PrestigeModel.restart_target(4), 0.25, 1e-9, "重开曲线 R5 触底")
a.true_(PrestigeModel.enthrone_available(2, 2), "敕封:转世 2 可")
a.true_(not PrestigeModel.enthrone_available(1, 2), "敕封:转世 1 不可")