# 10. Universal package mapping via project-relative path

**Date:** 2026-07-03

**Status:** Accepted

## Context

Each detected behavioral convention needs a "package" or "module" label so the LLM knows where to place generated code. Options:

- **No package info**: LLM guesses wrong directory, generates code at project root.
- **Per-language directory lookup**: Hardcode `kotlin`/`java`/`python` source root names. Breeds per-language branches — violates the zero-adapters constraint.
- **Full file path**: Too verbose, exposes absolute system paths (/home/user/project/...).
- **Project-relative path**: Pure path arithmetic, no language assumptions.

## Decision

Derive the package from the file's directory relative to the project root:

```python
def _file_to_package(fp, project_root):
    rel = os.path.relpath(os.path.dirname(fp), project_root)
    if rel == ".":
        return ""  # file at project root
    return rel
```

No source root markers. No per-language directory names. Just `relpath` from the root the user passed to `analyze_directory`.

Examples:
```
/project/src/main/kotlin/org/app/User.kt  →  src/main/kotlin/org/app
/project/mypackage/module.py               →  mypackage
/project/lib/core/helper.rb                →  lib/core
/project/src/main.rs                        →  src
/flat/project/file.py                       →  flat
```

The project root is the directory passed to `analyze_directory(...)` and threaded down through `analyze_clusters` → `_top_packages`.

## Consequences

**Positive:**
- Zero per-language branches. Works identically for all 10 languages.
- No configuration or convention list to maintain.
- LLM sees the exact directory structure it should mirror in generated code.

**Negative:**
- `relpath` assumes the project root is the scan root. Scanning a subdirectory gives partial paths (still correct, but missing context).
- Files at the root of deeply nested projects get empty package strings. Mitigation: users should scan from the project root.

## Alternatives Considered

- **Per-language source root list (reverted)**: Hardcoded `kotlin`/`java`/`python` directory names. Brittle, violated zero-adapters constraint. Reverted to `feature/kotlin-specific-extras`.
- **Source root markers (`src`/`lib`/`pkg`/`app`)**: Broader than per-language but still assumes project layout conventions. Broke for flat repos, non-standard layouts.
- **No package mapping**: Simpler but useless — LLM can't locate generated code. The package label is essential for file placement.
