oneground 0.1.0rc1__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.
Files changed (87) hide show
  1. oneground-0.1.0rc1/PKG-INFO +244 -0
  2. oneground-0.1.0rc1/README.md +200 -0
  3. oneground-0.1.0rc1/oneground/__init__.py +18 -0
  4. oneground-0.1.0rc1/oneground/adapters/__init__.py +28 -0
  5. oneground-0.1.0rc1/oneground/adapters/base.py +254 -0
  6. oneground-0.1.0rc1/oneground/adapters/conformance.py +320 -0
  7. oneground-0.1.0rc1/oneground/adapters/qdrant/__init__.py +3 -0
  8. oneground-0.1.0rc1/oneground/adapters/qdrant/adapter.py +371 -0
  9. oneground-0.1.0rc1/oneground/adapters/stub.py +154 -0
  10. oneground-0.1.0rc1/oneground/analogy.py +249 -0
  11. oneground-0.1.0rc1/oneground/calibrate/__init__.py +729 -0
  12. oneground-0.1.0rc1/oneground/calibrate/fixture.py +218 -0
  13. oneground-0.1.0rc1/oneground/calibrate/history.py +390 -0
  14. oneground-0.1.0rc1/oneground/calibrate/layers.py +230 -0
  15. oneground-0.1.0rc1/oneground/calibrate/reference.py +144 -0
  16. oneground-0.1.0rc1/oneground/calibrate/test_calibrate.py +728 -0
  17. oneground-0.1.0rc1/oneground/capacity.py +285 -0
  18. oneground-0.1.0rc1/oneground/characterize.py +522 -0
  19. oneground-0.1.0rc1/oneground/cli.py +277 -0
  20. oneground-0.1.0rc1/oneground/cost/__init__.py +233 -0
  21. oneground-0.1.0rc1/oneground/cost/test_cost.py +218 -0
  22. oneground-0.1.0rc1/oneground/embed/__init__.py +56 -0
  23. oneground-0.1.0rc1/oneground/environment.py +349 -0
  24. oneground-0.1.0rc1/oneground/fixture/__init__.py +16 -0
  25. oneground-0.1.0rc1/oneground/fixture/build.py +289 -0
  26. oneground-0.1.0rc1/oneground/fixture/reference.py +65 -0
  27. oneground-0.1.0rc1/oneground/fixture/test_verify.py +659 -0
  28. oneground-0.1.0rc1/oneground/fixture/verify.py +744 -0
  29. oneground-0.1.0rc1/oneground/fixture_verify.py +27 -0
  30. oneground-0.1.0rc1/oneground/intake/__init__.py +257 -0
  31. oneground-0.1.0rc1/oneground/intake/test_tier2.py +343 -0
  32. oneground-0.1.0rc1/oneground/measures/__init__.py +30 -0
  33. oneground-0.1.0rc1/oneground/measures/ambiguity.py +19 -0
  34. oneground-0.1.0rc1/oneground/measures/crispness.py +47 -0
  35. oneground-0.1.0rc1/oneground/measures/drift.py +82 -0
  36. oneground-0.1.0rc1/oneground/measures/lid.py +31 -0
  37. oneground-0.1.0rc1/oneground/measures/skew.py +17 -0
  38. oneground-0.1.0rc1/oneground/measures/test_measures.py +179 -0
  39. oneground-0.1.0rc1/oneground/models/__init__.py +49 -0
  40. oneground-0.1.0rc1/oneground/models/base.py +328 -0
  41. oneground-0.1.0rc1/oneground/models/hash_sharded/__init__.py +3 -0
  42. oneground-0.1.0rc1/oneground/models/hash_sharded/model.py +173 -0
  43. oneground-0.1.0rc1/oneground/models/semantic_sharded/__init__.py +3 -0
  44. oneground-0.1.0rc1/oneground/models/semantic_sharded/model.py +217 -0
  45. oneground-0.1.0rc1/oneground/models/single_node_hnsw/__init__.py +3 -0
  46. oneground-0.1.0rc1/oneground/models/single_node_hnsw/model.py +129 -0
  47. oneground-0.1.0rc1/oneground/models/test_conformance.py +368 -0
  48. oneground-0.1.0rc1/oneground/pod/__init__.py +60 -0
  49. oneground-0.1.0rc1/oneground/pod/__main__.py +7 -0
  50. oneground-0.1.0rc1/oneground/pod/api.py +394 -0
  51. oneground-0.1.0rc1/oneground/pod/cli.py +1078 -0
  52. oneground-0.1.0rc1/oneground/pod/confirm.py +139 -0
  53. oneground-0.1.0rc1/oneground/pod/plan.py +256 -0
  54. oneground-0.1.0rc1/oneground/pod/session.py +220 -0
  55. oneground-0.1.0rc1/oneground/pod/sshx.py +439 -0
  56. oneground-0.1.0rc1/oneground/pod/state.py +167 -0
  57. oneground-0.1.0rc1/oneground/pod/test_pod.py +2082 -0
  58. oneground-0.1.0rc1/oneground/receipts/__init__.py +170 -0
  59. oneground-0.1.0rc1/oneground/report/__init__.py +943 -0
  60. oneground-0.1.0rc1/oneground/report/html.py +464 -0
  61. oneground-0.1.0rc1/oneground/report/test_end_to_end.py +276 -0
  62. oneground-0.1.0rc1/oneground/report/test_verdict.py +650 -0
  63. oneground-0.1.0rc1/oneground/report/verdict.py +743 -0
  64. oneground-0.1.0rc1/oneground/sample/__init__.py +26 -0
  65. oneground-0.1.0rc1/oneground/sample/arxiv.py +128 -0
  66. oneground-0.1.0rc1/oneground/sample/loaders.py +195 -0
  67. oneground-0.1.0rc1/oneground/simulate/__init__.py +533 -0
  68. oneground-0.1.0rc1/oneground/simulate/test_simulate.py +269 -0
  69. oneground-0.1.0rc1/oneground/test_analogy.py +245 -0
  70. oneground-0.1.0rc1/oneground/test_capacity.py +184 -0
  71. oneground-0.1.0rc1/oneground/test_characterize.py +286 -0
  72. oneground-0.1.0rc1/oneground/test_cli.py +217 -0
  73. oneground-0.1.0rc1/oneground/test_environment.py +431 -0
  74. oneground-0.1.0rc1/oneground/truth/__init__.py +24 -0
  75. oneground-0.1.0rc1/oneground/verify/__init__.py +752 -0
  76. oneground-0.1.0rc1/oneground/verify/load.py +312 -0
  77. oneground-0.1.0rc1/oneground/verify/runpod.py +303 -0
  78. oneground-0.1.0rc1/oneground/verify/test_matched.py +1226 -0
  79. oneground-0.1.0rc1/oneground/verify/test_verify.py +322 -0
  80. oneground-0.1.0rc1/oneground.egg-info/PKG-INFO +244 -0
  81. oneground-0.1.0rc1/oneground.egg-info/SOURCES.txt +85 -0
  82. oneground-0.1.0rc1/oneground.egg-info/dependency_links.txt +1 -0
  83. oneground-0.1.0rc1/oneground.egg-info/entry_points.txt +2 -0
  84. oneground-0.1.0rc1/oneground.egg-info/requires.txt +28 -0
  85. oneground-0.1.0rc1/oneground.egg-info/top_level.txt +1 -0
  86. oneground-0.1.0rc1/pyproject.toml +92 -0
  87. oneground-0.1.0rc1/setup.cfg +4 -0
@@ -0,0 +1,244 @@
1
+ Metadata-Version: 2.4
2
+ Name: oneground
3
+ Version: 0.1.0rc1
4
+ Summary: Measure a retrieval architecture decision on your own vectors, with the receipt attached.
5
+ Author: oneproof
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/oneproof/oneground
8
+ Project-URL: Source, https://github.com/oneproof/oneground
9
+ Project-URL: Issues, https://github.com/oneproof/oneground/issues
10
+ Keywords: vector-search,retrieval,benchmarking,rag,embeddings
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: License :: OSI Approved :: Apache Software License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
20
+ Classifier: Topic :: Software Development :: Testing
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.12
23
+ Description-Content-Type: text/markdown
24
+ Requires-Dist: numpy==2.5.3
25
+ Requires-Dist: faiss-cpu==1.15.0
26
+ Requires-Dist: scikit-learn==1.9.0
27
+ Requires-Dist: pyyaml==6.0.3
28
+ Requires-Dist: zstandard==0.25.0
29
+ Provides-Extra: embed
30
+ Requires-Dist: sentence-transformers==6.0.1; extra == "embed"
31
+ Requires-Dist: torch==2.14.0; extra == "embed"
32
+ Provides-Extra: view
33
+ Requires-Dist: umap-learn==0.5.12; extra == "view"
34
+ Requires-Dist: pyarrow==25.0.1; extra == "view"
35
+ Requires-Dist: matplotlib==3.11.1; extra == "view"
36
+ Provides-Extra: qdrant
37
+ Requires-Dist: qdrant-client==1.19.0; extra == "qdrant"
38
+ Requires-Dist: pywin32==312; sys_platform == "win32" and extra == "qdrant"
39
+ Provides-Extra: pod
40
+ Provides-Extra: calibrate
41
+ Requires-Dist: h5py==3.16.0; extra == "calibrate"
42
+ Provides-Extra: test
43
+ Requires-Dist: pytest==9.1.1; extra == "test"
44
+
45
+ # oneground
46
+
47
+ ![The ground view: 150,000 arXiv abstracts, coloured by how many regions each vector must be copied into](docs/img/ground_thumbnail.png)
48
+
49
+ Choosing a vector store, an index, and a sharding scheme is usually decided by
50
+ vendor leaderboards, a blog post, and whatever the last team did. oneground
51
+ measures that decision on **your own embeddings**, against exact k-NN ground
52
+ truth, and writes down every number with the seeds and digests needed to
53
+ re-derive it. It is local-first and offline: your vectors never leave the
54
+ machine, and there is no telemetry.
55
+
56
+ Part of the [oneproof](https://oneproof.dev) suite — the *Choose* door.
57
+
58
+ ---
59
+
60
+ ## Install
61
+
62
+ ```bash
63
+ pip install oneground
64
+ oneground --help
65
+ ```
66
+
67
+ Python 3.12 or newer. Extras, each named for the capability it unlocks:
68
+
69
+ | extra | for |
70
+ | --- | --- |
71
+ | `[embed]` | handing oneground text instead of vectors |
72
+ | `[view]` | the ground view and the fixture builder's projection |
73
+ | `[qdrant]` | `oneground verify` against a real Qdrant |
74
+ | `[calibrate]` | reading the ANN-Benchmarks HDF5 |
75
+ | `[test]` | running the suite |
76
+
77
+ To work on oneground rather than with it:
78
+
79
+ ```bash
80
+ git clone https://github.com/oneproof/oneground && cd oneground
81
+ python -m venv .venv && . .venv/bin/activate # Windows: .venv\Scripts\activate
82
+ pip install -r requirements.txt && pip install -e .
83
+ ```
84
+
85
+ **Use that venv's interpreter explicitly.** Every command that writes a
86
+ canonical artifact refuses to run when your numpy, faiss-cpu or scikit-learn
87
+ differ from `requirements.txt`, and prints which. A measurement computed under
88
+ different libraries is not the measurement the pins describe. `--allow-unpinned`
89
+ proceeds and stamps the artifact `unpinned environment` so every reader of it
90
+ can see that.
91
+
92
+ ## Characterize your corpus
93
+
94
+ Copy [`requirements.example.yaml`](requirements.example.yaml) — it is the
95
+ schema by example — point it at your vectors, and run:
96
+
97
+ ```bash
98
+ oneground characterize requirements.yaml
99
+ ```
100
+
101
+ The minimum it needs is a sample of vectors, some queries, and a seed:
102
+
103
+ ```yaml
104
+ oneground: 1
105
+ run:
106
+ name: support-tickets-2026q3
107
+ seed: 20260910
108
+ workdir: ./runs/support-tickets-2026q3
109
+ corpus:
110
+ sample:
111
+ kind: receipt
112
+ vectors: {path: ./data/sample_vectors.npy}
113
+ queries: {path: ./data/queries.npy, count_min: 50}
114
+ target_sample_size: 20000
115
+ ```
116
+
117
+ You get five numbers about the shape of your corpus:
118
+
119
+ | measure | what it answers |
120
+ |---|---|
121
+ | `intrinsic_dimensionality` | how many dimensions the data actually occupies, against how many the embedding declares |
122
+ | `boundary_crispness` | do vectors sit clearly inside one region, or on a boundary between two |
123
+ | `ambiguous_query_rate` | what share of queries cannot be routed confidently to a single shard |
124
+ | `skew_top10_share` | how much of the corpus lands in the ten largest of 256 regions |
125
+ | `drift` | what a partition trained on the past does to queries from the future |
126
+
127
+ and a directory of receipts beside them:
128
+
129
+ ```
130
+ runs/support-tickets-2026q3/
131
+ characterization.json the measurements (receipt)
132
+ sample_ids.json which rows were measured (receipt)
133
+ queries_ids.json which queries were used (receipt)
134
+ build_info.json versions, device, input digests (declared)
135
+ MANIFEST.sha256 a digest for each of the above
136
+ ```
137
+
138
+ **Receipt** means re-derivable: same inputs and seed, same bytes.
139
+ **Declared** means recorded rather than re-derivable — timestamps, library
140
+ versions, the host. The two are never blurred, and anything that could not be
141
+ measured is reported as `couldnt_check` with the reason, never filled in from
142
+ a guess. Ask for drift without a timestamp column and you get
143
+ `"couldnt_check: no timestamp_field"`, not a number.
144
+
145
+ ## Check your installation against a public fixture
146
+
147
+ `fixtures/arxiv-150k` is 150,000 arXiv abstracts (CC0) embedded with pinned
148
+ weights, with exact ground truth and published values. It exists so a stranger
149
+ can confirm an installation reproduces the numbers this project publishes — it
150
+ is not a leaderboard.
151
+
152
+ ```bash
153
+ oneground fixture verify arxiv-smoke
154
+ ```
155
+
156
+ The picture at the top is that fixture. Almost all of it is one colour:
157
+ **84% of the vectors sit close enough to four different regions that they must
158
+ be copied into all of them.** The categories separate visibly, which is why
159
+ semantic sharding looks obviously right — and on this corpus it loses, 0.932
160
+ recall at 3.7x storage against 0.997 at 1x for a single flat index. That
161
+ result is why the tool exists.
162
+
163
+ ---
164
+
165
+ ## How this tool is checked against numbers that are not its own
166
+
167
+ Every recommendation is only as good as the instrument behind it, so the
168
+ instrument is measured too — against published ANN-Benchmarks results on a
169
+ corpus and a ground truth oneground did not produce, and against real engines
170
+ on your own sample.
171
+
172
+ ```bash
173
+ oneground calibrate show # the history, and the latest outcome per check
174
+ ```
175
+
176
+ [docs/VALIDATION.md](docs/VALIDATION.md) is the whole picture: the three
177
+ layers, what runs weekly, and — the part worth reading first — which measures
178
+ are **validated against a reference** and which are still **predictions with
179
+ no external counterpart** (boundary crispness, ambiguous query rate, drift).
180
+ A `contradicted` result blocks a release; `couldn't-check` never does, and is
181
+ never rounded up.
182
+
183
+ ---
184
+
185
+ ## What exists today
186
+
187
+ Everything in this list is in `0.1.0-preview` and has been run end to end.
188
+
189
+ - **`oneground characterize`** — the five measures on your own sample, with
190
+ receipts. Vectors (`.npy`, `.parquet`) or text (`.jsonl`) plus a pinned
191
+ model. Tier 2 (`corpus.declared`) describes a corpus you have not embedded
192
+ yet; it produces a fixture analogy and capacity arithmetic and **never a
193
+ verdict**. See [docs/INTAKE.md](docs/INTAKE.md).
194
+ - **`oneground simulate`** — `single_node_hnsw`, `hash_sharded` and
195
+ `semantic_sharded` as runnable families over your sample, against exact
196
+ k-NN, with loss decomposed into partitioning vs. index.
197
+ - **`oneground verify`** — a real engine on the same sample. One adapter today
198
+ (Qdrant), locally or in a matched environment on a pod where latency under
199
+ load is attributable. See [docs/VERIFY.md](docs/VERIFY.md).
200
+ - **`oneground report`** — the trade-off surface, three outcomes per option
201
+ (meets / fails / couldn't-check), a decision log naming every source field,
202
+ and a deployable manifest.
203
+ - **`oneground fixture verify`** — recompute a fixture's digests **and its
204
+ published values** and report verified / contradicted / couldn't-check for
205
+ each.
206
+ - **`oneground fixture build`** — rebuild a fixture from its spec and seeds.
207
+ - **`oneground pod`** — run a session on rented hardware, with the money
208
+ boundary documented in [docs/POD.md](docs/POD.md).
209
+ - **`oneground calibrate`** — measure this installation against published
210
+ ANN-Benchmarks values and against real engines, and keep the history. See
211
+ [docs/VALIDATION.md](docs/VALIDATION.md).
212
+ - **The arxiv-150k fixture**, `status: verified`: every digest and every
213
+ published value reproduced on a second machine and a second operating
214
+ system, under the same pinned versions.
215
+
216
+ ## What is planned
217
+
218
+ Nothing below is implemented, and oneground will not pretend otherwise.
219
+
220
+ - **A second engine adapter** — pgvector. The `VectorEngine` protocol and its
221
+ conformance suite exist and are the contribution gate; no second adapter
222
+ has been written. See [CONTRIBUTING.md](CONTRIBUTING.md).
223
+ - **`qps_max`** — the highest offered rate an engine sustains before latency
224
+ or errors break. Today's `qps` verdict answers a different question, whether
225
+ the engine held the rate it *was* offered, and the two must never share a
226
+ row. Documented and unimplemented in `oneground/report/verdict.py`.
227
+ - **A second corpus for the fixture analogy** — Tier 2 matches a declared
228
+ corpus against fixtures that publish an `analogy:` block, and only
229
+ arxiv-150k does. A support-ticket corpus therefore correctly gets *no*
230
+ analogy today.
231
+ - **The lab** — the ground view and query traces as interactive renderers over
232
+ the same simulator state the numbers come from.
233
+
234
+ The full plan, including what would make the project change course, is in
235
+ [docs/CHARTER.md](docs/CHARTER.md).
236
+
237
+ ## Principles
238
+
239
+ - Your data or nothing. No recommendation from a canned corpus.
240
+ - No engine of our own, no favourite. Every engine behind one adapter.
241
+ - Receipts (re-derivable) and declarations (bytes frozen), never blurred.
242
+ - `couldnt_check` is never rounded up to a verdict.
243
+ - Runs on your machine. Your vectors never leave it. No telemetry.
244
+ - Nothing labelled as capability that is only planned.
@@ -0,0 +1,200 @@
1
+ # oneground
2
+
3
+ ![The ground view: 150,000 arXiv abstracts, coloured by how many regions each vector must be copied into](docs/img/ground_thumbnail.png)
4
+
5
+ Choosing a vector store, an index, and a sharding scheme is usually decided by
6
+ vendor leaderboards, a blog post, and whatever the last team did. oneground
7
+ measures that decision on **your own embeddings**, against exact k-NN ground
8
+ truth, and writes down every number with the seeds and digests needed to
9
+ re-derive it. It is local-first and offline: your vectors never leave the
10
+ machine, and there is no telemetry.
11
+
12
+ Part of the [oneproof](https://oneproof.dev) suite — the *Choose* door.
13
+
14
+ ---
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ pip install oneground
20
+ oneground --help
21
+ ```
22
+
23
+ Python 3.12 or newer. Extras, each named for the capability it unlocks:
24
+
25
+ | extra | for |
26
+ | --- | --- |
27
+ | `[embed]` | handing oneground text instead of vectors |
28
+ | `[view]` | the ground view and the fixture builder's projection |
29
+ | `[qdrant]` | `oneground verify` against a real Qdrant |
30
+ | `[calibrate]` | reading the ANN-Benchmarks HDF5 |
31
+ | `[test]` | running the suite |
32
+
33
+ To work on oneground rather than with it:
34
+
35
+ ```bash
36
+ git clone https://github.com/oneproof/oneground && cd oneground
37
+ python -m venv .venv && . .venv/bin/activate # Windows: .venv\Scripts\activate
38
+ pip install -r requirements.txt && pip install -e .
39
+ ```
40
+
41
+ **Use that venv's interpreter explicitly.** Every command that writes a
42
+ canonical artifact refuses to run when your numpy, faiss-cpu or scikit-learn
43
+ differ from `requirements.txt`, and prints which. A measurement computed under
44
+ different libraries is not the measurement the pins describe. `--allow-unpinned`
45
+ proceeds and stamps the artifact `unpinned environment` so every reader of it
46
+ can see that.
47
+
48
+ ## Characterize your corpus
49
+
50
+ Copy [`requirements.example.yaml`](requirements.example.yaml) — it is the
51
+ schema by example — point it at your vectors, and run:
52
+
53
+ ```bash
54
+ oneground characterize requirements.yaml
55
+ ```
56
+
57
+ The minimum it needs is a sample of vectors, some queries, and a seed:
58
+
59
+ ```yaml
60
+ oneground: 1
61
+ run:
62
+ name: support-tickets-2026q3
63
+ seed: 20260910
64
+ workdir: ./runs/support-tickets-2026q3
65
+ corpus:
66
+ sample:
67
+ kind: receipt
68
+ vectors: {path: ./data/sample_vectors.npy}
69
+ queries: {path: ./data/queries.npy, count_min: 50}
70
+ target_sample_size: 20000
71
+ ```
72
+
73
+ You get five numbers about the shape of your corpus:
74
+
75
+ | measure | what it answers |
76
+ |---|---|
77
+ | `intrinsic_dimensionality` | how many dimensions the data actually occupies, against how many the embedding declares |
78
+ | `boundary_crispness` | do vectors sit clearly inside one region, or on a boundary between two |
79
+ | `ambiguous_query_rate` | what share of queries cannot be routed confidently to a single shard |
80
+ | `skew_top10_share` | how much of the corpus lands in the ten largest of 256 regions |
81
+ | `drift` | what a partition trained on the past does to queries from the future |
82
+
83
+ and a directory of receipts beside them:
84
+
85
+ ```
86
+ runs/support-tickets-2026q3/
87
+ characterization.json the measurements (receipt)
88
+ sample_ids.json which rows were measured (receipt)
89
+ queries_ids.json which queries were used (receipt)
90
+ build_info.json versions, device, input digests (declared)
91
+ MANIFEST.sha256 a digest for each of the above
92
+ ```
93
+
94
+ **Receipt** means re-derivable: same inputs and seed, same bytes.
95
+ **Declared** means recorded rather than re-derivable — timestamps, library
96
+ versions, the host. The two are never blurred, and anything that could not be
97
+ measured is reported as `couldnt_check` with the reason, never filled in from
98
+ a guess. Ask for drift without a timestamp column and you get
99
+ `"couldnt_check: no timestamp_field"`, not a number.
100
+
101
+ ## Check your installation against a public fixture
102
+
103
+ `fixtures/arxiv-150k` is 150,000 arXiv abstracts (CC0) embedded with pinned
104
+ weights, with exact ground truth and published values. It exists so a stranger
105
+ can confirm an installation reproduces the numbers this project publishes — it
106
+ is not a leaderboard.
107
+
108
+ ```bash
109
+ oneground fixture verify arxiv-smoke
110
+ ```
111
+
112
+ The picture at the top is that fixture. Almost all of it is one colour:
113
+ **84% of the vectors sit close enough to four different regions that they must
114
+ be copied into all of them.** The categories separate visibly, which is why
115
+ semantic sharding looks obviously right — and on this corpus it loses, 0.932
116
+ recall at 3.7x storage against 0.997 at 1x for a single flat index. That
117
+ result is why the tool exists.
118
+
119
+ ---
120
+
121
+ ## How this tool is checked against numbers that are not its own
122
+
123
+ Every recommendation is only as good as the instrument behind it, so the
124
+ instrument is measured too — against published ANN-Benchmarks results on a
125
+ corpus and a ground truth oneground did not produce, and against real engines
126
+ on your own sample.
127
+
128
+ ```bash
129
+ oneground calibrate show # the history, and the latest outcome per check
130
+ ```
131
+
132
+ [docs/VALIDATION.md](docs/VALIDATION.md) is the whole picture: the three
133
+ layers, what runs weekly, and — the part worth reading first — which measures
134
+ are **validated against a reference** and which are still **predictions with
135
+ no external counterpart** (boundary crispness, ambiguous query rate, drift).
136
+ A `contradicted` result blocks a release; `couldn't-check` never does, and is
137
+ never rounded up.
138
+
139
+ ---
140
+
141
+ ## What exists today
142
+
143
+ Everything in this list is in `0.1.0-preview` and has been run end to end.
144
+
145
+ - **`oneground characterize`** — the five measures on your own sample, with
146
+ receipts. Vectors (`.npy`, `.parquet`) or text (`.jsonl`) plus a pinned
147
+ model. Tier 2 (`corpus.declared`) describes a corpus you have not embedded
148
+ yet; it produces a fixture analogy and capacity arithmetic and **never a
149
+ verdict**. See [docs/INTAKE.md](docs/INTAKE.md).
150
+ - **`oneground simulate`** — `single_node_hnsw`, `hash_sharded` and
151
+ `semantic_sharded` as runnable families over your sample, against exact
152
+ k-NN, with loss decomposed into partitioning vs. index.
153
+ - **`oneground verify`** — a real engine on the same sample. One adapter today
154
+ (Qdrant), locally or in a matched environment on a pod where latency under
155
+ load is attributable. See [docs/VERIFY.md](docs/VERIFY.md).
156
+ - **`oneground report`** — the trade-off surface, three outcomes per option
157
+ (meets / fails / couldn't-check), a decision log naming every source field,
158
+ and a deployable manifest.
159
+ - **`oneground fixture verify`** — recompute a fixture's digests **and its
160
+ published values** and report verified / contradicted / couldn't-check for
161
+ each.
162
+ - **`oneground fixture build`** — rebuild a fixture from its spec and seeds.
163
+ - **`oneground pod`** — run a session on rented hardware, with the money
164
+ boundary documented in [docs/POD.md](docs/POD.md).
165
+ - **`oneground calibrate`** — measure this installation against published
166
+ ANN-Benchmarks values and against real engines, and keep the history. See
167
+ [docs/VALIDATION.md](docs/VALIDATION.md).
168
+ - **The arxiv-150k fixture**, `status: verified`: every digest and every
169
+ published value reproduced on a second machine and a second operating
170
+ system, under the same pinned versions.
171
+
172
+ ## What is planned
173
+
174
+ Nothing below is implemented, and oneground will not pretend otherwise.
175
+
176
+ - **A second engine adapter** — pgvector. The `VectorEngine` protocol and its
177
+ conformance suite exist and are the contribution gate; no second adapter
178
+ has been written. See [CONTRIBUTING.md](CONTRIBUTING.md).
179
+ - **`qps_max`** — the highest offered rate an engine sustains before latency
180
+ or errors break. Today's `qps` verdict answers a different question, whether
181
+ the engine held the rate it *was* offered, and the two must never share a
182
+ row. Documented and unimplemented in `oneground/report/verdict.py`.
183
+ - **A second corpus for the fixture analogy** — Tier 2 matches a declared
184
+ corpus against fixtures that publish an `analogy:` block, and only
185
+ arxiv-150k does. A support-ticket corpus therefore correctly gets *no*
186
+ analogy today.
187
+ - **The lab** — the ground view and query traces as interactive renderers over
188
+ the same simulator state the numbers come from.
189
+
190
+ The full plan, including what would make the project change course, is in
191
+ [docs/CHARTER.md](docs/CHARTER.md).
192
+
193
+ ## Principles
194
+
195
+ - Your data or nothing. No recommendation from a canned corpus.
196
+ - No engine of our own, no favourite. Every engine behind one adapter.
197
+ - Receipts (re-derivable) and declarations (bytes frozen), never blurred.
198
+ - `couldnt_check` is never rounded up to a verdict.
199
+ - Runs on your machine. Your vectors never leave it. No telemetry.
200
+ - Nothing labelled as capability that is only planned.
@@ -0,0 +1,18 @@
1
+ """oneground — characterize, simulate, verify, report.
2
+
3
+ The "Choose" door of the oneproof suite: measure a retrieval architecture
4
+ decision on your own vectors, against exact k-NN ground truth, and keep the
5
+ receipt.
6
+
7
+ What exists today is `characterize` (the five measures on your own sample),
8
+ `fixture verify` (does this installation reproduce the published values), and
9
+ `pod` (run a session on rented hardware). Everything else in the charter is
10
+ planned, and this package says so rather than implying otherwise.
11
+ """
12
+
13
+ # PEP 440 for the resolver, the display name for humans. `0.1.0rc1` is what
14
+ # pip compares and what the wheel is named; "0.1.0-preview" is what the
15
+ # release page, the teaser and `oneground --version` say. Neither is derived
16
+ # from the other, so neither can drift into a shape the other cannot read.
17
+ __version__ = "0.1.0rc1"
18
+ __display_version__ = "0.1.0-preview"
@@ -0,0 +1,28 @@
1
+ """Engines, each behind the one `VectorEngine` protocol.
2
+
3
+ stub in-process exact search; what CI runs against
4
+ qdrant the official qdrant-client
5
+
6
+ No engine of our own, no favourite, no sponsored defaults. An adapter earns
7
+ its place by passing `conformance.py`, and nothing here picks an engine for
8
+ the user.
9
+
10
+ See `docs/ADAPTERS.md` for the protocol and the contribution gate.
11
+ """
12
+
13
+ from . import base, stub
14
+ from .base import (AdapterError, Candidates, EngineFacts, NotConnected,
15
+ UnknownEngine, UpsertStats, VectorEngine, engines,
16
+ get, managed_namespace, namespace_for, register)
17
+
18
+ # Qdrant is imported lazily: the client is an optional dependency, and a
19
+ # machine with no qdrant-client must still be able to run the stub suite.
20
+ try: # pragma: no cover
21
+ from . import qdrant # noqa: F401
22
+ except Exception: # noqa: BLE001
23
+ qdrant = None
24
+
25
+ __all__ = ["AdapterError", "Candidates", "EngineFacts", "NotConnected",
26
+ "UnknownEngine", "UpsertStats", "VectorEngine", "base", "engines",
27
+ "get", "managed_namespace", "namespace_for", "qdrant", "register",
28
+ "stub"]