# 座標即內容：受約束組合空間的雙射枚舉與可導航生成宇宙
### —— 以「詩雲 / Poetry Cloud」為例的技術重建與通用化

> **本文性質**：技術方法論論文，目的是把一類技術從一個具體網頁中**抽象出來、形式化、並寫到能照著從零重建的精度**。
> **clean-room 聲明**：本文只提取**方法（演算法與不變式）**——方法、數學、演算法不受著作權保護。本文**不引用、不重製**對方的原始碼、字表資料、品牌或任何受保護的具體表達。所有命名、結構、公式均為本文獨立重述，供獨立重新實作之用。（可查證：對方的**字表 DATA 本就不在前端程式碼內**，而是另以外部 JSON 載入；詩人真作資料表亦然。本文未取得、亦未重述其內容。）
> **定位**：承 `paradigms/` 的 MSSP 與「從尋找到生成」範式；本技術是「生成 > 儲存/尋找」的一個可運行具體化。

---

## 0. 摘要

存在一類網頁，它把「**所有可能的詩**」做成一座可以用滑鼠飛進去的三維星雲。它那座「無限生成星雲」**不靠資料庫、不把任何一首『生成的』詩存在任何地方**（少數策展真作另從靜態資料載入，見 §11.2，不影響生成層的零儲存）；它的網址列裡那一串近百位的數字，**本身就是一首詩的完整座標**。樸素爬蟲抓到的是一個空殼，因為內容不在 HTML 裡——內容是瀏覽器拿著那個數字，從一個**雙射枚舉**當場算出來的。

把這件事拆開，會發現它不是「一個關於詩的網站」，而是一個通用模式的實例。本文將這個模式形式化為四個構件：

1. **內容即索引**：用雙射數系把「一個物件」與「一個大整數」一一對應；
2. **受約束子空間的排名/反排名**：當合法物件只佔組合空間的極小一塊（如格律詩的平仄與押韻），對這個**受約束子集**建立 `整數 ↔ 物件` 的雙射——這是全技術的皇冠；
3. **座標 ↔ 索引的可逆綁定**：用確定性空間雜湊，把每個索引固定散佈到三維空間的一點，反過來也能由空間位置取回索引；
4. **URL 即狀態**：把索引寫進網址，於是「內容定址、零後端、可分享、天然防爬」同時成立。

本文逐一形式化這四個構件、證明其關鍵不變式、抽象出通用的「X 之雲」介面、給出可照著重建的 MSSP 模組藍圖與 Knuth 閘門測試計畫，最後誠實對照它的邊界（訊號淹沒、可發現性、技術與財產的界線）。

---

## 1. 緣起：從一個「網頁比賽」到一類技術

原作把它當成一個有趣的網頁作品。但作品只是**載體**，真正被它一次到位地縫合起來的，是幾條本來各自存在、卻很少被合到一起用的線索：

- **波赫士《巴別圖書館》**：一座包含所有可能書籍的圖書館。它的哲學困境是「一切都在裡面，但你找不到任何有意義的東西」。
- **劉慈欣《詩雲》**：一個技術奇點文明為了寫出超越李白的詩，窮舉了所有可能的漢字排列，把整個太陽系變成儲存裝置——卻發現「窮舉出了所有好詩，卻無法把它們從垃圾裡認出來」。
- **組合物件的排名/反排名（ranking / unranking）**：計算組合學裡一個古典工具——在一個有限集合上建立 `{0,1,…,|S|-1} ↔ S` 的雙射，於是可以「給編號取物件」與「給物件取編號」。
- **內容定址（content addressing）**：當內容能由其本身的標識完全決定，標識就不再是「指向內容的指標」，而**就是內容**。

把這四條合起來，就得到本文要重建的東西。《詩雲》小說裡做不到的「從垃圾裡認出好詩」這一步，這個技術**誠實地沒有解決**——但它解決了前一半：**讓整個空間可被定址、可被導航、可被分享，且零儲存**。這一半本身就極有價值，而且**與「詩」完全無關**，可以套到任何結構化的組合內容上。

### 1.1 歷史脈絡（站在哪些肩膀上）

這個技術不是憑空的，它是幾個成熟領域第一次被縫在同一個介面背後：

- **巴別圖書館的可運行版本**：Jonathan Basile 的 *Library of Babel* 網站早已示範「用座標當場生成全部可能的英文文本頁」，核心也是「頁面內容 = 座標的確定性函數」。本技術可視為它的「**加約束 + 三維可導航 + 漢語格律**」進階版——關鍵升級正是 §4 的「受約束子空間」。
- **組合物件的排名/反排名**：這是計算組合學的古典工具（Nijenhuis–Wilf《Combinatorial Algorithms》、Kreher–Stinson《Combinatorial Algorithms: Generation, Enumeration, and Search》系統化了排列、組合、子集等的 rank/unrank）。本技術把它從「排列組合」推到「**受平仄/押韻約束的字串**」。
- **受文法約束語言的排名**：當約束更強（合法物件 = 某個自動機/文法接受的語言），就進入 Goldberg–Sipser 一系「ranking regular / context-free languages」的主題。§9.3 的難度光譜正沿著這條線往上爬。
- **內容定址與確定性生成**：從 Git/IPFS 的「內容即位址」，到 demoscene／程序生成（procedural generation）用「種子 → 確定性世界」——本技術把「種子」換成「**內容本身的編號**」，於是種子不再指向內容，種子**就是**內容。

換句話說：**rank/unrank（給編號 ⇄ 給物件）是引擎，內容定址（編號即網址）是傳動，確定性散佈（編號 → 座標）是把它變成可飛行空間的車輪。** 三者單獨都不新；合起來對準「組合內容」這個目標，就成了一台新車。

---

## 2. 全景：四個構件與一句話原理

> **一句話原理**：把內容空間 `S` 編號成整數區間 `[0, |S|)`，用可逆雜湊把每個編號釘在三維空間的固定一點，再把編號寫進網址——於是「飛行 = 瀏覽編號空間」「網址 = 內容」「無限 = 不儲存」。

```
                 ┌─────────────────────────────────────────────┐
   URL ?p=<大整數>│  i ∈ [0, |S|)        ← 內容定址 / 可分享        │
                 └───────────────┬─────────────────────────────┘
                                 │  unrank
                                 ▼
        ┌────────────────────────────────────────────┐
        │  雙射枚舉（兩套並存）                            │
        │  ①自由數系：URL 的 i ⇄ object（變長自由詩）      │
        │  ②受約束子集 S_valid：位置→只逛「合格律」詩之引擎  │
        └───────────────┬───────────────┬──────────────┘
            render │                     │ index (Vi/rank)
                   ▼                     ▼
            ┌──────────────┐     ┌────────────────────────┐
            │ 構件① 內容    │     │ 構件③ 座標 ⇄ 索引          │
            │ 即索引(數系)  │     │ pos = scatter(i)         │
            │ object↔digits│     │ i   = spatialHash(pos)   │
            └──────────────┘     └───────────┬────────────┘
                                             ▼
                                    3D 星雲渲染（飛行/環視）
```

> **兩套雙射並存（重要釐清）**：原作的**可分享 URL（`?p=`）攜帶的是構件①的「自由形式」編號**（變長雙射數系，over Σ\*），載入時被解碼成**自由詩**。構件②的「受約束子集」雙射（§4）在原作裡是另一個用途——**讓使用者只在「合格律」的詩之間飛**（由空間位置經 `locate` 取一個合法編號、再用受約束 `unrank` 解出一首必定合律的詩），以及計算顯示用的 `lushiIndex` 詮釋資料。**URL 並未攜帶 §4 的受約束 rank。** 重建時你可以**選擇**讓 URL 改攜受約束 rank（見 §6 註）——那是相對原作的乾淨改良，但要先知道原作不是這樣做的。

四構件彼此正交，可分別替換：換**數系/約束**就換了「什麼是一首詩」；換**散佈雜湊**就換了空間佈局；換**渲染**就換了呈現媒介；**URL 層**幾乎不變。下面逐件展開。

---

## 3. 構件①：內容即索引——雙射數系與混合基數枚舉

### 3.1 自由枚舉（uniform 混合基數）

設字表（lexicon）是一個有序有限集合 `Σ`，`N = |Σ|`，每個字元有唯一序號 `0 … N−1`。一首「定長」詩就是長度 `L` 的序號串 `c = (c_0, …, c_{L−1})`，`c_k ∈ [0, N)`。

- **反排名 unrank**（整數 → 物件）：把整數 `i ∈ [0, N^L)` 做 `L` 位定基數 `N` 展開：
  ```
  for k = L-1 downto 0:  c_k = i mod N;  i = i div N
  ```
- **排名 rank**（物件 → 整數）：`i = (((c_0)·N + c_1)·N + … )·N + c_{L-1}`。

這就是把「一首詩」看成一個 `N` 進位的 `L` 位數。空間大小 `|S| = N^L`。以 `N≈2500`（常用字級）為例：

| 形式 | 行×字 | L | 空間 `N^L` 量級 |
|---|---|---|---|
| 五絕 | 4×5 | 20 | ~10^68 |
| 七絕 | 4×7 | 28 | ~10^95 |
| 五律 | 8×5 | 40 | ~10^136 |
| 七律 | 8×7 | 56 | ~10^190 |

可觀測宇宙的原子數約 `10^80`。**七律的編號用盡了，宇宙的原子都不夠當紙。** 但我們一張紙都不用——詩不被儲存，只被「算」。

### 3.2 雙射數系（bijective base：解決變長與前導零歧義）

定長很乾淨，但若要枚舉**變長**內容（自由詩、含換行、空白），普通進位制會出問題：`0`、`00`、`000` 在普通 `N` 進位下都對應同一個值，於是「字串 ↔ 整數」不再是雙射（前導零歧義、空串無法唯一編碼）。

解法是**雙射數系（bijective numeration）**：基數 `b`，但每位的數字取值是 `1 … b`（而不是 `0 … b−1`）。此時非負整數與「有限字串」之間是嚴格雙射：

- **rank**：`i = (((d_0)·b + d_1)·b + …)·b + d_{m-1}`，其中 `d_k ∈ {1,…,b}`。
- **unrank**：
  ```
  digits = []
  while i > 0:  i = i - 1;  digits.unshift(i mod b);  i = i div b   // 得到 0…b-1，外層再 +1 對映回 1…b
  ```

實作上，把「字元序號 `0…N−1`」與一個「換行/分隔 token」一起塞進基數 `b = N+1` 的雙射數系（每個符號映到數字 `符號序號+1 ∈ {1,…,N+1}`），就得到一個**能唯一編碼任意長度、任意分行的自由詩**的雙射整數。網址裡那串近百位數，正是這種「自由形式」的編號。

> **要點**：`定長 → 普通混合基數`，`變長 → 雙射數系`。兩者都給你 `整數 ↔ 物件` 的雙射，差別只在邊界處理。

### 3.3 字表：把符號變成可索引的有序集

數系只認「序號」，不認「字」。所以需要一張**字表** `Σ`：一個固定順序的符號陣列，序號就是它在陣列裡的位置。字表是整個系統唯一需要「決定一次」的資料；它一旦固定，所有編號的意義就固定了。**字表是配置，不是內容**——換一張字表（換語言、換符號集），整座宇宙就換了內容，但程式碼一行不動。

> 在 clean-room 重建裡，**字表必須自己重建**（用你自己選的字集與排序），不能沿用對方的——因為字表是它的具體資料表達（受保護），而「用一張有序字表當基底」這個方法不受保護。

### 3.4 一個最小的數系往返範例

把抽象落到地面。設字表只有四個字 `Σ = [天, 地, 玄, 黃]`，`N = 4`，序號 `天=0, 地=1, 玄=2, 黃=3`。

- **定長（L=2，普通混合基數）**：編號 `i = 11`。
  ```
  c_1 = 11 mod 4 = 3 → 黃 ;  i = 11 div 4 = 2
  c_0 =  2 mod 4 = 2 → 玄
  ```
  得「玄黃」。反向：`rank(玄黃) = 2·4 + 3 = 11`。往返一致。空間大小 `4^2 = 16`，編號 `0…15` 正好對應十六首「兩字詩」。
- **變長（雙射數系，基數 `b = N = 4`，數字取 `1…4`；字元序號 `s` 對映數字 `s+1`）**：要能唯一編碼「空」「一字」「兩字」……不混淆。把整數 `7` 反排名：
  ```
  i=7: i-1=6;  6 mod 4 = 2 → 數字 2+1 = 3（末位）;  i = 6 div 4 = 1
  i=1: i-1=0;  0 mod 4 = 0 → 數字 0+1 = 1（首位）;  i = 0 → 停
  數字串 = [1, 3]  →  字元序號 [0, 2]  →  「天玄」
  ```
  反向驗證：`rank(天玄)`：序號 `[0,2]` → 數字 `[1,3]` → `1·4 + 3 = 7`。**往返一致**。而 `i=0` 唯一對應「空串」。普通進位制下 `0/00/000` 撞在一起的歧義，在這裡消失——這正是「自由形式」必須用雙射數系的原因。

> 兩種數系的差別只在邊界（是否需要編碼「長度本身」）。核心永遠是同一句話：**詩就是一個數，數就是一首詩。**

---

## 4. 構件②：受約束子空間的排名/反排名（本技術的皇冠）

§3 枚舉的是「所有字元組合」。但若你要的是**格律詩**——必須合平仄、必須押韻——那麼合法物件只佔 `N^L` 裡微不足道的一小塊。難點是：**如何對這個「受約束子集」`S_valid ⊂ Σ^L` 仍然建立 `整數 ↔ 物件` 的雙射，且不枚舉、不儲存？**

這就是排名/反排名的真正用武之地，也是這個技術從「玩具」變「真功夫」的地方。

### 4.1 約束的形狀

把格律詩的約束抽象成三層結構（這個抽象正是可推廣的關鍵）：

1. **模板集 Variants**：有限個「合法骨架」。律詩只有少數幾個標準平仄式（平起/仄起 × 首句入韻與否）。記為 `V = {v_1, …, v_m}`。
2. **每槽有限域 Domain(slot)**：在一個給定模板下，第 `k` 個位置的可選字元被約束在某個子集：
   - 該位要求「平聲」→ 可選字 = `Ping`（平聲字集）；
   - 該位要求「仄聲」→ 可選字 = `Ze`（仄聲字集）；
   - 該位是「韻腳」→ 可選字 = 某個**韻部** `g` 的成員集。
3. **跨槽等價耦合 Coupling**：所有韻腳位置必須屬於**同一個**韻部 `g`。這是唯一的非局部約束——它把若干槽「綁在一起」。

於是合法空間是一個**不交併**：
```
S_valid  =  ⊔_{v ∈ V}  ⊔_{g ∈ Rhymes}  Slots(v, g)
Slots(v, g)  =  ∏_{k}  Domain(k; v, g)
```
在模板 `v`、韻部 `g` 下，設平聲自由位 `pf` 個、仄聲位 `z` 個、韻腳位 `rh` 個，則
```
|Slots(v, g)|  =  |Ping|^{pf}  ·  |Ze|^{z}  ·  |g|^{rh}
```

### 4.2 基數（cardinality）

合法詩總數可**閉式**算出，不需枚舉：
```
|S_valid|  =  Σ_{v ∈ V}  ( |Ping|^{pf_v} · |Ze|^{z_v} )  ·  ( Σ_{g ∈ Rhymes} |g|^{rh_v} )
```
注意韻腳耦合讓「選哪個韻部」變成一個**加權的類別選擇**（每個韻部貢獻 `|g|^{rh}` 條），不是簡單乘法——這正是非局部約束的代價，也是它仍可閉式計數的優雅之處。

### 4.3 反排名 unrank（整數 → 合法詩）

給定 `i ∈ [0, |S_valid|)`：

```
1. 選模板 v：依序減去每個模板的容量 count(v)=(|Ping|^pf·|Ze|^z)·Σ_g|g|^rh，
   直到 i < count(v)。剩下的 i 就是「在 v 內的局部編號」。
2. 選韻部 g：把 v 內容量再拆成「韻部區塊」。每個 g 的區塊大小
   block(g) = |Ping|^pf · |Ze|^z · |g|^rh。依序減去 block(g) 定出 g。
3. 槽內混合基數展開：剩餘編號對「各位置的有限域大小」做一次混合基數
   unrank —— 平聲位用基數 |Ping|、仄聲位用 |Ze|、韻腳位用 |g| ——
   得到每個位置在其域內的「第幾個」，再查表還原成字。
```
全程只有大整數的除法與取模，**O(L) 次大數運算**，不觸碰 `|S_valid|` 這個天文數字本身。

### 4.4 排名 rank（合法詩 → 整數）與驗證

反向：給一首詩 `c`，
```
1. 驗證 + 認模板：找出 c 符合哪個模板 v 的平仄式；若都不符 → 不合法（回 null）。
2. 認韻部：取所有韻腳位的字，檢查是否同屬一個韻部 g；不一致 → 不合法。
3. 前綴和 + 混合基數 rank：i = (前面所有模板的總容量)
                              + (本模板內 g 之前所有韻部的區塊和)
                              + (槽內混合基數 rank)。
```
`rank` 與 `unrank` 互逆。**「驗證」與「排名」是同一個函數的兩面**：能排名 ⟺ 合法。

### 4.5 雙射的不變式（為什麼成立）

- **前提（韻部劃分，務必明列）**：假設所有韻部**兩兩不相交**——每個可入韻的字**恰屬一個韻部**（真實平水韻即如此）。這是 `⊔_g` 與 `Σ_g |g|^rh` 計數成立的**必要前提**：若兩個韻部共用一字，同一首詩會在兩個 `(v,g)` 格各被生成一次，`Σ_g|g|^rh` 就**重複計數**、雙射破裂（一詩兩號）。（驗算：取重疊群 `g0={p0,p1}`、`g1={p1,p2}` 與 2 個韻腳位，閉式給 `2²+2²=8` 但實際只有 7 個相異韻腳組——`(p1,p1)` 被算了兩次。）
- **不交性**：不同模板的平仄式互斥（平仄序列唯一決定模板，或都不屬於）；在上述劃分前提下，同模板的不同韻部也互斥（韻腳的韻部唯一）。故 `⊔` 是真不交併，編號不重不漏。若域允許重疊，則須讓編號**攜帶所屬類別（tag）**把併集人工不交化，rank/unrank 才仍良定義。
- **完備性**：`Slots(v,g)` 是笛卡兒積，混合基數對笛卡兒積是標準雙射。
- **閉合性**：`unrank(i)` 產出的詩，其平仄與韻必然滿足約束（因為域本身就是約束過的），所以 `rank(unrank(i)) = i`、`unrank(rank(c)) = c`。

> **這一節是可被推廣的最值錢的東西**：只要你的「合法物件」能寫成
> `⊔_模板 ⊔_類別 ∏_槽 域`
> 的形狀（模板有限、每槽有限域、跨槽用「同類別」耦合），你就能對它做零枚舉的 `整數 ↔ 物件` 雙射。格律詩只是這個形狀的一個實例。

### 4.6 一個經實際運算驗證的受約束範例（Knuth 閘門）

抽象容易自我感覺良好，所以本文**把它寫成程式跑過**——依 BUG學「修前 fail、修後 pass」的鐵律，論文裡的數字必須是可執行地證明的，不是嘴上說的。

設一個玩具受約束空間（刻意小到能暴力枚舉對帳）：

- 平聲字 `Ping = {p0,p1,p2}`（`|Ping|=3`）、仄聲字 `Ze = {z0,z1}`（`|Ze|=2`）；
- 韻部把平聲字切成兩組：`g0={p0,p1}`（大小 2）、`g1={p2}`（大小 1）；
- 長度 `L=4`，兩個模板（位置型別：`pf`=平聲自由、`ze`=仄聲、`rh`=韻腳）：
  - `v0 = [pf, rh, ze, rh]`，`v1 = [ze, rh, pf, rh]`（皆 `pf=1, z=1, rh=2`）。

依 §4.2 閉式基數：
```
count(v) = |Ping|^pf · |Ze|^z · Σ_g |g|^rh = 3^1 · 2^1 · (2^2 + 1^2) = 6 · 5 = 30
|S_valid| = count(v0) + count(v1) = 30 + 30 = 60
```

實作 §4.3 的 `unrank` 與 §4.4 的 `rank`，跑兩道閘門：

| 閘門 | 結果 |
|---|---|
| 閉式基數 == 暴力枚舉計數 | `60 == 60` ✓ |
| 對所有 `i ∈ [0,60)`：`rank(unrank(i)) == i` | 全通過 ✓ |
| `unrank` 的值域恰好覆蓋合法集（不重不漏） | `|image| = 60`，與暴力集相等 ✓ |

也順手驗了真實參數的空間量級（`N≈2500`）：五絕 `2500^20 ≈ 10^68`、七絕 `≈ 10^95`、五律 `≈ 10^136`、七律 `≈ 10^190`——與 §3.1 的表一致。

> **這一節同時是內容、也是驗證。** 它證明 §4 的雙射不是紙上談兵：給編號取詩、給詩取編號，在受約束子空間上嚴格互逆、不重不漏。重建時的第一個里程碑（§10.4 的 M2）就是把這道閘門在你自己的程式裡重現。

---

## 5. 構件③：座標 ↔ 索引——確定性可逆綁定

有了 `整數 ↔ 物件`，還差「整數 ↔ 三維位置」，才能把編號空間變成可飛行的星雲。

### 5.1 索引 → 位置（scatter）

把編號 `i` 用一個**確定性雜湊**打散到三維空間：
```
pos(i) = ( f(i, 1), f(i, 2), f(i, 3) ) · R
其中 f(i, axis) = hash64(i ⊕ axis) 映到 [-1, 1)，R = 雲半徑
```
`hash64` 用 splitmix64 風格的位元雪崩（乘以奇常數、右移異或；常見常數如 `⌊2^64/φ⌋`）。確定性保證：**同一個 `i` 永遠落在同一點**，所以位置不需儲存。

### 5.2 位置 → 索引（spatial hash）

反過來，當使用者在空間中「飛到某處／點選某處」，要由位置取回該處的詩：
```
1. 量化座標：q = round(pos · 量化粒度)            // 把連續空間切成格
2. 空間雜湊：h = (q.x·P1) ⊕ (q.y·P2) ⊕ (q.z·P3)   // P1,P2,P3 為大質數
3. 串流擴展到足夠位元，取模合法空間大小：i = expand(h) mod |S_valid|
```
其中 `P1,P2,P3` 是經典的**空間雜湊三質數**（Teschner 等人提出的 `73856093 / 19349663 / 83492791` 是這領域的事實標準）。`expand` 用 splitmix64 連續產生 64-bit 區塊，拼到比 `|S_valid|` 的位元數還多十幾位，再取模——確保落在合法區間且分布均勻。

> 注意：`scatter`（索引→位置）與 `spatialHash`（位置→索引）**不是嚴格互逆**，而是「一個負責把編號撒進空間、一個負責把空間格子映回編號」。系統靠的不是嚴格可逆，而是**兩個方向各自確定性**：同編號恆同位置、同格子恆同編號。導航體驗只需要「同一處永遠是同一首詩」，這個性質就夠了。

### 5.3 確定性 = 零儲存的前提

整個構件③沒有任何狀態。它是純函數。**確定性雜湊是「不儲存也能有穩定世界」的全部祕密**：世界不是被存下來的，是每次被同一個函數重新算出來的，而純函數每次算的結果一樣，於是看起來像一個固定存在的世界。

---

## 6. 構件④：URL 即狀態——內容定址與無後端

把當前選中物件的編號寫進網址查詢字串（如 `?p=<大整數>`），並用 `history.replaceState` 在使用者導航時無刷新同步。載入時讀網址、`unrank` 回物件、`scatter` 到位置、把相機飛過去。

> **原作攜帶的是構件①的「自由形式」編號**（§3.2 的 `babelIndex`，over Σ\*），載入時解碼成自由詩；§4 的受約束 rank（`lushiIndex`）只作**顯示用、不進 URL**（見 §2 釐清）。**重建建議**：若要 URL 直接定址到「一首合格律的詩」，可改用 §4 的受約束 rank 當 `?p=` 內容——這是相對原作的乾淨改良，代價是 URL 語意從「自由詩座標」變成「合律詩編號」，兩種定址不可混用（同一個數字在兩種解碼下是不同的詩）。

由此**同時**得到四個性質（下一節證明）：

- **零後端**：解析網址只需純前端計算，伺服器只送一份靜態檔。
- **可分享**：一個 URL 完整重現一首詩與它的位置；複製貼上即傳遞內容本身。
- **天然防爬**：HTML 是空殼，內容是前端從編號算的；樸素抓取（含多數「scrape→clone」工具）只得到殼。
- **無限**：URL 能放下的數字位數幾乎無上限，於是可定址的內容近乎無限。

> 可選的第二載體：把同一編號也放進 `#fragment`。`#` 之後不送伺服器、純客戶端路由，適合「分享時也帶狀態、但不污染伺服器日誌」。`?` 與 `#` 可並存，互為備援。

---

## 7. 系統不變式與性質（為什麼成立）

把四構件合起來，下列性質可由前文直接推出：

| 性質 | 由何保證 |
|---|---|
| **零儲存（生成層）** | 生成的內容 = `unrank(i)`、位置 = `scatter(i)`，皆純函數、無資料庫。（少數策展真作另從靜態 JSON 載入，不屬生成層。） |
| **近乎無限** | 可定址內容量 = `|S_valid|`，隨 `L` 指數成長（七律 ~10^190）。 |
| **確定性／可重現** | 所有雜湊為純函數；同 `i`／同位置恆得同結果。 |
| **天然防爬** | 內容不在初始 HTML；需執行前端解碼才現形。 |
| **可分享** | URL ⊇ 編號（原作為 §3.2 自由形式編號），單一整數重建內容＋位置。 |
| **合法性內建（受約束路徑）** | 走 §4 受約束 `unrank`（位置→只逛合律詩）時，域已是約束過的子集，產出必合格律；走 URL 自由編號路徑則解碼為自由詩。 |

**一個誠實的反面**：防爬不是「不可破」。若爬蟲願意**執行 JavaScript**（如以 headless 瀏覽器渲染——某些 `scrape-website` 服務的進階模式就會），它仍能抓到算出來的 DOM。真正穩固的不是「防住所有爬蟲」，而是**機制本身**：內容封進不透明編號、無後端可打、單一 URL 自包含——這讓「複製這個站」退化成「複製一個空殼 + 一個你看不懂的數字」。

---

## 8. 與生成範式的接合（從尋找到生成）

`paradigms/` 裡反覆出現的主軸——「**從尋找到生成**」「生成路徑優越性」——在這個技術裡有一個乾淨的具體化：

- **尋找式系統**：內容先被生產、儲存、建索引，使用者透過查詢去「找」它。成本在儲存與檢索，上限在「已被存進去的東西」。
- **生成式系統（本技術）**：內容不被儲存；給定座標，**當場生成**。上限不是「存了多少」，而是「編號空間有多大」——而編號空間是 `N^L`，免費的指數。

詩雲做不到《詩雲》小說裡那步「從垃圾裡認出好詩」，因為**那一步是價值判斷，不是枚舉**。但它把前一半做到了極致：**整個生成空間被完整定址、可導航、可分享、零成本。** 這恰好印證範式的論點——當「生成」便宜到近乎免費，瓶頸就從「製造/儲存內容」整個轉移到「在無限生成物裡施加意義與選擇」。**這個瓶頸轉移本身，就是『其他潛力發展』的入口。**

---

## 9. 通用化：「X 之雲」抽象介面

詩只是 `X` 的一個取值。把技術抽乾淨，得到一個介面：**任何能實作下列介面的 `X`，都能變成一座可飛行、URL 即內容、零儲存、近乎無限的「X 之雲」。**

### 9.1 介面定義

```
interface EnumerableSpace<X> {
  cardinality(): BigInt                 // |S_valid|，閉式可算（不枚舉）
  unrank(i: BigInt): X                  // 整數 → 物件（必落在合法子集）
  rank(x: X): BigInt | null             // 物件 → 整數（順帶驗證合法性）
  render(x: X): Visual                  // 物件 → 可呈現形態
}
interface Embedding {
  scatter(i: BigInt): Vec3              // 索引 → 三維位置（確定性）
  locate(p: Vec3): BigInt              // 位置 → 索引（空間雜湊 mod |S|）
}
// URL 層、相機/渲染層對所有 X 通用，不必重寫。
```

只要補上 `EnumerableSpace<X>` 與一張「字表/原子集」，其餘（座標綁定、URL、3D 導航）幾乎是現成的。

### 9.2 把 X 換成什麼（實例表）

| X | 原子集 Σ | 約束（模板×域×耦合） | 難度 |
|---|---|---|---|
| 古典詩（本例） | 字（含平仄、韻部） | 平仄模板 × 平/仄/韻域 × 同韻耦合 | ★★★ |
| 旋律 / 和弦進行 | 音符 / 和弦 | 調式音階 × 級數域 × 終止式耦合 | ★★★ |
| 合法棋局片段 | 棋步 | 規則合法步 × 局面域 × 將軍/連續性耦合 | ★★★★ |
| 形式證明樹 | 推理規則 | 型別/前提模板 × 可用規則域 × 結論一致耦合 | ★★★★★ |
| 分子式 | 原子/鍵 | 價數模板 × 成鍵域 × 價數守恆耦合 | ★★★★ |
| Shader / 程序紋理 | 運算節點 | 型別模板 × 節點域 × 輸入輸出耦合 | ★★★ |
| SVG 紋樣 / 圖騰 | 路徑基元 | 對稱模板 × 基元域 × 閉合/對稱耦合 | ★★ |
| 迷宮 | 牆/通道 | 連通模板 × 格域 × 單一連通耦合 | ★★ |

模式都一樣：**找到 `X` 的「合法骨架（模板）× 每槽有限域 × 跨槽等價耦合」結構，§4 的雙射就能套上去。**

### 9.3 難度光譜

- **容易**（★–★★）：約束是**局部**的（每槽獨立或只有簡單對稱）。混合基數直接做，幾乎是 §3。
- **中等**（★★★）：約束是「模板 + 每槽域 + 少量等價耦合」（詩、旋律、紋樣）。正是 §4 的形狀，可閉式計數。
- **困難**（★★★★+）：約束是**全域且互相牽連**的（棋局合法性、證明的全域一致性）。此時 `S_valid` 不再是「不交併的笛卡兒積」，閉式計數可能不存在——退路是**對更寬鬆的超集枚舉、生成後驗證、用拒絕採樣或更強的組合排名（如對自動機/文法語言的排名）**。這條線就通往「**對受文法約束的語言做排名**」這個更深的計算組合學主題，也是 `X` 越往「需要全域語義一致」走、技術越硬的地方。

> 「其他潛力發展」多半藏在 ★★★★ 那欄：當 `X` 是**有語義、有全域一致性**的東西（證明、程式、可運行的設計），這座雲就從「美學玩具」變成「可被導航的解空間」——而導航一個解空間，距離「在解空間裡搜尋/生成有用解」只剩一步。

---

## 10. 重建藍圖（clean-room，MSSP / DMS-first）

依房規：**先畫、先定憲法、先設計可觀測，再寫碼**。以下是可照著建的最小骨架（規模屬 Small：扁平優先、禁止過早分層）。

### 10.1 FMS（系統憲法・純元資料，不含可執行碼）

- **敘事（為什麼＋取捨）**：要的是「可導航的生成宇宙」。取捨：**選擇「每顆星都是真物件、由座標生成」而非「貼圖/預存」**——換來無限與防爬，代價是放棄「整體的人為策展」（多數點無意義）。
- **索引（模組＋依賴）**：見 §10.2。
- **註釋（決策＋限制）**：字表必須自建（法律＋語義）；雜湊必須確定性（零儲存的前提）；URL 編號是唯一真值來源（single source of truth）。

### 10.2 模組分解（SMS 穩定核心 / TMS 可插拔子集）

```
SMS（穩定核心・介面契約，最小核心原則）
  numeral/        混合基數 + 雙射數系（rank/unrank 基礎）   ← 純函數、可單測
  space/          EnumerableSpace 介面 + 受約束枚舉骨架       ← §4 的雙射
  embed/          scatter / locate（確定性雜湊、空間雜湊）    ← §5
  urlstate/       rank↔URL、replaceState 同步                ← §6
TMS（可插拔・自包含・可替換；移除測試：拿掉它核心仍可編譯）
  lexicon.x/      具體字表/原子集（換語言、換 X 就換這個）
  constraint.x/   具體約束（格律/調式/規則…）實作 EnumerableSpace
  render.x/       具體呈現（3D 星雲 / 文字卡 / 樂譜…）
DMS（診斷層・要設計進去，不是事後補）
  - rank(unrank(i)) === i 的往返自檢（任意抽樣 i）
  - locate(scatter(i)) 的穩定性檢查（同點恆同詩）
  - |S_valid| 與「實際可達編號上界」一致性檢查
  - URL 往返：parse(stringify(state)) === state
```

**移除測試判準**：`render.x`、`lexicon.x`、`constraint.x` 拿掉後 `numeral/`、`embed/`、`urlstate/` 仍能編譯與單測 → 它們是 TMS；反之核心三件是 SMS。

### 10.3 資料流圖（≤9 元素，A4 放得下）

```
 [URL ?p=i] ──parse──► [BigInt i] ──unrank──► [object x] ──render──► [3D 星 / 詩卡]
      ▲                                   │
      │ stringify(rank(x))                │ scatter(i)
      │                                   ▼
 [history.replaceState] ◄──select──── [camera flyTo pos] ◄──locate──── [使用者點選空間]
```

> **兩條路徑、兩個位置來源（重建勿混）**：**上排**（URL ⇄ 物件）用構件①的自由 `rank/unrank`，此路徑的位置 = `scatter(i)`。**下排**（點選空間「捕詩」）用 `locate` → §4 受約束 `unrank` 取一首合律詩，而**這首詩的顯示位置 = 使用者所點的那個三維點本身**（不是 `scatter(其編號)`）。亦即：已知編號才用 `scatter` 定位；當場捕撈則「位置先於編號」。別假設「捕到的詩」會落在 `scatter(它的編號)`——那會讓星星從你點的地方跳走（呼應 §5.2、§13.3）。

### 10.4 最小可重建核心（MVP）與 Knuth 閘門測試

依 BUG學：**每個核心函數先有「修前 fail、修後 pass」的可執行往返測試**，再談完成。

```
MVP 里程碑（每步都有閘門測試才算過）
  M1 numeral：unrank/rank 往返（定長 + 雙射數系變長）對隨機 i 全通過。
  M2 space ：給一個玩具約束（如「4 槽、2 模板、3 韻部」）實作 EnumerableSpace，
            cardinality 與「暴力枚舉計數」一致；rank(unrank(i))===i 全通過。
  M3 embed ：scatter 確定性、locate∘scatter 落在合法區間；同格子恆同編號。
  M4 url   ：parse∘stringify 往返；replaceState 不刷新。
  M5 render：先文字版（unrank→印出物件），確認端到端；再接 3D（可借用你現成的星空渲染）。
```

### 10.5 與星空渲染的接合

§5 的 `scatter(i)` 產出的就是一團三維點——這正是你**星空 v2** 已經會的東西（座標雲 + r3f/three instancing + 站在中心飛行）。把星空的「隨機散佈」換成「`scatter(編號)` 散佈」，把「點擊辨星卡」換成「`locate(位置) → unrank → 詩卡」，**你的星空就直接升級成 X 之雲的渲染層**。換言之 `render.x` 你已經寫過大半。

---

## 11. 風險、邊界與誠實對照

1. **訊號淹沒（最根本的限制）**：`|S_valid|` 裡絕大多數是「合格律但無意義」的詩。這座雲解決了「定址與導航」，**沒有**解決「找到好的」。這正是《詩雲》小說的困境被誠實地保留下來。任何認真的「其他潛力發展」都必須回答：**在無限合法物裡，如何施加意義/選擇/評分？**（curated 入口、評分函數、人在迴路、或把「選擇」本身也建模成可導航的維度。）
2. **可發現性**：URL 是內容，但「好 URL」本身不可被瀏覽地發現——你要嘛從某處飛到它、要嘛被分享。系統需要「策展入口 / 種子座標 / 評分熱區」來讓人有起點。
3. **計數可行性的天花板**：§9.3 ★★★★ 那類（全域語義一致的 X）可能沒有閉式 `cardinality`，雙射退化為「超集枚舉 + 驗證」。要事先誠實標注哪些 X 落在可閉式計數的那一側。
4. **技術 vs 財產（界線，接續前面那題）**：
   - **可借鑒（拿走就好）**：雙射數系、受約束子空間的 rank/unrank、空間雜湊綁座標、URL 即內容——這些是**方法/演算法**，不受著作權保護。
   - **不可照搬**：對方的**原始碼、字表資料、具體常數選擇之表達、品牌與視覺**。重建時這些**全部自建**。
   - 一句話：**要的是招，不是他的家具。** 招我已經拆給你了；家具我們自己打。

---

## 12. 意義工程：在無限中施加選擇（「其他潛力」的技術入口）

§11.1 點出了根本限制：詩雲把「定址與導航」做到極致，卻**完全沒碰**「從無限合法物裡認出有價值的那些」。這不是缺陷，是分工——它做的是**基礎建設**。而你說的「其他潛力發展」，幾乎全部落在它之上的這一層：**意義工程（meaning engineering）——在一個已被完整定址的無限空間裡施加價值、選擇與用途。** 下面是四條可走的路，每一條都以「可導航的雲」為地基。

### 12.1 把「選擇」變成另一個可導航維度

均勻散佈的雲沒有地形——每顆星一樣亮，眼睛無處落。引入一個**評分函數** `score: X → ℝ`（語意連貫度、美學、或「有用性」），就把均勻雲變成**有地形的景觀（fitness landscape）**：把分數映到亮度／大小／顏色／聚集度，**好的東西會自己發光**，導航就從「亂飛」變成「沿著梯度爬山」。

代價：`10^190` 個點不可能全評分。所以只能**局部**——只對相機鄰域 `scatter` 出來的點即時評分、即時著色。雲不是被預先點亮的，是**隨你飛到哪、哪裡才亮起來**。這恰好與構件③的「確定性、按需生成」同構：連「意義」都按需算。

### 12.2 種子 + 局部搜尋（把生成接回搜尋）

給若干**策展種子座標**當入口（對應詩雲的 `?a=` 詩人模式——已知的好起點）。從種子出發，在 `unrank` 的**鄰域**做局部最佳化（梯度、演化、MCTS），找更好的鄰居。

這正是範式「從尋找到生成」之後的下一拍：**不是生成 vs 尋找二選一，而是「廉價生成 + 廉價局部搜尋」聯手**——生成提供無限且零成本的候選地形，局部搜尋在地形上找峰。生成負責「有什麼」，搜尋負責「往哪走」。

### 12.3 把約束做得更強 = 把垃圾擋在門外

§4 的約束越強，`S_valid` 越小、**有意義的密度越高**。把約束從「合語法」推向「合語義」，等於把更多垃圾**排除在可定址空間之外**——它們連編號都拿不到。

這條路的盡頭極具威力：當 `X = 可驗證的物件`（形式證明、可編譯且通過測試的程式、滿足規格的設計），約束 = 「能通過驗證器」，則 `unrank` 的**每一點都是一個合法解**。此時這座雲不再是美學玩具，而是**解空間的可導航地圖**——而「導航一個全是合法解的空間」距離「在解空間裡找有用解」只剩最後一步。（代價見 §9.3：約束強到這種程度，閉式計數通常失效，雙射退化為「對驗證器接受的語言做排名」這個更硬的問題。這也正是 ★★★★ 那一欄、和你 P vs NP 那套思路真正接上的地方。）

### 12.4 人在迴路 / 集體標註

把人的行為（收藏、分享、停留）當成對無限空間的**稀疏標註**，反過來訓練 `score`，於是雲會**長出**被人關注的熱區。策展從「一次性挑選」變成「持續演化的點亮」。

這直接接上你 `paradigms` 裡的「集體智能相變」「同步發現的微觀差異」：**無限生成空間 + 集體標註 = 一個可被集體認知逐步點亮的宇宙。** 一個人點不亮 `10^190`，但一群人持續地飛、停、收藏，會在無限裡**演化出有結構的星座**。

### 12.5 定位

| 層 | 做什麼 | 詩雲 | 「其他潛力」 |
|---|---|---|---|
| 基礎建設 | 定址、導航、分享、零儲存 | ✅ 已做到 | 當地基 |
| 意義工程 | 在已定址的無限裡施加價值/選擇/用途 | ❌ 未碰 | **幾乎全在這** |

> 詩雲是一座**蓋好的無限圖書館**——書架完備、座標清晰、任何一本都能瞬間翻到。它沒做的是「告訴你哪本值得讀」。而那，恰恰是把這座圖書館從奇觀變成**工具**的全部關鍵。

---

## 13. 重建陷阱（務必避開）

照房規傳統，把重建時真正會踩的坑先標出來。這些多半是「不踩過不知道」的，列在前面省三輪重啟。

1. **變長內容用普通進位制 → 前導零歧義（最致命）**。`0`、`00`、`000` 在普通 `N` 進位下同值，於是「字串 ↔ 整數」不再是雙射，空串無法唯一編碼、不同長度會撞號。**變長一律用雙射數系（數字 `1…b`）**。定長才可以用普通混合基數。先想清楚你的內容是定長還是變長，再選數系。

2. **用 `Number` 而非 `BigInt` → 在 `2^53` 悄悄爆掉**。編號動輒近百位，遠超 IEEE-754 雙精度的安全整數上限（`2^53−1`）。**所有 rank/unrank/雜湊的整數運算必須全程 `BigInt`**。一個不小心混入的 `Number` 轉換，會在某個臨界值之後產出「看起來對、其實錯」的編號——而且很難察覺，因為小編號都正常。這正是 BUG學「注入↔顯現時間距離 ∝ 修復成本」的典型：錯在編碼、爆在某個大數，中間隔很遠。

3. **以為 `locate(scatter(i)) == i`，或以為「捕到的詩」住在 `scatter(其編號)`**。§5.3 已說：散佈與空間雜湊**不是嚴格互逆**。更具體地，有**兩條產生位置的路徑**：(a) 已知編號（如還原分享 URL）→ 位置 = `scatter(i)`；(b) 點虛空當場捕詩 → **位置 = 使用者所點的那個點**，編號由 `locate` 反求。別把兩者混為一談、別假設往返恆等；系統只依賴「同編號恆同位置、同格子恆同編號」這兩個**各自的**確定性。把它當互逆，會在「點選 → 取詩 → 再定位」處讓星星跳走。

4. **字表是凍結的協定，不是可調的參數**。字表的內容與**順序**一旦對外發布，就**不能再改**——改一個字的序號，所有舊 URL 指向的詩全部變了。字表必須像資料庫 schema 一樣版本化、append-only（要擴充只能在尾端加字，不能重排）。**把「字表凍結」寫進 FMS 的限制欄。**

5. **確定性雜湊的跨平台一致性**。`scatter`/`locate` 要在不同瀏覽器、不同裝置、甚至不同語言的後端重算出**同一個結果**，否則「分享的 URL 在你那裡是另一首詩」。務必：全部運算 `mod 2^64`（明確 wrap）、用同一組常數、避免任何浮點參與雜湊主路徑（浮點的捨入跨平台不保證一致）。座標量化那一步尤其要定死粒度與捨入規則。

6. **約束強到沒有閉式 `cardinality` 還硬算**。§9.3 ★★★★ 那類（全域語義一致的 `X`）的合法集不是「不交併的笛卡兒積」，`|S_valid|` 可能根本沒有閉式。硬套 §4.2 會算出錯的基數，連帶 `unrank` 的取模範圍全錯。**事先判斷你的 `X` 落在難度光譜哪一格**：可閉式計數的（★★★）才直接套 §4；否則改走「超集枚舉 + 驗證 + 拒絕採樣」或語言排名。

7. **URL 長度上限與分享媒介截斷**。近百位數字還好，但若 `X` 更大（長文、複雜結構），編號可能長到撞上瀏覽器 URL 長度上限或被聊天軟體/QR 截斷。對策：可在編號上加可逆壓縮、或改用較高基數（Base62/Base64url）縮短字面長度——但**壓縮層要與語意層解耦**（壓縮只動表示，不動「編號 ↔ 物件」的雙射）。

8. **`scatter` 分布不均 → 視覺結塊**。若散佈雜湊品質不夠，星會在某些區域堆積、某些區域空洞，破壞「無垠星海」的錯覺。用品質好的位元雪崩（splitmix64 風格），並對三個軸用**不同的鹽**（如 `i ⊕ axis`），避免三軸相關產生對角條紋。這與星空專案「球面取點別用 `random*π`」是同一類陷阱：**取樣分布的細節決定觀感。**

9. **把渲染和枚舉耦死**。常見誘惑是「邊飛邊直接從座標算詩、塞進渲染迴圈」。但 `unrank` + 約束驗證可能不便宜，塞進每幀會掉格。**渲染層只認座標與少量已解出的物件**；解碼放在選取/鄰域預取時做，並快取。保持 §10.2 的 SMS/TMS 邊界——`render.x` 不該知道 `constraint.x` 的內部。

10. **忘了「無限 ≠ 有意義」就對外宣稱**。展示時容易把「能定址 `10^190` 首詩」講成「有 `10^190` 首好詩」。誠實點：絕大多數是合格律的噪音（§11.1）。把這點寫進文案，否則使用者飛兩下發現全是亂句，會覺得被騙——而技術本身明明很誠實。

> 一句話：**雙射要用對數系、整數要用 `BigInt`、字表要凍結、雜湊要跨平台一致、別把「無限」當「有意義」。** 這五條踩過任何一條，都會在很後面才爆。

---

## 14. 結語

這個網頁的「強」，不在它是一個關於詩的作品，而在它**不小心示範了一個通用技術**：當內容能由座標確定性地生成，內容就不必被儲存、不必被尋找、可以被當成空間來飛行、可以被一個整數完整分享。它是「**從尋找到生成**」這條範式線上一個能用滑鼠拖動的具體證據。

原作者把它當「有趣的網頁比賽」。但他手上的，是「**生成式內容宇宙**」的一個可運行原型——而這類宇宙真正的潛力，在他畫的這條線之外：把 `X` 從「詩」換成**有語義、有用、有全域一致性**的東西時，這座可導航的雲就從美學玩具，變成一個**可被飛行的解空間**。

下一步——**現場重建**——就照 §10 的 MSSP 骨架走：先把 `numeral/` 與一個玩具 `constraint/` 的往返閘門測試做出來（M1–M2），其餘接上你現成的星空渲染。招在手上了，剩下的是把它打成你自己的。

> *寫實與寫意是同一顆球的內外兩面；儲存與生成，是同一個空間的兩種看法。它選了生成——於是一張紙都不用，就裝下了比宇宙原子還多的詩。*
