#!/usr/bin/env python3 """ mc 笔记库结构检查 — 2026-09-10 建(全面整理后防再犯) 检测 5 类问题: 1. 编码变体目录(同一目录被不同编码创建,如 织忆同步/ZhiyiSync/zhiyi-sync) 2. 非笔记混入(项目特征文件:Dockerfile/go.mod/package.json...) 3. 凭证泄露(文件名含 sk-/tskey-/nvapi-/ghp_) 4. 根目录散落文件 5. 空目录 用法: python3 mc-structure-check.py (有问题 exit 1,干净 exit 0) """ import os import re import sys import urllib.parse from collections import defaultdict MC = os.path.expanduser('~/mc') EXCL = ('/.git/', '.obsidian', '.smart-env', 'node_modules', '/.trash/', '/.openclaw-wiki/', '/_views/') issues = [] def norm(n: str) -> str: """把编码变体还原为统一形式(URL 编码 / unicode 转义 / latin1 误读)""" x = n if '%' in x: try: x = urllib.parse.unquote(x) except Exception: pass if '\\u' in x: try: x = x.encode('utf-8').decode('unicode_escape') except Exception: pass try: y = x.encode('latin1').decode('utf-8') if y != x: x = y except Exception: pass return x # 1. 编码变体 names = defaultdict(set) for root, dirs, files in os.walk(MC): if any(e in root for e in EXCL): continue for d in dirs: names[(root, norm(d))].add(d) for (root, n), vals in names.items(): if len(vals) > 1: issues.append(f"编码变体: {root.replace(MC + '/', '')} → {sorted(vals)}") # 2. 非笔记混入(项目特征文件) PROJ = {'Dockerfile', 'Makefile', 'go.mod', 'Cargo.toml', 'package.json', 'requirements.txt', 'pyproject.toml', 'pom.xml', 'docker-compose.yml'} for root, dirs, files in os.walk(MC): if any(e in root for e in EXCL): continue hit = PROJ & set(files) if hit: issues.append(f"疑似项目: {root.replace(MC + '/', '')} ({', '.join(sorted(hit))})") # 3. 凭证泄露(文件名) for root, dirs, files in os.walk(MC): if any(e in root for e in EXCL): continue for f in files: if re.search(r'(sk-[A-Za-z0-9]{20,}|tskey-|nvapi-|ghp_|github_pat_)', f): issues.append(f"文件名含凭证: {os.path.join(root, f).replace(MC + '/', '')}") # 4. 根目录散落 ALLOW_ROOT = {'AGENTS.md', 'WIKI.md', 'index.md', 'inbox.md', 'tracked_files.json', 'SOUL.md'} for f in os.listdir(MC): p = os.path.join(MC, f) if os.path.isfile(p) and not f.startswith('.') and f not in ALLOW_ROOT: issues.append(f"根目录散落: {f}") # 5. 空目录 for root, dirs, files in os.walk(MC): if any(e in root for e in EXCL): continue if not os.listdir(root) and root != MC: issues.append(f"空目录: {root.replace(MC + '/', '')}") if issues: print(f"⚠️ mc 结构检查: {len(issues)} 个问题") for i in issues[:30]: print(f" • {i}") if len(issues) > 30: print(f" ... 还有 {len(issues) - 30} 个") sys.exit(1) # 干净时静默(cron watchdog 模式:无输出=不打扰) if '--verbose' in sys.argv: print("✅ mc 结构检查通过(无编码变体 / 项目混入 / 凭证泄露 / 散落 / 空目录)")