mirror of
https://github.com/PR0M3TH3AN/bitvid.git
synced 2026-11-04 20:02:26 +00:00
chore(agents): run audit-agent daily task — initial audit report
- Executed `scripts/check-file-size.mjs --report` - Executed `scripts/check-innerhtml.mjs --report` - Executed `npm run lint` (skipped assets check due to missing build) - Created parser scripts in `scripts/agent/audit-parsers/` - Generated JSON reports and summary in `artifacts/audit/2026-02-12/` - Updated `AGENT_TASK_LOG.csv` Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
1 parent
8b00db23e3
commit
fab5b11824
12 files changed
+756
-23
No files matched your search
@@ -0,0 +1,61 @@
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
|
||||
def parse_file_size_log(filepath):
|
||||
"""
|
||||
Parses check-file-size.mjs raw output.
|
||||
"""
|
||||
try:
|
||||
with open(filepath, 'r') as f:
|
||||
content = f.read()
|
||||
except FileNotFoundError:
|
||||
print(f"Error: File not found: {filepath}", file=sys.stderr)
|
||||
return {}
|
||||
|
||||
metrics = {
|
||||
"grandfathered_files": 0,
|
||||
"grandfathered_excess_lines": 0,
|
||||
"new_oversized_files": 0,
|
||||
"new_excess_lines": 0,
|
||||
"grandfathered_list": [],
|
||||
"new_list": [],
|
||||
}
|
||||
|
||||
# Match "grandfathered" lines
|
||||
# Example: " ⚠ grandfathered: js/adminListStore.js (1033 lines)"
|
||||
grandfathered_matches = re.findall(r"⚠ grandfathered: (.+?) \((\d+) lines\)", content)
|
||||
for path, lines in grandfathered_matches:
|
||||
metrics["grandfathered_files"] += 1
|
||||
excess = int(lines) - 1000 # Default threshold
|
||||
metrics["grandfathered_excess_lines"] += excess
|
||||
metrics["grandfathered_list"].append({"path": path, "lines": int(lines), "excess": excess})
|
||||
|
||||
# Match "violations" (new files)
|
||||
# Example: " ✗ NEW: js/newfile.js (1200 lines, threshold 1000)"
|
||||
new_matches = re.findall(r"✗ NEW: (.+?) \((\d+) lines, threshold (\d+)\)", content)
|
||||
for path, lines, threshold in new_matches:
|
||||
metrics["new_oversized_files"] += 1
|
||||
excess = int(lines) - int(threshold)
|
||||
metrics["new_excess_lines"] += excess
|
||||
metrics["new_list"].append({"path": path, "lines": int(lines), "excess": excess})
|
||||
|
||||
# Match "GREW" violations (grandfathered growing)
|
||||
# Example: " ✗ GREW: js/file.js (1200 lines, was 1100, limit 1150)"
|
||||
grew_matches = re.findall(r"✗ GREW: (.+?) \((\d+) lines, was (\d+), limit (\d+)\)", content)
|
||||
for path, lines, was, limit in grew_matches:
|
||||
metrics["new_oversized_files"] += 1 # Count as a violation
|
||||
excess = int(lines) - int(limit) # Or relative to original? Let's use diff
|
||||
metrics["new_excess_lines"] += excess
|
||||
metrics["new_list"].append({"path": path, "lines": int(lines), "excess": excess, "type": "GREW"})
|
||||
|
||||
return metrics
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python parse_file_size.py <logfile>")
|
||||
sys.exit(1)
|
||||
|
||||
filepath = sys.argv[1]
|
||||
metrics = parse_file_size_log(filepath)
|
||||
print(json.dumps(metrics, indent=2))
|
||||
@@ -0,0 +1,57 @@
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
|
||||
def parse_innerhtml_log(filepath):
|
||||
"""
|
||||
Parses check-innerhtml.mjs raw output.
|
||||
"""
|
||||
try:
|
||||
with open(filepath, 'r') as f:
|
||||
content = f.read()
|
||||
except FileNotFoundError:
|
||||
print(f"Error: File not found: {filepath}", file=sys.stderr)
|
||||
return {}
|
||||
|
||||
metrics = {
|
||||
"total_assignments": 0,
|
||||
"files_count": 0,
|
||||
"top_offenders": [],
|
||||
"violations": []
|
||||
}
|
||||
|
||||
# Match total summary
|
||||
# Example: "innerHTML usage: 87 assignments across 34 files"
|
||||
summary_match = re.search(r"innerHTML usage: (\d+) assignments across (\d+) files", content)
|
||||
if summary_match:
|
||||
metrics["total_assignments"] = int(summary_match.group(1))
|
||||
metrics["files_count"] = int(summary_match.group(2))
|
||||
|
||||
# Match individual file usage
|
||||
# Example: " js/channelProfile.js: 10" or " js/file.js: 5 ← NEW"
|
||||
usage_matches = re.findall(r"^\s+([^\s:]+): (\d+)( ← NEW)?", content, re.MULTILINE)
|
||||
for path, count, is_new in usage_matches:
|
||||
metrics["top_offenders"].append({"path": path, "count": int(count), "is_new": bool(is_new)})
|
||||
|
||||
# Match violations (enforce mode output)
|
||||
# Example: " ✗ js/file.js: 5 total (baseline 3, +2 new) at line(s) 10, 20"
|
||||
violation_matches = re.findall(r"✗ ([^:]+): (\d+) total \(baseline (\d+), \+(\d+) new\) at line\(s\) (.+)", content)
|
||||
for path, total, baseline, new, lines in violation_matches:
|
||||
metrics["violations"].append({
|
||||
"path": path,
|
||||
"total": int(total),
|
||||
"baseline": int(baseline),
|
||||
"new": int(new),
|
||||
"lines": lines
|
||||
})
|
||||
|
||||
return metrics
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python parse_innerhtml.py <logfile>")
|
||||
sys.exit(1)
|
||||
|
||||
filepath = sys.argv[1]
|
||||
metrics = parse_innerhtml_log(filepath)
|
||||
print(json.dumps(metrics, indent=2))
|
||||
@@ -0,0 +1,58 @@
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
|
||||
def parse_lint_log(filepath):
|
||||
"""
|
||||
Parses npm run lint raw output.
|
||||
"""
|
||||
try:
|
||||
with open(filepath, 'r') as f:
|
||||
content = f.read()
|
||||
except FileNotFoundError:
|
||||
print(f"Error: File not found: {filepath}", file=sys.stderr)
|
||||
return {}
|
||||
|
||||
metrics = {
|
||||
"total_failures": 0,
|
||||
"files_with_errors": [],
|
||||
"skipped_checks": []
|
||||
}
|
||||
|
||||
# Looking for typical npm error outputs or specific linter errors.
|
||||
# Since we are running `npm run lint` which chains multiple commands, failure results in `npm ERR!`.
|
||||
|
||||
# Check if the process exited with error (usually indicated by npm ERR!)
|
||||
if "npm ERR!" in content:
|
||||
metrics["total_failures"] = 1 # At least one failure
|
||||
|
||||
# Check for specific skipped checks
|
||||
# Example: "[lint:assets] Missing dist/asset-manifest.json. Skipping asset reference check (build required)."
|
||||
skipped_matches = re.findall(r"\[(.+?)\] (.+?) Skipping (.+)", content)
|
||||
for check_name, reason, details in skipped_matches:
|
||||
metrics["skipped_checks"].append({
|
||||
"check": check_name,
|
||||
"reason": reason.strip(),
|
||||
"details": details.strip()
|
||||
})
|
||||
|
||||
# Check for stylelint errors
|
||||
# Example: "css/source.css\n 10:5 × Unexpected unknown property "foo" property-no-unknown"
|
||||
# This is hard to parse generally without JSON output, but we can look for "×" or "error" lines.
|
||||
|
||||
# Count "problems" from eslint/stylelint if standard format
|
||||
# "3 problems (3 errors, 0 warnings)"
|
||||
problem_matches = re.findall(r"(\d+) problems? \((\d+) errors?, (\d+) warnings?\)", content)
|
||||
for problems, errors, warnings in problem_matches:
|
||||
metrics["total_failures"] += int(errors)
|
||||
|
||||
return metrics
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python parse_lint.py <logfile>")
|
||||
sys.exit(1)
|
||||
|
||||
filepath = sys.argv[1]
|
||||
metrics = parse_lint_log(filepath)
|
||||
print(json.dumps(metrics, indent=2))
|
||||
@@ -0,0 +1,99 @@
|
||||
import json
|
||||
import sys
|
||||
import datetime
|
||||
|
||||
def load_json(filepath):
|
||||
try:
|
||||
with open(filepath, 'r') as f:
|
||||
return json.load(f)
|
||||
except FileNotFoundError:
|
||||
return {}
|
||||
|
||||
def generate_summary(file_size_path, innerhtml_path, lint_path, date_str):
|
||||
file_size = load_json(file_size_path)
|
||||
innerhtml = load_json(innerhtml_path)
|
||||
lint = load_json(lint_path)
|
||||
|
||||
lines = []
|
||||
lines.append(f"Title: Audit Report — {date_str} (unstable)")
|
||||
lines.append("")
|
||||
lines.append("**Summary**")
|
||||
lines.append("")
|
||||
lines.append(f"* Date: {date_str}")
|
||||
lines.append("* Branch: unstable")
|
||||
lines.append("")
|
||||
lines.append("**Metrics**")
|
||||
lines.append("")
|
||||
|
||||
# File Size
|
||||
gf_files = file_size.get("grandfathered_files", 0)
|
||||
gf_excess = file_size.get("grandfathered_excess_lines", 0)
|
||||
new_files = file_size.get("new_oversized_files", 0)
|
||||
new_excess = file_size.get("new_excess_lines", 0)
|
||||
|
||||
lines.append(f"* Grandfathered oversized files: {gf_files} files (total excess lines: {gf_excess})")
|
||||
lines.append(f"* New oversized files: {new_files} files (total excess lines: {new_excess})")
|
||||
|
||||
# InnerHTML
|
||||
total_assign = innerhtml.get("total_assignments", 0)
|
||||
files_count = innerhtml.get("files_count", 0)
|
||||
lines.append(f"* Total innerHTML assignments: {total_assign} across {files_count} files")
|
||||
lines.append("")
|
||||
lines.append(" * Top offenders:")
|
||||
lines.append("")
|
||||
|
||||
top_offenders = innerhtml.get("top_offenders", [])
|
||||
# Sort by count desc
|
||||
top_offenders.sort(key=lambda x: x["count"], reverse=True)
|
||||
|
||||
for i, offender in enumerate(top_offenders[:10]):
|
||||
status = " (NEW)" if offender.get("is_new") else ""
|
||||
lines.append(f" {i+1}. {offender['path']} — {offender['count']}{status}")
|
||||
|
||||
# Lint
|
||||
lint_failures = lint.get("total_failures", 0)
|
||||
lint_skipped = lint.get("skipped_checks", [])
|
||||
|
||||
lines.append("")
|
||||
lines.append(f"* Lint failures: {lint_failures}")
|
||||
if lint_skipped:
|
||||
lines.append(f"* Skipped checks: {len(lint_skipped)}")
|
||||
for skip in lint_skipped:
|
||||
lines.append(f" * {skip['check']}: {skip['reason']}")
|
||||
|
||||
lines.append("")
|
||||
lines.append("**High-priority items**")
|
||||
lines.append("")
|
||||
|
||||
if new_files > 0:
|
||||
for f in file_size.get("new_list", []):
|
||||
lines.append(f"* Remove or trim oversized file `{f['path']}` (excess lines: {f['excess']})")
|
||||
|
||||
violations = innerhtml.get("violations", [])
|
||||
if violations:
|
||||
for v in violations:
|
||||
lines.append(f"* Review `{v['path']}` for new innerHTML usage (+{v['new']})")
|
||||
|
||||
if lint_failures > 0:
|
||||
lines.append(f"* Fix lint errors (see logs)")
|
||||
|
||||
if not (new_files > 0 or violations or lint_failures > 0):
|
||||
lines.append("* None. Keep it up!")
|
||||
|
||||
lines.append("")
|
||||
lines.append("**Artifacts**")
|
||||
lines.append("")
|
||||
lines.append("* file-size-report.json")
|
||||
lines.append("* innerhtml-report.json")
|
||||
lines.append("* lint-report.json")
|
||||
lines.append("* raw logs")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 5:
|
||||
print("Usage: python generate_summary.py <file-size-json> <innerhtml-json> <lint-json> <date>")
|
||||
sys.exit(1)
|
||||
|
||||
summary = generate_summary(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])
|
||||
print(summary)
|
||||
Reference in new issue
Block a user