動作
Feature #365
進行中
SC
ARCH-1 Stage B 演算法細化實作批:A-06 單一記錄源修復+C3/C5/C2 分桶改良+_match_event_day range-overlap+devil F1~F4 修復(331 測試綠)
Feature #365:
ARCH-1 Stage B 演算法細化實作批:A-06 單一記錄源修復+C3/C5/C2 分桶改良+_match_event_day range-overlap+devil F1~F4 修復(331 測試綠)
狀態:
New
優先權:
Normal
被分派者:
-
開始日期:
2026-07-13
完成日期:
完成比例:
0%
預估工時:
概述
ARCH-1 Stage B 演算法細化實作批(A-06/2/C2/_match_event_day)+ devil 挑戰修復收口¶
背景¶
前批(Feature #361)完成 ARCH-1 Stage B 收口裁定:1~5 全數 結構裁定、C2 升 、EventNode 檔期語義定案(data-model §6 event),並由 qa 揪出 A1-B0-A-06 雙記錄真 bug(規格已收口、實作待補)。本批為對應的工程實作批(「同動 _match_event_day 者合併」),規格依據=architecture.md「ARCH-1 Stage B 節點→Day 地理分桶實作收口裁定」全段。
前置:system-architect 複驗 tree/adr adr-004(決策 3 子規格追記)與 adr-007(Gap-1~4 追記)兩 pending 節點,判定符合 ADR 本文原意,verification_status 已翻轉 verified。
變更內容¶
T1:A1-B0-A-06 雙記錄修復(單一記錄源裁定落地)¶
-
run_stage_b改以pending_forced暫存 anchor 強制歸屬候選,確認owned_days非空後才產出AnchorForcedAssignment——消除「已歸屬」與unassigned矛盾雙記錄。 - 新增
DestinationOwnedDaysMissingDiagnostic(frozen dataclass,非 persist):「Destination 有節點卻無 owned_days」違反 Stage A I-17 不變式時顯式 surface(比照GAP_DAYS_STRUCTURE_ERROR風格),對所有節點型別成立。
T2:2 分段判準改良(devil C3/C5)¶
-
C3:缺座標節點不再固定附鏈尾,改
_distribute_round_robin依 node_id 字典序循環分配(實作期裁定:round-robin 優於兩端交替)。 - 附帶實測發現:devil C3 場景經
run_stage_b端到端不可達(缺座標節點於_assign_destination前置過濾即落missing_coords),本修復屬防禦性/前瞻性,已於 specs 補註避免誤讀。 -
C5:新增
_split_chain_by_gap——均分基準線 ±window 內搜最大距離缺口為切點(gap 優先+段大小平衡組合;gap 比較 round 6 位消浮點雜訊)。均勻分布下退化為舊均分行為,既有測試 0 修改。
T3:C2 造訪次序感知分配(門戶城市來回訪)¶
- 新增
_detect_duplicate_coordinate_groups(lat/lng round 5 位分組);同座標重複 Destination 並列時不再「恆定較小 index 勝」,改依 node_id 字典序group_indices[j % k]輪流分配(方案②;方案①因 orchestration 層尚不存在無從落地)。 - 主場景驗收:門戶城市抵達日/離開日兩次造訪皆分得節點,第二次不被結構性掏空;容量壓制維持 Stage E 職責(Stage B 不消費
TRANSIT_DAY_CAP,qa grep 核實)。
T4:_match_event_day 檔期 range-overlap 改造(4/C8+§6 event 定案)¶
- 匹配改
start.date() <= 候選日 <= end.date()(end=None/end<start 防禦退化單日);檔期與旅程完全不重疊 → 顯式排除不靜默落日。 - 新增
_select_event_day擇日優先序:booking_slot(前向相容 Q17,現行 schema 不可觸發)→ 地理相容最早日 → 整體最早日。 - 新增
EventGeoMismatchWarning非阻擋診斷(geo 可得且超距時警告、不否決日期配對)。
5 前置條件釐清(data-integration-engineer 調查)¶
- orchestration 層目前不存在、無 geocoding 前置 gate 明文;且 serializer 無條件剔除 Destination.lat/lng → 重載存檔行程時「全缺座標」為常態路徑。
- architect 裁定:呈現層轉譯為必要契約不可省略,採防禦深度(best-effort 前置 gate+呈現層轉譯雙做),已追記 architecture.md 5。
- 附帶發現:serializer 對 Destination.lat/lng 無條件剔除 vs node GeoRef ≤30 天快取保留不一致——architect 定性為實作缺口(data-model DM-S1 規格無歧義,Destination 與 GeoRef 同規則),修復另開任務追蹤,不併本批。
devil-advocate 挑戰(D1D9)與修復批(F1F4)¶
- 報告:
docs/research/devil-advocate/2026-07-13_stage-b-refinement-challenge.md。結論:無致命項,qa 簽核維持有效。 -
F1(D1):
_split_chain_by_gapdocstring 誠實補註失效邊界(懸殊簇分布時退化近似純均分),演算法不動。 -
F2(D2):新增
EventDayAmbiguousMultiDestinationWarning非阻擋診斷——EventNode 缺 geo 且重疊集跨多 Destination 時觸發,補「安全網與失敗場景共用缺 geo 前提」的結構性空洞。 - F3(D7-b):owned_days 空+anchor/一般混合批次明確斷言測試。
-
F4(D8,本批唯一動演算法邏輯的修復):
_assign_destination並列判準由浮點精確相等改為「最近候選所屬重複座標群組 ∩ 半徑內候選」——與 round 5 位分組容差對齊,消除 C2 輪流分配對微差座標的靜默死路徑(qa 核實修復前該測試必然失敗)。 - 排下一棒(優先序):D4(anchor 超距 fallback 未套 C2 輪流,Band 0 公平性劣於一般節點;併業主複核清單與「來回訪頻率」合併詢問)> D9(多筆長檔期 EventNode 系統性堆積最早日)> D5(診斷補 anchor 子集欄位)> D3/D6(記錄不阻擋)。
規格與治理落檔¶
- architecture.md:「實作期裁定追記(2026-07-12)」+「devil 挑戰修復追記(2026-07-13)」兩子塊(system-architect)。
- test-plan-ARCH-1-core.md:「qa 對照簽核追記(2026-07-12)」+「qa 修復批複核追記(2026-07-13)」(qa 產出、architect 依寫入矩陣代落檔);錨點 A1-B0-A-06/N-13/N-14/A-07 升「已實作(qa 核實通過)」。
- tree/adr:adr-004、adr-007 追記範圍複驗通過,
verification_status→ verified(主協調者翻轉)。 - 全批維持 、無任何項目升 、不開新 ADR、不新增 constraint;Stage B 維持「架構已設計+L2 實作()」、ARCH-1 整體維持 。
驗收標準¶
-
tests/test_stage_b.py33 → 54 條(工程 12+qa 3+修復批 6),全綠 -
全套
python -m pytest -q→ 331 passed,exit code 0(主協調者親測;qa 獨立複測一致) - A-06 單一記錄源互斥性有明確斷言(不雙記錄+I-17 結構性診斷)
- 門戶城市來回訪主場景:兩次造訪皆分得節點(A1-B0-A-07)
- range-overlap 語義:完全不重疊顯式排除、既有單日回歸測試連動更新(A1-B0-N-14)
- 非阻擋診斷不否決日期配對(A1-B0-N-13+F2 正負向)
- qa 兩輪簽核(對照簽核+修復批複核)均通過,附機械證據
- devil 挑戰無致命項;F4 修復經「修復前必然失敗」因果驗證
備註¶
- 測試指令:
python -m pytest -q(conda envTravel_helper)→331 passed,exit 0。 - 遺留追蹤:serializer Destination.lat/lng 30 天快取不一致(實作缺口,另開任務);D4/D5/D9 排下一棒;Q17 真實命中率待 Tiqets key;PAGINATION_HARD_CAP 二分逼近屬 ARCH-2 採集線。
沒有任何資料可供顯示
動作