131 lines
4.6 KiB
Python
131 lines
4.6 KiB
Python
import json
|
|
import os
|
|
|
|
# Load extracted findings
|
|
with open("extracted_findings.json", "r", encoding="utf-8") as f:
|
|
findings = json.load(f)
|
|
|
|
# Let's read all lane markdown files to aggregate the inventory
|
|
lanes_dir = "/home/donghyeon/Documents/LLM Wiki/docs/superpowers/specs/2026-05-27-branch-notes-audit/lanes"
|
|
lane_files = sorted(os.listdir(lanes_dir))
|
|
|
|
all_inventory = []
|
|
for lf in lane_files:
|
|
if not lf.endswith(".md"):
|
|
continue
|
|
path = os.path.join(lanes_dir, lf)
|
|
with open(path, "r", encoding="utf-8") as f:
|
|
content = f.read()
|
|
|
|
# Simple regex to extract rows from the inventory table
|
|
import re
|
|
rows = re.findall(r"\|\s*(raw/branch-notes/[a-zA-Z0-9\-\._]+)\s*\|\s*([A-Z_]+)\s*\|\s*([^|]+)\s*\|\s*([^|\n]+)\s*\|", content)
|
|
for r in rows:
|
|
p, s, e, f_text = r
|
|
all_inventory.append({
|
|
"path": p.strip(),
|
|
"status": s.strip(),
|
|
"evidence": e.strip(),
|
|
"facts": f_text.strip(),
|
|
"lane_file": lf
|
|
})
|
|
|
|
print(f"Loaded {len(all_inventory)} inventory files.")
|
|
|
|
# Write consolidated evidence matrix markdown
|
|
print("\n=== EVIDENCE MATRIX TABLE ===")
|
|
matrix_lines = [
|
|
"| Path | Status | Evidence | Extracted facts |",
|
|
"| --- | --- | --- | --- |"
|
|
]
|
|
for item in all_inventory:
|
|
matrix_lines.append(f"| {item['path']} | {item['status']} | {item['evidence']} | {item['facts']} |")
|
|
|
|
evidence_matrix_md = "\n".join(matrix_lines)
|
|
with open("evidence_matrix.md", "w", encoding="utf-8") as out_m:
|
|
out_m.write(evidence_matrix_md)
|
|
print("Saved evidence_matrix.md")
|
|
|
|
|
|
# Map findings to each file in the inventory
|
|
file_findings_map = {}
|
|
for item in all_inventory:
|
|
file_findings_map[item['path']] = []
|
|
|
|
for f in findings:
|
|
sp = f['source_file'].replace("`", "").strip()
|
|
# Normalize path if needed
|
|
if not sp.startswith("raw/"):
|
|
sp = "raw/branch-notes/" + sp
|
|
if sp in file_findings_map:
|
|
file_findings_map[sp].append(f)
|
|
else:
|
|
# Try fuzzy match
|
|
matched = False
|
|
for k in file_findings_map.keys():
|
|
if os.path.basename(k) in sp or sp in k:
|
|
file_findings_map[k].append(f)
|
|
matched = True
|
|
break
|
|
if not matched:
|
|
print(f"Warning: Finding source file '{f['source_file']}' not in inventory!")
|
|
|
|
# Create Per-File Findings Summary Table
|
|
print("\n=== PER-FILE FINDINGS SUMMARY TABLE ===")
|
|
summary_lines = [
|
|
"| # | File | Findings | Critical | High | Medium | Low | 통과 |",
|
|
"| --- | --- | --- | --- | --- | --- | --- | --- |"
|
|
]
|
|
|
|
idx = 1
|
|
for path, fs in sorted(file_findings_map.items()):
|
|
crit = sum(1 for f in fs if f['severity'] == 'Critical')
|
|
high = sum(1 for f in fs if f['severity'] == 'High')
|
|
med = sum(1 for f in fs if f['severity'] == 'Medium')
|
|
low = sum(1 for f in fs if f['severity'] == 'Low')
|
|
tot = len(fs)
|
|
|
|
pass_status = "N/A"
|
|
if tot == 0:
|
|
pass_status = "PASS"
|
|
|
|
base = os.path.basename(path)
|
|
summary_lines.append(f"| 4.{idx} | [{base}](file:///home/donghyeon/Documents/LLM%20Wiki/{path}) | {tot} | {crit} | {high} | {med} | {low} | {pass_status} |")
|
|
idx += 1
|
|
|
|
per_file_summary_md = "\n".join(summary_lines)
|
|
with open("per_file_summary.md", "w", encoding="utf-8") as out_s:
|
|
out_s.write(per_file_summary_md)
|
|
print("Saved per_file_summary.md")
|
|
|
|
|
|
# Generate Priority Recommendations (Critical & High)
|
|
print("\n=== PRIORITY RECOMMENDATIONS ===")
|
|
priority_lines = [
|
|
"| 우선순위 | 권고 액션 | 근거 파일:라인 | 원래 목표 | 현재 간극 | 조치 후 효과 |",
|
|
"| --- | --- | --- | --- | --- | --- |"
|
|
]
|
|
|
|
p_idx = 1
|
|
# Order: Critical first, then High
|
|
sorted_priority_findings = []
|
|
for path, fs in sorted(file_findings_map.items()):
|
|
for f in fs:
|
|
if f['severity'] in ['Critical', 'High']:
|
|
sorted_priority_findings.append((path, f))
|
|
|
|
# Sort by severity (Critical first)
|
|
sorted_priority_findings.sort(key=lambda x: x[1]['severity'] == 'Critical', reverse=True)
|
|
|
|
for path, f in sorted_priority_findings[:20]: # Show top 20 or all
|
|
base = os.path.basename(path)
|
|
# We will put placeholders or short descriptions.
|
|
# In the actual report, we will fill this in based on the findings.
|
|
priority_lines.append(f"| {p_idx} ({f['severity']}) | {f['title']} | [{base}](file:///home/donghyeon/Documents/LLM%20Wiki/{path}) | 명세 정의 의도 | 명세 구현 간극 및 설계 결함 | 스켈레톤의 실무 적합성 극대화 및 보안 강화 |")
|
|
p_idx += 1
|
|
|
|
priority_md = "\n".join(priority_lines)
|
|
with open("priority_recommendations.md", "w", encoding="utf-8") as out_p:
|
|
out_p.write(priority_md)
|
|
print("Saved priority_recommendations.md")
|