生活分享
實戰:維護既有專案
建立現況基準,處理一項真實變更,以回歸檢查和交接紀錄交付可追溯成果。
閱讀時間約 15 分鐘 · 操作 30 分鐘

返回 Codex 教學總目錄Codex 學習中心:完整教學目錄從安裝、第一個任務到 MD 規則與進階整合,規劃 60 篇 Codex 教學、十個單元。依程度、平台、需求或指令搜尋下一篇;尚未公開的教學會標示狀態,方便安排學習路線。閱讀全文
目標與起點
本段提到的教學與資源: 練習材料 · 程式地圖先讀懂一個既有專案用唯讀流程找到啟動點、資料流與測試,產生有檔案依據的專案地圖。閱讀全文 · Git 還原Git、分支、diff 與還原Git 保存檔案版本,分支承接一組修改,diff 顯示差異。Codex 可以協助操作,但你仍要確認修改屬於這次任務。聊天紀錄與 Git 歷史不同,恢復舊對話不會自動還原檔案。閱讀全文
步驟 1:記錄基準,不先要求重寫
開啟 maintenance-lab,應只有 index.html、style.css、app.js、core.mjs、core.test.mjs 五份程式檔。先執行 node --test core.test.mjs,預期三項通過,再記下 Node 版本、日期與資料夾。如果不是這個結果,先查是否拿到 start 或 broken,不把既有失敗算在這次重構。將副本納入自己的本機 Git 基準提交,或另存完整 baseline 副本;保存後才開始修改,確保能還原這次改動。
修改前也要建立畫面基準:在此資料夾執行下方「畫面回歸」列出的對應平台預覽命令,使用專供練習的瀏覽器設定檔與來源網址。先確認 Show 為 All tasks 且沒有既存資料;若已有資料,先保存,再選用另一個全新練習設定檔,以空白狀態開始,不直接清除原資料。新增 Read、Build,完成 Read,確認 1 active / 2 total;在瀏覽器開發者工具的 Application/Storage → Local Storage 中,保存 mokaair-codex-todo-v1 的虛構 JSON,包含兩筆 ID 與完成狀態。保留這兩筆資料、網址及瀏覽器設定檔供修改後比對。接著在桌面版開啟 maintenance-lab 並建立任務,或從此資料夾另開的終端機執行 codex,再提交下一步的需求。
請 Codex 唯讀查看 app.js 中更新 #count 的地方,描述統計是全部任務還是篩選後清單。正確基準是全部任務,即使選 Completed,仍顯示所有任務的 active/total。接著確認儲存鍵 mokaair-codex-todo-v1、version 1、ID 與 completed 型別。重構只搬動計數責任,不改資料格式,不新增儲存遷移。這個先讀再改的步驟能避免把看似重複的程式碼合併後改變原本細節。
步驟 2:把範圍寫成可檢查的契約
| 項目 | 本次要求 | 不變條件 |
|---|---|---|
| core.mjs | 新增純函式 countTasks(tasks) | 不修改輸入,不碰 DOM/儲存 |
| app.js | 呼叫 countTasks 更新 #count | 顯示文字與全部任務計數不變 |
| maintenance.test.mjs | 新增計數與不變性案例 | 原 core.test.mjs 保留 |
| HTML/CSS | 本次無修改需要 | 按鈕、版面、焦點樣式維持 |
| 儲存資料 | 不做遷移 | 原 key、version、ID 與狀態保持 |
小範圍不代表不驗收;它讓你能把新的失敗和少數修改連起來。
步驟 3:加入會先失敗的新測試
把下方內容另存為 maintenance.test.mjs,與原測試並列。先跑兩份測試,新函式尚未存在時,新三項會失敗而原三項仍通過;保存這個預期失敗,確認測試真的會因缺少計數函式而報錯。不要因紅色結果就把教材當成壞版本,也不要讓 Codex 刪掉新測試來取得綠色。這裡輸入都符合既有 Task 契約,沒有擅自擴大成任意資料清理工具。
import test from 'node:test';
import assert from 'node:assert/strict';
import * as core from './core.mjs';
test('empty list counts are zero', () => {
assert.deepEqual(core.countTasks([]), { active: 0, total: 0 });
});
test('count all tasks without deduplicating equal titles', () => {
const tasks = [
{ id: 'a', title: 'Read', completed: false },
{ id: 'b', title: 'Read', completed: true },
{ id: 'c', title: 'Build', completed: false },
];
assert.deepEqual(core.countTasks(tasks), { active: 2, total: 3 });
});
test('counting preserves frozen task data and storage compatibility', () => {
const task = Object.freeze({ id: 'a', title: 'Read', completed: true });
const tasks = Object.freeze([task]);
const before = core.encodeTasks(tasks);
assert.deepEqual(core.countTasks(tasks), { active: 0, total: 1 });
assert.equal(core.encodeTasks(tasks), before);
assert.deepEqual(core.decodeTasks(before), tasks);
});
node --test core.test.mjs maintenance.test.mjs
步驟 4:實作並檢查差異
Add countTasks(tasks) to core.mjs, returning {active, total} for the full list.
Use it in app.js when updating #count; keep the existing visible text.
Preserve storage format, key, IDs, task behavior and original tests.
Do not edit index.html, style.css or the new test expectations.
Run node --test core.test.mjs maintenance.test.mjs.
Report changed files, test results and remaining browser verification.
完成後應有六項測試通過。參考核心函式如下,app.js 需匯入它並在 render 裡先對 tasks 計數,再組出與原本相同的文字。特別檢查是否誤傳 shown,也就是目前篩選結果;那會讓 Completed 頁面錯顯示總數。查看 git diff 或編輯器差異,原測試、HTML、CSS、儲存讀寫不應被改動。純函式的測試綠色,不能取代這個接線檢查。
export function countTasks(tasks) {
return {
active: tasks.filter((task) => !task.completed).length,
total: tasks.length,
};
}
在 app.js 原有的第一行匯入清單加上 countTasks,保留原六個函式。接著找到 render 中原本寫入 #count.textContent 的那一行,用第二段替換;不要把整個 render 換掉,也不改前面產生 shown 的篩選。以下兩段只是指定位置的片段,不是完整 app.js。
import { countTasks, addTask, toggleTask, removeTask, visibleTasks, decodeTasks, encodeTasks } from "./core.mjs";
const counts = countTasks(tasks);
document.querySelector("#count").textContent = `${counts.active} active / ${counts.total} total`;
檢查這裡的參數確實是 tasks。只有 Read 完成、Build 未完成時,Completed 的 shown 只有一筆;若誤傳 shown,會得到 0 active / 1 total,而正確畫面應仍為 1 active / 2 total。核心六項測試只驗 countTasks 的函式契約,仍可能全部通過,所以保留這個獨立的接線與畫面核對。
步驟 5:回歸畫面與保存資料
若修改前的同一個練習服務仍在執行,直接重新整理該網址,不另啟動第二個;已停止才使用以下命令。在此資料夾啟動預覽:Windows 執行 py -3 -m http.server 4173 --bind 127.0.0.1;macOS/Linux 執行 python3 -m http.server 4173 --bind 127.0.0.1,瀏覽同一 http://127.0.0.1:4173。若已有人占用,先核對原服務,不直接終止它。在修改前後使用同一來源網址及虛構待辦,避免換連接埠後空白的 localStorage 被誤認為資料遺失。保留修改前建立的 Read、Build,不重設或重複新增;先比對儲存的兩筆 ID 與完成狀態,再依序選 All tasks、Active、Completed,三次統計都必須是 1 active / 2 total。
重新整理確認兩筆資料、ID 與完成狀態保留。先用同一組兩筆資料,在 390px 與桌面寬度各檢查一次篩選與統計;接著選 All tasks,只刪除一次 Read,確認 1 active / 1 total。按 Tab 確認焦點仍可見。這是回歸驗收,不需要新的設計圖。若數字隨篩選改變,就回到 app.js 查函式引數;若純函式本身不對,用新測試的實際失敗案例定位。只有在確實觀察過後才填寫瀏覽器通過,未操作的系統另外標記。
還原與交接
需要撤回時先保存當前差異,再只還原本次改動的 core.mjs、app.js,並移走自己新增的 maintenance.test.mjs;重新執行原本三項測試及統計畫面,應回到原基準。不要用整個專案強制重設來清掉其他人的修改。交接寫明基準、抽出的責任、未變的資料契約、六項測試、實際畫面驗收及還原位置;沒跑的測試不能寫通過。下一個維護需求另列範圍,參考文件交接上下文與工作交接長工作需要把決策與證據留下,不能只依靠對話長度。README 說明怎麼使用專案,設計文件記錄為何這樣做,交接文件整理目前做到哪裡;AGENTS.md 則放持續有效的工作規則,避免把所有進度塞成規則。閱讀全文,不要在這次小重構順便重寫儲存層或更換框架。 完成後在自己的預覽終端機按 Ctrl+C 停止這次服務,保留基準 JSON 與驗收紀錄。
返回 Codex 教學總目錄Codex 學習中心:完整教學目錄從安裝、第一個任務到 MD 規則與進階整合,規劃 60 篇 Codex 教學、十個單元。依程度、平台、需求或指令搜尋下一篇;尚未公開的教學會標示狀態,方便安排學習路線。閱讀全文
閱讀完整文字說明
Three numbered stages: identify the starting point, perform the exercise, and verify the result. Original illustration, not a product screenshot.
同主題延伸閱讀
生活分享
Codex 學習中心:完整教學目錄
從安裝、第一個任務到 MD 規則與進階整合,規劃 60 篇 Codex 教學、十個單元。依程度、平台、需求或指令搜尋下一篇;尚未公開的教學會標示狀態,方便安排學習路線。
生活分享
Worktree 與多任務隔離
Worktree 讓同一個 Git 程式庫有不同的工作目錄,各自承接不同分支。它適合讓兩項工作分開改檔,但資料庫、連接埠與外部服務仍可能共用,不能把檔案隔離當成所有資源隔離。
生活分享
實戰:製作小網站
從 brief.md 規劃並製作 Small Steps 待辦網站,完成新增、完成、刪除、篩選與本機資料保存。將 HTML、CSS、資料函式、畫面事件與測試分開,以 Node 測試和瀏覽器操作驗收,並留下可重新啟動與還原的交接紀錄。
生活分享
用量與效率:減少重工
記錄任務條件、模型選項、時間與成果,找出能減少無效重試和過多上下文的調整。
引用本文的文章
最新旅遊情報攻略

情報
2026 韓國楓葉預測:雪嶽山 10 月 20 日、首爾近郊 10 月底、內藏山與漢拏山 11 月上旬
韓國山林廳 2026 年 9 月 22 日公布的楓紅高峰預測:雪嶽山 10 月 20 日,春川、國立樹木園到首爾植物園落在 10 月 28 日到 11 月 2 日,內藏山 11 月 4 日、漢拏山 11 月 6 日,整體比最近 5 年晚約 0.8 天。整理各地楓樹與銀杏的預測日、首爾出發怎麼排,以及出發前去哪裡看即時楓況。2026 年 10 月查證。
- 季節活動
- 自然
- 觀景

攻略胡志明市
胡志明市到頭頓一日遊:白藤碼頭搭高速船、船票與班次,下船就是胡梅纜車與耶穌基督像
人在胡志明市挪一天去頭頓看海:市中心的白藤高速船碼頭搭船,航程 120 分鐘到頭頓的胡梅碼頭,平日成人 320,000 越南盾、週末 350,000,回程末班平日 15:00。下船就是胡梅纜車站,同一條路上有白宮,小山頂上是耶穌基督像。平日一天只有兩班船,整天要從末班船倒推著排。
- 交通
- 行程範例
- 海灘

攻略沖繩
沖繩不開車攻略:單軌只到浦添,美麗海水族館要坐兩個多小時的巴士,回那霸的最後一班直達車 17:22 就開走
不租車的沖繩怎麼移動:那霸市區靠沖繩都市單軌電車(ゆいレール),那霸機場站到終點てだこ浦西 19 站、17 公里、37 分鐘,一日券 1,000 日圓;美麗海水族館有那霸機場直達的高速巴士,單程 2,000 日圓起、官方時刻表上 2 小時上下,下車後還要走 10 分鐘;古宇利島要在今帰仁村役場轉車,當天來回光坐車就六個半小時;回程的最後一班直達車 17:22 就從記念公園前開走(2026 年 9 月查證)。
- 交通
- 行程範例
- 預算
資料來源
- Codex prompting · 查證日期:
- Git worktree guidance · 查證日期: