Просмотр исходного кода

docs(smart-ops): record P-038–P-045 backlog and P-039 test-seed loops

Allow tenant-isolated test facts to close A/S8, B/S6–S7, and Demo/S5 diagnosis loops.

Co-authored-by: Cursor <cursoragent@cursor.com>
skygu 3 дней назад
Родитель
Сommit
53e8f844af

Разница между файлами не показана из-за своего большого размера
+ 2 - 1
doc/plan/Ai-DOP项目待办清单.md


+ 3 - 3
doc/plan/UAT留证/2026-08-17-智慧诊断正式落地/08-defects.json

@@ -33,9 +33,9 @@
     {
       "id": "SD-P1-003",
       "severity": "P1",
-      "status": "open_data_gap",
-      "title": "部分模块没有登记事实,未编造",
-      "detail": "B/S7 无 FQC;Demo/S5 无 IQC;A/S8 无异常。S9 按设计无 L2/无日值。两轮复跑缺口位置一致。"
+      "status": "closed_with_test_seed",
+      "title": "部分模块没有登记事实,已用测试数据补缺并测通",
+      "detail": "2026-08-18 编制 P039 测试行:A/S8=EX-20260818-P039-A,B/FQC=UATB-P039-FQC-001,B/S6报工=UATB-WO-001,Demo/IQC=UATDEMO-P039-IQC-001。四条诊断闭环均关闭。S9 树/日值仍属 P-040。发运/评审明细未补(注册表未用)。"
     }
   ]
 }

+ 94 - 0
doc/plan/UAT留证/2026-08-17-智慧诊断正式落地/09-p039-loop-A.json

@@ -0,0 +1,94 @@
+{
+  "work_package": "WP-SD7-API",
+  "generated_at": "2026-08-18T00:10:05",
+  "tenant": "A",
+  "account": "UATAdminA",
+  "auto_passed": false,
+  "modules": [
+    {
+      "module": "S8",
+      "dashboardHttp": 400,
+      "global": {
+        "http": 200,
+        "selectionMode": "s8_exception",
+        "metricCode": "S8_EXCEPTION",
+        "hasChildren": false,
+        "rootStatus": "red",
+        "evidenceScope": "filtered_atomic",
+        "evidenceTotal": 1,
+        "firstFact": "EX-20260818-P039-A"
+      },
+      "specified_same_as_current": true,
+      "kanban_root_present": true,
+      "create": {
+        "http": 200,
+        "skipped": null,
+        "reason": null,
+        "planNo": "SOP-20260818-001",
+        "planId": "187"
+      },
+      "submitApproval": {
+        "http": 200,
+        "message": null
+      },
+      "approveSteps": [
+        {
+          "http": 200,
+          "done": null
+        },
+        {
+          "http": null,
+          "done": true
+        }
+      ],
+      "startExecution": {
+        "http": 200,
+        "status": "executing"
+      },
+      "actionsCompleted": [
+        {
+          "actionId": "374",
+          "steps": [
+            {
+              "http": 200,
+              "status": "in_progress",
+              "message": null
+            },
+            {
+              "http": 200,
+              "status": "completed",
+              "message": null
+            }
+          ]
+        },
+        {
+          "actionId": "375",
+          "steps": [
+            {
+              "http": 200,
+              "status": "in_progress",
+              "message": null
+            },
+            {
+              "http": 200,
+              "status": "completed",
+              "message": null
+            }
+          ]
+        }
+      ],
+      "verify": {
+        "http": 200,
+        "auto": "INSUFFICIENT_DATA",
+        "status": "pending_verify"
+      },
+      "close": {
+        "http": 200,
+        "status": "closed"
+      },
+      "loopClosed": true
+    }
+  ],
+  "closed_count": 1,
+  "blocked_count": 0
+}

+ 177 - 0
doc/plan/UAT留证/2026-08-17-智慧诊断正式落地/09-p039-loop-B.json

@@ -0,0 +1,177 @@
+{
+  "work_package": "WP-SD7-API",
+  "generated_at": "2026-08-18T00:10:10",
+  "tenant": "B",
+  "account": "UATAdminB",
+  "auto_passed": false,
+  "modules": [
+    {
+      "module": "S6",
+      "dashboardHttp": 200,
+      "global": {
+        "http": 200,
+        "selectionMode": "global_worst",
+        "metricCode": "S6_L1_001",
+        "hasChildren": true,
+        "rootStatus": "yellow",
+        "evidenceScope": "filtered_atomic",
+        "evidenceTotal": 343,
+        "firstFact": "UATB-WO-008"
+      },
+      "specified_same_as_current": true,
+      "kanban_root_present": true,
+      "create": {
+        "http": 200,
+        "skipped": null,
+        "reason": null,
+        "planNo": "SOP-20260818-001",
+        "planId": "188"
+      },
+      "submitApproval": {
+        "http": 200,
+        "message": null
+      },
+      "approveSteps": [
+        {
+          "http": 200,
+          "done": null
+        },
+        {
+          "http": null,
+          "done": true
+        }
+      ],
+      "startExecution": {
+        "http": 200,
+        "status": "executing"
+      },
+      "actionsCompleted": [
+        {
+          "actionId": "376",
+          "steps": [
+            {
+              "http": 200,
+              "status": "in_progress",
+              "message": null
+            },
+            {
+              "http": 200,
+              "status": "completed",
+              "message": null
+            }
+          ]
+        },
+        {
+          "actionId": "377",
+          "steps": [
+            {
+              "http": 200,
+              "status": "in_progress",
+              "message": null
+            },
+            {
+              "http": 200,
+              "status": "completed",
+              "message": null
+            }
+          ]
+        }
+      ],
+      "verify": {
+        "http": 200,
+        "auto": "INSUFFICIENT_DATA",
+        "status": "pending_verify"
+      },
+      "close": {
+        "http": 200,
+        "status": "closed"
+      },
+      "loopClosed": true
+    },
+    {
+      "module": "S7",
+      "dashboardHttp": 200,
+      "global": {
+        "http": 200,
+        "selectionMode": "global_worst",
+        "metricCode": "S7_L1_001",
+        "hasChildren": true,
+        "rootStatus": "yellow",
+        "evidenceScope": "filtered_atomic",
+        "evidenceTotal": 1,
+        "firstFact": "UATB-P039-FQC-001"
+      },
+      "specified_same_as_current": true,
+      "kanban_root_present": true,
+      "create": {
+        "http": 200,
+        "skipped": null,
+        "reason": null,
+        "planNo": "SOP-20260818-002",
+        "planId": "189"
+      },
+      "submitApproval": {
+        "http": 200,
+        "message": null
+      },
+      "approveSteps": [
+        {
+          "http": 200,
+          "done": null
+        },
+        {
+          "http": null,
+          "done": true
+        }
+      ],
+      "startExecution": {
+        "http": 200,
+        "status": "executing"
+      },
+      "actionsCompleted": [
+        {
+          "actionId": "378",
+          "steps": [
+            {
+              "http": 200,
+              "status": "in_progress",
+              "message": null
+            },
+            {
+              "http": 200,
+              "status": "completed",
+              "message": null
+            }
+          ]
+        },
+        {
+          "actionId": "379",
+          "steps": [
+            {
+              "http": 200,
+              "status": "in_progress",
+              "message": null
+            },
+            {
+              "http": 200,
+              "status": "completed",
+              "message": null
+            }
+          ]
+        }
+      ],
+      "verify": {
+        "http": 200,
+        "auto": "INSUFFICIENT_DATA",
+        "status": "pending_verify"
+      },
+      "close": {
+        "http": 200,
+        "status": "closed"
+      },
+      "loopClosed": true
+    }
+  ],
+  "closed_count": 2,
+  "blocked_count": 0
+}

+ 94 - 0
doc/plan/UAT留证/2026-08-17-智慧诊断正式落地/09-p039-loop-DEMO.json

@@ -0,0 +1,94 @@
+{
+  "work_package": "WP-SD7-API",
+  "generated_at": "2026-08-18T00:10:28",
+  "tenant": "DEMO",
+  "account": "UATDemoAdmin",
+  "auto_passed": false,
+  "modules": [
+    {
+      "module": "S5",
+      "dashboardHttp": 200,
+      "global": {
+        "http": 200,
+        "selectionMode": "global_worst",
+        "metricCode": "S5_L1_001",
+        "hasChildren": true,
+        "rootStatus": "yellow",
+        "evidenceScope": "filtered_atomic",
+        "evidenceTotal": 1,
+        "firstFact": "UATDEMO-P039-IQC-001"
+      },
+      "specified_same_as_current": true,
+      "kanban_root_present": true,
+      "create": {
+        "http": 200,
+        "skipped": null,
+        "reason": null,
+        "planNo": "SOP-20260818-001",
+        "planId": "190"
+      },
+      "submitApproval": {
+        "http": 200,
+        "message": null
+      },
+      "approveSteps": [
+        {
+          "http": 200,
+          "done": null
+        },
+        {
+          "http": null,
+          "done": true
+        }
+      ],
+      "startExecution": {
+        "http": 200,
+        "status": "executing"
+      },
+      "actionsCompleted": [
+        {
+          "actionId": "380",
+          "steps": [
+            {
+              "http": 200,
+              "status": "in_progress",
+              "message": null
+            },
+            {
+              "http": 200,
+              "status": "completed",
+              "message": null
+            }
+          ]
+        },
+        {
+          "actionId": "381",
+          "steps": [
+            {
+              "http": 200,
+              "status": "in_progress",
+              "message": null
+            },
+            {
+              "http": 200,
+              "status": "completed",
+              "message": null
+            }
+          ]
+        }
+      ],
+      "verify": {
+        "http": 200,
+        "auto": "INSUFFICIENT_DATA",
+        "status": "pending_verify"
+      },
+      "close": {
+        "http": 200,
+        "status": "closed"
+      },
+      "loopClosed": true
+    }
+  ],
+  "closed_count": 1,
+  "blocked_count": 0
+}

+ 74 - 0
doc/plan/UAT留证/2026-08-17-智慧诊断正式落地/09-p039-summary.json

@@ -0,0 +1,74 @@
+{
+  "work_package": "P-039",
+  "generated_at": "2026-08-18T00:15:00",
+  "auto_passed": false,
+  "data_kind": "test_seed",
+  "seed_batch": "P039_TEST_20260818",
+  "seed_script": "doc/plan/sql/uat-data/run_wp_sd_p039_seed.py",
+  "seeded": [
+    {
+      "tenant": "A",
+      "table": "ado_s8_exception",
+      "object_code": "EX-20260818-P039-A",
+      "factory_id": "838257186320453"
+    },
+    {
+      "tenant": "B",
+      "table": "mdp_std_fqc_result",
+      "object_code": "UATB-P039-FQC-001",
+      "factory_id": "838257212858437"
+    },
+    {
+      "tenant": "B",
+      "table": "mdp_std_s6_report",
+      "object_code": "UATB-WO-001",
+      "factory_id": "838257212858437"
+    },
+    {
+      "tenant": "DEMO",
+      "table": "qms_qcp_inspbill",
+      "object_code": "UATDEMO-P039-IQC-001",
+      "factory_id": null
+    }
+  ],
+  "loops": [
+    {
+      "tenant": "A",
+      "module": "S8",
+      "evidenceScope": "filtered_atomic",
+      "firstFact": "EX-20260818-P039-A",
+      "planNo": "SOP-20260818-001",
+      "loopClosed": true
+    },
+    {
+      "tenant": "B",
+      "module": "S6",
+      "evidenceScope": "filtered_atomic",
+      "firstFact": "UATB-WO-008",
+      "note": "S6 合并工单排程与报工源;首条仍是排程贡献最大的工单。报工源现有 1 行 UATB-WO-001。",
+      "planNo": "SOP-20260818-001",
+      "loopClosed": true
+    },
+    {
+      "tenant": "B",
+      "module": "S7",
+      "evidenceScope": "filtered_atomic",
+      "firstFact": "UATB-P039-FQC-001",
+      "planNo": "SOP-20260818-002",
+      "loopClosed": true
+    },
+    {
+      "tenant": "DEMO",
+      "module": "S5",
+      "evidenceScope": "filtered_atomic",
+      "firstFact": "UATDEMO-P039-IQC-001",
+      "planNo": "SOP-20260818-001",
+      "loopClosed": true
+    }
+  ],
+  "not_seeded": [
+    "dwd_ship_trans",
+    "dwd_requirement_examine_detail"
+  ],
+  "not_seeded_reason": "当前 SmartDiagnosisEvidenceRegistry 未登记这两张表,不影响 S5/S6/S7/S8 诊断闭环。"
+}

+ 9 - 5
doc/plan/UAT留证/2026-08-17-智慧诊断正式落地/README.md

@@ -116,12 +116,16 @@ S8 专项(不复制 KPI 树):诊断 `selectionMode=s8_exception`,只把
 - 黄单 1 步、S9 三节点、自动评价 `INSUFFICIENT_DATA` 两轮相同。
 - 补跑 `08-rerun3-actions-*.json`:行动项按 `pending → in_progress → completed` 更新,接口 200。
 
-未完成 / 不得宣布交付通过:
+未完成 / 不得宣布交付通过(已登记项目待办)
 
-- 无页面截图。
-- A 无 S8 异常,S8 关联无法在该租户验收。
-- B/S7、Demo/S5、S9 KPI 树缺口仍在。
-- WP-SD9 仍 HOLD。ChatBI 未开始。
+- 无页面截图;本次推送跳过了前后端构建补跑。→ **P-038** / **P-037**
+- A/S8、B/S7、Demo/S5、B/S6 报工源已用 **P-039 测试数据**补缺并接口闭环(`09-p039-loop-*.json`)。数据性质为测试种子,不是生产事实。`dwd_ship_trans` / `dwd_requirement_examine_detail` 仍空,当前证据注册表未用。
+- S9 按设计无 L2/无日值。→ **P-040**
+- ChatBI 未开始。→ **P-041**
+- WP-SD9 仍 HOLD。→ **P-042**
+- 本机可能与远端 `1.0.358`–`1.0.362`(FQC/MRP)哈希不一致。→ **P-043**
+
+入口:[`Ai-DOP项目待办清单.md`](../../Ai-DOP项目待办清单.md) §3。
 
 ## WP-SD9
 

+ 125 - 0
doc/plan/sql/uat-data/run_wp_sd_p039_seed.py

@@ -0,0 +1,125 @@
+#!/usr/bin/env python3
+"""P-039: seed tenant-isolated test facts so diagnosis loops can run.
+
+Does not claim production truth. Rows are tagged P039 / P039_TEST_20260818.
+"""
+
+from __future__ import annotations
+
+import re
+from pathlib import Path
+
+import pymysql
+from pymysql.constants import CLIENT
+
+ROOT = Path(__file__).resolve().parents[4]
+CONFIG = ROOT / "server" / "Admin.NET.Application" / "Configuration" / "Database.json"
+
+A = {"tenant": 838257186181189, "factory": 838257186320453}
+B = {"tenant": 838257212780613, "factory": 838257212858437}
+DEMO = {"tenant": 838257237606469, "factory": 838257237676101}
+
+
+def connect() -> pymysql.Connection:
+    raw = CONFIG.read_text(encoding="utf-8-sig")
+    value = next(
+        item
+        for item in re.findall(r'(?m)^\s*"ConnectionString"\s*:\s*"([^"]+)"', raw)
+        if "Database=aidopdev" in item
+    )
+    parts = {
+        item.split("=", 1)[0].strip().lower(): item.split("=", 1)[1].strip()
+        for item in value.split(";")
+        if "=" in item
+    }
+    return pymysql.connect(
+        host=parts["server"],
+        port=int(parts["port"]),
+        user=parts["uid"],
+        password=parts["pwd"],
+        database=parts["database"],
+        charset="utf8mb4",
+        autocommit=True,
+        client_flag=CLIENT.MULTI_STATEMENTS,
+        cursorclass=pymysql.cursors.DictCursor,
+    )
+
+
+SQL = f"""
+INSERT INTO ado_s8_exception (
+  tenant_id, factory_id, exception_code, title, description, scene_code, source_type,
+  status, severity, priority_score, priority_level, occurrence_dept_id, responsible_dept_id,
+  timeout_flag, created_at, is_deleted, module_code, consecutive_hit_count, consecutive_miss_count,
+  related_object_code, created_by)
+SELECT {A['tenant']}, {A['factory']}, 'EX-20260818-P039-A', 'P039 测试异常 产销协同超期',
+  'P039 编制测试数据,用于 A 租户 S8 诊断闭环测通', 'S1', 'MANUAL', 'NEW', 'SERIOUS', 80.00, 'P1',
+  {A['factory']}, {A['factory']}, 0, NOW(), 0, 'S1', 1, 0, 'UATA-SO-P039', 'P039'
+FROM DUAL
+WHERE NOT EXISTS (
+  SELECT 1 FROM ado_s8_exception
+  WHERE tenant_id={A['tenant']} AND factory_id={A['factory']} AND exception_code='EX-20260818-P039-A');
+
+INSERT INTO mdp_std_fqc_result (
+  tenant_id, source_system, bill_no, inspect_time, material_code, material_name, judgment,
+  inspect_qty, qualified_qty, unqualified_qty, sap_work_order_no, source_row_id, source_biz_key,
+  sync_batch_id, sync_time)
+SELECT {B['tenant']}, 'P039', 'UATB-P039-FQC-001', NOW(), '3121C0035', 'P039测试物料', 'NG',
+  10, 0, 10, 'UATB-WO-001', 'P039-B-FQC-001', 'P039-B-FQC-001', 'P039_TEST_20260818', NOW()
+FROM DUAL
+WHERE NOT EXISTS (
+  SELECT 1 FROM mdp_std_fqc_result
+  WHERE tenant_id={B['tenant']} AND source_row_id='P039-B-FQC-001');
+
+INSERT INTO mdp_std_s6_report (
+  tenant_id, factory_id, source_system, work_order_no, report_date, report_qty,
+  source_row_id, source_biz_key, sync_batch_id, sync_time)
+SELECT {B['tenant']}, {B['factory']}, 'P039', 'UATB-WO-001', NOW(), 8,
+  'P039-B-S6-001', 'P039-B-S6-001', 'P039_TEST_20260818', NOW()
+FROM DUAL
+WHERE NOT EXISTS (
+  SELECT 1 FROM mdp_std_s6_report
+  WHERE tenant_id={B['tenant']} AND source_system='P039' AND source_biz_key='P039-B-S6-001');
+
+INSERT INTO qms_qcp_inspbill (
+  id, tenant_id, FBILLNO, FBILLSTATUS, FCREATETIME, SampleQty, TestQty, FCOMMENT, UnqualifiedDescription)
+SELECT 101991258985080001, {DEMO['tenant']}, 'UATDEMO-P039-IQC-001', 'NG', NOW(), 10, 10,
+  'P039 编制测试 IQC', 'P039 test NG'
+FROM DUAL
+WHERE NOT EXISTS (
+  SELECT 1 FROM qms_qcp_inspbill
+  WHERE tenant_id={DEMO['tenant']} AND FBILLNO='UATDEMO-P039-IQC-001');
+"""
+
+
+def main() -> None:
+    conn = connect()
+    try:
+        with conn.cursor() as cur:
+            cur.execute(SQL)
+            while True:
+                if not cur.nextset():
+                    break
+        with conn.cursor() as cur:
+            cur.execute(
+                """
+                SELECT 'A_s8' k, COUNT(*) c FROM ado_s8_exception
+                 WHERE tenant_id=%s AND exception_code='EX-20260818-P039-A' AND IFNULL(is_deleted,0)=0
+                UNION ALL
+                SELECT 'B_fqc', COUNT(*) FROM mdp_std_fqc_result
+                 WHERE tenant_id=%s AND bill_no='UATB-P039-FQC-001'
+                UNION ALL
+                SELECT 'B_s6', COUNT(*) FROM mdp_std_s6_report
+                 WHERE tenant_id=%s AND source_biz_key='P039-B-S6-001'
+                UNION ALL
+                SELECT 'D_iqc', COUNT(*) FROM qms_qcp_inspbill
+                 WHERE tenant_id=%s AND FBILLNO='UATDEMO-P039-IQC-001'
+                """,
+                (A["tenant"], B["tenant"], B["tenant"], DEMO["tenant"]),
+            )
+            print({row["k"]: row["c"] for row in cur.fetchall()})
+    finally:
+        conn.close()
+
+
+if __name__ == "__main__":
+    main()

Некоторые файлы не были показаны из-за большого количества измененных файлов