共通規則¶
本頁是所列 namespace 的內容權威;程式參數 只提供導覽。
1. 一致性級別¶
| 級別 | 跨 peer 必須一致 | 變更需 protocol 升版 | 範例 |
|---|---|---|---|
protocol/ |
✅ 共識必須相同 | ✅ | 重力 / 質量上限 / 簽章長度 |
network/ |
⚠️ 分支分類:sync 必須一致;signaling/discovery 為本機策略 |
sync ✅;其餘依 wire 影響 |
rollback wire/admission/voting;連線 timeout |
ui/ |
❌ 純客戶端 | ❌ | 動畫長度 / 預設音量 |
economy-config/ |
✅ 動態治理 | ❌(走 multisig) | 分潤比、新手保護天數 |
所有常數必須 Object.freeze() / as const readonly,禁止 runtime mutation。
19. 型別系統 + 不變式(CI 強制檢查)¶
19.1 Brand 型別(避免單位混淆)¶
@open4wd/system-constants 採 TypeScript Brand types 區分量化單位,編譯期阻擋「把 Mm 當 cm」之類錯誤:
// 版本欄位
type ProtocolVersion = string & { __brand: "ProtocolVersion" }; // e.g. "1.0.0"
type NetworkVersion = string & { __brand: "NetworkVersion" };
type ClientVersion = string & { __brand: "ClientVersion" };
type EconomyConfigEpoch = number & { __brand: "EconomyConfigEpoch" };
// 量化單位
type Mm = number & { __brand: "Mm" }; // 公釐
type Gram = number & { __brand: "Gram" }; // 克
type X1000 = number & { __brand: "X1000" }; // 乘 1000 量化(如 GRAVITY_X1000)
type X100 = number & { __brand: "X100" }; // 乘 100 量化(如 ratingX100)
type MinorUnits = bigint & { __brand: "MinorUnits" }; // 經濟最小單位(1 幣 = 100 minor)
// PeerId / CID / Signature 等識別符
type PeerId = string & { __brand: "PeerId" };
type CID = string & { __brand: "CID" };
type Signature = Uint8Array & { __brand: "Signature" };
建構工具:
const mm = (n: number): Mm => n as Mm;
const grams = (n: number): Gram => n as Gram;
// ...
19.2 常數不變式(pnpm run check:invariants)¶
// 經濟
assert(revShare.currentTierPct + parentTierPct + grandparentTierPct === 100); // pct 整數(economy-config.md §17.3)
// UGC
assert(VEHICLE_TOTAL_MASS_MIN_GRAMS < VEHICLE_TOTAL_MASS_MAX_GRAMS);
// 本機 UGC contribution policy(非共識,但 constants drift 必須 fail-closed)
for (const { trigger, target } of UGC_CACHE_USAGE_POLICIES) {
assert(0 <= target && target < trigger);
assert(trigger <= MAX_CONTRIBUTION_TRIGGER_USAGE_RATIO);
}
assert(MAX_CONTRIBUTION_TRIGGER_USAGE_RATIO < STORAGE_CRITICAL_USAGE_RATIO);
// 網路(三角形不變式)
assert(
ROLLBACK_FRAME_BUFFER_MIN <=
ROLLBACK_FRAME_BUFFER_DEFAULT <=
ROLLBACK_FRAME_BUFFER_MAX,
);
assert(STATE_BUFFER_MAX_FRAMES >= ROLLBACK_FRAME_BUFFER_MAX); // 緩衝容量 ≥ 回滾視窗
// 配對
assert(PLAYERS_PER_RACE_MIN <= PLAYERS_PER_RACE_MAX);
assert(PLAYERS_PER_RACE_MAX <= TRACK_MAX_PLAYERS_HARDCAP);
// 比賽結構(多回合)
assert(
MATCH_ROUND_COUNT_MIN <= MATCH_ROUND_COUNT_DEFAULT &&
MATCH_ROUND_COUNT_DEFAULT <= MATCH_ROUND_COUNT_MAX,
);
// 重力
assert(
physics.gravity_strength_m_s2 >= 1.6 && physics.gravity_strength_m_s2 <= 25,
);
// 物理 body 預算(最壞情況帳,見 protocol.md §2 註)
assert(
8 * 12 +
8 * MAX_WEAPON_DRIVEN_BODIES +
8 * LAUNCH_AMMO_COUNT_MAX +
TRACK_ENTITY_COUNT_MAX <=
MAX_RIGID_BODIES_PER_RACE,
);
// 回合共識錨 bounded proposer/收集窗
assert(CONSENSUS_ANCHOR_FALLBACK_SLOT_MS > 0);
assert(
CONSENSUS_ANCHOR_COLLECTION_TIMEOUT_MS > CONSENSUS_ANCHOR_FALLBACK_SLOT_MS * 4,
);
// 治理 quorum(見 [資料系統.md §12](../資料系統.md))
assert(
signerCount === 1
? quorum === 1
: signerCount >= 3 && quorum === Math.floor((2 * signerCount) / 3) + 1,
);
CI fail → 阻擋 merge。
20. 變更流程¶
| 級別 | 變更方式 |
|---|---|
protocol/ |
spec 改 + const 改 + protocol major bump + 全 client 強制升版 |
network/sync |
spec 改 + const/wire 改 + protocol_version major bump;同房必須完全一致,不協商 |
network/ 其餘 |
依是否影響 wire / 共識分類;signaling/discovery 本機策略可獨立調整 |
ui/ |
純前端改,無 protocol 影響 |
economy-config/ |
不改 spec 預設值;走 multisig propose + OrbitDB 寫入 + epoch +1 |
詳見 版本規範.md。