Skip to content

Commit 447d309

Browse files
author
NBL Agent
committed
v1.2.2: statistical validation hardening (FINAL_TEST leak fix + matched-card bootstrap + matched-seed rarity test)
FINAL_TEST leakage fixed (audit 2): model selection uses ONLY TRAIN+VALIDATION; FINAL_TEST is a true holdout, never used for fairness/Spearman/candidate selection/ threshold/logistic/weights. VALIDATION fairness uses VALIDATION-internal disjoint pairs only (audit 3). Pairwise + similar-BP split into train/validation/final (audit 4/5); release reports pairwiseFinal 0.761 and similarBPFinal 0.543. WinProbabilityModel: logistic fitted on TRAIN, VALIDATION sanity, FINAL only Brier/LogLoss/bins/ECE (audit 6). All scripts use Object.keys(NCB.ARCHETYPES) (7 archetypes incl. Support) (audit 7). Adjacent-rarity matrix pseudo-replication fixed (audit 8/9/15): matched-card bootstrap CI (statistical unit = independent card pair, not a battle); reports battle/generatedCard/seed/pair counts; archetype-conditioned rows; DRAWS reported separately (Support 'inversions' in v1.2.1 were Support-mirror stalemates, not rarity losses). Matched-Seed Rarity Test added (audit 10/11): causal (matched) 0.75-0.85 and population 0.57-0.64, both 0 hard inversions (<40%) -> per audit 22 NO Generator v2 rebalance. v1 fixture truly anchored to historical commit 19ca5a4 (audit 17/18): generated from a temp worktree at that commit; generator refuses to run without --historical-ref; tautological assertion removed (audit 19, count == 189). Health metrics: n=2000, point + 95% CI + P50/P75/P90/P95 per archetype (audit 20/21). stalemate 6.40% [5.41-7.56] exceeds the 5% point gate, driven by Support/Tank mirror sustain loops; documented honestly (audit 21: long tail is not a blocker; audit 24 A-E all satisfied), no hidden rebalance. Version 1.2.2; 177 tests pass; npm run verify + calibration + matched-rarity + adjacent matrix + similar-BP + health + browser QA (desktop/mobile) verified.
1 parent b5d3079 commit 447d309

21 files changed

Lines changed: 3334 additions & 850 deletions

FINAL-REPORT.md

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# FINAL-REPORT — 数值对战实验室
22

3-
**Status:** v1.2.1 · all final gates green · competencies verified in this environment
3+
**Status:** v1.2.2 · validation-correctness patch · §24 完成标准 A-E 全满足
4+
(health stalemate 发现已如实记录,非本版 blocker)· competencies verified
45

56
## 1. 项目最终结构
67

@@ -121,22 +122,28 @@ NUMERICAL-BATTLE-LAB-v1.0.0/
121122
- 战斗按 priority/speed 顺序结算(顺序非分片);相同/镜像阵容先手方约 -2~6 个百分点。
122123
- 单机本地,无网络多人/服务端/云存档;卡牌库存在浏览器本地存储。
123124
- 生成卡镜像自愈组合可能打满 maxRounds(draw),由 maxRounds 兜底不挂起。
125+
- **v1.2.2 实测**:Health stalemate n=2000 point **6.40% [5.41-7.56]**,超出 §20
126+
point<5% 门禁;主因是 Support 镜像(30.9%)与 Tank 镜像(8.0%)的 heal/shield
127+
sustain 循环。诊断确认单一 sustain 旋钮无法修复(结构性),按 §22 不重调 Generator v2,
128+
作为已文档化发现记录待后续轮次;不隐藏、不误标通过。
124129
- 战力是 1v1 通用排序指标,不是任意 matchup 的精确胜率;UI 不显示精确百分比,
125130
`战力较高 / 战力接近 / 战力较低` 或仅显示战力数字。
126131

127132
## 6. 验证门禁(本环境重测)
128133

129134
```
130-
ALL TESTS PASS ✔ 全量测试通过(含 v1 fixture / budget-curve / calibration-semantics)
131-
STATIC CHECK PASS ✔ 91 参数 / 18 Effect / v1.2.1 版本门禁 / manifest 审计
132-
V1 HISTORICAL FIXTURE ✔ 189 张旧卡 sha256 与 v1.1.0 逐字节一致
133-
HEALTH METRICS ✔ 秒杀 0% / 僵局 <5% / 中位数 8 回合
134-
STRICT RARITY MONOTONICITY ✔ adjacent-rarity-matrix:11 组方向全部正确(CI 下界 > 0.5)
135-
ADJACENT RARITY MATRIX ✔ winRateHigherTier 全部 > 0.5(A→A+ 0.535, S→SS 0.566, XS→XS典藏 0.540)
136-
SPEARMAN ✔ validation ~0.75-0.81(selected weights)
137-
PAIRWISE ORDERING ACCURACY ✔ ≥ 0.75(直接正反位)
138-
SIMILAR-BP FAIRNESS ✔ |ΔBP|/mean ≤ 5% 直接正反位 ∈ 40-60%
139-
WIN PROBABILITY CALIBRATION ✔ logistic(ln BP 比) + Brier/LogLoss/bins
135+
ALL TESTS PASS ✔ 全量测试通过(177,含 v1 fixture / budget-curve / calibration-semantics)
136+
STATIC CHECK PASS ✔ 91 参数 / 18 Effect / v1.2.2 版本门禁 / manifest 审计
137+
V1 HISTORICAL FIXTURE ✔ 189 张旧卡 sha256,由 v1.1.0 历史 commit 19ca5a4 worktree 生成
138+
HEALTH METRICS ✔ 秒杀 0% [0-0.19] · 中位数 9 · P90 25 · P95 40
139+
⚠ stalemate 6.40% [5.41-7.56](>5% 门禁,已文档化,非本版 blocker)
140+
STRICT RARITY MONOTONICITY ✔ adjacent-rarity-matrix:11 组方向全部正确(conditional)
141+
ADJACENT RARITY MATRIX ✔ conditional win rate 全部 EXPECTED(0.66-0.86),hard inversions 0
142+
MATCHED-SEED RARITY TEST ✔ Causal 0.75-0.85 / Population 0.57-0.64 全部 EXPECTED,hard 0
143+
SPEARMAN ✔ FINAL_TEST (frozen holdout) 0.785(validation selected)
144+
PAIRWISE ORDERING ACCURACY ✔ FINAL 0.761 ≥ 0.75(split train/validation/final 隔离)
145+
SIMILAR-BP FAIRNESS ✔ FINAL 0.543(ideal ~0.50)∈ 40-60%
146+
WIN PROBABILITY CALIBRATION ✔ 拟合于 TRAIN,FINAL holdout Brier 0.214 / LogLoss 0.621 / ECE 0.191
140147
BROWSER QA DESKTOP ✔ Chromium 1440×1000:全中文、新手流程可独立玩通、
141148
卡牌库/生成/帮助/高级实验室全部可用、无 JS 错误
142149
BROWSER QA MOBILE ✔ Chromium 390×844:无横向溢出、无 NaN
@@ -146,12 +153,27 @@ PAGES ACTION ✔ GitHub Pages deploy PASS
146153

147154
附注:浏览器控制台仅有 1 条 `favicon.ico` 404(非引擎错误,可忽略)。
148155

149-
## 7. 最终判断(v1.2.1 §19)
150-
151-
- **稀有度越高,统计意义上实力越高** —— 由 adjacent-rarity-matrix 直接支撑:
152-
11 组相邻档 higher-tier 胜率全部 > 0.5,95% CI 下界全部 > 0.5(严格单调)。
153-
- **战力越高,大概率更强** —— 由 Pairwise ordering accuracy ≥ 0.75 支撑。
154-
- **战力接近的卡,大多数情况下属于近似实力区间** —— 由 Similar-BP fairness
155-
(|ΔBP|/mean ≤ 5% 直接正反位,higher-BP 胜率 ∈ 40-60%)支撑。
156+
## 7. 最终判断(v1.2.2 §24)
157+
158+
- **A. 高稀有度整体人群统计更强** —— Population 11 组 conditional 全部 EXPECTED
159+
(0.57-0.64),hard inversions 0。
160+
- **B. 同 seed/archetype 仅提升 rarity 绝大多数不变弱** —— Causal matched 11 组
161+
conditional 全部 EXPECTED(0.75-0.85),hard inversions 0。
162+
- **C. 不存在大量 same-archetype higher-rarity WR<40% 系统性反转** —— matched +
163+
population 均 hard inversions 0。
164+
- **D. BattlePower FINAL 完全未参与模型选择** —— `modelSelectionUsedSplits =
165+
['TRAIN','VALIDATION']`,FINAL 只在 freeze 后 holdout。
166+
- **E. v1 fixture 真正来自 v1.1.0 历史 commit** —— 由 19ca5a4 worktree 生成,golden
167+
不可自动再生成。
156168
- **战力只是观测指标,不参与实际战斗结算** —— 由 battlepower.js 只读实现 +
157169
identical-data-diff-rarity 同 BP 测试 + BattleEngine 冻结保证。
170+
171+
## 8. v1.2.2 版本策略结论(§26)
172+
173+
- 本轮只修统计脚本(Phase A):FINAL_TEST 泄漏、pseudo-replication、Archetype 覆盖、
174+
v1 fixture 锚定、health CI 等全部修正;**产品功能与 Generator v2 冻结**
175+
- 新严格测量证明 **matched-seed rarity 与 population rarity 均健康**(0 hard
176+
inversion),故按 §22 Phase B **不做 Generator v2 数值重调**
177+
- Health stalemate 6.40% [5.41-7.56] 超出 §20 point<5% 门禁,作为 **validation
178+
correctness patch 的诚实发现**报告(§21 明确“长尾不是 blocker”,§24 A-E 全满足),
179+
不隐藏、不误标通过,留给后续轮次最小 sustain/composition 调整。

QA-REPORT.md

Lines changed: 71 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# QA 报告 — v1.2.1
1+
# QA 报告 — v1.2.2
22

3-
发布候选:`数值对战实验室` v1.2.1(战力可信度与相邻稀有度校准
3+
发布候选:`数值对战实验室` v1.2.2(统计验收方法与数据泄漏修正,validation correctness patch
44

55
## 自动化验证
66

@@ -10,7 +10,7 @@
1010
npm run verify
1111
```
1212

13-
结果:**全量测试通过**,静态架构检查通过(v1.2.1 版本门禁 + manifest 审计)。
13+
结果:**全量测试通过**,静态架构检查通过(v1.2.2 版本门禁 + manifest 审计)。
1414

1515
生成能力计数(verify 时):
1616

@@ -24,53 +24,96 @@ npm run verify
2424
- 示例技能:63
2525
- 示例状态:33
2626

27-
## 战力校准(v1.2.1 三分离门禁
27+
## 战力校准(v1.2.2 无泄漏三分离门禁
2828

2929
`scripts/power-calibration.js`:TRAIN / VALIDATION / FINAL_TEST 三套 seed 完全分离;
30-
`fitBattlePowerWeights()` 在 TRAIN 上自动拟合,VALIDATION 按 Spearman + similar-BP
31-
fairness 选模型,FINAL_TEST 只跑一次(§13A/§14)。
30+
`fitBattlePowerWeights()` 只在 **TRAIN** 拟合;**VALIDATION** 按 Spearman + similar-BP
31+
fairness(只用 VALIDATION 内部 disjoint pairs)选模型;**FREEZE****FINAL_TEST** 只做
32+
holdout 评估,全程不参与拟合/选择/调阈值(§2-6)。
3233

3334
```text
34-
Spearman VALIDATION: fitted 0.807 · committed 0.663 · balanced 0.698
35-
similar-BP fairness (direct <=5% battles): fitted 0.736 · committed 0.722 · balanced 0.617
36-
SELECTED (validation): wA -> {offense 0.22, durability 0.45, tempo 0.25, ...}
37-
Spearman FINAL_TEST (selected, run once): 0.735 (validation target >= 0.70)
38-
pairwise ordering accuracy (direct 正反位): validation 0.750 (target >= 0.75)
39-
similar-BP fairness (selected weights): 0.560 (ideal ~0.50)
40-
win-probability model: b0=0.038 b1=1.319 Brier=0.212 LogLoss=0.616 n=120
35+
Spearman VALIDATION: fitted 0.807 · committed 0.727 · balanced 0.698
36+
similar-BP fairness (VALIDATION-internal pairs): fitted 0.566 · committed 0.512
37+
SELECTED (validation, no FINAL): fitted -> {offense 0.25, durability 0.60, tempo 0.05, ...}
38+
--- MODEL FREEZED ---
39+
Spearman FINAL_TEST (frozen model, holdout): 0.785 (target >= 0.70)
40+
pairwise ordering: train 0.800 · validation 0.825 · FINAL 0.761 (final >= 0.75)
41+
similar-BP fairness: train 0.670 · validation 0.608 · FINAL 0.543 (ideal ~0.50)
42+
win-probability (fitted on TRAIN, b0=0.027 b1=1.309):
43+
FINAL holdout: Brier 0.214 · LogLoss 0.621 · ECE 0.191 (n=75)
44+
adjacent-rarity matrix: allDirectionCorrect YES · strictMonotonic YES · hardInversions 0
4145
CALIBRATION PASS ✔
4246
```
4347

44-
## 相邻稀有度矩阵(v1.2.1 新增
48+
## 相邻稀有度矩阵(v1.2.2 matched-card bootstrap
4549

46-
`scripts/adjacent-rarity-matrix.js`:11 组(C→C+ … XS→XS典藏),
47-
6 定位 × 6 种子 × 10 局 × 正反位(每组 5040 局),输出 winRateHigherTier / 95% CI / n。
50+
`scripts/adjacent-rarity-matrix.js`:11 组 × 7 Archetype(含 Support)× 48 matched seeds
51+
× 8 局/向;CI 由 **matched-card bootstrap**(统计单位 = 独立生成卡 pair,不是单场 battle)
52+
给出;胜率为 **conditional win rate(排除平局)**,drawRate 单独报告。
4853

4954
```text
50-
ALL ADJACENT DIRECTION CORRECT: YES (A→A+ 0.535, S→SS 0.566, XS→XS典藏 0.540 等)
51-
strictMonotonic = YES (所有相邻档 mean[n+1] > mean[n],CI 下界全部 > 0.5)
55+
ALL ADJACENT DIRECTION CORRECT (conditional): YES
56+
hard inversions (<40%): 0
57+
Support 每档 conditional 0.66-0.76 EXPECTED(v1.2.1 的“反转”实为 Support 镜像
58+
stalemate 平局——v1.2.2 将平局单独报告,不再把平局误计为高阶败)
59+
数据: independentSeedCount=48, generatedCardCount=7392, pairCount(cell)=48
5260
```
5361

54-
## 统计口径(v1.2.1 修正
62+
## Matched-Seed Rarity Test(v1.2.2 新增,§10/§11
5563

56-
- `rarityStrictMonotonic`(相邻 mean 单调)与 `rarityTrendAcceptable`(允许采样波动)
57-
分离报告,禁止把 trend acceptable 写成 strict monotonic YES。
64+
`scripts/matched-rarity-test.js`:同 seed/archetype/level 生成 C..XS 保持相同
65+
composition 结构,只变 rarity budget。
66+
67+
```text
68+
Causal (matched) : 11 组 conditional 0.75-0.85 全部 EXPECTED,hard inversions 0
69+
Population (random): 11 组 conditional 0.57-0.64 全部 EXPECTED,hard inversions 0
70+
```
71+
72+
## Health Metrics(v1.2.2 n=2000 + 95% CI + 分位)
73+
74+
`scripts/health-metrics.js`:n=2000 同稀有度镜像 1v1,point estimate + Wilson 95% CI。
75+
76+
```text
77+
one-shot : point 0.00% 95%CI [0.00-0.19] (gate < 5%) ✔
78+
stalemate: point 6.40% 95%CI [5.41-7.56] (gate < 5%) ✗ 见下
79+
rounds : P50 9 · P75 13 · P90 25 · P95 40 (median 6-10) ✔
80+
per-arch stalemate: Support 30.9% · Tank 8.0% · Balanced 3.8% · Controller 2.1% ·
81+
Bruiser/Assassin/Mage 0.0%
82+
```
83+
84+
> **stalemate 6.40% [5.41-7.56] 超出 §20 point<5% 门禁**:独立审计 §20/§21 预期此情形
85+
> (n=300 的 4.7% 统计误差足以让真实率 >5%),要求提高 n 并如实报告,且明确“长尾
86+
> 不是 blocker”。诊断(sustain-scale 扫描 720-1300)表明 Support 镜像是结构性
87+
> heal/shield sustain 循环,单一旋钮无法修复;按 §22 “rarity 健康则不继续过度调数值”,
88+
> v1.2.2 不重调 Generator v2,将其作为已文档化发现记录(后续轮次的最小 sustain/
89+
> composition 调整),不隐藏、不误标为通过。§24 完成标准 A-E(rarity/FINAL/fixture)
90+
> 全部满足。
91+
92+
## 统计口径(v1.2.2 修正)
93+
94+
- `rarityStrictMonotonic` / `rarityTrendAcceptable` 分离报告。
95+
- FINAL_TEST 完全未参与模型选择(`modelSelectionUsedSplits = ['TRAIN','VALIDATION']`)。
96+
- Pairwise / Similar-BP 拆成 train / validation / final,主报 final。
97+
- 全部脚本用 `Object.keys(N.ARCHETYPES)`(7 个,含 Support)。
98+
- 平局(stalemate)单独报告,不混入胜率。
5899
- BattlePower 口径:1v1 通用强度排序指标;3 主评分维度 + 4 诊断维度。
59100
- UI 移除精确预估胜率百分比 → `战力较高 / 战力接近 / 战力较低``card-ui.bpRelation`)。
60101

61-
## Generator 平衡(v1.2 深度重调 + v1.2.1 保留)
102+
## Generator 平衡(v1.2 深度重调 + v1.2.1 保留 + v1.2.2 冻结
62103

63104
`docs/GENERATOR-BALANCE-v1.2.md` 记录:
64105

65106
- 第一回合秒杀率:**0.0%**(目标 <5%)
66-
- 僵局率**1.7%**(目标 <5%
67-
- 战斗时长中位数:**8 回合**(目标 6–10)
68-
- v1.2.1 `V2_BUDGET_CURVE` 修正相邻档:A→A+(0.501→0.535)、XS→XS典藏(0.493→0.540)
107+
- 战斗时长中位数**9 回合**(目标 6–10
108+
- v1.2.2 **冻结 Generator v2**:rarity(matched + population)均健康、无 hard
109+
inversion,故不做数值重调;stalemate 发现如实记录。
69110

70-
## v1 历史 fixture(v1.2.1 新增
111+
## v1 历史 fixture(v1.2.2 真正锚定历史 commit
71112

72-
`tests/fixtures/generator-v1.1.0.json`:189 张代表旧卡 sha256(canonicalGeneratedCard)
73-
锁定,v1 byte-for-byte 防漂移(`tests/v1-fixture.test.js`)。
113+
`tests/fixtures/generator-v1.1.0.json`**189 张**旧卡 sha256(canonicalGeneratedCard)
114+
锁定,**由 v1.1.0 历史 commit `19ca5a443fcccd418d421a648f29a900098f55f8` 的临时
115+
worktree 实际生成**`scripts/generate-v1-fixture.js --historical-ref ... --src-dir ...`
116+
golden 不可自动再生成);`tests/v1-fixture.test.js` 只做 current-v1 vs golden 比对。
74117

75118
## 浏览器 QA
76119

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
项目目标不是不断给角色写特殊逻辑,而是维护一套固定的“数值战斗语言”:普通新角色、技能、状态只调整参数并组合组件;只有真正新增规则原语时才扩插件注册表。
66

7-
**v1.2.1 已改为玩家向 UI + 战力可信度校准**:默认导航 = 对战 / 卡牌 / 生成卡牌 / 玩法说明;
7+
**v1.2.2 已改为玩家向 UI + 战力可信度校准 + 统计验收加固**:默认导航 = 对战 / 卡牌 / 生成卡牌 / 玩法说明;
88
数值编辑 / 批量模拟 / 规则架构 / 对局重放 / 计算详情 / JSON 导入导出 收纳在右上角
99
「高级实验室」。默认全中文、默认 1 VS 1、新手流程(生成卡牌 → 加入卡牌库 →
1010
选卡选难度 → 开始对战 → 选技能 → 点目标 → 结算回合)无需知道 Seed/JSON/公式/ID。
@@ -27,7 +27,7 @@ python -m http.server 8765
2727
- 20 个示例实体、63 个示例技能、33 个状态;它们只是组件语言的示范组合,不是引擎上限。
2828
- **生成卡牌(Generator v2)**:12 档稀有度(C..XS 典藏版)、等级 1..100、7 种定位、
2929
确定性中文名称、Composition Grammar 技能组合、被动/触发预算真实消耗。
30-
- **战力评分(BattlePower)**:1v1 通用强度排序指标(v1.2.1 口径),
30+
- **战力评分(BattlePower)**:1v1 通用强度排序指标(v1.2.2 口径,FINAL holdout 独立验证),
3131
3 个主评分维度(进攻/生存/节奏)+ 4 个诊断维度(续航/功能/经济/稳定),
3232
复用引擎期望值数学;仅展示、不参与战斗结算。
3333
- **卡牌库**:本地持久化,可查看/选择/删除/同种子再生成/复制种子/改名。

0 commit comments

Comments
 (0)