Skip to content

Commit 1096e2e

Browse files
JuliaEdomclaude
andcommitted
refactor(namespace)!: runtime imports as agentflow_runtime; deprecated one-file src shim (audit F-09, P2-6 phases 1-2)
The runtime moves to the src-layout src/agentflow_runtime/ and installs/imports as agentflow_runtime (version 2.1.0). Wheels ship exactly two top-level members: the package and the deprecated src shim (packaging/src_shim) that aliases every src.X import onto the same module object as agentflow_runtime.X with a DeprecationWarning (AGENTFLOW_SRC_SHIM_SILENT=1 mutes it; removal lands in the next major). Full first-party cutover: source, tests, scripts, CI workflows, Makefile, Docker/compose files, helm templates, the Flink image layout (PYTHONPATH=/opt/agentflow/src), devcontainer, HF-Space image, demo notebook and living docs. New gates: tests/unit/test_namespace_policy.py (container layout + no first-party src.* imports + packaging maps) and scripts/wheel_smoke.py (wheel top-level policy + install smoke outside the checkout), wired into the python-compat CI job and pinned by the quickstart install contract. The byte-pinned golden-soak pack keeps its historical src.* imports (recorded exception). Verified on this host: ruff check+format clean; mypy src/ clean (152 files); sharded unit/property/sdk suite 2472/2472 (two path-pinned tests fixed and re-run green); integration outbox/alert-dedup/exceptions-inbox 34/34; generate_contracts --check clean; wheel smoke incl. shim warning/identity/silence PASS. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent 412b633 commit 1096e2e

396 files changed

Lines changed: 3765 additions & 2938 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.devcontainer/devcontainer.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {}
1616
},
1717
"postCreateCommand": "pip install -e '.[dev]'",
18-
"postStartCommand": "bash -lc \"pip install -e ./sdk && cd sdk-ts && npm install && cd .. && if [ ! -f agentflow_demo.duckdb ]; then python -m src.processing.local_pipeline --burst 500; fi\"",
18+
"postStartCommand": "bash -lc \"pip install -e ./sdk && cd sdk-ts && npm install && cd .. && if [ ! -f agentflow_demo.duckdb ]; then python -m agentflow_runtime.processing.local_pipeline --burst 500; fi\"",
1919
"forwardPorts": [8000, 8080, 8081, 8474, 9090, 3000, 9001, 16686],
2020
"portsAttributes": {
2121
"8000": {

‎.github/ISSUE_TEMPLATE/bug_report.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ body:
3838
label: Affected surface
3939
multiple: true
4040
options:
41-
- API (`src/serving/api/`)
41+
- API (`src/agentflow_runtime/serving/api/`)
4242
- Python SDK (`sdk/agentflow/`)
4343
- TypeScript SDK (`sdk-ts/`)
4444
- Helm chart (`helm/agentflow/`)

‎.github/dependabot.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ updates:
7575
# apache-flink majors/minors stay individual PRs by default (no group),
7676
# matching the deliberate-bump policy for the Flink line.
7777
- package-ecosystem: pip
78-
directory: "/src/processing/flink_jobs"
78+
directory: "/src/agentflow_runtime/processing/flink_jobs"
7979
schedule:
8080
interval: weekly
8181
day: monday
@@ -149,7 +149,7 @@ updates:
149149
- package-ecosystem: docker
150150
directories:
151151
- "/"
152-
- "/src/processing/flink_jobs"
152+
- "/src/agentflow_runtime/processing/flink_jobs"
153153
- "/docker/kafka-connect"
154154
- "/.devcontainer"
155155
schedule:

‎.github/workflows/backup.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ jobs:
3232
3333
import duckdb
3434
35-
from src.serving.backends.duckdb_backend import DuckDBBackend
35+
from agentflow_runtime.serving.backends.duckdb_backend import DuckDBBackend
3636
3737
pipeline_db = Path("agentflow_demo.duckdb")
3838
usage_db = Path("agentflow_api.duckdb")

‎.github/workflows/ci.yml‎

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,19 +87,44 @@ jobs:
8787
run: |
8888
uv run python -m build --wheel --no-isolation
8989
uv run python -m build --wheel --no-isolation --outdir dist sdk
90+
- name: Wheel top-level namespace policy (audit F-09)
91+
# The runtime wheel must ship exactly agentflow_runtime + the one-file
92+
# deprecated src shim; any other top-level entry is an undeclared
93+
# package leaking into the distribution.
94+
run: uv run python scripts/wheel_smoke.py 'dist/agentflow_runtime-*.whl'
9095
- name: Install production dependencies and wheel in a clean environment
9196
run: |
9297
python -m venv /tmp/agentflow-clean
9398
/tmp/agentflow-clean/bin/pip install --quiet --require-hashes -r requirements-docker.lock
9499
/tmp/agentflow-clean/bin/pip install --quiet --no-deps dist/agentflow_runtime-*.whl
95100
/tmp/agentflow-clean/bin/pip install --quiet --no-deps dist/agentflow_client-*.whl
96101
/tmp/agentflow-clean/bin/pip check
97-
- name: Smoke quickstart and materializer imports
98-
# Run outside the checkout so `src.*` must come from the installed
99-
# runtime wheel rather than the repository working tree on sys.path.
102+
- name: Smoke quickstart, materializer and deprecated-shim imports
103+
# Run outside the checkout so the runtime must come from the installed
104+
# wheel rather than the repository working tree on sys.path. The src.*
105+
# surface must keep working through the wheel's deprecated shim for
106+
# one deprecation window (removed in the next major release).
100107
working-directory: /tmp
101108
run: |
102-
/tmp/agentflow-clean/bin/python -c "from agentflow.client import AgentFlowClient; from src.serving.api.main import app; from src.processing.local_pipeline import main; from src.processing.lake_consumer import ValidatedLakeConsumer; assert AgentFlowClient and app and main and ValidatedLakeConsumer"
109+
/tmp/agentflow-clean/bin/python - <<'PY'
110+
import warnings
111+
112+
from agentflow.client import AgentFlowClient
113+
from agentflow_runtime.processing.lake_consumer import ValidatedLakeConsumer
114+
from agentflow_runtime.processing.local_pipeline import main
115+
from agentflow_runtime.serving.api.main import app
116+
117+
assert AgentFlowClient and app and main and ValidatedLakeConsumer
118+
119+
with warnings.catch_warnings(record=True) as caught:
120+
warnings.simplefilter("always")
121+
import src.serving.api.main as shim_main
122+
123+
assert any(
124+
issubclass(w.category, DeprecationWarning) for w in caught
125+
), "src shim import did not raise DeprecationWarning"
126+
assert shim_main.app is app, "src shim aliased a different module object"
127+
PY
103128
104129
local-duckdb-smoke:
105130
runs-on: ubuntu-latest
@@ -231,25 +256,25 @@ jobs:
231256
# --cov-branch turns the floor into a combined line+branch metric — local baseline
232257
# 2026-05-25 is 62% (7716 lines / 2010 branches measured on HEAD `22b1be9`), so the
233258
# 60% gate stays passing with a 2pp cushion. Raise the gate once that cushion grows.
234-
python -m pytest tests/unit/ tests/property/ -v --tb=short --cov=src --cov=sdk --cov-branch --cov-report=xml --cov-report=term-missing --cov-fail-under=60
259+
python -m pytest tests/unit/ tests/property/ -v --tb=short --cov=src/agentflow_runtime --cov=sdk --cov-branch --cov-report=xml --cov-report=term-missing --cov-fail-under=60
235260
- name: Enforce changed-code coverage
236261
run: diff-cover coverage.xml --compare-branch=origin/main --fail-under=80
237262
- name: Run quality validators coverage gate
238263
run: |
239-
python -m pytest tests/unit/test_validators.py -v --tb=short --cov=src.quality.validators --cov-report=term-missing --cov-fail-under=90
264+
python -m pytest tests/unit/test_validators.py -v --tb=short --cov=agentflow_runtime.quality.validators --cov-report=term-missing --cov-fail-under=90
240265
- name: Run freshness monitor coverage gate
241266
run: |
242-
python -m pytest tests/unit/test_freshness_monitor.py -v --tb=short --cov=src.quality.monitors.freshness_monitor --cov-report=term-missing --cov-fail-under=90
267+
python -m pytest tests/unit/test_freshness_monitor.py -v --tb=short --cov=agentflow_runtime.quality.monitors.freshness_monitor --cov-report=term-missing --cov-fail-under=90
243268
- name: Run event producer coverage gate
244269
run: |
245-
python -m pytest tests/unit/test_event_producer.py -v --tb=short --cov=src.ingestion.producers.event_producer --cov-report=term-missing --cov-fail-under=90
270+
python -m pytest tests/unit/test_event_producer.py -v --tb=short --cov=agentflow_runtime.ingestion.producers.event_producer --cov-report=term-missing --cov-fail-under=90
246271
- name: Run SQL guard coverage gate
247272
run: |
248273
# Security-critical NL->SQL guard: validate_nl_sql (SELECT-only, no DML,
249274
# tenant table allow-list, recursive-CTE shadow reject). test_sql_guard
250275
# plus test_sql_guard_mutation give full module coverage (100% local);
251276
# the 90% gate keeps a 10pp regression cushion.
252-
python -m pytest tests/unit/test_sql_guard.py tests/unit/test_sql_guard_mutation.py -v --tb=short --cov=src.serving.semantic_layer.sql_guard --cov-report=term-missing --cov-fail-under=90
277+
python -m pytest tests/unit/test_sql_guard.py tests/unit/test_sql_guard_mutation.py -v --tb=short --cov=agentflow_runtime.serving.semantic_layer.sql_guard --cov-report=term-missing --cov-fail-under=90
253278
- name: Run rate limiter coverage gate
254279
run: |
255280
# Security-critical sliding-window rate limiter (Redis + in-memory

‎.github/workflows/load-test.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ jobs:
5252
set -euo pipefail
5353
mkdir -p .artifacts/load
5454
python tests/load/run_load_test.py --duckdb-path "$DUCKDB_PATH" --seed-data --seed-only
55-
python -m uvicorn src.serving.api.main:app --host 127.0.0.1 --port 8011 > .artifacts/load/api.log 2>&1 &
55+
python -m uvicorn agentflow_runtime.serving.api.main:app --host 127.0.0.1 --port 8011 > .artifacts/load/api.log 2>&1 &
5656
api_pid=$!
5757
trap 'kill "$api_pid"' EXIT
5858
python scripts/wait_for_services.py --url http://127.0.0.1:8011 --timeout 120

‎.github/workflows/perf-regression.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242
mkdir -p .artifacts/perf-smoke docs/perf
4343
docker compose up -d --wait redis
4444
python tests/load/run_load_test.py --duckdb-path "$DUCKDB_PATH" --seed-data --seed-only
45-
python -m uvicorn src.serving.api.main:app --host 127.0.0.1 --port 8012 > .artifacts/perf-smoke/api.log 2>&1 &
45+
python -m uvicorn agentflow_runtime.serving.api.main:app --host 127.0.0.1 --port 8012 > .artifacts/perf-smoke/api.log 2>&1 &
4646
api_pid=$!
4747
trap 'kill "$api_pid" 2>/dev/null || true; docker compose stop redis >/dev/null 2>&1 || true' EXIT
4848
python scripts/wait_for_services.py --url http://127.0.0.1:8012 --timeout 120

‎.github/workflows/security.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ jobs:
176176
f"- Extra `[{extra_name}]` (root `pyproject.toml`): resolved install ({extra_count} packages)\n"
177177
)
178178
handle.write(
179-
f"- Flink runtime (`src/processing/flink_jobs/requirements.txt`): resolved install ({flink_count} packages)\n"
179+
f"- Flink runtime (`src/agentflow_runtime/processing/flink_jobs/requirements.txt`): resolved install ({flink_count} packages)\n"
180180
)
181181
handle.write("- Exclusions: dev/CI/test extras, local tooling, and unrelated Docker image packages\n")
182182
PY
@@ -219,7 +219,7 @@ jobs:
219219
# newest PyPI release (checked 2026-07-20) and itself caps
220220
# pyarrow<21; beam accepts pyarrow<24 only from 2.75.0, which no
221221
# released apache-flink allows. Dependabot watches the Flink
222-
# manifest (src/processing/flink_jobs), so the next apache-flink
222+
# manifest (src/agentflow_runtime/processing/flink_jobs), so the next apache-flink
223223
# release opens a PR — re-check this ignore there. Remove when the
224224
# resolved flink-runtime bucket installs pyarrow>=23.0.1.
225225
# Do NOT retry "uninstall unused pyarrow from the image" — probed

‎Dockerfile.api‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ COPY LICENSE /build/LICENSE
1111
COPY CHANGELOG.md /build/CHANGELOG.md
1212
COPY requirements.txt /build/requirements.txt
1313
COPY src /build/src
14+
COPY packaging /build/packaging
1415

1516
RUN pip install --no-cache-dir --upgrade pip build hatchling \
1617
&& python -m build --wheel --outdir /tmp/dist
@@ -89,4 +90,4 @@ EXPOSE 8000
8990
# image was the one place still asking the question that cannot get a no.
9091
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 CMD python -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health/ready', timeout=3).read()" || exit 1
9192

92-
CMD ["uvicorn", "src.serving.api.main:app", "--host", "0.0.0.0", "--port", "8000"]
93+
CMD ["uvicorn", "agentflow_runtime.serving.api.main:app", "--host", "0.0.0.0", "--port", "8000"]

‎Makefile‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,11 @@ wait-healthy:
3333
@echo "Service UIs: http://localhost:8081 (Flink), http://localhost:9001 (MinIO console)"
3434

3535
produce:
36-
python -m src.ingestion.producers.event_producer
36+
python -m agentflow_runtime.ingestion.producers.event_producer
3737

3838
api:
3939
docker compose up -d redis
40-
DUCKDB_PATH=agentflow_demo.duckdb uvicorn src.serving.api.main:app --host 0.0.0.0 --port 8000 --reload
40+
DUCKDB_PATH=agentflow_demo.duckdb uvicorn agentflow_runtime.serving.api.main:app --host 0.0.0.0 --port 8000 --reload
4141

4242
tools:
4343
python scripts/export_openapi.py
@@ -56,10 +56,10 @@ demo:
5656
@echo "Step 0.5: Provisioning the serving store (schema + demo rows)..."
5757
@echo " The API does not create or seed a store on boot any more (audit P0-2)."
5858
@echo " A real deployment runs this same command WITHOUT --seed, from a job."
59-
DUCKDB_PATH=agentflow_demo.duckdb python -m src.serving.provision --schema --seed
59+
DUCKDB_PATH=agentflow_demo.duckdb python -m agentflow_runtime.serving.provision --schema --seed
6060
@echo ""
6161
@echo "Step 1: Seeding 500 events through the full pipeline..."
62-
python -m src.processing.local_pipeline --burst 500
62+
python -m agentflow_runtime.processing.local_pipeline --burst 500
6363
@echo ""
6464
@echo "Step 1.5: Seeding benchmark fixture rows into agentflow_demo.duckdb..."
6565
python -c "from pathlib import Path; from scripts.run_benchmark import seed_benchmark_fixtures; seed_benchmark_fixtures(Path('agentflow_demo.duckdb'))"
@@ -69,10 +69,10 @@ demo:
6969
@echo " Try: curl http://localhost:8000/v1/metrics/revenue?window=24h"
7070
@echo " Try: curl http://localhost:8000/v1/entity/user/USR-10001"
7171
@echo " Try: curl http://localhost:8000/v1/health"
72-
AGENTFLOW_AUTH_DISABLED=true DUCKDB_PATH=agentflow_demo.duckdb uvicorn src.serving.api.main:app --host 0.0.0.0 --port 8000
72+
AGENTFLOW_AUTH_DISABLED=true DUCKDB_PATH=agentflow_demo.duckdb uvicorn agentflow_runtime.serving.api.main:app --host 0.0.0.0 --port 8000
7373

7474
pipeline:
75-
python -m src.processing.local_pipeline --eps 10
75+
python -m agentflow_runtime.processing.local_pipeline --eps 10
7676

7777
flink-local:
7878
ifeq ($(OS),Windows_NT)
@@ -93,7 +93,7 @@ test-integration:
9393
pytest tests/integration/ -v --tb=short -m integration
9494

9595
quality:
96-
python -m src.quality.validators.semantic_validator --check-all
96+
python -m agentflow_runtime.quality.validators.semantic_validator --check-all
9797

9898
# ── Load Testing ──────────────────────────────────────────────────
9999

0 commit comments

Comments
 (0)