decision-toolkit 0.4.1__tar.gz → 0.4.2__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 (99) hide show
  1. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/CHANGELOG.md +9 -1
  2. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/CONTRIBUTING.md +5 -3
  3. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/PKG-INFO +19 -31
  4. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/README.md +18 -30
  5. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/docs/BENCH.md +1 -1
  6. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/docs/CLI.md +4 -5
  7. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/docs/CORE.md +12 -13
  8. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/docs/OPERATIONS.md +2 -2
  9. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/docs/RELEASE.md +8 -7
  10. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/docs/REST.md +8 -8
  11. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/docs/VARIANTS.md +3 -3
  12. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/docs/index.md +1 -2
  13. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/docs/models/README.md +5 -16
  14. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/docs/models/gliner2.5-decide.md +0 -1
  15. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/docs/models/gliner2.5-multi.md +0 -1
  16. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/docs/models/julia-1.md +0 -1
  17. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/docs/models/laya-multilingual.md +0 -1
  18. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/docs/models/laya.md +0 -1
  19. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/docs/models/open-jev-deberta-v3-large.md +0 -1
  20. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/docs/models/opendecider-nano.md +0 -1
  21. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/docs/models/strands-decider-2b.md +0 -1
  22. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/pyproject.toml +1 -1
  23. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/__init__.py +1 -1
  24. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/cli.py +1 -1
  25. decision_toolkit-0.4.2/tests/test_help_examples.py +64 -0
  26. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/uv.lock +1 -1
  27. decision_toolkit-0.4.1/docs/CATALOG_PROPOSAL.md +0 -122
  28. decision_toolkit-0.4.1/docs/ROADMAP.md +0 -33
  29. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/.github/workflows/ci.yml +0 -0
  30. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/.github/workflows/docs.yml +0 -0
  31. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/.github/workflows/release.yml +0 -0
  32. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/.gitignore +0 -0
  33. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/LICENSE +0 -0
  34. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/SECURITY.md +0 -0
  35. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/THIRD_PARTY_NOTICES.md +0 -0
  36. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/bench/README.md +0 -0
  37. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/bench/__init__.py +0 -0
  38. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/bench/load.py +0 -0
  39. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/bench/results/2026-10-20-calibration.json +0 -0
  40. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/bench/results/2026-10-20-load.json +0 -0
  41. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/bench/results/2026-10-20-smoke.json +0 -0
  42. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/bench/run.py +0 -0
  43. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/bench/suites/calibration.jsonl +0 -0
  44. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/bench/suites/smoke.jsonl +0 -0
  45. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/docs/EXAMPLES.md +0 -0
  46. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/__main__.py +0 -0
  47. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/adapters/__init__.py +0 -0
  48. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/adapters/base.py +0 -0
  49. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/adapters/gliner2.py +0 -0
  50. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/adapters/gliner2_decide.py +0 -0
  51. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/adapters/julia.py +0 -0
  52. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/adapters/laya.py +0 -0
  53. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/adapters/opendecider.py +0 -0
  54. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/adapters/openjev.py +0 -0
  55. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/adapters/strands_decider.py +0 -0
  56. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/calibration.py +0 -0
  57. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/catalog.py +0 -0
  58. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/config.py +0 -0
  59. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/contracts/__init__.py +0 -0
  60. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/contracts/common.py +0 -0
  61. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/contracts/mapping.py +0 -0
  62. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/contracts/openai_decisions_beta.py +0 -0
  63. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/contracts/systemone_v1.py +0 -0
  64. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/decision_model.py +0 -0
  65. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/engine/__init__.py +0 -0
  66. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/errors.py +0 -0
  67. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/limits.py +0 -0
  68. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/metrics.py +0 -0
  69. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/models.py +0 -0
  70. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/observability.py +0 -0
  71. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/py.typed +0 -0
  72. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/registry.py +0 -0
  73. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/results.py +0 -0
  74. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/schema.py +0 -0
  75. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/server.py +0 -0
  76. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/src/decision_toolkit/tracing.py +0 -0
  77. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/__init__.py +0 -0
  78. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/conftest.py +0 -0
  79. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_adapters_gliner2.py +0 -0
  80. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_adapters_gliner2_decide.py +0 -0
  81. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_adapters_julia.py +0 -0
  82. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_adapters_laya.py +0 -0
  83. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_adapters_opendecider.py +0 -0
  84. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_adapters_openjev.py +0 -0
  85. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_adapters_strands.py +0 -0
  86. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_bench.py +0 -0
  87. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_catalog.py +0 -0
  88. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_cli.py +0 -0
  89. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_config.py +0 -0
  90. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_contracts_conformance.py +0 -0
  91. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_core_phase1.py +0 -0
  92. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_decision_model.py +0 -0
  93. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_fuzz_rest.py +0 -0
  94. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_integration_gliner2.py +0 -0
  95. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_models.py +0 -0
  96. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_operations.py +0 -0
  97. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_results.py +0 -0
  98. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_schema.py +0 -0
  99. {decision_toolkit-0.4.1 → decision_toolkit-0.4.2}/tests/test_server.py +0 -0
@@ -1,8 +1,15 @@
1
1
  # Changelog
2
2
 
3
- All notable changes to this project are documented here. Version `0.4.1` is
3
+ All notable changes to this project are documented here. Version `0.4.2` is
4
4
  published on PyPI.
5
5
 
6
+ ## [0.4.2] — 2026-10-21
7
+
8
+ Documentation cleanup: removed internal project language (`m0`, phase numbers,
9
+ waitlist), removed the public catalog proposal and roadmap pages, and rewrote
10
+ the model-card index for users. Every model card now includes library, CLI and
11
+ REST snippets for every variant. No runtime changes.
12
+
6
13
  ## [0.4.1] — 2026-10-21
7
14
 
8
15
  Catalog presentation patch: every variant now carries its REST alias
@@ -216,6 +223,7 @@ README correction. No code or model behavior changed.
216
223
  - Typed `DecisionModel` API with lifecycle, batching, async, usage, warnings,
217
224
  normalized confidence, capabilities, structured events and atomic model store.
218
225
 
226
+ [0.4.2]: https://pypi.org/project/decision-toolkit/0.4.2/
219
227
  [0.4.1]: https://pypi.org/project/decision-toolkit/0.4.1/
220
228
  [0.4.0]: https://pypi.org/project/decision-toolkit/0.4.0/
221
229
  [0.3.1]: https://pypi.org/project/decision-toolkit/0.3.1/
@@ -76,9 +76,11 @@ uv run dtk --version
76
76
  uv run pip-audit # dependency scan (CI runs this)
77
77
  ```
78
78
 
79
- CI runs these on Python 3.12 and 3.13, plus `pip-audit`. The tag-triggered
80
- release workflow builds and publishes the wheel with uv; see
81
- [RELEASE.md](docs/RELEASE.md). For rate limits, metrics, tracing and the load
79
+ CI runs these on Python 3.12 and 3.13, plus `pip-audit`. `tests/test_help_examples.py`
80
+ parses every example printed by `dtk --help` and checks referenced catalog
81
+ models/variants; run the full examples against a populated cache before a
82
+ release. The tag-triggered release workflow builds and publishes the wheel with
83
+ uv; see [RELEASE.md](docs/RELEASE.md). For rate limits, metrics, tracing and the load
82
84
  probe see [OPERATIONS.md](docs/OPERATIONS.md).
83
85
 
84
86
  ## Commits
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: decision-toolkit
3
- Version: 0.4.1
3
+ Version: 0.4.2
4
4
  Summary: Local-first toolkit for open-weights decision models: one ONNX engine, one adapter per model contract, typed choice/yes-no/score decisions with probabilities on CPU.
5
5
  Project-URL: Homepage, https://github.com/gia-uh/decision-toolkit
6
6
  Project-URL: Repository, https://github.com/gia-uh/decision-toolkit
@@ -59,7 +59,7 @@ and CLI. `dtk --help` and every subcommand help also include runnable examples.
59
59
  ## Installation
60
60
 
61
61
  ```bash
62
- uv pip install decision-toolkit # library + CLI (0.4.1 on PyPI)
62
+ uv pip install decision-toolkit # library + CLI (0.4.2 on PyPI)
63
63
  uv pip install "decision-toolkit[onnx]" # + onnxruntime, tokenizers (the model runtime)
64
64
  uv pip install "decision-toolkit[server]" # + REST server (FastAPI)
65
65
  ```
@@ -67,7 +67,7 @@ uv pip install "decision-toolkit[server]" # + REST server (FastAPI)
67
67
  The project is managed with [uv](https://docs.astral.sh/uv/) and ships a committed `uv.lock`. Published
68
68
  wheels remain compatible with `pip` for environments that do not use uv.
69
69
 
70
- PyPI: <https://pypi.org/project/decision-toolkit/0.4.1/>. See
70
+ PyPI: <https://pypi.org/project/decision-toolkit/0.4.2/>. See
71
71
  [docs/RELEASE.md](https://github.com/gia-uh/decision-toolkit/blob/main/docs/RELEASE.md)
72
72
  for the Trusted Publishing flow and clean-install checks.
73
73
 
@@ -135,7 +135,7 @@ decision.truncated, decision.warnings
135
135
  validated before inference (`box`/assets are rejected by text-only models).
136
136
  Custom adapters can be registered with `register_adapter`; local ONNX models
137
137
  can be opened with `DecisionModel.from_onnx(...)`. See
138
- [docs/CORE.md](https://github.com/gia-uh/decision-toolkit/blob/main/docs/CORE.md) for the full phase 1 contract, error taxonomy,
138
+ [docs/CORE.md](https://github.com/gia-uh/decision-toolkit/blob/main/docs/CORE.md) for the full API contract, error taxonomy,
139
139
  logging events and the expressiveness inventory.
140
140
 
141
141
  **2. As a CLI**
@@ -186,38 +186,26 @@ current text-only subset.
186
186
  See [docs/REST.md](https://github.com/gia-uh/decision-toolkit/blob/main/docs/REST.md) for the pinned contracts, limits, auth and
187
187
  the standard-evolution process.
188
188
 
189
- ## The catalog is curated
189
+ ## Models and variants
190
190
 
191
- The catalog is **ours**, not a mirror of HuggingFace. A model enters only when it
192
- is understood and verified:
191
+ The catalog lists models that are runnable with the toolkit today. Every entry
192
+ has a real ONNX export, verified files and measured behavior; nothing is listed
193
+ as a placeholder.
193
194
 
194
- 1. clean commercial license;
195
- 2. an adapter whose contract we can implement **from a real export**;
196
- 3. a real ONNX export on the Hub;
197
- 4. measured parity against the original on a fixed sample;
198
- 5. CPU-viable latency.
199
-
200
- Every variant points to files that exist. No placeholders, no speculative
201
- adapters (there is no generic "any ONNX" adapter).
202
-
203
- | id | adapter | status | variants (default *) |
195
+ | id | adapter | verification | variants (default *) |
204
196
  | --- | --- | --- | --- |
205
- | `gliner2.5-multi` | `gliner2` | **m0** — verified end-to-end (9/15, 353 ms) | `fp16`* (577 MB); `fp32` (1132 MB) |
206
- | `gliner2.5-decide` | `gliner2-decide` | **m0** — fused export verified (refund 0.944, 912 ms; English-only) | `q4f16`* (524 MB) |
207
- | `laya` | `laya` | **m0** — verified against torch (Δp ≤ 0.005) | `q8`* (528 MB) |
208
- | `julia-1` | `julia` | **m0** — verified: 100/100 argmax parity, 329 ms | `fp32`* (618 MB) |
209
- | `opendecider-nano` | `opendecider` | **m0** — official build; prompt ported from pinned code (530 ms) | `q8f16`* (469 MB); `fp16` (792 MB) |
210
- | `laya-multilingual` | `laya` | **m0** — fused ONNX; upstream parity (37 ms) | `fp16`* (682 MB); `fp32` (1326 MB) |
211
- | `open-jev-deberta-v3-large` | `open-jev` | **m0** — Open-Jev DeBERTa v3 large repro; 0.854 in-domain (241 ms) | `fp16`* (884 MB); `fp32` (1758 MB); `q4` (487 MB); `q4f16` (357 MB) |
212
- | `strands-decider-2b` | `strands-decider` | **m0** — reference fixture match (719 ms) | `q4f16`* (1114 MB); `q8` (1821 MB) |
197
+ | `gliner2.5-multi` | `gliner2` | verified end-to-end (9/15, 353 ms) | `fp16`* (577 MB); `fp32` (1132 MB) |
198
+ | `gliner2.5-decide` | `gliner2-decide` | fused export verified (refund 0.944, 912 ms; English-only) | `q4f16`* (524 MB) |
199
+ | `laya` | `laya` | verified against torch (Δp ≤ 0.005) | `q8`* (528 MB) |
200
+ | `julia-1` | `julia` | verified: 100/100 argmax parity, 329 ms | `fp32`* (618 MB) |
201
+ | `opendecider-nano` | `opendecider` | official build; prompt ported from pinned code (530 ms) | `q8f16`* (469 MB); `fp16` (792 MB) |
202
+ | `laya-multilingual` | `laya` | fused ONNX; upstream parity (37 ms) | `fp16`* (682 MB); `fp32` (1326 MB) |
203
+ | `open-jev-deberta-v3-large` | `open-jev` | Open-Jev DeBERTa v3 large reproduction; 0.854 in-domain (241 ms) | `fp16`* (884 MB); `fp32` (1758 MB); `q4` (487 MB); `q4f16` (357 MB) |
204
+ | `strands-decider-2b` | `strands-decider` | reference fixture match (719 ms) | `q4f16`* (1114 MB); `q8` (1821 MB) |
213
205
 
214
206
  Each variant has a REST alias in the form `id@variant`; `dtk models list` prints
215
207
  the alias next to every variant.
216
208
 
217
- **Only `m0` models are in the catalog.** Researched-but-unavailable models
218
- (planned, conversion pending, broken exports) are listed in
219
- [docs/ROADMAP.md](https://github.com/gia-uh/decision-toolkit/blob/main/docs/ROADMAP.md) and are not downloadable through the toolkit.
220
-
221
209
  Per-model cards with the contract, measured evidence and known limitations:
222
210
  [docs/models](https://github.com/gia-uh/decision-toolkit/tree/main/docs/models).
223
211
 
@@ -257,7 +245,7 @@ standard `model` field. The base id uses the server/persisted default. There is
257
245
  no `variant` field in the request body; `/v1/models` lists both the base model
258
246
  and every alias, and two aliases can be loaded concurrently.
259
247
 
260
- A variant becomes default only after passing the parity gate (top-1 ≥ 99%,
248
+ A variant becomes default only after passing the verification criteria (top-1 ≥ 99%,
261
249
  mean |Δp| ≤ 0.02, accuracy delta ≤ 1 pp against the fp32 build on a fixed
262
250
  sample) and measuring latency on CPU. Unverified conversions are not catalogued
263
251
  and never become a silent fallback. See [Variants and quantization](https://gia-uh.github.io/decision-toolkit/VARIANTS/)
@@ -303,7 +291,7 @@ See [CHANGELOG.md](https://github.com/gia-uh/decision-toolkit/blob/main/CHANGELO
303
291
 
304
292
  ## Custom ONNX (at your own risk)
305
293
 
306
- You can run any ONNX file with an adapter you trust — outside the curated
294
+ You can run any ONNX file with an adapter you trust — outside the
307
295
  catalog:
308
296
 
309
297
  ```python
@@ -21,7 +21,7 @@ and CLI. `dtk --help` and every subcommand help also include runnable examples.
21
21
  ## Installation
22
22
 
23
23
  ```bash
24
- uv pip install decision-toolkit # library + CLI (0.4.1 on PyPI)
24
+ uv pip install decision-toolkit # library + CLI (0.4.2 on PyPI)
25
25
  uv pip install "decision-toolkit[onnx]" # + onnxruntime, tokenizers (the model runtime)
26
26
  uv pip install "decision-toolkit[server]" # + REST server (FastAPI)
27
27
  ```
@@ -29,7 +29,7 @@ uv pip install "decision-toolkit[server]" # + REST server (FastAPI)
29
29
  The project is managed with [uv](https://docs.astral.sh/uv/) and ships a committed `uv.lock`. Published
30
30
  wheels remain compatible with `pip` for environments that do not use uv.
31
31
 
32
- PyPI: <https://pypi.org/project/decision-toolkit/0.4.1/>. See
32
+ PyPI: <https://pypi.org/project/decision-toolkit/0.4.2/>. See
33
33
  [docs/RELEASE.md](https://github.com/gia-uh/decision-toolkit/blob/main/docs/RELEASE.md)
34
34
  for the Trusted Publishing flow and clean-install checks.
35
35
 
@@ -97,7 +97,7 @@ decision.truncated, decision.warnings
97
97
  validated before inference (`box`/assets are rejected by text-only models).
98
98
  Custom adapters can be registered with `register_adapter`; local ONNX models
99
99
  can be opened with `DecisionModel.from_onnx(...)`. See
100
- [docs/CORE.md](https://github.com/gia-uh/decision-toolkit/blob/main/docs/CORE.md) for the full phase 1 contract, error taxonomy,
100
+ [docs/CORE.md](https://github.com/gia-uh/decision-toolkit/blob/main/docs/CORE.md) for the full API contract, error taxonomy,
101
101
  logging events and the expressiveness inventory.
102
102
 
103
103
  **2. As a CLI**
@@ -148,38 +148,26 @@ current text-only subset.
148
148
  See [docs/REST.md](https://github.com/gia-uh/decision-toolkit/blob/main/docs/REST.md) for the pinned contracts, limits, auth and
149
149
  the standard-evolution process.
150
150
 
151
- ## The catalog is curated
151
+ ## Models and variants
152
152
 
153
- The catalog is **ours**, not a mirror of HuggingFace. A model enters only when it
154
- is understood and verified:
153
+ The catalog lists models that are runnable with the toolkit today. Every entry
154
+ has a real ONNX export, verified files and measured behavior; nothing is listed
155
+ as a placeholder.
155
156
 
156
- 1. clean commercial license;
157
- 2. an adapter whose contract we can implement **from a real export**;
158
- 3. a real ONNX export on the Hub;
159
- 4. measured parity against the original on a fixed sample;
160
- 5. CPU-viable latency.
161
-
162
- Every variant points to files that exist. No placeholders, no speculative
163
- adapters (there is no generic "any ONNX" adapter).
164
-
165
- | id | adapter | status | variants (default *) |
157
+ | id | adapter | verification | variants (default *) |
166
158
  | --- | --- | --- | --- |
167
- | `gliner2.5-multi` | `gliner2` | **m0** — verified end-to-end (9/15, 353 ms) | `fp16`* (577 MB); `fp32` (1132 MB) |
168
- | `gliner2.5-decide` | `gliner2-decide` | **m0** — fused export verified (refund 0.944, 912 ms; English-only) | `q4f16`* (524 MB) |
169
- | `laya` | `laya` | **m0** — verified against torch (Δp ≤ 0.005) | `q8`* (528 MB) |
170
- | `julia-1` | `julia` | **m0** — verified: 100/100 argmax parity, 329 ms | `fp32`* (618 MB) |
171
- | `opendecider-nano` | `opendecider` | **m0** — official build; prompt ported from pinned code (530 ms) | `q8f16`* (469 MB); `fp16` (792 MB) |
172
- | `laya-multilingual` | `laya` | **m0** — fused ONNX; upstream parity (37 ms) | `fp16`* (682 MB); `fp32` (1326 MB) |
173
- | `open-jev-deberta-v3-large` | `open-jev` | **m0** — Open-Jev DeBERTa v3 large repro; 0.854 in-domain (241 ms) | `fp16`* (884 MB); `fp32` (1758 MB); `q4` (487 MB); `q4f16` (357 MB) |
174
- | `strands-decider-2b` | `strands-decider` | **m0** — reference fixture match (719 ms) | `q4f16`* (1114 MB); `q8` (1821 MB) |
159
+ | `gliner2.5-multi` | `gliner2` | verified end-to-end (9/15, 353 ms) | `fp16`* (577 MB); `fp32` (1132 MB) |
160
+ | `gliner2.5-decide` | `gliner2-decide` | fused export verified (refund 0.944, 912 ms; English-only) | `q4f16`* (524 MB) |
161
+ | `laya` | `laya` | verified against torch (Δp ≤ 0.005) | `q8`* (528 MB) |
162
+ | `julia-1` | `julia` | verified: 100/100 argmax parity, 329 ms | `fp32`* (618 MB) |
163
+ | `opendecider-nano` | `opendecider` | official build; prompt ported from pinned code (530 ms) | `q8f16`* (469 MB); `fp16` (792 MB) |
164
+ | `laya-multilingual` | `laya` | fused ONNX; upstream parity (37 ms) | `fp16`* (682 MB); `fp32` (1326 MB) |
165
+ | `open-jev-deberta-v3-large` | `open-jev` | Open-Jev DeBERTa v3 large reproduction; 0.854 in-domain (241 ms) | `fp16`* (884 MB); `fp32` (1758 MB); `q4` (487 MB); `q4f16` (357 MB) |
166
+ | `strands-decider-2b` | `strands-decider` | reference fixture match (719 ms) | `q4f16`* (1114 MB); `q8` (1821 MB) |
175
167
 
176
168
  Each variant has a REST alias in the form `id@variant`; `dtk models list` prints
177
169
  the alias next to every variant.
178
170
 
179
- **Only `m0` models are in the catalog.** Researched-but-unavailable models
180
- (planned, conversion pending, broken exports) are listed in
181
- [docs/ROADMAP.md](https://github.com/gia-uh/decision-toolkit/blob/main/docs/ROADMAP.md) and are not downloadable through the toolkit.
182
-
183
171
  Per-model cards with the contract, measured evidence and known limitations:
184
172
  [docs/models](https://github.com/gia-uh/decision-toolkit/tree/main/docs/models).
185
173
 
@@ -219,7 +207,7 @@ standard `model` field. The base id uses the server/persisted default. There is
219
207
  no `variant` field in the request body; `/v1/models` lists both the base model
220
208
  and every alias, and two aliases can be loaded concurrently.
221
209
 
222
- A variant becomes default only after passing the parity gate (top-1 ≥ 99%,
210
+ A variant becomes default only after passing the verification criteria (top-1 ≥ 99%,
223
211
  mean |Δp| ≤ 0.02, accuracy delta ≤ 1 pp against the fp32 build on a fixed
224
212
  sample) and measuring latency on CPU. Unverified conversions are not catalogued
225
213
  and never become a silent fallback. See [Variants and quantization](https://gia-uh.github.io/decision-toolkit/VARIANTS/)
@@ -265,7 +253,7 @@ See [CHANGELOG.md](https://github.com/gia-uh/decision-toolkit/blob/main/CHANGELO
265
253
 
266
254
  ## Custom ONNX (at your own risk)
267
255
 
268
- You can run any ONNX file with an adapter you trust — outside the curated
256
+ You can run any ONNX file with an adapter you trust — outside the
269
257
  catalog:
270
258
 
271
259
  ```python
@@ -66,7 +66,7 @@ and
66
66
  The model cards retain the historical cold-start measurements used when each
67
67
  variant was admitted. The harness reports **post-warmup steady-state** latency,
68
68
  which is lower. Compare like with like: use the harness when comparing commits
69
- or machines; use the card values only as historical admission evidence.
69
+ or machines; use the card values only as historical reference measurements.
70
70
 
71
71
  ## Adding a case
72
72
 
@@ -1,4 +1,4 @@
1
- # CLI (phase 3)
1
+ # CLI
2
2
 
3
3
  `dtk` is our own operational surface. Unlike REST, it has **no external
4
4
  standard** to comply with: it is consistent with itself, script-friendly, and a
@@ -9,7 +9,7 @@ CLI.
9
9
 
10
10
  | Command | Purpose |
11
11
  | --- | --- |
12
- | `dtk models` | Inspect the local cache and the curated catalog. |
12
+ | `dtk models` | Inspect the local cache and the model catalog. |
13
13
  | `dtk models list` | Every catalog variant, default (`*`) and cached variants (`--license`, `--quant`, `--adapter`). |
14
14
  | `dtk models variants <id>` | Every real variant of one model, with size, role and exact install command. |
15
15
  | `dtk models download <id>` | Download the default or `--variant` quantization (`--force`, `--dry-run`). |
@@ -244,8 +244,7 @@ dtk serve --model gliner2.5-multi --warmup \
244
244
  - `--workers N` and `--reload` use an internal uvicorn factory; `--reload`
245
245
  is for development and cannot be combined with `--workers > 1`.
246
246
  - `--max-models`, `--max-body-mb`, `--timeout`, `--warmup`, `--api-key`,
247
- `--cors-origin`, `--log-level` and `--log-format` are the server's phase 2
248
- controls.
247
+ `--cors-origin`, `--log-level` and `--log-format` are server controls.
249
248
  - Custom `--adapter`/`--files` also apply to the server's default model.
250
249
 
251
250
  ## Completion
@@ -281,6 +280,6 @@ dtk doctor --json
281
280
  config), but still does not reimplement inference.
282
281
  - It does not have a compatibility obligation to System One/OpenAI; those are
283
282
  REST contracts.
284
- - Metrics/rate limiting are server-side phase 5 features; see
283
+ - Metrics and rate limiting are server-side features; see
285
284
  [OPERATIONS.md](OPERATIONS.md). Wheel/PyPI releases are documented in
286
285
  [RELEASE.md](RELEASE.md).
@@ -1,4 +1,4 @@
1
- # Core programmatic API (phase 1)
1
+ # Core API
2
2
 
3
3
  The programmatic API is the **superset**: the most expressive layer of the
4
4
  toolkit. The REST server is a documented, conformance-tested projection of a subset of
@@ -207,7 +207,7 @@ Events emitted by `decision_toolkit.*` loggers:
207
207
  Each event is a compact JSON object with `event`, `request_id`, model identity,
208
208
  variant, adapter, question count, token counts, latency, truncation and error
209
209
  code. State and question text are **not** logged by default. The CLI/REST
210
- layers configure formatting and destinations in later phases.
210
+ layers configure formatting and destinations separately.
211
211
 
212
212
  ## Extensibility
213
213
 
@@ -254,9 +254,9 @@ Registration is in-process (no daemon, no plugin server).
254
254
  - `resolve(id, variant=...)`: local directory + role → file map + adapter for
255
255
  the core.
256
256
 
257
- ## Phase 1 expressiveness inventory
257
+ ## Capabilities and limits
258
258
 
259
- This is the checklist against which the REST projection will be verified:
259
+ The core exposes the following capabilities:
260
260
 
261
261
  | Capability | Core status |
262
262
  | --- | --- |
@@ -280,13 +280,12 @@ This is the checklist against which the REST projection will be verified:
280
280
  | Model store | atomic download, hashes, verify, import metadata |
281
281
  | Multi-label | capability flag + validation; no adapter yet |
282
282
 
283
- ## Out of scope for phase 1
283
+ ## Not part of the core
284
284
 
285
- - REST contract projection and standard compliance — implemented in phase 2
286
- (see [REST.md](REST.md)).
287
- - CLI workflows across the whole catalog — implemented in phase 3 (see
288
- [CLI.md](CLI.md)).
289
- - Pin/hash enforcement and source CI are implemented in phase 4; wheel,
290
- PyPI and distribution tagging are documented in [RELEASE.md](RELEASE.md).
291
- - Metrics server, rate limiting and load/fuzz testing are server-side phase 5
292
- features; see [OPERATIONS.md](OPERATIONS.md).
285
+ - REST contract projection and standard compliance are implemented in the
286
+ server; see [REST.md](REST.md).
287
+ - CLI workflows across the catalog are implemented in [CLI.md](CLI.md).
288
+ - Catalog pinning and source CI are implementation details; packaging is
289
+ documented in [RELEASE.md](RELEASE.md).
290
+ - Metrics, rate limiting and load/fuzz testing are server-side features; see
291
+ [OPERATIONS.md](OPERATIONS.md).
@@ -1,6 +1,6 @@
1
- # Operations (phase 5)
1
+ # Operations
2
2
 
3
- This document covers the operational behavior added in phase 5: rate limits,
3
+ This document covers operational behavior: rate limits,
4
4
  backpressure, metrics, tracing, load testing and the PII contract. Packaging is
5
5
  still a later milestone.
6
6
 
@@ -39,7 +39,7 @@ Clean install test (no `PYTHONPATH`):
39
39
  ```bash
40
40
  uv venv --python 3.12 /tmp/dtk-wheel
41
41
  uv pip install --python /tmp/dtk-wheel/bin/python \
42
- dist/decision_toolkit-0.4.1-py3-none-any.whl
42
+ dist/decision_toolkit-0.4.2-py3-none-any.whl
43
43
  uv pip check --python /tmp/dtk-wheel/bin/python
44
44
  /tmp/dtk-wheel/bin/dtk --version
45
45
  /tmp/dtk-wheel/bin/dtk models list --json
@@ -50,7 +50,7 @@ With inference and server extras:
50
50
 
51
51
  ```bash
52
52
  uv pip install --python /tmp/dtk-wheel/bin/python \
53
- "dist/decision_toolkit-0.4.1-py3-none-any.whl[onnx,server,tracing]"
53
+ "dist/decision_toolkit-0.4.2-py3-none-any.whl[onnx,server,tracing]"
54
54
  /tmp/dtk-wheel/bin/dtk decide --model gliner2.5-decide ...
55
55
  /tmp/dtk-wheel/bin/dtk serve --model gliner2.5-decide --warmup --port 8016
56
56
  curl -s http://127.0.0.1:8016/health
@@ -84,8 +84,8 @@ No long-lived PyPI token is needed; the workflow uses GitHub OIDC
84
84
  4. Create and push an annotated tag:
85
85
 
86
86
  ```bash
87
- git tag -a v0.4.1 -m "decision-toolkit 0.4.1"
88
- git push origin v0.4.1
87
+ git tag -a v0.4.2 -m "decision-toolkit 0.4.2"
88
+ git push origin v0.4.2
89
89
  ```
90
90
 
91
91
  5. `.github/workflows/release.yml` builds once, publishes to **TestPyPI**, then
@@ -134,9 +134,9 @@ to TestPyPI without publishing to PyPI or creating a GitHub release.
134
134
 
135
135
  ## Published release
136
136
 
137
- `0.4.1` is published through Trusted Publishing on 2026-10-21:
137
+ `0.4.2` is published through Trusted Publishing on 2026-10-21:
138
138
 
139
- <https://pypi.org/project/decision-toolkit/0.4.1/>
139
+ <https://pypi.org/project/decision-toolkit/0.4.2/>
140
140
 
141
141
  `0.1.0` was the first release; `0.1.1` refreshed the PyPI description; `0.1.2`
142
142
  validated the OIDC TestPyPI → PyPI flow; `0.1.3` added post-publish install
@@ -148,7 +148,8 @@ selection across library, CLI and REST; `0.2.0` corrected the REST conformance
148
148
  claims and wire shapes; `0.2.1` changed the public documentation URLs; `0.3.0`
149
149
  added the three new ONNX decision models; `0.3.1` made the catalog list one row per variant; `0.4.0` moved REST variant
150
150
  selection to standard model aliases; `0.4.1` exposed aliases in the catalog and
151
- per-variant loading examples in every model card.
151
+ per-variant loading examples in every model card; `0.4.2` removed internal
152
+ project language and public proposal/roadmap pages.
152
153
 
153
154
  The tag-triggered workflow remains the preferred path for future releases once
154
155
  the TestPyPI/PyPI trusted publishers and protected environments are configured.
@@ -1,4 +1,4 @@
1
- # REST projection (phase 2)
1
+ # REST API
2
2
 
3
3
  REST is a **documented projection** of the programmatic core, not a second
4
4
  implementation. The core remains the superset; the server selects a supported
@@ -337,11 +337,11 @@ at `http://localhost:8000/v1`.
337
337
  - Transport tests cover auth, request ids, 413, CORS, readiness and per-request
338
338
  model selection.
339
339
 
340
- ## Out of scope for phase 2
340
+ ## Not implemented by this server
341
341
 
342
- - Metrics/Prometheus, rate limiting and load tests are implemented in phase 5
343
- (see [OPERATIONS.md](OPERATIONS.md)).
344
- - CLI batch/JSONL and custom-model workflows are implemented in phase 3
345
- (see [CLI.md](CLI.md)).
346
- - Pinned catalog hashes and source CI are implemented in phase 4; wheel,
347
- PyPI and distribution tagging are documented in [RELEASE.md](RELEASE.md).
342
+ - Metrics, rate limiting and load testing are implemented as server-side
343
+ features; see [OPERATIONS.md](OPERATIONS.md).
344
+ - CLI batch/JSONL and custom-model workflows are in the CLI; see [CLI.md](CLI.md).
345
+ - Pinned catalog hashes and CI are implementation details; packaging is
346
+ documented in [RELEASE.md](RELEASE.md).
347
+ - Images/assets and `box` are rejected because the current catalog is text-only.
@@ -11,7 +11,7 @@ local model cache. Variants of the same model coexist, so you can compare them
11
11
  without deleting the default.
12
12
 
13
13
  Only catalogued and verified builds are selectable. Community conversions that
14
- have not passed the catalog gates are not exposed as variants.
14
+ have not passed the catalog checks are not exposed as variants.
15
15
 
16
16
  ## Available variants
17
17
 
@@ -38,7 +38,7 @@ other variant was selected with `dtk models use`.
38
38
 
39
39
  Models with a single row have only one catalogued, verified build. That does
40
40
  not mean other conversions do not exist upstream; it means they have not passed
41
- the parity, hash and license gates for this catalog.
41
+ the parity, hash and license checks for this catalog.
42
42
 
43
43
  ## One selection model across surfaces
44
44
 
@@ -202,7 +202,7 @@ The variant currently in use cannot be deleted.
202
202
 
203
203
  ## Why some models have only one variant
204
204
 
205
- The catalog is curated, not a mirror. A variant is admitted only with a pinned
205
+ The catalog is verified, not a mirror. A variant is admitted only with a pinned
206
206
  revision, a real ONNX export, SHA256 per file, a clean license and measured
207
207
  parity/latency. An upstream repository may contain fp32, fp16, int8 or q4
208
208
  builds that are not in the toolkit because they have not been validated.
@@ -23,8 +23,7 @@ PyPI: <https://pypi.org/project/decision-toolkit/>
23
23
  - [Variants and quantization](VARIANTS.md) — every catalogued build and how to download/select it.
24
24
  - [Operations](OPERATIONS.md) — rate limits, metrics, tracing and runbook.
25
25
  - [Benchmarks](BENCH.md) — reproducible latency/parity/calibration.
26
- - [Models](models/README.md) — the curated catalog.
27
- - [Catalog proposal](CATALOG_PROPOSAL.md) — analysis and evidence for the latest model additions.
26
+ - [Models](models/README.md) — the model catalog.
28
27
  - [Release](RELEASE.md) — build, TestPyPI/PyPI and Trusted Publishing.
29
28
 
30
29
  ## One example
@@ -1,8 +1,8 @@
1
1
  # Model cards
2
2
 
3
- Verified `m0` models. Each card documents the adapter contract, the real download,
4
- the measured evidence and the known limitations. Models that are not `m0` have no
5
- card on purpose: they are not part of the curated library yet.
3
+ These are the models available through `decision-toolkit`. Each card explains
4
+ how to load and use the model, its variants, the measured evidence and its
5
+ known limitations.
6
6
 
7
7
  | Model | Adapter | Variants (default *) | Pinned | Latency (CPU) | Evidence |
8
8
  |---|---|---|---|---|---|
@@ -18,16 +18,5 @@ card on purpose: they are not part of the curated library yet.
18
18
  A `*` marks the default. To inspect sizes, hashes and exact commands, run
19
19
  `dtk models variants <id>` or read [Variants and quantization](../VARIANTS.md).
20
20
 
21
- Latencies above are the historical admission measurements. Reproducible
22
- post-warmup measurements and the exact command are in
23
- [BENCH.md](../BENCH.md).
24
-
25
- ## What a card must contain
26
-
27
- 1. Status and adapter (the model contract).
28
- 2. Every catalogued variant: repo, files, quantization, download size and role.
29
- 3. Measured evidence: latency on CPU, parity/accuracy against a named baseline.
30
- 4. Known limitations (language, export layout, quantization, benchmark scope).
31
- 5. A runnable usage example.
32
- 6. Provenance of the export.
33
- 7. The pinned revision and SHA256 per file, plus the verify/bench command.
21
+ Latencies above are CPU measurements. Reproducible post-warmup measurements
22
+ and the exact command are in [BENCH.md](../BENCH.md).
@@ -1,6 +1,5 @@
1
1
  # GLiNER2.5-Decide
2
2
 
3
- - **Status:** `m0` (verified end-to-end)
4
3
  - **Adapter:** `gliner2-decide` — fused graph with `[L]` label markers and `[SEP_STRUCT]`
5
4
  - **License:** Apache-2.0
6
5
  - **Parameters:** 340M · **Architecture:** DeBERTa-v3-large · **Language:** English only
@@ -1,6 +1,5 @@
1
1
  # GLiNER2.5 multi (v1 + classifier)
2
2
 
3
- - **Status:** `m0` (verified end-to-end)
4
3
  - **Adapter:** `gliner2` — split encoder + classifier, schema with `[P]` / `[C]` / `[DESCRIPTION]` / `[SEP_TEXT]`
5
4
  - **License:** Apache-2.0
6
5
  - **Parameters:** 287M · **Architecture:** GLiNER2.5 multi-v1 · **Languages:** multilingual
@@ -1,6 +1,5 @@
1
1
  # Julia 1
2
2
 
3
- - **Status:** `m0` (official ONNX verified against published PyTorch logits)
4
3
  - **Adapter:** `julia` — single graph with `marker_pos` / `qtype`
5
4
  - **License:** Apache-2.0
6
5
  - **Parameters:** 141M · **Architecture:** mmBERT-small · **Languages:** 52 locales (MASSIVE)
@@ -1,6 +1,5 @@
1
1
  # Laya multilingual
2
2
 
3
- - **Status:** `m0` (fused ONNX export verified end-to-end)
4
3
  - **Adapter:** `laya` — fused encoder + decision head, `marker_pos` / `qtype`, calibrated temperatures
5
4
  - **License:** Apache-2.0
6
5
  - **Parameters:** 322M · **Architecture:** mmBERT-base · **Languages:** 100+ languages
@@ -1,6 +1,5 @@
1
1
  # Laya (English)
2
2
 
3
- - **Status:** `m0` (verified against the torch runtime)
4
3
  - **Adapter:** `laya` — split encoder + head with `marker_pos` / `qtype`
5
4
  - **License:** Apache-2.0
6
5
  - **Parameters:** 421M · **Architecture:** ModernBERT-large · **Language:** English
@@ -1,6 +1,5 @@
1
1
  # Open-Jev DeBERTa v3 large
2
2
 
3
- - **Status:** `m0` (ONNX export verified end-to-end)
4
3
  - **Adapter:** `open-jev` — one sequence, span-pooled option scoring
5
4
  - **License:** Apache-2.0
6
5
  - **Parameters:** ~435M · **Architecture:** DeBERTa-v3-large + span head
@@ -1,6 +1,5 @@
1
1
  # OpenDecider nano
2
2
 
3
- - **Status:** `m0` (official build; prompt/readout ported from pinned code)
4
3
  - **Adapter:** `opendecider` — single graph, softmax over `[MASK]` marker logits
5
4
  - **License:** Apache-2.0
6
5
  - **Parameters:** 395M · **Architecture:** Ettin encoder 400M
@@ -1,6 +1,5 @@
1
1
  # Strands Decider 2B
2
2
 
3
- - **Status:** `m0` (ONNX export verified end-to-end)
4
3
  - **Adapter:** `strands-decider` — Qwen3.5-2B torso + pointer head
5
4
  - **License:** Apache-2.0
6
5
  - **Parameters:** 2B · **Architecture:** Qwen3.5-2B-Base + LoRA + pointer head
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "decision-toolkit"
7
- version = "0.4.1"
7
+ version = "0.4.2"
8
8
  description = "Local-first toolkit for open-weights decision models: one ONNX engine, one adapter per model contract, typed choice/yes-no/score decisions with probabilities on CPU."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -7,7 +7,7 @@ questions with a calibrated probability for every option, on CPU.
7
7
 
8
8
  from __future__ import annotations
9
9
 
10
- __version__ = "0.4.1"
10
+ __version__ = "0.4.2"
11
11
 
12
12
  from .adapters import register_adapter
13
13
  from .calibration import brier_score, expected_calibration_error, threshold_sweep
@@ -135,7 +135,7 @@ def build_parser() -> argparse.ArgumentParser:
135
135
  ),
136
136
  "dtk models variants gliner2.5-multi",
137
137
  "dtk models download gliner2.5-multi --dry-run",
138
- "dtk models download gliner2.5-multi --variant fp32 --force",
138
+ "dtk models download gliner2.5-multi --variant fp32 --dry-run",
139
139
  )
140
140
  models_download.add_argument("model", help="Catalog id.")
141
141
  models_download.add_argument(
@@ -0,0 +1,64 @@
1
+ """Validate every runnable example printed by ``dtk --help``.
2
+
3
+ The full execution audit (real ONNX models and temporary files) is run before a
4
+ release with a populated cache. This test keeps every example syntactically
5
+ valid and ensures every referenced catalog model/variant still exists; it runs
6
+ in CI without downloading models.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import argparse
12
+ import shlex
13
+
14
+ from decision_toolkit import catalog, cli
15
+
16
+
17
+ def _walk(parser: argparse.ArgumentParser):
18
+ if parser.epilog and "examples:" in parser.epilog:
19
+ for line in parser.epilog.splitlines()[1:]:
20
+ if line.strip():
21
+ yield line.strip()
22
+ for action in parser._actions:
23
+ if isinstance(action, argparse._SubParsersAction):
24
+ for subparser in action.choices.values():
25
+ yield from _walk(subparser)
26
+
27
+
28
+ def _examples() -> list[str]:
29
+ examples = list(dict.fromkeys(_walk(cli.build_parser())))
30
+ assert examples
31
+ return examples
32
+
33
+
34
+ def _validate_model_variant(model_id: str | None, variant: str | None) -> None:
35
+ if model_id is None or "/" in model_id or model_id.startswith("."):
36
+ return
37
+ model = catalog.get(model_id)
38
+ if model is None:
39
+ return
40
+ if variant is not None:
41
+ catalog.select_variant(model, variant)
42
+
43
+
44
+ def test_every_help_example_parses_and_references_catalog_entries():
45
+ parser = cli.build_parser()
46
+ for example in _examples():
47
+ argv = shlex.split(example)
48
+ assert argv[0] == "dtk", example
49
+ args = parser.parse_args(argv[1:])
50
+ command = getattr(args, "command", None)
51
+ if command == "models":
52
+ model_id = getattr(args, "model", None)
53
+ variant = getattr(args, "variant", None)
54
+ if args.models_command == "variants":
55
+ model_id = args.model
56
+ variant = None
57
+ elif args.models_command in {"download", "use", "delete"}:
58
+ model_id = args.model
59
+ _validate_model_variant(model_id, variant)
60
+ elif command in {"decide", "classify", "serve"}:
61
+ _validate_model_variant(getattr(args, "model", None), getattr(args, "variant", None))
62
+ elif command == "config":
63
+ if getattr(args, "config_command", None) == "set" and args.key == "current":
64
+ _validate_model_variant(args.value, None)
@@ -349,7 +349,7 @@ wheels = [
349
349
 
350
350
  [[package]]
351
351
  name = "decision-toolkit"
352
- version = "0.4.1"
352
+ version = "0.4.2"
353
353
  source = { editable = "." }
354
354
  dependencies = [
355
355
  { name = "huggingface-hub" },
@@ -1,122 +0,0 @@
1
- # Catalog proposal: three ONNX decision models
2
-
3
- **Date:** 2026-10-21
4
- **Status:** published in `0.3.0`
5
- **Scope:** add Laya multilingual, Open-Jev DeBERTa v3 large and Strands Decider 2B
6
- **Release:** <https://pypi.org/project/decision-toolkit/0.3.0/>
7
-
8
- ## Executive summary
9
-
10
- Three public ONNX decision models meet the catalog gates for this iteration:
11
-
12
- | Model | License | Adapter | Variants | Default |
13
- |---|---|---|---|---:|
14
- | Laya multilingual | Apache-2.0 | existing `laya` + fused branch | fp16, fp32 | fp16 |
15
- | Open-Jev DeBERTa v3 large | Apache-2.0 | new `open-jev` | fp16, fp32, q4, q4f16 | fp16 |
16
- | Strands Decider 2B | Apache-2.0 | new `strands-decider` | q4f16, q8 | q4f16 |
17
-
18
- They have a real public ONNX export, complete external-data files, a pinned
19
- revision and a known prompt contract. The local machine verified every file
20
- hash and opened every ONNX session. No speculative or unavailable model was
21
- added.
22
-
23
- ## Why these three
24
-
25
- - **Laya multilingual** closes the multilingual gap in the existing Laya
26
- family. The ONNX export is fused, but the prompt and calibrated temperatures
27
- are the same as the split Laya contract. It needed one adapter branch, not a
28
- new model family.
29
- - **Open-Jev DeBERTa v3 large** is an independent, open reproduction of the
30
- typed-decision shape. It has a complete fp16/fp32/q4/q4f16 family and a
31
- documented span-pooling graph.
32
- - **Strands Decider 2B** is the first larger decision model in the catalog. It
33
- has a published reference fixture and a clear pointer-head graph. It is more
34
- expensive on CPU, so it is marked as a quality/agentic option rather than a
35
- replacement for the small models.
36
-
37
- `gliner2.5-multi-decide` is **not** in this batch. Its ONNX export is real, but
38
- the prompt uses `[L]` markers instead of the existing GLiNER2 `[C]` layout; it
39
- needs a separate prompt adapter and its own parity run.
40
-
41
- ## Verification performed
42
-
43
- - `dtk models verify --all --json`: **15/15 variants OK** (SHA256, files and
44
- ONNX sessions).
45
- - Real inference for every new variant, using `choice`, `noul` and `score`.
46
- - Smoke parity suite: all added cases matched their expected labels.
47
- - `dtk models variants` exposes all variants and install commands.
48
- - Full test suite: **247 passed, 1 deselected**.
49
- - Ruff and MkDocs `--strict`: clean.
50
- - Python 3.12/3.13 CI matrix and wheel clean-install job: green.
51
-
52
- ### Measured CPU latency
53
-
54
- Post-warmup p50, one simple choice question, audit machine (Python 3.13.2,
55
- ONNX Runtime 1.31.0, CPU):
56
-
57
- | Model | Variant | p50 |
58
- |---|---|---:|
59
- | Laya multilingual | fp16 | 37.4 ms |
60
- | Laya multilingual | fp32 | 34.1 ms |
61
- | Open-Jev DeBERTa v3 large | fp16 | 241.2 ms |
62
- | Open-Jev DeBERTa v3 large | fp32 | 78.2 ms |
63
- | Open-Jev DeBERTa v3 large | q4 | 56.0 ms |
64
- | Open-Jev DeBERTa v3 large | q4f16 | 219.4 ms |
65
- | Strands Decider 2B | q4f16 | 719.3 ms |
66
- | Strands Decider 2B | q8 | 1467.2 ms |
67
-
68
- The Open-Jev DeBERTa v3 large 4-bit paths are size/edge choices; they are not assumed to be
69
- faster or more accurate. Strands is a 2B model and is intentionally slower
70
- than the other catalog entries.
71
-
72
- ### Evidence / parity
73
-
74
- - **Laya multilingual:** upstream conversion reports fp32 max |Δp| 1e-4 and
75
- fp16 0.035 against PyTorch; local fp16/fp32 agree on the audit answers.
76
- - **Open-Jev DeBERTa v3 large:** upstream reports 0.854 in-domain and 0.690 OOD accuracy, plus
77
- 0.022 in-domain ECE. Local fp16/fp32 agree on the published example; q4
78
- variants are explicitly edge builds.
79
- - **Strands Decider 2B:** reference fixture matches within 0.018 max
80
- probability delta; q8 is closer to the reference on most fields.
81
-
82
- These are upstream parity claims plus local runtime/answer checks, not an
83
- independent reproduction of the full upstream training evaluation.
84
-
85
- ## Quantization policy
86
-
87
- - Default variants are chosen for a balance of quality, size and CPU latency:
88
- Laya fp16, Open-Jev DeBERTa v3 large fp16, Strands q4f16.
89
- - `fp32` remains a quality variant where published.
90
- - `q4`/`q4f16`/`q8` are exposed, but their thresholds must be validated on the
91
- user's data; no silent fallback exists.
92
- - `variant` remains a **decision-toolkit extension** in REST, not a TypeSafe or
93
- OpenAI field.
94
-
95
- ## Risks and limitations
96
-
97
- 1. **Upstream evidence vs local evidence.** Full PyTorch parity was not
98
- re-run for these three models; the catalog records upstream parity and local
99
- runtime checks. A larger acceptance run is still desirable.
100
- 2. **Strands CPU cost.** q8 takes ~1.5 s per simple question; this is suitable
101
- for local/agentic workflows, not high-throughput serving.
102
- 3. **Quantization drift.** Open-Jev DeBERTa v3 large q4 and Strands q4f16 can move near-ties;
103
- the model cards call this out.
104
- 4. **Coverage.** Laya multilingual is weak on low-resource languages;
105
- Open-Jev DeBERTa v3 large is English-only and weak on unseen score scales;
106
- Strands is a 2B model with
107
- its own upstream limitations.
108
- 5. **No image/box support.** The catalog remains text-only.
109
-
110
- ## Recommendation
111
-
112
- Accept the three models as `m0` entries with the variants listed above. Keep
113
- `gliner2.5-multi-decide` in the roadmap until its `[L]` adapter is implemented
114
- and parity is measured. The next model batch should prioritize either that
115
- adapter or a larger calibration/parity run for the new entries.
116
-
117
- ## Related documentation
118
-
119
- - [Model cards](models/README.md)
120
- - [Variants and quantization](VARIANTS.md)
121
- - [Benchmarks](BENCH.md)
122
- - [REST](REST.md)
@@ -1,33 +0,0 @@
1
- # Roadmap (not in the catalog)
2
-
3
- The catalog only contains models that are **runnable today** (`m0`). The entries
4
- below are researched but not available through the toolkit: they have no ONNX
5
- export, no verified parity, a broken export, or an adapter still to be written.
6
- They are deliberately absent from `CATALOG`, `dtk models list` and `/v1/models`.
7
-
8
- | id | status | reason |
9
- |---|---|---|
10
- | `gliner2.5-multi-decide` | planned | ONNX split export exists (`DanKau/gliner2.5-multi-decide-onnx`), but the `[L]` prompt layout needs an adapter |
11
- | `intern-decision-0.8b` | planned | ONNX exists (`Wortou/Intern-Decision-0.8B-ONNX-FP16`), but it is split and needs the upstream prompt compiler; `parityVerified: false` |
12
- | `d3-lite` | phase2 | Web ONNX torso/readout files exist, but the repo declares no license/README; not eligible |
13
- | `kev-0.8b` | phase2 | ONNX exists (`midudev/kev-0.8b-ONNX`) but external data is missing and it uses custom ops |
14
- | `sieve-0.8b` | phase2 | No ONNX published; conversion planned |
15
- | `thx-01` | phase2 | No ONNX published; conversion planned |
16
- | `jevk5-lite` | waitlist | Export references external `.onnx.data` files that are not published |
17
- | `bosun-0.6b` | waitlist | No ONNX yet |
18
- | `d3-edge` | waitlist | Web ONNX files exist, but no license/README; not eligible |
19
- | `tev1-0.8b` | waitlist | ONNX exists, but the upstream licence is `other` and needs review |
20
- | `d1-omni-600m` | waitlist | ONNX exists, but the LFM Open License needs review and it is multimodal |
21
- | `bekko-400m` | waitlist | License pending |
22
-
23
- ## How a model moves into the catalog
24
-
25
- 1. A real, runnable ONNX export exists on the Hub.
26
- 2. Its contract is understood and an adapter runs it (written only from the real files).
27
- 3. Parity against the original is measured on a fixed sample.
28
- 4. License is clean and CPU latency is measured.
29
- 5. A model card is written; the variant carries `verified_at`, `latency_ms_p50`
30
- and `parity`.
31
-
32
- Conversion work (safetensors → ONNX, quantization, manifests) is a separate
33
- project planned for the next phase.