# 数据集规格文档（DATA SPEC）

> **用途**：让别人能判断「**这份数据能不能用**」—— 这是"能交付"的前提。
> **⚠ 一条纪律**：**已知限制必须写全 · 不许淡化** —— 尤其是 `LIMITATIONS.md` 的 **L-1**。
> **⚠ 另一条**：**凡是标 `⚠ 待核实` 的字段，交付前必须实测填全**（**不许猜**）。

---

## 一、这是什么数据

```
**类型**：**行为级合成面板数据**（synthetic behavioral panel）
   —— **不是真实人口数据** · **不是抽样调查数据** · **不是统计模型输出**

**单位**：**虚拟个体（soul）** 与 **虚拟个体的一生（life）**
**粒度**：**个体 × 年**（可细到个体 × 日，但默认导出年）
**覆盖**：**出生 → 求学 → 就业 → 婚育 → 迁移 → 死亡 → 转世**
```

**⚠ 三句必须随数据一起给出的话：**
```
① **这些是【虚构人物】** —— 姓名 · 事件 · 关系**全部由规则引擎生成**，
   与任何真实个人**无对应关系**。
② **它【不是】对任何真实城市/人群的测量** —— 而是一个**参数化的沙盘**。
③ ⚠ **它【不能】用于"预测真实人群"** —— 理由见第五节（**没有真实对照**）。
```

---

## 二、数据集清单

| 数据集 | 文件 | 粒度 | 说明 |
|---|---|---|---|
| **灵魂档案** | `souls500.csv` | 个体 | 每个虚拟人的静态属性（姓名/性别/性格原型/出生） |
| **面板数据** | `panel500.csv.gz` | 个体 × 年 | 逐年状态（年龄/婚育/职业/财富/健康…） |
| **一生轨迹** | `lives500.jsonl.gz` | 个体 | 每人一条完整生命史（JSON Lines） |
| **年度汇总** | `demog.csv` | 年 | 聚合指标（整城视角）· ⚠ **列数随引擎版本变化：29 / 57 / 70 / 72** |
| **运行清单** | `manifest.json` | 运行 | 参数 · 种子 · 规模 · 年数 · **引擎指纹** |
| **诊断探针** | `govgate_probe.jsonl` 等 | 年 | 政府层 / 教育 / 失业 / 破产 四个诊断流 |

**🔴 已实测：`demog.csv` 的列数【随引擎版本变化】—— 这是一个交付陷阱**

```
全域扫描 60 个 demog.csv 的结果：
   列数  29 ⇒  1 个文件   （引擎 `f4f3d34f2221016b`）
   列数  57 ⇒ 36 个文件   （旧批次 · 如 `ab10A_sh`）
   列数  70 ⇒  3 个文件   （引擎 `370572ff4ed99c78`）
   列数  72 ⇒ 20 个文件   （引擎 `0269a820e07e0423` · 最新）
⇒ ⇒ ⚠⚠ **所以"72 列"只是【最新版】· 不是通例** ❗
   ⇒ ⭐ **消费者拿到 57 列的数据，会以为"缺了 15 列"** —— 而其实是引擎版本不同 ✓
   ⇒ ⇒ ✅ **正确做法**：**按【引擎指纹】确定列数**（指纹在 `RUN_MANIFEST.json` / `manifest.json` 里）
```

**⇒ 交付时必须做的一件事**：**在数据集中附【引擎指纹 → 列数】的对应表**，
否则接收方无法判断"字段缺失"与"版本差异"。

**✅ 已实测**（2026-10-07）：

```
`souls500.csv` = **4 列**（表头 + 491 行）：
   `sid` · `lives` · `各世性别` · `平均结局人格(O|C|E|A|N)`
   ⇒ ⚠ **列名含中文** ⇒ 读取时必须显式指定 UTF-8（默认编码会乱码）

`panel500.csv.gz` = **17 列**：
   `bid` · `sid` · `life` · `gen` · `year` · `age` ·
   `O` · `C` · `E` · `A` · `N` · `edu` · `health` · `job` · `inc` · `mstat` · `dist`
   ⇒ ⚠⚠ **它是 `panel500.csv.gz`（gzip 压缩）· 不是 `panel500.csv`** ——
     按 `.csv` 找会**找不到文件**（本项目的样例包脚本就因此先报"未找到"）✓
   ⇒ ⚠ **解压要流式处理**（`zlib.createGunzip()` + 逐行）
```

**⚠ 四个文件的粒度与关联键**：
```
demog.csv   1 行 = 1 年        （城市级）
souls.csv   1 行 = 1 个 sid    （灵魂级 · 跨世汇总）
panel.csv   1 行 = 1 bid 的 1 年（人·年 · 做统计最常用）
lives.jsonl 1 行 = 1 bid 的一生 （人·一生 · 做序列分析用）
关联：`panel.sid ↔ souls.sid` · `panel.bid ↔ lives.bid` · `lives.sid ↔ souls.sid`
```

---

## 三、字段字典

### 3.1 `demog.csv`（**72 列 · 已核实列数**）

**结构**：**表头 + 每年一行**（`year` · `day` · …）
**⚠ 口径**：**"从快照起跑"时，首行不是第 1 年** —— 例如快照起点为 `day 730` ⇒ 首行 `year=3`。

**已知列族（按用途分）**：

| 族 | 代表列 | 含义 | ⚠ 已知口径问题 |
|---|---|---|---|
| **时间** | `year` · `day` | 年 / 日 | — |
| **人口** | `pop` · `births` · `marriages` · `divorces` · `migIn` | 总量与流量 | — |
| **生育** | `tfr` · `fertWill` · **`expBirthsY`** · **`judgedN`** | 生育率 / 意愿 / 期望出生 | 🔴 **`expBirthsY` 的分母内生**（见 L-5①） |
| **教育** | **`normE1`~`normE6`** | ⚠ **不是学历分布** | 🔴 **它是"ASFR 质量覆盖比例"· 年年不变的常数** |
| **就业** | `unempRate` | 失业率 | ⚠ **是比值**；`unemp`/`adults` 绝对值**不在表里** |
| **经济** | `avgIncome` · `avgWealth` · `bankruptN` | 收入/财富/破产数 | ⚠ **`bankruptN` 是【个人】破产 · 不是市政破产** |
| **情绪** | **`mood`** | 心情 | 🔴 **直连项**：公式含 `+ (green − 1) × 4`（见 L-5⑥） |
| **队列** | `coh0` · `cohMean` · `cohNever` | 队列指标 | ⚠ **只在 ≥40 年跑里有效** |

**⚠⚠ 最重要的一条**：
```
🔴 **`demog.csv` 里【没有】基建级数 / 预算 / 财政 任何一列**
   ⇒ ⚠ **所以"政府层改了基建"时，`demog.csv` 可能【看起来没变】** ❗
   ⇒ ⇒ ✅ **要看基建/财政 ⇒ 必须读 `govgate_probe.jsonl`**（见 3.3）✓✓
```

### 3.2 `lives500.jsonl`（一生轨迹）

**格式**：**JSON Lines**（一行一个灵魂的一生）
**⚠ 解压要流式处理**（**别整个读进内存** —— 它是 gzip 压缩的）

**✅ 已实测：17 个顶层字段**
```
sid · life · bid · gen · arche · truncated · birthDay · deathDay · ageAtDeath ·
L1_start · L1_end · L1_peak · dev · ev · events · yearly · rebirth
```

**一条真实样例**（首条 · **29,695 字节** · 已截断显示）：
```json
{"sid":2,"life":1,"bid":268479,"gen":1,"arche":0,"truncated":true,
 "birthDay":0,"deathDay":29127,"ageAtDeath":92,
 "L1_start":[34.878635,48.584374,41.286592,48.879903,53.357333],
 "L1_end":[30.117402,46.289462,33.593333,49.145067,...]}
```

**⚠⚠ 体量与处理方式**：
```
· 单条可达 **~30 KB** —— 首条含 `events` **431 条** 与 `yearly` **79 个年点**
· ⇒ ⚠ **完整档案解压后可能非常大** ⇒ **必须流式**（逐行 `readline` · 别整个读进内存）
· ⇒ ⚠ 本项目的样例包子集：**20 条 = 746 KB**（可据此估算全量）
```

**⭐ 五维顺序**：`L1_start` / `L1_end` / `L1_peak` 三个数组**固定为 `O,C,E,A,N` 顺序**
（与 `panel.csv` 的五个独立列 `O`/`C`/`E`/`A`/`N` 一一对应）。
⇒ ⭐ **因此"人格变化"可直接算**：`delta[i] = L1_end[i] − L1_start[i]` ✓

### 3.3 四个诊断探针（**独立产物 · 不在 `demog.csv` 里**）

| 探针 | 关键字段 | 用途 |
|---|---|---|
| **`govgate_probe.jsonl`** | **`subway`/`hospital`/`school`/`green`** · `payRatio` · `capDay` · `gateLog` · `decide` | ⭐ **政府层的一切**（**基建级数在这里**） |
| `edu_probe.jsonl` | 学历 6 档分布 · **按年龄队列** · `school` · `eduPressure` | 教育链（**因为 `demog.csv` 无学历列**） |
| `unemp_probe.jsonl` | `adults`（分母）· **`unempA`（真分子）** · `unempB` | ⚠ **`unempA` 才是真分子**（`unempB` 含自动政策调整） |
| `bankrupt_probe.json` | 破产者画像（年龄/收入/财富/职业） | 破产诊断 |

---

## 四、生成方法（**可复现性的全部凭据**）

```
⭐ **一份数据集要能复现 · 必须同时给出这六项**：
   ① **引擎指纹**（如 `0269A820E07E0423`）
   ② **参数集**（如 `SOUL_LIFE_V2=all` · `SOUL_FORCE=1` · `SOUL_XFER=0` ·
      `SOUL_AMP_MUL=1` · `SOUL_RUN_PURPOSE=measurement`）
   ③ **随机种子**（整数）
   ④ **规模**（人口数）· ⑤ **年数**
   ⑥ **起跑方式**（**fresh 城市** / **从快照** —— ⚠ **快照起点会"吃掉"前几年**）
```

**⚠⚠ 三条会让人复现不出来的坑：**
```
🔴 **① 快照与人口【绑定】** —— 一份 2,500 人的快照**不能**给 5 万人的跑用
🔴 **② 快照携带 `budget`** ⇒ **从快照起跑时"改预算初值"【无效】**
🔴 **③ `SOUL_SNAP_AT=2` ⇒ 实算年数 = `YEARS − 2`**（**快照起点吃掉 2 年**）
```

**⇒ ⭐ 可复现性的判据（我们有）：**
```
✅ **"同一指纹 + 同参数 + 同种子 ⇒ `demog.csv` 逐字节相同"** ——
   用 **SHA16** 对比即可验证（**这是可交给第三方的检验**）✓✓
```

---

## 五、⚠⚠ 已知限制（**不许淡化 · 直接引 `LIMITATIONS.md`**）

> **完整版见 `civilization\LIMITATIONS.md`（L-1~L-6）。以下为必读摘要。**

### 🔴 L-1（**最严重 · 会让结论方向错**）

```
**学历的【反向队列结构】（方向与真实世界相反）**
   · 现象：`q25-29` 的 `meanEdu` 10 年**暴跌 54.4%**，而 `q30-34`/`q40-49` **在升**
     ⇒ ⚠ **即模型里「越年轻 ⇒ 学历越低」· 而真实世界相反**（教育扩张）❗
   · 根因：学历抽自【区的**全年龄**文化程度表】（第一档 ≈61.6% · 而那主要是**老年人**贡献的）
           + 年龄截断**只压上限**
   · 判定：**不是 bug** —— 而是**「未声明的简化」且方向反号**
   ⇒ ⇒ 🔴 **"学历 → 婚育/收入"的结论【方向可能错】**
     ⇒ ⚠ **任何基于此类结论的下游工作【必须重做】** ✓
```

### 🔴 L-5（**口径歧义总表 · 6 条 · 每条都可能让结论反向**）

```
① **总量型生育指标不可单独用** —— `expBirthsY` 的分母**内生**
   ⇒ **政策越有效 ⇒ 越多人退出判定池 ⇒ 它越【降】** ⇒ **最易误读为"政策失败"**
② **"零差异"是歧义的** —— 有【四个】原因：开关没开 / 机制中立 / 无预算可花 / 账本无反馈
③ **"测不到"是歧义的** —— 指标不存在 / 因果链不存在 / 窗口不够
④ **"噪声大" ≠ "信号假"** —— 要看**效应 / 标准误的比**
⑤ **"干预装载了" ≠ "干预生效了"**
⑥ ⭐ **"指标测得到" ≠ "它在测真实世界的东西"** —— **直连项**（如 `mood` 读 `green`）
```

### ⚠ L-2 ~ L-4 · L-6 · 以及**本次新发现的五条**

```
· **L-2** 分区学历公式整体偏高 3.6~6.0pp（**可校正 · 水平偏差**）
· **L-3** ⚠ **教育政策语义与真实世界不同**：
   **`school` 不提高学历** —— 它通过 `fEdu`（学位压力）**影响生育意愿**
· **L-4** 财政模型原先只覆盖手动干预（**现已扩展 · 但需显式开启**）
· **L-6** 其他已知限制

⭐ **本次新发现（也必须写）**：
   ① **直连项陷阱**（`DIRECT_LINK_AUDIT.md`）—— `mood` 等指标**不能作政策效应证据**
   ② **`migOutCum` 恒为 0** —— **迁出通道从不触发**（人口模型少一条腿）
   ③ **门槛修好了"穷"却造出"富"** —— 税收/维护 = **98.39**（**财政约束失效**）
   ④ **长窗口经济无均衡** —— `avgIncome` 200 年涨 **30 倍**
   ⑤ **第 14 类静默失效** —— **"我需要的那个开关，从未进入 env"**
```

### ⚠⚠ 一条**元限制**（最重要）

```
⚠⚠ **本项目最大的缺口是【没有真实对照】**
   ⇒ ⇒ ⭐ **所以这份数据【不能】用于"预测真实人群"** ✓✓
   ⇒ ⇒ ⇒ ✅ **它能用于**：
     · **方法研究**（机制可解释的多智能体社会仿真）
     · **AI 训练**（合成行为数据 · **不需要"准"**）
     · **教学 / 演示**
     · **探索性分析**（"如果…会怎样"的**可能性空间**）
```

---

## 六、引用方式

```bibtex
@misc{virtualcity2026,
  title  = {A Behavior-Level Virtual City Sandbox: Data Release},
  author = {sevnwu},
  year   = {2026},
  note   = {Engine fingerprint: 0269A820E07E0423; scale: TODO; years: TODO;
            seeds: TODO},
  howpublished = {TODO: 由用户拍板（发布渠道/DOI）}
}
```

**⚠ 引用时【必须】同时给出**：**引擎指纹** + **规模/年数/种子** + **本文件**（`DATA_SPEC.md`）。

---

## 七、许可与定价

```
✅ **已拍板（2026-10-07 · 用户授权："版权这块你看着改就行 · 只要是利于传播"）**：

   · ⭐ **本文档 · 样例数据 · 本仓库全部 `.md`** ⇒ **`CC BY 4.0`**
     （**署名即可 · 引用 · 转载 · 研究 · 教学 · 商业原型全部允许**）
   · **引擎代码 + 完整数据** ⇒ **All rights reserved**（闭源）
   · **商业授权 / 完整数据** ⇒ **另行授权**（⚠ **定价待定**）

   ⚠ **为什么不是 `CC BY-NC`**：`NC` 会挡住**公司内部试用 · 教学 · 咨询原型** ——
      而那**正是潜在客户**。`BY` 只要求署名 —— 而**署名正是我们最想要的**。
   ⇒ ⭐ **商业化保护不靠许可** ⇒ 靠 ① 引擎闭源 ② 样例只有几千行 ③ 定制服务。

⚠ **仍待决定的两项**（**不影响分发**）：
   ① **定价锚**（按规模 / 按用途 / 按项目 / 按订阅）
   ② **姓名库能不能随【完整数据】给出**（⚠ **它可能含真实姓氏分布**）
   ⇒ ⚠ **而"是否提上海"已按保守表述处理**（用"某超大城市"）
```

---

## 八、⚠ 交付前的检查清单

```
☐ `souls500.csv` / `panel500.csv` 的**确切列名与列数**已实测填全
☐ `lives500.jsonl` **一条完整样例**已给出
☐ `demog.csv` 的 **72 列**逐列含义已核实（**尤其 `normE1~6` 不是学历**）
☐ **引擎指纹 + 参数 + 种子 + 规模 + 年数**已填入 `manifest` 段
☐ **L-1 已写进数据说明**（**不许省**）
☐ ✅ **许可已拍板**（**`CC BY 4.0` · 2026-10-07**）
☐ **总大小已确认**（样例包建议 **≤ 2 MB**）
☐ ⚠ **所有标 `TODO` / `⚠ 待核实` 的地方已清零**
   ⇒ ✅ **字段级 `⚠ 待核实` 已全部实测填全**（2026-10-07）：
     `souls` 4 列 · `panel` **17 列** · `lives` **17 字段 + 真实样例** ·
     `demog` **列数随引擎版本变化（29/57/70/72）**
   ⇒ ✅ **许可已清零**（2026-10-07）
   ⇒ 🔴 **仍剩的商业项**：`author` · `howpublished` · **定价锚** · **姓名库是否随完整数据给出**
     ⇒ 详见 **`SAMPLE_PACKAGE\LICENSE_TODO.md`**
```

---

## 附：与本文档配套的其它文件

| 文件 | 用途 |
|---|---|
| **`SYSTEM_PAPER_OUTLINE.md`** | 系统论文骨架（**影响力入口**） |
| **`LIMITATIONS.md`** | 完整限制清单（L-1~L-6） |
| **`SAMPLE_PACKAGE\`** | 可交付样例包 |
| **`REALITY_ANCHOR_PLAN.md`** | 真实对照方案（**若将来要卖"预测"则必需**） |
| `SHANGHAI_SCALE_BUDGET.md` | 规模/时间/内存的实测模型（**定价与交付量的依据**） |
| `DIRECT_LINK_AUDIT.md` | 直连项清单（**判读前必读**） |
