歷史記錄 · 2026-07-06¶
重大重構里程碑¶
2026-07-06 ─ ⭐圖檔禁字鐵則定案(使用者裁;文字全禁、數字 0–9 與中立符號可;跨 6 檔)¶
決策檔:D-20260706-07
背景:原政策允許圖檔含「通用簡易英文」(前端技術策略 §16 B 類戲劇定格詞 READY/GO!等 SVG 寫死不翻)——使用者判定仍存語系問題 → 定案:出貨圖檔資產禁止內含任何語言文字;數字 0–9 與跨語系中立符號(! ? + × % : →)允許。時點=實作零圖檔(GLB/UI 資產/logo 皆未產出)=零遷移成本。改制:①前端技術策略 §16=鐵則權威——4 分類改 3 分類(沿用字母:A 品牌=圖形 mark 圖檔零字+wordmark web font 排版拆分/B 類廢除併入 C=定格詞變 i18n key 可翻/C web font 執行期渲染/D 動態字串)+C 類視覺強度 fallback 階梯 4 層(CSS → SVG filter on text〔feTurbulence/feDisplacementMap/feSpecularLighting〕→ Canvas/WebGL 動態文字渲染〔i18n 字串→CanvasTexture/TextGeometry+shader、賽內定格詞建議層〕→ 圖形層+文字層合成〔效果主體=零文字圖形資產〕)+明文不設 per-locale 分版圖檔後門(單一效果四層皆不可行=改設計遷就政策);②UI資產.md §2.5 整節改制=定格詞美術字 → 圖形效果層(text-* 資產 ID → fx-*、提示詞模板改零文字效果圖形+預留中央文字帶、配色表轉文字層 CSS 漸層 token)+檢查清單「§2.5 例外」刪除;③頁面概念圖=設計參考件豁免(圖內文字僅示意、非出貨資產——檔頭註記);④主題系統 review 補「圖檔禁字」檢查項(default+社群主題同標準);⑤美術資源.md §8 補鐵則指標;⑥CONTRIBUTING-art 清單句同步。範圍=官方出貨資產(builtin GLB 貼圖/UI 資產/default 主題/og:image〔純視覺+og:title 帶字〕);UGC 貼圖不在此政策(不可管、內容問題走檢舉);第三方含字 badge 不引(文字連結替代、兼 CSP 'self')。零件/場地參考圖提示詞本就內建 no-text 負向詞、無需改。收益=i18n 全對稱(消滅英文特權)+a11y(圖中字 screen reader 不可讀)+跨語系共用單份資產 cache+翻譯權完整交社群。掃描:text-ready 等舊資產 ID 與 B 類引用 0 殘留。
同日落地複審(細項 3 修;殘留掃描全淨):「4 分類」/「寫死、不翻」/「美術字」全 corpus 僅歷史記錄歷程行;修——§16 鐵則「GLB 貼圖」→「GLB〔貼圖與幾何字皆含〕」(3D 立體字 mesh 堵洞)+範圍句入權威(範圍=官方資產、UGC 貼圖不在此政策——原僅記歷史記錄、權威檔未明文)+UI資產 fx-lap 措辭收緊(「LAP」字樣=i18n 執行期、僅圈數 n 可入圖——原句可誤讀為 LAP 可入圖)。邊界確認:favicon/PWA icon 適用鐵則(mark 設計零字母;「4」數字可用);og:image 品牌字不留例外(wordmark 亦執行期排版、og:title 帶字);Lottie 已列鐵則;語系清單 race bucket 既有=定格詞 i18n key 落點無需登記改動。
2026-07-06 ─ 里程碑 3c-1:physics-engine 引擎核心(Rapier 落地;7 檔、測試 66/66 全綠——determinism/rollback bit-exact 一次過)¶
套件:@dimforge/rapier3d-deterministic-compat@0.19.3(deterministic build+WASM 內嵌變體——esbuild 免特殊打包;使用技術.md 補 -compat 對齊)。⭐踩坑:.npmrc save-exact 在 pnpm -C 用法下不生效(寫入 ^)→ 手動釘死+lockfile 同步——未來安裝一律檢查 specifier。模組 7 檔(權威=physics-engine.md+程式架構 §2.1/§6):rapier-init.ts(WASM 單例+rapierVersion()=配對全等欄位)/quantize.ts(m→mm X1000 整數;⭐Math.round(-0.5)=-0 坑→‖ 0 正規化)/timestep-loop.ts(accumulator+renderAlpha+防 spiral 上限 5 步)/mesh-volume.ts(watertight 檢查=無向邊恰 2 面共用→有號四面體積分 mm³ 整數+表面積 mm²;純 +−× f64=IEEE 決定性;非 watertight 回錯、voxel 備援隨編輯器管線;重用 security GLB 解析器——glb 件自 security index 轉公用、輸入前提=已過 sanitize)/deterministic-world.ts(60Hz 鎖死+numSolverIterations=SOLVER_VELOCITY_ITERATIONS〔Rapier 0.19 TGS 單迭代軸、position 軸不存在——常數保留待對映〕;collider↔擁有者=建構序 handle 對映;SavedState v1=4B frame ‖ Rapier snapshot〔restore 用 handle 重取 body、對映不失效〕;量化 canonical state→SHA-256 hash)/physics-engine.ts(RapierPhysicsEngine 契約 12 方法全實作——staged 誠實:inputs 收而不用〔技能/動力=3c-2〕、parts sim state=回合初始值、finishedVehicles 恆空〔route=3c-3〕、fingerprint 回明確 err〔anti-piracy〕;車體=per-part AABB cuboid 近似+均勻密度、場地=合併 trimesh)。測試 10:timestep 步數/spiral 上限、量化 -0、20mm 立方 8000mm³+2400mm²、開放面拒體積、落體上地板停住、兩獨立引擎 90 幀 stateHash 全等、rollback save→前進→load→hash 還原→重播 30 幀=原時間線 bit-exact(rollback netcode 核心語意)、fingerprint err。五驗證全綠(66/66)。3c-2=每幀模擬子系統(動力/技能/熱/損耗)、3c-3=場地物理(route/b-soft/天氣/entity)。
同日落地複審(⭐常數斷線 1+細項 5 修+spec 補 1、測試 66→67):⭐MAX_SUBSTEPS(4) 未接線——常數在 system-constants、引擎沒設(Rapier 0.19 對映=world.maxCcdSubsteps、default 1)→ 抽 applyLockedSettings()(建構+restore 統一套用 timestep/numSolverIterations/maxCcdSubsteps——restore 漏套設定的風險一併堵);restore 補 eventQueue.clear()(丟棄回滾前殘留碰撞事件——rollback 污染防禦);重複 loadVehicle/loadTrack 同 id → err(原本靜默覆蓋對映、舊 body 幽靈殘留世界);interfaces 契約補單位 TSDoc ×3(VehicleState.position=公尺/CollisionEvent point·relativeSpeed/computeMeshVolume mm³——原「WASM 內計算」措辭中性化);physics-engine.md §5 補實作落點 blockquote(首版 TS=IEEE 決定性、WASM 化隨 anti-piracy 工具鏈;watertight 判定與 voxel 備援時點明文)。乾淨面——package.json 無殘餘 caret、零文檔引用 0、f32 邊界正確(TS 側 f64 僅建構期輸入非每幀模擬)、POSITION_QUANTIZE_BITS 三顆屬 network-sync wire 層(checksum 演算法=同版本內部、無跨實作一致性需求)。測試補(未初始化載入 err+重複 id err ×2)——67/67、五驗證全綠。
2026-07-06 ─ 里程碑 3b:builtin-assets 模組(ID 名錄+loadout 型別;4 檔、測試 52/52 全綠)¶
決策檔:D-20260706-12
模組(權威=builtin-assets.md 全檔):builtin-ids.ts(BuiltinId=builtin:<type>-<nn> 模板型別+isBuiltin guard+27 筆 ID 名錄〔8 類 × 3 變體+3 場地〕+BUILTIN_BY_ID 索引+載入不變式〔id 格式/前綴與 type 一致/唯一/各類恰 3/場地 archetype 對映〕;BuiltinType=material-params PartType+'track'(單一來源不重複定義);deprecated flag 全 false、ID 永久保留原則入註)/loadout.ts(VehicleLoadout 首度落地——§2 逐欄含 passiveWeightSplitPct?;loadoutRefs 全引用展開+builtinRefsIn 公版過濾——economy 跳過鑄幣/fork 拒收的共用底層)。⭐物理參數 const 表刻意不建:spec 明文「具體數值由維護者校準後填入(其他.md §2 待 playtest)」——依 1b TBD 政策不做佔位值,本站交付 ID 名錄與機制、parts.ts/tracks.ts 待數值定案後建檔。⭐spec drift 修 4+canon 化 1:src/builtin/ vs src/builtin-assets/ 路徑名分裂(版本規範 §4 path 表+builtin-assets.md §3/§7+升版流程 §8.3 用前者、模組樹與檔頭用後者——path-based CI 會監看不存在的路徑)→ 統一 src/builtin-assets/;變體編號對映 impl 需要但 spec 未釘 → §5 補「變體編號=表列序:-01 speed/-02 heavy/-03 control、場地同法」。測試 7:27 筆+唯一/場地 archetype 對映/變體編號慣例/無 deprecated/不變式 throw ×3/isBuiltin 判別/loadoutRefs 展開(含無 weapon 9 筆)+builtinRefsIn 過濾。五驗證全綠(52/52)。
同日使用者翻案:參數表要建(「後續測試定案也只是改數值」)——成立:我把 1b「無初估 K 常數不 export」(散裝公式常數、佔位會靜默進共識)誤套到結構化資料表;正確先例=economy-config(結構先建+待校準值明標、playtest 純改值零結構變動),且 3c physics-engine 測試本就需公版 fixture。重構=builtin-ids.ts 精簡為型別基座+新 parts.ts(BuiltinPartParams〔material/volume_cm3/bbox_mm+per-type:torque_ratio/declared_output_w/skill_slots/weapon 物件〕+24 筆全初估值——spec 設計值直接入表〔chip 三配置 kinetic_ratio、motor control torque 50、heavy 武器 1 轉子 360 連旋、control launch 釘刺〕、其餘體積/材質/bbox 依迷你四驅尺寸感初估;參數不變式載入即檢=欄位歸屬 per-type 強制/torque 0–100/battery declared ≤ volume×K_BATTERY_OUTPUT/chip 槽數 ≤ volume 階梯(CHIP_SLOT_VOLUME_THRESHOLDS_CM3)+skill 不重複+Σratio ≤100/weapon passive↔mechanism 互斥+launch 彈藥 ≤ LAUNCH_AMMO_COUNT_MAX+材質場景合法性引 material-params isMaterialAllowed 跨模組檢核)+新 tracks.ts(3 筆:fixed loop 4cp/fixed loop 8cp/fixed linear 6cp、normal 20°C、9.81;open 強制 linear 等不變式)+新 registry.ts(合併名錄+原結構不變式)。幾何深度欄位(mount 座標/質心/aero)待 GLB 定稿由 convert 產出後補入——註記於檔頭。測試 +3(spec 設計值抽查/chip 階梯與總 ratio/參數不變式 throw ×4 含環境材質誤用零件)——55/55 全綠。教訓=TBD 政策分兩型:散裝常數無值不 export(fail-fast);結構化表=建結構+初估值+待校準標記(economy 先例)。
同日落地複審(細項 2 修+測試 3 補、測試 55→56):乾淨面——§1/§2/§5 設計值逐項(chip 三配置 Σ 皆 100、槽數階梯 3→3 槽 6→4 槽、battery cap 1200/1280 皆過、材質全 vehicle-friendly)、零文檔引用 0。修——⭐weapon 參數欄位錯置漏檢 2:actuators 非 general 機制可帶(launch/magnet/passive 帶了不炸)+ammo_count/bullet_material 非 launch 可帶 → invariant 補雙向歸屬檢核;builtinRefsIn inline 重寫 startsWith('builtin:') → 改呼叫 isBuiltin(guard 單一來源)。測試補 3:launch 彈藥 99 超限 throw/launch 帶 actuators throw/open 場地帶 loop throw(tracks invariant 首測)。五驗證全綠(56/56)。
同日架構回顧複審(使用者要求「評估錯誤決策/不合理架構」;掃描乾淨+固化 1+⭐設計級待裁 1):①一致性層級全掃(DEPRECATED_MATERIAL_IDS 錯置同類風險)——protocol/physics・ugc・ledger・matchmaking・gameplay+network/sync・versioning 逐檔核對語意:分層全數正確(network/versioning 的 PROTOCOL_VERSION_CURRENT=配對協商性質、合層)。②⭐TrueSkill 共識定點化未收斂(待裁、matchmaking 模組動工前必須收斂)——證據鏈:matchmaking.md §1 直用 ts-trueskill 浮點庫(μ25.0/σ8.333/β4.166/τ0.0833);程式參數表 §6 浮點五顆與 TRUESKILL_BETA_X1000/TAU_X10000 整數兩顆並存=雙重權威(其他.md 待校準清單僅列整數版=某輪定點化改造做半套);但 rating=MatchDerivedState 的 derive 狀態(版本規範 §2 derive_logic 明列 TrueSkill、全網重算需 bit-exact)+資料系統 §17「超越函數禁入共識」不變式——TrueSkill 內部 Gaussian erf/浮點除法=與仲裁 Math.log10 同款炸點(該案已判定改整數查表)。解法空間屬設計裁決:(a) 全整數定點(μσ X1000 化+erf 離線查表、仲裁權重表先例)/(b) rating 降格非共識(各 peer 自算、退出 derive 驗證面——需動 資料系統/版本規範)/(c) 浮點嚴格模式(跨 JS 引擎無保證、log10 教訓已否決)。code 側暫照 spec 兩組並存、不擅動。③check-materials.mjs 自臨時腳本固化為 scripts/+check:materials script(496 欄跑通;specs 不並列=明訊息 exit 1、CI 掛載待 specs checkout 決策)。決策回顧結論:既往翻案二件(註解零文檔引用、builtin 參數表)皆已閉環修正;架構面(模組依賴無環:interfaces←key-manager←security、material-params←builtin-assets/載入 fail-fast 慣例/staged-typing/TBD 兩型政策)評估健康;已知觀察維持(PeerId 應用層編碼 vs libp2p 原生=peer-discovery 階段收斂、sanitize 自寫 parser 與 Three 渲染雙解析器=fail-safe 方向可接受、Object.freeze 淺凍結=全 codebase 一致慣例)。五驗證+check:materials 全綠(56/56)。
同日定案執行:TrueSkill 全整數定點(使用者「依照你的建議」=選項 a;跨 7 檔+code):①算式表 §20 改寫=定點權威——μσ 全程 X1000 整數(初始 25000/8333)、β X1000/τ X10000(使用處明確換算)、成對近似多人更新(每有序對算 Δμ 與 w、Σ÷(P−1)、σ 用平均 w̄ 縮減一次+τ² 動態注入)、cSq→isqrt 整數開根、TRUESKILL_VW_TABLE_X1000 查表(v=φ/Φ、w=v(v+t);t ∈ ±6000、步長 10、不插值、1201 筆 × 2——同仲裁權重表模式、matchmaking 動工時離線生成)、整數截斷除+固定運算序=bit-exact;粒度 0.01 精度損失對配對可忽略(共識要求=bit-exact 非高精度);FFA 不平手=draw margin 0 無平手常數;窗口比較於 displayRating÷1000 整數分域(窗口常數 5/5/30 維持原尺度)。②程式參數表 §6 改造=浮點五顆(MU/SIGMA/BETA/TAU/DRAW_PROBABILITY)+SIGMA_MIN 6.0 全退場 → TRUESKILL_MU_INITIAL_X1000(25000)/SIGMA_INITIAL_X1000(8333)/SIGMA_MIN_X1000(6000) 三顆新列+VW_TABLE 規格列+blockquote 記浮點退場理由。③matchmaking.md §1 重寫=去 ts-trueskill、自製 trueskill-fixed.ts+RatingX1000 型別+示意碼整數化;§2 rawRating → {muX1000, sigmaX1000}、displayRating=X1000 整數。④入站修 4=使用技術(套件退場、依賴白名單少一顆)/賽內機制 :21(DRAW_PROBABILITY 引用去除)/資料系統 :69(μσ X1000 註)/其他.md 配對列補 VW 表生成時點(非 playtest 閘、數學確定值)。⑤code=protocol/matchmaking.ts 同步(浮點六顆刪、X1000 三顆入、VW 表 TBD 註同 K 族模式)。五驗證全綠(56/56)。
2026-07-06 ─ 里程碑 3a:material-params 模組(31 材質資料+使用規則;4 檔、測試 44/44 全綠)¶
模組(權威=材質表.md 全檔):materials.ts(MaterialDef+31 筆完整謄寫——陣列序=§2 表格序=canonical UI 排序;不存 name/desc〔i18n 對 id 取字〕;載入時 assertMaterialInvariants fail-fast=磁性雙向不變式〔passive↔0–1 磁化率、其餘必 null〕+fluid 結構〔必有 deploy_behavior+vehicle-forbidden〕+range 檢查+id 唯一;MATERIAL_BY_ID 索引)/material-rules.ts(§4 場景檢核 isMaterialAllowed〔僅 vehicle 有零件類型白名單例外〕+分類 materialClass+§5 materialsForScope〔預設表格序、display_order 覆蓋、禁 locale 排序〕);MaterialId 自 interfaces 引用(單一來源)、PartType 首度定義於此模組。⭐廢止清單搬家:DEPRECATED_MATERIAL_IDS 原落 system-constants/protocol/ugc.ts——但 spec 明文「非 protocol、client minor、不擋配對」,而 system-constants/protocol/ 路徑地板=major(版本規範 §4)→ 留置會把材質廢止自動化成擋配對 → 移至新 system-constants/ui/asset-policy.ts(ui 層=純客戶端語意 ✓、路徑地板 patch、廢止 PR 依「清單資料」分類手動 minor);程式參數表 §3 該列補 impl 落點與不置 protocol/ 的理由。腳本化 spec↔const 比對(1b 慣例):解析 材質表 §2 表、31 筆 × 16 欄=496 欄逐欄全數一致(謄寫零錯、順序一致)。測試 7:31 筆+id 唯一 snake_case/分類數 14·12·5/關鍵值抽查(steel passive 1.0、magnet_floor source+thermal_limit null 不鏡像、titanium 880、oil params)/malformed throw ×3/檢核(water 僅 weapon、asphalt·magnet_floor 場地限定、abs 全域)/清單(vehicle 14、weapon 19、environment 31+表格序)。踩坑:Object.freeze(陣列字面量) 吃掉 contextual typing → union 幻影型別(TS2322)、現代 lib 無陣列 overload → 兩段式(先注型 const 再 freeze)。五驗證全綠(44/44)。
同日落地複審(乾淨面為主;測試盲點 3 補、測試 44→45):乾淨面——§1.1 MaterialDef 逐欄/§4 檢核語意(environment 無白名單路徑=零件類型僅 vehicle 場景有意義、天然正確)/§5 排序/搬家零波及(DEPRECATED_MATERIAL_IDS 全 src 僅新家一處、invariants.ts 不涉)/material-params 零文檔引用;模組邊界正確(§7 合成/§8 磁性公式/§9 耐受度屬 physics-engine、不在本模組)。補——materialsForScope 加 source 注入參數(消滅 display_order 覆蓋排序的不可測分支)+測試 3(display_order=-1 插位最前/tire=14 無白名單同通用清單/duplicate id throw)。觀察 1 備查——display_order 覆蓋值與預設 array index 同一值域混排(spec §1/§5 未定兩者關係;現無任何材質設值、零現實影響):待首個實際設值時釘死語意(建議屆時 spec 補「覆蓋值需自行避開 index 值域」半句或改聚類語意)。五驗證全綠(45/45)。
2026-07-06 ─ 里程碑 2c:security 模組+repo 級資安件(12 檔;測試 36/36 全綠、開發順序站 1「抽象+身分+安全」收官)¶
模組(權威=security.md 全檔+資安規範):glb.ts(零依賴最小 GLB 解析——容器 chunk 驗界/POSITION·indices accessor 解碼〔sparse 拒收〕/PNG·JPEG·KTX2 表頭嗅探/canonical 重打包=剔除非標 chunk 與尾端垃圾;惡意輸入一律 throw→parse-error)/sanitize-core.ts(檢查順序照 §1.4:大小天花板→容器→外部 URI〔data: 不算外部〕→extras 三閘〔總量/深度/可執行 payload 啟發式;迭代走訪防深巢爆棧〕→三角形數〔metadata 先擋、不解碼〕→NaN·Inf→AABB→退化面 >5%→貼圖邊長 4096〔未知影像格式 fail-safe 拒收〕→正規化重打包;天花板全取自 system-constants、per-type 檢核歸 pipeline 不重複)/sanitize.worker.ts+mesh-sanitizer.ts(每請求一次性 Worker、timeout 即 terminate、transferable 零拷貝;記憶體上限=輸入天花板+terminate 兜底〔瀏覽器無 per-worker 硬限〕)/nonce-set.ts(容差窗淘汰;窗外重放由 timestamp 關擋=不需永久記憶)/verify-p2p.ts(四關:白名單→±30s→nonce→驗簽;結構化 P2pRejectReason、全過才收錄 nonce)/security-log.ts(環形 500、只存本機+attachCspViolationListener)/sri.ts。Repo 級:.npmrc(save-exact+engine-strict)+package.json 全依賴 exact pin(lockfile 解析值、^/~ 清零)+security.yml(pnpm audit --audit-level moderate、push/PR/週排程)+SECURITY.md(GSA+security@open4wd.org、回應時限表、90 天 disclosure)+CSP=build 注入(scripts/inject-csp.mjs 掛 build 鏈末端、meta 交付)+SRI=angular.json production subresourceIntegrity: true;順修 angular.json schematics prefix app→o4(漏網、對齊 selector canon)。測試 19(sanitize 11=各拒收路徑+正規化冪等+爆量解碼前擋;security 8=nonce 淘汰/驗簽四關各態/重放/日誌上限/CSP 監聽解除/SRI 與獨立計算一致)——累計 36/36。spec 同步:security.md §3 補 CSP 實作落點+§4 補 SRI 落點+§5 內部矛盾修(audit flag high vs 文字「≥ moderate 阻擋」→統一 moderate=資安規範 §6.2 權威;npm→pnpm;stale 版號範例去除);資安規範 §7 Referrer-Policy 值 drift 修(same-origin→strict-origin-when-cross-origin=security.md §6 權威)。五驗證+build 產物抽驗(CSP meta+bundle integrity 屬性)全綠。
同日落地複審(契約逐項比對+殘留掃描全淨;細項 4 修+spec 補 1、測試 36→37):乾淨面——§1.1 型別/8 拒收原因/§1.2 六天花板來源/§1.4 檢查順序/§2 四關與碼字/§3 CSP 11 指令逐項/§4/§5/§7 契約全對;Referrer-Policy 全 corpus 僅雙權威且一致、audit 措辭 0 殘留、src/security 零文檔引用零 console。修——MeshSanitizer 補 transferable 契約 TSDoc(呼叫後原 buffer 失效);computeSRI 補 response.ok 檢查(錯誤頁雜湊=靜默錯誤);測試補 2(不同 nonce 不受收錄影響+尾端垃圾正規化剔除證明);資安規範 §9.1 補 Email 現況(security@open4wd.org、與 dmca@ 同法設定、PGP 上線前發布、SECURITY.md=對外公告版)。觀察 2 備查——SANITIZE_WORKER_VERSION/SANITIZE_MAX_MEMORY_MB 已 export 未被 runtime 引用(前者屬指紋/收件 protocol 版本化、隨對應模組接線;後者=文檔性上限、實際機制=輸入天花板+terminate);worker 禁 fetch 屬程式紀律(worker 繼承頁面 CSP、connect-src 為 scheme 級——spec §1.3/資安 §2.3 既知設計)。五驗證+build 注入全綠(37/37)。
2026-07-06 ─ 里程碑 2b:key-manager 模組本體(9 檔、測試 16/16 全綠)¶
決策檔:D-20260706-14
套件(spec 明文之稽核級標準件):@scure/bip39+@scure/base+@noble/curves+@noble/hashes(皆 2.2)+@ipld/dag-cbor(10.x、canonical 序列化)——v2 系子路徑需帶 .js(@noble/hashes/sha2.js 等;check:types 抓出、四處修)。
實作(權威=key-manager.md 全檔):mnemonic.ts(24 詞生成/12·24 驗證/seed 前 32B)/ed25519.ts(keypair/簽驗/PeerId 編解碼——'z'+base58btc(0xed01‖pub)、解碼含防禦驗證回 null)/seed-crypto.ts(Argon2id 64MiB·3iter·4lane+AES-GCM;kdfParams 可注入供測試)/profile-store.ts(ProfileStore 抽象+IndexedDB 實作+Memory 實作——測試免 fake-indexeddb 依賴、IndexedDB 留待瀏覽器煙囪測)/pin-guard.ts(5 次錯鎖 30 分;結構化錯誤 union、manager 邊界才轉繁中訊息——利 i18n)/signed-payload.ts(sha256(dagCbor({nonce,payload,signer,timestamp}));verifySignedPayload 免本地身分——公鑰內含於 PeerId)/key-manager.ts(Open4wdKeyManager 實作契約全 14 方法+deriveRaceSignKey(sha256(master‖tag‖raceId) 確定性 ephemeral)+signPayload 便利法(nonce 長度取自 system-constants);lock()=privateKey.fill(0) 歸零;now 可注入)。測試 12:助記詞確定性/PeerId roundtrip+壞輸入/簽驗+竄改/加解密+錯 PIN/暴力鎖全流程(注入時鐘、期滿解鎖)/恢復(既有重設 PIN+跨機同身分)/changePin·deleteProfile 驗 PIN/SignedPayload 竄改 payload·signer 皆敗/race key 確定性/64MiB 真實參數 roundtrip。四驗證+check:types 全綠(累計 16/16)。
同日落地複審(契約逐項比對+spec 三處自漂修正+記憶體歸零加固;中 3 細 8 全修、測試 16→17):Spec 側——⭐① key-manager.md §7 recoverFromMnemonic 範例與 §2 契約自漂(3 參數帶 nickname、回 Result<ProfileMetadata> vs §2 的 2 參數回 KeyPair)→ §7 重寫對齊 §2(預設暱稱=PeerId 前 8 碼、恢復即解鎖);⭐② SignedPayload 簽章訊息位元組結構未釘死(§9 偽碼 4 參數 serializeForSigning 與 ledger.md §1 單參數簽名對不上——跨 client 各自序列化=驗簽必炸)→ §9 釘死 buildSignedMessage = sha256(dagCbor.encode({nonce,payload,signer,timestamp}))(名稱=雙向對照鍵、與 src 同名),三處 copy 同步(資安規範 §3.4 撤公式改指 §9/security.md §2 驗簽改呼叫 buildSignedMessage);③ §10 Race Sign Key「同 raceId 跨 peer 一致」錯誤措辭(字面=各玩家同鑰、簽章可互偽)→ 改「同(master, raceId)確定性重派生、各 peer 各自持鑰、公鑰賽前握手交換」+釘死派生式 sha256(master ‖ 'open4wd-race-sign' ‖ raceId);資安規範 §12 表兩列順修(「libp2p PeerId」→ 0xed01 multibase 編碼指 key-manager.md §1——本專案編碼非 libp2p 標準式;幽靈「Profile Key」→「Profile」多身分檔語意)。Code 側——⭐換鑰不歸零洞:unlockProfile/recoverFromMnemonic 覆蓋 current 前未歸零前一把私鑰(切換 profile 舊鑰殘留記憶體)→ 三處先 lock();明文 seed 生命週期收緊 ×5(createProfile 加密後歸零/changePin 重加密後歸零/deleteProfile 驗完即刻歸零/mnemonicToSeed 64B 原 buffer 歸零/KDF 派生鍵入 CryptoKey 後歸零);冗餘清理 ×3(as Signature 重複 cast/Memory store 冗餘 return/「可後改」暱稱註解去除——無此 API)。測試補 4:SignedPayload 竄改 timestamp/nonce 皆敗(§9 不變式直接護欄)+lock 歸零斷言+切換解鎖前鑰歸零(新測試)+listProfiles——17/17。觀察 3 備查:硬體 provider 模式 getPeerId/signPayload 未定義(§8 預留、隨硬體流程收斂);changePin/deleteProfile 不計暴力鎖 attempts(每次嘗試本就燒 Argon2 64MiB、離線攻擊不走此路徑——維持);unlock 錯誤=繁中 prose Error(UI 語系化時需結構化錯誤碼、pin-guard union 已備)。五驗證全綠。
同日使用者追問定案:PIN 錯誤結構化(觀察三之一轉正、跨 6 檔):使用者質疑「語系沒有一開始就收斂成結構化錯誤碼嗎?」——成立:§6 範例 prose 直出係早於表單兩層模型的寫法、實作照 spec 字面走=內層(pin-guard union)有結構、邊界壓扁,複審時誤降級為觀察而非上報 spec 對撞。裁「現在收斂」(未 commit=零遷移成本)→ KeyManagerError union 上移 interfaces 層(單一來源、pin-guard 併入引用;profile-not-found/pin-invalid+attemptsLeft〔null=不計次路徑 changePin·deleteProfile〕/pin-locked+remainingMinutes/pin-locked-now+lockMinutes);unlockProfile→Result<KeyPair, KeyManagerError>、changePin/deleteProfile→Result<void, KeyManagerError>——模組零文案、UI 以 code 映射 i18n(errors.keyManager.*=語系清單既有 errors 命名空間巢狀)+參數插值;不變式守門維持 throw(未解鎖呼叫 sign/getPeerId/changePin、createProfile 助記詞不合法/身分已存在——表單層 validateMnemonic 前置驗證、建檔助記詞現場生成=正常 UI 流程不可達、屬開發者面);changePin 未解鎖改走 requireUnlocked() 統一 throw。spec 同步=key-manager.md §1(KeyManagerError 型別)/§2(三簽名)/§6(範例改結構化+i18n 映射註、§4 error(→err( 順修)+interfaces.md §6 鏡像三簽名+型別列;測試斷言改驗 code+補 profile-not-found+暴力鎖逐次錯誤碼序列(1–4 次 pin-invalid、第 5 次 pin-locked-now、鎖定中 pin-locked)——17/17、五驗證全綠。
2026-07-06 ─ 里程碑 2a:interfaces 模組(六大介面契約+共用型別;8 檔、全綠)¶
實作(權威=程式架構/interfaces.md 全檔+key-manager.md §1·§8·§9 型別):shared.ts(Result+ok/err、VersionedInterface、Timestamp、Unsubscribe、REQUIRED_INTERFACE_VERSIONS+checkCompatibility;CID/PeerId/Signature 自 system-constants Brand 再匯出——不重複定義、單一來源)/signaling.ts(SignalingProvider+SignalMessage 3 型+MatchCriteria)/physics.ts(PhysicsEngine+世界設定+載入/Input/輸出全型別:VehicleSpec/PartInstance/PlayerInput/SkillId 8 種/SkillSlot/EntityType/WeaponBranch/WeaponActuator/StepOutput/VehicleState/PartState/MeshFingerprint)/asset-storage.ts/ledger.ts(Ledger+BaseEvent+CheckpointProposal)/key-manager.ts(KeyManager+Mnemonic/KeyPair/ProfileMetadata/HardwareKeyProvider/SignedPayload)/pinning.ts/index 彙整;tsconfig 補 @open4wd/interfaces path。Staged-typing 慣例:跨模組型別先以契約占位、隨對應模組收斂(LedgerEvent=暫以 BaseEvent 為上界/DerivedState opaque/SignalingWireMessage 最小型/TrackSpec·VehicleSpec 註明「隨 physics-engine 收斂」)——註解自足標示、零文檔引用(新 §14 鐵則首戰)。lint 風格落地:ReadonlyArray<T>→readonly T[](spec TS 區塊=契約示意、語法糖非 drift)+物件別名→interface(InputEvent=介面+別名保留 union 擴充位)。驗證全綠:format/lint/test 4/4/build。下一步 2b=key-manager 模組本體(需裝 @scure/bip39+@noble/curves+@noble/hashes——spec 明文 import 的稽核級套件)。
同日落地複審(⭐驗證盲區 1 補+慣例統一 1;契約雙向 diff 全對):⭐發現 build/test 的程式圖不涵蓋未被入口 import 的模組——ng build 只編譯 main.ts 可達圖、vitest 只編譯 spec 可達圖,interfaces(尚無消費者)完全沒被型別檢查 → 新 tsconfig.typecheck.json(include src//*.ts、noEmit)+check:types script+CI 補步——此後每個未接線模組都有全量 tsc 把關(跑通=interfaces 型別乾淨證實);順帶 app.spec.ts 全域 describe/it 改顯式 import from 'vitest'(統一專案慣例)。契約完整度腳本 diff:spec 成員名 91/匯出型別 41——src 雙向缺 0**。四項驗證+check:types 全綠。
2026-07-06 ─ 註解鐵則翻案:自足、零文檔引用(使用者批評成立;§14 改版+全 codebase 清掃 88 處)¶
決策檔:D-20260706-08
背景:使用者指出「把文檔資訊硬寫入註解不理想」三理由——①spec 章節重編=引用必漂移(本 corpus 的重編號之痛即鐵證)②開源讀者需對照外部文檔、閱讀困難③不預設 specs 永遠公開。全數成立 → §14 註解鐵則由「引 spec 出處、不複述內容」改為「自足、零文檔引用」:註解不得出現 spec 檔名/章節;一句話講完語意/約束、單看程式碼可讀;深層設計理由單一權威=specs 不複述;雙向對照鍵=名稱(常數/模組/介面名 spec 與 code 同名、spec↔const CI 按名對帳——1b 複審腳本已證明可行);spec→code 對應由 spec 側維護(§9.1 表)、code 側零反向指標。模組檔頭列同步改「自足、不引 spec 檔」。
清掃(88 處 → 0):system-constants 24 檔(純指標行刪除、混語意行改寫自足——如「——部署資訊.md §4.3」刪、「(資料系統.md §1.1 信任根)」→「(信任根=client 內建位址+genesis signer set)」)+32 骨架 stub 重生成(去「實作規格:」行)+eslint.config.js ×2+ci.yml 檔頭+.gitignore lockfile 註。驗證全綠(format/lint/test 4/4/build)、grep '\.md' 程式碼面 0 殘留。
2026-07-06 ─ 里程碑 1b:system-constants 模組本體(程式參數表 19 節 → 型別化常數;24 檔、測試 4/4 全綠)¶
實作(權威=程式參數.md 全表+程式架構/system-constants.md):四層結構 protocol/(physics+K 族/ugc/security/ledger/matchmaking/gameplay)+network/(sync/signaling/peer-discovery/versioning)+ui/(animation/audio/layout/i18n-defaults/seo)+economy-config/(EconomyConfig 介面+ECONOMY_CONFIG_DEFAULTS+governanceQuorum);brands.ts=§19.1 全 Brand 型別+建構工具;統一匯出 Protocol/Network/UI/EconomyConfig 命名空間;tsconfig path @open4wd/system-constants(TS 6 廢 baseUrl → 相對 paths 語法)。ARBITRATION_WEIGHT_X100_TABLE 離線生成(1001 筆、round(100×log10(rep+10))、值域 100–300——算式表 §17;隨 client 出貨)。§19.2 不變式=checkInvariants()(revShare=100/質量 min<max/rollback 三角/StateBuffer≥回滾窗/玩家數≤hardcap/回合三角/重力域/body 預算帳/快照門檻/治理 quorum〔genesis 空集跳過〕)+vitest spec(含權重表長度/首尾值/單調性)+check:invariants script(升版流程 §3 CI 名對齊)。TBD 政策:無初估值之 K 常數不 export(檔內註解列名單、指 其他.md §2——拒佔位值進共識計算);economy 待 playtest 欄位=0n 佔位+檔頭「genesis 前必填」警告;LEDGER_DB_ADDRESS 空字串=鏈未建。驗證全綠:format/lint/vitest 4/4(2 檔)/build/check:invariants。
同日順修 spec:程式參數表 §14 表格斷裂修復——07-06 斷點批插入的「斷點語意」blockquote 落在表中段、切斷 THEME_RESERVED_TOKENS/THEME_SIZE_MAX_MB 兩列 → 移至表尾。
同日落地複審(腳本化 spec↔const 首跑;細項 1 修):①名稱 diff(scanner 掃 §2–§16+§18 表格常數名 vs src export)——spec 215:src 201;「spec 有 src 無」18 顆=TBD 政策名單逐一相符(刻意不 export)、「src 有 spec 無」4 顆=§17 DEFAULTS+REPUTATION 三顆(spec 合併列、scanner regex 限制——實際 §5 有 ✓)→ 帳目全對;②數值 diff 155 筆單值常數逐一比對——0 不符;③細項修=EconomyConfig.creator_royalty.niche 預留槽補回(spec §17.1 介面字面有此欄、原以註解替代 → Readonly<Record<string, never>>+空物件預設、標注「預留治理槽、公式本體非 config」)。查核乾淨面:§19.1 Brand 12 型別全數+§19.2 不變式十條全實作、字串/陣列值人工核對無誤、四項驗證修後重跑全綠。此腳本=未來 CI「spec↔const 一致性」閘的雛形(升版流程 §3),實作 CI 閘時轉正。
2026-07-06 ─ 程式碼風格與註解規範定案(新 程式架構 §14)+主 repo 里程碑 1:Angular 22 workspace+33 模組骨架+CI 全鏈綠燈¶
風格規範(使用者問「formatter?開源註解該齊全?」→ 定案):Prettier 本已在 canon(使用技術 Lint 列)、補細節=新 程式架構.md §14:printWidth 100+singleQuote(恰為 Angular 22 生成預設);註解語言=繁體中文(使用者裁;識別字一律英文);註解鐵則=引 spec 出處、不複述內容(單一權威延伸——複本必漂移);覆蓋表=exported API 一律 TSDoc(用途+spec 出處)/模組進入點檔頭(角色+spec 檔)/inline 只寫 why;CI format:check 掛 lint 步(升版流程 §3 同步);使用技術 Lint 列補指標。
里程碑 1 執行(主 repo):Node 24.14→24.15(nvm;Angular CLI 最低要求)+corepack pnpm 11.10。Angular 22(ng new @latest:SCSS/無 SSR/Vitest 4+jsdom 內建/zoneless/Prettier 內建——spec「最新版+Vitest」全命中);angular-eslint+eslint-config-prettier(格式歸 Prettier);selector 前綴 app→o4(canon=前端技術策略 §4 o4-;root component o4-root、index.html lang=zh-TW);.gitignore 續守 lockfile 必 commit+補 .env/.tsbuildinfo/desktop.ini;.prettierignore;src/ 33 模組骨架(程式架構 §9 樹全數、各含 §14 規範繁中檔頭 stub 指向對應 spec);CI 起手式(.github/workflows/ci.yml:install→format:check→lint→test→build;private 期精簡、actions 鎖 tag、完整管線 public 前補——檔頭註明)。驗證全綠:format:check ✓/lint ✓/vitest 2/2 ✓/build ✓(main 214KB)。README 由 ng 生成版取代佔位。下一步(1b)=system-constants 模組本體(程式參數表 → 型別化常數、spec↔const CI 閘地基)。
同日落地複審(中2細項2、全數修畢重驗全綠):⭐tsconfig 無 strict——ng 22 生成檔只有零散嚴格項、違 使用技術.md「TypeScript strict 模式」→ 補 "strict": true+angularCompilerOptions.strictTemplates: true;⭐CRLF 地雷——使用者機器 core.autocrlf=true+無 .gitattributes+Prettier 強制 LF=commit 後任何 checkout 得 CRLF、format:check 全紅 → 趕在首次 commit 前補 .gitattributes(* text=auto eol=lf+glb/ktx2/wasm 等 binary 標記);細項=package.json 補 engines.node >=24.15.0+.gitignore 整併(使用者裁 .vscode/ 全忽略——刪 ng 白名單塊與其矛盾、lockfile 註解歸位獨立段)。查核乾淨面:CI=true 下 vitest 單跑 ✓、pnpm/action-setup 讀 packageManager ✓、Prettier 3 預設吃 .gitignore+.prettierignore ✓、actions 皆 tag 鎖版 ✓。
2026-07-06 ─ 主 repo 建立確認(使用者建置;⭐.gitignore 忽略 lockfile 違資安 §6 已修)¶
背景:使用者建立主 repo github.com/xjustloveux/open-4wd。確認全過:PRIVATE(private 起手策略 ✓ 部署資訊 §2.1)/預設分支 master(corpus 慣例 ✓——GitHub 預設 main、使用者已改)/LICENSE=MIT(Copyright 2026 JaJa、與 specs repo 一致)/Initial commit=README+LICENSE+.gitignore、與 origin 同步。
⭐發現並修:GitHub Angular .gitignore 模板忽略 /package-lock.json//yarn.lock——與 資安規範.md §6.1 嚴格鎖版直接衝突(供應鏈完整性要求 lockfile 進版控;本專案用 pnpm、pnpm-lock.yaml 必須 commit)→ 刪兩行+補註解。備忘:README 現為佔位(# open-4wd)、public 前補實內容;工作區空的 企劃/ 資料夾又出現(0 檔、待使用者刪)。
2026-07-06 ─ 全 corpus 收官複審(repo 遷移後;斷鏈 3 修+自違用語 2 修、跨 4 檔)¶
打法:①今日全部批次(鏈身分/TURN 模板化/DMCA 補強/Template 化/營運模式/斷點)術語家族總掃——舊制 11 族全 0 活殘留(一 repo=一部署單元/待購買/md 斷點/open4wd.dev/REGISTRY_TOKEN/官方 Harbor/ledgerName/企劃/ 等)、新制 12 族分佈全對(公版 Template ×9/ghcr ×10/use-template ×20/鏈重生 ×7 等);SignerSetUpdateEvent 等 2 命中=合法否定句。②全 corpus 斷鏈掃描(268 條唯一相對連結)→ 3 條真斷鏈全修:程式參數表 :163/:165 ../流程/→流程/(根層檔誤用上跳、07-05 加 LOADOUT 常數時引入)+DMCA流程 :103 ../升版流程→同資料夾(07-02 批引入);歷史記錄 :607 指向已刪 其他/武器多轉子.md 的連結去連結化(保文字+補「後經授權刪除」)。③TODO/TBD 盤點全屬合法(K 族待 playtest=其他.md §2 收錄/公版 inventory 待校準/economy 輔助函式待實作)。④修自違用語 2:部署資訊 §2.1(當日新寫)「本地測試」×2→「本機測試」(07-05 統一詞、自己違反)。
實作就緒度確認:程式架構.md 13 節含 §5 開發順序建議/§6 Determinism/§7 測試矩陣/§9 程式碼層次/§13 routes;使用技術=Rapier deterministic 鎖版+dt/f32/INTEGER_SCALE 全釘、Angular「最新版本」=init 時鎖定(刻意不預鎖);其他.md 現況 3 節全 playtest 閘。結論:spec 層完整、無阻塞實作項、可動工。
2026-07-06 ─ 斷點語意釘死:平板版面歸屬+CSS 邏輯像素/em 實作+1440=內容最大寬(中1細項2、跨 4 檔)¶
決策檔:D-20260706-10
背景:使用者兩問——①「之前好像只提 PC 與 mobile、平板有沒有被涵蓋」②「像素越來越高、純 px 斷點會不會失準」。盤點:斷點三級(640/1024/1440)+通用頁映射(Mobile 單欄/Tablet 雙欄/Desktop 三欄)+GARAGE_GRID_COLS+平板輸入層(§0.6 觸控無快捷鍵/外接鍵盤啟用)皆已有;真缺口=編輯器 PC/Mobile 版面家族無切換斷點(§0.5 標題殘留 Tailwind 式「≥ md 斷點」未定義詞)+BREAKPOINT_DESKTOP_PX(1440) 用途無明文(映射只用 640/1024、§14 說明欄全空)。「失準」擔憂經釐清=CSS px 為邏輯像素、DPR 平台歸一、高解析不失準;唯一真邊角=使用者調大預設字級(px MQ 不動)→ em 實作解。
落地:①編輯器版面家族切換點=BREAKPOINT_TABLET_PX(1024)(編輯器操作 §0.5 新引言:<1024=Mobile 版面/≥1024=PC 版面;版面依寬度、輸入依偵測(§0.6)兩層正交——平板直向≈Mobile+觸控、橫向≈PC+觸控〔目標仍 ≥44px〕、外接鍵盤任一版面啟用快捷鍵;「≥ md 斷點」「< md」→「viewport ≥/< 1024」全 corpus 0 殘留)②§14 三常數說明補齊+表下語意註(單位=CSS 邏輯像素・DPR 屬渲染軸/MQ 一律 em 實作=40/64/90em @16px 同值、字級無障礙加分/語意=可用寬度分桶・禁機型綁定/桶間流式、不另設細粒度斷點)③BREAKPOINT_DESKTOP_PX(1440)=內容最大寬度(>1440 容器置中不放大、與設計畫布 1440×900 一致)④前端技術策略 §10+頁面線框 §13 同步鏡像。觀察不動:不加斷點(三級唯一已裁)、渲染解析度/舊機效能屬渲染設定軸。
2026-07-06 ─ open-4wd-specs repo 建立:spec corpus 全量搬遷 repo 根(使用者建置;措辭修 4 檔+README/.gitignore 補)¶
背景:使用者建立 github.com/xjustloveux/open-4wd-specs(MIT、master)並將 企劃/ 全部內容搬至 repo 根(無 企劃 wrapper 層;本機位置=工作區 open-4wd/open-4wd-specs/)。repo 名採 specs(vs docs 評估:本 corpus=設計規格非使用文件;-docs 留給未來玩家/開發者文件)。
驗證乾淨:層級保留=檔內相對連結全存活;當日全部編輯隨遷(抽驗 LEDGER_DB_ADDRESS/營運模式 bullet);檔數=根 26 md+流程 12+程式架構 43+美術資源 240+部署資訊 3;LICENSE=MIT(Copyright 2026 JaJa);維護者個人/工作資料與 project-resources/tools 全未入 repo。
措辭修(「企劃/」活指涉 3 檔;歷史記錄內 11 處=歷史語境保留):總覽 檔頭「以 企劃/ 為準」→「以本 repo(open-4wd-specs)為準」+project-resources 標注不在本 repo/美術資源 :9 tree root「企劃/美術資源/」→「美術資源/(repo 根下)」+:26「企劃/ canon」→「本 repo canon」/提示詞/零件參考圖 :3+:857 同款。版權 :311 LICENSE 列補 specs。補 README.md(landing:定位+入口 總覽/歷史記錄+資料夾導覽+MIT)+.gitignore(OS junk)。使用者已 push+刪除舊空 企劃/。LFS 評估=不用(repo 177MB/最大檔 2.6MB/參考件靜態一次性;LFS 免費頻寬 1GB/月=公開 repo 地雷——社群 clone 數次即爆、全員下載被擋;未來單檔 >50MB 或頻繁改版大檔才回頭、優先 Release assets/留工作區)。
同日:主 repo 可見性策略入 canon(使用者問「private 本地測試、後續再 public 可行嗎」→ 可行且為自然順序〔免費方案 Pages 僅 public=上線強制 public〕):新 部署資訊 §2.1 主 repo 可見性生命週期——private 期四現實(無 Pages/bootstrap raw 404 靠內建 fallback/Actions 2000 分/月省用矩陣/branch protection 免費僅 public=先自律)+「第一 commit 起當作已 public」鐵則(零 secrets/訊息乾淨/noreply email 可選)+切 public 六步 checklist+「公版直接 public、-deploy 恆 private」註;升版流程 §8.2 禁直推列補鏡像半句。
2026-07-06 ─ 營運模式定案:捐助制+不掛第三方廣告;域名定案 open4wd.org(跨 3 檔+根目錄個人參考檔)¶
決策檔:D-20260706-01
背景:使用者問「MIT 下塞廣告營利會有問題嗎」→ 評估:MIT 明文允許營利(雙向——任何 fork 也可),但三堵牆使廣告與專案骨架相性差:①資安/隱私鐵則(CSP 'self'+無第三方 script+不蒐集 telemetry+CI 不變式)與聯播網正面衝突②GitHub Pages ToS 禁商業託管③架構上無廣告鏡像連同一條鏈一鍵替代、廣告燒信任。續問贊助制義務/法律/稅務 → 定案:捐助制、不掛第三方廣告。
落地:總覽.md 專案定位補「營運模式」bullet(權威:MIT 開源+捐助制〔GitHub Sponsors/Ko-fi+FUNDING.yml〕、不掛第三方廣告、贊助不影響 roadmap 與治理);部署資訊.md §12 補延伸指標(與 telemetry 隱私立場同源);dmca.md §6 信箱例 open4wd.dev→open4wd.org。域名定案=open4wd.org(無連字號、gTLD 避 ccTLD 風險、.org 契合捐助制開源定位;程式架構.md :334 佔位本就是它、無需改;example.com 級佔位待實際購入後統一輪)。另同步維護不入任何 repo 的個人參考資料。
同日:域名已購入(open4wd.org+open4wd.com 防禦性)——部署資訊 :28/:202+程式架構 :334「待購買」現況化;example.com 級端點佔位(turn/pin/relay/bootstrap)刻意保留——端點與主站域名解耦(§8.3 不變式)、實值屬部署 repo、待實際部署才定。
2026-07-06 ─ 週邊 repo 全面 Template 化定案+金鑰產生 runbook(使用者提案;pinning/signaling 比照 TURN;跨 7 檔)¶
決策檔:D-20260706-02
背景:使用者提案「部署設定與流程人人不同——pinning 也做成跟 TURN 一樣:公版+use-template 微調後部署」→ 定案並統一三顆週邊 repo 模型=公版 Template repository(零 secrets、驗證/發佈 CI、永不部署)+官方部署 repo(use-template、與社群自架同一條路、微調與 secrets 全住部署 repo);差異僅時程(pinning/signaling 官方 day-one 部署、turn 延後)。關鍵改良(GHCR):公版 pinning CI 以內建 GITHUB_TOKEN(packages:write)發佈 public image 至 GHCR → 部署 repo 免 build、免 registry secret、免 imagePullSecrets(原待裁 1–4 全消解:部署方式=部署 repo 私事〔憑證三選一:KUBE_CONFIG 遠端/SSH 節點端/compose 免 CI〕;Harbor 整組退場;CI 鎖版+tag=時間戳+短 SHA 成公版規格句;單機=replicas:1+PVC 快照必做+「依實際資源調整」)。跟版=部署 repo git remote add upstream 定期 merge(use-template 無 fork 連結;三檔指南各一句)。
金鑰產生 runbook(使用者要求文檔化):open-4wd-pinning.md 新 §3.3——節點身分(docker 跑 kubo → ipfs id+ipfs config Identity.PrivKey → secret → 銷毀容器 → multiaddr 進 bootstrap/list.txt PR)/CLUSTER_SECRET=openssl rand -hex 32/DMCA_ADMIN_TOKEN=openssl rand -base64 32(純隨機 Bearer 口令、密碼管理器自留)/玩家 PeerId=助記詞→key-manager 工具(非 secret、填 config;助記詞永不進 GitHub、勿用泛用工具預產——與遊戲內身分對不上)。dmca.md §2 補「Windows bat 包裝(讀同目錄 txt 參數)」半句(使用者的 bat+txt 維運工具形狀)。
跨 7 檔:open-4wd-pinning.md(模型行+§3 兩層化+新 §3.3+§4 CI/CD 分層 GHCR+§5 指南)/open-4wd-signaling.md(模型行+§3 前言+§4 分層+§5 官方同路)/open-4wd-turn.md(§7 跟版句)/部署資訊.md §3(模型句+GHCR image)/程式架構.md §11 兩列/pinning-service.md §1 CI 句/dmca.md §2 bat 半句。
同日落地複審(修 5):⭐turn §4 變數表兩層化漏網補齊(公版零 secrets 前言+部署憑證三選一——與 pinning/signaling 形狀對齊、複審主發現)/turn §5 公版 CI 補 actions 鎖版句(三檔統一)/turn §7 k8s 路徑改「部署憑證(§4 三選一)」/pinning §3.3 節點身分補「可預產(私鑰先存密碼管理器、部署 repo 建立後入 secret)+init 未完重試」(聊天答覆與文檔落差回填——使用者問出)/pinning-service.md §5 replicas: 3 補「模板理想型、依規模調整單機=1」防誤讀。查核乾淨:舊模型句(「一 repo=一部署單元」「部署目標=官方 k8s」「fork → 設 secrets」)全 corpus 0 活殘留(僅歷史)、新增 §-引用全解析、KUBE_CONFIG 僅存兩處三選一列、罐頭範本六要件=dmca.md §1 schema 對齊、GHCR/跟版句三檔一致。
同日追補:部署 repo 命名慣例=<公版名>-deploy 入 spec 三檔「官方部署走同一條路」條(官方=open-4wd-{pinning,signaling,turn}-deploy;社群自架建議同慣例)——1:1 對應公版、排序相鄰、不用環境詞(環境分流走 branch→namespace)。
2026-07-06 ─ DMCA 維運補強包定案(admin 端點/防濫用三件組/反通知入口/登記 runbook;跨 2 檔)¶
決策檔:D-20260706-04
背景:部署討論延伸——使用者逐項問透 DMCA 維運(信箱申請/API 濫用/亂寄信/下架實操/反通知產生)→ 定案補強(原「通知維護者」「通知創作者」機制未釘、admin 端點整組缺失——DMCA_ADMIN_TOKEN 有了但可用它的端點沒定義)。
dmca.md:§2 API 表補 admin 兩端點(GET /admin/notices?status=+POST /admin/notice/:id/decision {take_down|reject|restore}——單一呼叫完成即時層 unpin+索引/gateway 排除〔pinning-service §9 執行點〕+status 轉移+透明度計數、restore 同步 re-pin;DMCA_ADMIN_TOKEN header 認證)+收件防濫用三件組(per-IP rate limit 掛 mgmt-api 既有骨架/payload 413/email 確認關=點確認連結才成案並通知 Agent 信箱、未確認 72h 清除;status 新增 pending-email-confirm;CAPTCHA 不採=第三方 script 違 CSP)+維運介面=HTTP 直呼(curl/Postman、GUI 非必要、指令範本隨部署 repo README);§3.1 詳情頁下架標示附反通知入口(client 以 TakedownEntry.noticeId 組 /dmca?counter=<noticeId>、表單自動帶 originalNoticeId)=「通知創作者」的實體(匿名 PeerId 無 email 可寄);§5 註解同步;§6 補 runbook 指標。
DMCA.md:§1 受理段補防濫用/確認關/通知 Agent 信箱、:38「通知被指控方」句釘死;§5 補「決策執行=admin API 單一呼叫+下架清單 PR」;新 §5.1 代理人登記與信箱建置 runbook(使用者要求文檔化):信箱=Cloudflare Email Routing 四步(免費)/登記=dmca.copyright.gov 步驟($6/3 年、續期入行事曆)/公示三處同步/隱私註記(登記資訊入公開名錄——組織名+郵政信箱建議)/時程=正式對外上線前、playtest 不需。
同日追補:admin 認證 header 釘死=Authorization: Bearer <DMCA_ADMIN_TOKEN>(secret 只存 token 本體、Bearer 前綴呼叫時加——使用者問出)+新 §5.2 直寄信罐頭回覆範本(使用者要求文檔化;EN 範本列 §512(c)(3) 六要件;三規則=導流非拒絕・要件齊全直寄信仍屬合格通知須維運者代錄入表單進同一管線・不全同範本回覆補齊前無義務・垃圾不回)。
2026-07-06 ─ TURN 公版模板化定案(使用者提案:先建公版不部署、需要時與社群同路 fork 部署;跨 6 檔)¶
決策檔:D-20260706-03
背景:部署討論(GitHub secrets 盤點→TURN 原理解說→UDP port range 疑慮)中使用者提案「先建 repo 不部署、需要部署時走跟其他人一樣的流程額外 fork 部署」→ 定案。原模型「一 repo=一部署單元=一條 CI(部署目標=官方 k8s)」改為:公版 Template repository(本體零 secrets、驗證 CI=envsubst 渲染檢查+compose config、永不部署)+官方部署延後——playtest 出現 symmetric NAT/CGNAT 連線障礙才需要;屆時維護者以「Use this template」產生部署 repo(GitHub 不允許同帳號 fork 自身 repo)、與社群自架同一條路=自架指南由官方持續 dogfood。未部署期間:client iceServers 首項空缺、STUN 直接 Google 保底(官方 TURN 上線隨 client patch 加回首位);官方 signaling 不設 TURN_SHARED_SECRET、/turn-token 停用(自架既有規則、官方適用明文化)。
討論脈絡(UDP 疑慮結論):TURN relay 需公網 UDP range 不能過 ingress(hostNetwork)——但 range 平時無 socket 在聽、allocation 需 token 認證、coturn 權限模型只收授權對端、防內網跳板=denied-peer-ip 安全必開(spec §3 既有、無缺口);建議路線=初期不架(Google STUN 保底足以覆蓋多數 NAT)、要架放獨立 VPS 不動個人伺服器。
跨 6 檔:open-4wd-turn.md(檔頭模型行+§5 改「CI(公版)與 CD(部署 repo)」+§7 官方同路首條+§8 client 耦合列)/部署資訊.md §4.3/open-4wd-signaling.md §5 注意(官方亦同句)/signaling-service.md §6 iceServers 註解/程式架構.md §11 TURN 列。
2026-07-06 ─ 鏈身分信任根+經濟壞損復原階梯明文化(使用者問「怎麼辨識這是專案的鏈/經濟壞掉能否從好點分支」;中2細項1+追補細項1、跨 10 檔)¶
決策檔:D-20260706-05
背景:使用者兩問——①怎麼辨識某條鏈是本專案的鏈、可否偽造;②經濟壞掉能否修好機制後從未壞點分支續行。盤點發現架構上三層信任鏈(client 出貨錨/檢查點簽章鏈/事件層)與「修法+重算」能力皆已存在但均為隱含、無明文;鏈重生零著墨(部署資訊 §13 災難表只有基建災難)。
細項1 鏈身分信任根:新 資料系統 §1.1——「本專案的鏈」=client build 內建錨(LEDGER_DB_ADDRESS 位址錨=DB manifest CID 純內容派生不含域名〔部署資訊 §8.3 CI 不變式既有〕+genesis governanceSigners 治理錨),驗證鏈=位址→genesis signer set→檢查點多簽鏈(逐代 prevEpoch quorum)→log head→事件簽章+全網重算;信任根收斂於官方 build(開源+PR/CI+SRI §5)。新常數 LEDGER_DB_ADDRESS(build 注入)掛 程式參數表 §5;資安規範 §11.3 表補 client 出貨信任根列(首列)。偽造面結論:改史(hash-linked)/假檢查點(需 2/3+1 signer 鑰)/平行假鏈(位址不同 client 不連)全被錨鎖死;殘餘風險=eclipse 遮蔽——只能使人晚看到、不能使人看到假的(既有四緩解+settlement 新鮮度錨)。
中1 修法+全網重算(免分叉修復):經濟系統 §2.1 補「事件不可篡改 ≠ 解讀不可修正」復原階梯三級——①參數壞損=治理緊急回滾(既有 §7)②規則壞損=修正隨 derive_logic major 出貨(強制升級+配對互擋)+全網重算、毒害在重算中消失;生效切點=鏈上事件錨(帳本檢查點 CID/事件位置、隨版寫死、禁 wall-clock 護 deriveStateAt 純函數→規則 epoch 化、與 economy_config 分代適用同哲學);政策=預設帶切點既往不咎、僅 exploit 所得顯著失衡時允許追溯(使用者核);切點+追溯範圍=升版 PR 必載欄位(升版流程 §8.2 新 bullet)③帳本壞損→鏈重生。版本規範 §2 derive_logic_version 列+治理事件流程 §7 各補指標。
中2 鏈重生(最後手段):新 資料系統 §19(原 §19 對應檔案→§20;入站引用全 corpus 0 筆確認後重編)——以最後良好帳本檢查點為新鏈起點:治理 quorum 議決切點+公告(不寫舊鏈事件)→新 OrbitDB log(新位址)、genesis 內嵌 initialStateCid=切點 derived_state_cid→client major 出貨新 LEDGER_DB_ADDRESS 收斂全網(舊鏈 pinning 封存不再收件)→derive 自 initialStateCid 起算(與 syncFromCheckpoint 同型——「檢查點+後續事件」本就是自足單位、檢查點前事件本可裁剪 §8)。保留=餘額/信譽/UGC 註冊/fork 血緣/cold CID map(derived state 即全部帳目、IPFS 內容不受影響);消失=切點後事件(含進行中仲裁案/similarity-pending/未入帳結算,公告重跑)。部署資訊 §13 災難表補 2 列(經濟機制壞損/帳本壞損);ledger.md §3 補「檢查點兼鏈重生錨」。
跨 10 檔:資料系統(新 §1.1+新 §19+§17 補列+對應檔案→§20)/程式參數表 §5/資安規範 §11.3+§14/經濟系統 §2.1/版本規範 §2/升版流程 §8.2/治理事件流程 §7/部署資訊 §13/ledger.md §3+§11/interfaces.md §5。
同日追補+落地複審(細項1+修 5、+1 檔):使用者追問「fork 專案原樣部署在自己 GitHub Pages=另一條鏈?」→ 答案=同一條鏈(位址/genesis/端點全在 build 內容、與 origin 無關——域名遷移不變式的直接推論;bootstrap 清單更是執行期抓官方 repo raw;改 ledger 位址才是平行宇宙、MIT 允許且與官方鏈互不相通);照出 資安規範 §14 玩家教育缺口→補「從官方網址取得遊戲;鏡像站可連同一網路、但輸入助記詞=金鑰安全交給該發布者」條(使用者核)。複審修 5:①經濟 §2.1 追溯 scope 釘死(僅及規則 bug 下的不當所得、合法既得權益保護〔不回收各條/黑名單歷史 royalty〕不受影響——排除與 moderation.md「幣永遠可能被回收」哲學的表面矛盾)②資料系統 §19 補 initialStateCid=出身證明句(新鏈可驗證繼承舊鏈多簽信任、非憑空 genesis)③資料系統 §17 Determinism 表補「derive 規則變更」列(同 major 同規則+鏈上錨切點、禁 wall-clock——§15.1「跨 peer 一致」的跨版前提補完)④interfaces.md ledgerName→ledgerAddress(孤欄、企劃/ 無其他消費者;綁 LEDGER_DB_ADDRESS 註記)⑤open() 連線目標註記 ×2(ledger.md §11+interfaces.md §5 鏡像同步)。評估不動:版本規範 §2 六欄位表不加位址列(位址非版本欄位、major 規則已兩處權威、避免第三鏡像面);moderation.md 不回收條文不動(黑名單路線語境、§2.1 scope 註已調和)。查核乾淨:新增 §-引用全解析、資料系統 §19 重編入站 0、ledgerName 企劃/ 0 殘留、「鏈重生/信任根/initialStateCid」用語單一權威。
2026-07-06 ─ 被動武器加持定案(使用者三因子模型;擱置項出清、跨 8 檔)¶
決策檔:D-20260706-06
背景:其他.md §4 擱置項(passive 補償機制)由使用者提出模型定案。canon 早有預留接口(建模參數表 §3.7 blockquote:passive kinetic_ratio 佔位值「保留為未來加持強度、GLB 無須重上鏈」)——本次轉正。
模型(使用者定、三因子):效果% = kinetic_ratio ×(分配值)× K_PASSIVE_EFFECT_MAX_PCT / 10000(X100 整數、整除截斷)——①外層總量=chip weapon 槽 kinetic_ratio(上鏈鎖死、計入全 chip ≤100% 預算=加持與技能能量競爭同一預算)②分配值=passive_weight_split_pct(0–100、預設 50、組裝層設定):減重 vs 損壞抗性兩效果同預算競爭(例 kr=100、split 77/23 → 減重 23.1%+抗性 6.9%)③封頂=K_PASSIVE_EFFECT_MAX_PCT = 30(初估、進待校準清單)。含耐熱(使用者核):抗性=fatigue 累積與熱流入打折、thermal_limit 本身不變(升溫變慢、閾值語意不動)——不含耐熱會讓熱系武器成 passive 絕對剋星+熱場地過度懲罰單流派。僅及 passive 武器零件自身:chip/motor/battery 熱模型零改動(殺手鐧不稀釋)、抗性不改對外輸出。靜態係數:組裝/實例化套用、非 runtime 變動(不踩「runtime 改 mass」紅線——W01 被拒的是賽中觸發改 mass)。二階 tradeoff=物理自然湧現(壓減重→撞角動量變小;壓抗性→重)。
split 住組裝層(三選一裁定):零 schema 變更(守住「無須重上鏈」、連新欄位都不加)+同一武器每車可異配(UGC 重用)+進 LoadoutSubmission 簽章(loadoutHash 涵蓋)deterministic ✓;對比=武器 extras 定死會催生同模型多 CID、chip 欄位語意錯位。連帶修訂「組裝不調參數」原則:改「不設定零件參數;唯一組裝層調校值=passive_weight_split_pct(不覆蓋零件本體)」。整車 50–500g 以加持後有效質量檢核。驗證=值域 0–100 整數+weapon 為 null/active 帶值即拒(儲存與 LoadoutSubmission 同規則)。
漏洞盤點(設計時封掉):負/零質量(%方案免疫、絕對值方案的洞——百分比勝出主因之一,另=UGC 尺寸不可預知無法用絕對值平衡+整數 pct 慣例現成+基底=材質表 canon 值不可灌)/體積灌水(%-of-self 不獎勵體積、AABB+密度比 50:1+watertight 既有閘)/fluid sub-mesh density 計入 mass 無特例/全車不可破壞疊加(全車 1 武器+chip 唯一=無疊加向量)。
跨 9 檔:算式表 §3(公式權威+:58 佔位值句轉正)/零件與場景 §9.1(機制本體、擱置 blockquote 出清)/建模參數表 §3.7(預留句轉正)/車輛組裝(§2 loadout 欄位+:53 原則修訂+§3.4 有效質量+新 §3.5+§8 UI 滑桿步驟)/程式參數表(K 族新常數)/builtin-assets.md(VehicleLoadout.passiveWeightSplitPct?)/matchmaking.md(validate step 6 補 split)/比賽進行流程 §1.3(驗證表半句)/其他.md(§4 刪除〔末節零重編號、待辦索引現況 3 節〕+§2 補常數行)。grep:佔位值/其他.md §4/擱置 passive 相關全 corpus 0 殘留。
同日落地複審(補 3):①§3.4「整車最重/最輕零件質量比 ≤ 50:1」補同以有效質量計(與總質量同一次求和——減重後 passive 可能成最輕件、影響比值,須明文)②matchmaking validateLoadoutSubmission step 6 註解補 split 值域/passive-only(impl 權威側鏡像)③算式表靜態係數註補「有效質量進入整車總質量/質量比/重心/慣量計算、GLB extras mass_g 原始值不動」(慣量面明文化)。查核乾淨:physics-engine/interfaces 無 loadout 質量鏡像需求、UGC卡片零件質量=零件本體原始值(加持屬組裝層、卡片不受影響)、本機測試資產與 Bot 練習走同一 loadout 機制自然涵蓋。