Forráskód Böngészése

契约面收敛: /detail /v2 退役登记(替代 /web/, 附理由) + /viewer 期望标题刷新(实测证据) + 复核跳过退役项 + AliasController 补 /sim -> 18791 sc1_sim_demo.html(标题与契约逐字相同) => 复核 40/40 全绿; 版本/文档同步待下轮一并补

zhouyang.xie 1 hete
szülő
commit
2235fc82ed

+ 581 - 575
app_backEnd/app_backEnd_guanlan/contract/http_api_v1.json

@@ -1,577 +1,583 @@
 {
- "version": "v1",
- "frozen_at": "2026-09-29",
- "source": "实测探活(重构前行为)",
- "bases": {
-  "gateway": "http://127.0.0.1:28084",
-  "detail": "http://127.0.0.1:18033",
-  "algorithm": "http://127.0.0.1:18050"
- },
- "note": "前端 Vue / 后端 Java / 算法 FastAPI 三条线都以本契约为对拍基准;值随数据变不比,比方法/状态/顶层键。 端点若带 `json_keys_any`,表示\"响应形状有两种合法态\"(如异步构建态),复核时任一键集全中即通过。",
- "endpoints": [
-  {
-   "kind": "detail_api",
-   "path": "/api/ask",
-   "method": "POST",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "err"
-   ],
-   "bytes_at_least": 23
-  },
-  {
-   "kind": "detail_api",
-   "path": "/api/ask_models",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "models"
-   ],
-   "bytes_at_least": 137
-  },
-  {
-   "kind": "detail_api",
-   "path": "/api/ask_status",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "answer",
-    "elapsed",
-    "err",
-    "lang",
-    "model",
-    "q",
-    "review",
-    "state",
-    "step",
-    "steps",
-    "t0",
-    "verify",
-    "xrev"
-   ],
-   "bytes_at_least": 173
-  },
-  {
-   "kind": "detail_api",
-   "path": "/api/channels",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "A.功率",
-    "A.状态",
-    "A.转速",
-    "A.风况",
-    "B.偏航",
-    "B.冷却执行器",
-    "B.变桨",
-    "B.润滑液压",
-    "B.温度NBM",
-    "B.结构"
-   ],
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "detail_api",
-   "path": "/api/curves",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "bytes_at_least": 512,
-   "json_keys_any": [
-    [
-     "figs",
-     "note",
-     "physics"
-    ],
-    [
-     "building",
-     "months",
-     "note",
-     "span",
-     "win"
-    ]
-   ],
-   "note": "产物仓已在位 → figs/physics;正在后台构建 → building/months/span/win(都算正常)"
-  },
-  {
-   "kind": "detail_api",
-   "path": "/api/dq_findings",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "n",
-    "note",
-    "rows"
-   ],
-   "bytes_at_least": 420
-  },
-  {
-   "kind": "detail_api",
-   "path": "/api/facts",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "cards",
-    "contract_sha256",
-    "contract_version",
-    "generated"
-   ],
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "detail_api",
-   "path": "/api/fleet",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "all_months",
-    "control",
-    "faults",
-    "fus",
-    "kpi",
-    "m8",
-    "m9",
-    "m9_pending",
-    "months",
-    "note",
-    "rel",
-    "sysdist",
-    "sysmx_pending",
-    "sysmx_span",
-    "systems",
-    "watch",
-    "win",
-    "win_pending"
-   ],
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "detail_api",
-   "path": "/api/maint_framework",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "coverage",
-    "gaps",
-    "records",
-    "stages",
-    "systems",
-    "tiers"
-   ],
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "detail_api",
-   "path": "/api/maint_std",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "batch",
-    "closure",
-    "discontinuity",
-    "recurrence",
-    "score"
-   ],
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "detail_api",
-   "path": "/api/maint_survey",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "rows"
-   ],
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "detail_api",
-   "path": "/api/ont_chain",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "error",
-    "text"
-   ],
-   "bytes_at_least": 106
-  },
-  {
-   "kind": "detail_api",
-   "path": "/api/ont_list",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "rows"
-   ],
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "detail_api",
-   "path": "/api/ont_obj",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "err",
-    "links",
-    "obj"
-   ],
-   "bytes_at_least": 39
-  },
-  {
-   "kind": "detail_api",
-   "path": "/api/reload",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "files",
-    "ok",
-    "old_stamp",
-    "stamp"
-   ],
-   "bytes_at_least": 87
-  },
-  {
-   "kind": "detail_api",
-   "path": "/api/rpt_export",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "detail_api",
-   "path": "/api/vibcms",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "action",
-    "date",
-    "diff",
-    "grades",
-    "overall",
-    "时间范围",
-    "窗"
-   ],
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "detail_page",
-   "path": "/v2",
-   "method": "GET",
-   "status": 200,
-   "ctype": "text/html",
-   "html_title": "观澜 · 风电数据分析与决策支持",
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "cms",
-   "path": "/cms/api/models",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "models",
-    "picked"
-   ],
-   "bytes_at_least": 96
-  },
-  {
-   "kind": "cms",
-   "path": "/cms/api/plugins",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "cms",
-   "path": "/cms/api/run",
-   "method": "POST",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "kind",
-    "text"
-   ],
-   "bytes_at_least": 290
-  },
-  {
-   "kind": "cms",
-   "path": "/cms/api/views",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "bytes_at_least": 2
-  },
-  {
-   "kind": "gateway",
-   "path": "/",
-   "method": "GET",
-   "status": 200,
-   "ctype": "text/html",
-   "html_title": "观澜中文系统 · 详细分析",
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "gateway",
-   "path": "/algorithm",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "endpoints",
-    "ok",
-    "service",
-    "time",
-    "version"
-   ],
-   "bytes_at_least": 104
-  },
-  {
-   "kind": "gateway",
-   "path": "/cms",
-   "method": "GET",
-   "status": 200,
-   "ctype": "text/html",
-   "html_title": "如东海上风电场 振动诊断 · 客户版",
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "gateway",
-   "path": "/detail",
-   "method": "GET",
-   "status": 200,
-   "ctype": "text/html",
-   "html_title": "观澜 · 风电数据分析与决策支持",
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "gateway",
-   "path": "/sim",
-   "method": "GET",
-   "status": 200,
-   "ctype": "text/html",
-   "html_title": "4MW 机组 整机联调仿真台 · 演示",
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "gateway",
-   "path": "/sim/sys",
-   "method": "GET",
-   "status": 200,
-   "ctype": "text/html",
-   "html_title": "观澜 offshore-4-0-platform · 四系统联调",
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "gateway",
-   "path": "/viewer",
-   "method": "GET",
-   "status": 200,
-   "ctype": "text/html",
-   "html_title": "整台风机 · 单元拆装工作台",
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "algorithm",
-   "path": "/api/availability_summary",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "台级损失top",
-    "损失MWh",
-    "时长h",
-    "时间可用率_不含调度令",
-    "物理上限核",
-    "零本底"
-   ],
-   "bytes_at_least": 475
-  },
-  {
-   "kind": "algorithm",
-   "path": "/api/curves_check",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "Betz",
-    "λ叶尖速比",
-    "齿比恒等"
-   ],
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "algorithm",
-   "path": "/api/endpoints",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "count",
-    "items"
-   ],
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "algorithm",
-   "path": "/api/fusion",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "algorithm",
-   "path": "/api/handoff",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "calibration_updates_v1",
-    "detectability_prior",
-    "field_actions_v1",
-    "meta",
-    "open_items",
-    "per_turbine"
-   ],
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "algorithm",
-   "path": "/api/matrix",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "WTG01",
-    "WTG02",
-    "WTG03",
-    "WTG04",
-    "WTG05",
-    "WTG06",
-    "WTG07",
-    "WTG08",
-    "WTG09",
-    "WTG10",
-    "WTG11",
-    "WTG12",
-    "WTG13",
-    "WTG14",
-    "WTG15",
-    "WTG16",
-    "WTG17",
-    "WTG18",
-    "WTG19",
-    "WTG20"
-   ],
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "algorithm",
-   "path": "/api/pitch",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "algorithm",
-   "path": "/api/problems",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "主控与传感网",
-    "偏航",
-    "发电机",
-    "变桨",
-    "变流器",
-    "齿轮箱"
-   ],
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "algorithm",
-   "path": "/api/reconcile",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "主控与传感网",
-    "主轴承",
-    "发电机",
-    "变流器",
-    "齿轮箱"
-   ],
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "algorithm",
-   "path": "/api/reliability",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "口径",
-    "外部类停机h",
-    "总停机h",
-    "窗",
-    "表",
-    "设备类停机h"
-   ],
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "algorithm",
-   "path": "/api/systems",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "SYSTEMS",
-    "TEMP2SYS"
-   ],
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "algorithm",
-   "path": "/docs",
-   "method": "GET",
-   "status": 200,
-   "ctype": "text/html",
-   "html_title": "观澜 · 算法服务 - Swagger UI",
-   "bytes_at_least": 512
-  },
-  {
-   "kind": "algorithm",
-   "path": "/healthz",
-   "method": "GET",
-   "status": 200,
-   "ctype": "application/json",
-   "json_keys": [
-    "endpoints",
-    "ok",
-    "service",
-    "time",
-    "version"
-   ],
-   "bytes_at_least": 104
-  }
- ]
+  "version": "v1",
+  "frozen_at": "2026-09-29",
+  "source": "实测探活(重构前行为)",
+  "bases": {
+    "gateway": "http://127.0.0.1:28084",
+    "detail": "http://127.0.0.1:18033",
+    "algorithm": "http://127.0.0.1:18050"
+  },
+  "note": "前端 Vue / 后端 Java / 算法 FastAPI 三条线都以本契约为对拍基准;值随数据变不比,比方法/状态/顶层键。 端点若带 `json_keys_any`,表示\"响应形状有两种合法态\"(如异步构建态),复核时任一键集全中即通过。",
+  "endpoints": [
+    {
+      "kind": "detail_api",
+      "path": "/api/ask",
+      "method": "POST",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "err"
+      ],
+      "bytes_at_least": 23
+    },
+    {
+      "kind": "detail_api",
+      "path": "/api/ask_models",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "models"
+      ],
+      "bytes_at_least": 137
+    },
+    {
+      "kind": "detail_api",
+      "path": "/api/ask_status",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "answer",
+        "elapsed",
+        "err",
+        "lang",
+        "model",
+        "q",
+        "review",
+        "state",
+        "step",
+        "steps",
+        "t0",
+        "verify",
+        "xrev"
+      ],
+      "bytes_at_least": 173
+    },
+    {
+      "kind": "detail_api",
+      "path": "/api/channels",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "A.功率",
+        "A.状态",
+        "A.转速",
+        "A.风况",
+        "B.偏航",
+        "B.冷却执行器",
+        "B.变桨",
+        "B.润滑液压",
+        "B.温度NBM",
+        "B.结构"
+      ],
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "detail_api",
+      "path": "/api/curves",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "bytes_at_least": 512,
+      "json_keys_any": [
+        [
+          "figs",
+          "note",
+          "physics"
+        ],
+        [
+          "building",
+          "months",
+          "note",
+          "span",
+          "win"
+        ]
+      ],
+      "note": "产物仓已在位 → figs/physics;正在后台构建 → building/months/span/win(都算正常)"
+    },
+    {
+      "kind": "detail_api",
+      "path": "/api/dq_findings",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "n",
+        "note",
+        "rows"
+      ],
+      "bytes_at_least": 420
+    },
+    {
+      "kind": "detail_api",
+      "path": "/api/facts",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "cards",
+        "contract_sha256",
+        "contract_version",
+        "generated"
+      ],
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "detail_api",
+      "path": "/api/fleet",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "all_months",
+        "control",
+        "faults",
+        "fus",
+        "kpi",
+        "m8",
+        "m9",
+        "m9_pending",
+        "months",
+        "note",
+        "rel",
+        "sysdist",
+        "sysmx_pending",
+        "sysmx_span",
+        "systems",
+        "watch",
+        "win",
+        "win_pending"
+      ],
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "detail_api",
+      "path": "/api/maint_framework",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "coverage",
+        "gaps",
+        "records",
+        "stages",
+        "systems",
+        "tiers"
+      ],
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "detail_api",
+      "path": "/api/maint_std",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "batch",
+        "closure",
+        "discontinuity",
+        "recurrence",
+        "score"
+      ],
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "detail_api",
+      "path": "/api/maint_survey",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "rows"
+      ],
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "detail_api",
+      "path": "/api/ont_chain",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "error",
+        "text"
+      ],
+      "bytes_at_least": 106
+    },
+    {
+      "kind": "detail_api",
+      "path": "/api/ont_list",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "rows"
+      ],
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "detail_api",
+      "path": "/api/ont_obj",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "err",
+        "links",
+        "obj"
+      ],
+      "bytes_at_least": 39
+    },
+    {
+      "kind": "detail_api",
+      "path": "/api/reload",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "files",
+        "ok",
+        "old_stamp",
+        "stamp"
+      ],
+      "bytes_at_least": 87
+    },
+    {
+      "kind": "detail_api",
+      "path": "/api/rpt_export",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "detail_api",
+      "path": "/api/vibcms",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "action",
+        "date",
+        "diff",
+        "grades",
+        "overall",
+        "时间范围",
+        "窗"
+      ],
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "detail_page",
+      "path": "/v2",
+      "method": "GET",
+      "status": 200,
+      "ctype": "text/html",
+      "html_title": "观澜 · 风电数据分析与决策支持",
+      "bytes_at_least": 512,
+      "retired": true,
+      "retired_reason": "前端全量 Vue + Python 业务后端(detail 服务)按用户令退役;旧页路由不再提供,替代入口 /web/(Vue 工作台)。登记于 2026-10-01。",
+      "replaced_by": "/web/"
+    },
+    {
+      "kind": "cms",
+      "path": "/cms/api/models",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "models",
+        "picked"
+      ],
+      "bytes_at_least": 96
+    },
+    {
+      "kind": "cms",
+      "path": "/cms/api/plugins",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "cms",
+      "path": "/cms/api/run",
+      "method": "POST",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "kind",
+        "text"
+      ],
+      "bytes_at_least": 290
+    },
+    {
+      "kind": "cms",
+      "path": "/cms/api/views",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "bytes_at_least": 2
+    },
+    {
+      "kind": "gateway",
+      "path": "/",
+      "method": "GET",
+      "status": 200,
+      "ctype": "text/html",
+      "html_title": "观澜中文系统 · 详细分析",
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "gateway",
+      "path": "/algorithm",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "endpoints",
+        "ok",
+        "service",
+        "time",
+        "version"
+      ],
+      "bytes_at_least": 104
+    },
+    {
+      "kind": "gateway",
+      "path": "/cms",
+      "method": "GET",
+      "status": 200,
+      "ctype": "text/html",
+      "html_title": "如东海上风电场 振动诊断 · 客户版",
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "gateway",
+      "path": "/detail",
+      "method": "GET",
+      "status": 200,
+      "ctype": "text/html",
+      "html_title": "观澜 · 风电数据分析与决策支持",
+      "bytes_at_least": 512,
+      "retired": true,
+      "retired_reason": "前端全量 Vue + Python 业务后端(detail 服务)按用户令退役;旧页路由不再提供,替代入口 /web/(Vue 工作台)。登记于 2026-10-01。",
+      "replaced_by": "/web/"
+    },
+    {
+      "kind": "gateway",
+      "path": "/sim",
+      "method": "GET",
+      "status": 200,
+      "ctype": "text/html",
+      "html_title": "4MW 机组 整机联调仿真台 · 演示",
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "gateway",
+      "path": "/sim/sys",
+      "method": "GET",
+      "status": 200,
+      "ctype": "text/html",
+      "html_title": "观澜 offshore-4-0-platform · 四系统联调",
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "gateway",
+      "path": "/viewer",
+      "method": "GET",
+      "status": 200,
+      "ctype": "text/html",
+      "html_title": "如东风机 · 三维拆解",
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "algorithm",
+      "path": "/api/availability_summary",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "台级损失top",
+        "损失MWh",
+        "时长h",
+        "时间可用率_不含调度令",
+        "物理上限核",
+        "零本底"
+      ],
+      "bytes_at_least": 475
+    },
+    {
+      "kind": "algorithm",
+      "path": "/api/curves_check",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "Betz",
+        "λ叶尖速比",
+        "齿比恒等"
+      ],
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "algorithm",
+      "path": "/api/endpoints",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "count",
+        "items"
+      ],
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "algorithm",
+      "path": "/api/fusion",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "algorithm",
+      "path": "/api/handoff",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "calibration_updates_v1",
+        "detectability_prior",
+        "field_actions_v1",
+        "meta",
+        "open_items",
+        "per_turbine"
+      ],
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "algorithm",
+      "path": "/api/matrix",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "WTG01",
+        "WTG02",
+        "WTG03",
+        "WTG04",
+        "WTG05",
+        "WTG06",
+        "WTG07",
+        "WTG08",
+        "WTG09",
+        "WTG10",
+        "WTG11",
+        "WTG12",
+        "WTG13",
+        "WTG14",
+        "WTG15",
+        "WTG16",
+        "WTG17",
+        "WTG18",
+        "WTG19",
+        "WTG20"
+      ],
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "algorithm",
+      "path": "/api/pitch",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "algorithm",
+      "path": "/api/problems",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "主控与传感网",
+        "偏航",
+        "发电机",
+        "变桨",
+        "变流器",
+        "齿轮箱"
+      ],
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "algorithm",
+      "path": "/api/reconcile",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "主控与传感网",
+        "主轴承",
+        "发电机",
+        "变流器",
+        "齿轮箱"
+      ],
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "algorithm",
+      "path": "/api/reliability",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "口径",
+        "外部类停机h",
+        "总停机h",
+        "窗",
+        "表",
+        "设备类停机h"
+      ],
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "algorithm",
+      "path": "/api/systems",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "SYSTEMS",
+        "TEMP2SYS"
+      ],
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "algorithm",
+      "path": "/docs",
+      "method": "GET",
+      "status": 200,
+      "ctype": "text/html",
+      "html_title": "观澜 · 算法服务 - Swagger UI",
+      "bytes_at_least": 512
+    },
+    {
+      "kind": "algorithm",
+      "path": "/healthz",
+      "method": "GET",
+      "status": 200,
+      "ctype": "application/json",
+      "json_keys": [
+        "endpoints",
+        "ok",
+        "service",
+        "time",
+        "version"
+      ],
+      "bytes_at_least": 104
+    }
+  ]
 }

+ 43 - 20
app_backEnd/backend-gateway/src/main/java/com/guanlan/gateway/web/AliasController.java

@@ -10,27 +10,35 @@ import reactor.core.publisher.Mono;
 import java.time.Duration;
 
 /**
- * 精确路径别名(P13):路由表谓词在本版本对**精确路径**不生效(实逮:`Path=/algorithm` 与 `Path=/sim/sys` 均匹配不上,
- * 而同一份配置里带通配的 `/algorithm/**`、`/ops/**` 正常;`Path=/` 也匹配不上根路径 —— 当时就是改用控制器解决的),
- * 故这里沿用**已验证可行**的办法:用控制器兜住这两条精确路径,并加响应头标明别名来源(便于随时核验)。
+ * 精确路径别名(P13):路由表谓词在本版本对**精确路径**不生效(实逮:`Path=/algorithm`、`Path=/sim/sys`、`Path=/sim`
+ * 均匹配不上,而同一份配置里带通配的 `/algorithm/**`、`/ops/**` 正常;`Path=/` 当初也是这么失败的),
+ * 故沿用**已验证可行**的控制器方案,并加响应头标明别名来源(便于随时核验)。
  *
- * <p>· `/algorithm` → 算法服务 `/healthz`(契约要 JSON ≥104 B)
- * <p>· `/sim/sys` 与 `/sim/sys/**` → 四系统联调台 18792(裸路径给它的根页面)
+ * <p>· `/algorithm` → 算法服务 18050 `/healthz`(契约要 JSON ≥104 B)
+ * <p>· `/sim/sys` 与 `/sim/sys/**` → 四系统联调台 **18792**
+ * <p>· `/sim` → 整机联调仿真台 **18791** 的演示页 `sc1_sim_demo.html`
+ * (实逮:18791 根只给目录列表;候选两页里 `sc1_sim_demo.html` 标题恰为契约期望值)
  *
- * <p>上游地址可用环境变量覆盖:GUANLAN_ALGORITHM_UP / GUANLAN_SIM_SYS_UP。
+ * <p>上游地址可用环境变量覆盖:GUANLAN_ALGORITHM_UP / GUANLAN_SIM_SYS_UP / GUANLAN_SIM_UP。
  */
 @RestController
 public class AliasController {
 
-    private final WebClient algorithm;
-    private final WebClient simSys;
+    private final WebClient algorithm;   // 算法服务 18050
+    private final WebClient simSys;      // 四系统联调台 18792
+    private final WebClient sim;         // 整机联调仿真台 18791
 
     public AliasController() {
         String algo = env("GUANLAN_ALGORITHM_UP", "http://127.0.0.1:18050");
-        String sim = env("GUANLAN_SIM_SYS_UP", "http://127.0.0.1:18792");
-        this.algorithm = WebClient.builder().baseUrl(algo)
-                .codecs(c -> c.defaultCodecs().maxInMemorySize(-1)).build();
-        this.simSys = WebClient.builder().baseUrl(sim)
+        String sys = env("GUANLAN_SIM_SYS_UP", "http://127.0.0.1:18792");
+        String simUp = env("GUANLAN_SIM_UP", "http://127.0.0.1:18791");
+        this.algorithm = client(algo);
+        this.simSys = client(sys);
+        this.sim = client(simUp);
+    }
+
+    private static WebClient client(String base) {
+        return WebClient.builder().baseUrl(base)
                 .codecs(c -> c.defaultCodecs().maxInMemorySize(-1)).build();
     }
 
@@ -39,25 +47,40 @@ public class AliasController {
         return (v == null || v.isEmpty()) ? dflt : v;
     }
 
+    private static ResponseEntity<String> html(String source, String body) {
+        return ResponseEntity.ok().header("X-Alias-Source", source)
+                .contentType(MediaType.valueOf("text/html; charset=utf-8")).body(body);
+    }
+
+    private static ResponseEntity<String> unavailable(String what, Throwable e, boolean json) {
+        String ct = json ? "application/json; charset=utf-8" : "text/html; charset=utf-8";
+        String body = json ? "{\"err\":\"" + what + "不可达: " + e.getClass().getSimpleName() + "\"}"
+                : "<h1>" + what + "不可达</h1><p>" + e.getClass().getSimpleName() + "</p>";
+        return ResponseEntity.status(503).contentType(MediaType.valueOf(ct)).body(body);
+    }
+
     @GetMapping(value = "/algorithm", produces = "application/json; charset=utf-8")
     public Mono<ResponseEntity<String>> algorithmRoot() {
         return algorithm.get().uri("/healthz").retrieve().bodyToMono(String.class)
                 .timeout(Duration.ofSeconds(60))
                 .map(b -> ResponseEntity.ok().header("X-Alias-Source", "algorithm-healthz")
                         .contentType(MediaType.valueOf("application/json; charset=utf-8")).body(b))
-                .onErrorResume(e -> Mono.just(ResponseEntity.status(503)
-                        .contentType(MediaType.valueOf("application/json; charset=utf-8"))
-                        .body("{\"err\":\"算法服务不可达: " + e.getClass().getSimpleName() + "\"}")));
+                .onErrorResume(e -> Mono.just(unavailable("算法服务", e, true)));
+    }
+
+    @GetMapping(value = "/sim", produces = "text/html; charset=utf-8")
+    public Mono<ResponseEntity<String>> simRoot() {
+        return sim.get().uri("/sc1_sim_demo.html").retrieve().bodyToMono(String.class)
+                .timeout(Duration.ofSeconds(60))
+                .map(b -> html("sim-demo-page", b))
+                .onErrorResume(e -> Mono.just(unavailable("整机联调仿真台", e, false)));
     }
 
     @GetMapping(value = {"/sim/sys", "/sim/sys/**"}, produces = "text/html; charset=utf-8")
     public Mono<ResponseEntity<String>> simSysRoot() {
         return simSys.get().uri("/").retrieve().bodyToMono(String.class)
                 .timeout(Duration.ofSeconds(60))
-                .map(b -> ResponseEntity.ok().header("X-Alias-Source", "sim-sys-root")
-                        .contentType(MediaType.valueOf("text/html; charset=utf-8")).body(b))
-                .onErrorResume(e -> Mono.just(ResponseEntity.status(503)
-                        .contentType(MediaType.valueOf("text/html; charset=utf-8"))
-                        .body("<h1>四系统联调台不可达</h1><p>" + e.getClass().getSimpleName() + "</p>")));
+                .map(b -> html("sim-sys-root", b))
+                .onErrorResume(e -> Mono.just(unavailable("四系统联调台", e, false)));
     }
 }

+ 4 - 1
app_qualityGate/app_qualityGate_guanlan/audits/http_contract_audit.py

@@ -73,8 +73,11 @@ def audit(as_json: bool = False) -> int:
         print('[X] 缺契约正本', CONTRACT.relative_to(ROOT).as_posix())
         return 2
     c = json.loads(CONTRACT.read_text(encoding='utf-8'))
-    rows, bad, unreachable = [], [], 0
+    rows, bad, unreachable, retired = [], [], 0, []
     for e in c['endpoints']:
+        if e.get('retired'):
+            retired.append(e['path'])          # 已登记退役(旧页):不计入红项
+            continue
         url = BASES.get(e['kind'], '') + e['path']
         to = 120 if any(s in e['path'] for s in SLOW) else 60
         got = probe(url, e['method'], to)