Skip to content

Repository architecture: consolidate Python packages under a unified src/cacheroute namespace #157

Description

@rickisba

Context

CacheRoute currently discovers Python packages directly from the repository root ([tool.setuptools.packages.find] where = ["."]). This makes it easy for cross-component features to add new functional top-level directories such as cacheroute_compat/ and the proposed cacheroute_observability/. Each directory can be reasonable in isolation, but continued growth will make the repository root increasingly flat, fragmented, and difficult to navigate.

This also creates architectural ambiguity:

  • there is no single canonical Python namespace for CacheRoute;
  • dependency-light shared code is separated by new root package names rather than by a planned package hierarchy;
  • imports, CLI/module entry points, tests, Docker commands, scripts, monkeypatch targets, and documentation links can silently break when directories are moved;
  • root README and component READMEs can drift away from the actual repository layout;
  • future work may continue introducing cacheroute_<feature>/ directories without an architectural review.

This issue establishes a repository-level source layout and migration plan before continuing the runtime integration phases of #141.

Related work:

Goal

Adopt a clear, scalable Python source layout centered on one canonical namespace:

src/
└── cacheroute/
    ├── __init__.py
    ├── compat/
    ├── observability/
    ├── core/
    ├── kdn/
    ├── scheduler/
    ├── proxy/
    ├── instance/
    └── ... existing domains after audit

The repository root should contain only a small, reviewed set of project categories such as source, tests, documentation, scripts, deployment/configuration assets, examples, and project metadata. New functional Python packages must not be added directly at the root.

Architectural requirements

1. Inventory the current repository before moving files

Produce a complete inventory of all current top-level directories and classify each as one of:

  • Python runtime package;
  • test suite;
  • documentation;
  • scripts/tooling;
  • deployment/configuration;
  • examples/assets;
  • generated or temporary content.

For every Python runtime package, identify:

  • its public import paths;
  • imports from other packages;
  • imports into it;
  • application entry points;
  • python -m usage;
  • Uvicorn/FastAPI module strings;
  • subprocess module invocation;
  • monkeypatch/mock target strings;
  • serialization or plugin strings containing module paths;
  • Dockerfile, Compose, shell, CI, and documentation references;
  • test collection and fixture dependencies.

Do not move a package until its reference inventory is recorded.

2. Define the canonical namespace and dependency direction

Use src/cacheroute/ as the canonical Python namespace.

src/cacheroute/__init__.py must remain empty or extremely lightweight. Importing cacheroute must not eagerly import FastAPI, Redis, NumPy, Torch, vLLM, LMCache, Scheduler, Proxy, Instance, KDN runtime services, or application configuration.

Dependency-light packages such as compatibility and observability must remain independently importable:

from cacheroute.compat import ...
from cacheroute.observability import ...

They must not be placed under a component package if doing so reverses dependencies for Scheduler, Proxy, KDN, Gateway, or Instance.

Define and document allowed dependency directions between at least:

  • compatibility primitives;
  • observability contracts;
  • shared core/domain models;
  • KDN contracts/domain/Gateway;
  • Scheduler;
  • Proxy;
  • Instance;
  • storage and deployment adapters.

Add an import-cycle or import-isolation check where practical.

3. Update packaging to a real src layout

Update pyproject.toml so setuptools discovers packages from src, for example through the appropriate equivalents of:

[tool.setuptools]
package-dir = {"" = "src"}

[tool.setuptools.packages.find]
where = ["src"]

Verify all required package data and editable installs still work.

Test both:

  • python3 -m pip install -e .;
  • building and installing a wheel in a clean environment.

The installed package must not depend on the repository root being on sys.path.

4. Migrate in reviewable phases

This issue may be completed by multiple PRs, but the final state must satisfy all acceptance criteria.

Recommended sequence:

Phase A — establish the namespace and migrate dependency-light packages

  • create src/cacheroute/;
  • migrate cacheroute_compat/ to src/cacheroute/compat/;
  • migrate the PR docs: research unified v1 LMCache observability for #141 #156 implementation to src/cacheroute/observability/ after its contract issues are corrected;
  • update core/runtime_compat.py and all other imports to use the canonical namespace;
  • update tests, demos, scripts, type references, and documentation;
  • decide and document whether old import paths receive temporary compatibility shims.

Phase B — migrate shared and KDN packages

  • migrate core/ into the planned namespace without preserving eager import side effects;
  • migrate kdn_server/ to the agreed canonical package path, preferably cacheroute.kdn, while preserving its existing HTTP/CLI operational behavior;
  • update all KDN contracts, Gateway, Domain, script, test, and deployment references;
  • preserve existing README content and add only accurate structural updates.

Phase C — migrate application components

  • migrate Scheduler, Proxy, Instance, storage, component, and other audited runtime packages in dependency-safe groups;
  • preserve executable commands, service startup behavior, Docker/Compose paths, and test behavior;
  • remove obsolete root runtime-package directories only after all references have moved.

Do not perform an unreviewable blind git mv of the whole repository in one commit.

5. Import compatibility and deprecation policy

Before changing an import path, search the entire repository for:

  • normal imports;
  • importlib and dynamic imports;
  • string module references;
  • Uvicorn application strings;
  • pytest monkeypatch paths;
  • shell and Docker commands;
  • notebooks and examples;
  • Markdown code examples.

For old paths such as:

cacheroute_compat.runtime
cacheroute_observability
core.runtime_compat
kdn_server.contracts
kdn_server.domain
kdn_server.gateway

choose one explicit policy:

  1. temporary compatibility re-export with a documented removal milestone; or
  2. intentional breaking migration before the next release, with every in-repository consumer updated.

Do not leave two permanent implementations. Compatibility layers, when used, must be thin forwarding modules with tests proving that old and new imports resolve to the same objects.

The final issue state must not retain functional root package directories merely to avoid updating references.

6. Preserve runtime and command entry points

Audit and update all executable references, including but not limited to:

  • python3 -m ... commands;
  • direct script execution;
  • Uvicorn/FastAPI module:app strings;
  • console entry points in package metadata;
  • Docker CMD/ENTRYPOINT;
  • Compose commands and mounted paths;
  • shell scripts;
  • CI commands;
  • subprocess calls in tests;
  • developer documentation.

For each changed entry point, provide a before/after mapping and a smoke test.

No service should require ad-hoc sys.path insertion after the migration, except narrowly justified standalone scripts that are not installed entry points.

7. Preserve method, class, and module references

Moving files must not silently break:

  • public re-exports and __all__;
  • type annotations using qualified names;
  • Pydantic discriminators or serialized type names;
  • pickled objects, if any are in scope;
  • decorators or registries keyed by module/function name;
  • monkeypatch targets;
  • logging names relied upon by tests or operations;
  • plugin/adapter lookup strings;
  • relative imports inside moved packages.

Add targeted tests for any string-based method/module references discovered during the audit.

8. README and Markdown-link migration

Do not rewrite or delete existing README introductions merely because directories move.

Apply progressive disclosure:

  • root README.md: project-level overview only;
  • src/cacheroute/README.md or maintained architecture document: canonical package map and dependency rules;
  • component READMEs: component purpose, directory map, entry points, and links to deeper contracts/tests;
  • detailed protocol and workflow documentation remains in nested READMEs or doc/.

When files move:

  • update every relative Markdown link;
  • update source-file links and code examples;
  • update directory trees;
  • update commands that contain old module paths;
  • ensure every nested README links back to its parent architecture document;
  • do not introduce a second documentation root (docs/); keep the existing doc/ convention.

Add an automated repository-wide Markdown link check that handles local relative paths and anchors where practical. At minimum, all local file links must resolve.

9. Root-directory governance

Document a root-directory allowlist or equivalent architectural rule.

Required rule:

No new functional top-level directory may be added without a dedicated architecture Issue. New Python capabilities must first be placed under src/cacheroute/<domain>/ or an existing component hierarchy. Cross-component shared code must use a dependency-light, side-effect-free package under the cacheroute namespace.

Add this rule to the repository's contributor/agent guidance so future implementation sessions apply it automatically.

The root README must not be expanded with detailed package internals; it should link inward.

10. Coordination with #141 and PR #156

Until this issue's Phase A layout is merged:

Resume #141 runtime integration only after the canonical package location and import policy are merged and verified.

Required validation

The implementing PRs must report exact results for the applicable commands.

At minimum:

python3 -m pip install -e .
python3 -m compileall -q src test scripts
python3 -m pytest -q test/observability
python3 -m pytest -q test/kdn
python3 -m pytest -q test/test_runtime_compat.py
python3 -m pytest -q \
  test/test_instance_capability.py \
  test/test_instance_capability_registration.py
git diff --check

Build/install validation:

python3 -m build
python3 -m venv /tmp/cacheroute-wheel-test
/tmp/cacheroute-wheel-test/bin/python -m pip install --upgrade pip
/tmp/cacheroute-wheel-test/bin/python -m pip install dist/*.whl
/tmp/cacheroute-wheel-test/bin/python - <<'PY'
import cacheroute
import cacheroute.compat
import cacheroute.observability
print("installed namespace imports: passed")
PY

Add fresh-process import-isolation checks proving that importing dependency-light packages does not load heavy application modules.

Add a repository-wide stale-reference check covering old package paths in:

  • Python;
  • shell scripts;
  • Docker/Compose files;
  • TOML/YAML/JSON configuration;
  • Markdown and notebooks.

Any remaining old reference must be either:

  • an intentional compatibility test;
  • a documented deprecation shim;
  • historical text explicitly marked as historical.

Acceptance criteria

  • src/cacheroute/ is the canonical Python source namespace.
  • setuptools package discovery uses src, not the repository root.
  • cacheroute.compat replaces the permanent root cacheroute_compat/ implementation.
  • Issue v0.1.10-4: Add Unified v1 LMCache Gateway, Tier, Adapter, and Queue Observability #141 observability code lives at cacheroute.observability, not a permanent root cacheroute_observability/ package.
  • cacheroute/__init__.py has no heavy imports or application side effects.
  • all affected imports, dynamic references, entry points, scripts, Docker/Compose commands, and tests are updated.
  • any temporary old import path is a tested thin shim with an explicit removal plan.
  • component behavior, contract wire values, Runtime Profiles, Gateway outcomes, and service semantics do not change because of the move.
  • root README remains high-level and existing README introductions are preserved.
  • directory trees, source links, commands, and relative README links match the final layout.
  • automated local Markdown-link validation passes.
  • editable install and clean wheel install both pass without repository-root path assumptions.
  • relevant CPU-only regression suites pass.
  • root-directory governance is added to contributor/agent guidance.
  • obsolete functional root package directories are removed in the final state.
  • v0.1.10-4: Add Unified v1 LMCache Gateway, Tier, Adapter, and Queue Observability #141 runtime integration remains paused until the structural foundation is merged.

Non-goals

  • changing CacheRoute routing, scheduling, queue, cache, or fallback behavior;
  • changing v1/Legacy contract wire values;
  • implementing new LMCache/vLLM production I/O;
  • adding a tracing backend;
  • rewriting the project homepage;
  • deleting existing operational README content;
  • combining unrelated feature work into the structure migration.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions