jevkit-runtime 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jevkit_runtime-0.1.0/.github/workflows/downstream.yml +39 -0
- jevkit_runtime-0.1.0/.github/workflows/publish.yml +33 -0
- jevkit_runtime-0.1.0/.github/workflows/test.yml +18 -0
- jevkit_runtime-0.1.0/.gitignore +9 -0
- jevkit_runtime-0.1.0/LICENSE +21 -0
- jevkit_runtime-0.1.0/PKG-INFO +179 -0
- jevkit_runtime-0.1.0/README.md +164 -0
- jevkit_runtime-0.1.0/TESTING.md +95 -0
- jevkit_runtime-0.1.0/consumer-baselines.json +7 -0
- jevkit_runtime-0.1.0/pyproject.toml +39 -0
- jevkit_runtime-0.1.0/scripts/dev.py +170 -0
- jevkit_runtime-0.1.0/scripts/offline/sitecustomize.py +41 -0
- jevkit_runtime-0.1.0/scripts/probe_consumer.py +232 -0
- jevkit_runtime-0.1.0/src/jevkit_core/__init__.py +48 -0
- jevkit_runtime-0.1.0/src/jevkit_core/backends.py +142 -0
- jevkit_runtime-0.1.0/src/jevkit_core/cache.py +92 -0
- jevkit_runtime-0.1.0/src/jevkit_core/client.py +109 -0
- jevkit_runtime-0.1.0/src/jevkit_core/errors.py +22 -0
- jevkit_runtime-0.1.0/src/jevkit_core/provenance.py +18 -0
- jevkit_runtime-0.1.0/src/jevkit_core/transport.py +119 -0
- jevkit_runtime-0.1.0/src/jevkit_core/usage.py +88 -0
- jevkit_runtime-0.1.0/tests/test_accounting.py +62 -0
- jevkit_runtime-0.1.0/tests/test_backends.py +82 -0
- jevkit_runtime-0.1.0/tests/test_cache_and_usage.py +91 -0
- jevkit_runtime-0.1.0/tests/test_shared_requests.py +122 -0
- jevkit_runtime-0.1.0/tests/test_transport.py +136 -0
- jevkit_runtime-0.1.0/uv.lock +303 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
name: downstream compatibility
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
consumer-ref:
|
|
9
|
+
description: Branch or tag available in all five migrated consumer repos
|
|
10
|
+
required: false
|
|
11
|
+
default: main
|
|
12
|
+
type: string
|
|
13
|
+
permissions:
|
|
14
|
+
contents: read
|
|
15
|
+
jobs:
|
|
16
|
+
consumers:
|
|
17
|
+
# Enabled after all five migration PRs land; manual runs remain available.
|
|
18
|
+
if: vars.JEVKIT_CONSUMERS_READY == 'true' || github.event_name == 'workflow_dispatch'
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
strategy:
|
|
21
|
+
fail-fast: false
|
|
22
|
+
matrix:
|
|
23
|
+
tool: [jgrep, jsort, jlink, jselect, jcol]
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
with:
|
|
27
|
+
path: jevkit-core
|
|
28
|
+
- uses: actions/checkout@v4
|
|
29
|
+
with:
|
|
30
|
+
repository: keltokhy/${{ matrix.tool }}
|
|
31
|
+
ref: ${{ inputs.consumer-ref || 'main' }}
|
|
32
|
+
path: ${{ matrix.tool }}
|
|
33
|
+
fetch-depth: 0
|
|
34
|
+
- uses: astral-sh/setup-uv@v5
|
|
35
|
+
with:
|
|
36
|
+
python-version: "3.13"
|
|
37
|
+
- run: python jevkit-core/scripts/dev.py --tool ${{ matrix.tool }} setup
|
|
38
|
+
- run: python jevkit-core/scripts/dev.py --tool ${{ matrix.tool }} check
|
|
39
|
+
- run: python jevkit-core/scripts/dev.py --tool ${{ matrix.tool }} wheel-check
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: publish
|
|
2
|
+
on:
|
|
3
|
+
workflow_dispatch:
|
|
4
|
+
inputs:
|
|
5
|
+
tag:
|
|
6
|
+
description: Verified release tag to publish to PyPI
|
|
7
|
+
required: true
|
|
8
|
+
default: v0.1.0
|
|
9
|
+
type: string
|
|
10
|
+
jobs:
|
|
11
|
+
pypi:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
environment: pypi
|
|
14
|
+
permissions:
|
|
15
|
+
id-token: write
|
|
16
|
+
contents: read
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
with:
|
|
20
|
+
ref: ${{ inputs.tag }}
|
|
21
|
+
- uses: astral-sh/setup-uv@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.13"
|
|
24
|
+
- name: Verify the selected tag matches the package version
|
|
25
|
+
env:
|
|
26
|
+
RELEASE_TAG: ${{ inputs.tag }}
|
|
27
|
+
run: test "$RELEASE_TAG" = "v$(uv version --short)"
|
|
28
|
+
- run: uv sync --locked
|
|
29
|
+
- run: uv run ruff check src tests scripts
|
|
30
|
+
- run: uv run ruff format --check src tests scripts
|
|
31
|
+
- run: uv run pytest -q
|
|
32
|
+
- run: uv build --no-sources
|
|
33
|
+
- run: uv publish --trusted-publishing always
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
name: test
|
|
2
|
+
on: [push, pull_request]
|
|
3
|
+
permissions:
|
|
4
|
+
contents: read
|
|
5
|
+
jobs:
|
|
6
|
+
core:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
strategy:
|
|
9
|
+
matrix:
|
|
10
|
+
python: ["3.10", "3.13"]
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v4
|
|
13
|
+
- uses: astral-sh/setup-uv@v5
|
|
14
|
+
- run: uv sync --locked --python ${{ matrix.python }}
|
|
15
|
+
- run: uv run ruff check src tests scripts
|
|
16
|
+
- run: uv run ruff format --check src tests scripts
|
|
17
|
+
- run: uv run pytest -q
|
|
18
|
+
- run: uv build --no-sources
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Khaled Eltokhy
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: jevkit-runtime
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Shared transport, configuration, caching, and accounting for JevKit tools
|
|
5
|
+
Project-URL: Homepage, https://github.com/keltokhy/jevkit-core
|
|
6
|
+
Project-URL: Issues, https://github.com/keltokhy/jevkit-core/issues
|
|
7
|
+
Author: Khaled Eltokhy
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Requires-Dist: httpx>=0.27
|
|
12
|
+
Provides-Extra: http2
|
|
13
|
+
Requires-Dist: httpx[http2]>=0.27; extra == 'http2'
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# JevKit core
|
|
17
|
+
|
|
18
|
+
Distribution: **`jevkit-runtime`**. Python import: **`jevkit_core`**.
|
|
19
|
+
The PyPI name `jevkit-core` belongs to a different project.
|
|
20
|
+
|
|
21
|
+
Shared provider definitions, backend configuration, HTTP transport, retries, deadlines,
|
|
22
|
+
SQLite answer storage, in-flight requests, usage accounting, and answer provenance
|
|
23
|
+
for jgrep, jsort, jlink, jselect, and jcol.
|
|
24
|
+
|
|
25
|
+
Each product remains a separate repository and package. This core imports none of them.
|
|
26
|
+
Product adapters retain prompts, cache identities, reuse policies, budget policies, and public APIs.
|
|
27
|
+
|
|
28
|
+
Version 0.1.0 is a **local development release**, not a published PyPI release.
|
|
29
|
+
Ordinary source edits in an editable core installation apply on the next run;
|
|
30
|
+
already-running Python processes need to restart.
|
|
31
|
+
|
|
32
|
+
## Development
|
|
33
|
+
|
|
34
|
+
Keep the six checkouts as siblings. Each consumer declares a normal versioned
|
|
35
|
+
dependency on `jevkit-runtime` and a uv development override:
|
|
36
|
+
|
|
37
|
+
```toml
|
|
38
|
+
[tool.uv.sources]
|
|
39
|
+
jevkit-runtime = { path = "../jevkit-core", editable = true }
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Clone `keltokhy/jevkit-core` beside `keltokhy/jgrep`, `keltokhy/jsort`,
|
|
43
|
+
`keltokhy/jlink`, `keltokhy/jselect`, and `keltokhy/jcol`. All six repositories
|
|
44
|
+
remain independently versioned. For isolated development checkouts named
|
|
45
|
+
`jgrep-jevkit` and so on, use the `--suffix=-jevkit` option shown below.
|
|
46
|
+
|
|
47
|
+
From this directory:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
python3 scripts/dev.py --suffix=-jevkit setup
|
|
51
|
+
python3 scripts/dev.py --suffix=-jevkit check
|
|
52
|
+
python3 scripts/dev.py --suffix=-jevkit wheel-check
|
|
53
|
+
python3 scripts/dev.py --suffix=-jevkit run jgrep -- --help
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`run` uses the selected worktree's virtual environment and preserves the caller's
|
|
57
|
+
working directory. To use it with data, replace `--help` with the normal tool arguments.
|
|
58
|
+
For ordinary unsuffixed clones, omit `--suffix`. `--repos-root` selects their parent;
|
|
59
|
+
`--tool jgrep` limits setup and checks to one consumer.
|
|
60
|
+
|
|
61
|
+
`setup` installs dependencies and prepares the public tiktoken encoding files needed
|
|
62
|
+
by jselect. It performs no model inference. `check` runs each suite in its own
|
|
63
|
+
environment, strips model credentials, isolates configuration/cache directories,
|
|
64
|
+
and blocks outbound sockets while permitting local fake HTTP servers. It also proves
|
|
65
|
+
that every consumer calls the shared transport and imports this exact source tree,
|
|
66
|
+
and compares its fixture behavior to the commits in `consumer-baselines.json`.
|
|
67
|
+
Those commits must be present locally; use a full clone or fetch that history.
|
|
68
|
+
|
|
69
|
+
`wheel-check` builds the core and consumer wheels, installs each consumer alongside
|
|
70
|
+
the core wheel in a separate temporary environment, and exercises model fixtures and
|
|
71
|
+
CLI entry points outside the source trees. It also checks packaged browser/review assets
|
|
72
|
+
and jcol's installed process workflow. Dependency installation may use the package index;
|
|
73
|
+
inference checks stay offline.
|
|
74
|
+
|
|
75
|
+
## Shared boundary
|
|
76
|
+
|
|
77
|
+
| Module | Responsibility |
|
|
78
|
+
|---|---|
|
|
79
|
+
| `backends.py` | Provider catalog, credential/configuration lookup, capabilities, selection |
|
|
80
|
+
| `transport.py` | HTTP requests, total deadlines, retries, JSON/error handling |
|
|
81
|
+
| `client.py` | Client lifecycle, shared in-flight requests, transport delegation, common answer validation |
|
|
82
|
+
| `cache.py` | SQLite answer storage and atomic provenance writes, key serialization |
|
|
83
|
+
| `usage.py` | Usage validation, reported/estimated costs, meter and report accumulation |
|
|
84
|
+
| `provenance.py` | Versioned answer origins with literal or unknown responder identity |
|
|
85
|
+
| `errors.py` | Shared failure types and structured request exhaustion |
|
|
86
|
+
|
|
87
|
+
`DecisionClient` is an adapter base, not a complete standalone scoring SDK. Product
|
|
88
|
+
adapters supply their own `ask` and `_record` contracts. jselect calls the shared
|
|
89
|
+
transport directly while retaining its relevance batching, score cache, and statistics.
|
|
90
|
+
Tool-specific meter fields remain in small subclasses.
|
|
91
|
+
|
|
92
|
+
`backend_catalog` selects provider definitions in each tool's priority order and
|
|
93
|
+
accepts model overrides. The four decision clients retain moving model aliases;
|
|
94
|
+
jselect keeps its pinned defaults. The catalog also defines two opt-in local providers; tools choose whether to expose them. Adding a catalog entry does not automatically enable it in every tool.
|
|
95
|
+
|
|
96
|
+
`DecisionClient.share_request` returns a task and an ownership flag. It invokes a
|
|
97
|
+
lazy request factory only for the owner, allowing jlink's cache-only callers to
|
|
98
|
+
join existing requests and jsort to charge only the initiating caller. It removes
|
|
99
|
+
finished, failed, and cancelled tasks from the registry. Awaiting, cancellation,
|
|
100
|
+
cache identity, and jcol's hedging policy remain with the adapters; sharing does
|
|
101
|
+
not introduce cancellation shielding or change how a hedge is charged.
|
|
102
|
+
|
|
103
|
+
`Meter.record` and `record_usage` accumulate the same call/token/cost fields for
|
|
104
|
+
the four clients and jselect's dictionary reports. Meter callbacks run after
|
|
105
|
+
totals change and before latency/model updates. Cost-source labels, jsort's
|
|
106
|
+
maximum call cost, jlink's provenance summaries, and model fallback remain local.
|
|
107
|
+
`answer_provenance` constructs the shared version-1 metadata for jsort and jlink;
|
|
108
|
+
missing responder identity stays unknown rather than inheriting a requested alias.
|
|
109
|
+
|
|
110
|
+
No product imports another product, and the core imports none of them. NumPy,
|
|
111
|
+
pandas, SciPy, Polars, tokenizers, and browser dependencies stay in their owning
|
|
112
|
+
tools. HTTP/2 is an optional core extra used by jcol.
|
|
113
|
+
|
|
114
|
+
## Compatibility
|
|
115
|
+
|
|
116
|
+
- Existing prompts, CLI flags, supported backend choices, cache-key bytes, and
|
|
117
|
+
saved project/scale/index formats are retained by the adapters.
|
|
118
|
+
- Existing `~/.config/jev` and cache locations continue to work. No user cache or
|
|
119
|
+
credential files were opened or migrated during development.
|
|
120
|
+
- Legacy answer keys remain explicitly tool-owned. The shared `answer_key` function
|
|
121
|
+
offers an opt-in, versioned provider/endpoint identity for future consumers; it
|
|
122
|
+
never falls back to an ambiguous legacy entry. In particular, jlink's existing
|
|
123
|
+
cross-backend cache behavior has not silently changed.
|
|
124
|
+
- jcol checkpoints and jselect's score cache remain separate from shared answer storage.
|
|
125
|
+
- Budget meanings remain local: zero is unlimited for jgrep/jsort, cache-only for
|
|
126
|
+
jlink, and rejected by jselect's semantic scorer. jcol retains its scheduler policy.
|
|
127
|
+
- The separate experimental jgrep branch retains joint-read caching and keyless
|
|
128
|
+
local backends. The main-branch migration exposes its original three providers;
|
|
129
|
+
unrelated experiments and benchmark graphics are not part of that migration.
|
|
130
|
+
- All clients now use a true total HTTP deadline. jlink and jcol previously passed
|
|
131
|
+
the remaining time only to httpx's individual network waits.
|
|
132
|
+
- All five use validated usage parsing. Malformed, negative, nonfinite, or boolean
|
|
133
|
+
usage values fail rather than corrupting accounting; jselect retains its
|
|
134
|
+
fractional-token and missing-token estimate policy.
|
|
135
|
+
|
|
136
|
+
These last two points are deliberate hardening accompanying the extraction.
|
|
137
|
+
The adapter tests remain the source of truth for each tool's external behavior.
|
|
138
|
+
|
|
139
|
+
## Cross-repository validation
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
python3 scripts/dev.py --suffix=-jevkit check
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
For a before/after request, result, and metering comparison, use a consumer's
|
|
146
|
+
environment with `scripts/probe_consumer.py TOOL --baseline-repo PATH --baseline-ref COMMIT`.
|
|
147
|
+
The probe covers cold/warm caches, repeated requests, in-flight sharing, typed
|
|
148
|
+
jcol answers, and provider definitions/defaults. It verifies shared accounting
|
|
149
|
+
for all five, request sharing for the four decision clients, and provenance
|
|
150
|
+
construction for jsort/jlink. It is a focused compatibility fixture, not an
|
|
151
|
+
exhaustive equivalence proof.
|
|
152
|
+
|
|
153
|
+
The core CI tests Python 3.10 and 3.13. The downstream workflow tests the exact
|
|
154
|
+
core revision against all five consumer main branches in separate jobs, including
|
|
155
|
+
wheel installs. Pull-request and main-push runs are enabled with the repository
|
|
156
|
+
variable `JEVKIT_CONSUMERS_READY=true` after bootstrap. Manual dispatch can select
|
|
157
|
+
a common consumer branch/tag before then. All five consumer repositories are public.
|
|
158
|
+
|
|
159
|
+
## Release sequence
|
|
160
|
+
|
|
161
|
+
The five packages retain independent releases. Their wheels contain a dependency
|
|
162
|
+
on `jevkit-runtime>=0.1.0,<0.2.0`, never a local source path; jcol requests the `http2` extra.
|
|
163
|
+
|
|
164
|
+
Before publishing any migrated consumer to PyPI:
|
|
165
|
+
|
|
166
|
+
1. Merge and tag the verified core as `v0.1.0`. Consumer CI checks out this tag
|
|
167
|
+
beside its own source, so tests do not depend on PyPI publication timing.
|
|
168
|
+
2. Configure a PyPI Trusted Publisher for `jevkit-runtime`, repository
|
|
169
|
+
`keltokhy/jevkit-core`, workflow `publish.yml`, environment `pypi`. Dispatch the
|
|
170
|
+
publish workflow with the verified release tag. Publishing is explicit; creating
|
|
171
|
+
a Git tag alone does not upload a package.
|
|
172
|
+
3. Release each consumer through its existing versioning/publishing process. Update
|
|
173
|
+
its supported core range, lockfile, and CI core reference together on upgrades.
|
|
174
|
+
|
|
175
|
+
Until the runtime distribution is available on PyPI, source development uses the
|
|
176
|
+
sibling checkout. The cross-repository wheel checks install a freshly built core
|
|
177
|
+
wheel explicitly alongside each consumer. Existing published tool versions remain
|
|
178
|
+
independent of this migration. Once the runtime is published, standalone source
|
|
179
|
+
clones can use `uv sync --no-sources`; published wheels use ordinary dependencies.
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# JevKit core
|
|
2
|
+
|
|
3
|
+
Distribution: **`jevkit-runtime`**. Python import: **`jevkit_core`**.
|
|
4
|
+
The PyPI name `jevkit-core` belongs to a different project.
|
|
5
|
+
|
|
6
|
+
Shared provider definitions, backend configuration, HTTP transport, retries, deadlines,
|
|
7
|
+
SQLite answer storage, in-flight requests, usage accounting, and answer provenance
|
|
8
|
+
for jgrep, jsort, jlink, jselect, and jcol.
|
|
9
|
+
|
|
10
|
+
Each product remains a separate repository and package. This core imports none of them.
|
|
11
|
+
Product adapters retain prompts, cache identities, reuse policies, budget policies, and public APIs.
|
|
12
|
+
|
|
13
|
+
Version 0.1.0 is a **local development release**, not a published PyPI release.
|
|
14
|
+
Ordinary source edits in an editable core installation apply on the next run;
|
|
15
|
+
already-running Python processes need to restart.
|
|
16
|
+
|
|
17
|
+
## Development
|
|
18
|
+
|
|
19
|
+
Keep the six checkouts as siblings. Each consumer declares a normal versioned
|
|
20
|
+
dependency on `jevkit-runtime` and a uv development override:
|
|
21
|
+
|
|
22
|
+
```toml
|
|
23
|
+
[tool.uv.sources]
|
|
24
|
+
jevkit-runtime = { path = "../jevkit-core", editable = true }
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Clone `keltokhy/jevkit-core` beside `keltokhy/jgrep`, `keltokhy/jsort`,
|
|
28
|
+
`keltokhy/jlink`, `keltokhy/jselect`, and `keltokhy/jcol`. All six repositories
|
|
29
|
+
remain independently versioned. For isolated development checkouts named
|
|
30
|
+
`jgrep-jevkit` and so on, use the `--suffix=-jevkit` option shown below.
|
|
31
|
+
|
|
32
|
+
From this directory:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
python3 scripts/dev.py --suffix=-jevkit setup
|
|
36
|
+
python3 scripts/dev.py --suffix=-jevkit check
|
|
37
|
+
python3 scripts/dev.py --suffix=-jevkit wheel-check
|
|
38
|
+
python3 scripts/dev.py --suffix=-jevkit run jgrep -- --help
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`run` uses the selected worktree's virtual environment and preserves the caller's
|
|
42
|
+
working directory. To use it with data, replace `--help` with the normal tool arguments.
|
|
43
|
+
For ordinary unsuffixed clones, omit `--suffix`. `--repos-root` selects their parent;
|
|
44
|
+
`--tool jgrep` limits setup and checks to one consumer.
|
|
45
|
+
|
|
46
|
+
`setup` installs dependencies and prepares the public tiktoken encoding files needed
|
|
47
|
+
by jselect. It performs no model inference. `check` runs each suite in its own
|
|
48
|
+
environment, strips model credentials, isolates configuration/cache directories,
|
|
49
|
+
and blocks outbound sockets while permitting local fake HTTP servers. It also proves
|
|
50
|
+
that every consumer calls the shared transport and imports this exact source tree,
|
|
51
|
+
and compares its fixture behavior to the commits in `consumer-baselines.json`.
|
|
52
|
+
Those commits must be present locally; use a full clone or fetch that history.
|
|
53
|
+
|
|
54
|
+
`wheel-check` builds the core and consumer wheels, installs each consumer alongside
|
|
55
|
+
the core wheel in a separate temporary environment, and exercises model fixtures and
|
|
56
|
+
CLI entry points outside the source trees. It also checks packaged browser/review assets
|
|
57
|
+
and jcol's installed process workflow. Dependency installation may use the package index;
|
|
58
|
+
inference checks stay offline.
|
|
59
|
+
|
|
60
|
+
## Shared boundary
|
|
61
|
+
|
|
62
|
+
| Module | Responsibility |
|
|
63
|
+
|---|---|
|
|
64
|
+
| `backends.py` | Provider catalog, credential/configuration lookup, capabilities, selection |
|
|
65
|
+
| `transport.py` | HTTP requests, total deadlines, retries, JSON/error handling |
|
|
66
|
+
| `client.py` | Client lifecycle, shared in-flight requests, transport delegation, common answer validation |
|
|
67
|
+
| `cache.py` | SQLite answer storage and atomic provenance writes, key serialization |
|
|
68
|
+
| `usage.py` | Usage validation, reported/estimated costs, meter and report accumulation |
|
|
69
|
+
| `provenance.py` | Versioned answer origins with literal or unknown responder identity |
|
|
70
|
+
| `errors.py` | Shared failure types and structured request exhaustion |
|
|
71
|
+
|
|
72
|
+
`DecisionClient` is an adapter base, not a complete standalone scoring SDK. Product
|
|
73
|
+
adapters supply their own `ask` and `_record` contracts. jselect calls the shared
|
|
74
|
+
transport directly while retaining its relevance batching, score cache, and statistics.
|
|
75
|
+
Tool-specific meter fields remain in small subclasses.
|
|
76
|
+
|
|
77
|
+
`backend_catalog` selects provider definitions in each tool's priority order and
|
|
78
|
+
accepts model overrides. The four decision clients retain moving model aliases;
|
|
79
|
+
jselect keeps its pinned defaults. The catalog also defines two opt-in local providers; tools choose whether to expose them. Adding a catalog entry does not automatically enable it in every tool.
|
|
80
|
+
|
|
81
|
+
`DecisionClient.share_request` returns a task and an ownership flag. It invokes a
|
|
82
|
+
lazy request factory only for the owner, allowing jlink's cache-only callers to
|
|
83
|
+
join existing requests and jsort to charge only the initiating caller. It removes
|
|
84
|
+
finished, failed, and cancelled tasks from the registry. Awaiting, cancellation,
|
|
85
|
+
cache identity, and jcol's hedging policy remain with the adapters; sharing does
|
|
86
|
+
not introduce cancellation shielding or change how a hedge is charged.
|
|
87
|
+
|
|
88
|
+
`Meter.record` and `record_usage` accumulate the same call/token/cost fields for
|
|
89
|
+
the four clients and jselect's dictionary reports. Meter callbacks run after
|
|
90
|
+
totals change and before latency/model updates. Cost-source labels, jsort's
|
|
91
|
+
maximum call cost, jlink's provenance summaries, and model fallback remain local.
|
|
92
|
+
`answer_provenance` constructs the shared version-1 metadata for jsort and jlink;
|
|
93
|
+
missing responder identity stays unknown rather than inheriting a requested alias.
|
|
94
|
+
|
|
95
|
+
No product imports another product, and the core imports none of them. NumPy,
|
|
96
|
+
pandas, SciPy, Polars, tokenizers, and browser dependencies stay in their owning
|
|
97
|
+
tools. HTTP/2 is an optional core extra used by jcol.
|
|
98
|
+
|
|
99
|
+
## Compatibility
|
|
100
|
+
|
|
101
|
+
- Existing prompts, CLI flags, supported backend choices, cache-key bytes, and
|
|
102
|
+
saved project/scale/index formats are retained by the adapters.
|
|
103
|
+
- Existing `~/.config/jev` and cache locations continue to work. No user cache or
|
|
104
|
+
credential files were opened or migrated during development.
|
|
105
|
+
- Legacy answer keys remain explicitly tool-owned. The shared `answer_key` function
|
|
106
|
+
offers an opt-in, versioned provider/endpoint identity for future consumers; it
|
|
107
|
+
never falls back to an ambiguous legacy entry. In particular, jlink's existing
|
|
108
|
+
cross-backend cache behavior has not silently changed.
|
|
109
|
+
- jcol checkpoints and jselect's score cache remain separate from shared answer storage.
|
|
110
|
+
- Budget meanings remain local: zero is unlimited for jgrep/jsort, cache-only for
|
|
111
|
+
jlink, and rejected by jselect's semantic scorer. jcol retains its scheduler policy.
|
|
112
|
+
- The separate experimental jgrep branch retains joint-read caching and keyless
|
|
113
|
+
local backends. The main-branch migration exposes its original three providers;
|
|
114
|
+
unrelated experiments and benchmark graphics are not part of that migration.
|
|
115
|
+
- All clients now use a true total HTTP deadline. jlink and jcol previously passed
|
|
116
|
+
the remaining time only to httpx's individual network waits.
|
|
117
|
+
- All five use validated usage parsing. Malformed, negative, nonfinite, or boolean
|
|
118
|
+
usage values fail rather than corrupting accounting; jselect retains its
|
|
119
|
+
fractional-token and missing-token estimate policy.
|
|
120
|
+
|
|
121
|
+
These last two points are deliberate hardening accompanying the extraction.
|
|
122
|
+
The adapter tests remain the source of truth for each tool's external behavior.
|
|
123
|
+
|
|
124
|
+
## Cross-repository validation
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
python3 scripts/dev.py --suffix=-jevkit check
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
For a before/after request, result, and metering comparison, use a consumer's
|
|
131
|
+
environment with `scripts/probe_consumer.py TOOL --baseline-repo PATH --baseline-ref COMMIT`.
|
|
132
|
+
The probe covers cold/warm caches, repeated requests, in-flight sharing, typed
|
|
133
|
+
jcol answers, and provider definitions/defaults. It verifies shared accounting
|
|
134
|
+
for all five, request sharing for the four decision clients, and provenance
|
|
135
|
+
construction for jsort/jlink. It is a focused compatibility fixture, not an
|
|
136
|
+
exhaustive equivalence proof.
|
|
137
|
+
|
|
138
|
+
The core CI tests Python 3.10 and 3.13. The downstream workflow tests the exact
|
|
139
|
+
core revision against all five consumer main branches in separate jobs, including
|
|
140
|
+
wheel installs. Pull-request and main-push runs are enabled with the repository
|
|
141
|
+
variable `JEVKIT_CONSUMERS_READY=true` after bootstrap. Manual dispatch can select
|
|
142
|
+
a common consumer branch/tag before then. All five consumer repositories are public.
|
|
143
|
+
|
|
144
|
+
## Release sequence
|
|
145
|
+
|
|
146
|
+
The five packages retain independent releases. Their wheels contain a dependency
|
|
147
|
+
on `jevkit-runtime>=0.1.0,<0.2.0`, never a local source path; jcol requests the `http2` extra.
|
|
148
|
+
|
|
149
|
+
Before publishing any migrated consumer to PyPI:
|
|
150
|
+
|
|
151
|
+
1. Merge and tag the verified core as `v0.1.0`. Consumer CI checks out this tag
|
|
152
|
+
beside its own source, so tests do not depend on PyPI publication timing.
|
|
153
|
+
2. Configure a PyPI Trusted Publisher for `jevkit-runtime`, repository
|
|
154
|
+
`keltokhy/jevkit-core`, workflow `publish.yml`, environment `pypi`. Dispatch the
|
|
155
|
+
publish workflow with the verified release tag. Publishing is explicit; creating
|
|
156
|
+
a Git tag alone does not upload a package.
|
|
157
|
+
3. Release each consumer through its existing versioning/publishing process. Update
|
|
158
|
+
its supported core range, lockfile, and CI core reference together on upgrades.
|
|
159
|
+
|
|
160
|
+
Until the runtime distribution is available on PyPI, source development uses the
|
|
161
|
+
sibling checkout. The cross-repository wheel checks install a freshly built core
|
|
162
|
+
wheel explicitly alongside each consumer. Existing published tool versions remain
|
|
163
|
+
independent of this migration. Once the runtime is published, standalone source
|
|
164
|
+
clones can use `uv sync --no-sources`; published wheels use ordinary dependencies.
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Validation record — 2026-09-22
|
|
2
|
+
|
|
3
|
+
The five source baselines are recorded in `consumer-baselines.json`. Bootstrap
|
|
4
|
+
fetches verified current remote main branches. No model inference was performed. Tests used mock
|
|
5
|
+
transports or local HTTP fixtures with outbound sockets blocked and model
|
|
6
|
+
credentials removed. Dependency installation and public tokenizer preparation
|
|
7
|
+
are separate from those inference-free checks.
|
|
8
|
+
|
|
9
|
+
| Package | Interpreter | Result |
|
|
10
|
+
|---|---|---|
|
|
11
|
+
| jevkit-core | Python 3.13.15 | 44 passed |
|
|
12
|
+
| jevkit-core | Python 3.10.21 | 44 passed |
|
|
13
|
+
| jgrep | Python 3.12.14 | 282 passed |
|
|
14
|
+
| jsort | Python 3.13.15 | 159 passed |
|
|
15
|
+
| jlink | Python 3.12.14 | 720 passed |
|
|
16
|
+
| jselect | Python 3.13.15 | 164 passed |
|
|
17
|
+
| jcol | Python 3.12.14 | 138 passed, 3 existing warnings |
|
|
18
|
+
|
|
19
|
+
The consumer total for the main-branch migrations is 1,463. All existing consumer test files were retained
|
|
20
|
+
without modifying their assertions. The core now includes 17 additional tests
|
|
21
|
+
for provider selection/model overrides, accounting callback order, unknown-model
|
|
22
|
+
provenance, single-owner charges, cache-only sharing, task isolation, and cleanup
|
|
23
|
+
after success, failure, or cancellation. All five baselines were also tested before
|
|
24
|
+
the extraction; jselect's first attempt had an incorrect tokenizer-cache path,
|
|
25
|
+
then passed all 164 tests after pointing to the existing local cache. The first
|
|
26
|
+
migrated jselect run exposed a timeout error-message regression, fixed in the
|
|
27
|
+
adapter without changing its test.
|
|
28
|
+
|
|
29
|
+
Additional checks:
|
|
30
|
+
|
|
31
|
+
- All five import `/Volumes/K3/GitHub/jevkit-core/src/jevkit_core` from their separate
|
|
32
|
+
editable development environments. Instrumentation verifies that each actually
|
|
33
|
+
calls the shared transport.
|
|
34
|
+
- All five match their original Git versions on the focused request/result/metering
|
|
35
|
+
probe: raw request bodies, responses, warm-cache reuse, common counters, and
|
|
36
|
+
effective provider definitions/defaults. The provider comparison normalizes
|
|
37
|
+
capability fields that were implicit in older adapters.
|
|
38
|
+
The four client adapters also exercise in-flight request sharing; jcol includes
|
|
39
|
+
binary, categorical, and scale answers. This is bounded fixture evidence, not
|
|
40
|
+
exhaustive equivalence across every input.
|
|
41
|
+
- Instrumentation verifies that all five use shared usage accumulation, the four
|
|
42
|
+
decision clients use shared in-flight request handling, and jsort/jlink construct
|
|
43
|
+
answer provenance through the core. jselect keeps its relevance batching and
|
|
44
|
+
separate score-cache behavior. Existing tests retain coverage for jsort's charge
|
|
45
|
+
attribution, jlink's cache-only sharing, and jcol's hedging.
|
|
46
|
+
- Fresh core and consumer wheels install in five independent temporary environments
|
|
47
|
+
outside source checkouts. Every installed CLI reports its version and every
|
|
48
|
+
installed consumer uses the wheel's core, not the editable checkout.
|
|
49
|
+
- jlink review HTML/JS/CSS and jcol's browser HTML are present in the installed wheels.
|
|
50
|
+
- The installed jcol process checks pass for pipes, partial completion/resume,
|
|
51
|
+
offline export, Parquet stdin, and SIGINT recovery.
|
|
52
|
+
- Core and jselect lint/format checks pass. All modified GitHub workflow YAML parses;
|
|
53
|
+
all repository diffs pass whitespace checks. Hosted CI has not been run.
|
|
54
|
+
|
|
55
|
+
Reproduce the suite from the core checkout:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
python3 scripts/dev.py --suffix=-jevkit setup
|
|
59
|
+
python3 scripts/dev.py --suffix=-jevkit check
|
|
60
|
+
python3 scripts/dev.py --suffix=-jevkit wheel-check
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Current logs are retained in `/Volumes/K3/agent-working-space/jevkit/`:
|
|
64
|
+
`core-followup-check.log`, `core-followup-wheels.log`, and
|
|
65
|
+
`core-followup-py310.log`. The initial extraction logs and two preliminary
|
|
66
|
+
provider-comparison runs are preserved separately. Those preliminary comparisons
|
|
67
|
+
needed normalization of implicit legacy capability fields; consumer behavior did
|
|
68
|
+
not require a correction. These logs are development artifacts, not package contents.
|
|
69
|
+
|
|
70
|
+
Release boundary: this validates the local development implementation and locally
|
|
71
|
+
built packages. It does not establish live model quality, hosted CI status, or
|
|
72
|
+
publication. The core remote/tag/package must be published before migrated consumer
|
|
73
|
+
CI and public releases can resolve their pinned core dependency.
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
## GitHub bootstrap
|
|
77
|
+
|
|
78
|
+
The distribution is named `jevkit-runtime`: the PyPI project `jevkit-core` belongs
|
|
79
|
+
to another developer. The repository remains `keltokhy/jevkit-core`, and Python
|
|
80
|
+
imports remain `jevkit_core`. The five source overrides and lockfiles use the new
|
|
81
|
+
distribution name. Wheel checks install the freshly built runtime explicitly.
|
|
82
|
+
|
|
83
|
+
The jgrep PR is based on main (`7b2c867`), excluding the separate experimental
|
|
84
|
+
backend and benchmark commits used in the first local exploration. Its 282-test main-branch suite passes; the earlier local 299-test run covered
|
|
85
|
+
that experimental branch. The other four baselines are unchanged.
|
|
86
|
+
|
|
87
|
+
All six repositories are public, so the hosted downstream matrix can check out
|
|
88
|
+
all five consumers without extra repository credentials. The matrix is gated by
|
|
89
|
+
`JEVKIT_CONSUMERS_READY` during the initial six-PR bootstrap, then enabled for
|
|
90
|
+
future core pull requests and pushes. PyPI publishing is manually dispatched after
|
|
91
|
+
Trusted Publishing is configured; Git tags alone do not publish a distribution.
|
|
92
|
+
|
|
93
|
+
Bootstrap logs: `publish-setup.log`, `publish-check.log`, and `publish-wheels.log`
|
|
94
|
+
in the same local report directory. The source-only jgrep migration, distribution
|
|
95
|
+
rename, and installed wheel paths are verified again before merging.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"jgrep": "7b2c86752a1b5d1ec0a250069bb4bce8f98a30f6",
|
|
3
|
+
"jsort": "4fa1e5e6d68543f24e7c1f390fd7167612b2f6c2",
|
|
4
|
+
"jlink": "3cce3e3446e90b7407bf8b6cf8023e2fedac8c03",
|
|
5
|
+
"jselect": "5bad1145c5c4a7f05b201d7d15e23e6608caa588",
|
|
6
|
+
"jcol": "7d2b9892342e90fbd8745487e378df294d6096f8"
|
|
7
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "jevkit-runtime"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Shared transport, configuration, caching, and accounting for JevKit tools"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
authors = [{ name = "Khaled Eltokhy" }]
|
|
8
|
+
requires-python = ">=3.10"
|
|
9
|
+
dependencies = ["httpx>=0.27"]
|
|
10
|
+
|
|
11
|
+
[project.urls]
|
|
12
|
+
Homepage = "https://github.com/keltokhy/jevkit-core"
|
|
13
|
+
Issues = "https://github.com/keltokhy/jevkit-core/issues"
|
|
14
|
+
|
|
15
|
+
[project.optional-dependencies]
|
|
16
|
+
http2 = ["httpx[http2]>=0.27"]
|
|
17
|
+
|
|
18
|
+
[dependency-groups]
|
|
19
|
+
dev = ["pytest>=8", "ruff>=0.11"]
|
|
20
|
+
|
|
21
|
+
[build-system]
|
|
22
|
+
requires = ["hatchling"]
|
|
23
|
+
build-backend = "hatchling.build"
|
|
24
|
+
|
|
25
|
+
[tool.hatch.build.targets.wheel]
|
|
26
|
+
packages = ["src/jevkit_core"]
|
|
27
|
+
|
|
28
|
+
[tool.pytest.ini_options]
|
|
29
|
+
testpaths = ["tests"]
|
|
30
|
+
|
|
31
|
+
[tool.uv.workspace]
|
|
32
|
+
members = []
|
|
33
|
+
|
|
34
|
+
[tool.ruff]
|
|
35
|
+
line-length = 110
|
|
36
|
+
target-version = "py310"
|
|
37
|
+
|
|
38
|
+
[tool.ruff.lint]
|
|
39
|
+
select = ["E", "F", "I", "UP", "B"]
|