diff --git a/.claude/settings.local.json b/.claude/settings.local.json
deleted file mode 100644
index 3b538bf..0000000
--- a/.claude/settings.local.json
+++ /dev/null
@@ -1,32 +0,0 @@
-{
- "permissions": {
- "allow": [
- "Bash(git:*)",
- "Bash(printf '\\\\n---\\\\n')",
- "Bash(dotnet new:*)",
- "Bash(dotnet sln:*)",
- "Bash(dotnet build:*)",
- "Bash(dotnet add:*)",
- "Bash(powershell -NoProfile -Command \"[Reflection.Assembly]::LoadFrom\\('C:/Users/yunxiao.zhu/.nuget/packages/iotclient/1.0.42/lib/netstandard2.0/IoTClient.dll'\\).GetTypes\\(\\) | Where-Object { $_.Name -like '*Modbus*' -or $_.FullName -like '*Modbus*' } | Select-Object -ExpandProperty FullName\")",
- "Bash(powershell -NoProfile -Command '[Reflection.Assembly]::LoadFrom\\(\"C:/Users/yunxiao.zhu/.nuget/packages/iotclient/1.0.42/lib/netstandard2.0/IoTClient.dll\"\\).GetType\\(\"IoTClient.Clients.Modbus.ModbusTcpClient\"\\).GetMethods\\(\\) | Where-Object { $_.Name -in @\\(\"Connect\",\"ReadDiscrete\",\"Write\",\"ReadUInt16\"\\) } | ForEach-Object { $_.ToString\\(\\) }')",
- "Bash(powershell -NoProfile -Command '$asm=[Reflection.Assembly]::LoadFrom\\(\"C:/Users/yunxiao.zhu/.nuget/packages/iotclient/1.0.42/lib/netstandard2.0/IoTClient.dll\"\\); $type=$asm.GetType\\(\"IoTClient.Clients.Modbus.ModbusTcpClient\"\\); $type.GetMethods\\([System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::Public -bor [System.Reflection.BindingFlags]::DeclaredOnly\\) | ForEach-Object { $_.ToString\\(\\) }')",
- "Bash(powershell -NoProfile -Command '$asm=[Reflection.Assembly]::LoadFrom\\(\"C:/Users/yunxiao.zhu/.nuget/packages/iotclient/1.0.42/lib/netstandard2.0/IoTClient.dll\"\\); $type=$asm.GetType\\(\"IoTClient.Clients.Modbus.ModbusTcpClient\"\\); $type.GetInterfaces\\(\\) | ForEach-Object { $_.FullName }')",
- "Bash(powershell -NoProfile -Command '$asm=[Reflection.Assembly]::LoadFrom\\(\"C:/Users/yunxiao.zhu/.nuget/packages/iotclient/1.0.42/lib/netstandard2.0/IoTClient.dll\"\\); $type=$asm.GetType\\(\"IoTClient.Clients.Modbus.ModbusTcpClient\"\\); \"BASE: $\\($type.BaseType.FullName\\)\"; $type.GetMethods\\([System.Reflection.BindingFlags]::Instance -bor [System.Reflection.BindingFlags]::Public\\) | Where-Object { $_.Name -match \"Connect|Close|Dispose|Disconnect|Open|Start|Stop|Release\" } | ForEach-Object { $_.DeclaringType.FullName + \" :: \" + $_.ToString\\(\\) }')",
- "Bash(powershell -NoProfile -Command '$asm=[Reflection.Assembly]::LoadFrom\\(\"C:/Users/yunxiao.zhu/.nuget/packages/iotclient/1.0.42/lib/netstandard2.0/IoTClient.dll\"\\); $type=$asm.GetType\\(\"IoTClient.Clients.Modbus.ModbusTcpClient\"\\); $type.GetConstructors\\(\\) | ForEach-Object { $_.ToString\\(\\) }')",
- "Read(//d D:/Dev/Codes/MFD_Solution/Axi_Omron/src/**)",
- "Bash(dotnet restore:*)",
- "Bash(systemctl status *)",
- "Bash(service ssh *)",
- "Bash(sshd -V)",
- "Bash(apt list *)",
- "Bash(dpkg -l)",
- "Bash(sudo apt-get *)",
- "Bash(sudo -n true)",
- "Bash(mkdir -p /tmp/pcb)",
- "Read(//tmp/**)",
- "Bash(taskkill /F /IM \"AxiOmron.PcbCheck.exe\")",
- "Bash(powershell -Command \"Stop-Process -Id 23292 -Force -ErrorAction SilentlyContinue\")",
- "Bash(dotnet publish *)"
- ]
- }
-}
diff --git a/docs/AxiOmron_PCBCheck_汇报文案.md b/docs/AxiOmron_PCBCheck_汇报文案.md
index 602234e..a08c442 100644
--- a/docs/AxiOmron_PCBCheck_汇报文案.md
+++ b/docs/AxiOmron_PCBCheck_汇报文案.md
@@ -1,14 +1,35 @@
-# AxiOmron.PcbCheck 汇报文案
+# AxiOmron.PcbCheck 汇报演讲稿
-> 主题:3 个月,我从写 if-else 到 Vibe Coding
+> 主题:从初学者需求,到完整项目计划
> 项目:AxiOmron.PcbCheck / PCB 目检放行上位机
-> 建议时长:10 分钟
-> 使用方式:本文件按网页汇报的 9 个页面整理;“屏显文案”用于页面内容,“讲述提示”用于口头汇报。
+> 建议时长:10~12 分钟
+> 对应页面:[axiomron-pcbcheck-report-draft.html](./axiomron-pcbcheck-report-draft.html)
+> 内容来源:`docs/开发流程.txt`、`docs/纯plan.md`、当前项目实际工程
+
+## 使用说明
+
+这份文件不是简单的页面文案,而是现场可以直接使用的演讲稿:
+
+- “屏显文案”对应 HTML 页面上看到的文字。
+- “演讲主词”是建议直接讲出来的内容,可以按现场时间适当删减。
+- “转场”用于从当前页面自然过渡到下一页。
+- “操作/提示”用于现场演示,避免临场忘记重点。
+- 全程只展示本地模拟和软件证据,不连接真实生产设备。
+
+这次汇报的主线是:
+
+```text
+模糊需求 → 对话追问 → 补齐边界 → 完整计划 → 分阶段实现 → 测试验收
+```
+
+整场汇报不需要把代码讲得很深,重点是说明:我如何从一个初学者的功能描述,逐步学会定义问题、判断风险和验证结果。
---
## 01. 封面|3 个月,我从写 if-else 到 Vibe Coding
+**预计时长:40 秒**
+
### 屏显文案
**3 个月,**
@@ -18,250 +39,495 @@
用 AI 协作搭建一套 PCB 目检放行上位机:把 PLC、双扫码、文件校验、安灯和追溯记录,收束为一条可解释的现场闭环。
- 产品形态:WPF 工业上位机
-- 架构基座:.NET 8 / MVVM
-- 核心结果:可追溯放行闭环
+- 技术基线:.NET 8 / MVVM
+- 汇报重点:需求演进、调试方法、工程边界
-### 讲述提示
+### 演讲主词
-三个月前,我遇到类似需求时,第一反应通常是继续加 if-else:扫码成功怎么办、文件找不到怎么办、PLC 超时又怎么办。现在我更关注如何先把现场规则拆成状态、契约和异常边界,再借助 AI 快速实现与验证。
+大家好,今天我想分享的不是“AI 帮我生成了多少代码”,而是我如何从一个很简单的现场需求,逐步把它变成一份完整的项目计划,并最终做成一个可以运行的上位机项目。
-今天分享的不是一个单独页面,而是我如何用 AI 协作,逐步搭建一套 PCB 目检放行上位机。
+三个月前,遇到扫码、查文件、通知 PLC 这种需求时,我很容易直接进入 if-else:扫码成功怎么办,文件找不到怎么办,PLC 超时怎么办。
+
+后来我逐渐发现,工业软件最重要的不是先写出一段代码,而是先把现场规则、设备边界、异常情况和验收方式问清楚。AI 可以加快实现,但方向和判断仍然需要我自己负责。
+
+### 转场
+
+所以我们先回到起点,看一下最开始的需求到底是什么样的。
---
-## 02. 起点|让一块 PCB 安全地被放行
+## 02. 初始需求|我只想让它先跑起来
+
+**预计时长:55 秒**
### 屏显文案
-**不是做一个界面,**
-**而是让一块 PCB 安全地被放行。**
+**最开始,我只想让它**
+**先跑起来。**
-> “扫码成功、文件存在、PLC 收到信号——这些局部成功,如何组成一个真正可追溯的业务成功?”
+> “我需要写一个程序:PCB 到位后扫码,根据条码检查文件是否存在,再把结果返回给 PLC。”
-| 关联对象 | 需要解决的问题 |
+初版要求:
+
+1. PCB 到位后开始处理。
+2. 读取一个条码。
+3. 根据条码检查对应文件是否存在。
+4. 文件存在显示“正常”。
+5. 文件不存在显示“异常”。
+6. 页面显示当前状态、条码、处理结果和日志。
+7. 保存最近的处理记录。
+8. 先使用模拟数据,不连接真实设备。
+9. 页面提供“正常”“异常”“设备故障”三种模拟情况。
+
+### 演讲主词
+
+这不是一个错误的需求,反而非常适合作为第一版。
+
+它已经说清楚了业务主线:PCB 到位以后开始处理,读到条码,根据条码查文件,文件存在就是正常,不存在就是异常,同时页面要能显示状态和日志,而且一开始先用模拟数据。
+
+对初学者来说,这已经足够启动一个原型了。问题是,它还没有进入现场工程的层次。
+
+它没有说明 PLC 的哪个信号算到位,两把扫描枪到底怎样通信,文件具体怎样命名,也没有说明异常时如何恢复、结果保持多久、什么条件下才算真正完成。
+
+所以我当时的第一版想法是:先把正常流程跑通,再用模拟按钮把正常、异常和设备故障演示出来。
+
+### 转场
+
+但是,当我准备真正开始写设备通信代码时,就会遇到一个问题:还缺哪些信息?
+
+---
+
+## 03. 第一次对话|还需要哪些信息才能开始写程序
+
+**预计时长:1 分钟**
+
+### 屏显文案
+
+**真正开始写代码前,**
+**我先问:还缺什么?**
+
+> “还需要哪些信息才能开始写程序?”
+
+需要补齐四类事实:
+
+| 类别 | 关键问题 |
| --- | --- |
-| PLC | PCB 到位触发、忙碌、结果码、放行与复位,都需要明确握手语义。 |
-| 双扫码枪 | 两路 TCP 返回可能成功、失败或不一致,不能靠单一分支草率处理。 |
-| 文件校验 | 根据条码查找产品 ID 文件;找不到、重试耗尽和连接异常是不同结果。 |
-| 现场追溯 | 异常要能报警、记录、回看;工程师需要看到过程,而不仅是最终 OK / NG。 |
+| PLC | 型号、协议、点位、保持/脉冲、复位、应答、超时和异常恢复。 |
+| 双扫描枪 | 通信角色、端口、结束符、编码、超时、双枪关系和断线行为。 |
+| 文件规则 | 条码格式、文件名规则、匹配方式、目录类型、空文件和正在写入的处理。 |
+| 程序与记录 | 界面、配置、日志、权限、模拟入口、部署方式和是否需要数据库。 |
-### 讲述提示
+### 演讲主词
-这个项目的难点不在于“连上设备”,而在于这些设备的局部结果如何组成一个可靠的业务结论。
+这一步的价值,不是让 AI 变得更会猜,而是让它少猜。
-例如,扫码成功不代表可以放行;PLC 写成功也不代表产线已经完成放行;文件删除更不能发生在错误的时机。我要解决的是一条完整的现场闭环。
+首先是 PLC。需要知道 PLC 的型号和通信协议,哪个地址代表 PCB 到位,哪些地址由上位机写入,信号是保持型还是脉冲型,PLC 有没有复位和业务应答。
+
+然后是扫描枪。两把枪是同时触发还是有先后?它们是 TCP Server 还是 TCP Client?返回有没有结束符?如果没有结束符,程序怎么知道一条条码已经接收完成?
+
+第三是文件规则。条码是完整文件名,还是要转换成文件名?文件不存在和目录无法访问,是不是同一种异常?文件正在生成时应该等待、重试还是直接失败?
+
+最后是程序怎么使用。操作员需要看到什么,工程师需要哪些日志,哪些操作需要权限,模拟入口怎样保留,记录是否要长期保存。
+
+这些问题如果不提前确认,代码可能在本地看起来正确,到了现场却因为一个点位、一个报文边界或一个异常分类而产生错误判断。
+
+### 转场
+
+当这些问题被逐项问出来,需求就开始从“功能列表”变成“工程契约”。
---
-## 03. 架构|先搭骨架,再接设备
+## 04. 需求完善|从功能描述到工程契约
+
+**预计时长:1 分钟**
### 屏显文案
-**把易变的设备放在边缘,**
-**把稳定的业务流程留在中心。**
+**需求不再只是“做什么”,**
+**还要说清楚“边界在哪里”。**
-核心:`WorkflowHostedService`
-
-后台状态机负责单板生命周期;WPF 只订阅运行态,不阻塞 UI。
-
-| 分类 | 组件 | 职责 |
-| --- | --- | --- |
-| 触发 | Omron PLC | 到位、复位、结果码、放行应答 |
-| 输入 | 双 TCP 扫码枪 | 并发触发、结果汇总与不一致处理 |
-| 校验 | SFTP / 本地文件 | 按条码检索、重试、路径安全边界 |
-| 可观察性 | 安灯、CSV、日志 | 异常通知、结果追溯、监控与设置 |
-
-架构原则:
-
-- 接口隔离设备实现
-- 后台处理耗时 I/O
-- 配置不写死在流程里
-- UI 只展示状态
-
-### 讲述提示
-
-我的第一步不是先做漂亮界面,而是把每一类设备抽象成接口。这样 PLC、扫码枪、文件查找和安灯都能被替换为模拟实现,流程服务只关心业务规则。
-
-这一层架构也让 AI 能更好地协作:我可以让它先沿接口和实现追踪调用链,再只改动目标边界,而不是在 UI 或设备代码里直接塞逻辑。
-
----
-
-## 04. 核心流程|从 if-else 到状态机
-
-### 屏显文案
-
-**代码不再问“下一个 if 是什么”,**
-**而是问“当前 PCB 处于什么状态”。**
-
-1. **到位触发**:忽略重复上升沿,防止同一块板流程重入。
-2. **扫码与校验**:汇总双扫码,再根据条码检索产品 ID 文件。
-3. **结果与放行**:写入结果码,发出放行脉冲,等待 PLC 业务应答。
-4. **完成与追溯**:清状态、记录 CSV、刷新界面,等待下一块板。
-
-关键规则:
-
-- 扫码失败:安灯 + NG 放行
-- 文件不存在:重试耗尽后 NG 放行
-- 系统异常:故障锁存,不自动放行
-- 收到 PLC 应答后,才执行可选清理
-
-### 讲述提示
-
-这就是我从 if-else 思维切换到状态机思维的关键点。每一种异常都不是额外补一段判断,而是状态机中明确的一条路径。
-
-这样做的好处是,任何一个现场问题都可以回到三个问题:当前状态是什么?允许的下一步是什么?失败后应该如何恢复或锁存?
-
----
-
-## 05. 搭建过程|从方案到可运行系统
-
-### 屏显文案
-
-**从方案到测试,**
-**每一层都先解决一个真实问题。**
-
-| 时间 | 阶段 | 内容 |
-| --- | --- | --- |
-| 04·16 | 先把现场语言画出来 | 梳理通信角色、PLC 点位、结果码、异常策略和状态机,不急着进入代码。 |
-| 04·17 | 初始化 WPF 工程 | 建立 MVVM、Host/DI、日志与配置,让界面与业务流程先有干净的边界。 |
-| 04·19 | 补齐可运维能力 | 管理员解锁、SFTP 探活、扫码启动探活、CSV 结果记录相继落地。 |
-| 05·17 | 重构主放行流程 | 接入双扫码判定,把扫码、查文件、告警、放行统一为单板工作流。 |
-| 06·10 | 把联调变得可观察 | 补齐 TCP 扫码连接测试与日志,让通信问题可以被定位,而不是被猜测。 |
-
-### 讲述提示
-
-这个项目不是一次性把所有功能堆出来,而是按风险逐层搭建:先确定规则,再建立骨架,然后补齐运维能力,最后持续让通信和异常更可观察。
-
-AI 在这里的作用,是加快每一个小闭环的实现和验证,而不是跳过业务设计。
-
----
-
-## 06. 场景演示|一块 PCB 从到位到放行
-
-### 屏显文案
-
-**用一个可控的模拟流程,演示“从到位到放行”。**
-
-流程:
-
-1. PLC 检测到 PCB 到位
-2. 双扫码枪返回条码
-3. 产品 ID 文件校验
-4. 写结果并等待放行应答
-5. 写入追溯记录,回到空闲
-
-关键判断:
-
-> “PLC 写入成功”不代表产线已确认放行。只有收到 PLC 应答,才能进入后续清理和完成记录。
-
-补充规则:
-
-- 双扫码任一成功即可继续;两者不一致时保留诊断信息。
-- 文件未找到会受控重试;通信或认证异常进入系统故障,而非误放行。
-- 放行脉冲有时长与应答超时;清理动作默认关闭,避免误删现场依据。
-
-### 现场演示动作
-
-1. 点击网页上的“播放模拟流程”。
-2. 随着每一步高亮,口头说明它对应的现场动作。
-3. 在第 4 步强调:此时不是“写了放行位就结束”,而是等待 PLC 给出业务应答。
-4. 到第 5 步说明:完成记录和文件清理都依赖这一确认条件。
-
-### 讲述提示
-
-我不会在汇报现场连接真实 PLC 或 SFTP,而是用模拟器展示主流程。这种方式既能稳定演示完整业务链路,也能清楚地区分“本地逻辑验证”与“真实现场验收”。
-
----
-
-## 07. AI 编程案例|先问清楚何时可以删
-
-### 屏显文案
-
-**AI 的价值不是直接补一行 `Delete(file)`,**
-**而是先问清楚“何时可以删”。**
-
-需求:配置可选启用;收到 PLC 放行应答后,删除本轮读取到的产品 ID 文件。
-
-AI 协作过程:
-
-1. 追踪 `扫码 → 文件匹配 → ReleasePermit → PlcAckRelease` 的调用链。
-2. 明确 FINS 写入成功,只证明协议操作成功;不能等同于 PLC 完成业务应答。
-3. 保存精确命中路径;等待应答;先清放行脉冲;再由本地或 SFTP Provider 负责安全删除。
-4. 验证:应答成功删除;应答超时不删;越界路径拒绝;删除失败不回滚已确认放行。
-
-AI 的三个贡献:
-
-- **读懂陌生系统**:快速在配置、接口、后台服务、设备实现和测试之间建立调用链。
-- **把自然语言变成契约**:把“放行后删除”翻译成前置条件、超时行为、默认开关和失败后果。
-- **让异常可验证**:用 Fake PLC / Fake 文件服务覆盖关键分支,让现场风险先在可控环境暴露。
-
-### 讲述提示
-
-这个案例最能说明我对 AI 的使用方式发生了变化。以前我可能直接让 AI 写删除文件的代码;现在我会先要求它追踪整条流程,再一起确认动作的前置条件与失败边界。
-
-AI 帮我缩短了理解陌生系统和实现测试的时间,但业务责任仍然在我这里:什么时候删、删谁、失败后如何处理,必须由我结合现场规则确认。
-
----
-
-## 08. 学习路径|从看懂到解决
-
-### 屏显文案
-
-**学习不是囤教程,**
-**而是不断缩短“看懂”到“解决”的距离。**
-
-1. **看 5 个视频**:只抓住 WPF、依赖注入、后台服务、设备通信的基础概念。
-2. **拆 1 个项目**:沿着一块 PCB 的生命周期,理解配置、状态、接口和日志为何存在。
-3. **自己搭一个**:从界面骨架到 PLC、扫码、文件校验,持续用 AI 做代码阅读和小步实现。
-4. **解决真实问题**:把“PLC 应答后再删文件”落成可配置、可测试、可追溯的工程规则。
-
-关键转变:
-
-> 从“让 AI 帮我生成代码”,升级为“我能给 AI 足够明确的业务上下文,并验证它给出的工程边界”。
-
-### 讲述提示
-
-我并不是等到学会所有技术才开始做项目,而是在真实问题里逐步学习。视频帮助我建立术语,拆项目帮助我理解结构,自己实现帮助我建立手感,真实问题则迫使我理解生产边界。
-
----
-
-## 09. 总结|从代码到工程交付
-
-### 屏显文案
-
-**从 if-else 到 Vibe Coding,**
-**改变的不是“谁来写代码”。**
-
-而是我开始能把一个模糊的现场需求,拆成:
-
-- 设备契约
-- 状态机
-- 异常边界
-- 可验证的交付
-
-| 边界 | 内容 |
+| 契约 | 需要明确的边界 |
| --- | --- |
-| 已在本地覆盖 | 项目定向构建与工作流、文件相关测试可验证逻辑分支、接口隔离和异常行为。 |
-| 仍需现场确认 | 真实 PLC 点位、SFTP 根目录与删除权限,必须在产线按实际设备与权限完成联调。 |
+| PLC 契约 | 到位、复位、结果、应答、任务去重和确认超时。 |
+| 扫描枪契约 | 双路并发、无结束符、总超时、首个有效结果和迟到数据。 |
+| 文件契约 | 条码清洗、路径安全、文件存在、目录异常和结果分类。 |
+| 应用契约 | 设备状态、当前任务、日志、统计、模拟场景和权限边界。 |
-最后三点:
+需求演进链路:
-1. **技术深度**:不是“调用了多少 SDK”,而是能否说清状态、超时、失败与恢复。
-2. **学习能力**:不是“看了多少教程”,而是能否把陌生系统拆成可验证的问题。
-3. **业务结合**:不是“做了一个界面”,而是让现场每一次放行都可解释、可追溯。
+`功能描述 → 条件边界 → 失败策略 → 验收证据`
+
+### 演讲主词
+
+需求完善以后,变化最大的地方是:每个功能都开始有前置条件和失败策略。
+
+比如“把结果返回给 PLC”不再只是一句写入代码,而要继续问:结果保持多久?PLC 是否会给业务应答?确认超时怎么办?复位由谁触发?如果到位信号一直保持为真,是否会重复触发同一块 PCB?
+
+“读取一个条码”也不再只是调用一次 Receive。要确认两把枪是否同时触发,是否允许任意一把成功,没有结束符时如何判断报文结束,迟到的数据是否会影响下一轮任务。
+
+文件检查也要分清楚:文件存在、文件不存在、目录不可访问、路径越界、条码格式错误,这些不能全部压成一个简单的异常。
+
+最终,需求被整理成一条链路:先描述功能,再补充条件边界,然后规定失败策略,最后为每个关键判断准备验收证据。
+
+### 转场
+
+当问题和边界都被整理出来以后,对话的结果就不再是一段零散的代码,而是一份可以执行的项目计划。
+
+---
+
+## 05. 完整项目计划|对话的终点是一份可执行的计划
+
+**预计时长:1 分钟**
+
+### 屏显文案
+
+**对话的终点,**
+**是一份可以执行的计划。**
+
+| 层面 | 最终形成的内容 |
+| --- | --- |
+| 目标 | 让 PCB 从到位、扫码、文件校验到 PLC 结果反馈,形成可解释、可追溯的业务闭环。 |
+| 流程 | 到位触发 → 双枪扫描 → 条码校验 → 文件判断 → 结果保持 → 应答/复位 → 记录完成。 |
+| 架构 | 当前项目落地为 .NET 8 + WPF;设备通信、流程编排、界面状态、配置和日志保持清晰边界。 |
+| 测试与验收 | 单元测试和 Fake 设备先验证逻辑,再使用真实设备完成现场联调。 |
+
+计划的价值:把“我想要一个程序”翻译成目标、状态、接口、阶段、测试和交付门槛。
+
+### 演讲主词
+
+最后形成的不是一张简单流程图,而是一份完整的项目计划。
+
+第一层是目标:让一块 PCB 从到位、扫码、文件校验,到结果反馈和记录完成,形成一条能够解释、能够追溯的业务闭环。
+
+第二层是流程:什么时候开始,什么时候扫描,什么时候查文件,结果什么时候写回,什么时候等待 PLC 应答,什么时候复位并进入下一轮。
+
+第三层是架构:当前仓库的实际落地基线是 .NET 8 加 WPF。设备通信、流程编排、界面状态、配置和日志各自有清晰边界,便于模拟、测试和后续替换设备实现。
+
+第四层是测试和验收:先用单元测试和 Fake 设备验证软件逻辑,再使用真实 PLC、扫描枪和文件服务做现场联调。
+
+这里有一个需要主动说明的历史差异:早期计划文本里出现过 WinForms,但当前工程实际采用 WPF。计划不是一次写死的合同,事实确认后可以修正;重要的是把历史方案和最终落地方案区分清楚。
+
+### 转场
+
+有了目标、流程、架构和验收标准,下一步就是按风险顺序把大计划拆成多个小闭环。
+
+---
+
+## 06. 开发阶段|七个小闭环,逐步降低风险
+
+**预计时长:55 秒**
+
+### 屏显文案
+
+**计划被拆成七个小闭环,**
+**每一步都有可以验证的产物。**
+
+| 阶段 | 产物 |
+| --- | --- |
+| 01 需求与协议确认 | 点位、握手、报文、结果码和文件规则。 |
+| 02 项目骨架 | WPF、配置、日志、依赖注入和基础状态。 |
+| 03 PLC 通信 | 读写、超时、断线、重连和模拟接口。 |
+| 04 双扫描枪 | 并发触发、无结束符、首个有效结果。 |
+| 05 流程编排 | 任务去重、文件安全、结果保持和恢复。 |
+| 06 状态界面 | 设备、任务、统计、日志和操作权限。 |
+| 07 测试与交付 | 单测、Fake 流程、异常测试和现场验收。 |
+
+### 演讲主词
+
+这个项目不是一次性把所有功能堆出来,而是按风险顺序搭建。
+
+第一阶段先确认事实,避免在错误协议或错误点位上继续开发。第二阶段建立项目骨架,让配置、日志、界面和业务流程有边界。第三、第四阶段分别处理 PLC 和双扫描枪通信,把设备问题尽量隔离在接口和服务里。
+
+第五阶段才把到位、扫码、查文件、结果保持和复位串成完整流程。第六阶段把状态和结果展示给使用者。最后用单元测试、Fake 流程、异常测试和真实设备联调完成交付。
+
+每个阶段都有可以检查的产物,所以遇到问题时,可以定位是需求没确认、通信没稳定、流程没定义,还是验收证据不足,而不是把所有问题都归结为“代码有 bug”。
+
+### 转场
+
+这也说明了 Vibe Coding 的真正价值:它可以加快每个小闭环,但不能替我们决定闭环是否成立。
+
+---
+
+## 07. Vibe Coding 上手难度|能跑不等于可靠
+
+**预计时长:50 秒**
+
+### 屏显文案
+
+**上手不难,**
+**难的是从“能跑”走到“可靠”。**
+
+| 阶段 | 需要的能力 |
+| --- | --- |
+| 做出原型 | 会描述需求、会运行项目,就能很快看到第一个结果。 |
+| 做到可用 | 会拆小任务、补充上下文,并检查 AI 实际改了什么。 |
+| 做到可靠 | 理解业务风险,验证断网、超时、错误输入和恢复路径。 |
+
+> 它降低的是写代码的门槛,没有消除软件工程本身的难度。
+
+### 演讲主词
+
+从体验上说,Vibe Coding 的确降低了入门门槛。
+
+会描述目标、会运行项目,就可以很快做出一个原型。再进一步,需要会拆小任务、补充上下文,并且确认 AI 实际修改了什么。真正做到可靠,则必须理解业务风险,主动验证断网、超时、错误输入和恢复路径。
+
+工业软件最难的地方,往往不是正常时能不能跑,而是异常时会不会误判、重复触发、误放行,或者丢失现场证据。
+
+所以我现在的理解是:AI 像一名速度很快的协作程序员,负责加速实现;我负责方向、边界和最终验收。
+
+### 转场
+
+下面看一下这份计划最终如何落到一个可以运行的项目界面和处理流程上。
+
+---
+
+## 08. 实际项目运行|程序真的运行起来了
+
+**预计时长:1 分钟**
+
+### 屏显文案
+
+**这不是概念图,**
+**程序真的运行起来了。**
+
+一块 PCB 的 5 步旅程:
+
+1. PLC 通知 PCB 到位。
+2. 两把扫码枪读取条码。
+3. 根据条码检查产品文件。
+4. 发送结果并等待确认。
+5. 保存记录并回到空闲。
+
+> 本地运行界面是软件证据,不等同于真实 PLC、扫描枪和文件服务现场验收。
+
+### 现场操作
+
+1. 展示 WPF 主界面中的设备状态、当前任务、文件校验、流程和日志。
+2. 按页面右侧的 5 个步骤,说明一块 PCB 如何经过系统。
+3. 重点停在第 4 步,说明写入结果以后还要等待 PLC 业务确认。
+4. 强调当前是本地展示环境,没有连接真实生产设备。
+
+### 演讲主词
+
+到这里,前面讨论的计划已经对应到了实际工程中的界面和服务。
+
+页面不是只显示一个最终的 OK 或 NG,而是把设备状态、当前任务、条码、文件检查、流程阶段和日志放在一起。这样发生异常时,工程师能够看到问题发生在哪一步,而不只是看到一个结果颜色。
+
+这一页展示的是软件可以运行、流程可以观察,但它仍然不是现场验收证明。真实 PLC、真实扫描枪、真实文件服务和生产网络权限,还需要在现场单独验证。
+
+### 转场
+
+真正让我意识到工程边界的,是下面这个调试案例:信号明明写成功了,为什么文件仍然不能立即删除?
+
+---
+
+## 09. 真实调试案例|先问清楚何时可以删
+
+**预计时长:1 分 10 秒**
+
+### 屏显文案
+
+**信号写成功了,**
+**为什么文件不能删?**
+
+最初想法:
+
+```text
+写入放行信号 → 删除文件
+```
+
+调试后的流程:
+
+```text
+写入放行信号 → 等待 PLC 业务确认
+ → 确认成功后,才按配置执行后续动作
+```
+
+> PLC 写入成功,不等于产线已经完成业务确认。
+
+### 现场操作
+
+1. 进入第 9 页。
+2. 点击“收到 PLC 确认”,观察状态变成“业务已确认”,文件允许按配置处理。
+3. 点击“等待确认超时”,观察状态变成“确认超时”,文件保持不动。
+4. 对听众强调:写入成功和业务完成是两个不同层次的结果。
+
+### 演讲主词
+
+最初的想法很直接:写入放行信号成功以后,就把本轮文件删掉。
+
+后来调试时发现,这里混淆了两个概念:协议操作成功,和业务动作已经完成。
+
+这可以类比成发邮件。系统显示“发送成功”,只表示邮件已经交给发送系统,并不代表对方已经阅读,更不代表对方已经执行了邮件里的内容。
+
+在这个项目里,FINS 写入成功只能说明上位机完成了一次通信操作。只有 PLC 返回业务确认,才能说明产线已经确认了放行结果。确认成功以后,才可以根据配置决定是否执行后续清理;如果确认超时,就必须保留文件,不继续执行危险动作。
+
+这个案例让我改变了使用 AI 的方式。以前我可能会直接让 AI 补一行 `DeleteFile`;现在我会先让它追踪完整调用链,确认前置条件、超时行为、默认开关和失败后果。
+
+### 转场
+
+当问题变复杂时,我不会只把错误信息丢给 AI,而是使用一套固定的证据驱动调试方法。
+
+---
+
+## 10. 五步调试法|证据越完整,AI 越不容易靠猜
+
+**预计时长:1 分钟**
+
+### 屏显文案
+
+**程序出错时,**
+**我用这套五步调试法。**
+
+1. **先复现**:说明做了什么、期望什么、实际发生什么。
+2. **给证据**:提供报错、日志、配置和最近的修改。
+3. **讲流程**:先让 AI 解释调用过程,不急着修改。
+4. **小步改**:一次只处理一个原因,修改后立即运行。
+5. **正反测**:既测试成功,也测试超时、断网和错误输入。
+
+常用提示:
+
+> “先不要改代码。请根据日志找到调用流程,列出最可能的三个原因,以及如何逐个验证。”
+
+### 演讲主词
+
+我的调试方式可以概括成五步。
+
+第一,先复现,把做了什么、期望什么、实际发生什么说清楚。第二,给证据,包括日志、异常、配置和最近的修改。第三,让 AI 先解释调用流程,不要一上来就修改代码。
+
+第四,一次只改一个原因,修改以后立即运行。第五,不只测试成功场景,还要测试超时、断网、错误输入和功能开关关闭的情况。
+
+我常用的提示词是:“先不要改代码,请根据日志找到调用流程,列出最可能的三个原因,以及如何逐个验证。”
+
+这样做的好处是,每次修改都能回答三个问题:为什么改、改了什么、怎么证明改对了。
+
+### 操作/提示
+
+- 页面上的测试证据展示了 PLC 确认成功、确认超时和功能开关关闭三种结果。
+- 不需要逐字讲出所有测试名称,只需说明“成功和失败都要验证”。
+
+### 转场
+
+方法解决了如何调试,边界解决的是哪些事情不能省、哪些结果不能被误读。
+
+---
+
+## 11. 工程边界与验收|这几条不能省
+
+**预计时长:55 秒**
+
+### 屏显文案
+
+**Vibe Coding 很快,**
+**但这些不能省。**
+
+| 规则 | 现场含义 |
+| --- | --- |
+| 任务要拆小 | 每一步都应该能运行、能观察、能撤回。 |
+| 修改要看懂 | 确认改了哪些文件、为什么改、影响到哪里。 |
+| 模拟不等于现场 | Fake 设备只能先验证逻辑,不能替代真实设备联调。 |
+| 高风险动作默认关闭 | 删除、放行等动作必须有明确条件和可控开关。 |
+
+交付边界:
+
+- 异常可恢复:断线、超时、目录不可访问都有状态、日志和恢复策略。
+- 过程可追溯:每一轮任务都能回看输入、判断、结果和失败原因。
+- 现场才算验收:真实点位、通信边界、权限和连续生产稳定性必须确认。
+
+### 演讲主词
+
+这一页是我认为最重要的工程边界。
+
+第一,任务要拆小,每一步都要能运行、能观察、能撤回。第二,修改要看懂,至少知道改了哪些文件、为什么改、影响了什么。
+
+第三,模拟不等于现场。Fake PLC、Fake 扫描枪和本地文件可以帮助我们先验证逻辑,但不能替代真实设备、真实网络和真实权限。
+
+第四,高风险动作默认关闭。删除文件、放行、清理现场依据,都要有明确条件、可控开关和失败策略。
+
+所以交付标准不是“页面能打开”,而是异常可恢复、过程可追溯,并且真实设备完成现场验收。
+
+### 被问到现场验证时
+
+可以直接回答:
+
+> 当前已有本地构建、定向测试和可控模拟流程证据;真实 PLC、扫描枪、文件服务、网络权限和连续生产稳定性仍需要现场联调验收,不能用模拟结果替代。
+
+### 转场
+
+最后用三句话总结这次从初始需求到项目计划的变化。
+
+---
+
+## 12. 总结|从一句话需求到可运行项目
+
+**预计时长:50 秒**
+
+### 屏显文案
+
+**从一句话需求,**
+**到可验证的完整计划。**
+
+最后再到一个能运行、能追溯、知道边界的项目。
+
+- **会提问**:把需求里的空白和风险问出来。
+- **会拆解**:把自然语言变成流程、阶段和验收标准。
+- **会验证**:把本地证据与真实现场验收分开。
### 收尾讲述
-AI 让开发速度更快,但它没有替代工程判断。真正的成长,是我开始能定义问题、判断边界、验证结果,并把一个模糊需求交付成可靠的现场流程。
+这次最大的变化,不是 AI 替我写了多少代码,而是我开始能把一个模糊的现场需求,拆成设备契约、状态流程、异常边界、开发阶段和验收证据。
-谢谢。
+以前我更关注“能不能生成代码”,现在我更关注“问题有没有定义清楚、边界有没有说明白、结果有没有被验证”。
+
+AI 让开发速度更快,但没有替代工程判断。真正的成长,是我开始能定义问题、判断风险、验证结果,并把一句话需求逐步变成一份完整计划和一个可以运行的项目。
+
+谢谢大家。
---
-## 汇报现场速记
+## 问答备忘
-- 用方向键或右下角“上一页 / 下一页”控制网页汇报。
-- 第 6 页点击“播放模拟流程”,演示完整闭环。
-- 不演示真实 PLC、真实 SFTP 或真实删除动作。
-- 不展示具体现场 IP、账号、密码、完整生产路径或未确认的 PLC 点位。
-- 被问到“是否现场验证”时,回答:本地逻辑与定向测试可验证;真实设备和权限仍需现场联调验收。
+### 问:这套程序现在是不是已经连接真实 PLC 了?
+
+答:本次汇报展示的是本地可控环境和软件运行证据,没有连接真实生产设备。真实 PLC 点位、通信边界、权限和连续生产稳定性仍需要现场联调验收。
+
+### 问:AI 是不是已经替代了开发人员?
+
+答:AI 加快了查找、实现和测试,但没有替代需求确认、风险判断和验收责任。尤其是放行、删除和复位这类动作,必须由业务人员确认规则。
+
+### 问:为什么计划里出现过 WinForms,最后项目是 WPF?
+
+答:WinForms 是早期计划中的技术选择,随着实际工程基线和项目结构确认,当前实现落地为 .NET 8 + WPF。这个变化被保留并明确说明,避免把历史方案误认为最终实现。
+
+### 问:为什么不直接把正常流程做完再说?
+
+答:正常流程可以快速做出原型,但工业现场真正容易出问题的是超时、断线、重复触发、结果未确认和权限异常。提前定义这些边界,可以减少后期返工和现场风险。
+
+### 问:项目现在能不能直接上产线?
+
+答:不能仅凭本地模拟结果判断可以上产线。需要完成真实 PLC、双扫描枪、文件服务、网络权限、异常恢复和连续生产稳定性验证后,才能按现场验收结果决定。
+
+---
+
+## 现场演示检查清单
+
+### 开始前
+
+- 确认浏览器打开的是 `docs/axiomron-pcbcheck-report-draft.html`。
+- 确认页面能看到 12 个圆点和“下一页”按钮。
+- 确认第 9 页的两个调试按钮可以点击。
+- 不打开真实 PLC、真实扫描枪、真实文件服务器或生产目录。
+
+### 演示中
+
+- 第 2 页讲完初始需求后,停顿一下,强调“这已经能做原型,但还不能直接上现场”。
+- 第 3~6 页是本次新增主线,要讲清“追问如何变成完整计划”。
+- 第 8 页展示项目运行证据,但明确它不是现场验收。
+- 第 9 页先点“收到 PLC 确认”,再点“等待确认超时”。
+- 第 11 页主动说明模拟测试和现场验收的区别。
+
+### 结束后
+
+- 用“会提问、会拆解、会验证”收尾。
+- 如果时间不足,优先保留第 2、3、5、9、11、12 页。
+- 如果时间充足,再完整讲第 4、6、7、8、10 页。
diff --git a/docs/assets/axiomron-dashboard-report.png b/docs/assets/真实UI.png
similarity index 100%
rename from docs/assets/axiomron-dashboard-report.png
rename to docs/assets/真实UI.png
diff --git a/docs/axiomron-pcbcheck-report-draft.html b/docs/axiomron-pcbcheck-report-draft.html
index 6e94b1e..3bbbd43 100644
--- a/docs/axiomron-pcbcheck-report-draft.html
+++ b/docs/axiomron-pcbcheck-report-draft.html
@@ -4,7 +4,7 @@
-