版本记录.md 249 KB

版本记录(观澜·如东样板 v2)

本文件由 scripts/version_log.py 生成,勿手改:事实(版本号、级别、变更)写在 src/version.py 的 HISTORY 里,改完跑 python scripts/version_log.py --write。 guanlan.py check 与打包器都会校验本文件与代码里的版本号是否一致。

版本号规则(用户令 2026-09-17)

编号 v<大版本号>.<中版本号>.<小版本号>,例如 v2.90.0。

级别 含义
大版本号 系统解决方案、架构或核心功能改变
中版本号 非核心功能新增、减少、修改
小版本号 消缺完善

怎么改:改动落在"解决方案/架构/核心功能" → 大 +1(中/小归 0);落在"非核心功能的新增/减少/修改" → 中 +1(小归 0);只是"消缺完善" → 小 +1;一次发布混了几类,取最高那一级

打包文件名 = app_guanlang_v2.90.0.zip(规则:app_guanlang_v<版本号>.zip)。

版本号只写在 src/version.py 一行(VERSION = '2.90.0');打包器、安装脚本、安装记录 install-info.json、自检都读它,不另设真源。

版本 日期 级别 主要变更 说明
v2.90.0 2026-10-06 中 置信度诊断式接线(①)· TCM 口径与规则立项(③)· 扩窗数据阻塞结论(②) 用户令:持续执行 ①②③④。④ 已完成:删除中间交付包 app_guanlang_v2.89.4.zip(885.7 MB),保留 v2.89.5。① 置信度接线(诊断式,已上线):新增 app_ontology/app_ontology_guanlan/sop/vib_confidence_wire.py —— 从现有产物(fusion_table 行 + 振动 handoff)装配五轴,缺数的轴显式计 0 并列入 missing_inputs(不猜不凑);service/fleet_views.py 的 fus 载荷新增 置信度 字段(只加不改,不参与任何判级)。接线状态登记为 WIRING = "wired_diagnostic"。实跑结论(重要):69 行全部 usable=false(档位"不足",中位 2.5 分),缺件四项 —— A handoff 无逐台闸过数 · B 同窗无独立源(温度轴判「—」、油样 stale)· C handoff 无实物锚字段 · E 反证搜索无产物承载(模块自身口径:没做过反证搜索=0 分)。因此每台分数都附带 caveat「不可用于判断机组状态:低分反映缺少输入,不等于证据弱」 —— 这正是"防止把缺数据读成证据不足"的处理;补件后重算才有意义。③ TCM 口径与规则立项:新增 docs/TCM口径与规则引入_需求立项_v0.1.md —— 把上游 §5-1(Reference 基线公式)/§5-2(CurrentCount 样本身份)/§5-3(原厂逐测量迟滞)逐条写成「原判断→反例→修正→适用域」+观澜现状实测+所需输入/产出/前置+四条验收标准(含"不得把参考/推断值当实际数值阈用于定级"的明文禁令与"判级变化范围须逐一列出");不在本版改算法(引入属算法改动)。② 扩窗:数据阻塞(不是代码):本机 data/raw/如东/windcms 仅 202603-04 一个周期(25,776 件),已生成窗只有 w0316(另有一个 superseded 副本);代码侧已就绪(rudong_tcm_index.py --root <period> 逐周期建窗;P0 的门 max(4, ceil(2N/3)) 已按 N 伸缩)⇒ 需补更多周期的 CMS 原始件(或指认盘上历史数据位置)方可扩到 ≥2(理想 9)窗。该阻塞同时是 §5-3 与 C02 逐窗滞回的前置。
v2.89.5 2026-10-06 小 backlog 其余 6 项收口:C02 未接线且当前不可实现 · A03/A04 定论 · §5 三项观澜已实现 用户令:继续(backlog 剩余项)。实测结论:① C02 滞回 [未接线]:apply_hysteresis 在 app_ontology/app_ontology_guanlan/sop/fusion_diag.py:88,但外部调用 0 处、oem_hysteresis 符号不存在、其入参 window_levels(逐窗 level 序列)无生产端 ⇒ 与上游报告「要逐窗序列而全窗裁决不产生该序列」完全一致;且观澜实况 1 窗 ⇒ 连续 h 窗同向在数据上不可实现 ⇒ 标注「待接线 + 待扩窗(≥2 窗,理想 9 窗)」。② A03 [不适用]:上游 9/25 才加的「告警滞留特判」观澜没有;观澜现行等价纪律为 app_ETL/.../builders/scada_slim_build.py:19「缺列如实记、不造 0、不静默丢列 ⇒ 缺了就当不可判」+ pitch_face_build.py:33 的不可判门 窗内 nop < 144 + report_std.py 三轴口径 ⇒ 登记观澜口径,不照搬上游特判。③ A04 [已实现]:sop/sensor_validation.py:429/534「疑似同一测量写多列 ⇒ parity/level/swap 全不可证 ⇒ INSUFFICIENT」已与上游 9/17 的「疑似」修正同义。④ §5-4 相对强度与绝对锚 [已实现]:perf/curves.py:100「定级必须过绝对量」、fleet_views.py:687「出带且过锚才算离群」、temp_nbm.py:6/225「相对判据配绝对量;升定论须外部绝对锚」、powercurve.py:3「绝对达成率 INSUFFICIENT 不产出」。⑤ §5-5 证据独立性 [已实现]:discriminators.py:937「疑似同源复制→勿当两路独立证据」+ vib_confidence 扣分项 same_source_multi_stat (-20)。⑥ §5-6 覆盖与缺测传播 [已实现] + 本版 P1 已明文化「不得静默丢窗」。⑦ §5-1/2/3(Reference 基线公式 / CurrentCount 样本身份 / 原厂迟滞规则)观澜未引入 ⇒ 作为适用域提示登记(引用 TCM 值时不得把参考/推断值当实际数值阈用于定级),引入属算法改动、需另立需求。以上结论已回填 docs/主张审计清单_v0.1.md 第八、九节(含 backlog 全量状态表)。
v2.89.4 2026-10-06 小 P2:置信度模块接线状态明文标注(unwired / 待接线 · 含接入前禁令) 用户令:执行 P2 —— 确认 score_internal / score_sample 是否接入生产链,未接入则明确标注以免被误读为"已在用"。实测结论(2026-10-06,全仓排除 .venv/vendor/node_modules):score_internal / score_independent / score_falsification / confidence / penalize / band 的外部调用点均为 0 ✗;score_physical(:212)与 detectability(:161)的命中全部在本文件内部;模块已在 app_ontology/app_ontology_guanlan/api.py:45 注册为 sop_vib_confidence ⇒ 具备接线条件但尚未接线。决定:标注「待接线」,不擅自接线 —— 接线会改变报告/页面呈现,属产品决策;而报告告诫的核心风险是「函数存在 ≠ 生产链使用」,用明文即可消除误读。落地:① sop/vib_confidence.py 新增常量 WIRING = "unwired" 与 WIRING_NOTE,并在注释中写明接线实测证据、接线入口、接入前禁令(报告与交付件在接线并通过验收前不得声称已使用置信度评分)、以及接线后须把 WIRING 改为 "wired" 并记录接入点 file:line 与验收证据;② docs/振动六层链_接口规格与缺口_v0.1.md 新增「置信度模块接线状态」小节;③ docs/主张审计清单_v0.1.md 记录 P2(含"若日后要接线需先明确的三件事":消费端 / 五轴输入来源 / 验收证据)。验证:模块导入正常、常量读出 unwired、评分函数仍可调用(score_internal(4,…) ⇒ 17.6)。部署说明:本次为常量/文档级改动,无需重启服务(无生产调用方 ⇒ 运行期行为不变)。
v2.89.3 2026-10-06 小 P1:窗数口径与单窗拒判升格为明文条款(代码 + 文档 + 随 fus.纪律/盲区 传导到页面) 用户令:执行 P1。落地四处:① app_ontology/app_ontology_guanlan/sop/vib_confidence.py 模块文档 —— 修正 P0 后已过时的两处口径行(A 轴「持续≥4/6窗」、D 轴「覆盖窗数≥4」⇒ 均改为 max(4, ceil(2N/3))),并在模块头新增「窗数口径与单窗拒判」小节;② app_algorithmModel/app_algorithmModel_guanlan/subsys/fusion.py —— 新增模块常量 WINDOW_CLAUSE,并在 fusion_table() 的消费处把条款拼进 纪律 与 盲区(该处原为 h["meta"]["reading_discipline"] 与 h["detectability_prior"]["known_blind_spots"])⇒ 经 service/fleet_views.py:581 进入页面 fus.纪律/fus.盲区;③ docs/振动六层链_接口规格与缺口_v0.1.md 新增「窗数口径与拒判条件」节(门的形式、单窗拒判、不得静默丢窗、当前实况 1 窗、四处出处 file:line);④ docs/主张审计清单_v0.1.md 增记 P1 执行结果。条款要点:① 持续性/覆盖门分母 = max(4, ceil(2N/3))(N≤6 恒 4 · N=9 ⇒ 6 · 分母只增不减 ⇒ 任何窗数都不更宽松);② N<3 时不得用「持续性」「逐窗趋势」类判据出个体结论,只能标「窗内周段趋势(单窗补充口径,仅参考不作判据)」(与 app_ETL/.../component_history_build.py 既有降级口径同源);③ 不得静默丢窗(谱窗与仅标量/原厂状态窗分列,缺窗显式进盲区)。验证:本地实跑 fusion_table() ⇒ 107 行 · 纪律 含条款 ✓ · 盲区 含条款 ✓(5 项);远端部署后重启算法服务,线上 /api/fleet ⇒ 200 · 纪律含条款 true · 盲区含条款 true · 盲区项数 5 ✓(条款已上页面)。过程实逮:首版补丁因 CRLF 行尾导致多行匹配失败(0 处改动)⇒ 改为逐行替换后成功。
v2.89.2 2026-10-06 小 P0:持续性门/覆盖门改为 max(4, ceil(2N/3))(N≤3 更严 · N=4~6 逐位一致 · N>6 自动升级) 用户令:执行 P0(backlog 第 1 项建议)。实现位置 app_ontology/app_ontology_guanlan/sop/vib_confidence.py:① score_internal 持续性分母由硬编码 max(min(4, n_windows), 1) 改为 max(4, ceil(2*n_windows/3));② score_sample 新增 n_windows=6 形参(向后兼容),窗覆盖分母由 4.0 改为同一公式。已补 import math。验证(函数级对照,旧实现逐字复刻 · 含同样的 round(raw,1)):N=4/5/6 ⇒ 两个分量逐位一致(0 处差异) ✓;N=7/8 ⇒ 分母 5/6(升级);N=9 ⇒ 分母 6(旧恒为 4)✓;N=1/2/3 ⇒ 分母 4 ⇒ 更严(旧口径下 min(4,nw) 意味着"1 窗即满分持续性",新口径要求 4 窗)✓。关键安全性质:分母只增不减 ⇒ 任何情形都不会比旧口径更宽松 ✓。过程实逮(重要,如实记录):最初的实现用纯 ceil(2N/3) ✗,实测在 N<6 时反而放宽 —— 例如 N=1 时窗覆盖满分只需 1 窗(旧需 4 窗),最大差 7.5 分 ✗,与上游报告"覆盖与缺测传播·部分覆盖被埋进健康"的告诫相反 ✗;故改为带 4 下限 的 max(4, ceil(2N/3)),既消除该放宽、又保留 N>6 的自动升级。实际影响:当前实况为 1 窗且这两个评分函数全仓无调用点(函数存在 ≠ 生产链使用),故线上产物零变化 ✓;本次改动为"扩窗到 7~9 窗时的口径预置"。
v2.89.1 2026-10-06 小 backlog 第 1 项定位:观澜持续性门/覆盖门与窗数口径 用户令:执行 backlog 第 1 项 —— 定位观澜的持续性门/覆盖门实现位置与窗数口径(对应上游报告 C05「四窗 ≠ 九窗同等证据」)。实测定位(观澜自身证据):① 持续性门(A 轴) 在 app_ontology/app_ontology_guanlan/sop/vib_confidence.py:146,口径为 p = 3.0 * min(persist_windows / max(min(4, n_windows), 1), 1.0) ⇒ 分母固定封顶 4,函数默认 n_windows=6;② 窗覆盖门(D 轴) 同文件 :173 w = 10.0 * min(n_windows_covered / 4.0, 1.0) ⇒ 同样 4 封顶,且 score_sample() 签名无 n_windows;③ 盲区门 :170 if is_blind: return 0.0;④ 逐日持续(冲击轴) windcms/report_std.py:187/213(类型枚举 + n_high_days_all >= 3);⑤ 比例门 sop/farm_pipeline.py:57 sync_fraction >= 0.5、service/fleet_views.py:458 _share >= 0.5。关键判定:ceil(2·6/3) = 4 ⇒ 仅当 N=6 时观澜的"固定 4"与上游 ceil(2N/3) 恰好等价 ✓,但 N=9 时上游要求 6 而观澜仍取 4 ⇒ 扩窗即静默放宽(潜在隐患)。实际窗数(实测):baseline_38_build.py:41「本机实况只有 w0316 一窗」、component_history_build.py:34「只解析出一个窗」、融合产物 fus.盲区 自述「单窗数据时逐窗趋势信息量有限」⇒ 当前 1 窗 ⇒ 报告所指"四窗当九窗"在观澜尚未发生。另一重要发现:score_internal / score_sample 在观澜全仓无任何调用点 ⇒ 属「函数存在 ≠ 生产链使用」(本清单按 [码] 记存在、不按 [场] 记已用)。建议:P0 低风险改法 —— 两处 4 改为 max(1, ceil(2*n_windows/3))(N=6 时行为不变 ⇒ 零回归;N=9 时自动为 6),score_sample() 需新增 n_windows 形参;P1 把窗数口径与"单窗不得用持续/趋势判据"升格为明文拒判条件;P2 确认两函数是否接入生产链或标注"待接线"。
v2.89.0 2026-10-06 中 主张审计清单 v0.1(吸收上游算法模型分类报告的边界写法)+修 B02 陈旧文案 用户令:就当前源代码版本打包(已在 2.88.1 上启动),然后按 A 建议执行。① 主张审计清单:新增 docs/主张审计清单_v0.1.md —— 把上游《wind_analytics 算法模型分类报告》(wind-analytics main 357350d4,2026-09-30 静态快照)的 §4 九条与 §5 六条,用其「原判断→反例→修正→适用域」写法逐条落到观澜自身,并对观澜仓单次遍历 23,828 个文本文件逐条实测 + 命中处逐行看上下文。② 实测结论(A 档成果):确证真缺陷 1 处并已修 —— app_ontology/app_ontology_guanlan/sop/discriminators.py:1094 原文写「builtin_avail_verify/zero_gen_redflag 待实现」,而两函数均已实现(builtin_avail_verify 见第 2203 行、zero_gen_redflag 见第 2234 行)⇒ 改为据实表述(两函数实现均已落地,此处仅说明不入 A_op 抽取面、留 per-farm 传入比对);同词不同义(假阳性)2 处:C04 的 全盲 在观澜指"全盲台 02/18/37"(windcms/report_std.py:182)、A03 的 滞留 在观澜指热滞留(sop/discriminators.py:2410/2420),均非报告所指问题;观澜已优于上游 1 处:C01 —— 观澜 windcms/report_std.py:67 已同时携带 ISO_C, ISO_D = 7.1, 11.0 双阈并留有历史漏判实逮注释;不适用 2 处:B21 四层异常(观澜仅有一处翻译字符串,无实现与调用)、D04 gym(观澜无该目录);列入 backlog 7 处(优先项:定位观澜持续性门/覆盖门的实现位置与窗数口径,因全仓未出现 ceil(2N/3) 与"九窗")。③ 纪律:报告中以上游 file:line 为准,不得直接引为观澜结论;本清单「观澜实测」列是唯一可引用来源;不并入上游分支、不照抄其状态、不用其替代观澜验收。
v2.88.1 2026-10-06 小 核实并修正「Word 里的图与页面一致」:缺 data-blk 导致导出仍用后端重绘 + 图内字体未内联 用户令:检查「汇报定制」导出的 Word 里的图是否与页面完全一致。实证检查(本机 jsdom + 无头浏览器探测)实逮两个缺陷:① 页面里根本没有 [data-blk] 容器 ⇒ 前端 rasterizeCharts() 按 [data-blk="k"] 找图会一个都找不到 ⇒ images 为空 ⇒ 静默回落到后端 matplotlib 重绘 ⇒ Word 里的图仍不是页面图(上一版 2.88.0 因此并未真正达成该要求,已纠正);根因:上一版补 data-blk 的判断条件 "data-blk" not in 文件 被我插入的辅助代码字符串命中,模板补丁根本没执行。② 图内文字字体不一致:页面 CSS 有 svg.dt text { font-family: var(--sans) },而 SVG 单独成图(经 <img>→canvas)不继承页面 CSS ⇒ Word 里的图内文字会退回默认衬线字体,与页面肉眼可见不同。修:模板给章节块加 :data-blk="k"(复核:BLOCKS_WITH_KEY 9、CHART_KEYS [water,blame,ram,pareto]、SVG_TOTAL 4 · SVG_IN_BLOCKS 4 · SVG_OUTSIDE 0 ⇒ 导出时 4 张图一张不漏);栅格化前把页面字体内联进 SVG(根元素 + 所有 text/tspan 设 font-family)。已验证:后端逐字节嵌入前端图(线上 18050 直连与 28084 网关两条路 n_media 2 · all_match true);栅格化所用的 SVG 原文即页面上的那一份(同一 DOM 取出的 outerHTML)。未能自动验证(如实):本机无头 Edge/Chrome 均无法启动(--headless=new / --headless 皆失败)⇒ 像素级一致性无法在本机自动化,需在浏览器点一次导出并肉眼比对;链路已按标准 API 实现且保留 GET 回落。
v2.88.0 2026-10-06 中 Word 里的图与页面完全一致:前端把页面 SVG 栅格化回传,后端原样嵌入 用户令:Word 里的图必须与页面完全一样。做法:前端把纸面各章节的图(SVG)栅格化为 PNG,随导出请求回传,后端原样嵌入(缺失的块才回落到 matplotlib 重绘)。前端(views/Report.vue):新增 rasterizeCharts()(XMLSerializer 序列化 SVG → Image → canvas.drawImage(2 倍像素、白底)→ toDataURL("image/png"));exportAs("docx") 改为先栅格化再 POST /api/rpt_export(JSON 体含 images),失败自动回落到原 GET 路径;章节块加 data-blk 以便定位各块的图。Java(RptExportController):新增 @PostMapping("/api/rpt_export"),把整个 JSON 体(含 images)转发到算法的 /api/rpt_export_raw,MIME 与文件名规则与 GET 一致。算法(service/app.py + report_views.py + report_export.py):新增 POST /api/rpt_export_raw;export_bytes(..., images=None) 透传;to_docx(..., images=None) 优先用 _decode_png(images[k])(支持 dataURL 或裸 base64)。验证(逐字节):本地以真实 PNG 传 {water, blame} ⇒ docx 里 word/media/image1/image2 的 sha256 与传入完全一致 ✓;线上经 18050 直连与 28084 网关两条路 ⇒ n_media 2 · all_match true ✓。过程实逮(共 4 个自身缺陷,均已修):① app.py 插入路由时顶格 ⇒ IndentationError,算法服务起不来(连带 /api/fleet 500);② Java 侧手写 POST 方法编译不过(mvn 报错)⇒ 重写为干净实现;③ Java 控制器缺 PostMapping/RequestBody 导入;④ 最隐蔽的一个:report_export.py 里 import base64 从未插入成功 ⇒ NameError 被函数内 except Exception: return None 静默吞掉 ⇒ 永远回落到 matplotlib(表现为"传了图却没用上")⇒ 补上 import 后立即生效。遗留说明:前端的 SVG→PNG 栅格化需真实浏览器(本机 jsdom 无 canvas,无法自动化验证);已按标准 API 实现并保留 GET 回落,请在浏览器点「导出 docx」确认图中文字/线条与页面一致。
v2.87.0 2026-10-06 中 导出 Word 带图形:后端按章节生成 matplotlib 图并嵌入 docx 用户令:修「汇报定制 → 导出 word」生成的文档里没有图形的问题。先查清性质:v2.9.2 的导出实现(src/windscada/report_export.py,179 行)只导入 Document/Pt/WD_ALIGN_PARAGRAPH,从来没有任何图片代码 ⇒ 这不是回归,而是新功能。而依赖里已有 matplotlib 3.11 · python-docx 1.2 · openpyxl ⇒ 后端具备能力。实现(app_backEnd/app_backEnd_guanlan/report_export.py):① blocks_data() 的每条中间表示带上所属块键 k(用可变持有者,最小改动);② 新增 _figure_png(k, fl):用 matplotlib(Agg) 按块键画同类图 —— 二、发电完成(瀑布)· 损失归因/停机时长归因(横向条形)· 可靠性(按部件停机时长)· 报警帕累托(柱+累计线)· 故障四象限(散点)· 故障率(月度折线),中文字体回退 Microsoft YaHei/SimHei;③ to_docx() 在该块标题之后、正文之前 add_picture(..., width=6.4in)(与页面版式一致)。本地验证:以真实 /api/fleet 夹具调 to_docx(blocks=kpi,water,emon,blame,ram,pareto,quad,frate) ⇒ docx 241,665 B、word/media/image1..6.png 6 张、<w:drawing> 6 处 ✓。线上验证:部署后先重启组件服务(首次 stop/start 后接口仍返回 39,943 B 纯文本 ⇒ 实逮:算法进程被"复用"未真正重启、旧模块仍在内存 ⇒ 结束 18050 进程再拉起)⇒ 复验 /api/rpt_export?fmt=docx&… ⇒ 200 · 241,710 B · n_media 6 · drawings 6 ✓。说明:Word 里的图是由同一份数据在 Python 侧重绘的同类图(语义一致、数据同源),与页面上的 SVG 图形不保证像素一致;若要求与页面完全一致,需改为"前端把 SVG 转 PNG 回传后端嵌入",属额外工作量(可选)。
v2.86.0 2026-10-06 中 汇报定制:章节正文渲染器从 v2.9.2 原文移植(此前为空实现) 用户反馈:「汇报定制」页面与原页面不一致。实逮根因:Vue 版里两块是空实现 —— factsHtml = computed(() => "") 与 blockHtml = () => "" ⇒ 选中任何章节,纸面上什么都不渲染 (而一致性判据只比默认视图「预览为空」⇒ 两边一致 ⇒ 判据 15/15 也没发现)。修:把 v2.9.2 的 rptFacts / rptK / rptBlock(app.js 第 531–571 行)原文移植为 src/lib/reportBlocks.ts(工厂形式接收注入的 t/fmt/esc/dv/displayText/chart/SYS_KEY/sysName/stateChip/unitNo/STEP/winName/语言包/RPT/FACTS),仅做机械适配:CH.x( → chart("x",、D. → d.、BD 明确为 d.fus.链盘(旧页 app.js:541 的原始定义)。同时在 Report.vue 接线 blockHtml/factsHtml,并让 App 为 report 页签补取 /api/facts(事实卡契约来源)。过程实逮(自身缺陷,均已修):① 抽取旧码时少取一行 ⇒ 括号不闭合(构建报 Unexpected end of file);② 重复导入 winName(Identifier already declared);③ 语言包导出名是 ZH 而非 zh。验证(真应用 jsdom · 点「月报」预设):BEFORE_ELS 1 ⇒ AFTER_ELS 575 · BLOCKS 10 · CHART_HOSTS 4 · TEXT_LEN 4180,正文首段为「观澜 · 运行分析报告 / 统计期 2026年 | 38 台 / 9 个章节 / 250,744MWh 上网电量 / 理论可发 287,713 / 1,650h 等效满发小时 / 94.8% 时间可用率 / 12.8% 损失率 / 36,968 MWh / 172h 平均停机间隔 …」,ERRS 0 ✓。
v2.85.2 2026-10-05 小 修「执行重算」第 ⑦ 步失败:「kb_ingest.py」 把 「_install_root」 误写成 「_p._install_root」 用户令(选 A):等"数据重算"跑完后复跑判据。过程中实逮一个后端代码 bug:整轮 「rebuild」 耗时 2,701 s、21 步里只有第 ⑦ 步「本体: 码表/手册/文档」失败 ⇒ 「app_ontology/app_ontology_guanlan/ontology/kb_ingest.py:74」 调用了 「_p._install_root(file)」,而 「_install_root」 是本模块第 20 行 「from app_common.app_common_guanlan.api import install_root as _install_root」 (或第 23 行的兜底定义)导入的模块级函数;「_p」 在此处解析成了别的东西(报错:「AttributeError: module 'pathlib' has no attribute '_install_root'」)⇒ 该步失败并中断整轮重算(后面步骤依赖它 ⇒ 「/api/fleet」 持续 500 · 页面呈"无数据")。修:全仓检索同写法,仅此 1 处 ⇒ 改为 「_install_root(file)」;并在远端单独跑该步验证通过:「python -m src.ontology.kb_ingest」 ⇒ 产出 「{AlarmCode: 555, WorkInstruction: 559, FailureMode: 150, MaintTask: 559, Doc: 303, Component: 9, causedBy: 60, …}」 ✓。随后重新触发整轮 「rebuild」(各步幂等)以补齐后续步骤,待 「/api/fleet」 恢复 200 后再复跑结构/内容两套判据(15/15 目标)。
v2.85.1 2026-10-05 小 措辞政策定案:以实时接口(当前算法)用词为准;3 条差异改判为「基线旧快照用词」 承接上一轮"建议第 2 步":统一 「链判级」 / 「窗末月?」 / 「平均停机间隔(MTBO)」 三处措辞差异。先查清来源(实测):这不是同一系统两条路径互相打架,而是「v2.9.2 基线页面自带的旧快照用词」与「当前算法新词」之差 —— 实时 「/api/fleet」 里新词内部一致(「MTBO口径」 1 处 · 「变化口径」 1 处 · 「纯故障口径」 1 处;旧词 0 处),而基线 「detail_v2.html」 里旧词 7 处、新词 0 处。用户裁定(2026-10-05):选 A —— 以当前算法新词为准(「口径」 等),旧快照用词视为已过时。落地:判据工具 「tools/render_parity_v292.mjs」 中三条例外的 「why」 由"待后端统一口径"改判为「基线旧快照用词 vs 当前算法新词 · 以实时接口为准 · 预期差异(非缺陷)」,并在版本记录留档。现状说明(重要):本轮复跑对拍时发现 「/api/fleet」 返回 500(110 B) —— 因为产物已被用户"清除产物"清除,故基线页与 Vue 侧都取不到数据、对拍必然 [X](预期现象,不是回归 ✓)。待用户执行「执行重算」后,需复跑结构/内容两套判据确认仍为 15/15(本轮之前刚跑过:结构 15/15 · 内容 15/15 ✓)。
v2.85.0 2026-10-05 中 清产物后给友好空态(不暴露 HTTP 500) 用户令:清除产物后相应页面不显示数据,提示要友好(不要报 HTTP 500)。修:「App.load()」 对 4xx/5xx/异常一律视为"暂无数据" ⇒ 「d = {}」(空快照 ⇒ 各页照常渲染空态、不崩)+ 「dataMissing = true」,页面顶部给友好可操作提示(i18n 「app.data_missing」:「暂无数据:产物尚未生成或已被清除。请到「系统维护」页执行「数据重算」(或在 /ops 控制台点「执行重算」),完成后本页会自动刷新。」),不出现任何 HTTP 状态码。过程实逮(两处自身缺陷,均已修):① 脚本因锚点不匹配漏插 「const dataMissing」 ⇒ 打包产物报 「ReferenceError: dataMissing is not defined」;② 「System.vue」 的 vue import 漏补 「onMounted」 ⇒ 「ReferenceError: onMounted is not defined」(system 页签渲染失败)。验证(模拟 「/api/fleet」 返回 500):七个页签(overview/energy/component/vibration/generation/fault/system)逐一 ⇒ 「errs=0」 · 「friendly=true」 · 「leaks500=false」 ✓。
v2.84.1 2026-10-05 小 清产物/重算后工作台自动重取数(并加「刷新数据」);实测空数据各页显示空态 用户要求:「清除产物」完成后,工作台相应功能(总览/电量算账/部件问题/振动融合分析/发电性能/故障统计)不应再有数据展示。实逮的问题:这些页的数据来自 「/api/fleet」(按窗实时 ✓),但清除产物是在 「/ops」 控制台里点的 ⇒ Vue 应用不会自动重新取数 ⇒ 页面仍显示清除前的数据。修:① 「System.vue」 在 「/ops」 iframe 「load」 后(同源 ✓ 可直接访问其文档)监听 「#b_off」(清除产物)/「#b_rebuild」(执行重算)/「#b_start」/「#b_stop」/「#b_restart」 的点击,动作后 4 秒触发 「refresh」;② 重算块上方加「刷新数据」按钮(手动兜底);③ 「Workbench」 透传、「App」 新增 「reload()」 —— 清空页签级缓存 「apis」/「curves」 后重新 「load()」 与 「ensureTabApis(当前页签)」。验证(用空数据模拟"清完产物",不做破坏性操作):把 「/api/fleet」 返回置为空对象后,六个页签逐一渲染 ⇒ 「overview elements=113 · energy elements=5(正文为「电量算账 无数据」)· component 21 · vibration 82 · generation 9 · fault 43」,全部 「errs=0」(不崩) ✓ —— 即清除后重取数时,各页会如实呈现"无数据/占位符"状态 ✓。
v2.84.0 2026-10-05 中 修「清除产物 404」:网关加 Path=/ops/api/** 专用路由(并实逮网关一直未真正重启) 用户反馈「系统维护」内嵌的 /ops 控制台里点「清除产物」报 404 操作被拒绝。排查链:该按钮调 「/ops/api/<动作>」(该页 API 前缀 「/ops/api/」);直连 Python 网关 28086 ⇒ 「/ops/api/state」 200 · 1,155 B(正常);经 Java 网关 28084 ⇒ 404,响应体是 Spring 的 「{"timestamp":…,"status":404}」 ⇒ 说明没有路由匹配、请求没到 28086。实逮根因(两个叠加):① 路由表里 「ops → 28086」 的谓词是 「Path=/ops/」 + 「Path=/ops」,但运行中的进程用的仍是旧配置** ⇒ 网关根本没有真正重启(旧 pid 50588 一直存活;此前几轮 「sc stop/start」 的回显都是空的、实际未生效);② 为稳妥起见还在路由表最前加了一条专用路由 「ops-api」 「Path=/ops/api/」 → 28086。修法**:改 classpath 「application.yml」 ⇒ 先 「taskkill」 旧 pid、再 「sc stop/start guanlan」、轮询确认端口换新 pid ⇒ 实测 旧 pid 50588 → 新 pid 53904 ✓,随后 「/ops/api/state」 经 28084 ⇒ 200 · 1,155 B ✓(「/ops」 仍 200 ✓)。判据:「/ops/api/state」 经网关必须 200(直连本就是 200)✓ —— 达标。教训(已记入):改配置后必须确认进程换新 pid 才算重启成功,回显为空不能当作已重启。
v2.83.3 2026-10-05 小 修「系统维护」数据重算按钮消失:内嵌改为直接 iframe src=/ops 用户反馈「系统维护」里的「清除产物」「数据重算」按钮又没了。根因:这两个按钮位于内嵌的 「/ops」 运维控制台内;该块此前用的是 Blob-URL iframe(与「振动 CMS」同一批尝试),在你的浏览器上不显示。而 「/ops」 的 「X-Frame-Options」 早在 2.81.4 已放开(网关 「frameOptions().disable()」,实测响应头无 DENY ✓)。修:把该块改回最朴素、与 v2.9.2 门户同款的写法 —— 直接 「