生活分享
实战:维护既有专案
建立现况基准,处理一项真实变更,以回归检查和交接纪录交付可追溯成果。
阅读时间约 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 年 9 月核实的东京都住宿税(2027 年 4 月改为 3%)和机场宅急便寄送行李的规则。
- 预算
- 酒店

攻略东京
东京交通票券怎么选:Suica/Welcome Suica、Tokyo Subway Ticket、JR Pass 值不值得买
第一次去东京,每人先用一张 IC 卡按次付费(Welcome Suica 免押金、有效期 28 天)。一天搭四趟以上地铁,再加买 2,000 日元的 Tokyo Subway Ticket 72 小时券;只玩东京、不去关西,买 JR Pass 一定不划算。用决策图比较 TOURIST PASMO、iPhone 里的 Suica、东京 Metro 一日券能搭什么、不能搭什么;价格于 2026 年 9 月核实。
- 交通
- 预算

攻略东京
东京迪士尼乐园、海洋攻略:票价、梦幻泉乡 Fantasy Springs、尊享卡 DPA 与预约等候卡怎么用,第一次去选哪个园区
东京迪士尼一日护照采用浮动票价,2026 年 9 月平日大多为 9,900 日元、周末为 10,900 日元,官网每天 14:00 开售两个月后同一天的门票;免费的优先通行卡已不在官网服务清单,缩短排队时间只剩付费的迪士尼尊享卡(每人每次 1,000 至 3,500 日元)。另有运营时间与 25 周年活动、预约等候卡与报名体验、梦幻泉乡如何进入,以及第一次去选乐园还是海洋;2026 年 9 月通过东京迪士尼度假区官网核实。
- 行程范例
- 亲子
资料来源
- Codex prompting · 查证日期:
- Git worktree guidance · 查证日期: