本文件由
scripts/version_log.py生成,勿手改:事实(版本号、级别、变更)写在src/version.py的HISTORY里,改完跑python scripts/version_log.py --write。guanlan.py check与打包器都会校验本文件与代码里的版本号是否一致。
编号 v<大版本号>.<中版本号>.<小版本号>,例如 v2.52.1。
| 级别 | 含义 |
|---|---|
| 大版本号 | 系统解决方案、架构或核心功能改变 |
| 中版本号 | 非核心功能新增、减少、修改 |
| 小版本号 | 消缺完善 |
怎么改:改动落在"解决方案/架构/核心功能" → 大 +1(中/小归 0);落在"非核心功能的新增/减少/修改" → 中 +1(小归 0);只是"消缺完善" → 小 +1;一次发布混了几类,取最高那一级
打包文件名 = app_guanlang_v2.52.1.zip(规则:app_guanlang_v<版本号>.zip)。
版本号只写在 src/version.py 一行(VERSION = '2.52.1');打包器、安装脚本、安装记录 install-info.json、自检都读它,不另设真源。
| 版本 | 日期 | 级别 | 主要变更 | 说明 |
|---|---|---|---|---|
v2.52.1 |
2026-10-01 | 小 | 修 config_audit 逮到的“手拼 configs 路径”(合同审计改走 P.config)⇒ 全门禁恢复 | ① 2.52.0 提交后门禁报红一项:config_audit 逮到我在合同审计里手拼 configs 路径(ROOT / 'configs/serve.json')—— 项目纪律要求统一走公共层 P.config()/P.config_dir()。已改为 from app_common.app_common_guanlan.api import paths as _P; _P.config('serve.json'),并把兜底里的手拼字符串彻底删掉(审计器扫源码文本,留兜底同样判红)。② 复跑:config_audit "待处理 0 · 全部符合约定; 退出码 0",全门禁通过。③ 教训(记档):写读配置的代码必须用 P.config();这与"端口只改 serve.json"是同一条纪律的两面。 |
v2.52.0 |
2026-10-01 | 中 | HTTP 契约复核基址随架构更新(detail_api → Java 后端)⇒ 36/42;6 条页级不一致已列明 | ① 开箱验证里「HTTP 契约复核(42 条)」FAIL 的根因:BASES 里 detail_api/detail_page 仍直连旧 detail 服务(18033,已退役)。已改为:detail_api → Java 业务后端(端口从 configs/serve.json 现取,可用环境变量覆盖)、detail_page → 入口(Java 网关),不再写死端口。② 复核结果由"整体 FAIL"转为 一致 36 · 不一致 6 · 不可达 0;6 条全部是页面级契约项,逐条列明如下:a) /v2 → 404(旧 Vue 页路由,随 detail 服务退役);b) /detail → 500(同上,旧页已退役);c) /algorithm → 404(Java 网关只有 /algorithm/** ,裸路径没路由);d) /sim → 200 但标题是目录列表(期望"4MW 机组 整机联调仿真台 · 演示");e) /sim/sys → 404;f) /viewer → 200 但标题"如东风机 · 三维拆解"≠ 契约"整台风机 · 单元拆装工作台"。③ 判定(如实):业务面(17 条 detail_api)在 Java 侧早已全绿;这 6 条属页面/路由面,其中 a/b 是"按用户令退役旧页"的预期结果(需在契约里正式登记退役,而不是让它继续当红项),c/d/e 是 Java 网关缺裸路径与 sim 子路径的路由,f 需要核对 viewer 页版本。④ 下一步:先按"退役登记 + 补路由"把 6 条收敛(能绿的绿、该退役的登记),复跑开箱验证,再出最终总包。 |
v2.51.1 |
2026-10-01 | 小 | 开箱核验页面清单随架构更新(旧页 /detail/ → Vue /web/)⇒ 页面 5/5 | ① 开箱验证里那 1 页缺失查明并修掉:核验清单探的是旧页 /detail/,而按用户令旧页与 Python 业务后端已退役(configs/serve.json 的 retire_detail: true)⇒ 副本启动不再拉起 detail,该项必然失败。清单改为当前页面集合:根路径(门户,与主实例同字节比对)· /web/(Vue 工作台)· /cms/ · /ops · /healthz。② 重跑开箱验证:页面可用 5/5 —— 可以交付;卸载核验 通过(五项实测均 200:/ · /web/ · /cms/ · /ops · /healthz;门户字节差 96 B 为副本端口改写,脚本已注明属预期)。③ 如实记录一条新曝出的红:同一验证里的「HTTP 契约复核(42 条端点)」FAIL —— 该复核仍打旧路径 /detail/api/(detail 服务已退役),而契约端点现在由 Java 后端在 /api/ 上提供。下一轮按同样办法把该复核的基址切到新入口并复跑,之后才谈最终总包。 |
v2.51.0 |
2026-10-01 | 中 | 交付形态补齐:四模块可单独打包 + 根 run.bat/run.sh + install/uninstall 支持按模块 | ① 用户令(2026-10-01)"各系统模块目录支持打包 + 总包 + install/uninstall/run"全部落地:新增 scripts/pack_module.py(模块级打包器:排除缓存/数据/产物/日志;包含 Java 的 target/classes 与 target/lib;支持 <模块>/pack_include.json 把模块外的运行产物收进包;--all 四模块一起、--verify 逐文件核验 sha256);四模块各自新增 pack.bat(纯 ASCII)/pack.sh;根新增 run.bat(纯 ASCII)/run.sh,支持 start / stop / restart / status / help;根 `install.bat |
v2.50.0 |
2026-10-01 | 中 | 停用 Python 业务后端(detail 服务退役开关):运行期验证不再需要它 | ① 按"先停用、再删除"的纪律:configs/serve.json 加 retire_detail: true(附说明与回滚方法),cli.py 的 services(c) 在该开关为真时不再拉起 detail 服务(Python 业务后端 serve.py)。理由:契约 17 条 detail_api 端点已全部由 Java 后端承接并过裁判,前端也已全量 Vue(10/10 过对拍)。② 停用后整栈实测:根路径(门户制品 file)200 · /web/index.html 200(Vue)· /api/fleet 200(Java 后端)· /algorithm/healthz 200 · /ops 200;服务清单里已无 detail,其余服务(algorithm/web/cms/viewer/sim/sim_sys/gateway)照常。③ 结果确认:运行期不再需要 Python 业务后端(旧页 /detail/v2 随之退役,其路由上游已停 ⇒ 返回 500/404,这正是"删掉被替掉的 Python 前端与后端"的直接结果;前端对拍基线到此为止,注意后续改前端将无法再跑该对拍)。④ 下一步:真正删除被替掉的源码(前端渲染批 + serve.py 与 windscada_serve 入口),并清理 Java 网关里已无上游的 /detail 路由;随后重打包与开箱验收。 |
v2.49.0 |
2026-10-01 | 中 | 门户制品化:Java 网关文件优先伺服 release/portal.html(入口不再依赖旧网关的门户) | ① 用户选定路线 A(先把入口依赖清干净,再删 Python 源码)的第一步落地:门户改为构建期制品 —— scripts/portal_build.py 产出 release/portal.html(实测 20186547 B · sha256 8b0976b4c3 · 内嵌件 28 个),Java 网关的 PortalController 整文件重写为"文件优先":读制品即用,制品缺失才回退代理上游。② 响应头加 X-Portal-Source(file / upstream)—— 一眼可验"到底谁在伺服",不必靠停服务去猜;实测根路径与 /index.html 均为 200、来源=file、20186547 B。③ 路径刻意不走 application.yml(上一轮追加第二个顶层 guanlan: 触发过 snakeyaml DuplicateKeyException),改由环境变量 GUANLAN_PORTAL_FILE 覆盖;并记下另一条教训:改这种链式返回方法必须整段替换,上一轮只换前半段把 .timeout().map().onErrorResume() 链拼坏 ⇒ 编译失败(已回滚)。④ 实测全路由(入口 28084):/ 与 /index.html → 200(来源 file)· /web/index.html → 200(Vue)· /api/fleet → 200(Java 后端)· /detail/v2 → 200(旧页,对拍基线)· /ops → 200 · /algorithm/healthz → 200。⑤ /ops 归属(本轮明确):运营控制台 + 交付工具链(cli/ops/pack 与开箱验收)保留在 Python 侧,属"工具链"而非"业务后端";故 gateway.py 仍作为 /ops 与过渡期回退上游保留,但它已不再是门户的必要条件。⑥ 下一步:删被替掉的 Python 源码(前端渲染批 + serve.py 的 /api 实现批,保留工具链)→ 重打包 → 开箱验收。 |
v2.48.0 |
2026-09-30 | 中 | 补 /api/rpt_compose 探针(与 Python 同语义)⇒ 前端对拍恢复 10/10 | ① 入口切换后的最后一处连带差异查明并修掉:旧页 bindReport 首屏会探 /api/rpt_compose?probe=1,入口切到 Java 后这条探针 404 ⇒ 旧页 RPT.compose=false ⇒ 多渲染一句「本部署未启用编排接口, 画布仍可手动拼装」(t(rpt.no_compose)),于是对拍报"基准多 1 项"。② 处置:Java 新增 RptComposeController,照抄 Python 探针语义({ok:true, probe:true},不跑模型 —— Python 侧注释写明照跑会让汇报定制页首屏空等约 23 秒);真正的编排(rpt_compose(need, canvas, model) 走 LLM)尚未迁,非探针请求明确回"尚未迁移",不假装成功。③ 实测:/api/rpt_compose?probe=1 与 /detail/api/rpt_compose?probe=1 两侧同形;前端对拍 report 页签恢复一致(48 条文本)。④ 结论:新入口(28084 = Java 网关)下,前端 10 页签对拍全绿、后端裁判 Java 范围全一致、全门禁通过 —— 可以进入"删 Python 源码 + 重打包 + 开箱验收"阶段。 |
v2.47.1 |
2026-09-30 | 小 | 修门户回归(Java 网关代理根路径)+ 登记 gateway_java 端口 ⇒ 门禁恢复全绿 | ① 门禁逮到的回归已修:入口切到 Java 网关后我把根路径做成重定向,改变了根路径行为 ⇒ pages_audit 未通过;改为控制器代理:根路径与 /index.html 从旧网关(28086)取回门户 HTML 原样返回,Vue 工作台仍走 /web/。② 两处实逮:a) Spring Cloud Gateway 的 Path 谓词写法不匹配根请求(根路径与 /index.html 仍 404)⇒ 改用控制器;b) 门户页 20186279 B(约 20 MB,内联经典图表脚本) 远超 WebClient 默认 256 KB 内存缓冲 ⇒ 放开 maxInMemorySize 后返回 200。③ pages_audit 的第二处失败是配置缺口:入口端口 28084 未登记在 serve.json;已加 gateway_java=28084,audit 随即报 0 项要处理、退出码 0,全门禁恢复通过。④ 实测(入口 28084):根路径与 /index.html → 200(20186279 B)· /web/index.html → 200(Vue)· /detail/v2 → 200(旧页,前端对拍基线保留)· /api/fleet → Java 后端 · /ops → 200。⑤ 后端裁判:16/17 · 有差异 0 · 未落定 1(curves 冷启按窗重算),结论仍为 Java 范围端点全部一致。⑥ 下一步:复跑前端对拍 10 页签与 SPA 冒烟 → 按选定范围删被替掉的 Python 源码 → 重打包与开箱验收。 |
v2.47.0 |
2026-09-30 | 中 | 入口切到 Java 网关(28084);Python 网关退到 28086 继续供 /ops;旧页 /detail/v2 仍可达 | ① 按用户选定「先把入口切到 Java 网关,再删被替掉的源码」,本轮完成入口切换(全部走配置、可回滚):configs/serve.json 的 gateway 28084 → 28086(Python 网关续供 /ops 运维台);Java 网关 server.port 28085 → 28084(成为唯一用户入口);Java 网关新增 /ops/** → 28086(不剥前缀)。② 实测(入口 28084,全部经 Java 网关):/ → 200(Vue 首页)· /web/index.html → 200 · /api/fleet → 200 JSON 210 KB(走 Java 后端,kpi 正确) · /algorithm/healthz → 200 · /detail/v2 → 200(旧页仍可达 ⇒ 前端对拍基线保留) · /ops → 200(运维台仍在)。③ 意义:页面(Vue)+ 业务接口(Java 后端)+ 算法(FastAPI)+ 运维台四面同源,入口由 Java 网关承担;而旧页与对拍能力都还在,删除 Python 源码前还能做最后一次全量回归。④ 下一步:跑全量回归(后端裁判 17/17 · 前端对拍 10/10 · SPA 冒烟)→ 按选定范围删被替掉的 Python 源码 → 重打包与开箱验收。 |
v2.46.0 |
2026-09-30 | 中 | Java 网关补齐入口(/api 直通 + 门户重定向 + 离线构建)——为删 Python 源码铺路 | ① 用户选定「先把入口切到 Java 网关,再删被替掉的源码」。本轮给 Java 网关(28085)补齐入口能力:/api/** → 28120(不带 StripPrefix,Java 后端路由本就是 /api/*)· /sim/**、/viewer/**;新增 PortalController 把根路径 / 重定向到 /web/(Vue 工作台);新增 build_offline.py 与 settings-offline.xml(与 backend-java 同法:mvn -o compile + 复用既有 target/lib 95 个 jar)。② 实测(经 Java 网关 28085):/ → 200(落到 /web/ 的 Vue 首页)· /web/index.html → 200 text/html · /api/fleet → 200 JSON 214 KB,kpi={全场 38, 关注台 15, 报警台 28}(走 Java 后端)· /algorithm/healthz → 200。③ 至此 Java 网关已可承担入口:页面(Vue)、业务接口(Java 后端)、算法(FastAPI)三面都在同一源站下。④ 下一步(按用户选定的顺序):把部署入口从 28084 切到 28085 → 回归(裁判 17/17 + 前端对拍 10/10 + SPA 冒烟)→ 再删被替掉的 Python 源码(app_frontEnd 页面渲染批 + serve.py 的 /api 实现批;工具链 guanlan.py/ops 保留,否则打包与开箱验收会失效)。 |
v2.45.0 |
2026-09-30 | 中 | 灰度切换:同源 /api/* 直通 Java(Vue 前端零改动走新后端) | ① 网关新增同源 /api/* → Java 后端(28120)的不剥前缀直通:Vue 前端经 /web 伺服、页面打的是相对 /api/*,现在这些请求直接落到 Java;旧页仍走 /detail/api/*(Python),灰度期两条并存。② 实逮并修:最初用路由表加 /api 前缀不行 —— _route() 会把命中前缀剥掉再转发(/api/fleet → 上游 /fleet)⇒ Java 404;改为在 _handle 里显式直通(与 /ops 同风格)。③ 实测:/api/fleet(应走 Java)与 /detail/api/fleet(Python)的 kpi 完全一致(全场 38 · 关注台 13 · 报警台 25)⇒ 前端零改动即可切到 Java 后端。④ 裁判 IGNORE 的判断改为多前缀(上一版换了数据结构但比对处那行没跟着改)。⑤ 下一步:删 Python 前端+后端源码 → 重打包(随包 JRE + jar + Vue 产物 + 算法服务)→ 开箱验收。 |
v2.44.0 |
2026-09-30 | 中 | 问答管线真跑成功(state=done + 校闸结论);裁判把 ask_status 状态字段整组登记忽略 | ① 起本机模型服务(F:/Ollama/ollama.exe serve,4 个模型含 qwen3:8b)后真跑一次问答:POST /java/api/ask 立即回 {state: running} → 247 秒后 state=done;steps 依次为「推理· 第 1/3 轮」「取证· ont_mechanism_search」「预算· 31s 已过 60%, 收工具强制成文」「推理· 第 2/3 轮」「成文· 162 字」「校闸· 第 1 次」;answer 是「【校闸未过, 不出正文】有效=False, 越界=无, 契约引用=无误 … 请换个问法」——即管线真的跑通,而校闸(质量闸)按设计拒绝了本次答案(问法偏泛、未达契约取证要求),不是接线缺陷。② 裁判口径修正:ask_status 是各自进程内的问答状态机 ⇒ 状态类字段整组登记忽略(state/q/model/answer/verify/err/step/steps/review/xrev/t0/elapsed),只保留 lang 等与实现有关的字段严格比对;IGNORE 结构升级为「多前缀 + 理由」。③ 至此:前端 10/10 页签过对拍 · Java 范围 17/17 端点过裁判 · 问答端到端可跑。④ 剩余收尾:入口切 /java → 一次性删 Python 前端+后端源码 → 重打包(随包 JRE + jar + Vue 产物 + 算法服务)→ 开箱验收。 |
v2.43.0 |
2026-09-30 | 中 | 问答管线端到端接通(Java → 算法服务真跑 → 状态/步骤回填);仅因本机模型服务未启动而报错 | ① 接线完成:POST /api/ask(Java)校验通过后置 state=running 并起守护线程调用算法服务 POST /api/ask_run(该端点跑的是从详情层搬来的 _ask_worker),完成/失败时把末态写回 Java 侧状态字典,/api/ask_status 照旧供前端轮询(前端契约不变)。② 实测验链路:立即回 {state: running, model: qwen3:8b};轮询可见步骤推进(推理· 第 1/3 轮);随后因本机模型服务(Ollama, 11434)未启动报错(WinError 10061 目标计算机积极拒绝)——这是环境依赖缺失,不是接线缺陷:管线确实跑了、错误如实回传(state=running→error,steps 有记录)。③ 算法侧补齐记录(同前几次的教训):搬运闭包要按所有裸名引用算,不能只跟函数调用 —— 实逮 _warm 是以 threading.Thread(target=_warm) 传入的,漏了它导致 name "_warm" is not defined;补齐 _warm 与 ASK/ASK_MODELS/_ASK_STEP_KEY_EN 后导入自检通过。④ 编译问题也一并解决:上一轮 Java 编译失败是因为控制台把 mvn 的中文错误打成乱码 ⇒ 改为把构建输出写文件再读,确定性补丁(导入/字段/构造器/成功分支)后编译通过。⑤ 裁判复验:Java 范围 17/17 仍全部一致(口径未回退)。 |
v2.42.1 |
2026-09-30 | 小 | 问答管线搬进算法服务(导入自检通过);Java 侧接线暂撤回以保树可编译 | ① 算法侧成果(保留并提交):service/ask_views.py —— 从详情层搬来 _ask_worker(60 行)与 _ask_step_text,仅三处改动(签名加 st 参数 · 体内 ASK[x] 改 st[x] · 外层 ask_run 建 st 并按 ask_start 的 hints 逻辑拼词);常量 ASK_CAT_HINTS/ASK_CAT_HINTS_EN/MODEL_SPEC 一并搬入。导入自检通过:4 类提示词 · 9 模型档 · 有 ask_run。② app.py 新增 POST /api/ask_run(同步跑一次并返回末态)——新增路由,不影响既有 17 条端点的判定。③ Java 侧接线(POST /api/ask 起后台线程调 /api/ask_run 并把末态写回状态机)本轮没做完:改动后 Java 编译失败(控制台编码把错误信息打成乱码,未能当场定位),按纪律回滚了 AskController.java,回到 2.42.0 的可用版本(校验语义对齐 + 成功分支明确回"未迁")。宁可回滚,也不留编译不过的树。④ 下一步:先让 Java 编译错误可见(把 mvn 输出写文件再读,或用 -q/-e 参数),修好接线,再做一次真问答端到端验证(POST /api/ask → 轮询 /api/ask_status → 出答案),最后才谈切入口与删 Python。 |
v2.42.0 |
2026-09-30 | 中 | POST /api/ask 校验语义对齐 + 裁判加 POST 能力 ⇒ Java 范围 17/17 全部一致 | ① 最后一条端点落地:AskController 增 POST /api/ask,与 Python ask_start()(serve.py:1896-1916)的校验与错误语义逐字对齐 —— 空问题(问题为空 / The question is empty)· 串行锁(已有问题在推理中 (串行锁, 一次一问) + state)· 未知模型(未知模型 X; 可选 [...])。② 裁判新增 POST 能力:按"契约抓取时的最小请求"发空体 {} 两侧同法比对(并修掉一处顺序 bug:POST 分支写在了 jurl/purl 组装之前 ⇒ UnboundLocalError)。③ 实测(裁判原话):一致 17/17 · 有差异 0 · 未实现 0 · 跳过 0 · 未落定 0,结论"Java 范围端点全部一致"。至此冻契约里 17 条 detail_api 业务端点全部由 Java 承担并与 Python 逐值/逐文档/逐错误语义等价(含二进制 rpt_export:docx/xlsx 解包文本比对)。④ ★如实标注的功能缺口:/api/ask 的成功路径(真正跑 LLM 的管线:dsh + 本体 MCP + 交叉审核 + 串行锁)尚未迁入 Java;Java 对合法请求明确回"问答管线尚未迁移到 Java(P12 进行中)",不假装 state=running。因此删 Python 后端前必须先补这块,否则"问答"功能会缺失。⑤ 下一步:迁问答管线(或按既有范式让算法服务承担 LLM 调用、Java 持有状态机)→ 之后才做入口切换 /java → 一次性删 Python 前端+后端源码 → 重打包(随包 JRE + jar + Vue 产物 + 算法服务)与开箱验收。 |
v2.41.0 |
2026-09-30 | 中 | rpt_export 收口(二进制端点)+ 裁判加解包文本比对 ⇒ 计分板 16/17(Java 范围无未实现) | ① 端到端打通:算法服务 /api/rpt_export_raw 实测 docx 36873 B / xlsx 4792 B(均 PK 魔数);Java 侧 RptExportController 透传 fmt/blocks/aud/win/narr 并按同样 MIME 与文件名回传字节。② 裁判新增二进制比对:契约 ctype 非 JSON 的端点走"取字节 + 解包"——docx/xlsx 用 zipfile 逐条目读 XML,剔除 dcterms:created/modified、cp:lastModifiedBy、TotalTime 等每次都变的时间戳/属性后逐字比对;非 zip 字节则如实报"非 zip,两侧大小"。这样 Office 导出才算"真的比过",而不是只看状态码。③ 实测:一致 16/17 · 有差异 0 · 未实现 0 · 未落定 0 · 跳过 1;裁判结论为"Java 范围端点全部一致"——唯一剩下的 /api/ask 是 POST,需先给裁判补"构造请求体"能力。④ 这一步的意义:契约 17 条业务端点(detail_api)里 16 条已与 Python 逐值/逐文档等价,Java 后端已能独立承担业务面;最后一条 POST 打通后即可切入口并删 Python 源码。 |
v2.40.1 |
2026-09-30 | 小 | rpt_export 组装侧就绪(自检导出 36.8 KB docx 成功);HTTP 与 Java 侧下一轮接通 | ① 落地:新增 service/report_views.py(导出组装:fleet(w) → 上报版再 _redact(_jclean(fl)) → to_docx/to_xlsx,参数与顺序照抄详情层);app.py 新增 /api/rpt_export_raw(返回字节的路由,并把 Response 加进 fastapi.responses 导入);fleet_views.py 补搬 _jclean/_redact/_redact_text 及其正则常量与别名导入。② 自检(独立进程,不经 HTTP):导入后真的导出一次 ⇒ 36873 B · docx · 文件名正确(带窗重算日志是冷启正常现象)。③ 修 bug 记录(本轮真踩的坑,一并记档):a) 上一轮把 app.py 的路由装饰器与插入块缩进改坏(装饰器掉到 0 列、函数体停在 4 列);本轮按行区间精确补/退缩进并用 ast.parse 断言,才把文件修回语法正确。b) 搬运块缺 import os as _os 等别名导入 ⇒ 模块导入即 NameError;已按 serve.py 顶部导入逐条补齐(只补缺的)。c) 搬运脚本的"自检"里用了 % 格式化,把字符串写坏 ⇒ 改为纯函数式拼接。④ 待办(下一轮):重启后端到端验证 /api/rpt_export_raw 返回字节 → 加 Java RptExportController 透传 → 给裁判加二进制比对(状态码 + Content-Type + 大小量级 + 解包后的文档文本逐字一致,忽略时间戳)。 |
v2.40.0 |
2026-09-30 | 中 | vibcms 与 reload 迁移 + 裁判对有状态端点加固 ⇒ 计分板 15/17 | ① 迁移:vibcms_results(65 行·自足)与 reload_products(7 行)按传递闭包搬进 fleet_views.py,并各加一层详情层口径的包装(vibcms 原样返回;reload 组装 ok/old_stamp/stamp/files);登记表新增 vibcms、reload;Java 侧新增 ProductController(代理 + 对外脱敏)。② 裁判三处加固(都由本轮实逮的假差异驱动):a) 预热由一次改两次 —— /api/reload 是清缓存副作用端点,连比两次会让先比的一侧持旧指纹、后比的一侧为 None(实逮 old_stamp str 对 None);两次预热后两侧都处于刚清过的稳态。b) 落定等待上限 10 提到 20 次,且到上限仍未落定就单列"未落定"(不混进"有差异")。c) 新增登记忽略字段(附理由,与前端对拍门的 ALLOW 同风格):/api/reload 的 old_stamp 属"有状态"字段,取决于比对顺序与两侧缓存状态,非实现差异;其余字段照常严格比对。③ 自己抓到的疏漏:给裁判加忽略规则时把 JS 风格注释(斜杠星号)插进了 Python ⇒ 语法错误;已改为井号注释并加"语法自检"(ast.parse)后再跑。④ 实测:一致 15/17(ask_models · ask_status · channels · curves · dq_findings · facts · fleet · maint_framework · maint_std · maint_survey · ont_chain · ont_list · ont_obj · reload · vibcms)· 有差异 0 · 未实现 1(rpt_export)· 跳过 1(POST /api/ask);--require 十五条门禁通过。 |
v2.39.0 |
2026-09-30 | 中 | ask_models 与 ask_status 用 Java 实现并逐值一致 ⇒ 计分板 13/17 | ① 两个端点用 Java 实现(后端自有状态/清单,不是代理):AskController 里 ASK_MODELS 的 6 个模型 id 由 AST 从 serve.py 原样抽出;ask 状态字典按 Python 的 ASK 初值逐键对齐(state=idle · q/model/answer 空 · t0=0 ⇒ elapsed=0 · steps=[] · xrev=false · lang=zh)。② 编译踩点:生成器把模型 id 写成了裸字符串字面量(少了 ASK_MODELS.add(...))⇒ 编译报错,已修(生成器模板问题,不是设计问题)。③ 实测:一致 13/17(ask_models · ask_status · channels · curves · dq_findings · facts · fleet · maint_framework · maint_std · maint_survey · ont_chain · ont_list · ont_obj)· 有差异 0 · 未实现 3(reload / rpt_export / vibcms)· 跳过 1(POST /api/ask);--require 两条门禁通过。④ 下一批:vibcms(大概率是产物读取)· reload(产物重载:产物指纹与文件数,副作用需按只读口径处理)· rpt_export(Word/Excel 导出,写盘类,需明确落地方式)· 最后 ask(POST,裁判要补请求体构造)。 |
v2.38.0 |
2026-09-30 | 中 | curves 迁移 + 裁判学会等落定 ⇒ 计分板 11/17 | ① 曲线视图迁移:curves_of 与 curve_view 按传递闭包补进现有 fleet_views.py(共享辅助 _win_get/_load/months_of/span_of 等已在其中,只新增 2 个函数与 LENSES 等 5 项全局);登记表登记为 curves_view —— 注意命名冲突:算法服务里 curves 已被原生 build_store(write=False) 占用,故详情层视图另起名,Java 对外仍提供契约路径 /api/curves。② 新增 CurvesController(代理 + 对外脱敏)。③ 裁判两处改进(都是本轮实逮的假差异):a) 预热后若响应里仍有 *_pending=true 就轮询到落定(最多 10 次 x 15 秒)再比 —— 之前 fleet 会在 13/15 之间翻。b) 落定判据要含 building:/detail/api/curves 后台算时回 building=true,而算法侧那份已算完,直接比会报 "$.building: Java 缺键"(假差异)。④ 实测:一致 11/17(channels · curves · dq_findings · facts · fleet · maint_framework · maint_std · maint_survey · ont_chain · ont_list · ont_obj)· 有差异 0 · 未实现 5(ask / ask_status / ask_models / reload / rpt_export)· 跳过 1(POST /api/ask);--require 十一条门禁通过。⑤ 下一批:reload / rpt_export(看清依赖)与 LLM 类 ask 家族(先给裁判补 POST 请求体构造)。 |
v2.37.0 |
2026-09-30 | 中 | /api/fleet 逐值一致 ⇒ 计分板 10/17(10 个页签取数源打通);裁判加预热消除冷启假差异 | ① 上一轮报的单字段差异(kpi.关注台 13 对 15)查明为冷启时点所致:关注台 = len(watch),watch 由 sysmx(按窗重算 + 进程内缓存)推出;两侧各取一次(预热)后均为 15、完全一致 ⇒ 不是搬运遗漏。② 裁判据此改进:比对前两侧各 GET 一次(丢弃结果)再取第二次,比的是稳态行为;并把这条写进脚本文档(否则带按窗重算/进程内缓存的端点会持续报假差异)。③ 顺带修好的:算法服务 /api/fleet 500(搬运来的 fleet_view(win) 无默认值)⇒ 加薄包装 fleet(win="2026年"),登记表改指它;Java 侧新增 FleetController(代理 + 对外脱敏)。④ 实测:一致 10/17(channels · dq_findings · facts · fleet · maint_framework · maint_std · maint_survey · ont_chain · ont_list · ont_obj)· 有差异 0 · 未实现 6(ask / ask_status / ask_models / curves / reload / rpt_export)· 跳过 1(POST /api/ask);--require 十条门禁通过。⑤ 意义:fleet 是 10 个页签的取数源,它一致等于业务主链在 Java 侧已打通。 |
v2.36.2 |
2026-09-30 | 小 | fleet 链路打通(修算法服务 500)但差异收敛到单字段,未计一致 | ① 实逮并修:登记表把 win 当可选参数,而搬运来的 fleet_view(win) 没有默认值 ⇒ 算法服务 500(TypeError: fleet_view() missing 1 required positional argument)。处置:在搬运模块里加薄包装fleet(win="2026年")(照抄详情层 q.get("win", "2026年") 的默认窗口径),登记表改指它 —— 不改写搬运逻辑,只补默认值这一层。② 新增 FleetController(Java):/api/fleet 代理算法服务 + 对外脱敏;登记表新增 fleet。③ 判定结果(如实):/java/api/fleet 已能取到 210 KB 载荷,但裁判报单字段差异 $.kpi.关注台: 13 ≠ 15 —— 两侧现在跑的是同一份搬运代码,差异只能来自进程状态/时点(详情层进程带着长期累积的按窗缓存与重算状态,算法服务是干净的)。④ 因此仍不计入一致(9/17):下一轮先判定 kpi.关注台 是否时点相关——若相关则按既有"数据两条来源"机制登记例外并写明理由;若不相关,说明搬运还有遗漏(继续查)。⑤ 附带收获:--java-kinds 计分板把真实待办列出(余 ask/ask_status/ask_models/curves/reload/rpt_export/…)。 |
v2.36.1 |
2026-09-30 | 小 | fleet 搬运完成(AST 传递闭包 591 行)但未计一致:自检仅剩 kpi.关注台 一处差异 | ① 用 AST 传递闭包把详情层 fleet_view 搬进算法服务(service/fleet_views.py,591 行):种子 fleet_view → 递归展开被调本地函数(共 13 个:span_of/win_range/_month_end/months_of/_load/products_stamp/_product_files/m9_of/_win_get/_mem_mb/_win_key/sysmx_of)→ 带上被引用的 12 个模块级全局(CFG/LOCK/ST/TS/_CACHE/_HEAVY_LOCK/_STAMP/_STAMP_TTL/_WIN_BUSY/_WIN_CACHE/_WIN_ERR/_WIN_LOCK)。② 本地自检(搬运版 fleet_view("2026年") vs 线上 /detail/api/fleet):顶层 18 键,仅 kpi.关注台 一处不同(13 vs 15) —— 属"重算时点/缓存"类差异(搬运版会触发按窗重算,线上那份是既有缓存结果),不是搬运漏项。③ 因此本轮不把 /api/fleet 计入一致(计分板仍 9/17),下一轮先把两侧置于同一时点(预热后各取两次、或等按窗重算完成再比)再判定。④ 期间实逮两次"漏依赖":LOCK、以及只算直接引用不够(_load 调 products_stamp,后者又调别的)⇒ 改为传递闭包后一次到位。 |
v2.36.0 |
2026-09-30 | 中 | /api/channels 一致(Java 原生实现)⇒ 计分板 9/17 | ① 这是第一个真正用 Java 实现的 detail_api 端点(非代理):读契约 YAML(Spring Boot 自带 snakeyaml)→ 取每组 liveness 为“活”的列 → {code, cn: ch_cn(col, with_tag=False) + " · " + col},与 Python channel_list()(serve.py:1974-1980)逐字对齐。② ch_cn 的 STEM(70 项)/SUFFIX(8 项) 数据表用 AST 从 i18n.py 原样抽出生成 Java 常量(不手抄,漏项会被对拍逮住)。③ 踩点记录:契约 YAML 实际在 reference/rudong/windscada_contract.yaml(由 src.windscada.config.farm() 的 contract 键给出);注解默认值里写 Windows 绝对路径会被 Java 当转义序列(反斜杠 + w 非法)⇒ 改安装根相对路径 + 两处探测(工作目录/仓库根)。④ 为何此处不“搬进算法服务”:列名中文化属后端展示口径,且 Python 后端终将删除 ⇒ 用 Java 实现才符合终态。⑤ 实测:一致 9/17 · 有差异 0 · 未实现 7 · 跳过 1;--require 九条门禁通过。⑥ 下一批:算数大头 fleet(10 个页签取数源)· curves · 然后 LLM/编排类 ask/ask_status/ask_models/rpt_compose。 |
v2.35.0 |
2026-09-30 | 中 | /api/maint_std 逐值一致 ⇒ 计分板 8/17(维护面三端点齐活) | ① service/maint_views.py 追加 maint_std():把详情层 /api/maint_std 分支(standards.run_all(wo) + standards.score(wo, r),异常 → {err: 运维标准判据失败: …})逐字搬进目标栈;登记表新增 maint_std。② MaintFrameworkController 增加 /api/maint_std(代理 + 对外脱敏)。③ 实测:一致 8/17(facts · dq_findings · maint_survey · maint_framework · maint_std · ont_list · ont_obj · ont_chain)· 有差异 0 · 未实现 8 · 跳过 1(/api/ask POST);--require 八条门禁通过。④ 下一批:channels · 算数大头 fleet(10 个页签取数源)· curves · LLM 类 ask/ask_status/ask_models/rpt_compose(先给裁判补 POST 请求体构造)。 |
v2.34.0 |
2026-09-30 | 中 | /api/maint_framework 逐值一致 ⇒ 计分板 7/17 | ① 新增算法服务模块 service/maint_views.py:把详情层 maint_framework_view()(serve.py:361-394)搬进目标栈(读同一份 objects.json、调同一批 maint/framework.py 函数、保留英文化分支),不是重写 ⇒ 输出与详情层应当逐值一致;登记表新增 maint_framework(可选 lang)。② 新增 MaintFrameworkController(Java):代理算法服务 + 对外脱敏。③ 实测:一致 7/17 · 有差异 0 · 未实现 9 · 跳过 1;--require 七条门禁通过。④ "搬"这一手让数据/规则类端点的迁移成本显著下降:只要 Python 侧逻辑能整体搬进算法服务包,Java 就只是一层代理 + 脱敏,一致性天然成立;真正的重写只留给纯展示/组装逻辑。⑤ 下一批:maint_std(同一手法)· channels · 算数大头 fleet(10 个页签取数源)· curves · LLM 类 ask/ask_status/ask_models/rpt_compose。 |
v2.33.0 |
2026-09-30 | 中 | /api/ont_chain 逐值一致 ⇒ 计分板 6/17(本体三端点齐活) | ① 算法服务 ontology_views.ont_chain() 逐字照抄详情层五路分派(fault/prev/tree/plan/doc)与错误形状(含"未知链 …"与异常包装"本体查询失败: …");登记表新增 ont_chain(6 个可选参数:kind/code/system/top/keyword/dkind)。② OntController 增加 /api/ont_chain(代理 + 对外脱敏)。③ 实测:一致 6/17(facts · dq_findings · maint_survey · ont_list · ont_obj · ont_chain)· 有差异 0 · 未实现 10 · 跳过 1;--require 六条门禁通过。④ 下一批:channels(需先摸清 ETL contract(CFG) 的输入是否可直读)· maint_std(四判据 + 成熟度)· maint_framework(maint/framework.py 六个函数)· 算数大头 fleet(10 个页签取数源)· curves · LLM 类 ask/ask_status/ask_models/rpt_compose(先给裁判补 POST 请求体构造)。 |
v2.32.0 |
2026-09-30 | 中 | 本体两端点(/api/ont_list、/api/ont_obj)逐值一致 ⇒ 计分板 5/17;算法服务通用参数透传 | ① 算法服务新增适配模块 service/ontology_views.py(逐字照抄详情层包装口径:ont_list → {rows: ont_query(...).data};ont_obj → {obj, links, err}),登记表新增两条。② 算法服务通用 handler 实逮并改造:原先参数写死为 span/since/month_from/all_turbines,新增端点(ont_list 的 type/t/limit、ont_obj 的 id)只能改代码 ⇒ 改为按登记表声明的参数从查询串透传(类型校验 str/int/bool,固定值参数不接受外部传入),登记表自此真正成为"唯一需要维护的清单"。③ 新增 OntController(Java):/api/ont_list、/api/ont_obj 代理算法服务 + 对外脱敏(Redact)。④ 实测:一致 5/17(facts · dq_findings · maint_survey · ont_list · ont_obj)· 有差异 0 · 未实现 11 · 跳过 1;--require 五条门禁通过。⑤ 下一批:ont_chain(5 种 kind 分派)· maint_framework · channels · maint_std · 算数大头 fleet / curves · LLM 类 ask* / rpt_compose。 |
v2.31.0 |
2026-09-30 | 中 | /api/maint_survey 逐值一致(3/17):定下数据类端点迁移范式 + Java 复刻对外脱敏 | ① 范式定下(数据类 detail_api 端点都这么做):重算/读 parquet 这类数据活归算法服务(用户三栈令 ③ 的目标栈 = Python + FastAPI,已满足),Java 后端实现同名业务端点、经 /algorithm/... 取数、再按契约组装 —— 两侧最终走同一段 Python 实现,一致性由裁判逐值验收。② 算法服务登记表新增 maint_survey(app_ontology…maintenance.survey,只读)。③ ★Java 侧复刻对外脱敏 redact/Redact.java(与 Python 详情层 _redact 逐条对齐):Hz 前数字 → ▪▪;≥/≤ 后数字 → ≥▪(保留时间口径 h/天/日、台数计数 台/次/条/起/个、无单位小整数);判据门槛(前 8 字含 z/σ/×/倍/dev/resid/选择性/峰/结构度/ratio)必脱;含 0.593/贝兹/Betz 只做 Hz 脱敏;WINDSCADA_INTERNAL=1 全程不脱。这是"行为与重构前一致"的必答项 —— 本轮实逮:Java 直接回算法服务的原值给 ≥1.3,而线上 Python 给 ≥▪,正是缺了这一步。④ 实测:一致 3/17(/api/facts、/api/dq_findings、/api/maint_survey)· 有差异 0 · 未实现 13 · 跳过 1;--require 三条门禁通过。⑤ 下一批:maint_framework(依赖 maint/framework.py 六个函数)· ont_list/ont_obj/ont_chain(依赖 ontology MCP)· channels · 算数大头 fleet/curves· LLM 类 ask*/rpt_compose。 |
v2.30.1 |
2026-09-30 | 小 | Java 迁移范围澄清:契约 42 条中属 Java 后端的是 17 条(detail_api),算法 13 条本就是目标栈 | ★重要澄清(改口径,不做事后美化):冻契约 42 条按 kind 分为 —— detail_api 17 条(业务后端,= Java 迁移范围)· algorithm 13 条(算法服务,目标栈本就是 Python+FastAPI,用户三栈令 ③ 已满足,Java 只需经 /algorithm 调用)· gateway 7 条(页面/网关路由)· cms 4 条 · detail_page 1 条(页面)。① 因此裁判 scripts/java_contract_parity.py 增加 --java-kinds(默认 detail_api):只对 Java 范围内的端点计分,范围外单列;计分板由 y/42 改为更如实的 2/17。② 实测:一致 2/17(/api/facts、/api/dq_findings)· 有差异 0 · 未实现 14 · 跳过 1(/api/ask 为 POST,需先给裁判补"构造请求体"的能力)· 范围外 25 条单列。③ 下一批仍按难易推进:channels(依赖 ETL 侧 contract(CFG) + i18n ch_cn,需先摸清输入)→ maint_framework(依赖 maint/framework.py 的 6 个函数)→ ont_list/ont_obj/ont_chain(依赖 ontology MCP)→ 算数类 fleet/curves/maint_survey/maint_std → LLM 类 ask*/rpt_compose。 |
v2.30.0 |
2026-09-30 | 中 | Java 第二批端点 /api/dq_findings 逐值一致(计分板 2/42) | ① 新增 DqController:与 Python dq_findings_view()(serve.py:394-446)逐字对齐 —— 读同一份对象库产物 outputs/rudong/ontology/objects.json,取四族前缀 finding/{data_quality,caliber,system_coverage,tier_trend}/ 投影成 rows,按 (kind != data_quality, id) 排序,空时补 note;两侧 JSON 深度比对完全一致。② 路径解析踩过的点:Python 的 objects_json() 是 outputs/rudong/ontology/objects.json(不是 derived/ 下),故 Java 侧以 guanlan.objects-json 配置注入并从工作目录/仓库根两处探测;产物一律"读同一份、不重算",与方法学一致。③ 实测计分板:一致 2/42(/api/facts、/api/dq_findings)· 有差异 1(根路径 /)· Java 未实现 37 · 跳过 2(POST 类);--require /api/facts,/api/dq_findings 门禁通过。④ 下一批(同型:纯产物投影/读取)拟按 maint_framework → channels → ont_list/ont_obj/ont_chain 推进,再做算数类 fleet/curves/matrix/availability_summary。 |
v2.29.1 |
2026-09-30 | 小 | Java 迁移裁判修正:未实现只按 HTTP 状态判;澄清 /api/facts/claim 不在 42 条契约内 | ① 裁判 scripts/java_contract_parity.py 修正:原先"未实现"判定里带了"正文含 404 字样"这一条,会把已实现但正文含该字样的端点误判 ⇒ 改为只按 HTTP 状态(0/404)。② 事实澄清:/api/facts/claim 不在冻契约的 42 条里(契约只列 /api/facts)—— 我上一轮用 --require /api/facts/claim 要求它,属于用法错误(拿契约外的路径当门禁项);该端点 Java 侧已实现且两侧直连/经网关均 200,作为"契约外增量"记录在案,不计入 42 条计分板。③ 当前计分板(如实):一致 1/42(/api/facts)· 有差异 1(根路径 /,Java 未按契约同构返回)· Java 未实现 38 · 跳过 2(POST 类需构造请求体)。④ 下一轮开始按分层逐条实现,先用纯产物读取类(channels / dq_findings / maint_framework / maintstd / ont*)打开局面。 |
v2.29.0 |
2026-09-30 | 中 | Java 后端迁移开工:逐条比对裁判 + 同一源站灰度路由 + 首批端点 /api/facts 已一致 | 用户令「Java 后端按冻契约 42 条端点逐条迁移并灰度切换」⇒ 中版本 +1。① 新增裁判 scripts/java_contract_parity.py:按冻契约逐条真问两侧(Java 走 /java、Python 走 /detail),JSON 归一化后深度比对,输出「一致 / 有差异 / Java 未实现」计分板,并支持 --require 作门禁。② 灰度路由:Python 网关 _DEFAULT_ROUTES 实逮根本没有 /java(此前 /java/* 是走 Java 网关 28085 或直连 28120)⇒ 新增 ("/java", 28120, …) 与 _PORT_KEY/serve.json 登记,实现"同一源站两条路并存"。③ 首批端点:FactsController 落地 /api/facts(原样返回 derived/detail_cards.json,与 Python 同源同字节)与 /api/facts/claim(从 qa_refs.json 取 claim 引用);新增 app_backEnd/backend-java/run_java.py 启动器。④ 实测:/api/facts 已一致(计分板 1/42,--require 通过),/api/facts/claim 见门禁输出。⑤ 下一轮:按计分板逐条实现其余端点(先做纯产物读取类:channels / dq_findings / maint_std / maintframework / ont* / facts 系;再做算数类:fleet / curves / matrix / availability_summary;最后 LLM 类:ask / rpt_compose),每条都以裁判过关为准;42 条全绿后切入口并一次性删 Python 源码。 |
v2.28.1 |
2026-09-29 | 小 | 灰度切换第一步就绪:Vue 产物经网关可作并列入口(新增产物级冒烟门) | 用户令「先做灰度切换,Java 后端迁完再一次性删 Python 源码」⇒ 小版本 +1。① 新增 app_frontEnd/web/tools/spa_smoke.mjs 与仓库入口 scripts/spa_smoke.py:校验 /web/index.html 可达且引用构建产物、产物内含全部 10 个页签标签与 10 个视图组件、SPA 依赖的接口面(/detail/api/fleet、/algorithm/healthz)经网关可达;实测全绿。② 如实标注覆盖边界:本机无浏览器自动化、jsdom 也不能执行 Vite 的 ESM 包 ⇒ 该门是产物级验证;"呈现一致"仍由 10 页签 SSR 严格对拍承担,浏览器内交互回归不在覆盖内。③ 冒烟里的页签标签取自现网语言包(window.__L 的 tab.<id>)而不是硬编码 —— 实逮一次"期望文案猜错"的假失败(真实标签是 总览/电量算账/部件问题/故障统计/振动融合分析/发电性能/检修决策/检修助手/汇报定制/系统维护)。④ 灰度路线(按用户令):先并列入口(本轮)→ Java 后端按冻契约 42 条端点逐条迁移与灰度 → 最后一次性删除 Python 前端+后端源码,重打包并开箱验收。 |
v2.28.0 |
2026-09-29 | 中 | report 页签迁移完成 ⇒ 10/10 页签全部通过严格整页签对拍(Vue 前端迁完) | 用户令「直到 generation → decision → assistant → report → system 完成」达成 ⇒ 中版本 +1。① report(报告组装)逐字转写旧 report():控制面板(5 组章节库按钮带勾选态/图标/名称 · 预设 · 受众 · 打印/导出 · 需求文本 + 模型下拉 + 组装按钮 + 提示行)+ 纸面骨架(标题/副题/章节数 · 页脚);RPT_PRESETS/RPT_BLOCKS/RPT_ICON/MDL_LOC 一律从 app.js 原样抽出。对拍 48 条文本一致,0 例外。② 实逮并修:与 decision 同法 —— 旧 bindReport 取到模型清单后把 RPT.model 置为清单第一个键,于是提示行会带";数据不出本地";我留空 ⇒ 少一段文案。③ 10/10 页签通过严格整页签对拍:overview 138 · energy 51+图11/11 · component 260 · fault 133(例外1) · vibration 561(例外1) · generation 122 · decision 26 · assistant 40 · system 165(例外1) · report 48。④ 口径与边界(如实记):对拍对象是首屏呈现(各块正文 rptBlock 仅在用户往章节库里加块时才出现,属交互路径,本版未覆盖);3 条登记例外均为后端两条数据来源的文案不一致(非前端偏差),待后端统一后删除。⑤ 下一步(目标剩余部分):按纪律删除对应 Python 前端源码 → Java 后端按冻契约 42 条端点逐条迁移并灰度切换 → 随包 JRE + jar 的离线单包与开箱验收。 |
v2.27.0 |
2026-09-29 | 中 | assistant 与 system 两个页签迁移完成 ⇒ 已迁页签 9/10(仅余 report) | 中版本 +1。① assistant(三类查询助手)逐字转写旧 assistant():故障码纠正(输入 + 常用码链接)· 预防性维护(系统下拉)· 故障树(系统下拉),各自"查询"按钮与输出区;对拍 40 条文本一致,0 例外。② system(维护巡检)逐字转写旧 system():/api/maint_survey 数据按"数据/机理"两层出两张表(存在标记 · 覆盖 · 条数 · 末次更新 · 频率 · 责任 · 位置/摄入/说明);对拍 165 条文本 + 2 张表一致(例外 1)。③ 该例外如实登记:/api/maint_survey 的"说明"字段在页面缓存与回放快照间文案不同("确诊链判级…" vs "定谳链判级…"),与 fault/vibration 两例同类(数据两条来源),非前端偏差;待确认数据来源后删除。④ 顺带把 zh.ts 重新从现网语言包生成,消除快照漂移。⑤ 进度:九个页签过对拍(overview/energy/component/fault/vibration/generation/decision/assistant/system),仅余 report。 |
v2.26.0 |
2026-09-29 | 中 | decision 页签迁移完成(AI 决策问答,对拍全绿)⇒ 已迁页签 7/10 | 中版本 +1。① decision(AI 决策问答)逐字转写旧 decision():CATS 四类 pill · 该类常用问题三条 · 提问输入框 · 模型下拉(唯一来源 /api/ask_models)· 越界开关 · 输出区。② 修掉的三处偏差:a) 旧 bindDecision(app.js:435-436)拿到清单后把 ASK.model 置为清单第一个键,我留空 ⇒ 少一条档位说明并连带错位;b) 旧模板 SNAP ? '' : <p>…</p> 的经典版入口提示本页确实渲染(我按"v2 是快照站"想当然省略);c) MDL_LOC(模型档位表)我手抄缺项 ⇒ 档位后缀" · 云端"丢失,改为从 app.js 原样抽出。③ 对拍工具新增通用接口快照:把页面请求过的 /api/* 首次响应按路径记下(state.apis),经 renderTab(..., apis) → Workbench apis → 组件取用 —— 供 decision 及后续 assistant/report/system 复用。④ 进度:overview · energy · component · fault · vibration · generation · decision 七个页签过对拍;余 assistant/report/system 三个。 |
v2.25.0 |
2026-09-29 | 中 | generation 页签迁移完成(对拍 122 条文本一致)⇒ 已迁页签 6/10 | 中版本 +1。① generation 在严格整页签口径下与重构前一致:122 条文本全同、0 例外。② 最后一处偏差是"我把旧图的中位数注解塞进了 __data__"(对拍报"Vue 有 1 个数字不在旧图里:4212.5")——按已定规则(__data__ 只放"我画的数据且旧图会写成文字"的数字)三张图应为空:旧 capAxis/betaBar/rulerBar 只把刻度与注解写成 SVG 文字,散点/条形即数据本身。③ 关键工程改进:把"等 /api/curves 出图"做成对拍工具的显式前置条件(加载页面前先追到 figs 非空,最多 20×3 秒,超时报错而不是退化成骨架屏)—— 此前同一轮对拍会在 56/122 条之间飘,改一处飘一次、无法收敛;现在可复现。④ 本轮还修:候选机列表整串 v-html(分隔符粘前项尾部)、曲线图组补 HTML 图例(系列名)、图例色块内联数组(常量声明没落地导致 SSR 取到 undefined 而崩)。⑤ 进度:overview · energy · component · fault · vibration · generation 六个页签过对拍;余 decision/assistant/report/system 四个。 |
v2.24.2 |
2026-09-29 | 小 | generation 继续推进:补曲线图组 HTML 图例、候选机整串渲染;对拍仍受 /api/curves 建设态影响 | 仍未过对拍 ⇒ 不列入 DONE,小版本 +1 记进度。① 本轮修:候选机列表必须整串拼 HTML(旧模板 `join(' |
v2.24.1 |
2026-09-29 | 小 | generation 页签迁移进行中(结构/三图/曲线图组已落地,对拍尚差 25 条文本) | 未过对拍 ⇒ 不列入 DONE,版本按小版本 +1 记进度。① 已落地:Generation.vue 逐字转写旧 generation()(固定窗提示 · m9 控制面板 · 候选机列表 · 曲线图组),capAxis/betaBar/rulerBar/multiline 四图改 ECharts(__data__ 只放旧图写成文字的数字:两行中位/β 中位/规范线 3.7);/api/curves?win=… 与 cms 同法接进对拍(新增"追到算出图的那一份再回放",因为首次常是 building)并透传 renderTab(..., curves)。② 实逮并修:Generation.vue 误从 lib/render 导入 dv/esc(rollup 报 not exported)⇒ 改从 lib/vib;β 注里的机组链接必须 v-html(否则尖括号被转义、节点边界与旧页不同)。③ 当前对拍:generation 97 ≠ 122 条文本、图数字 220/4(子集满足)。缺口集中在 β 偏置图的 HTML 注解("38# +7.184kNm"、"虚线=物理绝对锚 ±0.25kNm … | 样本 179")与曲线图组的图题/单位("L2 功率-桨距 (控制律/削峰)"、"(°)")—— 下一轮按定点取证逐条补齐。④ 已迁 5 页签复验仍全过。 |
v2.24.0 |
2026-09-29 | 中 | vibration 页签迁移完成(5 个子视图全过对拍)⇒ 已迁页签 5/10 | 用户令「vibration(含 5 子视图)→ generation → … 直到全部完成」的第 1 个页签落地 ⇒ 中版本 +1。① 五个子视图全部通过严格对拍:matrix 561 文本+1 表(例外 1)· loop 9 文本(该子视图数据多为空,走 loop_none 分支)· units 1126 文本+2 表 · events 492 文本+9 表 · cms 158 文本+2 表。② cms 的数据来自按需异步 /api/vibcms:对拍工具新增"记录并回放该响应"(与 fleet 同法:只认第一次,并喂给 Vue 的 renderTab(d, tab, sub, cms) → Workbench cms prop),基准侧点 cms pill 后多等 4 秒;实逮一次"改了桩但 baseline() 没把 cms 返回出去"(Vue 侧一直显示"载入振动评估结果…")⇒ 已修。③ vibration 列入 src/lib/tabs.ts 的 DONE;界面不再标"迁移中"。④ 进度:overview · energy · component · fault · vibration 五个页签过对拍;余 generation/decision/assistant/report/system 五个。 |
v2.23.3 |
2026-09-29 | 小 | vibration 的 events 子视图迁移完成(对拍 492 条文本 + 9 张表一致) | 逐子视图推进 ⇒ 小版本 +1。① 旧 fusEvents(app.js:946-958)逐字转写为 eventsHtml(F, d):按部件出"报警码统计 + 近况明细"与"工单明细"两张表。② 同时把 cms 子视图的构件(gc/chainStates/evLadder)与 cmsHtml(V) 一并落地(cms 的数据来自按需异步 /api/vibcms,尚未对拍)。③ 本轮排障记录(已全部解决):"原样抽取"把下一行一起带进来 + 多次追写叠加,导致 gc/evLadder 重复声明、并留下孤立的缩进行(esbuild 报 symbol already declared / Unexpected export)—— 逐条定位删除后 SSR 构建通过。④ 对拍:vibration:events 492 条文本 + 9 张表一致,0 例外;vibration:units 复验 1126 条仍一致。⑤ 进度:vibration 5 子视图 matrix ✓ loop ✓ units ✓ events ✓,余 cms(需把 /api/vibcms 的按需数据接进对拍);vibration 仍未列入 DONE。 |
v2.23.2 |
2026-09-29 | 小 | vibration 的 units 子视图迁移完成(对拍 1126 条文本 + 2 张表一致) | 逐子视图推进 ⇒ 小版本 +1。① 逐字转写旧 fusUnits(app.js:924-944)为 unitsHtml(F, filter),并把它用到的构件 devBar/winBar/oilPill/stateChip 一并落地;devBar/winBar/oilPill 与它依赖的 CHAIN7 常量一律从 app.js 原样抽出(不手抄)。② 实逮三处并修:displayText 未定义(旧 app.js 的显示文案函数,中文口径=原样);CHAIN7 未定义;追写叠加导致 chainMini 重复声明(且 CHAIN7 抽取把后一行 const chainMini 一并带进来)⇒ 去重并删杂散片段。③ 对拍:vibration:units 1126 条文本 + 2 张表一致,0 例外。④ 进度:vibration 5 子视图 matrix ✓ loop ✓ units ✓,余 events/cms;vibration 仍未列入 DONE。 |
v2.23.1 |
2026-09-29 | 小 | vibration 的 loop 子视图迁移完成(对拍 9 条文本一致) | 逐子视图推进 ⇒ 小版本 +1。① vib.ts 追写 baBar/chainMini(chainMini 的整串正则替换从 app.js 原样抽出)与 loopHtml(旧 fusLoop 逐字转写);Vibration.vue 接上 loop 子视图。② 对拍:vibration:loop 9 条文本一致(说明:本机该子视图的数据多为空 —— 走的是 fus.loop_none 分支,所以证据量小;结构与文案一致性仍由对拍保证)。③ 进度:vibration 5 子视图中 matrix ✓ loop ✓,余 units/events/cms;vibration 仍未列入 DONE。 |
v2.23.0 |
2026-09-29 | 中 | vibration 的 matrix 子视图迁移完成(5 子视图中的第 1 个),对拍 561 条文本一致 | 逐子视图推进 ⇒ 中版本 +1。① Vibration.vue + src/lib/vib.ts:把旧 fusMatrix 与它的构件(spark/famBar/duo/tierWord/shortOf/cell/状态色表)逐字转写,用 v-html 渲染 —— 旧代码本就是拼 HTML 字符串,转写后 DOM 与文本节点边界天然一致。② VIBJARGON(技术速记→人话,6 行长正则数组)改为从 app.js 原样抽出(src/lib/vibjargon.ts),避免手抄漏项。③ pill 键名实逮:旧用 fus.sub.<s>(我写成 fus.s.<s> ⇒ 5 个 pill 全显键名)。④ 对拍结果:vibration:matrix 561 条文本 + 1 张表一致(含 1 条登记例外);既有四页签重跑仍全过。⑤ vibration 仍未列入 DONE —— 余下 4 个子视图(loop/units/events/cms)未迁;cms 还需按需异步取 /api/vibcms。⑥ 对拍门增强:例外清单改为"包含匹配"并同时作用于文本与表格。 |
v2.22.1 |
2026-09-29 | 小 | 对拍门支持子视图(页签:子视图);vibration 侦察结论入档 | 进行中 ⇒ 小版本 +1。① 对拍门新增子视图口径:node tools/render_parity.mjs <网关> vibration:matrix —— 基准侧加载后点一下对应 pill(旧页面 data-fsub)再抽锚点,Vue 侧把 sub 传进组件;renderTab(d, tab, sub)、Workbench 增 sub prop、页签文案比对含 [data-fsub]。② vibration 侦察结论(本轮实测):该页签内部分 5 个子视图(matrix/loop/units/events/cms,旧 FUS.sub),不含图表(无需 ECharts),但依赖约 10 个 SVG/HTML 小构件(spark/famBar/baBar/winBar/devBar/chainMini/chainStates/oilPill/evLadder/gc),且 cms 子视图按需异步取 /api/vibcms ⇒ 需逐子视图迁并对拍。③ 四个已迁页签重跑仍全过(overview 138 · energy 51+图11/11 · component 260 · fault 133 含 1 例外)。 |
v2.22.0 |
2026-09-29 | 中 | fault 页签迁移完成(4/10 过对拍);对拍门加“显式例外”并记下后端一处口径文案不一致 | 用户令「迁 energy/component/fault 三页签」的第三个落地 ⇒ 中版本 +1。① fault(故障统计)在严格整页签口径下与重构前呈现一致:文本 133 条(含 1 条登记例外)、2 张表全同、图数据 132 ⊆ 旧图。本轮补齐的关键三处:Pareto 图的 HTML 摘要("关键少数: 前 N 项占 80%"、"前三: 码 名 · …"、note —— 旧 paretoChart 返回的 HTML 而非 SVG,用定点取证 tools/probe_baseline.mjs 查明)、季节性图的 HTML 图例(旧 multiline 的 .legend,4 条系列名)、rate 示例的守卫条件(旧代码 i0>=0 && mo.per_day 即便值为 null 也照样渲染)。② 图数据子集规则下把 __data__ 收敛到"旧图真的写成 SVG 文字的数字"(柱状/条形图的值;散点/折线只标刻度故为空),并改正两处口径:ramChart 旧为 MTBF×MDT 散点、attribBar 旧分组为 ok=总−无记录−未归类 / unk / un2。③ 对拍门加显式例外清单(ALLOW,每条必须写理由并在结论里报数):已登记 1 条 —— m8.mtbf.口径 在后端两条路径上文案不一致(页面的按窗缓存给"(MTBO统计方法)/(纯故障统计方法)",实时 /api/fleet 给"(MTBO口径)/(纯故障口径)");两侧同字段同模板 ⇒ 非前端偏差,待后端统一口径后删除该例外(已作为遗留项记录)。④ 顺带实逮并修正对拍工具:页面有 pending 轮询,桩若记录"最后一次"响应,两侧数据版本会不同 ⇒ 改为"记录页面第一次拿到的 /api/fleet 并回放给后续请求"。⑤ 进度:overview · energy · component · fault 四页签过对拍;余 vibration/generation/decision/assistant/report/system 六个。 |
v2.21.2 |
2026-09-29 | 小 | fault 对拍推进:Pareto 图内 HTML 摘要逐字复现(含前三),图数据改用原值 | 进行中 ⇒ 小版本 +1。① 定点取证 tools/probe_baseline.mjs(在旧页面 DOM 里按文本找父元素)实逮:旧 paretoChart 除 SVG 外还返回一段 HTML —— <b>关键少数: 前 N 项占 80%</b> (共 M 项, 合计 X unit)<br>前三: <b>码</b> 名 · …<br>note;本版按同构 v-html 复现(三处 Pareto:次数/时长/停机),文本差异由 133≠103 收敛到 133≠129。② 图数据比对:__data__ 改用原图打印的原值(旧图 txt(..., v) 直接写值,不四舍五入);并把 ramChart(旧为 MTBF×MDT 散点)与 attribBar(旧分组 ok=总−无记录−未归类 / unk=无记录 / un2=未归类)的口径改正 —— 此前我给的是"停机时长柱/设备·外部·无记录",属口径用错。③ 仍差 4 条文本:停机 Pareto 摘要"前三"的第 2/3 项与其分隔符(“1020 / 就地操作模式 · / 2700 / 塔筒频率外部允许窗口”)与一处注文顺序;fault 仍在 IN_PROGRESS,不列入 DONE。 |
v2.21.1 |
2026-09-29 | 小 | fault 页签迁移进行中(未过对拍,如实标注)+ 对拍门两处口径修正 | 进行中 ⇒ 小版本 +1。① Fault.vue 已按旧 fault() 实现全部区块(警报面:月度故障率 · 次数/时长 Pareto · 可靠性×可维修性象限 · 逐台故障表 · 季节性;停机面:RAM 分解 · 停机 Pareto · 停机台次表),图表用 ECharts;但严格整页签对拍尚未通过(当前 133≠103 文本、图数字子集不满足),故不列入 DONE,界面标"迁移中"(新增 IN_PROGRESS 常量)。② 本轮对拍门两处口径修正:(a) 图数据比对由"集合相等"改为子集(旧图把数据与坐标刻度都写成 SVG 文本,ECharts 刻度在画布上取不到;子集规则抓"画错/画多",不苛求刻度);(b) 文本比对明确要求文本节点边界一致(旧模板一个插值里拼多段 = 一个节点)。③ 本轮已修:winBanner 的 " |
v2.21.0 |
2026-09-29 | 中 | 三页签通过严格整页签对拍(overview/energy/component)· ECharts 图表数据级一致 | 用户令「迁 energy/component/fault 三页签并逐页签对拍」的收口:overview / energy / component 三页签在严格整页签口径下与重构前呈现一致 ⇒ 中版本 +1。① 对拍门(app_frontEnd/web/tools/render_parity.mjs)本版实测:overview 138 条文本全同;energy 51 条文本 + 1 张表 + 图表数字集合 11/11 一致;component 260 条文本 + 2 张表全同。② 逐条修掉的偏差(每条都由对拍指出,不是靠眼看):a) 页头窗徽应为 t(win.label) + " · " + winName(win)(我写成 win.l+值);b) 旧 CH.blameBar 的图例是 HTML 三段(名称/数值/说明)不是画布 ⇒ 必须照渲,否则少 9 条文本;c) 瀑布图数字集合口径 = theo · act · Σitems · 各 item · 组占比%(ECharts __data__ 按同一公式给数);d) 文本节点边界也要一致:KPI「报警台数」旧模板是 <b>28 <small>/ 38</small></b> 两个节点(用 v-html 复现)、九系统卡计数三段拼成一个插值、命中系统格用 v-html 复现"锚+文本分隔符+锚";e) 块顺序:旧页面是 KPI → 需要关注 → 全场状态 → 九系统(我原先把九系统放在状态条之前);f) cmp.rel_meta 传原始值不 fmt;rel_note 与 cmp.fusion_n("(107 台次收录)")漏了要补;g) 徽章前空格会被 Vue 模板空白压缩吃掉 ⇒ 用 {{ ' ' }} 显式给。③ fault 页签仍未迁移(下一步);总览/电量/部件三页签的 Python 前端源码暂不删(需全 10 页签通过)。④ 客户端产物 release/web 重建;契约冒烟 42/42、HTTP 契约门 42/42、模块边界门 OK。 |
v2.20.0 |
2026-09-29 | 中 | ECharts 引入 + Java 网关/OAuth2/Security 落地;呈现对拍门升级为“严格整页签” | 用户令 2026-09-29(第二轮):引入 ECharts;补齐 spring-cloud-gateway / oauth2 / security 构件;迁 energy/component/fault 三页签并补打四个模块包。⇒ 中版本 +1。① 构件获取(实逮纠正):上一轮判"Maven Central 不可达"是瞬时探测失败 —— 实际 repo.maven.apache.org / maven.aliyun.com / repo.huaweicloud.com / mirrors.cloud.tencent.com 均可达。新增 settings-online.xml(阿里云 public 镜像)把 spring-cloud-starter-gateway 2021.0.9、spring-boot-starter-security、spring-boot-starter-oauth2-resource-server、spring-security-oauth2-jose、nacos-discovery 2021.0.5.0 下到用户本地仓(mvn -s settings-online.xml compile 成功)。② 离线可复现:settings-offline.xml 补与联机同名的 mirror/repository id,并加 -Dmaven.legacyLocalRepo=true(实逮:来源仓库 id 不一致会让 mvn -o 误报"不可达");Nacos 依赖显式钉版本(离线时 BOM 导入不参与解析)。③ Java 网关独立成工程 app_backEnd/backend-gateway/(实逮:Spring Cloud Gateway 走 WebFlux,与本工程 MVC+springfox 同进程不兼容):Spring Cloud Gateway + OAuth2 资源服务器 + Nacos(可关);端口 28085,与现 Python 网关 28084 并存、按前缀灰度。实测经它 /algorithm/healthz、/web/index.html、/detail/api/facts 全 200。④ OAuth2+JWT 闭环(业务后端):/java/token 自签 HS256(无 IdP 的离线口径)、/java/secure/whoami 带 token 200(authenticated=true, SCOPE_guanlan.read)、不带 token 401;Swagger UI 仍 200。实逮两坑并已修:Nacos 在 classpath 就抢连(需 spring.cloud.nacos.discovery.enabled=false)、application.yml 出现两个 guanlan: 顶层键导致 snakeyaml DuplicateKey。⑤ 前端(进行中,未完成):引入 ECharts 6.1.0 与 EChart.vue 包装;Energy.vue(4 KPI + 水位图/责任分账两图 + 工况态表)、Component.vue(九系统卡 + 可靠性表 + 跨系统关注台表 + 系统详情)已迁;fault 未开始。语言包改为全量搬(845 键,此前只挑前缀导致 en.*/cmp.* 取不到词)。⑥ 对拍门升级:tools/render_parity.mjs 从"分块锚点"改为整页签比对(#root 文本序列 + 表格逐行 + 图表数据数字集合;Vue 侧摘掉页签导航单独比),页签由 hash 驱动。当前它如实报出未通过:overview 138≠95 文本、energy 51≠42 文本与 11≠16 图数字、component 260≠243 文本 + 一处空格差异("运维操作 外部")。⇒ 上一轮"总览 11 组一致"更正为"总览前三个区块一致、整页签仍有差异"。⑦ 四个模块包已按本版补打(app_frontEnd/app_ETL/app_algorithmModel/app_backEnd)。 |
v2.19.0 |
2026-09-29 | 中 | Vue 迁移第一个页签(总览)+ 呈现对拍门:jsdom 跑旧页面 vs Vue SSR,锚点逐项一致 | 三栈重写(前端)⇒ 中版本 +1。① 迁移:app_frontEnd/web/src/views/{Workbench,Overview}.vue —— 页签清单与重构前 app.js 的 TABS 逐字一致(10 个,含 system);总览页签按 app.js 的 overview(d) 逐块搬出 KPI 卡(6)、需要关注卡(含"查看完整依据"与卡在哪一步)、全场状态条(38 格 + 台号 + 静默台数);渲染口径函数(状态枚举/台号/数字格式/台级状态取最严)原样搬到 src/lib/render.ts,文案搬到 src/i18n/zh.ts(105 键,逐字取自现网语言包,由对拍复核)。② 呈现对拍门(本轮核心):app_frontEnd/web/tools/render_parity.mjs —— 因为 /detail/v2 是浏览器里现渲的单页(HTML 只有壳 + 内联 app.js + 语言包),所以基线不能靠 curl,必须让旧代码真跑一遍:jsdom 加载现网页面 + 在 beforeParse 装 fetch 桩转发到真实网关(实逮:桩晚装一句就 fetch is not defined、基线全空)+ 等 .kpis 出现;再用同一份数据(桩记录下的 /api/fleet 响应)把 Vue 组件 SSR 出来,抽同一批锚点比对:KPI 值/文案/类名、需关注卡的 id/部件/状态词、状态条格子的类名/data-u/台号、静默文案、页签文案 —— 11 组全部一致。③ 附带:类名比较按排序后的集合(旧页 kpi warn / Vue warn kpi 只是属性顺序,实逮后归一)。④ 未迁移的 9 个页签在界面上如实标"迁移中",不造假界面;tools/contract_smoke.mjs 仍 42/42 一致。 |
v2.18.0 |
2026-09-29 | 中 | 后端 Java 化(P12 起步):Spring Boot 2.7.18 + springfox Swagger 离线可编可跑,与算法服务打通 | 三栈重写第三步(用户令 2026-09-29:后端完全 Java + Spring Boot + Swagger,与算法模块经接口交互;用户指定用本机 JDK 1.8 + Maven)⇒ 中版本 +1。① 工程 app_backEnd/backend-java/:Spring Boot 2.7.18 + spring-boot-starter-web + springfox-boot-starter 3.0.0 (Swagger UI + OpenAPI 3.0)+ RestTemplate 调算法服务;控制器 /java/healthz、/java/algorithm/endpoints、/java/algorithm/{name}(13 条只读白名单,与算法服务登记表同源);application.yml 端口 28120(与现有 Python 后端并存,迁移期两套同跑、逐条对拍)。② 离线实逮(本机仓残缺,逐条绕开并记在 README):mvn package 打不出 jar(缺 maven-archiver、plexus-utils 1.1);surefire 缺运行期依赖;缺 spring-boot-loader-tools ⇒ 不打 fat jar;springfox 运行期要 mapstruct(未传递);Boot 2.6+ 需 ant_path_matcher。因此改走 mvn -o compile + 自组装 target/lib(53~54 jar / 26.4 MB),由 build_offline.py 一键完成(环境变量优先、随工程带 settings-offline.xml,仓里不写死本机路径)。③ 实测证据:/java/healthz 200 且 algorithm_ok=true(Java→FastAPI 通)、/java/algorithm/endpoints 返回 11 个端点、/swagger-ui/index.html 200、/v3/api-docs 200(OpenAPI 3.0.3)。④ 交付与打包:Java 构建输出 target/ 明确不进包(pack_dist EXCLUDE_DIRS);交付形态 = 随包 JRE + classes + lib。⑤ 迁移纪律:按冻契约 42 条端点逐条搬、逐条对拍(Python 门 + Node 冒烟),通过后才删对应 Python 源码;Gateway/Nacos/OAuth2 待依赖到位再接。 |
v2.17.0 |
2026-09-29 | 中 | 前端 Vue 化(P11 起步):Vue3+Vite+TS 工程落 release/web、经网关 /web 同源伺服、契约冒烟两侧一致 | 三栈重写第二步(用户令 2026-09-29:前端完全 Vue.js + Node.js,与后端结构交互;用户选定"先冻契约 → 前端 Vue 优先")⇒ 中版本 +1。① 工程 app_frontEnd/web/:Vue 3 + Vite 6 + TypeScript + Node 24(依赖取自可达的 registry.npmmirror.com,npm install 50 包 13 秒);npm run build → release/web/(index.html + assets,gzip 后约 28 KB);取数入口 src/api/contract.ts 只走相对路径(/api、/algorithm),与冻契约 http_api_v1.json 的路径一一对应。② 运行体系接入:configs/serve.json 加 web=28110;cli.services() 加 web 静态组件;网关加路由 /web → 28110 —— 于是 Vue 页面与后端/算法同源,页面里的相对取数直接可用。③ 两侧对拍:scripts/http_contract_audit.py(Python 门,已在 guanlan.py check 里)与 app_frontEnd/web/tools/contract_smoke.mjs(Node,走同一网关同一批路径)—— 实测均 42/42 一致,Vue 前端 /web/index.html 200 且挂载点就位。④ 契约支持"异步构建态":/api/curves 记为双形状(json_keys_any)—— 产物仓在位返回 figs/physics、后台构建中返回 building/months/span/win,两者皆合法(node 侧冒烟曾据此实逮误报)。⑤ v2 工作台逐页签迁移与"删对应 Python 前端源码"留待下一阶段(对拍通过后再删)。 |
v2.16.0 |
2026-09-29 | 中 | 冻契约:现有 HTTP 面固化成契约正本 + 在线复核门(并入 guanlan.py check) | 三栈重写第一步(用户令 2026-09-29:前端 Vue / 后端 Java / 算法 FastAPI,"确保与重构前一致";用户选定"先冻契约 → 前端 Vue 优先")⇒ 中版本 +1。① 抽面:从 serve.py / windcms serve.py / gateway.py / 算法登记表 / 壳与 JS 里抽出 53 个候选路径;② 逐路径双方法探活(GET+POST),据实定方法/状态/形状 —— 42 条至少一种方法返回 200;③ 契约正本 app_backEnd/app_backEnd_guanlan/contract/http_api_v1.json(42 条端点:类别/路径/方法/状态/JSON 顶层键或 HTML 标题)+ 人读版 docs/接口契约_前后端_v0.1.md;④ 复核门 app_qualityGate/.../audits/http_contract_audit.py(CLI 壳 scripts/http_contract_audit.py)并入 guanlan.py check:方法/状态码/JSON 顶层键必须与契约一致(值随数据变不比),实测 42/42 一致、check 全绿。它是 Vue/Java/FastAPI 三条线的对拍口 —— 任何一条偏离都会在这里报出来。 |
v2.15.2 |
2026-09-29 | 小 | 算法服务随 serve 默认起(并入网关 /algorithm,端口取 configs/serve.json) | 用户令 2026-09-29「算法服务随 guanlan.py serve 默认起」⇒ 小版本 +1。① cli.services() 增加 algorithm 组件(端口取 configs/serve.json 的 algorithm,缺省 18050)—— guanlan.py serve / start.bat / 服务化启动都会连带起算法服务;② 统一网关加路由 /algorithm → 上游 18050(探活 /healthz):前端与后端(各栈)都从一个源站调算法,不必直连端口;③ ops.py 的 DEFAULT_PORTS 加 algorithm(运维控制台兜底端口表);④ scripts/guanlan_offline_up.sh 加 18050 启动行;⑤ configs/registry.yaml 里 serve.json 的 schema 加 algorithm 键。验收:guanlan.py stop → guanlan_start_hidden.py(= serve)后,直连 http://127.0.0.1:18050/healthz 与经网关 http://127.0.0.1:28084/algorithm/healthz 均 200,/algorithm/api/endpoints 返回 11 个端点;门户与其它组件不受影响;全门禁与 guanlan.py check 全绿。 |
v2.15.1 |
2026-09-29 | 小 | 算法服务消缺:日志纳入统一格式(logs/algorithm.log)+ 端点登记表按实测收口 + 模块入口可起服务 | 缺陷修复 ⇒ 小版本 +1(2.15.0 同日)。① 日志:算法服务原先用裸 stdout 重定向,guanlan.py check 的"日志统一"门禁实逮 FAIL(logs/algorithm_service.log 末尾 104 行都不符合 "时间戳 级别 组件 消息");现改为入口调 logfile.prefix_stdout('algorithm')(与 detail/cms/gateway/static_server 同一套设施),日志落 logs/algorithm.log,门禁转全绿。② 端点收口(逐值对拍时实逮):撤掉 availability(=perf.availability.build() 只写盘返回 None,不是接口);撤掉 matrix/pitch/curves/reliability 的 span 参数(这些函数的 span 是跨度对象不是窗口字符串,传字符串必炸:Given date string "2" not likely a datetime / too many values to unpack);保留实测可用的 reliability.since、fusion.all_turbines、availability_summary.month_from。③ 模块入口:bootstrap 的 app_algorithmModel 增加 service 入口(run.bat service / sh run.sh service → 起 FastAPI 服务,默认 18050),app_algorithmModel/README.MD 补"算法服务"一节(端点表 + 离线依赖 + 对拍口径)。验收:11 个端点 + 3 个带参抽查逐值对拍一致;guanlan.py check 全绿;总包开箱 5/5 + 卸载核验;算法模块包自检通过。 |
v2.15.0 |
2026-09-29 | 中 | 算法服务化(P10):算法层包成 FastAPI 服务(11 个只读端点 + OpenAPI/Swagger),离线依赖随包 | 功能新增(目标技术栈第一步)⇒ 中版本 +1。用户令 2026-09-29:前端 Vue/TS/Node · 后端 Java + Spring Cloud Alibaba(Nacos/Gateway/OAuth+JWT)+ Spring Boot + Swagger + MyBatis-Plus · 算法 Python + FastAPI;经确认本期只做算法一步。① 实现 app_algorithmModel/app_algorithmModel_guanlan/service/{app,registry,jsonable,deps}.py:FastAPI 应用 + 端点登记表(判级矩阵/对账/可靠性/问题清单/可用率摘要/融合面/交接件/变桨面/曲线仓/曲线检查/维度字典)+ 确定性 JSON 归一化 + 依赖兜底;入口 scripts/algorithm_service.py(端口 18050,登记 configs/serve.json 的 algorithm)。② 只读:带写盘副作用的参数在登记表里固定成只读值(curves.write=False)。③ 离线依赖实逮:目标机离线且 wheels/ 无 FastAPI 轮子,而开发机 .venv 是 include-system-site-packages (fastapi/uvicorn 来自系统 Python)⇒ 把运行栈整目录随包 vendor/pyfastapi/(15.9 MB,含 dist-info),ensure_fastapi() 在导入失败时插 sys.path,并已按"纯 stdlib + 该目录"验证可导入。④ 验收:逐值对拍 —— /api/<端点>/raw 的确定性 JSON 与进程内直调逐字节一致(sha256 相等),11 个端点 + 3 个带参抽查全部一致(曲线仓 69.4 万字节 81 秒、判级矩阵 2.1 万字节)。⑤ 零行为变化:不改现有进程内调用链,页面/CLI/产物不变;是否随 serve 默认启动留待后续。文档:设计说明新增 §3.5 算法服务化。 |
v2.14.0 |
2026-09-29 | 中 | 分别打包:前端 / 后端 / 算法 / 数据接入与管理 各自成包(含依赖闭包 + 独立 install/run/uninstall) | 功能新增(打包形态)⇒ 中版本 +1。用户令 2026-09-28「前端、后端、算法、数据接入及管理 支持分别打包」。① 打包器加 --module <名>:产物 app_guanlangv<版本><模块>.zip;模块包 = 该模块 + 它依赖的模块(按 configs/modules.yaml 的 allow 递归闭包)+ 公共层 + 共享支撑件(src 兼容壳 / scripts / configs 单件 / wheels·vendor 离线依赖 / reference;前端与后端另带 release·resources,算法带 resources)。② 包根写 MODULE_PACKAGE.json(模块 + 闭包 + 版本),模块目录里的 install/run/uninstall(bat+sh)改双模:总包内调安装根统一入口;独立模块包走新增的 app_common/.../bootstrap.py(自建 .venv、离线装依赖、自检、按模块起服务或跑链、卸载)。③ bootstrap 自检覆盖:目录与 6 个入口脚本、版本一致、配置单源、公开面可导入;run 支持 --cmd(后端 serve/check/status/stop;前端 portal 静态服务;ETL/算法按脚本名跑,ETL 默认 --dry-run);list 列出各模块可运行入口。④ 新增门:根 VERSION 镜像文件必须与 version.py 同号(version_log --check 里查 —— 此前它是 0.2.0 的历史遗留,与真源脱节)。⑤ 打包验证加 --verify <zip> --module <名>:解压 → 入口引用闭合与编码守则 → bootstrap 自检 → 可运行入口列举。验收:四个模块包各自出包并验证通过;总包开箱 5/5 + 卸载核验;全门禁 rc=0;guanlan.py check 全绿。 |
v2.13.0 |
2026-09-28 | 中 | P9 源码目录结构变更:实现包上提模块根 + 每模块 common/configs/data/README/入口脚本 + 配置双根 | 用户令 2026-09-28 变更重构要求(架构布局变更)⇒ 中版本 +1。① 实现包上提:app<模块>/common/app<模块>guanlan/ → app<模块>/app_<模块>guanlan/(7 模块),全仓点号 540 处 + 实路径 190 处一次改写(src/** 壳、scripts/** 壳、api.py、安装器、打包器、门禁、文档)。② 旧前缀兼容:common/app<模块>_guanlan/init.py 用 sys.meta_path 前缀重定向(sys.modules[旧名] is sys.modules[新名],不产生两份模块对象),保留一个版本。③ 每模块补齐 common/(模块内通用组件)、configs/(模块专属配置)、data/(数据件预留)、README.MD(含安装部署与运行)、install/uninstall/run(bat+sh,内部调安装根统一入口;纳入入口引用闭合,92 条)。④ 配置双根:app_ETL/configs/{canonical,contracts,farms}(164 件)与 app_frontEnd/configs/terms(3 件)下放;安装根 configs/ 只留共用单件(serve.json/models.json/portal_pages.yaml/modules.yaml/registry.yaml);P.config()/P.config_dir() 多根查找 + 单源校验;登记表加 owner,config_audit 按归属根校验。⑤ 门禁联动:模块边界 R1/R2/R5 改新布局(并修 _TARGETS 带注解写法漏检);uninstall --all 纳入模块目录。验收:189 个模块文件新旧前缀同体导入;全门禁 rc=0;guanlan.py check 全绿;起服务逐页(/detail/v2 唯一差异为页内注释里的配置路径 +13 字节);打包开箱 5/5 + 卸载核验通过。 |
v2.12.1 |
2026-09-28 | 小 | 源码梳理与死代码清理:删 cms_availability(275 行,另有实现)+ 清本地残留 15.4 MB | 清理类改动(不改行为口径)⇒ 小版本 +1。用户令「梳理源代码,及清理无用源代码程序」。新增 docs/源代码梳理_v0.1.md(761 受管件 / 437 .py / 72,787 行 / 158 兼容壳的规模与分层、十条根入口、23 个质量门、依赖纪律 R1–R8,以及按"引用计数 + 出处"取证的五类无用件清单)。① 删死代码: app_ontology/.../sop/cms_availability.py(275 行)与壳 src/sop/cms_availability.py(23 行)——全仓无调用,L0 数据可用性判据的实际实现在 scripts/rudong_model_run.py::l0_layer;并从 app_ontology/api.py 摘掉 sop_cms_availability 公开名。④ 清本地残留: scripts/sim_hub/frames/(37 张 PNG,8.7 MB,本就 .gitignore)+ 全仓 46 个 pycache 与散落 .pyc,共释放约 15.4 MB(.venv 未动)。②③ 两批(8 件零引用一次性生成器、33 个无人使用的旧路径壳)经用户裁示保留;C 类接入点契约(MinIO objectstore / Redis cache)保留。验收: 全门禁 rc=0(模块边界 R1–R8 / 配置统一 / 页面归口 / 产物反向呼应 / 链路缺口 / 可移植 / 版本记录 / 依赖台账)+ guanlan.py check 全绿 + 起服务逐页探活 + 打包开箱 5/5 + 卸载核验。 |
v2.12.0 |
2026-09-28 | 中 | 模块化重构收官 P7:质量门与打包安装迁移(23 件 / 7,426 行)——七个模块齐备 | 重构收官的架构里程碑(七个模块目录 + 公开面 + 兼容壳齐备)⇒ 中版本 +1。P7 把质量门与打包安装 23 件 / 7,426 行迁入 app_qualityGate/app_qualityGate_guanlan/{audits,docs,pack}/;旧路径 scripts/<件>.py 留 CLI 壳(公开名同面转发 + main(),guanlan.py check 的 importlib 载入照旧)。*根引导脚本 install.ps1/install.sh/uninstall./check.bat/pack.*/start |
v2.11.9 |
2026-09-28 | 小 | 模块化重构 P6:本体与知识层实体迁移(58 模块 / 19,775 行) | 重构推进(源码组织层)⇒ 小版本 +1。本体 20 件 + SOP 38 件迁入 app_ontology/app_ontology_guanlan/{ontology,sop}/;旧路径 src/ontology/<件>.py、src/sop/<件>.py 全部留兼容壳 (模块别名 + python -m 经 runpy 重跑实现,重算链 ⑦ 步命令不变)。实逮: ① 包内 from .. import paths(23 处)改绝对路径;② 19 处 file 取根改 install_root();③ -m 入口必须由壳 runpy.run_module(run_name="main") 兜住;④ 按源码路径读本层的审计器与登记表(audit_chinese_terms、check_portability 的 ALLOW 键、products_reverse_audit 的生成端、configs/{registry,terms/jargon_rules}.yaml)同步改位置。验收: 58/58 模块新旧路径同体导入 + 取根抽查正确 + 十条本体/SOP 路由响应体逐字节等于迁移前 + -m 旧入口冒烟通过 + 全门禁 rc=0 + 开箱验证 5/5。 |
v2.11.8 |
2026-09-28 | 小 | 消缺:guanlan.py stop 在 pids.json 读不动/删不掉时抛异常中断 | 消缺(不改行为口径,只修坏掉的路径)⇒ 小版本 +1。根因: cli.py::cmd_stop() 直接 PIDS.unlink(),而服务宿主与启动器并存时 run/pids.json 可能已被清掉、被句柄占用或读到一半;2026-09-28 远端同步 2.11.7 时实逮:guanlan.py stop 以 FileNotFoundError 中断,组件其实已停掉。修法: 读记录失败按空记录处理(如实报一句);删记录失败只报一句,不影响停机结果与退出码;v.get("pid") 容忍记录缺字段。回归: pids.json 不存在 / 是目录(读+删都失败)/ 内容损坏 三种情形均不抛异常且 rc=0。验收: 本机 guanlan.py stop 正常停六个组件并删记录、再跑一次给友好提示 rc=0;三情形回归 3/3 通过;全门禁 rc=0。 |
v2.11.7 |
2026-09-28 | 小 | 模块化重构 P5:前端层实体迁移(13 件;经典页模板从 serve.py 抽出) | 重构推进(源码组织层)⇒ 小版本 +1。前端层迁入 app_frontEnd/app_frontEnd_guanlan/:assets/{app.js,app.css,charts.js,favicon.svg,classicchart.js}、pages/{shell.html,build.py,snapshot.py,classic.py,classic*.html}、design.py、lang.py、terms.py(经用户裁:语言包与显示层术语归前端)、builders/{portal_build,portal_fix_anchors,portal_inject_claims}.py。serve.py 的经典页模板(CHART_JS/PAGE_FLEET/PAGE_PROBLEM/PAGE_TURBINE,约 246 KB)抽成真资源件 + 只读装载器,serve.py 5549 → 2707 行,模板值逐字节一致。旧路径全部留壳(5 个模块别名壳 + 3 个 CLI 壳,python -m 照旧)。实逮:① 资源件无壳可留 ⇒ 六个按路径读它们的审计器/登记表同步改;② 子目录取根层数变 ⇒ 统一 install_root();③ 模板装载必须 newline=""(否则换行翻译改掉字节);④ 搬迁中被工具改写的换行风格要按 HEAD blob 对齐,避免整文件伪 diff。验收:build.render 四组合与 design 两段 CSS 逐字节等于迁移前;四个模板常量与三张经典页渲染逐字节一致;portal_build --verify 与 20.19 MB 门户逐字节一致;服务重启后门户//detail/v2//ops//cms/ 页面体 sha256 一致;全门禁 rc=0;开箱验证 5/5。 |
v2.11.6 |
2026-09-28 | 小 | 消缺:服务 restart 的等待判据把 STOP_PENDING 当成已停(远端实测吃 1056) | 消缺(承 2.11.5,同一动作的判据收紧)⇒ 小版本 +1。2.11.5 把 sc.exe restart 拆成"停 → 等 → 起"后,等待判据写成"状态不是 RUNNING 就算停稳"—— 而 sc.exe stop 是异步的,SCM 先回 STOP_PENDING,该判据立刻为真,于是 start 抢跑,远端 Windows 服务上实测报 1056(服务的一个实例已在运行),网关/仿真/三维端口被停掉约一分钟(站点短暂不可用)。修法: 新增 win_state()(按 STOP_PENDING / START_PENDING / RUNNING / STOPPED 顺序认状态字)与 wait_state("STOPPED", 120s),必须等于 STOPPED 才继续;start 再给三次机会(间隔 5 s)兜 SCM 状态刚落地的偶发 1056/1058。补回归测试: 用真实 sc query 的四种输出喂 win_state(),并断言 STOP_PENDING 下 wait_state("STOPPED") 不会提前为真。验收: 本地回归 6/6 + restart --dry-run 三步全打印 + 远端 Windows 服务用新 restart 真重启成功(服务 RUNNING、六个端口重新监听、七条路由全 200)。 |
v2.11.5 |
2026-09-28 | 小 | 消缺:Windows 服务 restart 是无效命令(sc.exe 无 restart 子命令) | 消缺(不改行为口径,只修坏掉的动作)⇒ 小版本 +1。根因: scripts/service_ctl.py restart 在 Windows 上落成 sc.exe restart guanlan,而 sc.exe 没有 restart 子命令 ⇒ 实际只打印用法帮助并以非零码退出,服务从未被重启(此前只能用 stop + start 两步绕过)。修法: 新增 win_restart() / wait_stopped() —— 先 sc.exe stop,轮询 sc.exe query 直到不再是 RUNNING(最长 90 s),再 sc.exe start;因为 stop 是异步的,不等停稳就 start 会吃 1056/1058 错。--dry-run 现在会把"停 / 等停稳 / 起"三步都打印出来。Linux 侧 systemctl restart 本来就对,不动。验收: restart --dry-run 打出 stop+start 两条;真跑到远端 Windows 服务上又逮到"等待判据只看不是 RUNNING"⇒ STOP_PENDING 抢跑、紧接着 start 吃 1056(服务的一个实例已在运行),网关等端口被停掉 ⇒ 见 2.11.6。 |
v2.11.4 |
2026-09-28 | 小 | 模块化重构 P4:后端层实体迁移(21 文件 / 10,482 行,服务与入口留壳) | 重构推进(源码组织层)⇒ 小版本 +1。后端层(cli/serve/gateway/ops/service/starthidden/ops*/windcms 服务侧 4 件/config/terms/i18n/lang/report_export/deid*)迁入 app_backEnd/app_backEnd_guanlan/;根 guanlan.py 与 scripts/<9 件> 留 CLI 壳、src/<库件> 留模块别名壳;网关—Nginx 接入点契约改名 gateway_contract.py 避免与真实现撞名;13 处 file 安装根推算改为公共层 install_root()。实逮并修掉: ① CLI 壳 sys.path 插错层;② serve/gateway 无 main()(入口在 main 守卫)⇒ 壳改 runpy 兜底;③ P0 接口契约同名挡住 git mv;④ 审计器 detail_deps 按旧路径读 serve 源码(改读新位置);⑤ 网关按同目录兄弟名找 guanlan_ops.py(改找同包 ops.py)。验收: 服务起停 + 六条路由全 200(/、/detail/v2、/detail/api/fleet、/ops、/ops/api/state、/cms/、/sim/)+ 全门禁 rc=0 + 开箱验证 5/5。 |
v2.11.3 |
2026-09-22 | 小 | 模块化重构 P3:算法层实体迁移(26 文件 / 3,858 行,逐值对拍零变化) | 重构推进(源码组织层)⇒ 小版本 +1。落地: 算法层(taxonomy、audit、perf/、subsys/ 与随迁的 windcms 分析件 6 个)迁入 app_algorithmModel/app_algorithmModel_guanlan/;旧路径留兼容转发壳;跨模块依赖改经公开面(数据层 app_ETL…api,本轮为它补函数级公开名 load_10min/contracted_cols 与 slim;安装根 app_common…api)。验收=逐值对拍: 同一时间窗下 25 项算法输出(判级矩阵/七镜头曲线/M9/可靠性/四轴 registry/限电/故障/趋势/功率曲线),迁移前后 24 项逐字节一致,唯一差异为 trend.attribution_router 报出的缺件名(快照自身写产物所致);同状态重跑两次 25/25 一致(同一总哈希 ee80df59…→77319d18…→77319d18…)。实逮并修掉: ① 导入改写规则顺序误伤 windcms 侧 .data/.config(5 处);② from . import X 类模块对象导入未覆盖;③ 函数级公开名需在 api 显式暴露。全门禁 rc=0(含模块边界 R2/R3/R6/R7/R8),开箱验证 5/5。 |
v2.11.2 |
2026-09-22 | 小 | 模块化重构 P2:数据接入管理实体迁移(4 库模块 + 12 构建器,scripts 留 CLI 壳) | 重构推进(源码组织层)⇒ 小版本 +1。落地: ① 四个库模块(data/scada_source/slim/mdb_names)与十二个构建器(rebuild_from_raw、rebuild_all、scada_slim_build、windscada_monthly_build、vib_raw_build、raw_scan、raw_data_check、place_raw_data、pitch_face_build、baseline_38_build、component_history_build、csv_to_mdb)迁入 app_ETL/app_ETL_guanlan/;② scripts/<同名>.py 留 CLI 兼容壳(导入实现并原样返回退出码)—— scripts/<构建器>.py 这条路径被链、审计器与文档引用约 269 处,必须保留;③ 构建器安装根推算改用公共层公开面 install_root(不再用 file.parents[1]);④ 公共层 api.py 公开 install_root,满足「模块间只经 api 调用」的边界规则。实逮并修掉: 包内相对导入(from .config、from . import scada_source、from .mdb_names 共 6 处)在换包后指向不存在的模块。验证: 12/12 构建器可导入;raw_scan --check、scada_slim_build --check、rebuild_all --dry-run(26 步 / --skip-scada 23 步)全部 rc=0;库模块旧路径别名与模块身份实测一致;guanlan.py check、config_audit、pages_audit、chain_gap、version_log、detail_deps、check_portability、products_reverse_audit、module_boundary_audit 全 rc=0;开箱验证 5/5。 |
v2.11.1 |
2026-09-22 | 小 | 模块化重构 P1:公共层九个平台件实体迁移(旧路径留兼容转发壳,零行为变化) | 重构推进(源码组织层)⇒ 小版本 +1。落地: ① 九个平台件(paths/version/logfile/proc/entry_refs/console/opsjob/derived_manifest/tabfmt)实体迁入 app_common/app_common_guanlan/; ② 安装根推算由 file.parents[1] 改为 _root.install_root()(按 configs/ 与 guanlan.py 标记向上查找, 位置无关; 移深三层后仍算得对); ③ 旧路径 src/<件>.py 变兼容转发壳(sys.modules 别名, 含私有名)⇒ from src import paths as P / from src.proc import NO_WINDOW / importlib.import_module(src.version) 三种写法全部照旧, 全仓约 120 处引用无需一次性改完; ④ config_audit 的「配置取用口豁免」由按旧路径判改为按取用口所在文件判(位置无关), 以后 paths.py 再搬也不会误报 R6。⚠ P1 附带逮到并修掉的入口耦合缺陷: 安装器原先按 src/version.py 的字面量读包版本,该文件变转发壳后读不到 ⇒ 回落到读 dist-manifest.json,而 PS 5.1 的 Get-Content 默认按 ANSI 解码无 BOM 的 UTF-8 ⇒ 中文乱码、ConvertFrom-Json 抛异常 ⇒ 安装中断(开箱验证从 5/5 掉到 0)。修法: install.ps1 与 install.sh 改为按候选路径解析(公共层新路径优先,旧路径兜底),且 JSON 一律按 UTF-8 读;并新增两条门防复发 —— R6「入口与布局解耦」(安装器必须能在当前布局下解析出版本)与 R7「入口读 JSON 必须指定 UTF-8」,都并入 module_边界审计。 验证: 旧路径导入与安装根实测正确(P.ROOT/P.RAW_ROOT/P.store/P.config 全对, 模块身份同一); raw_scan --check rc=0、rebuild_all --dry-run rc=0(23 步计划不变)、三份交付文档重渲通过; guanlan.py check、config_audit、pages_audit、chain_gap、version_log、detail_deps、check_portability、module_boundary_audit 全 rc=0。 |
v2.11.0 |
2026-09-22 | 中 | 源码模块化重构 P0:七个模块目录 + 接口层 + 模块边界门(每模块只经 api 调用,可插拔) | 源码组织层重构 ⇒ 中版本 +1(运行形态、交付形态与核心功能未变)。用户令: 「对观澜的源代码,按算法、数据接入管理、前端、后端 等系统模块进行重构,每个模块一个目录;遵循组件化、高内聚低耦合、可复用、可扩展(支持热插拔)、兼容性、性能优化、高可用、分布式、面向对象、代码精简;系统组件: TiDB community、MinIO、Redis、Nginx」。本轮按用户选择执行:只重构目录与接口(暂不引入四个组件,只留接入点)、零行为变化、逐版本可回滚。落地: ① 七个模块目录(每模块一个目录): app_common(公共层)/ app_ETL(数据接入管理)/ app_algorithmModel(算法)/ app_ontology(本体与知识层)/ app_backEnd(后端)/ app_frontEnd(前端)/ app_qualityGate(质量门与审计 + 打包安装);每个模块下 common/app_<模块>_guanlan/ 放观澜实现,api.py 是唯一对外公开面(PEP 562 惰性转发到既有实现,因此行为与重构前一致)。② configs/modules.yaml 模块登记表(职责/允许依赖/实现落点/迁移阶段/组件接入点)。③ 新增 scripts/module_boundary_audit.py 并接入 guanlan.py check: 查结构齐、模块间只经 api、依赖方向合规(不得反向成环)、公共层不依赖业务模块、api 转发目标真实存在;并统计迁移进度。④ 四个系统组件的接入点先立接口契约(无实现,默认仍走本地/进程内): TiDB community ↔ app_ETL 的标准仓读写接口、MinIO ↔ 源件与产物对象存储接口、Redis ↔ app_backEnd 的按时间窗缓存与作业状态接口、Nginx ↔ 统一入口与路由表接口。⑤ 设计说明新增「源码模块化布局与边界」一节(模块表 + 目录树 + 边界规则 + 分阶段迁移 P1–P7),方案全文见 docs/重构方案_模块化_v0.1.md。⑥ 三份交付文档随版本号改名重渲(内容口径不变)。验证: 边界审计 rc=0;旧路径(src/、scripts/)与页面/CLI/产物零变化;guanlan.py check、配置统一、页面归口、反向呼应、可移植性、可转移、文档三检 全绿。 |
v2.10.4 |
2026-09-22 | 小 | 数据要求说明补测点:安全链与数字输入、执行器与热管理、计数账、CMS 采集参数、位号字典 | 纯交付物修订 ⇒ 小版本 +1。用户令: 「测点遗漏体检的方案补进数据要求说明」。体检口径(六组真源): 现场件表头 595 个 10 分钟通道(9 前缀)· 标准仓契约 164 登记项(10 中文域)·窄仓 48 列 · 1 分钟转发层 76 列 · CMS 振动 71 项 · 状态与告警与工单与整定值 44 字段;逐列判定(参考/覆盖/缺失/待判): 595/325/151/119、164/117/31/16、48/46/0/2、76/61/11/4、71/50/19/2、44/33/6/5。三块结构性遗漏: ① din_ 数字输入 93 列几乎整片未登记(烟雾/急停/外部停机/UPS/油位/滤芯/接地刀闸/能见度);② dot_ 执行器 69 列整片为空(泵/阀/加热器/冷却器/通风),而文档把「热链与冷却」列为支撑功能;③ cnt_ 计数账 69 列只登记 6 条(外部错误小时= IEC 责任剥离并列账、OK 与可用小时、各类停机小时、寿命小时)。补齐内容: 10 分钟节新增「数字输入与安全链」「执行器命令与热管理」两域,扩充计数与统计及 tur/flg/int/prs/grd;秒级节补 11 条;CMS 节新增「采集参数与溯源要求」小节(键相/转速脉冲、窗函数、采样频率、量程与过载、序列号与配置、触发时刻、标称频率等 —— 没有键相无法做真阶次跟踪,窗函数在振动侧两侧都缺);第 5 章增「位号释义」质量要求;第 8 章收资清单增「测点与位号字典」一项(119 条待判通道没有位号释义就永远只能存而不解)。口径不变: 只写中文业务含义名 + 度量单位 + 必须性,不出现英文列名/文件名/落盘位置/机组编号/样本场现状;单位只取自已取证口径(canonical 词典 unit_majority、机型契约 unit),查不到写「未取证」;中文业务名取自 src/windscada/i18n.py 的 STEM 中译(源西门子 WTC-3 IO 表)与产物列名。验证: 严格模式(英文标识/扩展名/路径/机组编号/现状字样)0 命中;去标识化 0 命中;21 类逐类仍有四列测点表;表号引用闭合;guanlan.py check 全绿;三份 docx 重渲到 2.10.4。 |
v2.10.3 |
2026-09-22 | 小 | 交付件定名:设计说明改为「系统设计说明」(与需求分析、数据要求说明命名对齐) | 纯交付物修订(文档内容未变,只改交付件名称与随之而来的引用)⇒ 小版本 +1。用户令: 「设计说明_观澜 word 文档,改名为:系统设计说明观澜[版本号].docx」。做法: ① 渲染器的交付件定义改名 —— docs/设计说明_观澜_<版本>.docx → docs/系统设计说明_观澜_<版本>.docx(封面标题、页眉、markdown 源件名一并改为「系统设计说明」);② 三份稿里指向该交付件的交叉引用与「编写依据」路径同步改名(《设计说明_观澜_…》→《系统设计说明_观澜_…》、docs/src/设计说明_观澜_….md→docs/src/系统设计说明_观澜_….md),以及"三份交付文档(需求分析、设计说明、数据要求说明)"这类并列清单;③ 仓库内的内部文档 docs/系统设计说明.md 不受影响(替换模式带 _观澜_ 或书名号,不会误伤同名内部件);④ 三份 markdown 源件随批次改名到 2.10.3,正文"当前版本"口径(系统版本行、包名、本文版本、变更级别、版本表新增 2.10.3 一行、HISTORY 计数 15 条)同步更新,历史行保留。文档内容与图表未变。2026-09-22 用户复核补记: 用户对交付的《数据要求说明》做了一处口径修改 —— 秒级 SCADA 的采样频率由「1 秒或 5 秒(二选一)」放宽为「1 秒至 30 秒之间」(共 7 个落点: 第 3.2 节正文、第 5 章质量要求、数据分类总表、必须性分档表、收资 21 项对照表、面向现场的收资清单、附录 B 收资原文第 2 项)。已按「相关内容以后照此描述」并入源件,并把该口径写进 docs/系统设计说明.md §17 的描述口径清单;附录 B 的标题与说明同步改为「第 2 项采样频率按现场最新口径」,不再声称逐字。验证: 三份 markdown 与 docx 重渲染后 delivery_docs_build --verify rc=0(目录/页码域、去标识化、数据稿去实现细节、表号引用闭合);新文件名含当前版本号,guanlan.py check 的「交付文档三件」门按新名核验通过;包内只带 2.10.3 三份 docx,无同名旧版残留。 |
v2.10.2 |
2026-09-22 | 小 | 数据要求说明改成纯数据需求规格(去现状/去实现细节)+ 新增 SCADA 秒级数据要求 | 纯交付物修订 ⇒ 小版本 +1。用户令: 「数据要求说明不要体现样本场的接入情况、英文测点名称、机组名称、文件名称、落盘位置,只体现测点真实业务含义名称;每类数据的测点以列表呈现(测点/字段名、业务含义、度量单位、是否必须);增加 SCADA 秒级数据的要求」。做法: ① 删掉一切样本场现状: 到位情况/缺口/催缴状态、件数体量、行数、时间覆盖、日期全部不再出现(该文只写"对数据的要求",不描述任何具体场站);机组范围改写为「全场机组(按场实际台数)」。② 去实现细节: 正文与表格不再出现英文测点名(snake_case)、文件名与扩展名、目录与落盘位置、机组编号;测点一律用中文业务含义名称(有功功率、齿轮箱油温、机舱风速…),单位取自app_ETL/configs/canonical/dictionary.yaml 的 unit_majority 与机型—场站契约的 unit,查不到就写「未取证」。③ 测点列表化: 每类数据一节 + 一张四列表(测点/字段名 |
v2.10.1 |
2026-09-22 | 小 | 交付文档对外版:去样本场标识(全文不体现具体风电场)+ 新增多场适用性章节 | 纯交付物修订(系统功能未变)⇒ 小版本 +1。用户令: 「修改三份文档,内容参考如东风电场,但不体现如东风电场,且具有不同风电场适用性」。做法: ① 去标识化(中文与罗马化形态一并去): 场名/业主/地域/OEM/第三方机构/系统名里的样本场代号一律换成中性表述(样本风电场 / 本场 / 业主单位(从略)/ 主机制造商(OEM,名称从略)/ 4.0 MW 级海上机组(机型代号从略)/ 观澜 v2(风电场智能分析系统));路径写成模板(data/raw/<场站>/…、outputs/<场>/…、reference/<场>/…、app_ETL/configs/contracts/<机型>_<场>.yaml、app_ETL/configs/farms/<场>.yaml、WINDSCADA_FARM=<场>),并在「编写依据」表下写明占位符替换规则;实测数字与结论全部保留,标注「样本场实测(2026-09-22)」。② 多场适用性(用户令第二句): 需求分析新增第 11 章(FR-44…FR-52 + NFR-12: 场配置化、机组与机型可替换、数据源形态可适配、阈值按场标定、术语与单位可配、跨场统一口径、按场裁剪收资、换场验收检查表);设计说明新增第 16 章(场抽象层与配置 schema、场无关引擎 vs 场相关参数分层表、换场作业单与检查表、接新 OEM/新数据形态的扩展点、换场会失效的假设如实列);数据要求说明新增第 12 章(通用必选/可选判定规则、场配置字段对照、数据源形态适配、换场收资差异清单、按场裁剪步骤)。③ 去标识化做成机器可查的硬门(不靠人自觉): scripts/delivery_docs_build.py 增 FORBIDDEN 词表并在 --check/--verify 里逐份扫描(命中即报 FAIL),guanlan.py check 的「交付文档三件」门同步带上该扫描;图表器里出现的样本场字样一并中性化(图题写「样本场实测」)。验证: 三份 markdown 源件与 docx 对 12 个禁用词 0 命中;delivery_docs_build --verify rc=0;guanlan.py check 全绿;三份 docx 与插图重渲,图表数字仍与正文同源(图解析文档表)。 |
v2.10.0 |
2026-09-22 | 中 | 交付文档三件(需求分析 / 设计说明 / 数据要求说明)与源代码化生成器 | 非核心功能新增(交付物)⇒ 中版本 +1。用户令: 「整理观澜的需求/设计/数据接入,各写一份 Word 文档,要求区分章节目录、文表图并茂、字体字号分类统一;数据要求说明结合现场《数据分析收资要求-v3.docx》」。① 新增三份交付文档(落 docs/,文件名带本版本号): 需求分析_观澜_2.10.0.docx(需求来源与演进、角色场景、功能需求 FR、非功能需求 NFR、页面与信息架构、验收门、需求跟踪矩阵)、设计说明_观澜_2.10.0.docx(总体架构、目录与路径真源、重算链、判级与算法、时间窗口径、服务与前端、本体与模型、运维编排、安装与版本、质量保证、安全与边界、可移植性)、数据要求说明_观澜_2.10.0.docx(数据分类总表、逐类要求、核心测点/字段/单位/必须性、质量与对齐、落位流程、收资要求 v3 的 21 项逐条对照、缺失与替代、核对锚点、面向现场的收资清单); ② 两份源件均源代码化(用户令「所有的计算均要形成观澜的源代码」): scripts/delivery_docs_build.py 把 docs/src/*.md 渲染成 docx(Word 域目录 + 标题/正文/表格/图题四级字体字号分类统一: 黑体标题 + 宋体正文小四 + 表格五号 + 图题五号居中, 页眉页脚页码, 附录排版规范); scripts/delivery_docs_figures.py 生成 14 张插图, 每张图的数字都从真件取: src/version.py 的 HISTORY、configs/portal_pages.yaml、configs/serve.json、data/raw/<场>/**、outputs/<场>/**、并落 guanlan.py check 与 rebuild_all.py --dry-run 的实跑底稿到 docs/src/_*.txt(可复核); ③ 文档口径遵循用户令 §17: 含"窗"且指时间窗口写全"时间窗"、影响机组写"影响机组数"、英文简写写"中文(英文简写)"(平均无故障间隔(MTBF)/平均停机间隔(MTBO)/单次停机时长(MDT)); ④ 不确定与缺件一律如实写(测风塔零交付、m5_cms_tcm 正本缺失由观澜自算件顶上、故障录波仅 4 台、远端未装 Ollama),不编造; 每份文档附「编写依据」表逐章列出源文件; ⑤ guanlan.py check 增一行「交付文档三件 · v<版本>」: 校验三份 docx 在位且文件名含当前版本号、markdown 源件与所引插图都在位 —— 否则升一次版本号, 旧文档名就悄悄过期(同名旧版会跟着进包); ★2026-09-22 用户令「三份文档不同步到远端服务器」⇒ 该行先看 docs/src 在不在: 不在 = 本机是不随文档的部署(远端演示机即此),只报提示行、不 FAIL,且在 import python-docx 之前分流(那台机未装该依赖,直接进渲染器会炸成 ModuleNotFoundError)。 |
v2.9.2 |
2026-09-22 | 小 | 升级后验收补缺:版本/文档漂移有了自动拦截点(重算链增 ⑧d 版本记录门) | 纯消缺 ⇒ 小版本 +1。检查: 远端 2.9.1 升级 + 重算完成后跑 guanlan.py check,出现两处 FAIL —— ① docs/版本记录.md 与 src/version.py 不一致(version_log rc=6);② 安装根多出 _pre290_backup/(16 件扁平旧副本)让 config_audit rc=8。根因: 这次升级的差异盘点只覆盖 src/+scripts/+configs/(remote_src_inv.py),文档从不在盘点面上 ⇒ 代码升到 2.9.1、文档留在旧版(版本记录 13,277 vs 21,284 字节、系统设计说明缺 §17);而重算链里没有版本门(rebuild_all 只到 ⑧c 页面归口审计),于是 24/24 步全 OK、控制台写"重算完成",漂移照样静默过关 —— 没有任何自动拦截点。解决: ① scripts/rebuild_all.py 增「⑧d 版本记录一致性」(version_log.py --check,tolerate=(6,) —— 与 ⑧c 同口径: 缺的是"文档同步"这一路,报出来但不打断整条链);② 远端补齐 4 份文档(版本记录/系统设计说明/输入数据放置指导/detail 页面依赖台账),逐件 sha256 与本地一致;③ 远端把 _pre290_backup 移出安装根到 D:\产品\_pre290_backup_20260921(备份保留,不删除)。验证: 远端 version_log.py --check rc=0、config_audit.py rc=0;本地 guanlan.py check 全绿 + 反向审计/页面归口/chain_gap 全 rc=0。遗留(如实记录,未处理): 远端没有装 Ollama(无二进制、PATH 无、11434 拒绝连接)⇒ 本机模型探针在远端必然 FAIL,问答/升档类功能在远端不可用;要不要在远端装 Ollama 与拉哪几档模型,等用户定。 |
v2.9.1 |
2026-09-22 | 小 | 人工测试 7 项消缺(描述口径 + 依据空白 + 问题页空 + 门户链接 404 + 闭环文案 + Ollama 档位) | 纯消缺(无功能增减)⇒ 小版本 +1。逐项「检查→根因→解决→验证」: ① 描述口径: 「窗」确实指时间窗者一律写「时间窗」(预设窗→预设时间窗、判级窗→判级时间窗、窗内→时间窗内、证据窗→证据时间窗、随所选窗→随所选时间窗…;天气窗/作业窗/预览窗/观测窗属领域词,保持原样);「影响台」→「影响机组」(含报告构建器表头);英文简写改「中文(英文简写)」(平均停机间隔(MTBO)/平均无故障间隔(MTBF)/单次停机时长(MDT)),英文映射键同步; ② 需要关注「查看完整依据」空白: 根因=行的来源是融合面链盘(d.fus.链盘.rows),依据却只从 SCADA 的 d.watch 查 ⇒ 两边机组集合不同时 why[t] 为空(实测 WTG09 齿轮箱 bad 台)。改为按本行字段自组句(部件/链路进度/卡在哪步/证据源),永不空; ③ 报警机组「该问题页」打开空白 + ⑤ 命中系统链接: 根因=链接传slug(pitch)而页面/接口按中文系统名取数 ⇒ /api/problem 返回 0 条,页面还写"该系统在判级窗内无非常态"(对报警机组是假陈述)。改为: 链接传中文名 + 服务端 sys_norm() 双向归一(slug/中文/大小写都认)+ 页面区分"系统标识无法识别 / 本时间窗无异常"两者,绝不把认不出说成正常; ④ /turbine 页「返回观澜门户」→ 原写死 http://127.0.0.1:18084/观澜_如东样板_门户_单文件.html(用户机器上等于访问自己的 loopback,且该文件服务端没有)⇒ 网关回 not found。修法: 用根相对 /,并给网关加 data-abs="1" 豁免(作者显式声明某链接不按组件前缀改写,否则根相对链接一律被改写成 /detail/… 永远回不到门户),普通链接前缀行为不变(有单测); ⑥ 振动「端到端闭环」文案: 去掉内部黑话 handoff,改为「暂无端到端闭环证据:现场提交的振动数据包里没有「报警→检修→复测」的成对记录」; ⑦ 观澜↔本机 Ollama: 链路实测可用(探针 OK、/api/ask 提交成功、8B 出答但未过校闸→触发升档),但升档目标硬编码在 src/ontology/fast_agent.py 的 ESCALATE(写的是本机没装的 qwen3.8:27b,configs/models.json 只是同处笔误的另一份)⇒ 升档 digest=None、ask 终态 error(用户只看到"复核中")。修法: ESCALATE 改 qwen3:32b + 新增 installed_models()/escalate_target() —— 升档目标按「配置档位且确已安装」解析,没装则响亮回落并打日志,不再把答案静默卡死;初答文案里的"27B"改为实际目标名;BUDGET_S 随档位更新(32B 给 120 s)。验证: escalate_target("qwen3:8b") → qwen3:32b(本机实装 4 档实测);另: 远端 106.120.102.238 与本地各跑一遍 HTTP 抽样(门户链接=/、slug 归一出 1 条问题、文案含时间窗/影响机组/(MTBO)、闭环新文案、WTG09 依据不再空),网关改写 data-abs 豁免单测通过,config_audit/pages_audit/反向审计/raw_scan selftest 全 rc=0,guanlan.py check 全绿 |
v2.9.0 |
2026-09-21 | 中 | 时间窗真正生效(用户令):「部件问题」与「发电性能」随所选窗重算,并新增自定义起止日期窗 | 功能增减改 ⇒ 中版本 +1。要点: ① 窗口词表新增自定义起止日期(YYYY-MM-DD~YYYY-MM-DD,含两端):months_of() 取相交月、新增 win_range()/in_win() 供日粒度件做含端过滤;v2 顶栏加两个日期输入框 + 应用(校验 a≤b),月度件按所跨月取整、日粒度件按日精确,页上写明; ② 判级四轴按窗重算:taxonomy.system_matrix(span=…) 把窗透到 变桨(日粒度件切片, 精确)/偏航/蓄能/温度(走新窄仓重算);reliability.overview(span=…) 让部件可靠性表按窗;温度面的 ref/ref_sm 对照窗仍固定(季节解耦基线,跟着漂就失去对照意义); ③ 发电性能按窗:/api/curves?win= 七镜头按窗重算 + 7 张月度时序图按窗过滤;选到 2025-07~2025-12(限电前干净判别窗)时直接用正式产物不重算;④ 新产物 windscada/slim10min/*(公共列子集,不裁剪行)作按窗重算底座:一次全量扫≈2 分钟,把"每换一个窗重读 15 GB"降到秒级;已进重算链 ③b 并登记反向审计族表; ④b M9 控制参数一致性(就摆在发电性能页上)此前仍钉死 2025-H2 ⇒ control.registry(span=…) 按窗重算(窄仓补 grd_wtc_ActPower_max/tur_wtc_GenRpm_max 两列 ⇒ 48 列;≈0.6 s/窗,P封顶中位 4190(干净窗) → 4181.7(2026年) / 4177.5(2026Q1)),fleet 响应加 m9_pending/win_pending 并由页面轮询(5 s)—— 至此判级四轴 + 可靠性 + 控制参数 + 七镜头 + 7 张月度图全部随窗;远端两窗对比只剩 all_months/note/*_pending 三个元数据键不变; ⑤ 按窗重算一律"后台算+进程缓存"(判级≈25 s/窗、镜头≈10~45 s/窗):命中即回,未命中先回 pending/building 并由页面轮询,不静默拿旧口径当新窗;启动时后台预热 6 个预设窗(判级+默认窗镜头); ⑥ 实测(本机 38 台): 判级逐系统报警台数随窗变(变桨 15/13/10、偏航 15/11/5、齿轮箱 7/4/4 对应2026年/2025H2/2026-07),曲线图注窗=所选窗且样本量随窗变;验收: 反向审计 3548 件 0 未归类、pages_audit/detail_deps/config_audit/raw_scan(selftest,rc=0)/chain_gap 全绿;⑦ 远端部署(D:\产品\app,2026-09-21)实逮两处并已修: (a) 预热与请求各自起线程 ⇒ 同时算两份按窗中间帧,改为重活全局串行(_HEAVY_LOCK)并打印可用内存;(b) 退化窗("近30日"=2026-09只有 1 个节拍 ⇒ 比档件为空)时 groupby().apply() 返回空表 ⇒ .rename("dev_K") 抛 TypeError 把整面判级打断,改为如实"不可判(样本不足)";另: 远端进程须由 Windows 服务 guanlan 托管(SSH 会话里起的进程会随会话关闭而死,实测全端口消失 ⇒ 已装服务并 RUNNING),远端核验: fleet 两窗 pending→就位、变桨报警 15→7 / 偏航 15→3、rel 窗随窗、curves 图注"窗 2026-07-01 ~ 2026-07-31 (随所选窗)"、v2 页含自定义起止控件 |
v2.8.2 |
2026-09-21 | 小 | 消缺:扫描器的"变化"判据被两类非摄入件常年占住 —— 现场按类目交付的月度通道组库(scada_mdb/<年>年/<月>月/<年>-<月>-<类>.mdb)被当成"数据没人读·缺口",用户指定的按月提取件(<场站>/scada_10min_<YYYYMM>.csv)被当成"未归类";两者每次扫描都计一次变化 ⇒ raw_scan --check 永远 rc=4,rebuild_all.py --auto 与 raw_watch 会每轮都以为来了新数据 |
纯消缺(无功能变化)⇒ 小版本 +1。要点: ① CONSUME 新增 upstream 口径(信息级):类目库是 10min 同台补充件的上游,取数层不直接读它 ⇒ 不再算缺口、不计变化,改按"上游归档件(要先转换才被消费)"列出并写清转换口径; ② 新增 IGNORE_PATTERNS:scada_\d+min_\d{6}\.csv 是按月提取/核对件(位置由用户指定、不是摄入源)⇒ 不报未归类、不计变化;③ 实测(2026-09-21 落位 7-8 月交付后):修前 --check rc=4 且每轮都报"2 处变化",修后 --check rc=0「与上次快照一致,没有新数据」,--selftest 通过,24 件类目库如实以信息级列出; ④ 口径写进 docs/输入数据放置指导_v0.1.md §4.1(含 12 组中文目录↔类目码、9 类↔主件 595 通道一一对应、float32+ISO 对齐、以及"类目库→同台补充件"的落位转换) |
v2.8.1 |
2026-09-20 | 小 | 消缺:重算链末步「台账等价验收」在全新机器上必然 rc=5(交付包不含产物 ⇒ 没有随包基线),原先把它判成失败 ⇒ 门户上写"重算失败"(实测服务器 2.8.0 一轮 24/24 步全 OK 却整轮 rc=1) | 纯消缺(无功能变化)⇒ 小版本 +1。要点: ① rebuild_all.py 的 ⑧ 台账等价验收由 tolerate=(4,) 改成 tolerate=(4, 5) —— rc=5 = "找不到随包基线 ⇒ 没做验收",与 ④ 的口径对齐(④ 一直容忍 5 并写明"跳过等价验收≠通过");步名与步说明都改写清楚"rc=4 = 有需人工看的差异 / rc=5 = 没基线 ⇒ 没验收(不是失败,也不是通过)",并指路 scripts/set_baseline.py(用已核实的当前产物快照登记基线,之后这一项才会真比对); ② 远端复核(服务器 D:\产品\app): 该轮 24 个实质步骤全绿(①b 扫描 53.7s · ② 164s · ③ 1025s · ④ 99s · ④b 2118s · ④c 385s · ④d 41.6s · ④e 15.3s · ⑤b/⑤c/⑤a/⑤ · ⑥ · ⑦×6 · ⑦b 78s · ⑧ 7.1s · ⑧b 3s · ⑧c 9.5s),只有第 25 步判失败;且同批数据已真进产物:temp_monthly 21 个月、末四格 2026-06/07/08/09、2026-08 = 1,026 行(服务器 scada_10min 也有 76 件含 38 个 WTG??-B2.csv 同台补充件,说明步骤 B 的同台多件合并已在服务器上生效); ③ 已把修好的 scripts/rebuild_all.py(+ src/version.py / docs/版本记录.md)单文件部署到服务器,无需重装整包。交付包 app_guanlang_v2.8.1.zip |
v2.8.0 |
2026-09-20 | 中 | 输入数据自动扫描识别:<安装目录>/data/raw 逐族指纹 → 发现新增/变化 → 指明该跑哪几步;重算链加 ①b 步 + rebuild_all.py --auto(新数据不被 --skip-* 漏掉)+ 服务侧可选看门狗 |
非核心功能新增 ⇒ 中版本 +1(无架构改动)。要点: ① 新增 scripts/raw_scan.py(用户令 2026-09-19「对 <安装目录>/data/raw 目录下的接入数据处理,增加自动扫描识别机制,以能发现新增数据,并纳入重算」):逐族指纹 = 件数/体积/最新落盘时间/清单摘要(--deep 再叠内容哈希),与快照 outputs/<场>/_raw_scan.json 比;rc: 0 无变化 · 4 有新增/变化 · 5 还没有基线; --write 记基线, --json 给机器读, --selftest 对账"族表覆盖反查族表里所有 raw 输入 + 步骤名都能在链上找到"(防两处漂移); ② 族表把每个 raw 子目录映射到链上步骤(故障报警/工单/油样→②;scada_10min→③④④c⑤b;scada_1min→④c;scada_mdb→③④④c;windcms→④b④d④e;m5_cms_tcm→④b;西门子4.0技术资料→⑦),data/raw/<场>/ 下出现族表没有的目录则如实报"未归类、没有已知消费者"(不猜); ③ 进重算链作 ①b 步(--check --write,容忍 rc=4/5,并在步说明里写清"4 = 有新数据不是失败"); ④ rebuild_all.py --auto:先扫一遍,新数据落在被 --skip-scada/--skip-vib 跳过的族里就自动取消跳过(实测: scada_10min 新增 1 件 → 计划从 22 步变 24 步并打印取消原因); ⑤ 服务侧看门狗(scripts/service_worker.py::raw_watch,配置 configs/serve.json 的 raw_watch,默认关):每 N 分钟扫一次,有新数据写 logs/service.log 并列出该跑的步;auto_rebuild=true 时顺手发起一次重算(走 ops 同一条路;run/ops_job.json 显示在跑则不重复发起)。★2026-09-20 按用户令「对 data/raw(含嵌套子目录)下文件的增减做到监听;重算要按该目录最新的变化算」逐条查证并补了三处: ⑥ 扫描改成递归统计全部文件(不限扩展名; 白名单命中的另记 matched, 差额单列为"信息,不计变化")+ 子目录清单进指纹(新建空目录也发现) + 未归类改成全树逐件找(不再只看一层); ⑦ 产物 = 当前源件的函数(删/换源件后, 那些行不再产出并大声报出"哪几件不在盘、少多少行、涉及哪些月"): 报警/工单/油样三个摄入器原先是"只替换本次涉及的件、其余原样保留" ⇒ 源件删了行还在; ⑧★报警台账改键集合并集去重(键=Name/Alarmcode/TimeOn, 归属取最窄的源件)—— 原先按"逐件累加、没新键就跳过"的贪心判快照, 实测删一个源件反而让总行数从 39,211 涨到 56,593(被跳过的大快照件整件摄入, 重复计数) ⇒ 既不是源集的函数也会虚增; 现在 39,211 键稳定、重复 3.6 万行如实去掉; ⑨ 振动窗: 同名窗已存在时原来一律改名 _reimport(被 EXCLUDE_DEFAULT 排除 ⇒ 补进来的 CMS 数据根本进不了生产集), 现在默认替换同名窗(旧窗留档 _superseded_<时分>, 已加入排除表; 要旧行为用 --reimport-as-new)。★另按用户令「按你的建议执行 先 C 再 B」补完"同台多件 10min 进不来"这条链: ⑩ 步骤 C(让"放了没人读"当场可见):raw_scan.py 新增 CONSUME 表(逐族写清消费者真实取数口径),判据从"扩展名白名单没命中"改成"全部文件里没被消费者读的"—— 实测 data/raw/如东/scada_10min/WTG01-B2.csv(856 列 / 2026-08 数据)扩展名 *.csv 命中白名单,旧判据永远发现不了它;现在报成缺口级(计入变化 rc=4 + ★[缺口] 块写明消费者口径与件例),附件类(.rar/.jpg/厂商软件)仍只列信息;建议行也分流说明"缺口类重算也纳入不了"。raw_data_check.py 同步: 同台补充件不再误报"文件名不是本场机组",改为 info 行。⑪ 步骤 B(真正把新月份的 10min 件吃进来):scada_source.load 取数从"只认 <台号>.csv"扩到 <台号>.csv + 同台补充件 <台号>-*.csv/<台号>_*.csv:按列名对齐(新导出把类型前缀去掉了: din_wtc_HydLevel_timeon → wtc_HydLevel_timeon,实测老件 598 列里 597 列能这样对上)、按时间戳排序去重(主件优先,重叠条数写进 attrs.scada_overlap 并打印)、来路件名与各件行数写进 attrs.scada_files/scada_rows。实测 WTG01:主件 77,551 行 + 补充件 5,820 行 → 合并 83,353 行(重叠 18 行去重),时间范围由 2026-07-07 延到 2026-09-01,2026-08 的 5,819 行关键通道非空率 77%(空白是源件自带的:该月 144 行/日齐全但约 23% 行的通道为空,如实保留 NaN)。交付包 app_guanlang_v2.8.0.zip |
v2.7.0 |
2026-09-19 | 中 | 远程部署消缺:振动窗发布被杀软/索引占用不再打断整条重算链(+ --publish-only 恢复通道);门户可对外监听(public_host,组件仍只本机);GBK 控制台打印不炸 | 一次消缺 + 一项非核心功能新增(对外监听)⇒ 按规则取最高一级(minor)。要点: ① ★远端实逮(服务器 D:\产品\app):索引 719 s + 谱 894 s 落进 windows_staging_ingest 后,staging.rename(final) 回 PermissionError: [WinError 5] 拒绝访问(360 实时扫描/索引器持着刚写的 1710 件小文件的句柄,Windows 的目录改名要求树里无打开句柄)⇒ ④b 失败 ⇒ 链停在第 4 步,页面表现为「需要关注 0 台 + 融合面缺件」。修法:发布改 _move_tree()(整目录 rename 退避重试 → 逐件搬,rename 不行就 copy+删 → 仍锁住的逐条如实报出);并加 --publish-only:已算完的暂存窗可直接发布,不必白等 25 分钟重跑索引/谱; ② 用户令「观澜改为监听所有 IP」:configs/serve.json 增 public_host(空=跟 host=只本机;设 0.0.0.0=所有网卡),只有门户网关用它,detail/cms/viewer/sim 仍绑 127.0.0.1 ⇒ 对外只有 28084 一个入口;启动时打印对外地址并提示"页面无鉴权,请在防火墙侧限来源"; ③ 消缺: 新生成端在 GBK 控制台打印 m/s² / ⇒ 时抛 UnicodeEncodeError(远端 baseline_38 整件没出)⇒ 四个生成端加 stdout 守卫;trend_ingest 的"台账止 2024-11"过期断言改实话;CMS 三层基线卡的"健康期窗 N"重复措辞; ④ 部署口径: 用 SSH 起的服务在会话断开时会被一起收掉 ⇒ 现场改注册 Windows 服务(guanlan)(scripts/service_ctl.py install),开机自启、SCM 崩溃重启。交付包 app_guanlang_v2.7.0.zip |
v2.6.0 |
2026-09-19 | 中 | 「所有的计算均要形成观澜的源代码」:融合面/总览页/事实契约/发布层/掩码阈值/六层链两步/变桨面/振动在升与三层基线 全部落成观澜自算;SCADA 接入兼容 CSV+MDB;交付包带输入数据目录结构(不含文件) | 功能新增为主、夹带多项消缺 ⇒ 按规则取最高一级(minor)。要点: ① 六层链 model_run/fusion 两步按口径重建(报告的"融合级"列从此有值)+ energy_share 步补上 + 峰值拾取口径定案(观澜口径,四件 *_freq_scan 形式不再复刻); ② 融合面 handoff 与总览页 windscada/index.html 由观澜自算生成(原为"包内无生成端",新机器上 /detail/v2 的"需要关注/全场状态"必空白); ③ 事实契约改为从重算台账生成 claim(门户结论段/问答/报告随重算刷新,/api/facts 不再 503); ④ 本体发布层 r1/r2、TCM 掩码阈值(观澜自算口径,非厂商)分别落成生成端; ⑤ SCADA 接入统一取数层兼容 CSV 与 MDB(含老库列位错位如实拒绝;37 个月库按修好的建库脚本重建并逐分片对拍); ⑥ 变桨面 pitch/** 落成生成端(10min 开关量/压力锯齿 + 1min 桨距角;零位口径按用户令停机段/满发段分列,并据实测反推补上运行段同工况分档这一真正的判据轴 —— 它能把现场确诊的 19# 单独拎出来); ⑦ 振动 component_history.json(在升/换件闭环)与 baseline_38.json(自/机群/绝对三层基线)落成生成端(窗数不足时如实空表并写明数据边界); ⑧ 打包:带输入数据目录结构(30 个空目录, 含 data/raw/西门子4.0技术资料)+ 放置说明文件随包, 仍不含数据文件; ⑨ 消缺: report 步踩可选包 tabulate 致整链中断、语言包闸拦下的 /v2 500、振动页看不出数据区间与"3 月数据消失"(趋势按日聚合)、账目单位错(kWh/MW)、Access 锁文件误报、日志保留策略等。交付包 app_guanlang_v2.6.0.zip |
v2.5.0 |
2026-09-17 | 中 | 卸载闭环(uninstall.bat / uninstall.sh)+ 版本管理与打包命名规则 + 版本记录 | 二代架构(大版本 2,与 NAME 里的 v2 对齐)的第 5 次功能性发布,无消缺项;交付包 app_guanlang_v2.5.0.zip |
v0.4.0 |
2026-09-17 | 旧编号 | 打包默认不含 输入数据/产物/日志/临时文件;无窗口启动(去掉 VBScript);统一配置与日志;页面归口审计;输入数据放置检查;安装时版本检查与服务化 | 旧编号体系;交付包 app_guanlan_v2_0.4.0.zip(= guanlan-v0.4.0_dist_20260917.zip) |
v0.2.0 |
2026-09-01 | 旧编号 | 含产物的旧交付基线(历史上用作"包内无生成端"那批产物的补救源;该用途 2026-09-19 起已失效) | 旧编号体系;交付包 guanlan-rudong-v2_0.2.0_test_win64.zip —— ★2026-09-19 用户令从工作树清理(943 MB):① 「所有的计算均要形成观澜的源代码」落地后无生成端件 = 0(反向呼应审计 1,800 件全部 raw-derived)⇒ 它作为"补救源"的用途消失;② 该包仍留在 git 历史里(blob 可随时 git 取回),需要时用 git show 恢复即可 |
v2.52.1(观澜·如东样板 v2)app_guanlang_v2.52.1.zipguanlan(Windows 服务 / systemd 单元)install.bat、install.sh / uninstall.bat、uninstall.sh