PickTrip建造術:旗標打開的那一天——行程引擎正式自駕,訂購三大件全數搶回
PickTrip 產品建造筆記:從旅行想法到可預訂行程 · Episode #9 · · PT10M39S
Host · Kai
Summary
dogfooding 第三天,第八集留下的三個懸念一次結清。頭條是行程引擎的自駕旗標正式打開——AI 行程管線 DAG 在 HTTP 與語音兩個入口翻成預設開啟並保留一鍵 kill-switch,等同 0→100% 上線;敢開的底氣來自先補護欄:中文意圖解析修好(天數、全形數字、國籍別名可 ground 不再鬼打牆)、單一環節軟跳過不再中止整趟、confirm 失敗也放行、降級路徑不偽造訂單編號、持久化寫出可用行程結構並拋 feasibility/degrade 橫幅。訂購三大件全數搶回:一次修掉三個 confirm bug(只驗選取子集、五分鐘清道夫釋放卡住的 hold 與幽靈訂單、TWD 低於 Stripe 下限翻成人話),購物車顯示補回真實旅遊日期(根因在前端丟資料)、訂單 attach 改後端伺服器端插入行程項目、eSIM 錢包卡讀對欄位;供應商硬化(DIDA 可達性巡檢、Klook max=0 當無上限哨兵修售完誤判、票券 offerId 以 DB 為準 fail-closed)。第六集 TREK 報告點名的缺口交作業:附件匯入子管線(分類/抽取/關聯+從附件生成行程+併入暫留預訂)把確認信變可編輯行程,前端 PDF 匯入採靈感純資料與整份行程串流雙軌並各補防呆。待辦長出日粒度(三端 dual-read/dual-write、以既有 id 為準合併、iOS 加未知型別 fallback 防全體崩潰);iOS 購買體驗重設計 waves 1-4 上線(毛玻璃搜尋、全域購物車、生命週期統一、QA 修死路與草稿遺失與百倍報價與時區),並埋下旅程夥伴地基(含隱私遮蔽,規格 Notion 搬到 Linear)。貨幣三部曲大結局是虛驚一場——探針證明潛伏非發作(15 筆 DIDA 全 USD 零 mismatch),收掉探針、對齊報價流程,正式從風險清單畢業。大局:Linear 十四張票完成、主線 AI 行程管線重構 P0 到 P8 收官,demo 鏈路靈感匯入到行程到購物車到結帳首次整條跑通。新風險:finalize 掃票 180 秒逾時、offers/quote 過 Cloudflare 502 凍住 Klook、待辦收尾待兩端 client 上線。demo 剩三天。
Transcript
歡迎回到 PickTrip 產品建造筆記。 昨天結尾我留了三個問題:dogfooding 繼續跑,訂購三大件能搶修回來幾件?
那顆自動駕駛的心臟,什麼時候敢把旗標打開? 還有——demo 只剩四天。 今天這三題全部有答案了,而且答案比我原本想的漂亮。
先講最大的一句:那顆自動駕駛的心臟,今天,旗標打開了。
Luna: 打開了? 昨天你還一臉慎重地說「旗標還關著,因為自動駕駛上路前要先過安全檢查」, 一天就敢開?
這個你一定要知道,因為它不是「膽子變大」,是「護欄補完」。 先把事情講簡單:我們那條 AI 行程管線,過去一直靠一個開關擋著, 預設走舊路。
今天這個開關被翻成預設打開——而且是 HTTP 跟語音兩個入口同時翻。 環境變數不設,就走新的自駕管線;
真出事,把它設成關,就是一鍵剎車。 等於這條管線從零,一次切到百分之百上線。
Luna: 一次切到百分之百? 那萬一路上翻車呢?
所以真正關鍵的是,翻旗標之前,這兩天先把每個容易翻車的路口都補了護欄。 第一個路口是「聽不懂人話」。
以前你跟它說「八晚九天」、用全形數字、說「拿台灣護照」, 它會卡住、會無限重問。 這兩天把中文的意圖解析修好了:天數、全形數字、國籍都能落地,
連「ROC」「Taiwanese passport holder」這種別名跟雜訊也能對上, 不再鬼打牆。
Luna: 等一下,這聽起來很小,但其實是自駕最怕的事對吧——它連目的地都聽錯, 後面全盤皆錯。
完全正確。 第二個路口是「一步踩空就熄火」。 以前某一段——比如某家飯店或某班機沒搜到——整條管線可能直接中止。
現在改成「軟跳過」:單一環節沒結果,不會拖垮整趟; 確認步驟採「失敗也放行」,住宿沒解出來就先擺一張佔位卡, 而且降級的路徑絕不會偽造一個訂單編號——你看到的,跟你真的能訂的,
永遠是同一個。 最後,持久化那步真的把「可用的行程結構」寫出來了:分日、 命名、佔位、定位都到位,還把「這趟哪裡降級了、哪裡卡了」拋成看得懂的橫幅。
Luna: 所以「敢開旗標」翻譯成白話,不是變勇敢,是把每一個可能翻車的地方都先立了牌子、 鋪了緩衝。
這我服。 那第二題呢——訂購三大件,昨天第一天全趴,今天搶回幾件?
全回來了。 而且不是一件一件硬補,是一次把三個獨立的結帳 bug 一起修掉。
先講最陰險的那個:以前你購物車裡只要有一項卡住——比如一張過期的機票你根本沒勾——它會把整筆結帳一起擋下來, 害你連旁邊那張 eSIM 都付不了。
現在改成「只驗你真的選的那些」,沒選的過期項目不再牽連付款。
Luna: 這根本是連坐法被廢掉了。 那另外兩個?
第二個,加了一個五分鐘巡邏的清道夫,專門去釋放那些卡住的預留跟「幽靈訂單」——就是那種掛在半空、 佔著位子又結不了帳的殘骸。
第三個很實際:台幣金額如果低於 Stripe 的最低下限, 以前會噴一個看不懂的錯,現在直接翻成一句人話告訴你。
這三個修完,加上購物車顯示也修好了——這個根因其實在前端, 後端明明有回傳行程編號、行程項目跟真實旅遊日期,是網頁層自己丟掉了,
硬寫成「PickTrip 購物車」,現在把真的旅遊日期補回來。
Luna: 我記得昨天你特別立了一條驗收:「單一供應商失敗, 不准影響其他供應商」。 這排修復,是不是就是那條驗收長出來的?
就是它長出來的一整排護欄。 供應商這端這兩天也硬化了:DIDA 加了每十五分鐘的可達性巡檢, Klook 的 webhook 密鑰沒設就開機告警,不讓訂單靜靜卡在 pending。
還修掉一個超好笑的 bug——Klook 有些票把「年齡上限」「人數上限」標成零, 我們的程式老實地讀成「零個人能買」,於是整批票被判成售完。
這次把「零」正確理解成「無上限」的哨兵值,票才重新上得了架。 還有票券的訂單編號改成以資料庫為準,對不上就直接擋下、降級成自行購買, 不硬湊。
Luna: 所以昨天那句「你看到的行程排得再漂亮,最後一哩路按不下去, 就是一本很會講話的旅遊雜誌」——今天這一哩路,總算按得下去了。
按得下去了。 而且訂單綁行程也通了:以前你把一張訂單掛回某趟旅程,行程裡卻是空的; 現在訂單一 attach,後端會在伺服器端直接合成、插入那個行程項目。
iOS 端也接上後端這組新的掛載、卸載接口,把「加入行程卻看不到」那個用戶回報正面解掉。 連 eSIM 的錢包卡都修了——以前適用地區、有效期、資料量全顯示一槓,
現在讀對了欄位,該有的資訊都回來了。
Luna: 好,兩題都答完了。 可是我知道你憋著第三段,你剛剛講「答案比想的漂亮」,肯定不只是修 bug。
這一段我最想講。 還記得第六集嗎? 我們花了一整集把競品 TREK 整台拆開,那份二十幾頁的報告點名我們一個很痛的缺口: TREK 能把一封訂位確認信,自動變成行程、地圖釘、帳本;
我們只能讓你手動上傳。 報告當時給的建議是「把自購上傳,升級成 AI 訂位匯入」。 今天,這份作業交了。
Luna: 交了? 就是那個「確認信丟進去自動變行程」的能力?
對。 後端長出一條三步的子管線——分類、抽取、關聯。 你在對話裡丟進一張票券、一份訂房、一張登機證,它先分類這是什麼, 抽出結構化的線索,再把線索綁到行程裡對應的那個點。
全程「抽不到就明說抽不到」,絕不捏造。 上面再包一個工具,能直接「從附件生成行程」,還有一步專門把你已經預訂、 暫留的東西併進你的旅客檔案。
Luna: 所以第六集我們下的結論——「AI 體驗跟商務閉環, 我們領先一個世代; 但旅程管理的完整度,我們落後」——這一步是把落後那一格補起來。
而且補的方式很 PickTrip。 前端這兩天上了 PDF 匯入,特別的是它是「雙軌」的:同一份 PDF, 看你從哪裡丟進來,走兩條刻意不一樣的路。
從「匯入靈感」丟,它走純資料的路,把一份 PDF 裡的多個景點抽成站內靈感; 從「建立行程」丟,它走串流的路,把整份 Travel Pack 即時串成一整趟完整行程。
兩條路還各自補上防呆——匯入到一半不准重選檔造成打架、串流失敗不准讓轉圈圈永遠轉下去、 離開頁面就中止那個很燒錢的 AI 運算。
Luna: 一份 PDF 分兩條路,這個設計很細。 不是照抄 TREK,是想清楚使用者到底想幹嘛。
那待辦跟 iOS 呢? 昨天你才說三套待辦客戶端合一。
今天它長出了「日」的粒度。 以前待辦掛在整趟行程上,現在能掛到「某一天」。 這件事橫跨三個倉庫一起做:後端讓查詢接口把「某天的待辦」吐出來,
網頁跟 iOS 用一個很聰明的「以既有編號為準」的合併規則, 把新舊兩套待辦疊在一起、還帶墓碑標記處理刪除。
這裡 iOS 補了一刀很關鍵:給待辦型別加了一個「未知就退回預設」的防線——因為只要有一個沒見過的型別, 舊版 App 的解碼會硬崩,會一次弄掛所有已經上線的客戶端。
這是相容性的教科書。
Luna: 一個未知型別能弄掛全部上線的 App,這個防線值錢。 那昨天講的 iOS 購買體驗重設計,今天動工了嗎?
不只動工,第一到第四波都上了。 整個購買流程換上一層毛玻璃的搜尋介面,地點、日曆、人數、 航段、艙等分頁式選;
購物車變成全域的,使用者自己一區、每趟行程各一區,失效的項目會自動重新報價; 還統一了「到期、已用」的購買生命週期。
順手修掉一堆 QA 抓到的蟲:搜尋結果被折疊讀成死路、機票草稿會遺失、 報價差到一百倍、時區顯示錯。
另外還埋下一個更長線的地基——「旅程夥伴」,一個獨立的元件套件, 管快照儲存、時間模型,還特別做了隱私遮蔽。
這個需求的規格,這兩天正式從 Notion 搬到了 Linear, 以後以 Linear 為準。
Luna: 隱私遮蔽這件事你們最近很堅持。 對了,貨幣那條線呢? 第七集埋探針、第八集你給它「收官待驗」,今天驗了沒?
驗了,結局有點反高潮,但很健康——是虛驚一場。 那支探針的任務,是去確認「DIDA 回傳的幣別到底有沒有被我們硬改成美金」。
這兩天答案出來:十五筆搜尋全部回美金、零筆對不上。 所以結論是——這是潛伏、不是發作,不需要動大手術重構匯率。
於是把那支臨時探針收掉,把搜價的邏輯對齊到正式的報價流程, 逐筆用它自己的幣別。
Luna: 所以是白緊張一場? 那第七集那麼慎重埋探針,值得嗎?
值得,而且這正是重點。 這種「虛驚一場」,要用證據換來,不能用「應該沒事」換來。 這跟第八集那句「上線資格要靠真的綠燈掙來,不能靠灰色地帶偷渡」, 是同一個信念的兩面。
我們不是賭它沒事,是查到它沒事。 好,收尾照慣例,先結算大局,再結算風險。 大局這樣看:專案管理板上,這兩天有十四張票標成完成,那條主線大工程——AI 行程管線重構,
從第零階段到第八階段,全部收官。 最重要的是,demo 要 show 的那條鏈路:靈感匯入、 變成行程、丟進購物車、按下結帳——今天第一次,整條可以從頭跑到尾。
Luna: 整條跑通! 那風險清單呢? 昨天可是越結越長。
今天有畢業生了。 貨幣:從「收官待驗」升級成「查明結案」,正式從風險清單畢業。 iOS 可用性:購買體驗重設計整包上線、訂單真的綁上後端行程, 再往上動一格。
訂購三大件:從一張嚇人的大票,變成一排修好的護欄。 但清單不會空,換三張新票進來:一張是行程定稿時掃票券會卡到一百八十秒逾時;
一張比較急——報價接口經過 Cloudflare 會吃到 502, 直接把 Klook 凍住,這是供應商那端剛冒出來的新火;
還有一張是待辦收尾,得等兩端 App 都上線才能驗。
Luna: 所以老火滅了、新火起來,這就是 demo 前的日常。
就是這樣。 但今天我心裡是踏實的:旗標開了、三大件回來了、TREK 的作業也交了。 接下來三天,其實只剩一個問題——把全團隊的真實旅程,從靈感、
排程、購物車,一路按到結帳,這條鏈路今天第一次全綠; 它撐得住 demo 當天,站在台上、有人盯著看的那一刻嗎?
demo,剩三天。
明天同一時間,PickTrip 產品建造筆記,每日更新。
Luna: 掰掰!