From 94d2095dd3c2bbaab7178f06b650af927b6d10ae Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 05:08:42 +0000 Subject: [PATCH 1/4] fix(CODEWIKI-005): 6 review findings across 4 files --- codewiki/src/fe/cache_manager.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/codewiki/src/fe/cache_manager.py b/codewiki/src/fe/cache_manager.py index d1560519..2ce6f9c7 100644 --- a/codewiki/src/fe/cache_manager.py +++ b/codewiki/src/fe/cache_manager.py @@ -4,6 +4,7 @@ """ import hashlib +import logging from datetime import datetime, timedelta from pathlib import Path from typing import Optional, Dict @@ -12,6 +13,8 @@ from .config import WebAppConfig from codewiki.src.utils import file_manager +logger = logging.getLogger(__name__) + class CacheManager: """Manages documentation cache.""" @@ -38,7 +41,13 @@ def load_cache_index(self): last_accessed=datetime.fromisoformat(value['last_accessed']) ) except Exception as e: - print(f"Error loading cache index: {e}") + logger.error(f"Error loading cache index: {e}, backing up corrupted file") + try: + backup_file = self.cache_dir / f"cache_index.json.corrupted.{int(datetime.now().timestamp())}" + index_file.rename(backup_file) + except Exception as backup_error: + logger.error(f"Error backing up corrupted cache index: {backup_error}") + self.cache_index = {} def save_cache_index(self): """Save cache index to disk.""" @@ -56,7 +65,7 @@ def save_cache_index(self): file_manager.save_json(data, index_file) except Exception as e: - print(f"Error saving cache index: {e}") + logger.error(f"Error saving cache index: {e}") def get_repo_hash(self, repo_url: str) -> str: """Generate hash for repository URL.""" @@ -116,4 +125,4 @@ def cleanup_expired_cache(self): del self.cache_index[repo_hash] if expired_entries: - self.save_cache_index() \ No newline at end of file + self.save_cache_index() From c56a94096784a8307ff3d2b8a3de6319a7a4dd59 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 05:08:44 +0000 Subject: [PATCH 2/4] fix(CODEWIKI-005): 6 review findings across 4 files --- codewiki/src/fe/github_processor.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/codewiki/src/fe/github_processor.py b/codewiki/src/fe/github_processor.py index bc9084d1..a31ce6b8 100644 --- a/codewiki/src/fe/github_processor.py +++ b/codewiki/src/fe/github_processor.py @@ -3,13 +3,17 @@ GitHub repository processing utilities. """ +import logging import os +import shutil import subprocess from typing import Dict from urllib.parse import urlparse from .config import WebAppConfig +logger = logging.getLogger(__name__) + class GitHubRepoProcessor: """Handles GitHub repository processing.""" @@ -66,7 +70,7 @@ def clone_repository(clone_url: str, target_dir: str, commit_id: str = None) -> ], capture_output=True, text=True, timeout=WebAppConfig.CLONE_TIMEOUT) if result.returncode != 0: - print(f"Error cloning repository: {result.stderr}") + logger.error(f"Error cloning repository: {result.stderr}") return False # Checkout specific commit @@ -75,7 +79,9 @@ def clone_repository(clone_url: str, target_dir: str, commit_id: str = None) -> ], cwd=target_dir, capture_output=True, text=True, timeout=30) if result.returncode != 0: - print(f"Error checking out commit {commit_id}: {result.stderr}") + logger.error(f"Error checking out commit {commit_id}: {result.stderr}") + if os.path.isdir(target_dir): + shutil.rmtree(target_dir, ignore_errors=True) return False else: # Clone repository with shallow depth (default behavior) @@ -84,10 +90,12 @@ def clone_repository(clone_url: str, target_dir: str, commit_id: str = None) -> ], capture_output=True, text=True, timeout=WebAppConfig.CLONE_TIMEOUT) if result.returncode != 0: - print(f"Error cloning repository: {result.stderr}") + logger.error(f"Error cloning repository: {result.stderr}") return False return True except Exception as e: - print(f"Error cloning repository: {e}") - return False \ No newline at end of file + logger.error(f"Error cloning repository: {e}") + if os.path.isdir(target_dir): + shutil.rmtree(target_dir, ignore_errors=True) + return False From 4caa35f80f11bc41ddbed5f36ff73bb0aeee88f0 Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 05:08:46 +0000 Subject: [PATCH 3/4] fix(CODEWIKI-005): 6 review findings across 4 files --- codewiki/src/be/flamingo_guidelines.py | 42 ++++++++++++++------------ 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/codewiki/src/be/flamingo_guidelines.py b/codewiki/src/be/flamingo_guidelines.py index 8014a8c5..97761d68 100644 --- a/codewiki/src/be/flamingo_guidelines.py +++ b/codewiki/src/be/flamingo_guidelines.py @@ -12,9 +12,12 @@ # In prompts: prompt = f"{get_custom_instructions_section()}{get_guidelines_section()}Your actual prompt here..." """ +import logging import os from pathlib import Path +logger = logging.getLogger(__name__) + GUIDELINES_ENV_VAR = "FLAMINGO_MARKDOWN_GUIDELINES_PATH" CUSTOM_INSTRUCTIONS_ENV_VAR = "CUSTOM_REPO_INSTRUCTIONS" VALIDATION_RULES_ENV_VAR = "VALIDATION_RULES_PATH" @@ -34,20 +37,20 @@ def load_flamingo_guidelines() -> str: guidelines_path = os.environ.get(GUIDELINES_ENV_VAR) if not guidelines_path: - print(f"[CodeWiki] {GUIDELINES_ENV_VAR} not set - continuing without Flamingo guidelines") + logger.info(f"[CodeWiki] {GUIDELINES_ENV_VAR} not set - continuing without Flamingo guidelines") return "" try: path = Path(guidelines_path) if not path.exists(): - print(f"[CodeWiki] Guidelines file not found: {guidelines_path}") + logger.warning(f"[CodeWiki] Guidelines file not found: {guidelines_path}") return "" content = path.read_text(encoding='utf-8') - print(f"[CodeWiki] Loaded Flamingo markdown guidelines ({len(content)} chars)") + logger.info(f"[CodeWiki] Loaded Flamingo markdown guidelines ({len(content)} chars)") return content except Exception as e: - print(f"[CodeWiki] Failed to load guidelines: {e}") + logger.warning(f"[CodeWiki] Failed to load guidelines: {e}") return "" @@ -75,12 +78,12 @@ def sanitize_problematic_patterns(text: str) -> str: """ import re - print(f"[DEBUG] sanitize_problematic_patterns called - input length: {len(text)}") + logger.debug(f"[DEBUG] sanitize_problematic_patterns called - input length: {len(text)}") # Count braces before sanitization open_count_before = text.count('{') close_count_before = text.count('}') - print(f"[DEBUG] BEFORE: {{ count={open_count_before}, }} count={close_count_before}") + logger.debug(f"[DEBUG] BEFORE: {{ count={open_count_before}, }} count={close_count_before}") # 1. GitHub Actions syntax: ${{...}} → ${...} # Use iterative approach for robustness with nested braces @@ -104,8 +107,8 @@ def sanitize_problematic_patterns(text: str) -> str: # Count braces after sanitization open_count_after = text.count('{') close_count_after = text.count('}') - print(f"[DEBUG] AFTER: {{ count={open_count_after}, }} count={close_count_after}") - print(f"[DEBUG] Sample (first 200 chars): {text[:200]}") + logger.debug(f"[DEBUG] AFTER: {{ count={open_count_after}, }} count={close_count_after}") + logger.debug(f"[DEBUG] Sample (first 200 chars): {text[:200]}") return text @@ -146,7 +149,7 @@ def sanitize_and_escape_format_braces(text: str) -> str: """ import re - print(f"[DEBUG] sanitize_and_escape_format_braces called - input length: {len(text)}") + logger.debug(f"[DEBUG] sanitize_and_escape_format_braces called - input length: {len(text)}") # STEP 1: SANITIZATION (if not already done) # This ensures problematic patterns are normalized before we escape braces @@ -164,7 +167,7 @@ def preserve_numeric(match): # Replace all {digit} patterns with markers text = re.sub(r'\{(\d+)\}', preserve_numeric, text) - print(f"[DEBUG] Preserved {len(numeric_placeholders)} numeric placeholders: {list(numeric_placeholders.values())}") + logger.debug(f"[DEBUG] Preserved {len(numeric_placeholders)} numeric placeholders: {list(numeric_placeholders.values())}") # STEP 3: ESCAPE ALL REMAINING BRACES # Now escape ALL braces (non-numeric content like {Decision}, {Component}) @@ -180,8 +183,8 @@ def preserve_numeric(match): # Count braces after escaping open_count_after = result.count('{') close_count_after = result.count('}') - print(f"[DEBUG] AFTER ESCAPING: {{ count={open_count_after}, }} count={close_count_after}") - print(f"[DEBUG] Sample (first 200 chars): {result[:200]}") + logger.debug(f"[DEBUG] AFTER ESCAPING: {{ count={open_count_after}, }} count={close_count_after}") + logger.debug(f"[DEBUG] Sample (first 200 chars): {result[:200]}") return result @@ -259,16 +262,16 @@ def load_custom_instructions() -> str: custom_instructions = os.environ.get(CUSTOM_INSTRUCTIONS_ENV_VAR, "") if not custom_instructions: - print(f"[CodeWiki] {CUSTOM_INSTRUCTIONS_ENV_VAR} not set - continuing without custom instructions") + logger.info(f"[CodeWiki] {CUSTOM_INSTRUCTIONS_ENV_VAR} not set - continuing without custom instructions") return "" - print(f"[CodeWiki] Loaded custom repo instructions ({len(custom_instructions)} chars)") + logger.info(f"[CodeWiki] Loaded custom repo instructions ({len(custom_instructions)} chars)") # CRITICAL: Sanitize on input - this is the ONLY place text sanitization should happen # Shell scripts pass raw text, and we handle all sanitization here in Python # This prevents double-sanitization and ensures consistent behavior sanitized = sanitize_problematic_patterns(custom_instructions) - print(f"[CodeWiki] Sanitized custom instructions ({len(sanitized)} chars after sanitization)") + logger.info(f"[CodeWiki] Sanitized custom instructions ({len(sanitized)} chars after sanitization)") return sanitized @@ -291,20 +294,20 @@ def load_validation_rules() -> str: rules_path = os.environ.get(VALIDATION_RULES_ENV_VAR) if not rules_path: - print(f"[CodeWiki] {VALIDATION_RULES_ENV_VAR} not set - continuing without validation rules injection") + logger.info(f"[CodeWiki] {VALIDATION_RULES_ENV_VAR} not set - continuing without validation rules injection") return "" try: path = Path(rules_path) if not path.exists(): - print(f"[CodeWiki] Validation rules file not found: {rules_path}") + logger.warning(f"[CodeWiki] Validation rules file not found: {rules_path}") return "" content = path.read_text(encoding='utf-8') - print(f"[CodeWiki] Loaded markdown validation rules ({len(content)} chars)") + logger.info(f"[CodeWiki] Loaded markdown validation rules ({len(content)} chars)") return content except Exception as e: - print(f"[CodeWiki] Failed to load validation rules: {e}") + logger.warning(f"[CodeWiki] Failed to load validation rules: {e}") return "" @@ -375,3 +378,4 @@ def get_custom_instructions_section() -> str: escaped_instructions + "\n\n---\n" ) + From 07138b59d088e2dd91b32a88b2a4eea4d0e7227c Mon Sep 17 00:00:00 2001 From: "flamingo[bot]" <277372822+flamingo[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2026 05:08:47 +0000 Subject: [PATCH 4/4] fix(CODEWIKI-005): 6 review findings across 4 files --- codewiki/src/fe/visualise_docs.py | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/codewiki/src/fe/visualise_docs.py b/codewiki/src/fe/visualise_docs.py index 2c8648dc..c2bd9e97 100644 --- a/codewiki/src/fe/visualise_docs.py +++ b/codewiki/src/fe/visualise_docs.py @@ -12,6 +12,7 @@ """ import argparse +import logging import sys from pathlib import Path from typing import Dict, Optional @@ -25,6 +26,8 @@ from .templates import DOCS_VIEW_TEMPLATE from codewiki.src.utils import file_manager +logger = logging.getLogger(__name__) + app = FastAPI(title="Documentation Server", description="Simple documentation server for hosting markdown documentation folders") # Global variables to store configuration @@ -55,13 +58,13 @@ def load_module_tree(docs_folder: Path) -> Optional[Dict]: """Load the module tree structure from module_tree.json.""" tree_file = docs_folder / "module_tree.json" if not tree_file.exists(): - print(f"Warning: module_tree.json not found in {docs_folder}") + logger.warning(f"module_tree.json not found in {docs_folder}") return None try: return file_manager.load_json(tree_file) except Exception as e: - print(f"Error loading module_tree.json: {e}") + logger.error(f"Error loading module_tree.json: {e}") return None @@ -219,17 +222,17 @@ def main(): # Validate docs folder docs_folder = Path(args.docs_folder) if not docs_folder.exists(): - print(f"Error: Documentation folder '{docs_folder}' does not exist") + logger.error(f"Documentation folder '{docs_folder}' does not exist") sys.exit(1) if not docs_folder.is_dir(): - print(f"Error: '{docs_folder}' is not a directory") + logger.error(f"'{docs_folder}' is not a directory") sys.exit(1) # Check for overview.md overview_file = docs_folder / "overview.md" if not overview_file.exists(): - print(f"Warning: overview.md not found in '{docs_folder}'") + logger.warning(f"overview.md not found in '{docs_folder}'") # Set global variables and environment variable for uvicorn reload global DOCS_FOLDER, MODULE_TREE @@ -240,16 +243,16 @@ def main(): import os os.environ['DOCS_FOLDER'] = DOCS_FOLDER - print(f"šŸ“š Starting documentation server...") - print(f"šŸ“ Documentation folder: {DOCS_FOLDER}") - print(f"🌐 Server running at: http://{args.host}:{args.port}") - print(f"šŸ“– Main page: overview.md") + logger.info(f"šŸ“š Starting documentation server...") + logger.info(f"šŸ“ Documentation folder: {DOCS_FOLDER}") + logger.info(f"🌐 Server running at: http://{args.host}:{args.port}") + logger.info(f"šŸ“– Main page: overview.md") if MODULE_TREE: modules_count = len(MODULE_TREE) - print(f"šŸ—‚ļø Found {modules_count} main modules in module_tree.json") + logger.info(f"šŸ—‚ļø Found {modules_count} main modules in module_tree.json") - print("\nPress Ctrl+C to stop the server") + logger.info("Press Ctrl+C to stop the server") try: import uvicorn @@ -261,8 +264,8 @@ def main(): log_level="debug" if args.debug else "info" ) except KeyboardInterrupt: - print("\nšŸ‘‹ Server stopped") + logger.info("šŸ‘‹ Server stopped") if __name__ == "__main__": - main() \ No newline at end of file + main()