subproto 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- subproto-0.1.0/.github/ISSUE_TEMPLATE/bug-report.yml +62 -0
- subproto-0.1.0/.github/ISSUE_TEMPLATE/config.yml +11 -0
- subproto-0.1.0/.github/ISSUE_TEMPLATE/model-or-agent.yml +59 -0
- subproto-0.1.0/.github/PULL_REQUEST_TEMPLATE.md +27 -0
- subproto-0.1.0/.github/workflows/ci.yml +168 -0
- subproto-0.1.0/.github/workflows/pages.yml +43 -0
- subproto-0.1.0/.github/workflows/publish.yml +81 -0
- subproto-0.1.0/.subproto.example.json +9 -0
- subproto-0.1.0/CHANGELOG.md +492 -0
- subproto-0.1.0/CONTRIBUTING.md +103 -0
- subproto-0.1.0/LICENSE +204 -0
- subproto-0.1.0/MANIFEST.in +25 -0
- subproto-0.1.0/PKG-INFO +708 -0
- subproto-0.1.0/README.md +679 -0
- subproto-0.1.0/ROADMAP.md +323 -0
- subproto-0.1.0/SECURITY.md +49 -0
- subproto-0.1.0/SPEC.md +672 -0
- subproto-0.1.0/TODO.md +489 -0
- subproto-0.1.0/WIRING.md +125 -0
- subproto-0.1.0/bench/ab.py +146 -0
- subproto-0.1.0/bench/ablation.py +421 -0
- subproto-0.1.0/bench/ablation_results.md +36 -0
- subproto-0.1.0/bench/launch_stats.json +374 -0
- subproto-0.1.0/bench/launch_stats.py +785 -0
- subproto-0.1.0/bench/laya_latency.json +423 -0
- subproto-0.1.0/bench/laya_latency.md +37 -0
- subproto-0.1.0/bench/laya_latency.py +342 -0
- subproto-0.1.0/bench/live.py +554 -0
- subproto-0.1.0/bench/live_results.md +29 -0
- subproto-0.1.0/bench/live_results_hard.md +29 -0
- subproto-0.1.0/bench/mutation_gate.py +763 -0
- subproto-0.1.0/bench/results.md +14 -0
- subproto-0.1.0/bench/s32_probe.py +91 -0
- subproto-0.1.0/bench/tasks.hard.jsonl +8 -0
- subproto-0.1.0/bench/tasks.sample.jsonl +20 -0
- subproto-0.1.0/docs/assets/first-30-seconds.cast +19 -0
- subproto-0.1.0/docs/assets/first-30-seconds.gif +0 -0
- subproto-0.1.0/docs/assets/first-30-seconds.sh +63 -0
- subproto-0.1.0/docs/assets/terminal-stills.sh +118 -0
- subproto-0.1.0/docs/commands.md +473 -0
- subproto-0.1.0/docs/configuration.md +183 -0
- subproto-0.1.0/docs/index.md +49 -0
- subproto-0.1.0/docs/troubleshooting.md +198 -0
- subproto-0.1.0/fakeup/__init__.py +1 -0
- subproto-0.1.0/fakeup/server.py +295 -0
- subproto-0.1.0/install.sh +46 -0
- subproto-0.1.0/pyproject.toml +78 -0
- subproto-0.1.0/requirements-dev.txt +1 -0
- subproto-0.1.0/run_tests.sh +257 -0
- subproto-0.1.0/setup.cfg +4 -0
- subproto-0.1.0/subproto/__init__.py +7 -0
- subproto-0.1.0/subproto/__main__.py +5 -0
- subproto-0.1.0/subproto/cli.py +1493 -0
- subproto-0.1.0/subproto/compiler.py +431 -0
- subproto-0.1.0/subproto/config.py +216 -0
- subproto-0.1.0/subproto/dataset.py +330 -0
- subproto-0.1.0/subproto/demo.py +260 -0
- subproto-0.1.0/subproto/doctor.py +282 -0
- subproto-0.1.0/subproto/engine.py +352 -0
- subproto-0.1.0/subproto/graph.py +502 -0
- subproto-0.1.0/subproto/heuristics.py +177 -0
- subproto-0.1.0/subproto/implicit.py +534 -0
- subproto-0.1.0/subproto/laya.py +19 -0
- subproto-0.1.0/subproto/laya_server.py +389 -0
- subproto-0.1.0/subproto/live.py +149 -0
- subproto-0.1.0/subproto/pricing.py +43 -0
- subproto-0.1.0/subproto/protocol.py +342 -0
- subproto-0.1.0/subproto/proxy.py +349 -0
- subproto-0.1.0/subproto/report.py +509 -0
- subproto-0.1.0/subproto/retrain.py +541 -0
- subproto-0.1.0/subproto/style.py +292 -0
- subproto-0.1.0/subproto/systemone/__init__.py +28 -0
- subproto-0.1.0/subproto/systemone/base.py +123 -0
- subproto-0.1.0/subproto/systemone/evidence/ablation.json +404 -0
- subproto-0.1.0/subproto/systemone/registry.py +212 -0
- subproto-0.1.0/subproto/systemone/router.py +192 -0
- subproto-0.1.0/subproto/systemone/versions.py +322 -0
- subproto-0.1.0/subproto/telemetry.py +147 -0
- subproto-0.1.0/subproto/tests/conftest.py +74 -0
- subproto-0.1.0/subproto/tests/fixtures/sample_repo/app/payments/retry.py +12 -0
- subproto-0.1.0/subproto/tests/fixtures/sample_repo/app/services/gateway_client.py +11 -0
- subproto-0.1.0/subproto/tests/fixtures/sample_repo/web/src/refund.ts +9 -0
- subproto-0.1.0/subproto/tests/test_ablation.py +128 -0
- subproto-0.1.0/subproto/tests/test_ambient_graph.py +145 -0
- subproto-0.1.0/subproto/tests/test_cli_demo_home.py +158 -0
- subproto-0.1.0/subproto/tests/test_cli_says_why.py +155 -0
- subproto-0.1.0/subproto/tests/test_compiler.py +687 -0
- subproto-0.1.0/subproto/tests/test_dataset_split.py +132 -0
- subproto-0.1.0/subproto/tests/test_dialects_e2e.py +224 -0
- subproto-0.1.0/subproto/tests/test_doctor.py +398 -0
- subproto-0.1.0/subproto/tests/test_engine.py +106 -0
- subproto-0.1.0/subproto/tests/test_finetune.py +68 -0
- subproto-0.1.0/subproto/tests/test_graph.py +335 -0
- subproto-0.1.0/subproto/tests/test_heuristics.py +42 -0
- subproto-0.1.0/subproto/tests/test_implicit.py +525 -0
- subproto-0.1.0/subproto/tests/test_invariants.py +326 -0
- subproto-0.1.0/subproto/tests/test_laya.py +92 -0
- subproto-0.1.0/subproto/tests/test_laya_latency.py +127 -0
- subproto-0.1.0/subproto/tests/test_laya_real.py +427 -0
- subproto-0.1.0/subproto/tests/test_learn.py +345 -0
- subproto-0.1.0/subproto/tests/test_live.py +141 -0
- subproto-0.1.0/subproto/tests/test_live_bench.py +119 -0
- subproto-0.1.0/subproto/tests/test_proxy_e2e.py +90 -0
- subproto-0.1.0/subproto/tests/test_report_sections.py +91 -0
- subproto-0.1.0/subproto/tests/test_retrain.py +665 -0
- subproto-0.1.0/subproto/tests/test_router.py +282 -0
- subproto-0.1.0/subproto/tests/test_show.py +373 -0
- subproto-0.1.0/subproto/tests/test_style.py +382 -0
- subproto-0.1.0/subproto/tests/test_systemone.py +251 -0
- subproto-0.1.0/subproto/tests/test_telemetry.py +75 -0
- subproto-0.1.0/subproto/tests/test_usage.py +70 -0
- subproto-0.1.0/subproto/tests/test_versions.py +491 -0
- subproto-0.1.0/subproto/tests/test_wiring.py +110 -0
- subproto-0.1.0/subproto/usage.py +268 -0
- subproto-0.1.0/subproto.egg-info/PKG-INFO +708 -0
- subproto-0.1.0/subproto.egg-info/SOURCES.txt +120 -0
- subproto-0.1.0/subproto.egg-info/dependency_links.txt +1 -0
- subproto-0.1.0/subproto.egg-info/entry_points.txt +2 -0
- subproto-0.1.0/subproto.egg-info/requires.txt +8 -0
- subproto-0.1.0/subproto.egg-info/top_level.txt +2 -0
- subproto-0.1.0/tools/check_install.sh +44 -0
- subproto-0.1.0/train/finetune_mlx.py +132 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: A command that does not do what its page says it does
|
|
3
|
+
labels: ["bug"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
The single most useful thing you can paste here is the command and its real
|
|
9
|
+
output. Most "it does not work" reports are a Python version, a port in use,
|
|
10
|
+
or a slot that is observing rather than enforcing — `doctor` tells you which.
|
|
11
|
+
- type: textarea
|
|
12
|
+
id: command
|
|
13
|
+
attributes:
|
|
14
|
+
label: The command, exactly as you typed it
|
|
15
|
+
render: shell
|
|
16
|
+
placeholder: |
|
|
17
|
+
subproto demo --port 8000 --slots
|
|
18
|
+
subproto report
|
|
19
|
+
validations:
|
|
20
|
+
required: true
|
|
21
|
+
- type: textarea
|
|
22
|
+
id: expected
|
|
23
|
+
attributes:
|
|
24
|
+
label: What you expected, and what printed instead
|
|
25
|
+
description: Paste the output. Do not paraphrase a number.
|
|
26
|
+
validations:
|
|
27
|
+
required: true
|
|
28
|
+
- type: textarea
|
|
29
|
+
id: doctor
|
|
30
|
+
attributes:
|
|
31
|
+
label: Output of `subproto doctor`
|
|
32
|
+
description: |
|
|
33
|
+
If that command does not exist in your version, paste instead:
|
|
34
|
+
`python3 --version`, `uname -sr` (or your Windows build), and
|
|
35
|
+
`echo "$SUBPROTO_HOME"`.
|
|
36
|
+
render: shell
|
|
37
|
+
validations:
|
|
38
|
+
required: true
|
|
39
|
+
- type: dropdown
|
|
40
|
+
id: slotstate
|
|
41
|
+
attributes:
|
|
42
|
+
label: Are any slots enforcing?
|
|
43
|
+
description: Observation-only is the default; a drop you did not turn on is a different bug.
|
|
44
|
+
options: [none, SUBPROTO_APPLY set, a config file, I do not know]
|
|
45
|
+
validations:
|
|
46
|
+
required: true
|
|
47
|
+
- type: textarea
|
|
48
|
+
id: noise
|
|
49
|
+
attributes:
|
|
50
|
+
label: Anything else running on this machine
|
|
51
|
+
description: >
|
|
52
|
+
A second proxy, an Ollama server, a training run or a laptop on battery changes
|
|
53
|
+
both the latency numbers and whether a model backend answers in time.
|
|
54
|
+
- type: checkboxes
|
|
55
|
+
id: terms
|
|
56
|
+
attributes:
|
|
57
|
+
label: Confirmations
|
|
58
|
+
options:
|
|
59
|
+
- label: I can reproduce this on a fresh `SUBPROTO_HOME` (or I say what is in mine)
|
|
60
|
+
required: true
|
|
61
|
+
- label: I redacted any API key or source code from the pasted output
|
|
62
|
+
required: true
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
blank_issues_enabled: true
|
|
2
|
+
contact_links:
|
|
3
|
+
- name: SECURITY.md — what subproto does and does not send anywhere
|
|
4
|
+
url: https://github.com/aashish254/limen/blob/main/SECURITY.md
|
|
5
|
+
about: It is a local proxy with no telemetry and no update check. Read this before wiring it into an agent that handles private code.
|
|
6
|
+
- name: WIRING.md — base_url per coding agent
|
|
7
|
+
url: https://github.com/aashish254/limen/blob/main/WIRING.md
|
|
8
|
+
about: Claude Code, Codex, Gemini CLI, Cline, aider, OpenCode. Open an issue if your agent or version is missing.
|
|
9
|
+
- name: CONTRIBUTING.md — the invariants a PR has to keep
|
|
10
|
+
url: https://github.com/aashish254/limen/blob/main/CONTRIBUTING.md
|
|
11
|
+
about: Zero dependencies, colour only on a state word, and a test that would have failed without your change.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
name: Wiring a model or an agent
|
|
2
|
+
description: Add a model backend to the registry, or document an agent's base_url setup
|
|
3
|
+
labels: ["good first issue"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Two kinds of contribution live here, and both are small:
|
|
9
|
+
|
|
10
|
+
**A model backend.** `subproto/systemone/registry.py` is the only file that
|
|
11
|
+
knows model families. If your server already answers `GET /health` and
|
|
12
|
+
`POST /score` (`{"state", "question", "options"}` in, `{option: probability}`
|
|
13
|
+
out), you can point at it today with `SUBPROTO_MODEL=http://host:port` and no
|
|
14
|
+
code change — a registry entry is only needed to give it a name in the report
|
|
15
|
+
and the ablation.
|
|
16
|
+
|
|
17
|
+
**An agent's wiring.** `WIRING.md` holds the exact `base_url` / env setup per
|
|
18
|
+
coding agent. A missing agent, or a setup that changed upstream, is an issue
|
|
19
|
+
worth opening.
|
|
20
|
+
- type: dropdown
|
|
21
|
+
id: kind
|
|
22
|
+
attributes:
|
|
23
|
+
label: Which one is this?
|
|
24
|
+
options: [a model backend / adapter, an agent's wiring page, something else]
|
|
25
|
+
validations:
|
|
26
|
+
required: true
|
|
27
|
+
- type: textarea
|
|
28
|
+
id: contract
|
|
29
|
+
attributes:
|
|
30
|
+
label: For a backend — what does it answer?
|
|
31
|
+
description: >
|
|
32
|
+
Paste a real `curl` of `/health` and of one `/score` request and response. If
|
|
33
|
+
it answers a different shape, say so: the adapter seam is in
|
|
34
|
+
`subproto/systemone/base.py`, and a translation layer there is a reasonable
|
|
35
|
+
change if the question it answers is genuinely the same question.
|
|
36
|
+
render: shell
|
|
37
|
+
- type: textarea
|
|
38
|
+
id: evidence
|
|
39
|
+
attributes:
|
|
40
|
+
label: For a wiring page — how did you verify it?
|
|
41
|
+
description: The command you ran, and the line in `subproto report` that proves traffic reached the proxy.
|
|
42
|
+
- type: textarea
|
|
43
|
+
id: numbers
|
|
44
|
+
attributes:
|
|
45
|
+
label: What it scores on the labelled set (optional, and never required to open this)
|
|
46
|
+
description: >
|
|
47
|
+
`LAYA_URL=http://127.0.0.1:8000 python3 -m bench.ablation --adapters laya` prints
|
|
48
|
+
precision against the shipped heuristic and an `answered N/M` column. A backend
|
|
49
|
+
that answered nothing must print `—`, not a number: if your run shows a number
|
|
50
|
+
for an unreachable endpoint, that is a bug, please open it separately.
|
|
51
|
+
- type: checkboxes
|
|
52
|
+
id: terms
|
|
53
|
+
attributes:
|
|
54
|
+
label: Confirmations
|
|
55
|
+
options:
|
|
56
|
+
- label: I read CONTRIBUTING.md, including the invariants
|
|
57
|
+
required: true
|
|
58
|
+
- label: No API key or proprietary prompt data is pasted above
|
|
59
|
+
required: true
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
## What rule does this change?
|
|
2
|
+
|
|
3
|
+
One or two sentences. Name the decision the code makes, not the file you edited.
|
|
4
|
+
|
|
5
|
+
## How do I see it fail without this change?
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
the command you ran
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Paste the **real** output, including the line that shows the fix.
|
|
12
|
+
|
|
13
|
+
## Gate
|
|
14
|
+
|
|
15
|
+
- [ ] `bash run_tests.sh` prints `ALL GATES PASS` (paste the last 3 lines)
|
|
16
|
+
- [ ] New rule ⇒ new mutant in `bench/mutation_gate.py`, and it is reported `KILLED`
|
|
17
|
+
- [ ] Any printed page touched ⇒ `subproto/tests/test_style.py` still passes
|
|
18
|
+
- [ ] Any claim in README/SPEC/ROADMAP changed ⇒ the number came from a command above
|
|
19
|
+
|
|
20
|
+
## Invariants
|
|
21
|
+
|
|
22
|
+
Which of I2 (cached prefix), I3 (tail is sacred), I4 (local only), I5 (byte
|
|
23
|
+
transparent), I6 (measured not claimed) does this touch, and what keeps it whole?
|
|
24
|
+
|
|
25
|
+
## Labels
|
|
26
|
+
|
|
27
|
+
Fixes #… — or say `no issue` for a drive-by.
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
name: verify
|
|
2
|
+
|
|
3
|
+
# Three jobs, answering three different questions:
|
|
4
|
+
# suite — do the tests pass on someone else's OS, on both supported Pythons?
|
|
5
|
+
# gates — does the whole one-command gate (benches, demo, mutation gate) hold?
|
|
6
|
+
# install — can a stranger `pip install` this and run the command, from a
|
|
7
|
+
# directory that is *not* the clone? Nothing in the runtime may
|
|
8
|
+
# depend on repo files, so this job unpacks the wheel elsewhere.
|
|
9
|
+
#
|
|
10
|
+
# No API key, no spend, no model weights: the Laya legs skip themselves unless
|
|
11
|
+
# SUBPROTO_LAYA_PYTHON names an interpreter that can import `laya`, and `fakeup`
|
|
12
|
+
# stands in for every provider.
|
|
13
|
+
|
|
14
|
+
on:
|
|
15
|
+
push:
|
|
16
|
+
branches: [main]
|
|
17
|
+
pull_request:
|
|
18
|
+
workflow_dispatch:
|
|
19
|
+
|
|
20
|
+
permissions:
|
|
21
|
+
contents: read
|
|
22
|
+
|
|
23
|
+
concurrency:
|
|
24
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
25
|
+
cancel-in-progress: true
|
|
26
|
+
|
|
27
|
+
jobs:
|
|
28
|
+
suite:
|
|
29
|
+
name: pytest ${{ matrix.os }} py${{ matrix.python }}
|
|
30
|
+
runs-on: ${{ matrix.os }}
|
|
31
|
+
strategy:
|
|
32
|
+
fail-fast: false
|
|
33
|
+
matrix:
|
|
34
|
+
python: ["3.9", "3.11"]
|
|
35
|
+
os: [ubuntu-latest, macos-latest]
|
|
36
|
+
include:
|
|
37
|
+
# Windows runs, but is not a release gate: `os.getloadavg` is POSIX and
|
|
38
|
+
# ANSI escape handling differs. It is reported rather than hidden, so a
|
|
39
|
+
# Windows contributor sees the real state of their platform here.
|
|
40
|
+
- os: windows-latest
|
|
41
|
+
python: "3.11"
|
|
42
|
+
continue-on-error: ${{ matrix.os == 'windows-latest' }}
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v4
|
|
45
|
+
- uses: actions/setup-python@v5
|
|
46
|
+
with:
|
|
47
|
+
python-version: ${{ matrix.python }}
|
|
48
|
+
allow-prereleases: false
|
|
49
|
+
- name: Install pytest (the package itself has zero dependencies)
|
|
50
|
+
run: python -m pip install --quiet "pytest>=7"
|
|
51
|
+
- name: Byte-compile every package under -W error
|
|
52
|
+
run: >-
|
|
53
|
+
python -W error -m compileall -q subproto fakeup bench train
|
|
54
|
+
- name: pytest
|
|
55
|
+
run: python -m pytest -q
|
|
56
|
+
|
|
57
|
+
gates:
|
|
58
|
+
name: one-command gate (benches + demo + mutation gate)
|
|
59
|
+
runs-on: ubuntu-latest
|
|
60
|
+
steps:
|
|
61
|
+
- uses: actions/checkout@v4
|
|
62
|
+
- uses: actions/setup-python@v5
|
|
63
|
+
with:
|
|
64
|
+
python-version: "3.11"
|
|
65
|
+
- name: Install dev requirements
|
|
66
|
+
run: python -m pip install --quiet -r requirements-dev.txt
|
|
67
|
+
- name: bash run_tests.sh
|
|
68
|
+
run: bash run_tests.sh
|
|
69
|
+
env:
|
|
70
|
+
PYTHON: python3.11
|
|
71
|
+
|
|
72
|
+
install:
|
|
73
|
+
name: pip install and run (${{ matrix.os }} py${{ matrix.python }})
|
|
74
|
+
runs-on: ${{ matrix.os }}
|
|
75
|
+
strategy:
|
|
76
|
+
fail-fast: false
|
|
77
|
+
matrix:
|
|
78
|
+
os: [ubuntu-latest, macos-latest]
|
|
79
|
+
python: ["3.9", "3.11"]
|
|
80
|
+
steps:
|
|
81
|
+
- uses: actions/checkout@v4
|
|
82
|
+
- uses: actions/setup-python@v5
|
|
83
|
+
with:
|
|
84
|
+
python-version: ${{ matrix.python }}
|
|
85
|
+
- name: Build the sdist and the wheel
|
|
86
|
+
run: |
|
|
87
|
+
python -m pip install --quiet build
|
|
88
|
+
python -m build
|
|
89
|
+
- name: Install the wheel into a clean venv, offline
|
|
90
|
+
run: |
|
|
91
|
+
python -m venv .verify-venv
|
|
92
|
+
.verify-venv/bin/python -m pip install --quiet --no-index --find-links dist subproto
|
|
93
|
+
.verify-venv/bin/python -m pip check
|
|
94
|
+
- name: The installed package agrees about which build it is
|
|
95
|
+
run: |
|
|
96
|
+
.verify-venv/bin/python - <<'PYV'
|
|
97
|
+
import importlib.metadata as md
|
|
98
|
+
import subproto
|
|
99
|
+
assert md.version("subproto") == subproto.__version__, (
|
|
100
|
+
md.version("subproto"), subproto.__version__)
|
|
101
|
+
print("metadata and subproto.__version__ agree:", subproto.__version__)
|
|
102
|
+
PYV
|
|
103
|
+
.verify-venv/bin/subproto --version
|
|
104
|
+
- name: Run the installed command from outside the clone
|
|
105
|
+
shell: bash
|
|
106
|
+
run: |
|
|
107
|
+
set -euo pipefail
|
|
108
|
+
ROOT="$PWD"
|
|
109
|
+
WORK="$(mktemp -d)"
|
|
110
|
+
BIN="$ROOT/.verify-venv/bin/subproto"
|
|
111
|
+
cd "$WORK"
|
|
112
|
+
SUBPROTO_HOME="$WORK/home" "$BIN" --help > /dev/null
|
|
113
|
+
SUBPROTO_HOME="$WORK/home" "$BIN" doctor --port 0 --json > doctor.json
|
|
114
|
+
SUBPROTO_HOME="$WORK/home" "$BIN" demo --port 8743 --slots > demo.log
|
|
115
|
+
SUBPROTO_HOME="$WORK/home" "$BIN" report
|
|
116
|
+
echo "--- doctor ---"; cat doctor.json
|
|
117
|
+
echo "--- demo tail ---"; tail -5 demo.log
|
|
118
|
+
- name: The installed Router ranks on evidence that shipped with it
|
|
119
|
+
shell: bash
|
|
120
|
+
run: |
|
|
121
|
+
set -euo pipefail
|
|
122
|
+
PY="$GITHUB_WORKSPACE/.verify-venv/bin/python"
|
|
123
|
+
# From a directory that is not the clone, twice over: inside the clone a
|
|
124
|
+
# `import subproto` answers from the source tree, so every assertion below
|
|
125
|
+
# would pass with nothing installed at all. A pip user has no source tree,
|
|
126
|
+
# and a Router that reads its ranking evidence out of one worked in CI and
|
|
127
|
+
# nowhere in their day — degrading to manual selection so quietly that no
|
|
128
|
+
# test fails (S46/M4).
|
|
129
|
+
cd "$(mktemp -d)"
|
|
130
|
+
"$PY" -c "import subproto; assert 'site-packages' in subproto.__file__, subproto.__file__"
|
|
131
|
+
"$PY" - <<'PYV'
|
|
132
|
+
import json, os, subproto
|
|
133
|
+
from subproto.systemone import router
|
|
134
|
+
path = router.DEFAULT_ABLATION_JSON
|
|
135
|
+
pkg = os.path.dirname(os.path.abspath(subproto.__file__))
|
|
136
|
+
assert path.startswith(pkg + os.sep), "%s is outside the package" % path
|
|
137
|
+
data = json.load(open(path))
|
|
138
|
+
assert {"heuristic", "adapters"} <= set(data), sorted(data)
|
|
139
|
+
# `adapters` is a list of records keyed by "name" — the schema load_evidence()
|
|
140
|
+
# reads. This used to test `"laya" in data["adapters"]`, a shape guess that was
|
|
141
|
+
# never true of the file and reddened all four install legs of the first public
|
|
142
|
+
# run: the suite proves this through load_evidence(), so nothing local saw it.
|
|
143
|
+
assert "laya" in [a.get("name") for a in data["adapters"]], data["adapters"]
|
|
144
|
+
ev = router.load_evidence()
|
|
145
|
+
assert {"heuristic", "laya"} <= set(ev), sorted(ev)
|
|
146
|
+
print("installed Router ranks on %s" % os.path.relpath(path, pkg))
|
|
147
|
+
PYV
|
|
148
|
+
- name: Confirm the sdist carries what the docs tell people to run
|
|
149
|
+
run: |
|
|
150
|
+
python - <<'PYSMOKE'
|
|
151
|
+
import glob, os, tarfile
|
|
152
|
+
name = glob.glob("dist/*.tar.gz")[0]
|
|
153
|
+
names = set(tarfile.open(name).getnames())
|
|
154
|
+
top = os.path.basename(name)[: -len(".tar.gz")]
|
|
155
|
+
need = ["pyproject.toml", "run_tests.sh", "bench/ablation.py",
|
|
156
|
+
"bench/mutation_gate.py", "fakeup/server.py", "WIRING.md"]
|
|
157
|
+
missing = [n for n in need if "%s/%s" % (top, n) not in names]
|
|
158
|
+
assert not missing, "sdist is missing: %s" % missing
|
|
159
|
+
print("sdist carries the bench and the fakeup mock")
|
|
160
|
+
PYSMOKE
|
|
161
|
+
- name: Run install.sh, the no-package-index route the README leads with
|
|
162
|
+
run: |
|
|
163
|
+
set -euo pipefail
|
|
164
|
+
SUBPROTO_BIN_DIR="$PWD/.verify-bin" bash install.sh
|
|
165
|
+
export SUBPROTO_HOME="$(mktemp -d)"
|
|
166
|
+
./.verify-bin/subproto doctor --port 0 --json
|
|
167
|
+
./.verify-bin/subproto demo --port 8744 --slots > /dev/null
|
|
168
|
+
./.verify-bin/subproto report | head -3
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: pages
|
|
2
|
+
|
|
3
|
+
# The landing page is a build artifact of the measurement run, so it is committed and
|
|
4
|
+
# published as-is: `bench/launch_stats.py` measures, `tools/make_site.py` renders, and
|
|
5
|
+
# this workflow only carries `_site/` to Pages. Nothing recomputes a number here, so the
|
|
6
|
+
# page a reviewer reads on github.io is byte-identical to the one in the repo.
|
|
7
|
+
|
|
8
|
+
on:
|
|
9
|
+
push:
|
|
10
|
+
branches: [main]
|
|
11
|
+
paths: ["_site/**", "docs/assets/fonts/**", ".github/workflows/pages.yml"]
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
|
|
14
|
+
permissions:
|
|
15
|
+
contents: read
|
|
16
|
+
pages: write
|
|
17
|
+
id-token: write
|
|
18
|
+
|
|
19
|
+
concurrency:
|
|
20
|
+
group: pages
|
|
21
|
+
cancel-in-progress: false
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
deploy:
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
environment:
|
|
27
|
+
name: github-pages
|
|
28
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@v4
|
|
31
|
+
- name: Refuse to publish a page with an unrendered token
|
|
32
|
+
run: |
|
|
33
|
+
if grep -rl '{{[A-Z_]*}}' _site >/dev/null 2>&1; then
|
|
34
|
+
grep -rn '{{[A-Z_]*}}' _site
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
test -s _site/index.html
|
|
38
|
+
- uses: actions/configure-pages@v5
|
|
39
|
+
- uses: actions/upload-pages-artifact@v3
|
|
40
|
+
with:
|
|
41
|
+
path: _site
|
|
42
|
+
- id: deployment
|
|
43
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
name: publish
|
|
2
|
+
|
|
3
|
+
# The release is built and uploaded from the tag, by CI, with no credential stored on
|
|
4
|
+
# anybody's laptop: PyPI trusts this workflow's OIDC identity, registered once as a
|
|
5
|
+
# "pending publisher" on pypi.org. Nothing here recomputes a number — `verify` is the
|
|
6
|
+
# gate on the code, and this job only packages the tagged tree, proves the artifact
|
|
7
|
+
# installs and runs, and hands it to the index.
|
|
8
|
+
|
|
9
|
+
on:
|
|
10
|
+
push:
|
|
11
|
+
tags: ["v*"]
|
|
12
|
+
workflow_dispatch:
|
|
13
|
+
inputs:
|
|
14
|
+
tag:
|
|
15
|
+
description: Which tag to publish
|
|
16
|
+
default: v0.1.0
|
|
17
|
+
type: string
|
|
18
|
+
|
|
19
|
+
permissions:
|
|
20
|
+
contents: read
|
|
21
|
+
id-token: write
|
|
22
|
+
|
|
23
|
+
concurrency:
|
|
24
|
+
group: publish
|
|
25
|
+
cancel-in-progress: false
|
|
26
|
+
|
|
27
|
+
jobs:
|
|
28
|
+
publish:
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
environment: pypi
|
|
31
|
+
steps:
|
|
32
|
+
- uses: actions/checkout@v4
|
|
33
|
+
with:
|
|
34
|
+
ref: ${{ github.event.inputs.tag || github.ref_name }}
|
|
35
|
+
- uses: actions/setup-python@v5
|
|
36
|
+
with:
|
|
37
|
+
python-version: "3.11"
|
|
38
|
+
- name: Every classifier must be one PyPI recognises
|
|
39
|
+
run: |
|
|
40
|
+
set -euo pipefail
|
|
41
|
+
python - <<'PYP'
|
|
42
|
+
import re, html, tomllib, urllib.request
|
|
43
|
+
declared = tomllib.load(open("pyproject.toml", "rb"))["project"]["classifiers"]
|
|
44
|
+
page = urllib.request.urlopen("https://pypi.org/classifiers/").read().decode()
|
|
45
|
+
valid = {html.unescape(re.sub(r"<[^>]+>", "", m.group(1))).strip()
|
|
46
|
+
for m in re.finditer(r'data-clipboard-target="source">(.*?)</a>', page, re.S)}
|
|
47
|
+
assert len(valid) > 500, "the classifier list did not parse (%d)" % len(valid)
|
|
48
|
+
bad = [c for c in declared if c not in valid]
|
|
49
|
+
for c in declared:
|
|
50
|
+
print("%s %s" % ("ok " if c not in bad else "BAD ", c))
|
|
51
|
+
# One invented trove 400s the whole upload, after the files are already sent.
|
|
52
|
+
assert not bad, "not on https://pypi.org/classifiers/: %s" % bad
|
|
53
|
+
PYP
|
|
54
|
+
- name: Build the sdist and the wheel
|
|
55
|
+
run: |
|
|
56
|
+
python -m pip install --quiet build twine
|
|
57
|
+
python -m build
|
|
58
|
+
twine check dist/*
|
|
59
|
+
- name: The artifact must carry the version the tag was cut from
|
|
60
|
+
run: |
|
|
61
|
+
set -euo pipefail
|
|
62
|
+
REF="${{ github.event.inputs.tag || github.ref_name }}"
|
|
63
|
+
TAG="${REF#v}"
|
|
64
|
+
SRC="$(python -c 'import subproto; print(subproto.__version__)')"
|
|
65
|
+
WHEEL="$(basename dist/*.whl)"
|
|
66
|
+
echo "tag=$TAG source=$SRC wheel=$WHEEL"
|
|
67
|
+
test "$SRC" = "$TAG" || { echo "subproto.__version__ disagrees with the tag"; exit 1; }
|
|
68
|
+
test "$WHEEL" = "subproto-$TAG-py3-none-any.whl" \
|
|
69
|
+
|| { echo "the built wheel is not tagged $TAG"; exit 1; }
|
|
70
|
+
- name: Install the built wheel offline and run it
|
|
71
|
+
run: |
|
|
72
|
+
set -euo pipefail
|
|
73
|
+
python -m venv .smoke
|
|
74
|
+
.smoke/bin/python -m pip install --quiet --no-index --find-links dist subproto
|
|
75
|
+
.smoke/bin/python -m pip check
|
|
76
|
+
cd "$(mktemp -d)"
|
|
77
|
+
SUBPROTO_HOME="$PWD" .smoke/bin/subproto --version
|
|
78
|
+
SUBPROTO_HOME="$PWD" .smoke/bin/subproto doctor --port 0 > /dev/null
|
|
79
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
80
|
+
with:
|
|
81
|
+
verbose: true
|