import argparse
|
import os
|
from datetime import datetime
|
|
import pymysql
|
|
|
ARCHIVE_BATCH_ID = "DL_LEGACY_COMPLIANCE_REPAIR_20260624_V1"
|
DEFAULT_SOURCE_ID = "SOURCE_LEGACY_EXTERNAL_INFORMATION_CASEBOOK"
|
|
|
def connect(args):
|
password = args.password
|
if password is None:
|
password = os.environ.get("DARKLINE_MYSQL_PASSWORD", "")
|
return pymysql.connect(
|
host=args.host,
|
port=args.port,
|
user=args.user,
|
password=password,
|
database=args.database,
|
charset="utf8mb4",
|
cursorclass=pymysql.cursors.DictCursor,
|
autocommit=False,
|
)
|
|
|
def fetch_one(cur, sql, params):
|
cur.execute(sql, params)
|
return cur.fetchone()
|
|
|
def upsert(cur, sql, params):
|
cur.execute(sql, params)
|
|
|
def main():
|
parser = argparse.ArgumentParser(description="Repair legacy darkline case structural compliance without fabricating facts.")
|
parser.add_argument("--host", default="127.0.0.1")
|
parser.add_argument("--port", type=int, default=3306)
|
parser.add_argument("--user", default="root")
|
parser.add_argument("--password", default=None)
|
parser.add_argument("--database", default="tianxia")
|
args = parser.parse_args()
|
|
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
conn = connect(args)
|
repaired = {
|
"event_gap_rows": 0,
|
"event_gap_links": 0,
|
"manifestation_gap_rows": 0,
|
"alternative_gap_rows": 0,
|
"chain_state_rows": 0,
|
}
|
|
with conn.cursor() as cur:
|
cur.execute(
|
"""
|
SELECT c.case_id, c.case_title, c.case_level, h.darkline_hypothesis_id
|
FROM dl_case_record c
|
JOIN dl_darkline_hypothesis h ON h.case_id = c.case_id
|
WHERE c.import_batch_id LIKE 'DL_LEGACY_CASE_IMPORT%'
|
ORDER BY c.case_order, c.case_id
|
"""
|
)
|
cases = cur.fetchall()
|
|
for case in cases:
|
case_id = case["case_id"]
|
hypothesis_id = case["darkline_hypothesis_id"]
|
case_title = case["case_title"]
|
event_level = case["case_level"] or "UNKNOWN"
|
|
first_step = fetch_one(
|
cur,
|
"SELECT reasoning_step_id FROM dl_case_reasoning_step WHERE case_id=%s ORDER BY step_order LIMIT 1",
|
(case_id,),
|
)
|
first_evidence = fetch_one(
|
cur,
|
"SELECT evidence_id FROM dl_evidence WHERE case_id=%s ORDER BY evidence_id LIMIT 1",
|
(case_id,),
|
)
|
first_expected = fetch_one(
|
cur,
|
"SELECT expected_line_id FROM dl_expected_line WHERE case_id=%s ORDER BY expected_line_id LIMIT 1",
|
(case_id,),
|
)
|
first_target = fetch_one(
|
cur,
|
"SELECT impact_target_id FROM dl_impact_target WHERE case_id=%s ORDER BY impact_target_id LIMIT 1",
|
(case_id,),
|
)
|
|
step_id = first_step["reasoning_step_id"] if first_step else None
|
evidence_id = first_evidence["evidence_id"] if first_evidence else None
|
expected_id = first_expected["expected_line_id"] if first_expected else None
|
target_id = first_target["impact_target_id"] if first_target else None
|
|
missing_flags = []
|
|
event_count = fetch_one(cur, "SELECT COUNT(*) cnt FROM dl_event_node WHERE case_id=%s", (case_id,))["cnt"]
|
if event_count == 0:
|
event_id = f"{case_id}_EVENT_NODE_GAP_REVIEW"
|
upsert(
|
cur,
|
"""
|
INSERT INTO dl_event_node (
|
event_node_id, darkline_hypothesis_id, case_id, event_title,
|
event_date, available_time, actor_list, target_list,
|
event_type, event_level, source_id, node_status,
|
source_reasoning_step_id, archive_batch_id
|
) VALUES (%s,%s,%s,%s,NULL,NULL,NULL,NULL,%s,%s,%s,%s,%s,%s)
|
ON DUPLICATE KEY UPDATE
|
node_status=VALUES(node_status),
|
archive_batch_id=VALUES(archive_batch_id)
|
""",
|
(
|
event_id,
|
hypothesis_id,
|
case_id,
|
f"历史导入缺口:{case_title} 尚未拆解现实事件节点",
|
"EVENT_NODE_ARCHIVE_GAP",
|
event_level,
|
DEFAULT_SOURCE_ID,
|
"HELD_BY_EVENT_NODE_ARCHIVE_GAP",
|
step_id,
|
ARCHIVE_BATCH_ID,
|
),
|
)
|
repaired["event_gap_rows"] += 1
|
missing_flags.append("event_node_gap")
|
if evidence_id:
|
link_id = f"{case_id}_LINK_EVENT_GAP_REVIEW"
|
upsert(
|
cur,
|
"""
|
INSERT INTO dl_evidence_node_link (
|
evidence_node_link_id, evidence_id, event_node_id,
|
darkline_hypothesis_id, expected_line_id, link_role, archive_batch_id
|
) VALUES (%s,%s,%s,%s,%s,%s,%s)
|
ON DUPLICATE KEY UPDATE
|
event_node_id=VALUES(event_node_id),
|
expected_line_id=VALUES(expected_line_id),
|
link_role=VALUES(link_role),
|
archive_batch_id=VALUES(archive_batch_id)
|
""",
|
(
|
link_id,
|
evidence_id,
|
event_id,
|
hypothesis_id,
|
expected_id,
|
"GAP_REVIEW_EVIDENCE",
|
ARCHIVE_BATCH_ID,
|
),
|
)
|
repaired["event_gap_links"] += 1
|
|
manifestation_count = fetch_one(cur, "SELECT COUNT(*) cnt FROM dl_manifestation_bridge WHERE case_id=%s", (case_id,))["cnt"]
|
bridge_id = None
|
if manifestation_count == 0:
|
bridge_id = f"{case_id}_MANIFESTATION_GAP_REVIEW"
|
upsert(
|
cur,
|
"""
|
INSERT INTO dl_manifestation_bridge (
|
bridge_id, darkline_hypothesis_id, case_id, expected_line_id,
|
impact_target_id, output_layer, manifestation_time,
|
manifestation_value, control_group_id, support_status,
|
source_reasoning_step_id, archive_batch_id
|
) VALUES (%s,%s,%s,%s,%s,%s,NULL,%s,NULL,%s,%s,%s)
|
ON DUPLICATE KEY UPDATE
|
manifestation_value=VALUES(manifestation_value),
|
support_status=VALUES(support_status),
|
archive_batch_id=VALUES(archive_batch_id)
|
""",
|
(
|
bridge_id,
|
hypothesis_id,
|
case_id,
|
expected_id,
|
target_id,
|
"MARKET_MANIFESTATION_REVIEW",
|
"历史导入缺口:尚未归档市场或输出层显影;不得视为已验证。",
|
"HELD_BY_MARKET_MANIFESTATION_GAP",
|
step_id,
|
ARCHIVE_BATCH_ID,
|
),
|
)
|
repaired["manifestation_gap_rows"] += 1
|
missing_flags.append("manifestation_gap")
|
else:
|
first_bridge = fetch_one(
|
cur,
|
"SELECT bridge_id FROM dl_manifestation_bridge WHERE case_id=%s ORDER BY bridge_id LIMIT 1",
|
(case_id,),
|
)
|
bridge_id = first_bridge["bridge_id"] if first_bridge else None
|
|
alternative_count = fetch_one(cur, "SELECT COUNT(*) cnt FROM dl_alternative_explanation WHERE case_id=%s", (case_id,))["cnt"]
|
if alternative_count == 0:
|
alternative_id = f"{case_id}_ALTERNATIVE_GAP_REVIEW"
|
upsert(
|
cur,
|
"""
|
INSERT INTO dl_alternative_explanation (
|
alternative_id, darkline_hypothesis_id, case_id, bridge_id,
|
alternative_type, explanation, strength, current_status,
|
source_reasoning_step_id, archive_batch_id
|
) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
|
ON DUPLICATE KEY UPDATE
|
bridge_id=VALUES(bridge_id),
|
explanation=VALUES(explanation),
|
current_status=VALUES(current_status),
|
archive_batch_id=VALUES(archive_batch_id)
|
""",
|
(
|
alternative_id,
|
hypothesis_id,
|
case_id,
|
bridge_id,
|
"ALTERNATIVE_EXPLANATION_REVIEW_PENDING",
|
"历史导入缺口:替代解释未完整归档。复用前必须检查市场普涨、行业风、单股动能、其他暗线和数据缺口。",
|
"REVIEW",
|
"HELD_BY_ALTERNATIVE_EXPLANATION_GAP",
|
step_id,
|
ARCHIVE_BATCH_ID,
|
),
|
)
|
repaired["alternative_gap_rows"] += 1
|
missing_flags.append("alternative_gap")
|
|
note = "Legacy case structural compliance audited."
|
if missing_flags:
|
note += " Gap placeholders added: " + ",".join(missing_flags) + ". These rows are review markers, not confirmed facts."
|
chain_status = "LEGACY_STRUCTURAL_COMPLIANCE_REPAIRED"
|
reality_status = "REVIEW_GAP_EXPLICITLY_MARKED"
|
market_status = "REVIEW_GAP_EXPLICITLY_MARKED"
|
readout = "CASEBOOK_WITH_EXPLICIT_GAPS"
|
else:
|
note += " Full chain rows were already present before repair."
|
chain_status = "LEGACY_FULL_CHAIN_PRESENT"
|
reality_status = "LEGACY_FULL_CHAIN_PRESENT"
|
market_status = "LEGACY_FULL_CHAIN_PRESENT"
|
readout = "CASEBOOK_FULL_CHAIN_IMPORTED"
|
|
state_id = f"{case_id}_STATE_LEGACY_COMPLIANCE_V1"
|
upsert(
|
cur,
|
"""
|
INSERT INTO dl_chain_state (
|
state_record_id, darkline_hypothesis_id, case_id,
|
chain_clarity_status, reality_confirmation_status,
|
market_manifestation_status, validation_readout_status,
|
current_consumption_level, state_record_time, note
|
) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
|
ON DUPLICATE KEY UPDATE
|
chain_clarity_status=VALUES(chain_clarity_status),
|
reality_confirmation_status=VALUES(reality_confirmation_status),
|
market_manifestation_status=VALUES(market_manifestation_status),
|
validation_readout_status=VALUES(validation_readout_status),
|
current_consumption_level=VALUES(current_consumption_level),
|
state_record_time=VALUES(state_record_time),
|
note=VALUES(note)
|
""",
|
(
|
state_id,
|
hypothesis_id,
|
case_id,
|
chain_status,
|
reality_status,
|
market_status,
|
readout,
|
"CASEBOOK",
|
now,
|
note,
|
),
|
)
|
repaired["chain_state_rows"] += 1
|
|
conn.commit()
|
|
print({"case_count": len(cases), **repaired})
|
|
|
if __name__ == "__main__":
|
main()
|