# 第 35 课教师讲稿｜让 AI 找到相关代码，然后用证据检查修改

对应 AIPath 第 7 阶段 Cursor 案例，60 分钟。学生将处理一个只有四个文件的原创小项目：合计学习时长，却把没有填写的时长当作了零。主问题是“编程工具找到一段代码以后，怎样知道它找全了必要条件，改动也符合要求？”本课不要求从零背 JavaScript 语法；教师带学生认输入、转换、求和、调用和检查五个动作。

## 学完可以独立做什么

学生能够依据错误现象找到规则、计算函数、调用输入和测试；能够说明代码检索与把整个仓库全读一遍的区别；能够给一个候选修复准备正常、边界及调用兼容的核验记录。实际成果是四文件项目的原始失败、修改差异与测试结果，或浏览器中相同规则下的本地验证记录。拥有已可用 Cursor 的学生可让工具协助阅读和编辑；课堂网页本身不会调用 Cursor。

本课不把 AI 生成了多少行代码当作成绩。学生可以使用工具提出修复，但必须能说清：它从哪里看到了规则，哪些输入以前错了，修改后有没有把本来允许的输入也拒绝。若环境还没有准备好，保留真实完成的浏览器计算，不把安装和登录故障混成算法理解失败。

## 教师课前准备：让课堂时间用在读代码和判断结果

准备已安装可运行的 Node.js，不在这 60 分钟临时下载运行时。把以下四个文件放到同一个自建目录 ai-study-time。这是独立练习目录，不打开学生的真实业务项目：

- [README.md](project/README.md)：规则与操作约定。
- [total.cjs](project/total.cjs)：待修复计算函数。
- [main.cjs](project/main.cjs)：三条示范输入和实际调用。
- [test.cjs](project/test.cjs)：八个固定输入的检查脚本。

教师用自己的终端先运行 node --version，再在练习目录执行 node main.cjs 与 node test.cjs。初始程序故意不符合全部规则，测试出现 FAIL 是预期教学素材，不要课前把它修好。四文件无安装依赖、不联网。终端找不到 node、文件保存成 .cjs.txt 或当前目录不对时，先纠正这一层，不连续让 AI 改代码“修复”环境问题。

同时打开本课“找到时长合计的错误，再检验候选修复”，默认关键词 minutes、原始直接转换版、三条 25、15、空格记录。核心按钮“检索摘录并运行检查”。确认能看到自定义记录、Number 转换示意、八个固定检查三部分，再复位。无 Node 或无 Cursor 的学生直接用本地网页；这仍是真实 JavaScript 运算，但不是实际编辑器检索或 AI 修改。

## 完整任务和四份证据

业务规则写在 README：输入是记录数组，每条 minutes 可以是数字或只含十进制数字的字符串，字符串允许首尾空格。换算后必须为 1 至 480 的整数。空串、全空格、零、负数、小数、布尔值、null、缺字段与非数字字符串拒绝。空数组返回零。历史调用还在传字符串，因此不能随意把接口改成只收数字。

学生必须看到的原函数只有三行：

~~~javascript
function total(rows) {
  return rows.reduce((sum, row) => sum + Number(row.minutes), 0);
}
~~~

逐个给符号贴中文含义：rows 是一叠记录；row 是当前这条；row.minutes 取这一条的时长；Number 尝试转成数字；sum 是目前累计值；末尾 0 是从零开始。reduce 这个名字暂时只需理解成“逐条处理并累计”，不让零基础学生在开头背完整函数式编程定义。

main.cjs 实际给了阅读 25、练习 15、复盘一个空格。规则希望未填写的复盘触发拒绝，不能偷偷计零。test.cjs 把八个事先定义的输入和预期放在一起，既含这次错误，也含本来应该工作的正常情况。README、函数、调用、测试是四种证据，不能用其中一份代替其他三份。

## 0—6 分钟｜先说清“算出 40”为什么可能是错的

教师展示 main 的三条记录，说：“前两条能加成多少，大家都会。第三条没填。你希望程序把它当零，还是提醒数据没填完？生活里两种设计都可能存在，但这次 README 已经给定了规则，我们要检查实现是否服从规则。”学生完成 Q1，先按规则写预期，再猜旧程序实际会怎样。

这里一定先问规则，后看代码。若学生说输出数字就是成功，追问：“这三条里有一条没有合法时长，40 是否表达了全部记录已经有效？它与只提交两条有效记录有什么差别？”让学生在纸上分成“数学合计”和“输入是否合法”两栏。程序有结果，不等于任务要求得到满足。

教师打开 README 标注范围 1—480 和字符串兼容，再打开 total 函数。说：“AI 编程工具也需要这些条件。如果我们只说‘修一下’，它可能修成与原本约定不同的功能。今天我们会把缺陷、边界和验收标准写出来，让建议有可以对照的对象。”

## 6—12 分钟｜从四文件找到一条因果链

请学生按 Q2 在编辑器文件树依次打开 README、total、main、test，写每份文件回答的问题。用编辑器全项目搜索输入 minutes，点击一处函数命中和一处调用命中。没有编辑器时使用页面摘录检索，明确页面只查四段精选文字，并不读取磁盘项目。

教师说：“知道精确名字时，可以按字找；只记得‘合计学习时长’这种意思时，某些工具会用语义检索辅助找相关片段。但找到片段后仍要打开前后文和调用位置。标题再像、相似分数再高，也不能替你证明这就是全部调用。”让学生画出 main 输入 → total 转换累计 → test 比较预期，并把 README 画在旁边作为共同规则。

官方公开证据简要说明即可：Cursor 的[索引工程文章](https://cursor.com/blog/secure-codebase-indexing)介绍了根据内容变化更新索引、按语法切块与形成嵌入表示等做法；[搜索文档](https://cursor.com/docs/agent/tools/search)也提供按名称和文本查找的说明。教师只借此解释“变化检测 → 分块 → 表示与索引 → 查找 → 取回相关上下文”的用途，不宣称课堂四文件检索复现了 Cursor 内部系统。

## 12—18 分钟｜真正运行，找到空格变成零的那一步

具备 Node 的学生在练习目录打开终端，先运行 node main.cjs，保留完整输出，再运行 node test.cjs。教师投影终端时保留输入命令和当前目录，让学生看到输出来自哪个文件。若显示 Cannot find module，先核对目录与文件名；这不证明函数算法错了。

浏览器后备学生点击“检索摘录并运行检查”，保持原始版本。每人抄一个中间过程：原始 minutes 是一个空格字符串，类型是 string，Number 转换显示什么。教师说：“Number 是 JavaScript 的转换规则，不是 AI 读懂了‘没填’。程序没有先按业务规则判空，于是把一个不应参与计算的输入送进了合计。”

运行八个检查后，让学生先数正常、空数组和字符串调用这几项，找出为什么旧程序不是完全不能用，却仍不能交付。此处不要求全班背通过率；更重要的是把 B 空格失败指到具体输入与转换步骤。让学生写 Q3 的错误定位句：“当……输入经过……时，程序……，但 README 要求……。”

## 18—25 分钟｜给 AI 一项清楚的阅读任务

已经有可用 Cursor 的学生通过 File → Open Folder 打开练习目录，进入 Agent 面板。具体界面名称以已安装版本为准；找不到对应面板时用编辑器的命令面板搜索 Agent。先粘贴以下任务，不要求新购订阅，也不往账户里添加付款：

~~~text
这是课堂原创学习时长项目。请先阅读README.md、total.cjs、main.cjs、test.cjs，不修改文件。
问题：main里minutes只有空格，却输出了合计。请指出输入从哪个文件进入，在哪一步被转换，并引用实际文件和函数。
解释规则对空白、数字字符串、整数范围、空数组的要求。列出最小修复计划以及需要保留的正常和边界测试。
没有读取到的文件请明确说明，不推测已经看过整个项目。
~~~

请学生核查输出是否真的引用 total 与 main，有没有把 README 的“数字字符串也允许”漏掉。若工具给的答案没有实际引用，学生自己打开文件补核，不用反复要求“更专业”。没有 Cursor 的学生照这个阅读清单用四文件或本地摘录回答相同问题，并标记人工阅读。

教师继续说：“这里第一步限定阅读，是因为我们正在练定位。读完计划后，下一步会明确让它改具体范围。过程不应停在它说‘可以修’；要看到真实文件差异和测试。”若工具已偏离课程范围去引入数据库、框架或统计模型，使用 Stop 停止当前生成，回到三行求和与输入规则。

## 25—32 分钟｜比较一个很像修好了的候选

教师给出候选逻辑 if (!row.minutes) throw ...，翻译成“如果原始值在 JavaScript 的真假判断中为假，就拒绝”。不要把它说成“字符串没有可见内容”。让学生先预测空格字符串和 0 能否被拦住。随后在网页只把程序版本改为“仅增加真假值判空”，运行并检查 B、C 两行。

教师问：“空格看起来空，字符串长度却不是零。我们用的是哪套规则在判断？”请学生口头区分人的视觉、语言转换规则与本课业务规则。然后比较只判真假值与完整校验版：后者先检查类型、字符串格式，再检查换算后的整数范围，最后才参与求和。

不需要初学者当场发明正则表达式。说明 /^\d+$/ 在本课只用于判断去掉首尾空格后是否全是十进制数字；Number.isInteger 再判断数字是否整数；1 与 480 是业务给定边界。小数、负数、布尔值不能因为能转成某个数就自动被允许。请学生做 Q4，写两个能区分候选的输入，不能只写“多测一下”。

## 32—38 分钟｜实际修改并检查差异

Cursor 路径学生在同一项目提出第二条明确请求：

~~~text
现在执行最小修复。只修改total.cjs中与输入校验有关的代码，保留导出的total名称以及数字、十进制整数字符串两类调用。
按README拒绝空白和非法类型/范围，空数组仍返回0。不要删除或放宽已有八个测试，不安装依赖，不改其他项目。
修改后运行node main.cjs与node test.cjs，报告真实结果和未运行的部分。
~~~

让学生打开文件差异，检查新增校验是否发生在累加之前、函数名字和导出有没有变化、测试预期是否被改成迎合错误。教师按[Cursor 的代码审阅课程](https://cursor.com/learn/reviewing-testing)中可见的差异审阅与测试思路组织检查；实际按钮位置随版本确认，不根据本课网页冒称已操作了产品。

不能实际改文件的学生在网页选择完整校验版运行，读八项结果，填写“浏览器候选逻辑检查已完成；实际项目编辑未完成”。有 Node 但无 AI 工具者可由教师带着人工添加校验，在本课独立目录执行。教师参考修复放在答案区，独立练习仍由新输入检验，不能只复制最终通过截图。

## 38—48 分钟｜独立任务：旧错误之外还能发现什么

给学生 Q5 的新材料，不展示答案。A 为 12 与字符串8两条 minutes；B 为字符串00；C 为首尾有空格的字符串7；D 为 true；E 为缺 minutes 的对象。每题先写规则预期，再把工作纸的完整记录 JSON 放入实验，选择已校验版运行并记录。未修复项目的同学也可以用后备验证，但要写清实际执行位置。

教师巡查只问“哪个规则支持你的预期”“首尾空格和全空格在这题一样吗”“原始类型是什么”。不要提前公布数值或拒绝结论。学生需要选一个失败输入解释阻止它进入合计的检查层；再选一个合法字符串说明为什么不能简单改成只收数字。

后半段发出迁移卡：“另一个调用方仍把 minutes 作为字符串传入；AI 建议把函数改成只收数字，并称目前所见测试都通过。”请学生独立写还需检索哪里，以及怎样证明接口兼容。这里不增加服务器或数据库部署任务；只要求识别没看到的调用证据是待查，不能从一个函数的局部正确直接跳到整个项目安全。

## 48—54 分钟｜讲评与一段可信的修改说明

独立段结束再打开答案。先比较 A、C 与 B、D、E 的规则依据，而不是只报一串结果。教师说：“如果你猜错，但运行后找到了类型、格式或范围中的具体一层，已经形成了可复查的修订。把测试预期直接改成程序输出，反而丢掉了最有价值的差异。”

请学生写 Q6 修改说明：“空格时长原先经 Number 被当零，现在按规则先拒绝无效输入；保留数字字符串调用和空数组；实际执行了……；还未覆盖……。”工具协助的部分如实注明，不把人工候选说成 Cursor 自动生成，也不把八例通过说成适用于所有输入。学生两人互读，检查是否同时有问题、改动、证据和限制。

## 54—60 分钟｜回看索引与代码质量的联系

教师画六格：本地文件变化 → 定位变化部分 → 切分相关片段 → 更新可检索表示 → 按问题取回材料 → 修改与验证。请学生把这节课亲手做过的格子用实线圈出：打开文件、精确搜索、修改、执行检查；未实测的 Cursor 嵌入索引与后台更新用虚线标。讲的是公开流程作用，不拿课堂记录去断言完整产品结构。

问：“如果只改 total，为什么我们仍读 main 和 README？”让学生用字符串调用与空数组规则举例。再问：“八个测试全过以后，接下来的合理工作是什么？”可答保存版本与证据，针对新使用场景补真实需求和相关案例；不必无限新增与任务无关的测试，也不能立即推广成万能数据系统。

最后交付 Q1 预测、四文件角色图、原始失败、候选对比、独立新输入记录与修改说明。实际操作 Cursor 的同学另交真实文件差异与终端输出。工具尚不可用的状态保留，课程不会把它统计成产品已跑通。60 分钟结束时，学生应能把“AI 帮我改好了”换成“我知道它改了哪里，并留下了为什么符合这些规则的证据”。

## 后置讲评、板书和补救

原始默认总数 40，但按规则应拒绝第三条空格记录；原版八例通过 3 个，仅真假值检查通过 4 个，完整校验版通过 8 个。独立题 A 合计 20；B 拒绝零值；C 合法为 7；D 布尔拒绝；E 缺字段拒绝。迁移题要查调用方、接口约定与传参测试，不能默改成只接收数字。

板书：**规则 → 实际输入 → 转换与校验 → 结果；找到一段代码不代表找齐全部条件；修改差异＋正常/边界/调用检查。** 如果学生读不懂 reduce，让他把三条卡放在桌上，逐条说当前值与累计值；算法概念可以先于语法熟练。如果终端出错，写下原错误和目录，切换浏览器继续同一规则实验，另列环境问题待解决，避免吞掉整节课。

课后可在已授权的非敏感小项目中添加一项真实需求，再重复阅读、最小修改和针对新场景的验证。不引入真实同学学习记录做能力排名。本课 Node 与网页指定案例可以检验局部代码行为，不能代替外部产品完整验收或真人试教。

## 公开来源与原创范围

- [AIPath 对应课](https://aipath.buynao.com/#/lesson/32-inside-cursor)：课序和主题。
- [Cursor 官方索引工程文章，2026-01-27](https://cursor.com/blog/secure-codebase-indexing)：公开索引流程的有限依据。
- [Cursor 官方搜索文档](https://cursor.com/docs/agent/tools/search)：精确查询与相关上下文查找的操作说明。
- [Cursor 官方审阅与测试课程](https://cursor.com/learn/reviewing-testing)：差异审阅和测试的基本用法。

四文件项目、分钟安排、材料摘录、候选程序和独立题为本课原创。随课浏览器不是 AI IDE，也不是 Cursor 内部实现的复刻。真实工具操作是否完成，以学生保留的实际记录为准。


## 逐分钟安排

| 时间 | 教师讲解与操作 | 学生活动 | 检查结果 |
|---|---|---|---|
| 00:00—01:00 | 展示25、15、全空格三条学习记录，先问规则期待什么。 | Q1写合法性判断首答。 | 运行前首答保留。 |
| 01:00—02:00 | 请学生区分数学合计与输入是否填完。 | 把两类问题分两栏。 | 没有把算出数字等同全部合法。 |
| 02:00—03:00 | 读README的1至480、整数和空白拒绝条款。 | 圈出影响第三条输入的规则。 | 预期来自任务规则。 |
| 03:00—04:00 | 指出数字与数字字符串兼容、空数组为零。 | 补写需要保留的正常行为。 | 修复目标包含原调用兼容。 |
| 04:00—05:00 | 展示三行total，解释rows与row。 | 指认记录组和当前一条。 | 能定位minutes取值。 |
| 05:00—06:00 | 把Number、sum与末尾0译成转换、累计和起点。 | 画三条卡的累计方向。 | 不靠背reduce定义完成理解。 |
| 06:00—07:00 | 检查四文件位于同一练习目录。 | Q2打开README、total、main、test。 | 四个文件后缀和角色清楚。 |
| 07:00—08:00 | 问README与test分别决定和检查什么。 | 填四文件角色表中的规则与测试。 | 规则不被程序输出替代。 |
| 08:00—09:00 | 要求全项目搜索minutes并打开函数命中。 | 定位total或用页面摘录搜索。 | 记录检索方式与范围。 |
| 09:00—10:00 | 要求打开一处调用而非只看函数。 | 定位main的三条输入及total调用。 | 调用证据含原始字符串。 |
| 10:00—11:00 | 简述官方变化检测、分块、索引与取回的用途。 | 将公开机制图与本地搜索区分标记。 | 未声称运行完整Cursor索引。 |
| 11:00—12:00 | 让学生连接main输入、total累计、test比较与README规则。 | 完成Q2因果图。 | 四种证据均有位置。 |
| 12:00—13:00 | 投影练习目录，执行node main.cjs。 | 运行命令或原始网页版本。 | 保存实际命令或表单输入。 |
| 13:00—14:00 | 不急于修复，要求保留原始输出。 | Q3记自定义记录实际结果。 | 原始失败记录未被覆盖。 |
| 14:00—15:00 | 指向Number转换示意第三行。 | 记空格原值、string类型与转换值。 | 错误定位到转换之前缺校验。 |
| 15:00—16:00 | 执行node test.cjs或查看网页八例表。 | 记录通过和失败数。 | 固定八例结果可回查。 |
| 16:00—17:00 | 请学生选B空格比较预期与实际。 | 写一项失败的完整输入依据。 | 失败原因与README对应。 |
| 17:00—18:00 | 给出当输入经过某步骤的定位句式。 | 完成Q3错误因果说明。 | 不是只写程序有bug。 |
| 18:00—19:00 | 已有Cursor者用File→Open Folder打开练习目录。 | 核对当前项目或选择人工阅读后备。 | 没有打开其他私人项目。 |
| 19:00—20:00 | 在Agent面板粘贴先阅读四文件的完整任务。 | 发送阅读任务或人工逐项阅读。 | 工具与人工路径明确记录。 |
| 20:00—21:00 | 让学生核查输出是否指出输入来源main。 | 打开引用文件比对。 | 引用与实际内容一致。 |
| 21:00—22:00 | 检查解释是否遗漏字符串兼容与空数组。 | 给遗漏要求做标记。 | 模型措辞没有覆盖业务约定。 |
| 22:00—23:00 | 问没有读取的文件能否声称已审完。 | 记录实际未读或不确定范围。 | 没有整个仓库已理解的过度结论。 |
| 23:00—24:00 | 对引入数据库或新框架的偏离示例要求收回最小计划。 | 检查计划只处理本题输入校验。 | 改动范围符合任务。 |
| 24:00—25:00 | 给出仅真假值判空候选，先问空格和0。 | Q4写两个输入预测。 | 候选运行前预测保存。 |
| 25:00—26:00 | 解释真假值判断不等于有无可见字符。 | 标空格字符串与数值零的原类型。 | 区分视觉与语言规则。 |
| 26:00—27:00 | 网页只切换为真假值检查并运行。 | 比较B空格、C零值实际结果。 | 唯一改动与结果相对应。 |
| 27:00—28:00 | 要求记录该候选仍失败的输入。 | 填写对照表第二行。 | 发现修复不完整而非只看一例。 |
| 28:00—29:00 | 展示完整校验版的类型、格式、范围三层。 | 给每层写中文用途。 | 三层没有混作同一判空。 |
| 29:00—30:00 | 解释去首尾空格后的十进制数字检查与整数范围。 | 选择一个小数或布尔值说明应在哪层处理。 | 例子连接到具体规则。 |
| 30:00—31:00 | 运行完整校验版，与相同八例比较。 | 填第三行并保存拒绝原因。 | 没有改变测试预期。 |
| 31:00—32:00 | 要求写两个能区分候选的实际输入。 | 完成Q4输入及依据。 | 不是泛写多测几个。 |
| 32:00—33:00 | Cursor路径提交只修total校验的明确指令。 | 执行修复或用人工/浏览器后备。 | 实际编辑方式有记录。 |
| 33:00—34:00 | 在文件差异中找校验添加位置。 | 核查校验是否在累计之前。 | 有实际差异或后备代码观察。 |
| 34:00—35:00 | 检查total导出及数字字符串支持是否保留。 | 对照README和main调用。 | 未默改接口以简化实现。 |
| 35:00—36:00 | 要求确认test八例未被删除或放宽。 | 核对测试变化及原预期。 | 测试仍检查原需求。 |
| 36:00—37:00 | 让学生自己运行main与test，不只听AI报告。 | 保留真实输出或标项目运行未执行。 | 执行状态与证据一致。 |
| 37:00—38:00 | 收起参考修复，发独立A至E新输入。 | Q5逐题先写规则预期。 | 独立首答不受答案提示。 |
| 38:00—39:00 | 只问A两条值的原始类型。 | 预测A并粘贴完整JSON运行。 | 预测与实际结果分栏。 |
| 39:00—40:00 | 提示B的字符串外形与转换后数值分别检查。 | 预测并运行B，定位规则层。 | 按实际观察填写拒绝或数值。 |
| 40:00—41:00 | 问C首尾空格与全空格的差异。 | 独立预测、运行并记录C。 | 未提前宣布结果。 |
| 41:00—42:00 | 提醒D检查原始类型，不只看能否转换。 | 完成D的判断和运行。 | 类型依据明确。 |
| 42:00—43:00 | 对E只问minutes字段是否存在。 | 完成E预测与实际结果。 | 缺字段作为输入条件记录。 |
| 43:00—44:00 | 要求选一个预测修订说明原因。 | 写原想法、实际观察、调整依据。 | 保留因观察而修正的过程。 |
| 44:00—45:00 | 问一个应保留的字符串输入如何说明兼容需求。 | 选例并解释不能只收数字。 | 规则与合法调用相连。 |
| 45:00—46:00 | 发迁移卡：其他调用方仍传字符串。 | 独立写要搜索的函数引用和输入组装位置。 | 新材料需要的额外证据具体。 |
| 46:00—47:00 | 追问什么实际检查能证明迁移兼容。 | 写一条保留字符串调用的测试。 | 不是笼统说回归一下。 |
| 47:00—48:00 | 宣布独立段结束，开放参考答案。 | 保留首答，另列核查和修订。 | 答案后置。 |
| 48:00—49:00 | 按规则比较A、C与B、D、E。 | 逐题说明允许或拒绝的层。 | 数值结果伴随依据。 |
| 49:00—50:00 | 展示把预期改成输出的错误修复方式。 | 指出需求为何被悄悄换掉。 | 明确测试不是迎合实现。 |
| 50:00—51:00 | 要求修改说明先写空格触发的原问题。 | Q6写问题与校验变化。 | 说明有具体前后行为。 |
| 51:00—52:00 | 要求说明保留哪些正常与调用行为。 | 补数字字符串、空数组及相关检查。 | 不仅描述新增拒绝。 |
| 52:00—53:00 | 提醒区分AI建议、人工操作、浏览器后备。 | 填写实际执行与未执行部分。 | 没有冒称真实工具成功。 |
| 53:00—54:00 | 请同桌检查问题、改动、证据、限制四项。 | 互读Q6并补具体缺项。 | 修改说明可独立理解。 |
| 54:00—55:00 | 画文件变化到修改验证的六格流程。 | 实线圈出亲手操作步骤。 | 实际经历与公开介绍区分。 |
| 55:00—56:00 | 问未实测的嵌入索引与后台更新如何标记。 | 虚线标官方资料来源。 | 本地网页不被说成产品内部复刻。 |
| 56:00—57:00 | 问只改total为何仍读main和README。 | 用字符串与空数组例子回答。 | 调用与约定的重要性具体化。 |
| 57:00—58:00 | 问八例通过可以支持多大范围结论。 | 写已测输入与未覆盖场景。 | 没有宣称任意输入都正确。 |
| 58:00—59:00 | 按Q1至Q6清点预测、图、失败、候选、新题和说明。 | 整理并导出学习记录。 | 完整学习证据可回查。 |
| 59:00—60:00 | 确认真实产品操作另附差异与输出，结束课程。 | 提交实际执行方式及剩余环境问题。 | 课堂静态验证不等同产品或真人试教。 |

---

# 第 35 课参考答案｜先完成独立输入再核查

首次预测错误不扣分，保留依据和改正过程。工具的代码建议不设唯一实现，只要满足 README、保留调用兼容并有真实测试证据。浏览器测试与外部编辑器操作必须分开记。

## Q1：输出一个数不等于输入合法

默认第三条是全空格字符串，规则要求拒绝，不形成有效总数。原版 Number 把它转成 0，最终 25＋15＋0 得到 40。40 的算术没有算错，缺陷在于没有先按任务规则拒绝第三条。这与合法地只提交前两条不同：后者确有两条完整记录，前者有缺失记录却被悄悄当零。

## Q2：四文件承担不同证据

README 规定类型、范围、空数组与兼容要求；total 是转换与累加实现；main 给出包含空格的实际调用；test 将固定输入结果和预期比较。可画 main → total → main 输出，test 另调用 total 并核对 README。

页面 minutes 查询在固定四份摘录中命中 README、total、main，共 3/4；test 摘录用自然语言列案例而没有该关键词。磁盘 test 完整文件确实含 minutes，因此真实编辑器全项目搜索的命中数可能不同。这个差异正好说明检索范围需要写明。没有命中不能推出完整项目不存在相关内容，更不能说已经读完全部仓库。

## Q3：原版失败证据

Node main 的原始输出为“合计分钟：40”。原版固定八例 **3/8 通过、5/8 失败**，通过 A 正常、E 空数组、G 字符串调用；B 空格、C 零、D 小数、F 超范围、H 布尔失败。原版直接做数值转换，对 true 会得 1，对 481 会保留 481，这些不符合输入规则。

定位句例：“全空格 minutes 从 main 进入 total，未经格式检查就经 Number 转成 0，导致不完整记录也得到 40；README 要求拒绝空白。”引用必须指向实际文件内容，工具仅说“类型问题”不构成完整证据。运行环境缺失应标为环境未就绪，不当作函数测试通过或失败。

## Q4：三个版本的区别

| 版本 | 默认输入 | 固定检查 | 原因 |
|---|---|---|---|
| 原始转换 | 40 | 3/8 | 多种不合法原值被直接转换 |
| 仅真假值检查 | 40 | 4/8 | 增加拦截数值0，但空格字符串为真，仍漏空格、小数、超上限、布尔值 |
| 完整校验 | 拒绝第三条 | 8/8 | 类型、去空格后的格式、整数范围均核对后才累加 |

候选区分输入可用一个空格、1.5、481、true；必须说清 README 期望拒绝。不是所有可被 Number 转换的值都是本任务允许的输入。字符串 " 7 " 允许先去首尾空格检查；全空格去空格后为空，不允许。

教师备查的[参考实现](reference-total.cjs)与待修复四文件分开放，避免首次运行已经没有错误。独立题完成后，可以逐行比较自己的修复；不要覆盖唯一的原始失败记录。参考代码如下：

~~~javascript
function total(rows) {
  if (!Array.isArray(rows)) throw new Error('需要记录数组');
  return rows.reduce((sum, row, index) => {
    const value = row && row.minutes;
    if (typeof value !== 'number' && typeof value !== 'string') {
      throw new Error('minutes类型不支持');
    }
    if (typeof value === 'string' && !/^\d+$/.test(value.trim())) {
      throw new Error('需要十进制整数字符串');
    }
    const minutes = Number(value);
    if (!Number.isInteger(minutes) || minutes < 1 || minutes > 480) {
      throw new Error('需要1至480的整数');
    }
    return sum + minutes;
  }, 0);
}
module.exports = { total };
~~~

错误文案可以不同；判断规则与函数导出约定不能偷换。复制参考实现不证明学生能定位问题，仍应提交首答与新输入判断。保存参考文件至四文件目录的上一级后，可在 project 目录运行 node test.cjs ../reference-total.cjs 检查参考模块；它不修改原始 total.cjs。

## Q5：独立题与迁移

| 题 | 结果 | 对应依据 |
|---|---|---|
| A | 20 | 数字12与十进制字符串8均有效 |
| B | 拒绝 | "00" 通过数字字符格式，但转换后为0，违反1至480 |
| C | 7 | 去首尾空格后为有效十进制整数，保留字符串兼容 |
| D | 拒绝 | true 是 boolean，不在允许原始类型中 |
| E | 拒绝 | minutes 缺失，得到 undefined，类型不支持 |

迁移要检索函数引用、导入、调用方与输入组装位置，并阅读接口约定。至少保留一个数字字符串实际调用（如10与"10"合计20）和空数组检查。只测数字的局部新程序即使通过，也没有覆盖原来允许的字符串调用。是否改接口需要明确需求与对应迁移，不由 AI 为了省校验默默决定。

## Q6：修改说明的范围

例：“空格时长原先被 Number 转为零，现按 README 在求和前拒绝无效类型、格式与范围，保留数字字符串调用和空数组。实际执行原八例及 A—E 新例；保存差异和命令输出。未测试真实业务大数据，也未据此验证 Cursor 的内部检索或服务效果。”

浏览器后备应改写为“验证了随课三份候选逻辑，实际项目文件未修改，Cursor 操作未执行”。实际工具建议也应由学生打开文件和运行检查支持。公开索引图中的后台更新、嵌入和检索服务没有在网页被实测，用虚线标明来源阅读。

## 10 分评分

| 项目 | 分数 | 可收集证据 |
|---|---:|---|
| Q1 规则与首答 | 1 | 区分算术结果和输入合法 |
| Q2 四文件定位 | 2 | 规则、函数、调用、测试各有实际对象 |
| Q3 原版复现 | 1 | 命令或网页输入、原输出和一项失败原因 |
| Q4 候选与实际差异 | 2 | 比较两个具体输入，识别真假值误判 |
| Q5 新输入与调用迁移 | 2 | 五题有依据，保留字符串兼容 |
| Q6 修改说明 | 1 | 问题、变化、测试、未覆盖齐全 |
| 执行来源准确 | 1 | AI、人工、浏览器、未执行不混写 |

不能操作 Cursor 不扣概念分；相应操作证据写未执行。原版预期失败和参考版通过属于本地代码检验，不是商业产品验收或真人试教。
