algoriq 0.2.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.
- algoriq-0.2.0/.gitignore +16 -0
- algoriq-0.2.0/PKG-INFO +193 -0
- algoriq-0.2.0/README.md +147 -0
- algoriq-0.2.0/examples/notebooks/research_roundtrip.ipynb +569 -0
- algoriq-0.2.0/hatch_build.py +364 -0
- algoriq-0.2.0/pyproject.toml +157 -0
- algoriq-0.2.0/src/algoriq_research/__init__.py +237 -0
- algoriq-0.2.0/src/algoriq_research/_probes.py +372 -0
- algoriq-0.2.0/src/algoriq_research/capabilities.py +826 -0
- algoriq-0.2.0/src/algoriq_research/capability_status.py +59 -0
- algoriq-0.2.0/src/algoriq_research/client.py +591 -0
- algoriq-0.2.0/src/algoriq_research/errors.py +136 -0
- algoriq-0.2.0/src/algoriq_research/plane.py +188 -0
- algoriq-0.2.0/src/algoriq_research/runtime_guard.py +353 -0
- algoriq-0.2.0/tests/test_capabilities.py +349 -0
- algoriq-0.2.0/tests/test_client.py +688 -0
- algoriq-0.2.0/tests/test_distribution_boundary.py +626 -0
- algoriq-0.2.0/tests/test_plane_inventory.py +102 -0
- algoriq-0.2.0/tests/test_public_api.py +195 -0
- algoriq-0.2.0/tests/test_runtime_guard.py +292 -0
algoriq-0.2.0/.gitignore
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# This file exists for a build reason as well as a VCS one.
|
|
2
|
+
#
|
|
3
|
+
# Hatchling resolves the nearest VCS ignore file by walking up to the repository
|
|
4
|
+
# root and then FORCE-includes it in the sdist (builders/sdist.py
|
|
5
|
+
# get_default_build_data), where `exclude` cannot reach it and `ignore-vcs` does
|
|
6
|
+
# not apply. Without a package-local file the nearest one is the monorepo root's,
|
|
7
|
+
# so every sdist shipped a listing of this repository's internal directories.
|
|
8
|
+
# Keeping one here means the shipped file is this package's own and says nothing
|
|
9
|
+
# about anything else. tests/test_distribution_boundary.py pins that.
|
|
10
|
+
|
|
11
|
+
.venv/
|
|
12
|
+
dist/
|
|
13
|
+
__pycache__/
|
|
14
|
+
*.pyc
|
|
15
|
+
.pytest_cache/
|
|
16
|
+
.ruff_cache/
|
algoriq-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: algoriq
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: AlgoriQ Research — notebook SDK: the supported compute surface plus the submission plane client
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Requires-Dist: cryptography>=42.0.0
|
|
7
|
+
Requires-Dist: dcor>=0.6
|
|
8
|
+
Requires-Dist: econml<0.17,>=0.16.0
|
|
9
|
+
Requires-Dist: hmmlearn>=0.3.2
|
|
10
|
+
Requires-Dist: holidays>=0.65
|
|
11
|
+
Requires-Dist: httpx>=0.27.0
|
|
12
|
+
Requires-Dist: joblib>=1.3.0
|
|
13
|
+
Requires-Dist: numba>=0.59
|
|
14
|
+
Requires-Dist: numpy>=2.2.6
|
|
15
|
+
Requires-Dist: orjson>=3.9.0
|
|
16
|
+
Requires-Dist: pandas>=2.3.3
|
|
17
|
+
Requires-Dist: pyarrow>=15.0.0
|
|
18
|
+
Requires-Dist: pydantic-settings>=2.3.0
|
|
19
|
+
Requires-Dist: pydantic>=2.9.0
|
|
20
|
+
Requires-Dist: scikit-learn>=1.4.0
|
|
21
|
+
Requires-Dist: scipy>=1.11.0
|
|
22
|
+
Requires-Dist: structlog>=25.0.0
|
|
23
|
+
Requires-Dist: tenacity>=8.2.0
|
|
24
|
+
Requires-Dist: threadpoolctl>=3.1.0
|
|
25
|
+
Provides-Extra: boosting
|
|
26
|
+
Requires-Dist: catboost>=1.2; extra == 'boosting'
|
|
27
|
+
Requires-Dist: lightgbm>=4.5.0; extra == 'boosting'
|
|
28
|
+
Requires-Dist: ngboost>=0.5; extra == 'boosting'
|
|
29
|
+
Requires-Dist: xgboost>=2.1.0; extra == 'boosting'
|
|
30
|
+
Provides-Extra: foundation
|
|
31
|
+
Requires-Dist: chronos-forecasting>=1.4; extra == 'foundation'
|
|
32
|
+
Requires-Dist: torch<2.6,>=2.2; extra == 'foundation'
|
|
33
|
+
Provides-Extra: mlx
|
|
34
|
+
Requires-Dist: cvxpy>=1.5.0; extra == 'mlx'
|
|
35
|
+
Requires-Dist: cvxpylayers>=1.2.0; extra == 'mlx'
|
|
36
|
+
Requires-Dist: mlx>=0.31.0; (sys_platform == 'darwin' and platform_machine == 'arm64') and extra == 'mlx'
|
|
37
|
+
Provides-Extra: signal
|
|
38
|
+
Requires-Dist: pywavelets>=1.7.0; extra == 'signal'
|
|
39
|
+
Requires-Dist: statsmodels>=0.14.0; extra == 'signal'
|
|
40
|
+
Provides-Extra: symbolic
|
|
41
|
+
Requires-Dist: pysr<2,>=1.5; extra == 'symbolic'
|
|
42
|
+
Provides-Extra: tabpfn
|
|
43
|
+
Requires-Dist: tabpfn>=2.0; extra == 'tabpfn'
|
|
44
|
+
Requires-Dist: torch<2.6,>=2.2; extra == 'tabpfn'
|
|
45
|
+
Description-Content-Type: text/markdown
|
|
46
|
+
|
|
47
|
+
# AlgoriQ Research — notebook SDK
|
|
48
|
+
|
|
49
|
+
The pro-code side of AlgoriQ. Install it in any Python kernel — Colab, a local
|
|
50
|
+
Jupyter, a VS Code notebook — and you get two things:
|
|
51
|
+
|
|
52
|
+
1. **The supported compute surface** of the platform: AFML labeling, purged and
|
|
53
|
+
combinatorial cross-validation, MDI/MDA/SFI importance, sample weighting,
|
|
54
|
+
covariance denoising and ONC clustering, indicators and fractional
|
|
55
|
+
differentiation. These are re-exports, not copies — the notebook runs the
|
|
56
|
+
same code the platform runs.
|
|
57
|
+
2. **The research submission plane client**: declare an observation, seal a
|
|
58
|
+
snapshot, submit a result, read it back.
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
import algoriq_research as aq
|
|
62
|
+
|
|
63
|
+
aq.print_capabilities() # what this install actually supports
|
|
64
|
+
client = aq.ResearchClient() # reads ALGORIQ_SUBMISSION_TOKEN
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Connecting
|
|
68
|
+
|
|
69
|
+
**There is one connection flow and it does not depend on where your kernel
|
|
70
|
+
runs.** The notebook starts a device authorization (RFC 8628), prints a short
|
|
71
|
+
code and a link, and you approve it in a browser already signed in to AlgoriQ —
|
|
72
|
+
choosing on that screen which account the notebook acts as. The credential is
|
|
73
|
+
then issued straight to the kernel, into `ALGORIQ_SUBMISSION_TOKEN`, and the SDK
|
|
74
|
+
sends it as a bearer. Nothing else identifies you. Colab, a local Jupyter and a
|
|
75
|
+
VS Code kernel take the identical path; no step of this has a per-runtime
|
|
76
|
+
variant.
|
|
77
|
+
|
|
78
|
+
The same credential fetches the SDK itself, because the wheel is served by
|
|
79
|
+
AlgoriQ rather than by a public index: you download it with the credential,
|
|
80
|
+
check it against the digest the server published, and install that exact file.
|
|
81
|
+
So connecting comes first and installing second, on every runtime.
|
|
82
|
+
|
|
83
|
+
Both steps, working, are cells 1 and 2 of
|
|
84
|
+
[`examples/notebooks/research_roundtrip.ipynb`](examples/notebooks/research_roundtrip.ipynb).
|
|
85
|
+
|
|
86
|
+
⛔ Never paste a credential into a notebook cell. A cell's contents are saved
|
|
87
|
+
with the notebook, and a notebook is the thing people share. The device grant is
|
|
88
|
+
what makes that avoidable — you never see the credential at all.
|
|
89
|
+
|
|
90
|
+
⛔ Never put a credential on a `pip` command line or in an index URL. It belongs
|
|
91
|
+
in an `Authorization` header: a command line lands in shell history, in the cell
|
|
92
|
+
output saved with the notebook, and in the process table of a shared machine.
|
|
93
|
+
|
|
94
|
+
⚠️ Send an explicit `User-Agent` on any hand-rolled HTTP call to `*.algoriq.ai`.
|
|
95
|
+
The edge refuses `urllib`'s default `Python-urllib/*` signature with a `403`
|
|
96
|
+
whose body is `error code: 1010` — not JSON, and not our `401`, so a client that
|
|
97
|
+
reads only the status will report the wrong cause. Every other user agent tested
|
|
98
|
+
is accepted, `httpx`'s default among them, so this bites hand-rolled `urllib`
|
|
99
|
+
calls — the bootstrap and install cells — and not the SDK.
|
|
100
|
+
|
|
101
|
+
The credential is **opaque** to this SDK: it is read, sent, and never parsed. If
|
|
102
|
+
the plane answers `401`, the credential is absent, expired or revoked — run the
|
|
103
|
+
connection cell again to get a new one. Revoking one takes effect on the next
|
|
104
|
+
call.
|
|
105
|
+
|
|
106
|
+
## What "supported" means, and what it does not
|
|
107
|
+
|
|
108
|
+
`print_capabilities()` answers by **running** each capability, not by reading a
|
|
109
|
+
table, so it cannot claim support this environment does not have. Every row comes
|
|
110
|
+
back as one of:
|
|
111
|
+
|
|
112
|
+
| Status | Meaning | What you do |
|
|
113
|
+
| --------------------- | ------------------------------------------ | --------------------------------------------------- |
|
|
114
|
+
| `available` | Installed and proven to execute here | Nothing |
|
|
115
|
+
| `not_installed` | Its extra is not installed | `pip install 'algoriq[<extra>]'` |
|
|
116
|
+
| `broken_install` | **Our own** module is missing from disk | Reinstall the wheel and tell us — no extra fixes it |
|
|
117
|
+
| `unsupported_runtime` | This runtime cannot have it at any version | Use a different backend — installing won't help |
|
|
118
|
+
| `not_entitled` | Your account may not do this | A plan/permission question, raised by the server |
|
|
119
|
+
|
|
120
|
+
`broken_install` is its own word because it is the one state where the obvious
|
|
121
|
+
remedy is wrong: a missing file of ours raises the same `ImportError` a missing
|
|
122
|
+
library does, so reporting it as `not_installed` hands you a `pip install` that
|
|
123
|
+
installs the libraries, changes nothing, and prints the same line again.
|
|
124
|
+
|
|
125
|
+
The extras are `boosting`, `tabpfn`, `foundation`, `symbolic`, `mlx` and `signal`. An extra
|
|
126
|
+
means _not in the default install_ — never _you may not use it_. You are free to
|
|
127
|
+
`pip install xgboost` in Colab and use it directly; the extra is what makes
|
|
128
|
+
**our** wrappers around it resolve.
|
|
129
|
+
|
|
130
|
+
⛔ **Widening the supported surface does not raise the evidence grade of what you
|
|
131
|
+
submit.** Results declared from a notebook come back graded `descriptive` with
|
|
132
|
+
`population_status='unverified'`, because the platform stores what you declared
|
|
133
|
+
and does not certify that your search was complete. That boundary is independent
|
|
134
|
+
of this table.
|
|
135
|
+
|
|
136
|
+
## The round trip
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
import algoriq_research as aq
|
|
140
|
+
|
|
141
|
+
client = aq.ResearchClient()
|
|
142
|
+
|
|
143
|
+
# 1. declare each terminal execution — including the ones you discarded
|
|
144
|
+
kept = client.record_observation(declaration)
|
|
145
|
+
|
|
146
|
+
# 2. submit the selected result's bytes (declare → upload → seal, in one call)
|
|
147
|
+
sealed = client.submit(submission_intent, parquet_bytes)
|
|
148
|
+
|
|
149
|
+
# 3. seal the scope, naming the server's normalised digest of that result
|
|
150
|
+
snapshot = client.seal_snapshot(snapshot_intent) # selected_result_sha256=sealed.normalized_sha256
|
|
151
|
+
|
|
152
|
+
# 4. bind the result to the snapshot that selected it
|
|
153
|
+
publication = client.publish_submission(sealed.receipt_id, publication_intent)
|
|
154
|
+
|
|
155
|
+
# 5. read it back, any time
|
|
156
|
+
client.get_publication(sealed.receipt_id)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
⛔ Steps 2 and 3 are in that order for a reason: a snapshot names the
|
|
160
|
+
**normalised** digest of its selected result, and that digest is the server's —
|
|
161
|
+
it does not exist until the bytes have been sealed. Sealing the scope first
|
|
162
|
+
leaves you with nothing to put in `selected_result_sha256`.
|
|
163
|
+
|
|
164
|
+
`submit()` checks your declared `raw_sha256` and `size_bytes` against the bytes
|
|
165
|
+
**before** it opens a connection. Found here it costs nothing; found server-side
|
|
166
|
+
it costs the whole upload first, which on a home uplink is minutes.
|
|
167
|
+
|
|
168
|
+
`prepare_submission()` returns an upload form whose `expires_in` is a function of
|
|
169
|
+
the `size_bytes` you declared — a large upload is given proportionally longer.
|
|
170
|
+
Read it rather than assuming a constant.
|
|
171
|
+
|
|
172
|
+
Worked example: [`examples/notebooks/research_roundtrip.ipynb`](examples/notebooks/research_roundtrip.ipynb).
|
|
173
|
+
|
|
174
|
+
## Not here yet
|
|
175
|
+
|
|
176
|
+
- **Reading platform data.** The read planes (`.../research/ingredients*`,
|
|
177
|
+
market-data) are live and take the same credential, but this SDK has no typed
|
|
178
|
+
client for them yet, so a notebook reaches them with plain HTTP for now.
|
|
179
|
+
- **Installation from an index.** The release flow, version SSOT and download
|
|
180
|
+
authorisation are owned by `docs/guides/notebook-sdk-distribution.md`; until a
|
|
181
|
+
release is published, install from a wheel built out of this repository.
|
|
182
|
+
|
|
183
|
+
## For maintainers
|
|
184
|
+
|
|
185
|
+
The public API is not written twice. `algoriq_research.capabilities.CAPABILITIES`
|
|
186
|
+
is both the allowlist and the support matrix: `__all__` is derived from it, and
|
|
187
|
+
each name's capability is checked before the name resolves. Adding a public name
|
|
188
|
+
means adding it there and nowhere else.
|
|
189
|
+
|
|
190
|
+
`tests/test_distribution_boundary.py` builds the wheel and the sdist and reads
|
|
191
|
+
the archives — paths, metadata, declared dependencies (including the shared
|
|
192
|
+
package's own base list) and a secret scan. Source-tree exclusion rules are not
|
|
193
|
+
evidence of what shipped.
|
algoriq-0.2.0/README.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# AlgoriQ Research — notebook SDK
|
|
2
|
+
|
|
3
|
+
The pro-code side of AlgoriQ. Install it in any Python kernel — Colab, a local
|
|
4
|
+
Jupyter, a VS Code notebook — and you get two things:
|
|
5
|
+
|
|
6
|
+
1. **The supported compute surface** of the platform: AFML labeling, purged and
|
|
7
|
+
combinatorial cross-validation, MDI/MDA/SFI importance, sample weighting,
|
|
8
|
+
covariance denoising and ONC clustering, indicators and fractional
|
|
9
|
+
differentiation. These are re-exports, not copies — the notebook runs the
|
|
10
|
+
same code the platform runs.
|
|
11
|
+
2. **The research submission plane client**: declare an observation, seal a
|
|
12
|
+
snapshot, submit a result, read it back.
|
|
13
|
+
|
|
14
|
+
```python
|
|
15
|
+
import algoriq_research as aq
|
|
16
|
+
|
|
17
|
+
aq.print_capabilities() # what this install actually supports
|
|
18
|
+
client = aq.ResearchClient() # reads ALGORIQ_SUBMISSION_TOKEN
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Connecting
|
|
22
|
+
|
|
23
|
+
**There is one connection flow and it does not depend on where your kernel
|
|
24
|
+
runs.** The notebook starts a device authorization (RFC 8628), prints a short
|
|
25
|
+
code and a link, and you approve it in a browser already signed in to AlgoriQ —
|
|
26
|
+
choosing on that screen which account the notebook acts as. The credential is
|
|
27
|
+
then issued straight to the kernel, into `ALGORIQ_SUBMISSION_TOKEN`, and the SDK
|
|
28
|
+
sends it as a bearer. Nothing else identifies you. Colab, a local Jupyter and a
|
|
29
|
+
VS Code kernel take the identical path; no step of this has a per-runtime
|
|
30
|
+
variant.
|
|
31
|
+
|
|
32
|
+
The same credential fetches the SDK itself, because the wheel is served by
|
|
33
|
+
AlgoriQ rather than by a public index: you download it with the credential,
|
|
34
|
+
check it against the digest the server published, and install that exact file.
|
|
35
|
+
So connecting comes first and installing second, on every runtime.
|
|
36
|
+
|
|
37
|
+
Both steps, working, are cells 1 and 2 of
|
|
38
|
+
[`examples/notebooks/research_roundtrip.ipynb`](examples/notebooks/research_roundtrip.ipynb).
|
|
39
|
+
|
|
40
|
+
⛔ Never paste a credential into a notebook cell. A cell's contents are saved
|
|
41
|
+
with the notebook, and a notebook is the thing people share. The device grant is
|
|
42
|
+
what makes that avoidable — you never see the credential at all.
|
|
43
|
+
|
|
44
|
+
⛔ Never put a credential on a `pip` command line or in an index URL. It belongs
|
|
45
|
+
in an `Authorization` header: a command line lands in shell history, in the cell
|
|
46
|
+
output saved with the notebook, and in the process table of a shared machine.
|
|
47
|
+
|
|
48
|
+
⚠️ Send an explicit `User-Agent` on any hand-rolled HTTP call to `*.algoriq.ai`.
|
|
49
|
+
The edge refuses `urllib`'s default `Python-urllib/*` signature with a `403`
|
|
50
|
+
whose body is `error code: 1010` — not JSON, and not our `401`, so a client that
|
|
51
|
+
reads only the status will report the wrong cause. Every other user agent tested
|
|
52
|
+
is accepted, `httpx`'s default among them, so this bites hand-rolled `urllib`
|
|
53
|
+
calls — the bootstrap and install cells — and not the SDK.
|
|
54
|
+
|
|
55
|
+
The credential is **opaque** to this SDK: it is read, sent, and never parsed. If
|
|
56
|
+
the plane answers `401`, the credential is absent, expired or revoked — run the
|
|
57
|
+
connection cell again to get a new one. Revoking one takes effect on the next
|
|
58
|
+
call.
|
|
59
|
+
|
|
60
|
+
## What "supported" means, and what it does not
|
|
61
|
+
|
|
62
|
+
`print_capabilities()` answers by **running** each capability, not by reading a
|
|
63
|
+
table, so it cannot claim support this environment does not have. Every row comes
|
|
64
|
+
back as one of:
|
|
65
|
+
|
|
66
|
+
| Status | Meaning | What you do |
|
|
67
|
+
| --------------------- | ------------------------------------------ | --------------------------------------------------- |
|
|
68
|
+
| `available` | Installed and proven to execute here | Nothing |
|
|
69
|
+
| `not_installed` | Its extra is not installed | `pip install 'algoriq[<extra>]'` |
|
|
70
|
+
| `broken_install` | **Our own** module is missing from disk | Reinstall the wheel and tell us — no extra fixes it |
|
|
71
|
+
| `unsupported_runtime` | This runtime cannot have it at any version | Use a different backend — installing won't help |
|
|
72
|
+
| `not_entitled` | Your account may not do this | A plan/permission question, raised by the server |
|
|
73
|
+
|
|
74
|
+
`broken_install` is its own word because it is the one state where the obvious
|
|
75
|
+
remedy is wrong: a missing file of ours raises the same `ImportError` a missing
|
|
76
|
+
library does, so reporting it as `not_installed` hands you a `pip install` that
|
|
77
|
+
installs the libraries, changes nothing, and prints the same line again.
|
|
78
|
+
|
|
79
|
+
The extras are `boosting`, `tabpfn`, `foundation`, `symbolic`, `mlx` and `signal`. An extra
|
|
80
|
+
means _not in the default install_ — never _you may not use it_. You are free to
|
|
81
|
+
`pip install xgboost` in Colab and use it directly; the extra is what makes
|
|
82
|
+
**our** wrappers around it resolve.
|
|
83
|
+
|
|
84
|
+
⛔ **Widening the supported surface does not raise the evidence grade of what you
|
|
85
|
+
submit.** Results declared from a notebook come back graded `descriptive` with
|
|
86
|
+
`population_status='unverified'`, because the platform stores what you declared
|
|
87
|
+
and does not certify that your search was complete. That boundary is independent
|
|
88
|
+
of this table.
|
|
89
|
+
|
|
90
|
+
## The round trip
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
import algoriq_research as aq
|
|
94
|
+
|
|
95
|
+
client = aq.ResearchClient()
|
|
96
|
+
|
|
97
|
+
# 1. declare each terminal execution — including the ones you discarded
|
|
98
|
+
kept = client.record_observation(declaration)
|
|
99
|
+
|
|
100
|
+
# 2. submit the selected result's bytes (declare → upload → seal, in one call)
|
|
101
|
+
sealed = client.submit(submission_intent, parquet_bytes)
|
|
102
|
+
|
|
103
|
+
# 3. seal the scope, naming the server's normalised digest of that result
|
|
104
|
+
snapshot = client.seal_snapshot(snapshot_intent) # selected_result_sha256=sealed.normalized_sha256
|
|
105
|
+
|
|
106
|
+
# 4. bind the result to the snapshot that selected it
|
|
107
|
+
publication = client.publish_submission(sealed.receipt_id, publication_intent)
|
|
108
|
+
|
|
109
|
+
# 5. read it back, any time
|
|
110
|
+
client.get_publication(sealed.receipt_id)
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
⛔ Steps 2 and 3 are in that order for a reason: a snapshot names the
|
|
114
|
+
**normalised** digest of its selected result, and that digest is the server's —
|
|
115
|
+
it does not exist until the bytes have been sealed. Sealing the scope first
|
|
116
|
+
leaves you with nothing to put in `selected_result_sha256`.
|
|
117
|
+
|
|
118
|
+
`submit()` checks your declared `raw_sha256` and `size_bytes` against the bytes
|
|
119
|
+
**before** it opens a connection. Found here it costs nothing; found server-side
|
|
120
|
+
it costs the whole upload first, which on a home uplink is minutes.
|
|
121
|
+
|
|
122
|
+
`prepare_submission()` returns an upload form whose `expires_in` is a function of
|
|
123
|
+
the `size_bytes` you declared — a large upload is given proportionally longer.
|
|
124
|
+
Read it rather than assuming a constant.
|
|
125
|
+
|
|
126
|
+
Worked example: [`examples/notebooks/research_roundtrip.ipynb`](examples/notebooks/research_roundtrip.ipynb).
|
|
127
|
+
|
|
128
|
+
## Not here yet
|
|
129
|
+
|
|
130
|
+
- **Reading platform data.** The read planes (`.../research/ingredients*`,
|
|
131
|
+
market-data) are live and take the same credential, but this SDK has no typed
|
|
132
|
+
client for them yet, so a notebook reaches them with plain HTTP for now.
|
|
133
|
+
- **Installation from an index.** The release flow, version SSOT and download
|
|
134
|
+
authorisation are owned by `docs/guides/notebook-sdk-distribution.md`; until a
|
|
135
|
+
release is published, install from a wheel built out of this repository.
|
|
136
|
+
|
|
137
|
+
## For maintainers
|
|
138
|
+
|
|
139
|
+
The public API is not written twice. `algoriq_research.capabilities.CAPABILITIES`
|
|
140
|
+
is both the allowlist and the support matrix: `__all__` is derived from it, and
|
|
141
|
+
each name's capability is checked before the name resolves. Adding a public name
|
|
142
|
+
means adding it there and nowhere else.
|
|
143
|
+
|
|
144
|
+
`tests/test_distribution_boundary.py` builds the wheel and the sdist and reads
|
|
145
|
+
the archives — paths, metadata, declared dependencies (including the shared
|
|
146
|
+
package's own base list) and a secret scan. Source-tree exclusion rules are not
|
|
147
|
+
evidence of what shipped.
|