Skip to content

fix(adhoc-sweep-fixes): CU-86akn96pk 3 review findings across 3 files - #111

Draft
flamingo[bot] wants to merge 3 commits into
mainfrom
ai-fix/adhoc-sweep-fixes-fcb5e2cf-35794e5e
Draft

flamingo[bot] wants to merge 3 commits into
mainfrom
ai-fix/adhoc-sweep-fixes-fcb5e2cf-35794e5e

Conversation

@flamingo

@flamingo flamingo Bot commented Sep 28, 2026 •

Copy link
Copy Markdown

Closes 3 review findings across 3 files.

Draft — this is a starting point, not a finished change. The fix required judgment, so read it before trusting it.

# Fix confidence Finding Location
1 🟡 75 medium test_clustering_debug.py monkey-patches a non-existent function create_llm_client test_clustering_debug.py:21
2 🟢 97 high clone_repository leaves a partially-cloned directory on shallow-clone failure codewiki/src/fe/github_processor.py:86
3 🟡 70 medium safe_open_text ignores O_NOFOLLOW fallback risk and permits TOCTOU between symlink check and open codewiki/src/be/dependency_analyzer/utils/security.py:28

What changed — and what was deliberately left — is explained per finding as inline review comments on the lines each finding touched.


Run: https://product-hub.flamingo.so/admin/code-review
Run id: 35794e5e-98a9-41e6-ac3b-f4c4c16f8e9d

Merging this PR is recorded as acceptance of the rule that produced it;
closing it unmerged is recorded as rejection. Both feed rule health, so
closing a wrong suggestion is useful rather than merely tidy.

ClickUp task: CU-86akn96pk CodeWiki review findings sweep (10 PRs)

@flamingo flamingo Bot left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 What this fix changed, finding by finding

3 finding(s) fixed in this draft — 3 explained inline on the diff.

Comment thread test_clustering_debug.py
Comment on lines 22 to 37
"""Monkey patch to capture LLM response."""
global captured_response
from codewiki.src.be import cluster_modules as cm_module
from codewiki.src.be.llm_services import create_llm_client

original_create = create_llm_client
original_call_llm = cm_module.call_llm

def patched_create(*args, **kwargs):
client = original_create(*args, **kwargs)
original_call = client.call
def patched_call_llm(*call_args, **call_kwargs):
result = original_call_llm(*call_args, **call_kwargs)
global captured_response
captured_response = result
return result

def patched_call(*call_args, **call_kwargs):
result = original_call(*call_args, **call_kwargs)
global captured_response
captured_response = result
return result

client.call = patched_call
return client

cm_module.create_llm_client = patched_create
cm_module.call_llm = patched_call_llm

capture_llm_response()

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🔴 test_clustering_debug.py monkey-patches a non-existent function create_llm_client

Rewrote capture_llm_response() in test_clustering_debug.py to monkey-patch cm_module.call_llm (the name cluster_modules.py actually imports and calls) instead of the nonexistent create_llm_client. The patch now wraps cm_module.call_llm directly with a function that calls the original call_llm, stores its return value into the module-global captured_response, and returns it unchanged — removing the dead create_llm_client import/client-wrapping logic entirely. This assumes cluster_modules.py calls call_llm via the module attribute (cm_module.call_llm(...) or an unqualified call_llm(...) resolved from module globals) rather than via a rebound local import; if cluster_modules.py does from codewiki.src.be.llm_services import call_llm and calls it as a bare name, patching cm_module.call_llm still works because Python looks up globals at call time. A complete verification would require seeing cluster_modules.py's exact call site to confirm the signature/return type matches what's captured here (assumed to be the raw response string, consistent with prior code's use of captured_response[:2000] and <GROUPED_COMPONENTS> substring checks).

🤖 Prompt for AI agents
In test_clustering_debug.py around line 21, review and complete this code-review fix: test_clustering_debug.py monkey-patches a non-existent function `create_llm_client`.
What the draft fix changed: Rewrote `capture_llm_response()` in `test_clustering_debug.py` to monkey-patch `cm_module.call_llm` (the name `cluster_modules.py` actually imports and calls) instead of the nonexistent `create_llm_client`. The patch now wraps `cm_module.call_llm` directly with a function that calls the original `call_llm`, stores its return value into the module-global `captured_response`, and returns it unchanged — removing the dead `create_llm_client` import/client-wrapping logic entirely. This assumes `cluster_modules.py` calls `call_llm` via the module attribute (`cm_module.call_llm(...)` or an unqualified `call_llm(...)` resolved from module globals) rather than via a rebound local import; if `cluster_modules.py` does `from codewiki.src.be.llm_services import call_llm` and calls it as a bare name, patching `cm_module.call_llm` still works because Python looks up globals at call time. A complete verification would require seeing `cluster_modules.py`'s exact call site to confirm the signature/return type matches what's captured here (assumed to be the raw response string, consistent with prior code's use of `captured_response[:2000]` and `<GROUPED_COMPONENTS>` substring checks).
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 75 medium — react 👍/👎 to teach the reviewer

Comment on lines 91 to 98

if result.returncode != 0:
logger.error(f"Error cloning repository: {result.stderr}")
if os.path.isdir(target_dir):
shutil.rmtree(target_dir, ignore_errors=True)
return False

return True

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🟠 clone_repository leaves a partially-cloned directory on shallow-clone failure

In clone_repository, the shallow-clone (else) branch now calls shutil.rmtree(target_dir, ignore_errors=True) (guarded by os.path.isdir(target_dir)) before returning False on result.returncode != 0, mirroring the cleanup already done in the commit_id branch, preventing stale/partial directories from blocking future clone attempts.

🤖 Prompt for AI agents
In codewiki/src/fe/github_processor.py around line 86, review and complete this code-review fix: clone_repository leaves a partially-cloned directory on shallow-clone failure.
What the draft fix changed: In `clone_repository`, the shallow-clone (`else`) branch now calls `shutil.rmtree(target_dir, ignore_errors=True)` (guarded by `os.path.isdir(target_dir)`) before returning False on `result.returncode != 0`, mirroring the cleanup already done in the `commit_id` branch, preventing stale/partial directories from blocking future clone attempts.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟢 97 high — react 👍/👎 to teach the reviewer

@@ -27,11 +27,21 @@ def assert_safe_path(base_dir: Path, target: Path):

def safe_open_text(base_dir: Path, target: Path, encoding="utf-8"):

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🦩 🟠 safe_open_text ignores O_NOFOLLOW fallback risk and permits TOCTOU between symlink check and open

In safe_open_text(), removed the conditional O_NOFOLLOW fallback: the function now raises PermissionError immediately if os.O_NOFOLLOW is unsupported on the platform, instead of silently opening without it. Additionally, after os.open() succeeds, the code now uses os.fstat() on the resulting file descriptor to verify (via stat.S_ISLNK) that the opened file is not a symlink, and re-runs assert_safe_path() against the target to re-check containment, narrowing (though not eliminating, since path-based re-check is still name-based) the TOCTOU window between the initial check and the open. A fully race-proof fix would require resolving containment purely from the fd (e.g. via /proc/self/fd or os.path realpath of the fd on platforms that support it), which is not attempted here since no such helper exists in this file or repo.

🤖 Prompt for AI agents
In codewiki/src/be/dependency_analyzer/utils/security.py around line 28, review and complete this code-review fix: safe_open_text ignores O_NOFOLLOW fallback risk and permits TOCTOU between symlink check and open.
What the draft fix changed: In safe_open_text(), removed the conditional O_NOFOLLOW fallback: the function now raises PermissionError immediately if os.O_NOFOLLOW is unsupported on the platform, instead of silently opening without it. Additionally, after os.open() succeeds, the code now uses os.fstat() on the resulting file descriptor to verify (via stat.S_ISLNK) that the opened file is not a symlink, and re-runs assert_safe_path() against the target to re-check containment, narrowing (though not eliminating, since path-based re-check is still name-based) the TOCTOU window between the initial check and the open. A fully race-proof fix would require resolving containment purely from the fd (e.g. via /proc/self/fd or os.path realpath of the fd on platforms that support it), which is not attempted here since no such helper exists in this file or repo.
Verify the change is correct and complete; do not refactor unrelated code.

fix confidence: 🟡 70 medium — react 👍/👎 to teach the reviewer

@flamingo flamingo Bot changed the title fix(adhoc-sweep-fixes): 3 review findings across 3 files fix(adhoc-sweep-fixes): CU-86akn96pk 3 review findings across 3 files Sep 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants