From 7a6c6a2b95d1839fbdafae785fb658aff34b9066 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Mon, 19 Oct 2026 20:35:13 +0900 Subject: [PATCH] =?UTF-8?q?chore(=EC=A0=95=EB=A6=AC):=20graphify=20=C2=B7?= =?UTF-8?q?=20=EC=9C=84=ED=82=A4=20=EC=B0=8C=EA=BA=BC=EA=B8=B0=20=E2=80=94?= =?UTF-8?q?=20main.py=20=EB=A6=AC=EB=A1=9C=EB=93=9C=20=EA=B1=B4=EB=84=88?= =?UTF-8?q?=EB=9C=80=20=EB=AA=A9=EB=A1=9D=EC=9D=98=20graphify-out=20=C2=B7?= =?UTF-8?q?=20=EC=9C=84=ED=82=A4=20=EB=A6=B0=ED=84=B0=20=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=A6=BD=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01C6BNBFXFndbqYxu6sZuknK --- main.py | 1 - resources/tester/scratch/wiki_linter.py | 131 ------------------------ 2 files changed, 132 deletions(-) delete mode 100644 resources/tester/scratch/wiki_linter.py diff --git a/main.py b/main.py index 3cd51fe23..8ffc770ba 100644 --- a/main.py +++ b/main.py @@ -738,7 +738,6 @@ _RELOAD_SKIP = { "docs", "resources", "scratch", - "graphify-out", "0_old", "db_management", "migrations", diff --git a/resources/tester/scratch/wiki_linter.py b/resources/tester/scratch/wiki_linter.py deleted file mode 100644 index 263b502c8..000000000 --- a/resources/tester/scratch/wiki_linter.py +++ /dev/null @@ -1,131 +0,0 @@ -import os -import re - -WIKI_DIR = r"C:\Program_coding\임도설계 및 견적자동화 프로그램 개발\docs\wiki" -PAGES_DIR = os.path.join(WIKI_DIR, "pages") -CONCEPTS_DIR = os.path.join(WIKI_DIR, "concepts") -INDEX_PATH = os.path.join(WIKI_DIR, "index.md") - -errors = [] -warnings = [] -all_wiki_files = {} # relative_path -> absolute_path - -# Collect all markdown files in wiki/ (ignoring graphify-out and memory directories) -for root, dirs, files in os.walk(WIKI_DIR): - # skip graphify-out or memory - if "graphify-out" in root or "memory" in root: - continue - for file in files: - if file.endswith(".md"): - abs_path = os.path.join(root, file) - rel_path = os.path.relpath(abs_path, WIKI_DIR).replace("\\", "/") - all_wiki_files[rel_path] = abs_path - simple_name = os.path.splitext(rel_path)[0] - all_wiki_files[simple_name] = abs_path - -# Read index.md content -with open(INDEX_PATH, "r", encoding="utf-8") as f: - index_content = f.read() - -# Pattern for wikilinks: [[link]] or [[link|label]] -wikilink_pat = re.compile(r"\[\[([^\]|]+)(?:\|[^\]]+)?\]\]") - -for rel_path, abs_path in list(all_wiki_files.items()): - if "/" not in rel_path and rel_path != "index" and rel_path != "log": - continue - if rel_path in ["index", "log", "index.md", "log.md"]: - continue - - with open(abs_path, "r", encoding="utf-8") as f: - lines = f.readlines() - - line_count = len(lines) - content = "".join(lines) - - # Rule 14: Max 100 lines - if line_count > 100: - warnings.append(f"[Line Count] `{rel_path}.md` exceeds 100 lines ({line_count} lines).") - - # Check YAML Frontmatter via simple regex - frontmatter_match = re.match(r"^---\s*\n(.*?)\n---\s*\n", content, re.DOTALL) - if not frontmatter_match: - errors.append(f"[Frontmatter] `{rel_path}.md` has no valid YAML frontmatter.") - continue - - fm_text = frontmatter_match.group(1) - - # Simple regex parsing for status & page_id - status_match = re.search(r"^status:\s*(\w+)", fm_text, re.MULTILINE) - page_id_match = re.search(r"^page_id:\s*([^\n\r]+)", fm_text, re.MULTILINE) - - if not status_match: - errors.append(f"[Status] `{rel_path}.md` has no status field in frontmatter.") - else: - status = status_match.group(1).strip() - if status not in ["draft", "stable", "stale"]: - errors.append( - f"[Status] `{rel_path}.md` has invalid status '{status}'. Must be draft, stable, or stale." - ) - elif status == "stale": - warnings.append( - f"[Stale Page] `{rel_path}.md` is marked as stale and needs updates from raw inputs." - ) - - # Rule 5: page_id required for pages/ - if "pages/" in rel_path: - if not page_id_match: - errors.append(f"[page_id] `{rel_path}.md` is in pages/ but lacks a 'page_id' field.") - - # Check for broken wikilinks in content - links = wikilink_pat.findall(content) - for link in links: - link_clean = ( - link.strip().replace("\\", "/").split("#")[0] - ) # ignore anchor for file existence check - if not link_clean: - continue - found = False - - # 1. Absolute link from vault root (e.g. concepts/storage_paths) - if link_clean in all_wiki_files: - found = True - # 2. Simple name match (e.g. storage_paths, B01_frontend) - elif link_clean.split("/")[-1] in all_wiki_files: - found = True - # 3. Handle subpages like [[B01_Dashboard/B01_frontend]] - elif f"pages/{link_clean}" in all_wiki_files: - found = True - elif f"concepts/{link_clean}" in all_wiki_files: - found = True - # 4. Handle nested directory patterns - elif link_clean.startswith("../"): - # Resolve relative link - curr_dir = os.path.dirname(rel_path) - resolved = os.path.normpath(os.path.join(curr_dir, link_clean)).replace("\\", "/") - if resolved in all_wiki_files or resolved.replace("pages/", "") in all_wiki_files: - found = True - - if not found: - errors.append(f"[Broken Link] `{rel_path}.md` contains broken wikilink: [[{link}]]") - - # Check if this file is registered in index.md (avoid orphans) - file_base = os.path.basename(abs_path) - file_name_no_ext = os.path.splitext(file_base)[0] - if file_name_no_ext not in index_content: - # check if relative path is in index - rel_path_no_ext = rel_path.replace(".md", "") - if ( - rel_path_no_ext not in index_content - and rel_path_no_ext.split("/")[-1] not in index_content - ): - warnings.append( - f"[Orphan Page] `{rel_path}.md` is not linked or mentioned in index.md." - ) - -print("=== LINT ERRORS ===") -for e in sorted(list(set(errors))): - print(e) -print("\n=== LINT WARNINGS ===") -for w in sorted(list(set(warnings))): - print(w) -print("\nLint completed.")