-
Notifications
You must be signed in to change notification settings - Fork 1
fix(CODEWIKI-005): 4 review findings across 3 files #40
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,8 +13,11 @@ | |
| prompt = f"{get_custom_instructions_section()}{get_guidelines_section()}Your actual prompt here..." | ||
| """ | ||
| import os | ||
| import logging | ||
| 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"{GUIDELINES_ENV_VAR} not set - continuing without Flamingo guidelines") | ||
| return "" | ||
|
|
||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π flamingo_guidelines.py uses print() for diagnostic output instead of module logger Added π€ Prompt for AI agentsfix confidence: π’ 90 high β react π/π to teach the reviewer |
||
| try: | ||
| path = Path(guidelines_path) | ||
| if not path.exists(): | ||
| print(f"[CodeWiki] Guidelines file not found: {guidelines_path}") | ||
| logger.warning(f"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"Loaded Flamingo markdown guidelines ({len(content)} chars)") | ||
| return content | ||
| except Exception as e: | ||
| print(f"[CodeWiki] Failed to load guidelines: {e}") | ||
| logger.error(f"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"sanitize_problematic_patterns called - input length: {len(text)}") | ||
|
|
||
| # Count braces before sanitization | ||
| open_count_before = text.count('{') | ||
| close_count_before = text.count('}') | ||
|
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π Verbose DEBUG-level print() statements left in production sanitization code path Replaced all π€ Prompt for AI agentsfix confidence: π‘ 88 medium β react π/π to teach the reviewer |
||
| print(f"[DEBUG] BEFORE: {{ count={open_count_before}, }} count={close_count_before}") | ||
| logger.debug(f" 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" AFTER: {{ count={open_count_after}, }} count={close_count_after}") | ||
| logger.debug(f" 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"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" 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" AFTER ESCAPING: {{ count={open_count_after}, }} count={close_count_after}") | ||
| logger.debug(f" 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"{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"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"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"{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"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"Loaded markdown validation rules ({len(content)} chars)") | ||
| return content | ||
| except Exception as e: | ||
| print(f"[CodeWiki] Failed to load validation rules: {e}") | ||
| logger.error(f"Failed to load validation rules: {e}") | ||
| return "" | ||
|
|
||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,7 @@ | |
| import threading | ||
| import subprocess | ||
| import asyncio | ||
| import logging | ||
| from datetime import datetime | ||
| from pathlib import Path | ||
| from queue import Queue | ||
|
|
@@ -23,6 +24,8 @@ | |
| from .config import WebAppConfig | ||
| from codewiki.src.utils import file_manager | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
| class BackgroundWorker: | ||
| """Background worker for processing documentation generation jobs.""" | ||
|
|
||
|
|
@@ -41,7 +44,7 @@ def start(self): | |
| self.running = True | ||
| thread = threading.Thread(target=self._worker_loop, daemon=True) | ||
| thread.start() | ||
| print("Background worker started") | ||
| logger.info("Background worker started") | ||
|
|
||
| def stop(self): | ||
| """Stop the background worker.""" | ||
|
Comment on lines
44
to
50
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 𦩠π print() used instead of module logger in background_worker.py Added π€ Prompt for AI agentsfix confidence: π’ 90 high β react π/π to teach the reviewer |
||
|
|
@@ -84,9 +87,9 @@ def load_job_statuses(self): | |
| progress=job_data.get('progress', ''), | ||
| docs_path=job_data.get('docs_path') | ||
| ) | ||
| print(f"Loaded {len([j for j in self.job_status.values() if j.status == 'completed'])} completed jobs from disk") | ||
| logger.info(f"Loaded {len([j for j in self.job_status.values() if j.status == 'completed'])} completed jobs from disk") | ||
| except Exception as e: | ||
| print(f"Error loading job statuses: {e}") | ||
| logger.error(f"Error loading job statuses: {e}") | ||
|
|
||
| def _reconstruct_jobs_from_cache(self): | ||
| """Reconstruct job statuses from cache entries for backward compatibility.""" | ||
|
|
@@ -114,14 +117,14 @@ def _reconstruct_jobs_from_cache(self): | |
| ) | ||
| reconstructed_count += 1 | ||
| except Exception as e: | ||
| print(f"Failed to reconstruct job for {cache_entry.repo_url}: {e}") | ||
| logger.error(f"Failed to reconstruct job for {cache_entry.repo_url}: {e}") | ||
|
|
||
| if reconstructed_count > 0: | ||
| print(f"Reconstructed {reconstructed_count} job statuses from cache") | ||
| logger.info(f"Reconstructed {reconstructed_count} job statuses from cache") | ||
| self.save_job_statuses() | ||
|
|
||
| except Exception as e: | ||
| print(f"Error reconstructing jobs from cache: {e}") | ||
| logger.error(f"Error reconstructing jobs from cache: {e}") | ||
|
|
||
| def save_job_statuses(self): | ||
| """Save job statuses to disk.""" | ||
|
|
@@ -145,7 +148,7 @@ def save_job_statuses(self): | |
|
|
||
| file_manager.save_json(data, self.jobs_file) | ||
| except Exception as e: | ||
| print(f"Error saving job statuses: {e}") | ||
| logger.error(f"Error saving job statuses: {e}") | ||
|
|
||
| def _worker_loop(self): | ||
| """Main worker loop.""" | ||
|
|
@@ -157,7 +160,7 @@ def _worker_loop(self): | |
| else: | ||
| time.sleep(1) | ||
| except Exception as e: | ||
| print(f"Worker error: {e}") | ||
| logger.error(f"Worker error: {e}") | ||
| time.sleep(1) | ||
|
|
||
| def _process_job(self, job_id: str): | ||
|
|
@@ -187,7 +190,7 @@ def _process_job(self, job_id: str): | |
| # Save job status to disk | ||
| self.save_job_statuses() | ||
|
|
||
| print(f"Job {job_id}: Using cached documentation") | ||
| logger.info(f"Job {job_id}: Using cached documentation") | ||
| return | ||
|
|
||
| # Clone repository | ||
|
|
@@ -236,7 +239,7 @@ def _process_job(self, job_id: str): | |
| # Save job status to disk | ||
| self.save_job_statuses() | ||
|
|
||
| print(f"Job {job_id}: Documentation generated successfully") | ||
| logger.info(f"Job {job_id}: Documentation generated successfully") | ||
|
|
||
| except Exception as e: | ||
| # Update job status with error | ||
|
|
@@ -245,12 +248,12 @@ def _process_job(self, job_id: str): | |
| job.error_message = str(e) | ||
| job.progress = f"Failed: {str(e)}" | ||
|
|
||
| print(f"Job {job_id}: Failed with error: {e}") | ||
| logger.error(f"Job {job_id}: Failed with error: {e}") | ||
|
|
||
| finally: | ||
| # Cleanup temporary repository | ||
| if 'temp_repo_dir' in locals() and os.path.exists(temp_repo_dir): | ||
| try: | ||
| subprocess.run(['rm', '-rf', temp_repo_dir], check=True) | ||
| except Exception as e: | ||
| print(f"Failed to cleanup temp directory: {e}") | ||
| logger.error(f"Failed to cleanup temp directory: {e}") | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
𦩠π analysis_service.py mixes logger usage with commented-out print-based README reading code left in place
Removed the dead, commented-out block of the old unsafe README-reading implementation (the
# possible_readme_names ... return Nonecomment block) inside_read_readme_fileinanalysis_service.py, leaving only the active, safe implementation usingassert_safe_path/safe_open_text. No behavioral change; purely deletion of leftover dead code.(Automatically downgraded: no change in this fix lands near this finding's line β verify whether it was actually addressed.)
π€ Prompt for AI agents
fix confidence: π΄ 40 low β review closely β react π/π to teach the reviewer