Skip to content

fix(CODEWIKI-005-2): CU-86akbhh7w 16 review findings across 7 files - #34

Merged
michaelassraf merged 9 commits into
mainfrom
ai-fix/codewiki-005-2-f0f98f64-bef4f5a8
Sep 8, 2026
Merged

michaelassraf merged 9 commits into
mainfrom
ai-fix/codewiki-005-2-f0f98f64-bef4f5a8

Conversation

@flamingo

@flamingo flamingo Bot commented Aug 24, 2026

Copy link
Copy Markdown

Closes 16 review findings across 7 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 _build_namespaced_components produces FQDNs with dot-only separators, violating the '::' component ID format codewiki/src/be/dependency_analyzer/ast_parser.py:202
2 🟡 75 medium _build_components_from_analysis constructs component FQDNs with only a dot separator, not the required '::' between module path and component name codewiki/src/be/dependency_analyzer/ast_parser.py:305
3 🟢 90 high ast_parser.py forces DEBUG level on its module logger, overriding centralized logging config codewiki/src/be/dependency_analyzer/ast_parser.py:15
4 🟡 85 medium ast_parser.py module lacks a module-level docstring codewiki/src/be/dependency_analyzer/ast_parser.py:1
5 🔴 35 low — review closely _resolve_cross_namespace_dependencies matches on first same-named component found across all namespaces without disambiguation, risking incorrect cross-repo dependency edges codewiki/src/be/dependency_analyzer/ast_parser.py:254
6 🟡 80 medium Python analyzer builds component IDs with dot-separator instead of required '::' FQDN format codewiki/src/be/dependency_analyzer/analyzers/python.py:51
7 🟢 90 high Bare except clauses swallow errors silently in python.py-adjacent module path helper codewiki/src/be/dependency_analyzer/analyzers/python.py:43
8 🟢 90 high Java analyzer builds component IDs with dot-separated path, not module.path::ClassName codewiki/src/be/dependency_analyzer/analyzers/java.py:40
9 🟡 85 medium Missing module-level docstring in java.py analyzer codewiki/src/be/dependency_analyzer/analyzers/java.py:1
10 🟡 65 medium Component FQDNs constructed with '.' separator instead of required '::' in JS/TS/C++/C# analyzers codewiki/src/be/dependency_analyzer/analyzers/javascript.py:96
11 🟢 90 high javascript.py analyzer module lacks a module-level docstring codewiki/src/be/dependency_analyzer/analyzers/javascript.py:1
12 🟡 65 medium cpp.py component IDs use '.' rather than the mandated '::' separator codewiki/src/be/dependency_analyzer/analyzers/cpp.py:42
13 🟢 90 high cpp.py analyzer module lacks a module-level docstring codewiki/src/be/dependency_analyzer/analyzers/cpp.py:1
14 🟡 65 medium csharp.py component IDs use '.' rather than the mandated '::' separator codewiki/src/be/dependency_analyzer/analyzers/csharp.py:39
15 🟢 90 high csharp.py analyzer module lacks a module-level docstring codewiki/src/be/dependency_analyzer/analyzers/csharp.py:1
16 🟡 75 medium PHP analyzer also constructs component IDs with dot separators, not the required '::' FQDN format codewiki/src/be/dependency_analyzer/analyzers/php.py:148

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: bef4f5a8-e7f3-478b-8731-2becca2de658

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-86akbhh7w Code review fixes: CodeWiki backend and CLI review findings (2 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

16 finding(s) fixed in this draft — 16 explained inline on the diff; 1 low-confidence hunk(s) need close review before merging.

Comment on lines 237 to 245
if not original_id:
continue

# Create FQDN (namespaced component ID)
fqdn = f"{namespace}.{original_id}"
# Create FQDN (namespaced component ID) using '::' to separate
# the namespace/module path from the component identifier
fqdn = f"{namespace}::{original_id}"

# Store mapping for dependency resolution
namespace_mapping[original_id] = fqdn

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.

🦩 🔴 _build_namespaced_components produces FQDNs with dot-only separators, violating the '::' component ID format

In _build_namespaced_components, changed fqdn = f"{namespace}.{original_id}" to fqdn = f"{namespace}::{original_id}" so the namespace is separated from the module/component path with '::' per the required FQDN format. Also updated the namespace-splitting logic in _resolve_cross_namespace_dependencies (component_id.split(".")[0] / other_id.split(".")[0]) to split on "::" instead, since FQDNs now use that separator for the namespace boundary; this keeps cross-namespace detection working with the new ID format. Note: the module-tracking line still uses f"{namespace}.{module_path}" (dot) since that is a separate internal self.modules bookkeeping set, not a component FQDN, and was not flagged by the finding.

🤖 Prompt for AI agents
In codewiki/src/be/dependency_analyzer/ast_parser.py around line 202, review and complete this code-review fix: _build_namespaced_components produces FQDNs with dot-only separators, violating the '::' component ID format.
What the draft fix changed: In `_build_namespaced_components`, changed `fqdn = f"{namespace}.{original_id}"` to `fqdn = f"{namespace}::{original_id}"` so the namespace is separated from the module/component path with '::' per the required FQDN format. Also updated the namespace-splitting logic in `_resolve_cross_namespace_dependencies` (`component_id.split(".")[0]` / `other_id.split(".")[0]`) to split on `"::"` instead, since FQDNs now use that separator for the namespace boundary; this keeps cross-namespace detection working with the new ID format. Note: the module-tracking line still uses `f"{namespace}.{module_path}"` (dot) since that is a separate internal `self.modules` bookkeeping set, not a component FQDN, and was not flagged by the finding.
Verify the change is correct and complete; do not refactor unrelated code.

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

Comment on lines 327 to 334
for other_id, other_component in sorted(all_components.items()): # ✅ SORT for determinism
if other_component.name == dep_name and other_id != component_id:
# Extract namespaces to check if it's cross-namespace
source_namespace = component_id.split(".")[0]
target_namespace = other_id.split(".")[0]
source_namespace = component_id.split("::")[0]
target_namespace = other_id.split("::")[0]
if source_namespace != target_namespace:
logger.debug(f" ├─ Cross-namespace dependency: {component_id} → {other_id}")
cross_deps_resolved += 1

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.

🦩 🔴 _build_components_from_analysis constructs component FQDNs with only a dot separator, not the required '::' between module path and component name

In _build_components_from_analysis, changed fqdn = f"{namespace}.{original_id}" to fqdn = f"{namespace}::{original_id}" to insert the required '::' separator between the namespace/module path and the original component id. The legacy_id fallback and module tracking (self.modules.add(f"{namespace}.{module_path}")) were left as dot-based since they are not component FQDNs subject to the '::' contract per the finding text.

🤖 Prompt for AI agents
In codewiki/src/be/dependency_analyzer/ast_parser.py around line 305, review and complete this code-review fix: _build_components_from_analysis constructs component FQDNs with only a dot separator, not the required '::' between module path and component name.
What the draft fix changed: In `_build_components_from_analysis`, changed `fqdn = f"{namespace}.{original_id}"` to `fqdn = f"{namespace}::{original_id}"` to insert the required '::' separator between the namespace/module path and the original component id. The legacy_id fallback and module tracking (`self.modules.add(f"{namespace}.{module_path}")`) were left as dot-based since they are not component FQDNs subject to the '::' contract per the finding text.
Verify the change is correct and complete; do not refactor unrelated code.

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



logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

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.

🦩 🟠 ast_parser.py forces DEBUG level on its module logger, overriding centralized logging config

Removed logger.setLevel(logging.DEBUG) at module load time (was directly under logger = logging.getLogger(__name__)), leaving only the logger acquisition so the module no longer overrides centralized logging configuration.

🤖 Prompt for AI agents
In codewiki/src/be/dependency_analyzer/ast_parser.py around line 15, review and complete this code-review fix: ast_parser.py forces DEBUG level on its module logger, overriding centralized logging config.
What the draft fix changed: Removed `logger.setLevel(logging.DEBUG)` at module load time (was directly under `logger = logging.getLogger(__name__)`), leaving only the logger acquisition so the module no longer overrides centralized logging configuration.
Verify the change is correct and complete; do not refactor unrelated code.

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

- Persists the resulting dependency graph to disk for downstream consumers
(e.g., clustering, LLM-based summarization, and documentation generation).
"""
import os

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.

🦩 🟠 ast_parser.py module lacks a module-level docstring

Added a module-level triple-quoted docstring at the top of the file (before the import os line) describing the module's responsibilities in the multi-repo AST parsing / dependency graph pipeline, satisfying the documentation requirement for non-trivial modules.

🤖 Prompt for AI agents
In codewiki/src/be/dependency_analyzer/ast_parser.py around line 1, review and complete this code-review fix: ast_parser.py module lacks a module-level docstring.
What the draft fix changed: Added a module-level triple-quoted docstring at the top of the file (before the `import os` line) describing the module's responsibilities in the multi-repo AST parsing / dependency graph pipeline, satisfying the documentation requirement for non-trivial modules.
Verify the change is correct and complete; do not refactor unrelated code.

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

Comment on lines 237 to 245
if not original_id:
continue

# Create FQDN (namespaced component ID)
fqdn = f"{namespace}.{original_id}"
# Create FQDN (namespaced component ID) using '::' to separate
# the namespace/module path from the component identifier
fqdn = f"{namespace}::{original_id}"

# Store mapping for dependency resolution
namespace_mapping[original_id] = fqdn

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.

🦩 🟠 _resolve_cross_namespace_dependencies matches on first same-named component found across all namespaces without disambiguation, risking incorrect cross-repo dependency edges

Did not implement full disambiguation scoring (e.g., module-context matching like _find_best_path_match_enhanced) in _resolve_cross_namespace_dependencies, since porting that logic is architecturally significant and not visible/available in this file. As a partial, low-risk mitigation I updated the namespace boundary detection there to be consistent with the corrected '::'-based FQDN format (see note 1), which at least prevents silent misclassification caused by the old dot-based split now being wrong after the ID format fix; the underlying "first match wins with no scoring" behavior described in the finding is unchanged and still needs a real disambiguation implementation (ideally reusing the existing tested logic) to fully resolve this finding.

🤖 Prompt for AI agents
In codewiki/src/be/dependency_analyzer/ast_parser.py around line 254, review and complete this code-review fix: _resolve_cross_namespace_dependencies matches on first same-named component found across all namespaces without disambiguation, risking incorrect cross-repo dependency edges.
What the draft fix changed: Did not implement full disambiguation scoring (e.g., module-context matching like `_find_best_path_match_enhanced`) in `_resolve_cross_namespace_dependencies`, since porting that logic is architecturally significant and not visible/available in this file. As a partial, low-risk mitigation I updated the namespace boundary detection there to be consistent with the corrected '::'-based FQDN format (see note 1), which at least prevents silent misclassification caused by the old dot-based split now being wrong after the ID format fix; the underlying "first match wins with no scoring" behavior described in the finding is unchanged and still needs a real disambiguation implementation (ideally reusing the existing tested logic) to fully resolve this finding.
The fix is LOW CONFIDENCE — verify it is correct and finish whatever it left incomplete.

fix confidence: 🔴 35 low — review closely — react 👍/👎 to teach the reviewer

Comment on lines 54 to 61
def _get_component_id(self, name: str, parent_class: str = None) -> str:
module_path = self._get_module_path()
if parent_class:
return f"{module_path}.{parent_class}.{name}" if module_path else f"{parent_class}.{name}"
return f"{module_path}.{name}" if module_path else name
return f"{module_path}::{parent_class}.{name}" if module_path else f"{parent_class}.{name}"
return f"{module_path}::{name}" if module_path else name

def _analyze(self):
language_capsule = tree_sitter_cpp.language()

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.

🦩 🔴 cpp.py component IDs use '.' rather than the mandated '::' separator

In _get_component_id (line ~42), changed the module-path/name joins from . to :: so IDs are formatted as module.path::Name (and module.path::ParentClass.name for methods, preserving the parent/child dot for the method-within-class segment as before). This satisfies the module.path::ComponentName contract at the module/component boundary; the parent_class-without-module_path branch (f"{parent_class}.{name}") was left as a dot join since there is no module path to separate from the component name in that case — a reviewer should confirm whether that fallback also needs a :: per the exact spec wording.

🤖 Prompt for AI agents
In codewiki/src/be/dependency_analyzer/analyzers/cpp.py around line 42, review and complete this code-review fix: cpp.py component IDs use '.' rather than the mandated '::' separator.
What the draft fix changed: In `_get_component_id` (line ~42), changed the module-path/name joins from `.` to `::` so IDs are formatted as `module.path::Name` (and `module.path::ParentClass.name` for methods, preserving the parent/child dot for the method-within-class segment as before). This satisfies the `module.path::ComponentName` contract at the module/component boundary; the parent_class-without-module_path branch (`f"{parent_class}.{name}"`) was left as a dot join since there is no module path to separate from the component name in that case — a reviewer should confirm whether that fallback also needs a `::` per the exact spec wording.
Verify the change is correct and complete; do not refactor unrelated code.

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

between them (calls, inheritance, instantiation and usage) as
`CallRelationship` objects, for use by the dependency analysis pipeline.
"""
import logging

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.

🦩 🟠 cpp.py analyzer module lacks a module-level docstring

Added a module-level docstring at the top of the file (before the import logging line) describing the module's purpose as a tree-sitter based C++ dependency analyzer, satisfying CODEWIKI-004's documentation requirement. No other code was altered.

🤖 Prompt for AI agents
In codewiki/src/be/dependency_analyzer/analyzers/cpp.py around line 1, review and complete this code-review fix: cpp.py analyzer module lacks a module-level docstring.
What the draft fix changed: Added a module-level docstring at the top of the file (before the `import logging` line) describing the module's purpose as a tree-sitter based C++ dependency analyzer, satisfying CODEWIKI-004's documentation requirement. No other code was altered.
Verify the change is correct and complete; do not refactor unrelated code.

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

Comment on lines 51 to 57

def _get_component_id(self, name: str) -> str:
module_path = self._get_module_path()
return f"{module_path}.{name}" if module_path else name
return f"{module_path}::{name}" if module_path else name

def _analyze(self):
language_capsule = tree_sitter_c_sharp.language()

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.

🦩 🔴 csharp.py component IDs use '.' rather than the mandated '::' separator

Changed _get_component_id in TreeSitterCSharpAnalyzer (line ~39) to join module_path and name with :: instead of ., aligning with the CODEWIKI-005-2 FQDN convention. This is a mechanical fix matching the finding's evidence, but confidence is not higher because downstream consumers/tests that may expect dot-separated IDs (e.g. cross-file resolution logic or snapshot tests elsewhere in the codebase) were not visible/verifiable from this single file, so consistency across the broader system cannot be fully confirmed here.

🤖 Prompt for AI agents
In codewiki/src/be/dependency_analyzer/analyzers/csharp.py around line 39, review and complete this code-review fix: csharp.py component IDs use '.' rather than the mandated '::' separator.
What the draft fix changed: Changed `_get_component_id` in `TreeSitterCSharpAnalyzer` (line ~39) to join `module_path` and `name` with `::` instead of `.`, aligning with the CODEWIKI-005-2 FQDN convention. This is a mechanical fix matching the finding's evidence, but confidence is not higher because downstream consumers/tests that may expect dot-separated IDs (e.g. cross-file resolution logic or snapshot tests elsewhere in the codebase) were not visible/verifiable from this single file, so consistency across the broader system cannot be fully confirmed here.
Verify the change is correct and complete; do not refactor unrelated code.

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

top-level components (classes, interfaces, structs, enums, records, delegates)
and derive call relationships between them for dependency analysis.
"""
import logging

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.

🦩 🟠 csharp.py analyzer module lacks a module-level docstring

Added a module-level docstring at the top of the file (before the imports) describing the C# analyzer's role, satisfying CODEWIKI-004's documentation requirement. This is a straightforward, low-risk addition with no behavioral impact.

🤖 Prompt for AI agents
In codewiki/src/be/dependency_analyzer/analyzers/csharp.py around line 1, review and complete this code-review fix: csharp.py analyzer module lacks a module-level docstring.
What the draft fix changed: Added a module-level docstring at the top of the file (before the imports) describing the C# analyzer's role, satisfying CODEWIKI-004's documentation requirement. This is a straightforward, low-risk addition with no behavioral impact.
Verify the change is correct and complete; do not refactor unrelated code.

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

@@ -148,18 +148,18 @@ def _get_relative_path(self) -> str:
return str(self.file_path)

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.

🦩 🔴 PHP analyzer also constructs component IDs with dot separators, not the required '::' FQDN format

Changed _get_component_id in TreeSitterPHPAnalyzer (php.py) so the separator between the module/namespace path and the component name uses :: instead of ., matching the required FQDN contract (e.g. ns_prefix::name, ns_prefix::parent_class.name, module_path::name, module_path::parent_class.name). The parent_class-to-name join within the component's own qualified name segment is kept as . (consistent with how method names are already built as ClassName.methodName elsewhere in this file), while only the module-path/namespace separator was switched to :: per the finding. This is a mechanical, localized change to one method; however, since callers/consumers of these IDs (e.g. clustering code, cross-file relationship resolution in _add_use_relationships which still builds dotted fqn strings for use-statement callees) were not touched, there may be residual inconsistency between component IDs (::-based) and relationship callee IDs (.-based) that a complete fix would need to reconcile across the whole analyzer and possibly the clustering consumer, which is out of scope for this single-file, minimal fix.

🤖 Prompt for AI agents
In codewiki/src/be/dependency_analyzer/analyzers/php.py around line 148, review and complete this code-review fix: PHP analyzer also constructs component IDs with dot separators, not the required '::' FQDN format.
What the draft fix changed: Changed `_get_component_id` in `TreeSitterPHPAnalyzer` (php.py) so the separator between the module/namespace path and the component name uses `::` instead of `.`, matching the required FQDN contract (e.g. `ns_prefix::name`, `ns_prefix::parent_class.name`, `module_path::name`, `module_path::parent_class.name`). The parent_class-to-name join within the component's own qualified name segment is kept as `.` (consistent with how method names are already built as `ClassName.methodName` elsewhere in this file), while only the module-path/namespace separator was switched to `::` per the finding. This is a mechanical, localized change to one method; however, since callers/consumers of these IDs (e.g. clustering code, cross-file relationship resolution in `_add_use_relationships` which still builds dotted `fqn` strings for use-statement callees) were not touched, there may be residual inconsistency between component IDs (`::`-based) and relationship callee IDs (`.`-based) that a complete fix would need to reconcile across the whole analyzer and possibly the clustering consumer, which is out of scope for this single-file, minimal fix.
Verify the change is correct and complete; do not refactor unrelated code.

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

@flamingo flamingo Bot changed the title fix(CODEWIKI-005-2): 16 review findings across 7 files fix(CODEWIKI-005-2): CU-86akbhh7w 16 review findings across 7 files Sep 3, 2026
@michaelassraf

Copy link
Copy Markdown

Blocking: this produces double-:: FQDNs and silently degrades clustering.

The PR changes _get_component_id from . to :: in six analyzers and changes ast_parser.py to build fqdn = f"{namespace}::{original_id}". Since original_id now already contains ::, every component ends up with two separators:

openframe-oss-tenant::src.services.auth::AuthService

extract_module_hint/extract_package_hint (called at cluster_modules.py:101-102, which builds the component descriptions fed into the clustering LLM prompt) both do fqdn.split('::')[0]. Running them against real FQDNs:

FQDN form module hint package hint
today's main auth service
with this PR openframe-oss-tenant service
with this PR + #45 openframe-oss-tenant core

Every component collapses to the same hint — the repository name. That is a silent documentation-quality regression, not a crash, so it will not show up as a failed pipeline run.

Second effect, ast_parser.py:279:

if "." in original_id:
    module_path = ".".join(original_id.split(".")[:-1])
    self.modules.add(f"{namespace}.{module_path}")
  • before: src.services.auth.AuthService → module ns.src.services.auth
  • after: src.services.auth::AuthService → module ns.src.services

One level of module granularity disappears. Note this line still uses . while the component ids now use ::, so the two are inconsistent.

Third: this changes the key format of the persisted dependency graph, so every cached graph is invalidated.

If :: is the intended canonical separator, it needs to be one coherent change: ast_parser must not re-prefix with :: when the id already has one, cluster_modules' hint extraction must parse the new shape, and line 279 must use the same separator. Worth a dedicated PR with multi-platform-hub's test_id_mapping.py (which asserts on extract_module_hint) run against it.

Bring the branch up to date with main (PRs #48, #49, #52, #53, #54, #55).

Conflicts were competing module docstrings in cpp.py, csharp.py and
javascript.py, added by both this branch and #55. Resolved in favour of the
wording already on main; this branch's _get_component_id changes are
unaffected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
michaelassraf added a commit that referenced this pull request Sep 8, 2026
…or change

- generate_sub_module_documentations.py: the branch's
  normalize_component_ids_by_lookup(specs, components, id_to_fqdn) call was a
  three-argument call against a two-argument function, unpacked as a 3-tuple
  from a dict return. #47 has since landed the correct dedupe via
  normalize_component_id_list, so this resolves in favour of main.

- analyzers/c.py: reverted the '.' -> '::' component-id change. Changing the
  separator for C alone is inconsistent with the other seven analyzers, and the
  FQDN format question belongs with #34/#45 where it can be made coherent
  end-to-end. The module docstring is kept.

What remains is worth having:
- deps.py: dict[str, any] -> dict[str, Any]. 'any' is the builtin function, not
  a type, so the old annotation was meaningless.
- agent_orchestrator.__init__: drops a local logger that shadowed the
  module-level one (same logging.getLogger(__name__) object, so no behaviour
  change).
- typescript.py _get_parent_context: returns 'unknown' instead of falling off
  the end as None, honouring its '-> str' annotation. Its one caller stores the
  value and nothing reads it, so this cannot regress.
- The tool description now asks for integer IDs, matching what
  format_potential_core_components actually puts in the prompt.
- Module docstrings throughout, plus from_web_job added to the config.py summary.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Switching the analyzers from '.' to '::' is right - it gives the module path and
the component name a real boundary - but the branch changed only half the
pipeline. ast_parser also joined the namespace with '::', so every component came
out with TWO separators:

    openframe-oss-tenant::src.services.auth::AuthService

Everything downstream that reads an FQDN splits on the first '::' and so saw the
repository name and nothing else. Measured against the real hint functions, which
build the component descriptions in the clustering prompt, every component in the
repository collapsed to the same module hint.

Fixed by making one separator authoritative - '<namespace>.<module.path>::<Name>',
exactly one '::':

- ast_parser: namespace joins revert to '.', at both construction sites.
- ast_parser: namespace extraction in _resolve_cross_namespace_dependencies
  reverts to split('.')[0]; splitting on '::' returned the whole module path,
  so cross-namespace edges compared paths instead of repositories.
- ast_parser: module registration takes original_id.split('::')[0] rather than
  dropping the last dot-segment. The old block silently lost one level of module
  depth ('...src.services' where main gives '...src.services.auth').
- analyzers/c.py and analyzers/typescript.py were the two the branch missed;
  all eight now agree.

Verified: FQDNs carry exactly one '::', the namespace is still recoverable,
cross-namespace comparison still distinguishes repositories, module granularity
matches main, and the prompt hints improve from '(openframe-oss-tenant, service)'
- identical for every component - to '(openframe-oss-tenant.src.services.auth,
service)'.

Note for operators: this changes the key format of the persisted dependency
graph, so any graph cached from a previous run is stale and should be discarded.
CI runs build it fresh.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@michaelassraf
michaelassraf marked this pull request as ready for review September 8, 2026 03:08
@michaelassraf
michaelassraf merged commit 4924484 into main Sep 8, 2026
michaelassraf added a commit that referenced this pull request Sep 8, 2026
#34 landed the coherent '::' format: '<namespace>.<module.path>::<Name>', with
the namespace still joined by '.' so each FQDN carries exactly one separator.
This branch's verify_fqdn_implementation.py asserted the opposite - that
ast_parser builds f"{namespace}::{original_id}" - which is precisely the
double-separator bug #34 fixed, so the script failed against its own branch.
Restored to expect the '.' join; the script now passes.

python.py's separator change is already on main via #34, so the conflicting
hunk (competing wording on one debug log line) resolves in favour of main.

What remains is this branch's real contribution: extract_module_hint and
extract_package_hint now parse only the module portion before '::' and warn on
an FQDN that lacks one, instead of scanning the whole string. On well-formed
FQDNs the output is identical to main's; a malformed id degrades to
unknown/core with a warning rather than silently yielding a wrong hint.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@michaelassraf
michaelassraf deleted the ai-fix/codewiki-005-2-f0f98f64-bef4f5a8 branch September 8, 2026 03:11
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.

1 participant