diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 48c1412..51af55b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -3,6 +3,7 @@ # Keep release and dependency policy visibly owned by the maintainer. /.github/workflows/** @Ezio2000 /.github/dependabot.yml @Ezio2000 -/python/**/pyproject.toml @Ezio2000 -/python/uv.lock @Ezio2000 +/pyproject.toml @Ezio2000 +/packages/**/pyproject.toml @Ezio2000 +/uv.lock @Ezio2000 /scripts/** @Ezio2000 diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 4eaf005..c08fc4b 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -2,7 +2,7 @@ version: 2 updates: - package-ecosystem: uv - directory: /python + directory: / schedule: interval: weekly day: tuesday diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 55d6df6..0341e17 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,24 +30,24 @@ jobs: uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 with: enable-cache: true - cache-dependency-glob: python/uv.lock + cache-dependency-glob: uv.lock - name: Install locked dependencies - run: uv --project python sync --locked + run: uv sync --locked - name: Synchronize pinned specification - run: uv --project python run python scripts/sync_spec.py + run: uv run python scripts/sync_spec.py - name: Smoke test conformance entry point - run: uv --project python run conformance --help + run: uv run conformance --help - name: Verify coordinated release metadata - run: uv --project python run python scripts/verify_release.py + run: uv run python scripts/verify_release.py - name: Check public export documentation shell: bash run: | - uv --project python run python - <<'PY' + uv run python - <<'PY' import importlib import inspect import typing @@ -78,47 +78,47 @@ jobs: PY - name: Lint - run: uv --project python run ruff check --config python/pyproject.toml . + run: uv run ruff check --config pyproject.toml . - name: Check formatting - run: uv --project python run ruff format --check --config python/pyproject.toml . + run: uv run ruff format --check --config pyproject.toml . - name: Type-check - run: uv --project python run pyright --project python + run: uv run pyright --project . - name: Test with branch coverage env: COVERAGE_FILE: ${{ runner.temp }}/.coverage run: >- - uv --project python run pytest - -c python/pyproject.toml + uv run pytest + -c pyproject.toml -q -p no:cacheprovider --cov - --cov-config=python/pyproject.toml + --cov-config=pyproject.toml --cov-report=term-missing:skip-covered - name: Repeat timing and ownership regressions shell: bash run: | for attempt in 1 2 3; do - uv --project python run pytest \ - -c python/pyproject.toml \ + uv run pytest \ + -c pyproject.toml \ -q \ -p no:cacheprovider \ - python/kernel/tests/test_runtime.py \ - python/kernel/tests/test_diagnostics.py + packages/kernel/tests/test_runtime.py \ + packages/kernel/tests/test_diagnostics.py done - name: Build and verify the three product distributions shell: bash run: | for package in jharness-kernel jharness-toolkit jharness-providers; do - uv --project python build \ + uv build \ --package "$package" \ --out-dir "$RUNNER_TEMP/dist" done - uv --project python run python scripts/verify_wheels.py "$RUNNER_TEMP/dist" + uv run python scripts/verify_wheels.py "$RUNNER_TEMP/dist" runtime: name: Python ${{ matrix.python-version }} (${{ matrix.os }}) @@ -143,22 +143,22 @@ jobs: uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 with: enable-cache: true - cache-dependency-glob: python/uv.lock + cache-dependency-glob: uv.lock - name: Install locked dependencies - run: uv --project python sync --locked + run: uv sync --locked - name: Synchronize pinned specification - run: uv --project python run python scripts/sync_spec.py + run: uv run python scripts/sync_spec.py - name: Test runtime - run: uv --project python run pytest -c python/pyproject.toml -q -p no:cacheprovider + run: uv run pytest -c pyproject.toml -q -p no:cacheprovider - name: Run conformance CLI run: >- - uv --project python run conformance + uv run conformance .jharness-spec/conformance/cases --spec-dir .jharness-spec/contracts/v0 - name: Run benchmark - run: uv --project python run python benchmarks/runtime_smoke.py + run: uv run python benchmarks/runtime_smoke.py diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 681020f..1477603 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -50,53 +50,53 @@ jobs: uses: astral-sh/setup-uv@11f9893b081a58869d3b5fccaea48c9e9e46f990 # v8.3.2 with: enable-cache: true - cache-dependency-glob: python/uv.lock + cache-dependency-glob: uv.lock - name: Install locked dependencies if: github.event_name == 'push' - run: uv --project python sync --locked + run: uv sync --locked - name: Synchronize pinned specification if: github.event_name == 'push' - run: uv --project python run python scripts/sync_spec.py + run: uv run python scripts/sync_spec.py - name: Verify tag, coordinated versions, and changelog if: github.event_name == 'push' - run: uv --project python run python scripts/verify_release.py --tag "$RELEASE_TAG" + run: uv run python scripts/verify_release.py --tag "$RELEASE_TAG" - name: Run release quality gate if: github.event_name == 'push' shell: bash run: | - uv --project python run ruff check --config python/pyproject.toml . - uv --project python run ruff format --check --config python/pyproject.toml . - uv --project python run pyright --project python - uv --project python run pytest \ - -c python/pyproject.toml \ + uv run ruff check --config pyproject.toml . + uv run ruff format --check --config pyproject.toml . + uv run pyright --project . + uv run pytest \ + -c pyproject.toml \ -q \ -p no:cacheprovider \ --cov \ - --cov-config=python/pyproject.toml \ + --cov-config=pyproject.toml \ --cov-report=term-missing:skip-covered - uv --project python run conformance \ + uv run conformance \ .jharness-spec/conformance/cases \ --spec-dir .jharness-spec/contracts/v0 - uv --project python run python benchmarks/runtime_smoke.py + uv run python benchmarks/runtime_smoke.py - name: Build the three product distributions if: github.event_name == 'push' shell: bash run: | for package in jharness-kernel jharness-toolkit jharness-providers; do - uv --project python build --package "$package" --out-dir dist + uv build --package "$package" --out-dir dist done - name: Verify publishable artifacts if: github.event_name == 'push' shell: bash run: | - uv --project python run python scripts/verify_wheels.py dist - uv --project python run twine check dist/* + uv run python scripts/verify_wheels.py dist + uv run twine check dist/* sha256sum dist/* > dist/SHA256SUMS - name: Recover the verified artifact from the failed release diff --git a/AGENTS.md b/AGENTS.md index 4caad42..4135bc5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -42,16 +42,16 @@ complete/stream protocols. Python must be managed with `uv`; never use `pip`. ```bash -uv --project python sync --locked -uv --project python run python scripts/sync_spec.py -uv --project python run pytest -c python/pyproject.toml -q -p no:cacheprovider -uv --project python run ruff check --config python/pyproject.toml . -uv --project python run ruff format --check --config python/pyproject.toml . -uv --project python run pyright --project python -uv --project python run conformance \ +uv sync --locked +uv run python scripts/sync_spec.py +uv run pytest -c pyproject.toml -q -p no:cacheprovider +uv run ruff check --config pyproject.toml . +uv run ruff format --check --config pyproject.toml . +uv run pyright --project . +uv run conformance \ .jharness-spec/conformance/cases \ --spec-dir .jharness-spec/contracts/v0 -uv --project python run python benchmarks/runtime_smoke.py +uv run python benchmarks/runtime_smoke.py ``` Do not claim completion until the spec pin, implementation, dependency gates, diff --git a/CHANGELOG.md b/CHANGELOG.md index 35de3a0..c1dbab6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,14 @@ versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +## [0.1.2] - 2026-07-15 + +### Changed + +- Moved the uv workspace to the repository root and grouped all workspace + projects under `packages/`, removing the redundant top-level `python/` + directory. + ## [0.1.1] - 2026-07-15 ### Changed @@ -31,6 +39,7 @@ versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Portable v0 contracts, 66 conformance cases, diagnostics, and trace verification. - Per-distribution Trusted Publisher environments for credential-free first releases. -[Unreleased]: https://github.com/Ezio2000/jharness-python/compare/v0.1.1...HEAD +[Unreleased]: https://github.com/Ezio2000/jharness-python/compare/v0.1.2...HEAD +[0.1.2]: https://github.com/Ezio2000/jharness-python/compare/v0.1.1...v0.1.2 [0.1.1]: https://github.com/Ezio2000/jharness-python/compare/v0.1.0...v0.1.1 [0.1.0]: https://github.com/Ezio2000/jharness-python/releases/tag/v0.1.0 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 32d3c6f..740b7f2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,13 +4,13 @@ JHarness Python changes must preserve the architecture and package boundaries in `AGENTS.md`. Python is managed exclusively with `uv`. ```bash -uv --project python sync --locked -uv --project python run python scripts/sync_spec.py -uv --project python run pytest -c python/pyproject.toml -q -p no:cacheprovider -uv --project python run ruff check --config python/pyproject.toml . -uv --project python run ruff format --check --config python/pyproject.toml . -uv --project python run pyright --project python -uv --project python run conformance \ +uv sync --locked +uv run python scripts/sync_spec.py +uv run pytest -c pyproject.toml -q -p no:cacheprovider +uv run ruff check --config pyproject.toml . +uv run ruff format --check --config pyproject.toml . +uv run pyright --project . +uv run conformance \ .jharness-spec/conformance/cases \ --spec-dir .jharness-spec/contracts/v0 ``` diff --git a/README.md b/README.md index ad1e1c6..41ec0d1 100644 --- a/README.md +++ b/README.md @@ -39,16 +39,16 @@ verifies its digest before running conformance. Python is managed exclusively with `uv`; do not use `pip`. ```bash -uv --project python sync --locked -uv --project python run python scripts/sync_spec.py -uv --project python run pytest -c python/pyproject.toml -q -p no:cacheprovider -uv --project python run ruff check --config python/pyproject.toml . -uv --project python run ruff format --check --config python/pyproject.toml . -uv --project python run pyright --project python -uv --project python run conformance \ +uv sync --locked +uv run python scripts/sync_spec.py +uv run pytest -c pyproject.toml -q -p no:cacheprovider +uv run ruff check --config pyproject.toml . +uv run ruff format --check --config pyproject.toml . +uv run pyright --project . +uv run conformance \ .jharness-spec/conformance/cases \ --spec-dir .jharness-spec/contracts/v0 -uv --project python run python benchmarks/runtime_smoke.py +uv run python benchmarks/runtime_smoke.py ``` ## Documentation diff --git a/docs/model-providers.md b/docs/model-providers.md index 014df3d..749f923 100644 --- a/docs/model-providers.md +++ b/docs/model-providers.md @@ -225,7 +225,7 @@ uses in one response; callers should control runtime execution concurrency with ## Testing Provider adapter behavior is tested in the owning package under -`python/providers/tests`. +`packages/providers/tests`. Default tests use mocked HTTP transports and cover each Chat Completions feature independently, including message/content encoding, model options, tool choice, diff --git a/docs/performance.md b/docs/performance.md index a4bfcbf..e015203 100644 --- a/docs/performance.md +++ b/docs/performance.md @@ -69,7 +69,7 @@ content checksum. Run from the repository root with the uv-selected interpreter: ```bash -uv --project python run python benchmarks/runtime_smoke.py +uv run python benchmarks/runtime_smoke.py ``` The benchmark compares identical asynchronous tools under serial and diff --git a/docs/python-package-boundaries.md b/docs/python-package-boundaries.md index b8b00e2..f994e76 100644 --- a/docs/python-package-boundaries.md +++ b/docs/python-package-boundaries.md @@ -1,7 +1,8 @@ # Python Package Boundaries -Python uses a uv workspace rooted at `python/` with standard `src` layouts. -Commands run from the repository root with `uv --project python`. +Python uses a uv workspace rooted at the repository root with standard `src` +layouts under `packages/`. Commands run directly from the repository root with +`uv`. ## Distributions and Workspace Projects @@ -58,9 +59,9 @@ transitive package is never treated as an implicit direct dependency. ## Source Layout ```text -python/ - pyproject.toml - uv.lock +pyproject.toml +uv.lock +packages/ kernel/ pyproject.toml src/jharness/kernel/ diff --git a/docs/releasing.md b/docs/releasing.md index 6da504e..89f0025 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -57,23 +57,23 @@ short-lived OIDC credential from each package index. 6. Refresh and verify the lock file: ```bash - uv --project python lock - uv --project python sync --locked - uv --project python run python scripts/sync_spec.py + uv lock + uv sync --locked + uv run python scripts/sync_spec.py ``` 7. Run the local release gate: ```bash - uv --project python run python scripts/verify_release.py - uv --project python run pytest -c python/pyproject.toml -q -p no:cacheprovider - uv --project python run ruff check --config python/pyproject.toml . - uv --project python run ruff format --check --config python/pyproject.toml . - uv --project python run pyright --project python - uv --project python run conformance \ + uv run python scripts/verify_release.py + uv run pytest -c pyproject.toml -q -p no:cacheprovider + uv run ruff check --config pyproject.toml . + uv run ruff format --check --config pyproject.toml . + uv run pyright --project . + uv run conformance \ .jharness-spec/conformance/cases \ --spec-dir .jharness-spec/contracts/v0 - uv --project python run python benchmarks/runtime_smoke.py + uv run python benchmarks/runtime_smoke.py ``` The pull request must merge before the release tag is created. Do not build or upload diff --git a/python/conformance/README.md b/packages/conformance/README.md similarity index 95% rename from python/conformance/README.md rename to packages/conformance/README.md index 173b4bb..9980c65 100644 --- a/python/conformance/README.md +++ b/packages/conformance/README.md @@ -12,7 +12,7 @@ normative runner contract, while this project contains Python implementation code. This project is never included in product builds. ```bash -uv --project python run conformance \ +uv run conformance \ .jharness-spec/conformance/cases \ --spec-dir .jharness-spec/contracts/v0 ``` diff --git a/python/conformance/pyproject.toml b/packages/conformance/pyproject.toml similarity index 100% rename from python/conformance/pyproject.toml rename to packages/conformance/pyproject.toml diff --git a/python/conformance/src/conformance/__init__.py b/packages/conformance/src/conformance/__init__.py similarity index 100% rename from python/conformance/src/conformance/__init__.py rename to packages/conformance/src/conformance/__init__.py diff --git a/python/conformance/src/conformance/_execution.py b/packages/conformance/src/conformance/_execution.py similarity index 100% rename from python/conformance/src/conformance/_execution.py rename to packages/conformance/src/conformance/_execution.py diff --git a/python/conformance/src/conformance/_expectations.py b/packages/conformance/src/conformance/_expectations.py similarity index 100% rename from python/conformance/src/conformance/_expectations.py rename to packages/conformance/src/conformance/_expectations.py diff --git a/python/conformance/src/conformance/_model.py b/packages/conformance/src/conformance/_model.py similarity index 100% rename from python/conformance/src/conformance/_model.py rename to packages/conformance/src/conformance/_model.py diff --git a/python/conformance/src/conformance/_schemas.py b/packages/conformance/src/conformance/_schemas.py similarity index 100% rename from python/conformance/src/conformance/_schemas.py rename to packages/conformance/src/conformance/_schemas.py diff --git a/python/conformance/src/conformance/_tools.py b/packages/conformance/src/conformance/_tools.py similarity index 100% rename from python/conformance/src/conformance/_tools.py rename to packages/conformance/src/conformance/_tools.py diff --git a/python/conformance/src/conformance/_validation.py b/packages/conformance/src/conformance/_validation.py similarity index 100% rename from python/conformance/src/conformance/_validation.py rename to packages/conformance/src/conformance/_validation.py diff --git a/python/conformance/src/conformance/_values.py b/packages/conformance/src/conformance/_values.py similarity index 100% rename from python/conformance/src/conformance/_values.py rename to packages/conformance/src/conformance/_values.py diff --git a/python/conformance/src/conformance/cli.py b/packages/conformance/src/conformance/cli.py similarity index 100% rename from python/conformance/src/conformance/cli.py rename to packages/conformance/src/conformance/cli.py diff --git a/python/conformance/src/conformance/py.typed b/packages/conformance/src/conformance/py.typed similarity index 100% rename from python/conformance/src/conformance/py.typed rename to packages/conformance/src/conformance/py.typed diff --git a/python/conformance/src/conformance/runner.py b/packages/conformance/src/conformance/runner.py similarity index 100% rename from python/conformance/src/conformance/runner.py rename to packages/conformance/src/conformance/runner.py diff --git a/python/conformance/tests/test_conformance.py b/packages/conformance/tests/test_conformance.py similarity index 100% rename from python/conformance/tests/test_conformance.py rename to packages/conformance/tests/test_conformance.py diff --git a/python/kernel/LICENSE b/packages/kernel/LICENSE similarity index 100% rename from python/kernel/LICENSE rename to packages/kernel/LICENSE diff --git a/python/kernel/README.md b/packages/kernel/README.md similarity index 100% rename from python/kernel/README.md rename to packages/kernel/README.md diff --git a/python/kernel/pyproject.toml b/packages/kernel/pyproject.toml similarity index 98% rename from python/kernel/pyproject.toml rename to packages/kernel/pyproject.toml index 23be3f2..6de0008 100644 --- a/python/kernel/pyproject.toml +++ b/packages/kernel/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "jharness-kernel" -version = "0.1.1" +version = "0.1.2" description = "JHarness model-neutral immutable runtime kernel" readme = "README.md" requires-python = ">=3.11" diff --git a/python/kernel/src/jharness/kernel/__init__.py b/packages/kernel/src/jharness/kernel/__init__.py similarity index 100% rename from python/kernel/src/jharness/kernel/__init__.py rename to packages/kernel/src/jharness/kernel/__init__.py diff --git a/python/kernel/src/jharness/kernel/_digest.py b/packages/kernel/src/jharness/kernel/_digest.py similarity index 100% rename from python/kernel/src/jharness/kernel/_digest.py rename to packages/kernel/src/jharness/kernel/_digest.py diff --git a/python/kernel/src/jharness/kernel/_engine/__init__.py b/packages/kernel/src/jharness/kernel/_engine/__init__.py similarity index 100% rename from python/kernel/src/jharness/kernel/_engine/__init__.py rename to packages/kernel/src/jharness/kernel/_engine/__init__.py diff --git a/python/kernel/src/jharness/kernel/_engine/change.py b/packages/kernel/src/jharness/kernel/_engine/change.py similarity index 100% rename from python/kernel/src/jharness/kernel/_engine/change.py rename to packages/kernel/src/jharness/kernel/_engine/change.py diff --git a/python/kernel/src/jharness/kernel/_engine/commit.py b/packages/kernel/src/jharness/kernel/_engine/commit.py similarity index 100% rename from python/kernel/src/jharness/kernel/_engine/commit.py rename to packages/kernel/src/jharness/kernel/_engine/commit.py diff --git a/python/kernel/src/jharness/kernel/_engine/deadline.py b/packages/kernel/src/jharness/kernel/_engine/deadline.py similarity index 100% rename from python/kernel/src/jharness/kernel/_engine/deadline.py rename to packages/kernel/src/jharness/kernel/_engine/deadline.py diff --git a/python/kernel/src/jharness/kernel/_engine/engine.py b/packages/kernel/src/jharness/kernel/_engine/engine.py similarity index 100% rename from python/kernel/src/jharness/kernel/_engine/engine.py rename to packages/kernel/src/jharness/kernel/_engine/engine.py diff --git a/python/kernel/src/jharness/kernel/_engine/planning.py b/packages/kernel/src/jharness/kernel/_engine/planning.py similarity index 100% rename from python/kernel/src/jharness/kernel/_engine/planning.py rename to packages/kernel/src/jharness/kernel/_engine/planning.py diff --git a/python/kernel/src/jharness/kernel/_engine/tooling.py b/packages/kernel/src/jharness/kernel/_engine/tooling.py similarity index 100% rename from python/kernel/src/jharness/kernel/_engine/tooling.py rename to packages/kernel/src/jharness/kernel/_engine/tooling.py diff --git a/python/kernel/src/jharness/kernel/_engine/verification.py b/packages/kernel/src/jharness/kernel/_engine/verification.py similarity index 100% rename from python/kernel/src/jharness/kernel/_engine/verification.py rename to packages/kernel/src/jharness/kernel/_engine/verification.py diff --git a/python/kernel/src/jharness/kernel/_history.py b/packages/kernel/src/jharness/kernel/_history.py similarity index 100% rename from python/kernel/src/jharness/kernel/_history.py rename to packages/kernel/src/jharness/kernel/_history.py diff --git a/python/kernel/src/jharness/kernel/_validation.py b/packages/kernel/src/jharness/kernel/_validation.py similarity index 100% rename from python/kernel/src/jharness/kernel/_validation.py rename to packages/kernel/src/jharness/kernel/_validation.py diff --git a/python/kernel/src/jharness/kernel/approval.py b/packages/kernel/src/jharness/kernel/approval.py similarity index 100% rename from python/kernel/src/jharness/kernel/approval.py rename to packages/kernel/src/jharness/kernel/approval.py diff --git a/python/kernel/src/jharness/kernel/checkpoint.py b/packages/kernel/src/jharness/kernel/checkpoint.py similarity index 100% rename from python/kernel/src/jharness/kernel/checkpoint.py rename to packages/kernel/src/jharness/kernel/checkpoint.py diff --git a/python/kernel/src/jharness/kernel/commands.py b/packages/kernel/src/jharness/kernel/commands.py similarity index 100% rename from python/kernel/src/jharness/kernel/commands.py rename to packages/kernel/src/jharness/kernel/commands.py diff --git a/python/kernel/src/jharness/kernel/context.py b/packages/kernel/src/jharness/kernel/context.py similarity index 100% rename from python/kernel/src/jharness/kernel/context.py rename to packages/kernel/src/jharness/kernel/context.py diff --git a/python/kernel/src/jharness/kernel/control.py b/packages/kernel/src/jharness/kernel/control.py similarity index 100% rename from python/kernel/src/jharness/kernel/control.py rename to packages/kernel/src/jharness/kernel/control.py diff --git a/python/kernel/src/jharness/kernel/diagnostics/__init__.py b/packages/kernel/src/jharness/kernel/diagnostics/__init__.py similarity index 100% rename from python/kernel/src/jharness/kernel/diagnostics/__init__.py rename to packages/kernel/src/jharness/kernel/diagnostics/__init__.py diff --git a/python/kernel/src/jharness/kernel/diagnostics/trace.py b/packages/kernel/src/jharness/kernel/diagnostics/trace.py similarity index 100% rename from python/kernel/src/jharness/kernel/diagnostics/trace.py rename to packages/kernel/src/jharness/kernel/diagnostics/trace.py diff --git a/python/kernel/src/jharness/kernel/diagnostics/verification.py b/packages/kernel/src/jharness/kernel/diagnostics/verification.py similarity index 100% rename from python/kernel/src/jharness/kernel/diagnostics/verification.py rename to packages/kernel/src/jharness/kernel/diagnostics/verification.py diff --git a/python/kernel/src/jharness/kernel/errors.py b/packages/kernel/src/jharness/kernel/errors.py similarity index 100% rename from python/kernel/src/jharness/kernel/errors.py rename to packages/kernel/src/jharness/kernel/errors.py diff --git a/python/kernel/src/jharness/kernel/events.py b/packages/kernel/src/jharness/kernel/events.py similarity index 100% rename from python/kernel/src/jharness/kernel/events.py rename to packages/kernel/src/jharness/kernel/events.py diff --git a/python/kernel/src/jharness/kernel/history.py b/packages/kernel/src/jharness/kernel/history.py similarity index 100% rename from python/kernel/src/jharness/kernel/history.py rename to packages/kernel/src/jharness/kernel/history.py diff --git a/python/kernel/src/jharness/kernel/invocation.py b/packages/kernel/src/jharness/kernel/invocation.py similarity index 100% rename from python/kernel/src/jharness/kernel/invocation.py rename to packages/kernel/src/jharness/kernel/invocation.py diff --git a/python/kernel/src/jharness/kernel/json_values.py b/packages/kernel/src/jharness/kernel/json_values.py similarity index 100% rename from python/kernel/src/jharness/kernel/json_values.py rename to packages/kernel/src/jharness/kernel/json_values.py diff --git a/python/kernel/src/jharness/kernel/limits.py b/packages/kernel/src/jharness/kernel/limits.py similarity index 100% rename from python/kernel/src/jharness/kernel/limits.py rename to packages/kernel/src/jharness/kernel/limits.py diff --git a/python/kernel/src/jharness/kernel/messages.py b/packages/kernel/src/jharness/kernel/messages.py similarity index 100% rename from python/kernel/src/jharness/kernel/messages.py rename to packages/kernel/src/jharness/kernel/messages.py diff --git a/python/kernel/src/jharness/kernel/models.py b/packages/kernel/src/jharness/kernel/models.py similarity index 100% rename from python/kernel/src/jharness/kernel/models.py rename to packages/kernel/src/jharness/kernel/models.py diff --git a/python/kernel/src/jharness/kernel/py.typed b/packages/kernel/src/jharness/kernel/py.typed similarity index 100% rename from python/kernel/src/jharness/kernel/py.typed rename to packages/kernel/src/jharness/kernel/py.typed diff --git a/python/kernel/src/jharness/kernel/repository.py b/packages/kernel/src/jharness/kernel/repository.py similarity index 100% rename from python/kernel/src/jharness/kernel/repository.py rename to packages/kernel/src/jharness/kernel/repository.py diff --git a/python/kernel/src/jharness/kernel/runtime.py b/packages/kernel/src/jharness/kernel/runtime.py similarity index 100% rename from python/kernel/src/jharness/kernel/runtime.py rename to packages/kernel/src/jharness/kernel/runtime.py diff --git a/python/kernel/src/jharness/kernel/snapshot.py b/packages/kernel/src/jharness/kernel/snapshot.py similarity index 100% rename from python/kernel/src/jharness/kernel/snapshot.py rename to packages/kernel/src/jharness/kernel/snapshot.py diff --git a/python/kernel/src/jharness/kernel/state.py b/packages/kernel/src/jharness/kernel/state.py similarity index 100% rename from python/kernel/src/jharness/kernel/state.py rename to packages/kernel/src/jharness/kernel/state.py diff --git a/python/kernel/src/jharness/kernel/tools.py b/packages/kernel/src/jharness/kernel/tools.py similarity index 100% rename from python/kernel/src/jharness/kernel/tools.py rename to packages/kernel/src/jharness/kernel/tools.py diff --git a/python/kernel/src/jharness/kernel/wire/__init__.py b/packages/kernel/src/jharness/kernel/wire/__init__.py similarity index 100% rename from python/kernel/src/jharness/kernel/wire/__init__.py rename to packages/kernel/src/jharness/kernel/wire/__init__.py diff --git a/python/kernel/src/jharness/kernel/wire/_helpers.py b/packages/kernel/src/jharness/kernel/wire/_helpers.py similarity index 100% rename from python/kernel/src/jharness/kernel/wire/_helpers.py rename to packages/kernel/src/jharness/kernel/wire/_helpers.py diff --git a/python/kernel/src/jharness/kernel/wire/checkpoint.py b/packages/kernel/src/jharness/kernel/wire/checkpoint.py similarity index 100% rename from python/kernel/src/jharness/kernel/wire/checkpoint.py rename to packages/kernel/src/jharness/kernel/wire/checkpoint.py diff --git a/python/kernel/src/jharness/kernel/wire/events.py b/packages/kernel/src/jharness/kernel/wire/events.py similarity index 100% rename from python/kernel/src/jharness/kernel/wire/events.py rename to packages/kernel/src/jharness/kernel/wire/events.py diff --git a/python/kernel/src/jharness/kernel/wire/messages.py b/packages/kernel/src/jharness/kernel/wire/messages.py similarity index 100% rename from python/kernel/src/jharness/kernel/wire/messages.py rename to packages/kernel/src/jharness/kernel/wire/messages.py diff --git a/python/kernel/src/jharness/kernel/wire/models.py b/packages/kernel/src/jharness/kernel/wire/models.py similarity index 100% rename from python/kernel/src/jharness/kernel/wire/models.py rename to packages/kernel/src/jharness/kernel/wire/models.py diff --git a/python/kernel/src/jharness/kernel/wire/requests.py b/packages/kernel/src/jharness/kernel/wire/requests.py similarity index 100% rename from python/kernel/src/jharness/kernel/wire/requests.py rename to packages/kernel/src/jharness/kernel/wire/requests.py diff --git a/python/kernel/src/jharness/kernel/wire/snapshot.py b/packages/kernel/src/jharness/kernel/wire/snapshot.py similarity index 100% rename from python/kernel/src/jharness/kernel/wire/snapshot.py rename to packages/kernel/src/jharness/kernel/wire/snapshot.py diff --git a/python/kernel/src/jharness/kernel/wire/state.py b/packages/kernel/src/jharness/kernel/wire/state.py similarity index 100% rename from python/kernel/src/jharness/kernel/wire/state.py rename to packages/kernel/src/jharness/kernel/wire/state.py diff --git a/python/kernel/src/jharness/kernel/wire/tools.py b/packages/kernel/src/jharness/kernel/wire/tools.py similarity index 100% rename from python/kernel/src/jharness/kernel/wire/tools.py rename to packages/kernel/src/jharness/kernel/wire/tools.py diff --git a/python/kernel/src/jharness/kernel/wire/trace.py b/packages/kernel/src/jharness/kernel/wire/trace.py similarity index 100% rename from python/kernel/src/jharness/kernel/wire/trace.py rename to packages/kernel/src/jharness/kernel/wire/trace.py diff --git a/python/kernel/tests/test_diagnostics.py b/packages/kernel/tests/test_diagnostics.py similarity index 100% rename from python/kernel/tests/test_diagnostics.py rename to packages/kernel/tests/test_diagnostics.py diff --git a/python/kernel/tests/test_runtime.py b/packages/kernel/tests/test_runtime.py similarity index 100% rename from python/kernel/tests/test_runtime.py rename to packages/kernel/tests/test_runtime.py diff --git a/python/kernel/tests/test_runtime_concurrency_edges.py b/packages/kernel/tests/test_runtime_concurrency_edges.py similarity index 100% rename from python/kernel/tests/test_runtime_concurrency_edges.py rename to packages/kernel/tests/test_runtime_concurrency_edges.py diff --git a/python/kernel/tests/test_values.py b/packages/kernel/tests/test_values.py similarity index 100% rename from python/kernel/tests/test_values.py rename to packages/kernel/tests/test_values.py diff --git a/python/kernel/tests/test_wire.py b/packages/kernel/tests/test_wire.py similarity index 100% rename from python/kernel/tests/test_wire.py rename to packages/kernel/tests/test_wire.py diff --git a/python/providers/LICENSE b/packages/providers/LICENSE similarity index 100% rename from python/providers/LICENSE rename to packages/providers/LICENSE diff --git a/python/providers/README.md b/packages/providers/README.md similarity index 100% rename from python/providers/README.md rename to packages/providers/README.md diff --git a/python/providers/pyproject.toml b/packages/providers/pyproject.toml similarity index 98% rename from python/providers/pyproject.toml rename to packages/providers/pyproject.toml index ff3541d..b509d9a 100644 --- a/python/providers/pyproject.toml +++ b/packages/providers/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "jharness-providers" -version = "0.1.1" +version = "0.1.2" description = "Concrete model provider adapters for the JHarness runtime" readme = "README.md" requires-python = ">=3.11" diff --git a/python/providers/src/jharness/providers/__init__.py b/packages/providers/src/jharness/providers/__init__.py similarity index 100% rename from python/providers/src/jharness/providers/__init__.py rename to packages/providers/src/jharness/providers/__init__.py diff --git a/python/providers/src/jharness/providers/_http.py b/packages/providers/src/jharness/providers/_http.py similarity index 100% rename from python/providers/src/jharness/providers/_http.py rename to packages/providers/src/jharness/providers/_http.py diff --git a/python/providers/src/jharness/providers/_json.py b/packages/providers/src/jharness/providers/_json.py similarity index 100% rename from python/providers/src/jharness/providers/_json.py rename to packages/providers/src/jharness/providers/_json.py diff --git a/python/providers/src/jharness/providers/_profiles.py b/packages/providers/src/jharness/providers/_profiles.py similarity index 100% rename from python/providers/src/jharness/providers/_profiles.py rename to packages/providers/src/jharness/providers/_profiles.py diff --git a/python/providers/src/jharness/providers/_stream.py b/packages/providers/src/jharness/providers/_stream.py similarity index 100% rename from python/providers/src/jharness/providers/_stream.py rename to packages/providers/src/jharness/providers/_stream.py diff --git a/python/providers/src/jharness/providers/anthropic/__init__.py b/packages/providers/src/jharness/providers/anthropic/__init__.py similarity index 100% rename from python/providers/src/jharness/providers/anthropic/__init__.py rename to packages/providers/src/jharness/providers/anthropic/__init__.py diff --git a/python/providers/src/jharness/providers/anthropic/errors.py b/packages/providers/src/jharness/providers/anthropic/errors.py similarity index 100% rename from python/providers/src/jharness/providers/anthropic/errors.py rename to packages/providers/src/jharness/providers/anthropic/errors.py diff --git a/python/providers/src/jharness/providers/anthropic/messages_api/__init__.py b/packages/providers/src/jharness/providers/anthropic/messages_api/__init__.py similarity index 100% rename from python/providers/src/jharness/providers/anthropic/messages_api/__init__.py rename to packages/providers/src/jharness/providers/anthropic/messages_api/__init__.py diff --git a/python/providers/src/jharness/providers/anthropic/messages_api/client.py b/packages/providers/src/jharness/providers/anthropic/messages_api/client.py similarity index 100% rename from python/providers/src/jharness/providers/anthropic/messages_api/client.py rename to packages/providers/src/jharness/providers/anthropic/messages_api/client.py diff --git a/python/providers/src/jharness/providers/anthropic/messages_api/codec.py b/packages/providers/src/jharness/providers/anthropic/messages_api/codec.py similarity index 100% rename from python/providers/src/jharness/providers/anthropic/messages_api/codec.py rename to packages/providers/src/jharness/providers/anthropic/messages_api/codec.py diff --git a/python/providers/src/jharness/providers/anthropic/messages_api/messages.py b/packages/providers/src/jharness/providers/anthropic/messages_api/messages.py similarity index 100% rename from python/providers/src/jharness/providers/anthropic/messages_api/messages.py rename to packages/providers/src/jharness/providers/anthropic/messages_api/messages.py diff --git a/python/providers/src/jharness/providers/anthropic/messages_api/stream.py b/packages/providers/src/jharness/providers/anthropic/messages_api/stream.py similarity index 100% rename from python/providers/src/jharness/providers/anthropic/messages_api/stream.py rename to packages/providers/src/jharness/providers/anthropic/messages_api/stream.py diff --git a/python/providers/src/jharness/providers/anthropic/messages_api/tools.py b/packages/providers/src/jharness/providers/anthropic/messages_api/tools.py similarity index 100% rename from python/providers/src/jharness/providers/anthropic/messages_api/tools.py rename to packages/providers/src/jharness/providers/anthropic/messages_api/tools.py diff --git a/python/providers/src/jharness/providers/anthropic/profiles.py b/packages/providers/src/jharness/providers/anthropic/profiles.py similarity index 100% rename from python/providers/src/jharness/providers/anthropic/profiles.py rename to packages/providers/src/jharness/providers/anthropic/profiles.py diff --git a/python/providers/src/jharness/providers/deepseek/__init__.py b/packages/providers/src/jharness/providers/deepseek/__init__.py similarity index 100% rename from python/providers/src/jharness/providers/deepseek/__init__.py rename to packages/providers/src/jharness/providers/deepseek/__init__.py diff --git a/python/providers/src/jharness/providers/deepseek/profiles.py b/packages/providers/src/jharness/providers/deepseek/profiles.py similarity index 100% rename from python/providers/src/jharness/providers/deepseek/profiles.py rename to packages/providers/src/jharness/providers/deepseek/profiles.py diff --git a/python/providers/src/jharness/providers/openai/__init__.py b/packages/providers/src/jharness/providers/openai/__init__.py similarity index 100% rename from python/providers/src/jharness/providers/openai/__init__.py rename to packages/providers/src/jharness/providers/openai/__init__.py diff --git a/python/providers/src/jharness/providers/openai/chat_completions/__init__.py b/packages/providers/src/jharness/providers/openai/chat_completions/__init__.py similarity index 100% rename from python/providers/src/jharness/providers/openai/chat_completions/__init__.py rename to packages/providers/src/jharness/providers/openai/chat_completions/__init__.py diff --git a/python/providers/src/jharness/providers/openai/chat_completions/client.py b/packages/providers/src/jharness/providers/openai/chat_completions/client.py similarity index 100% rename from python/providers/src/jharness/providers/openai/chat_completions/client.py rename to packages/providers/src/jharness/providers/openai/chat_completions/client.py diff --git a/python/providers/src/jharness/providers/openai/chat_completions/codec.py b/packages/providers/src/jharness/providers/openai/chat_completions/codec.py similarity index 100% rename from python/providers/src/jharness/providers/openai/chat_completions/codec.py rename to packages/providers/src/jharness/providers/openai/chat_completions/codec.py diff --git a/python/providers/src/jharness/providers/openai/chat_completions/messages.py b/packages/providers/src/jharness/providers/openai/chat_completions/messages.py similarity index 100% rename from python/providers/src/jharness/providers/openai/chat_completions/messages.py rename to packages/providers/src/jharness/providers/openai/chat_completions/messages.py diff --git a/python/providers/src/jharness/providers/openai/chat_completions/stream.py b/packages/providers/src/jharness/providers/openai/chat_completions/stream.py similarity index 100% rename from python/providers/src/jharness/providers/openai/chat_completions/stream.py rename to packages/providers/src/jharness/providers/openai/chat_completions/stream.py diff --git a/python/providers/src/jharness/providers/openai/chat_completions/tools.py b/packages/providers/src/jharness/providers/openai/chat_completions/tools.py similarity index 100% rename from python/providers/src/jharness/providers/openai/chat_completions/tools.py rename to packages/providers/src/jharness/providers/openai/chat_completions/tools.py diff --git a/python/providers/src/jharness/providers/openai/errors.py b/packages/providers/src/jharness/providers/openai/errors.py similarity index 100% rename from python/providers/src/jharness/providers/openai/errors.py rename to packages/providers/src/jharness/providers/openai/errors.py diff --git a/python/providers/src/jharness/providers/openai/profiles.py b/packages/providers/src/jharness/providers/openai/profiles.py similarity index 100% rename from python/providers/src/jharness/providers/openai/profiles.py rename to packages/providers/src/jharness/providers/openai/profiles.py diff --git a/python/providers/src/jharness/providers/py.typed b/packages/providers/src/jharness/providers/py.typed similarity index 100% rename from python/providers/src/jharness/providers/py.typed rename to packages/providers/src/jharness/providers/py.typed diff --git a/python/providers/tests/test_anthropic_provider.py b/packages/providers/tests/test_anthropic_provider.py similarity index 100% rename from python/providers/tests/test_anthropic_provider.py rename to packages/providers/tests/test_anthropic_provider.py diff --git a/python/providers/tests/test_http_errors.py b/packages/providers/tests/test_http_errors.py similarity index 100% rename from python/providers/tests/test_http_errors.py rename to packages/providers/tests/test_http_errors.py diff --git a/python/providers/tests/test_message_codecs.py b/packages/providers/tests/test_message_codecs.py similarity index 100% rename from python/providers/tests/test_message_codecs.py rename to packages/providers/tests/test_message_codecs.py diff --git a/python/providers/tests/test_openai_provider.py b/packages/providers/tests/test_openai_provider.py similarity index 100% rename from python/providers/tests/test_openai_provider.py rename to packages/providers/tests/test_openai_provider.py diff --git a/python/providers/tests/test_profiles.py b/packages/providers/tests/test_profiles.py similarity index 100% rename from python/providers/tests/test_profiles.py rename to packages/providers/tests/test_profiles.py diff --git a/python/providers/tests/test_provider_codec_edges.py b/packages/providers/tests/test_provider_codec_edges.py similarity index 100% rename from python/providers/tests/test_provider_codec_edges.py rename to packages/providers/tests/test_provider_codec_edges.py diff --git a/python/providers/tests/test_provider_stream_edges.py b/packages/providers/tests/test_provider_stream_edges.py similarity index 100% rename from python/providers/tests/test_provider_stream_edges.py rename to packages/providers/tests/test_provider_stream_edges.py diff --git a/python/providers/tests/test_stream_accumulator.py b/packages/providers/tests/test_stream_accumulator.py similarity index 100% rename from python/providers/tests/test_stream_accumulator.py rename to packages/providers/tests/test_stream_accumulator.py diff --git a/python/toolkit/LICENSE b/packages/toolkit/LICENSE similarity index 100% rename from python/toolkit/LICENSE rename to packages/toolkit/LICENSE diff --git a/python/toolkit/README.md b/packages/toolkit/README.md similarity index 100% rename from python/toolkit/README.md rename to packages/toolkit/README.md diff --git a/python/toolkit/pyproject.toml b/packages/toolkit/pyproject.toml similarity index 98% rename from python/toolkit/pyproject.toml rename to packages/toolkit/pyproject.toml index 61e515d..fdc6013 100644 --- a/python/toolkit/pyproject.toml +++ b/packages/toolkit/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "jharness-toolkit" -version = "0.1.1" +version = "0.1.2" description = "JHarness tool registry, validation helpers, and execution decorators" readme = "README.md" requires-python = ">=3.11" diff --git a/python/toolkit/src/jharness/toolkit/__init__.py b/packages/toolkit/src/jharness/toolkit/__init__.py similarity index 100% rename from python/toolkit/src/jharness/toolkit/__init__.py rename to packages/toolkit/src/jharness/toolkit/__init__.py diff --git a/python/toolkit/src/jharness/toolkit/decorators.py b/packages/toolkit/src/jharness/toolkit/decorators.py similarity index 100% rename from python/toolkit/src/jharness/toolkit/decorators.py rename to packages/toolkit/src/jharness/toolkit/decorators.py diff --git a/python/toolkit/src/jharness/toolkit/py.typed b/packages/toolkit/src/jharness/toolkit/py.typed similarity index 100% rename from python/toolkit/src/jharness/toolkit/py.typed rename to packages/toolkit/src/jharness/toolkit/py.typed diff --git a/python/toolkit/src/jharness/toolkit/registry.py b/packages/toolkit/src/jharness/toolkit/registry.py similarity index 100% rename from python/toolkit/src/jharness/toolkit/registry.py rename to packages/toolkit/src/jharness/toolkit/registry.py diff --git a/python/toolkit/src/jharness/toolkit/tool.py b/packages/toolkit/src/jharness/toolkit/tool.py similarity index 100% rename from python/toolkit/src/jharness/toolkit/tool.py rename to packages/toolkit/src/jharness/toolkit/tool.py diff --git a/python/toolkit/tests/test_toolkit.py b/packages/toolkit/tests/test_toolkit.py similarity index 100% rename from python/toolkit/tests/test_toolkit.py rename to packages/toolkit/tests/test_toolkit.py diff --git a/python/pyproject.toml b/pyproject.toml similarity index 87% rename from python/pyproject.toml rename to pyproject.toml index 12b1acf..bc54d9e 100644 --- a/python/pyproject.toml +++ b/pyproject.toml @@ -25,10 +25,10 @@ jharness-toolkit = { workspace = true } [tool.uv.workspace] members = [ - "conformance", - "kernel", - "providers", - "toolkit", + "packages/conformance", + "packages/kernel", + "packages/providers", + "packages/toolkit", ] [dependency-groups] @@ -57,7 +57,7 @@ known-first-party = ["conformance", "jharness"] [tool.pytest.ini_options] asyncio_mode = "auto" -testpaths = [".", "../tests"] +testpaths = ["packages", "tests"] [tool.coverage.run] branch = true @@ -75,6 +75,6 @@ show_missing = true skip_covered = true [tool.pyright] -include = [".", "../benchmarks", "../examples", "../tests"] +include = ["packages", "benchmarks", "examples", "tests"] pythonVersion = "3.11" typeCheckingMode = "strict" diff --git a/scripts/clean_workspace.py b/scripts/clean_workspace.py index 86b6a78..a2ed5af 100644 --- a/scripts/clean_workspace.py +++ b/scripts/clean_workspace.py @@ -18,7 +18,7 @@ ) _GENERATED_FILE_NAMES = frozenset({".coverage", ".DS_Store"}) _GENERATED_FILE_SUFFIXES = frozenset({".pyc", ".pyo"}) -_PROTECTED_PATHS = (Path(".git"), Path("python/.venv")) +_PROTECTED_PATHS = (Path(".git"), Path(".venv")) @dataclass(frozen=True, slots=True) @@ -44,7 +44,7 @@ def _is_protected(path: Path, root: Path) -> bool: def _project_roots(root: Path) -> tuple[Path, ...]: - return (root, *(root / "python" / project for project in _PROJECTS)) + return (root, *(root / "packages" / project for project in _PROJECTS)) def _minimal_targets(paths: set[Path], root: Path) -> tuple[Path, ...]: @@ -66,9 +66,6 @@ def _initial_targets(root: Path) -> set[Path]: synced_spec = root / ".jharness-spec" if synced_spec.exists() or synced_spec.is_symlink(): targets.add(synced_spec) - root_environment = root / ".venv" - if root_environment.exists() or root_environment.is_symlink(): - targets.add(root_environment) for project_root in _project_roots(root): for name in _PROJECT_OUTPUT_NAMES: candidate = project_root / name @@ -108,7 +105,7 @@ def build_cleanup_plan(root: Path) -> CleanupPlan: """Collect generated targets without traversing protected environments.""" root = root.resolve() - if not (root / "python" / "pyproject.toml").is_file(): + if not (root / "pyproject.toml").is_file(): raise ValueError(f"not a recognized workspace root: {root}") targets = _initial_targets(root) @@ -151,15 +148,6 @@ def main() -> int: print("workspace is clean") return 0 - root_environment = root / ".venv" - if args.apply and _is_within(Path(sys.prefix).resolve(), root_environment.resolve()): - print( - "workspace cleanup failed: run through `uv --project python`; " - "the active interpreter is inside the disposable root .venv", - file=sys.stderr, - ) - return 1 - action = "removing" if args.apply else "would remove" for path in plan.targets: print(f"{action} {_relative(path, root)}") diff --git a/scripts/verify_release.py b/scripts/verify_release.py index 3d282b7..38efc9e 100644 --- a/scripts/verify_release.py +++ b/scripts/verify_release.py @@ -28,7 +28,7 @@ def _project(owner: str) -> dict[str, Any]: - path = ROOT / "python" / owner / "pyproject.toml" + path = ROOT / "packages" / owner / "pyproject.toml" document = tomllib.loads(path.read_text()) return cast(dict[str, Any], document["project"]) diff --git a/tests/README.md b/tests/README.md index bbc7838..1629858 100644 --- a/tests/README.md +++ b/tests/README.md @@ -6,10 +6,10 @@ documentation links, examples, and repository maintenance tools. Behavior owned by one Python project stays with that project: -- kernel runtime and wire behavior: [`python/kernel/tests`](../python/kernel/tests/); -- concrete tool support: [`python/toolkit/tests`](../python/toolkit/tests/); -- provider adapters: [`python/providers/tests`](../python/providers/tests/); -- Python fixture-runner behavior: [`python/conformance/tests`](../python/conformance/tests/). +- kernel runtime and wire behavior: [`packages/kernel/tests`](../packages/kernel/tests/); +- concrete tool support: [`packages/toolkit/tests`](../packages/toolkit/tests/); +- provider adapters: [`packages/providers/tests`](../packages/providers/tests/); +- Python fixture-runner behavior: [`packages/conformance/tests`](../packages/conformance/tests/). Portable runtime behavior belongs in the pinned specification snapshot under `.jharness-spec/conformance/cases`, diff --git a/tests/test_dependency_boundaries.py b/tests/test_dependency_boundaries.py index 2f8e6a2..592a2c9 100644 --- a/tests/test_dependency_boundaries.py +++ b/tests/test_dependency_boundaries.py @@ -8,7 +8,7 @@ from typing import Any, cast ROOT = Path(__file__).resolve().parents[1] -PYTHON = ROOT / "python" +PACKAGES = ROOT / "packages" PROJECTS = {"kernel", "toolkit", "providers", "conformance"} IMPORT_ROOTS = { "kernel": "jharness.kernel", @@ -45,10 +45,10 @@ "conformance": {"conformance"}, } SOURCE_ROOTS = { - "kernel": PYTHON / "kernel" / "src" / "jharness" / "kernel", - "toolkit": PYTHON / "toolkit" / "src" / "jharness" / "toolkit", - "providers": PYTHON / "providers" / "src" / "jharness" / "providers", - "conformance": PYTHON / "conformance" / "src" / "conformance", + "kernel": PACKAGES / "kernel" / "src" / "jharness" / "kernel", + "toolkit": PACKAGES / "toolkit" / "src" / "jharness" / "toolkit", + "providers": PACKAGES / "providers" / "src" / "jharness" / "providers", + "conformance": PACKAGES / "conformance" / "src" / "conformance", } @@ -79,7 +79,7 @@ def requirement_name(requirement: str) -> str: def project_dependencies(owner: str) -> set[str]: - document = tomllib.loads((PYTHON / owner / "pyproject.toml").read_text()) + document = tomllib.loads((PACKAGES / owner / "pyproject.toml").read_text()) project = cast(dict[str, Any], document["project"]) dependencies = cast(list[str], project.get("dependencies", [])) return { @@ -133,11 +133,17 @@ def test_kernel_has_only_standard_library_dependencies() -> None: def test_workspace_contains_three_products_and_one_development_project() -> None: - workspace = tomllib.loads((PYTHON / "pyproject.toml").read_text()) + workspace = tomllib.loads((ROOT / "pyproject.toml").read_text()) uv = cast(dict[str, Any], workspace["tool"])["uv"] members = set(cast(list[str], cast(dict[str, Any], uv)["workspace"]["members"])) - assert members == {"kernel", "toolkit", "providers", "conformance"} - assert {PROJECT_NAMES[member] for member in members if member != "conformance"} == { + assert members == { + "packages/kernel", + "packages/toolkit", + "packages/providers", + "packages/conformance", + } + owners = {Path(member).name for member in members} + assert {PROJECT_NAMES[owner] for owner in owners if owner != "conformance"} == { "jharness-kernel", "jharness-toolkit", "jharness-providers", @@ -146,7 +152,7 @@ def test_workspace_contains_three_products_and_one_development_project() -> None def test_workspace_projects_declare_local_readmes() -> None: for owner in sorted(PROJECTS): - project_root = PYTHON / owner + project_root = PACKAGES / owner document = tomllib.loads((project_root / "pyproject.toml").read_text()) project = cast(dict[str, Any], document["project"]) assert project.get("readme") == "README.md" @@ -155,7 +161,7 @@ def test_workspace_projects_declare_local_readmes() -> None: def test_product_namespace_has_single_owner_per_child_and_no_shared_initializer() -> None: for owner in ("kernel", "toolkit", "providers"): - namespace = PYTHON / owner / "src" / "jharness" + namespace = PACKAGES / owner / "src" / "jharness" assert not (namespace / "__init__.py").exists() assert {path.name for path in namespace.iterdir() if path.is_dir()} == {owner} assert (namespace / owner / "__init__.py").is_file() @@ -163,3 +169,4 @@ def test_product_namespace_has_single_owner_per_child_and_no_shared_initializer( def test_repository_has_no_language_aggregation_tree() -> None: assert not (ROOT / "sdks").exists() + assert not (ROOT / "python").exists() diff --git a/tests/test_examples_and_docs.py b/tests/test_examples_and_docs.py index 80a1b92..30813cc 100644 --- a/tests/test_examples_and_docs.py +++ b/tests/test_examples_and_docs.py @@ -35,7 +35,7 @@ def test_every_local_markdown_link_resolves() -> None: broken: list[str] = [] markdown_files = [ROOT / "README.md", ROOT / "AGENTS.md"] markdown_files.extend((ROOT / "docs").rglob("*.md")) - markdown_files.extend((ROOT / "python").glob("*/README.md")) + markdown_files.extend((ROOT / "packages").glob("*/README.md")) markdown_files.extend((ROOT / "tests").glob("*.md")) pattern = re.compile(r"\[[^\]]+\]\(([^)]+)\)") for path in markdown_files: @@ -57,7 +57,7 @@ def test_ci_references_existing_sources_and_required_commands() -> None: referenced = set( re.findall( - r"(?:benchmarks|examples|python|scripts|tests)/[A-Za-z0-9_./-]+\.py", + r"(?:benchmarks|examples|packages|scripts|tests)/[A-Za-z0-9_./-]+\.py", workflow, ) ) diff --git a/tests/test_release_process.py b/tests/test_release_process.py index c7968bd..f65fa44 100644 --- a/tests/test_release_process.py +++ b/tests/test_release_process.py @@ -23,7 +23,7 @@ def test_release_workflow_uses_one_artifact_and_trusted_publishers() -> None: workflow = (ROOT / ".github" / "workflows" / "release.yml").read_text() assert "scripts/sync_spec.py" in workflow assert "verify_release.py --tag" in workflow - assert workflow.count("uv --project python build") == 1 + assert workflow.count("uv build") == 1 assert "publish-testpypi" in workflow assert "verify-testpypi" in workflow assert "publish-pypi" in workflow @@ -51,23 +51,24 @@ def test_repository_ownership_and_dependency_updates_are_explicit() -> None: for protected_path in ( "/.github/workflows/**", "/.github/dependabot.yml", - "/python/**/pyproject.toml", - "/python/uv.lock", + "/pyproject.toml", + "/packages/**/pyproject.toml", + "/uv.lock", "/scripts/**", ): assert protected_path in owners dependabot = (ROOT / ".github" / "dependabot.yml").read_text() assert "package-ecosystem: uv" in dependabot - assert "directory: /python" in dependabot + assert "directory: /" in dependabot assert "package-ecosystem: github-actions" in dependabot assert dependabot.count("interval: weekly") == 2 def test_package_readmes_follow_distribution_dependencies() -> None: - kernel = (ROOT / "python" / "kernel" / "README.md").read_text(encoding="utf-8").lower() - toolkit = (ROOT / "python" / "toolkit" / "README.md").read_text(encoding="utf-8").lower() - providers = (ROOT / "python" / "providers" / "README.md").read_text(encoding="utf-8").lower() + kernel = (ROOT / "packages" / "kernel" / "README.md").read_text(encoding="utf-8").lower() + toolkit = (ROOT / "packages" / "toolkit" / "README.md").read_text(encoding="utf-8").lower() + providers = (ROOT / "packages" / "providers" / "README.md").read_text(encoding="utf-8").lower() assert "jharness-toolkit" not in kernel assert "jharness.toolkit" not in kernel diff --git a/tests/test_repository_tools.py b/tests/test_repository_tools.py index 5ae970e..0a91a73 100644 --- a/tests/test_repository_tools.py +++ b/tests/test_repository_tools.py @@ -26,7 +26,7 @@ def _run_cleaner(root: Path, *arguments: str) -> subprocess.CompletedProcess[str def _workspace(tmp_path: Path) -> Path: workspace = tmp_path / "workspace" - _write(workspace / "python" / "pyproject.toml", "[project]\nname = 'test'\n") + _write(workspace / "pyproject.toml", "[project]\nname = 'test'\n") return workspace @@ -35,14 +35,12 @@ def test_workspace_cleaner_previews_then_removes_only_generated_targets( ) -> None: workspace = _workspace(tmp_path) root_environment = workspace / ".venv" / "marker" - uv_environment = workspace / "python" / ".venv" / "marker" - nested_cache = workspace / "python" / "kernel" / "src" / "jharness" / "__pycache__" / "x.pyc" + nested_cache = workspace / "packages" / "kernel" / "src" / "jharness" / "__pycache__" / "x.pyc" ordinary_cache = workspace / "examples" / "python" / "__pycache__" / "example.pyc" coverage_report = workspace / "coverage" / "index.html" retained_source = workspace / "src" / "application.py" for path in ( root_environment, - uv_environment, nested_cache, ordinary_cache, coverage_report, @@ -53,14 +51,12 @@ def test_workspace_cleaner_previews_then_removes_only_generated_targets( preview = _run_cleaner(workspace) assert preview.returncode == 0, preview.stderr - assert "would remove .venv" in preview.stdout - assert "would remove python/kernel/src/jharness/__pycache__" in preview.stdout - assert "python/.venv" not in preview.stdout + assert ".venv" not in preview.stdout + assert "would remove packages/kernel/src/jharness/__pycache__" in preview.stdout assert all( path.exists() for path in ( root_environment, - uv_environment, nested_cache, ordinary_cache, coverage_report, @@ -71,11 +67,10 @@ def test_workspace_cleaner_previews_then_removes_only_generated_targets( applied = _run_cleaner(workspace, "--apply") assert applied.returncode == 0, applied.stderr - assert not root_environment.exists() + assert root_environment.exists() assert not nested_cache.exists() assert not ordinary_cache.exists() assert not coverage_report.exists() - assert uv_environment.exists() assert retained_source.exists() diff --git a/python/uv.lock b/uv.lock similarity index 99% rename from python/uv.lock rename to uv.lock index bc5db15..255aa88 100644 --- a/python/uv.lock +++ b/uv.lock @@ -186,7 +186,7 @@ wheels = [ [[package]] name = "conformance" version = "0.1.0" -source = { editable = "conformance" } +source = { editable = "packages/conformance" } dependencies = [ { name = "jharness-kernel" }, { name = "jharness-toolkit" }, @@ -196,8 +196,8 @@ dependencies = [ [package.metadata] requires-dist = [ - { name = "jharness-kernel", editable = "kernel" }, - { name = "jharness-toolkit", editable = "toolkit" }, + { name = "jharness-kernel", editable = "packages/kernel" }, + { name = "jharness-toolkit", editable = "packages/toolkit" }, { name = "jsonschema", specifier = ">=4.23.0" }, { name = "referencing", specifier = ">=0.35.0" }, ] @@ -468,13 +468,13 @@ wheels = [ [[package]] name = "jharness-kernel" -version = "0.1.1" -source = { editable = "kernel" } +version = "0.1.2" +source = { editable = "packages/kernel" } [[package]] name = "jharness-providers" -version = "0.1.1" -source = { editable = "providers" } +version = "0.1.2" +source = { editable = "packages/providers" } dependencies = [ { name = "httpx" }, { name = "jharness-kernel" }, @@ -483,13 +483,13 @@ dependencies = [ [package.metadata] requires-dist = [ { name = "httpx", specifier = ">=0.27.0" }, - { name = "jharness-kernel", editable = "kernel" }, + { name = "jharness-kernel", editable = "packages/kernel" }, ] [[package]] name = "jharness-toolkit" -version = "0.1.1" -source = { editable = "toolkit" } +version = "0.1.2" +source = { editable = "packages/toolkit" } dependencies = [ { name = "jharness-kernel" }, { name = "jsonschema" }, @@ -498,7 +498,7 @@ dependencies = [ [package.metadata] requires-dist = [ - { name = "jharness-kernel", editable = "kernel" }, + { name = "jharness-kernel", editable = "packages/kernel" }, { name = "jsonschema", specifier = ">=4.23.0" }, { name = "referencing", specifier = ">=0.35.0" }, ] @@ -527,10 +527,10 @@ dev = [ [package.metadata] requires-dist = [ - { name = "conformance", editable = "conformance" }, - { name = "jharness-kernel", editable = "kernel" }, - { name = "jharness-providers", editable = "providers" }, - { name = "jharness-toolkit", editable = "toolkit" }, + { name = "conformance", editable = "packages/conformance" }, + { name = "jharness-kernel", editable = "packages/kernel" }, + { name = "jharness-providers", editable = "packages/providers" }, + { name = "jharness-toolkit", editable = "packages/toolkit" }, ] [package.metadata.requires-dev]