fix(installer,validation): correct default path and drop dangling links v5.9.0 update

This commit is contained in:
sck_0
2026-02-20 21:27:08 +01:00
parent e36d6fd3b3
commit 96ffb7d759
96 changed files with 843 additions and 758 deletions

View File

@@ -0,0 +1,52 @@
import os
import re
def fix_dangling_links(skills_dir):
print(f"Scanning for dangling links in {skills_dir}...")
pattern = re.compile(r'\[([^\]]*)\]\(([^)]+)\)')
fixed_count = 0
for root, dirs, files in os.walk(skills_dir):
# Skip hidden directories
dirs[:] = [d for d in dirs if not d.startswith('.')]
for file in files:
if not file.endswith('.md'): continue
file_path = os.path.join(root, file)
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
except Exception:
continue
def replacer(match):
nonlocal fixed_count
text = match.group(1)
href = match.group(2)
href_clean = href.split('#')[0].strip()
# Ignore empty links, web URLs, emails, etc.
if not href_clean or href_clean.startswith(('http://', 'https://', 'mailto:', '<', '>')):
return match.group(0)
if os.path.isabs(href_clean):
return match.group(0)
target_path = os.path.normpath(os.path.join(root, href_clean))
if not os.path.exists(target_path):
# Dangling link detected. Replace markdown link with just its text.
print(f"Fixing dangling link in {os.path.relpath(file_path, skills_dir)}: {href}")
fixed_count += 1
return text
return match.group(0)
new_content = pattern.sub(replacer, content)
if new_content != content:
with open(file_path, 'w', encoding='utf-8') as f:
f.write(new_content)
print(f"Total dangling links fixed: {fixed_count}")
if __name__ == '__main__':
base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
fix_dangling_links(os.path.join(base_dir, 'skills'))

View File

@@ -102,6 +102,22 @@ def validate_skills(skills_dir, strict_mode=False):
if not security_disclaimer_pattern.search(content):
errors.append(f"🚨 {rel_path}: OFFENSIVE SKILL MISSING SECURITY DISCLAIMER! (Must contain 'AUTHORIZED USE ONLY')")
# 5. Dangling Links Validation
# Look for markdown links: [text](href)
links = re.findall(r'\[[^\]]*\]\(([^)]+)\)', content)
for link in links:
link_clean = link.split('#')[0].strip()
# Skip empty anchors, external links, and edge cases
if not link_clean or link_clean.startswith(('http://', 'https://', 'mailto:', '<', '>')):
continue
if os.path.isabs(link_clean):
continue
# Check if file exists relative to this skill file
target_path = os.path.normpath(os.path.join(root, link_clean))
if not os.path.exists(target_path):
errors.append(f"{rel_path}: Dangling link detected. Path '{link_clean}' (from '...({link})') does not exist locally.")
# Reporting
print(f"\n📊 Checked {skill_count} skills.")