跳轉到

歷史記錄 · 2026-08-12

月份索引歷史記錄

重大重構里程碑

2026-08-12 ─ 首頁專案時間線與自適應歷史壓縮

規格站首頁新增由每日歷史生成的專案沿革。每日條目以可選的隱藏 marker 表示是否進入首頁; 未入選條目與 ADR 不補空 importance 欄位。首批 12 筆依專案身份、階段、核心架構與公開營運 邊界篩選,從 2026-04-28 的最早可稽核企劃基線一路呈現至首次公開發布鏈定案。

超過 12 筆後,生成器依最早至最晚標記日期的總跨度,逐步改採月、季、半年或年度 bucket; importance 5、全域最早與最新事件永久保留。首頁只存 managed block,不另建沿革頁或 JSON 登錄檔;呈現採無 JavaScript 的 responsive roadbook。

決策檔:D-20260812-01

2026-08-12 ─ 觀戰 deterministic replay 與精簡 fallback

觀戰主資料面由 10Hz 全量 presentation 快照改為唯讀、非權威 deterministic replay:觀戰端以 相同世界描述、已簽 input、週期 checksum 與按需 SavedState 重建同一場比賽,並共用參賽端的 world builder、renderer 與 HUD 派生。版本不符或裝置能力不足時才降級為有界精簡快照。

不採固定播放延遲;2–6 幀 buffer 只吸收網路抖動。displayName 改由觀戰端依 PeerId 解析, fallback 正面表列公開呈現欄位,加入拒因補齊 wrong-password

同輪完成 replay 呈現收口:觀戰端沿用共用 mapper/回合規則本地導出速度、馬達音高、碰撞與 武器音效、小地圖及回合摘要;移除從未有生產者的 race-event。起跑倒數因 readiness 使 descriptor 到達時點不固定,保留低頻、非權威 countdown 控制;UI 明示建立世界、等待 checkpoint、追趕、live 或 reduced,不再顯示含糊的 snapshot 接收狀態。

決策檔:D-20260812-02

2026-08-12 ─ 賽前協議窗改用絕對 deadline

loadout 提交窗與 race-ready stall/resend 不再把相對 setTimeout 當協議時鐘;兩者保存注入的 單調時鐘 deadline,timer callback 只重算剩餘時間。瀏覽器回前景時由 RaceSession 單一 visibility 訂閱 fan-out,立即定案已逾期的提交/stall,或對已到期 resend 補送一次,不形成 追趕 burst。賽內 rollback 的背景恢復判定仍沿用同一事件來源,物理幀與結算時序未改。

決策檔:D-20260802-02

2026-08-12 ─ signaling session 關閉傳播與重連

WebSocket closeerror 現在會經 SignalingSession 與 mux liveness contract 向 room dialer 傳播。dialer 原子停用 dead session、釋放舊 transport,重跑原先設定的 provider chain,並把 替代 session 綁回同一個 room presence 與 participant/spectator 撥號入口;重連期間所有握手 操作明確回 offline,不再靜默送進已關閉 socket。同時只允許一個重連,回前景可補試一次; 離房、明示 close/dispose 與延遲完成的舊重連都不會重新掛回。

決策檔:D-20260724-01

2026-08-12 ─ 公開房公告 lease 抗背景節流

公開房 announcement 與 member presence 保留 30 秒名目刷新,但 lease 從沒有節流餘裕的 60 秒 調整為 120 秒,足以跨過一分鐘級背景 timer 喚醒的一次漏拍與網路延遲,同時維持 300 秒接收 硬上限,避免 crash 房長期滯留。刷新以絕對 nextRefreshAt 判定,延遲 callback 只補一次; 頁面回 visible 時立即發布最新 room snapshot,離房則解除 lifecycle 訂閱並照常發 close/left。

決策檔:D-20260802-08

2026-08-12 ─ AudioContext 可重入恢復

音訊的「曾取得使用者手勢」不再和 AudioContext 當下是否 running 共用一個布林閂。SFX 與 world context 在 suspended-running-suspended 流程可再次 resume;真引擎先檢查 state 並以 single-flight 合流,running/closed 不做事,失敗則留待下一次手勢。全域 pointerdown 不再 once-only,頁面回 visible 時只重試已解鎖 context,不重建或重播 BGM。

決策檔:D-20260704-01

2026-08-12 ─ 跟車偏好 page lifecycle 收口

RacePage 在 pagehidefreeze 或轉為 hidden 時會取消跟車距離 debounce,立即啟動 best-effort 本機寫入;頁面銷毀時移除全部 lifecycle listener。gamepad 取樣在 visibility 切換 時重設基準,單次 elapsed 再夾到 250ms,長時間背景停頓不會在第一幀被當成持續推桿而把距離 瞬間跳到 0.30m/2.00m 邊界。

決策檔:D-20260810-01

2026-08-12 ─ 本機安全事件記錄與去識別匯出

sanitize Worker/editor admission 拒收、P2P 驗章拒絕與 CSP violation 現在接入同一個 app-scope 記憶體環形記錄。資料在寫入時即依事件類型正面表列;payload、signature、PeerId、未知欄位與 URL path/query/fragment 不會先落地,CSP URL 最多留下 origin 或 scheme。

設定頁維護區可由玩家主動下載版本化 JSON;記錄不持久化、重新整理即清空,亦沒有自動 telemetry 或遠端 transport。匯出使用同一份已去識別 snapshot,不額外蒐集裝置或環境資訊。

決策檔:D-20260812-03

2026-08-12 ─ 玩家安全與隱私必要揭露補齊

登入頁在可能輸入備份碼前警告第三方 client 風險;設定頁隱私分類固定列出第三方部署、P2P 直連 IP 可見性與聊天簽章證據三項告知;說明頁新增完整文章供日後回查。IP 文案明確區分直連與 實際 TURN relay,不把「有設定 TURN」誤寫成一律隱藏位址。

玩家介面沿用各語系既有的備份碼/backup phrase 名稱,BIP39「助記詞」只作技術文件術語; 告知不增加每場重複確認或遊戲流程阻擋。

2026-08-12 ─ CSP 逐頁雜湊與不安全請求升級

production prerender 後不再以靜態常數描述 CSP;生成器逐份 HTML 計算 inline import map、JSON-LD 與必要 handler 的 SHA-256。script-src 不使用 unsafe-inline,只有頁面確實含 inline handler 時 才加入 unsafe-hashes 與對應 hash。

固定 baseline 補回 upgrade-insecure-requests。專案所用 Chromium 實測 localhost 仍保留 HTTP 請求,因此不需要為本機 production smoke 犧牲正式站的縱深防禦;meta CSP 的 frame-ancestors 限制與 connect-src scheme 級節點選擇權維持不變。

決策檔:D-20260812-04

2026-08-12 ─ 首發前 Wire 與 Ledger 欄位必填化

尚未發布階段不再替不存在的舊 producer 保留 optional:RoomStateWire.spectatorsspectatorSources 成對必填,participant source 只接受 host 權威配置明確指向自己的觀戰連線; 缺欄不再退回空名冊或本機選舉。

RoundResult.endReason 同步在主程式、Ledger admission、正式 MatchSummary 與 pinning vendor 設為必填並納入多簽內容。deterministic replay 的精簡 presentation fallback 與語意性選填的 disallowChip 不受影響,也不建立不存在的 production migration。

決策檔:D-20260812-05

2026-08-12 ─ 治理信任根與比賽傳輸契約單一化

Ledger 不再接受 getSignerSet option 另行注入治理 signer。首個 checkpoint 只讀 genesis EconomyConfig.governanceSigners,後續只讀前一個已採納 checkpoint 的 derived state;pinning 部署的 GOVERNANCE_SIGNERS 會在啟動時寫入 genesis,空集合維持 fail-closed。

比賽同步的 NetworkLayer.broadcast 與定向 RaceWirePort.sendRaceTo 同步收斂為必回傳 booleanfalse 明確代表未交付並保留重試/correlation 狀態,測試 stub 不再以 void 假裝成功;best-effort fanout sendRacevoid 契約不變。

決策檔:D-20260812-06

2026-08-12 ─ i18n 使用面 strict gate

決策檔:D-20260811-18

四語系字典完成缺 key 與零引用 key 清理後,CI 除了既有 locale-to-locale schema 驗證, 也會以 strict 模式掃描 production TypeScript/HTML 的實際使用面。靜態 key、樣板與加號動態 前綴、registry 宣告前綴及 ICU 參數集合都有 fixture;任何缺字典或 dead translation 會直接失敗。

2026-08-12 ─ UI 錯誤翻譯鍵命名收斂

頁面、共享領域與共用控制項仍保留各自合理的 namespace;不為單一 root 犧牲跨頁重用。 UI-facing reject key 則統一為 errors.<domain>.<reason>:garage、rating、submit 與 spectator 共 28 個鍵及其 producer/consumer 已原子遷移,翻譯文字與產品行為不變。taxonomy regression 現在同時掃產品字面與四語系字典,避免平行 domain.reject.* 再次出現。

2026-08-12 ─ 觀戰相機跨裝置快捷鍵接線

外部觀戰者與本回合已淘汰玩家現在共用同一組 camera action:C 切換自由/巡禮,手把 LBRB 與畫面左/右緣循環上一/下一個固定 roster 目標。手把採 rising-edge,鍵盤在 文字輸入焦點內停用;仍在比賽的 participant 不攔截這些快捷鍵。四語系提示收進現行 pages.race.camera 命名空間,不復活已移除 WatchPage 的死鍵。

2026-08-12 ─ 建房前場地容量閉環

Race Config 的場地選項現在攜帶 canonical GLB root extras 的 auto_player_max,逐回合取最小值; 設定人數超額時立即顯示四語系拒因並停用建房。未解析或非法容量維持 fail closed,正式 matchmaking provider 在進入 room service 前以同一資料重驗,房間則繼續以已驗證的 maxPlayers 原子限制同時 admission。舊 loadoutMissing 沒有獨立 producer,且與既有 carRequiredonChainCarRequiredresourcesUnresolved 重疊,因此不建立平行分支。

2026-08-12 ─ 淘汰轉觀戰的 hold 輸入釋放

RacePage 現在統一追蹤已送入 session、尚未 release 的鍵盤與指標技能槽。玩家從參賽切成 本回合淘汰時會一次 flush 全部槽位,讓 RaceLoop 停止 hold tick 並清掉 HUD active;淘汰後只 拒絕新的 press,必要的 release 仍可通過。blur 與後到的 keyup/pointerup 共用同一冪等路徑, 下一回合恢復參賽時也不會殘留鍵盤 auto-repeat latch。

2026-08-12 ─ 賽中聊天連線狀態可見化

RacePage 的 participant 與 spectator chat 現在共用 idle/connecting/ready/unavailable/error 狀態機;連線中、能力不可用與加入失敗不再顯示成空白面板,error 可 single-flight 重試。 route 或角色切換後的過期成功會立即 leave,Promise rejection 也會收斂成可見錯誤而非 unhandled rejection。RoomPage 同步改用共享 chat.connection.* 四語系文案,不建立已移除 WatchPage 或 RacePage 的平行命名空間。

2026-08-12 ─ 共用聊天送出回饋閉環

O4ChatPanel 現在顯示 trim 後即時字數與 500 字上限,空白禁用、超限 inline 提示。送出改為 single-flight 等待 handle Result:成功且草稿未被玩家改寫才清空;限速與一般傳輸失敗都保留 草稿並顯示共享四語系安全文案,Promise rejection 不再成為 unhandled rejection,也不會把 provider 內部錯誤直接呈現。收端的驗章、封鎖與畸形訊息拒絕仍維持靜默。

2026-08-12 ─ 常數與追溯閘的 CI 現況誠實化

程式參數表不再把本機可執行的 check:constantscheck:trace 寫成已部署的 live CI 保證。 現況明列為完整 workspace 的本機硬閘;主 repo CI 尚未取得 immutable specs checkout,也尚未 呼叫兩支檢查。後續由 open-4wd-workflow #000062 隨跨 repo checkout 接線,完成時再同批把 canonical 措辭更新為 CI 強制,避免規格先行承諾不存在的執法。

2026-08-12 ─ 主題降級原因在設定頁可見

設定頁主題區現在讀取 ThemeService 的單一 fallbackReason,分別以四語系安全文案呈現主題 查無、已退役與資源載入失敗;啟動時既有失敗與頁內切換/重設失敗使用同一警告。成功套用 任一主題後會清除警告,既有 persisted themeId、自癒與目前可用主題保留規則不變。

2026-08-12 ─ 宣告註解治理拆批與常數群規則

exported API 與 private declaration 現在採同一自足用途註解要求;相鄰且同一語意邊界的 exported 常數允許由一則群組 TSDoc 涵蓋,避免逐列名稱重述。現有缺口依責任域拆成八批, 各批都以路徑內歸零驗收,不使用 baseline 或豁免;全部清零後才將 strict checker 接入硬閘。

2026-08-12 ─ 重複碼量測與分階段零容忍(issue 000389)

決策檔:D-20260812-07

跨檔 clone detector 採精確鎖版 jscpd,不以 npx 動態下載;production/tests 分開量測, generated、vendor、fixture、specs 與特殊證據面明確排除。Production 先 report-only 完成分類與 清理,再啟用 threshold 0;tests 維持 report-only,不建立債務 baseline,也不為數字抽掉測試意圖。