diff --git a/README.md b/README.md index 677ed2e..f9f821c 100644 --- a/README.md +++ b/README.md @@ -16,11 +16,11 @@ It is not a marketplace and there is no network to join. You run both halves — product, and [D2](docs/decisions/D2-economics.md) for the arithmetic that ruled out the alternative. -**This is the v1.0.0 feature-complete milestone — not a maturity claim.** It means the -v1 scope is built and the gate is green, not that anyone has run this in anger. Read -"What is actually true" before relying on anything here. +**This is the v1.0.1 feature-complete milestone — not a maturity claim.** It means the +v1 scope is built and the gate is green on every supported platform, not that anyone +has run this in anger. Read "What is actually true" before relying on anything here. -## What is actually true, as of 2026-08-15 +## What is actually true, as of 2026-08-17 Verified, not aspirational. `STATUS.md` is generated from real test runs; this section summarises it in prose. @@ -29,9 +29,18 @@ section summarises it in prose. Zenoh mesh, advertises the models Ollama actually has, and survives the Scheduler being unreachable. The Scheduler matchmakes, dispatches over the mesh (which is how a node behind NAT is reachable at all), and exposes an OpenAI-shaped gateway behind -RS256 JWT auth. State can persist across restarts. CI runs the gate on Linux, macOS -and Windows across Python 3.11–3.14; `STATUS.md` records the last measured result and -the commit it covers. +RS256 JWT auth. State can persist across restarts. + +CI runs the gate on Linux, macOS and Windows across Python 3.11–3.14 — ten jobs — and +as of `25fe60c` all ten pass. Worth stating plainly rather than as a badge: **they did +not, from 2026-08-09 to 2026-08-17.** The three Windows legs were red for eight days, +across the `v1.0.0` release commit, and nothing in this repository noticed. See +"What we cannot see" below, because that gap is more instructive than the bug was. + +**If `STATUS.md` and the paragraph above disagree, they are both right.** That claim +comes from reading the run directly; `STATUS.md` reports `UNVERIFIABLE` whenever it is +generated on a machine without the `gh` CLI, because that is the only way it knows how +to ask. Regenerate it where `gh` is installed and authenticated and the line resolves. **Does not work, and is not claimed to:** @@ -51,8 +60,59 @@ the commit it covers. there is no payout path — not "not yet", but a decision ([D2](docs/decisions/D2-economics.md)). - **There is no content filtering, no meaningful rate limiting, and no backups**, and - nothing verifies that a node ran the model it claims. + nothing verifies that a node ran the model it claims. The rate limiter is a + per-instance abuse dampener, not a quota. Canary checks catch a host running *no* + model; they cannot catch a host running the *wrong* one. [`docs/OPERATING.md`](docs/OPERATING.md) lists what you take on by running this. +- **`/v1/batch` is not implemented** — it answers 501. It is authenticated and + tenant-scoped, because those were real fixes to a real hole, but it dispatches + nothing. +- **JWTs cannot be revoked.** They are stateless by design; the mitigations are a + server-enforced TTL cap and key rotation. There is no revoke button and this is + said plainly rather than implied away. +- **Nodes installed before [D9](docs/decisions/D9-admission-is-not-identity.md) keep + the old weakness** — one header meaning both fleet admission and node identity — + until they are upgraded. That is a deliberate compatibility choice, not an + oversight: refusing them would strand every running host. + +## What we cannot see + +Distinct from the list above, which is what does not *work*. This is what this +project's own verification **cannot observe** — the gaps where a defect would not be +caught by anything here. It is written down because +[`docs/PREMISES.md`](docs/PREMISES.md) P8 records that every falsification of "the +gate is the definition of does this pass" has arrived by **absence rather than +failure**, and an unlisted absence is indistinguishable from an all-clear. + +- **`install.ps1` has never been executed, by anything, ever.** `install.sh` gets a + real run against a throwaway tree (`scripts/verify_install.sh`); the PowerShell + installer is only ever *read* — `scripts/audit_system.py` greps it for strings and + `tests/test_installer_parity.py` ratchets its structure. Every Windows install + defect to date (W1–W5, W8) was therefore found by a person on a real machine, not + by the gate. Assume the next one will be too. +- **The repository cannot read its own CI.** `scripts/generate_status.py` shells out + to `gh`; where `gh` is absent it reports `UNVERIFIABLE — cannot query run history`. + That is honest, and it reads like "no known problem". It is the mechanism by which + a red build sat under a published release for eight days. **The fix is known and + not yet made:** fall back to the GitHub REST API so the answer does not depend on + which machine regenerated the file. +- **Work on a branch is unverified until it becomes a pull request.** The workflow + triggers only on `push` to `main` and on PRs, so a feature branch gets no CI at all. +- **The local gate is one operating system and one interpreter.** CI is nine legs; a + developer's run is one. Platform-specific defects are structurally invisible + locally, and there have now been three: a cp1252 text encoding (2.9), CRLF line + endings (V1), and wall-clock resolution (V2). A local `PASS` is a weaker claim than + a CI `PASS` and the gate says so in its own output. +- **The gate skips checks it cannot run**, naming them as `DID NOT RUN`: a missing + interpreter, `shellcheck` if absent, the website suite without `node_modules`. The + honesty is real; the coverage still is not there. +- **`docker-compose.test.yml` has never run.** Two defects were found in it by + reading (`tests/test_compose_env_matches_settings.py`) rather than by executing it. +- **Four module pairs in `experimental/` remain duplicated** — `quantization`, + `local_boundary`, `kv_cache`, `transport`. Drift is ratcheted, not eliminated. +- **No human outside this project has reviewed any of it.** Two independent AI desk + reviews of the market premises are in [`docs/review/`](docs/review/) and they + converged, which is evidence but not independence. ## What this project has decided, and what it hasn't diff --git a/ROADMAP.md b/ROADMAP.md index 1c3c7f7..15be180 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,8 +1,16 @@ # ROADMAP — v1 -Status: **Stages 0–4, C and D are complete. 1.5 is half earned — a second machine -served a real request over the mesh on 2026-08-11, but not across a real NAT. -D7 is open. W1–W10 are done; W7 is done in code and unexercised on real hardware.** +Status: **Stages 0–4, C and D are complete. Released as `v1.0.1` on 2026-08-17, with +CI green on all ten jobs (Linux/macOS/Windows × Python 3.11–3.14) at `25fe60c`. +1.5 is half earned — a second machine served a real request over the mesh on +2026-08-11, but not across a real NAT. D7 is open. W1–W10 are done; W7 is done in +code and unexercised on real hardware. V1–V3 closed the Windows CI failure that had +been red since 2026-08-09, including across the `v1.0.0` release commit.** + +**`v1.0.0` was released on 2026-08-15 over a red CI run, and the tag is deliberately +left where it is.** Moving it would have silently changed the bytes its published +release hands out. `v1.0.1` is the first release whose commit CI has ever passed on +every supported platform. Both tags stand: `v1.0.0` → `39f0227`, `v1.0.1` → `25fe60c`. What is NOT done, and why, so this line does not have to be re-derived: diff --git a/STATUS.md b/STATUS.md index 68b7477..d01385a 100644 --- a/STATUS.md +++ b/STATUS.md @@ -4,16 +4,16 @@ -**Generated:** 2026-08-17 03:27 UTC +**Generated:** 2026-08-17 05:19 UTC **Test status:** PASSING ## Tests | Suite | Status | Passed | Failed | Skipped | Time | | --- | --- | --- | --- | --- | --- | -| Scheduler | PASS | 397 | 0 | 0 | 11.40s | -| Node | PASS | 260 | 0 | 1 | 2.83s | -| Root E2E | PASS | 249 | 0 | 0 | 26.42s | +| Scheduler | PASS | 397 | 0 | 0 | 13.39s | +| Node | PASS | 260 | 0 | 1 | 3.85s | +| Root E2E | PASS | 249 | 0 | 0 | 28.35s | | **Total** | **PASSING** | **906** | **0** | **1** | | Reproduce: @@ -26,23 +26,12 @@ Reproduce: ## Git -- **Last commit:** `b31fce3` one command to host a node -- **Author / date:** Claude — 2026-08-16 16:21:21 +0000 +- **Last commit:** `214bcb8` docs: record the real state, including what we cannot see +- **Author / date:** Claude — 2026-08-17 05:18:43 +0000 - **Branch:** claude/v1-wrap-up-checklist-6uadua -- **Total commits:** 50 +- **Total commits:** 52 - **Remote:** origin https://github.com/Epichlo/Public-Intelligence (fetch) -- **Working tree:** 8 uncommitted change(s) - -``` - M ROADMAP.md - M packages/scheduler/src/scheduler/api/openai.py - M packages/scheduler/tests/test_metering_and_accrual.py - M packages/website/package.json - M tests/test_source_parity.py - ?? .gitattributes - ?? specs/ci-green-on-windows.md - ?? tests/test_line_endings.py -``` +- **Working tree:** clean ## CI @@ -58,7 +47,7 @@ _Measured, not asserted. Re-run to refresh._ | Repo | Remote | Branch | Tracking | | --- | --- | --- | --- | -| root | `https://github.com/Epichlo/Public-Intelligence` | claude/v1-wrap-up-checklist-6uadua | **none** | +| root | `https://github.com/Epichlo/Public-Intelligence` | claude/v1-wrap-up-checklist-6uadua | origin/claude/v1-wrap-up-checklist-6uadua | - **`.gitmodules`:** absent, which is correct — `packages/` are ordinary directories since the 2026-08-04 monorepo migration, and CI's fresh-clone job asserts this file does not come back. - **root venv interpreter:** Python 3.11.15 diff --git a/VERIFY.md b/VERIFY.md index d0003a1..31b70ce 100644 --- a/VERIFY.md +++ b/VERIFY.md @@ -89,8 +89,22 @@ The first grep returns four benign hits, and no others: **Everything else it returns is real.** If it comes back completely clean, the pattern is broken, not the code. -The auth-bypass grep returns one hit, `packages/website/src/app/architecture/page.tsx:42`, -which is prose containing the word "bypassing", not code. +The auth-bypass grep returns **three** hits, all of them prose rather than code: + +- `packages/website/src/app/architecture/page.tsx:42` — page copy containing the word + "bypassing". +- `packages/scheduler/src/scheduler/api/ingress.py:69` — a comment explaining how a + `kid`-aware verifier turns into a bypass, naming the test that pins it + (`test_an_unknown_kid_does_not_bypass_verification`). +- `packages/scheduler/src/scheduler/core/rate_limiter.py:54` — a comment explaining + why evicting a depleted bucket would be a rate-limit bypass. + +**This line said "one hit" until 2026-08-17, when there were three.** Both extra hits +are comments describing bypasses being *prevented*, and both predate the correction — +so nothing was wrong with the code, and the count was wrong for long enough that the +instruction two paragraphs down ("check each hit against that list, because a new one +hides among them") had become harder to follow than it looks. A known-good list that +is stale by two is a list that trains you to skim. **Known pre-existing hits as of 2026-08-03** — these are real and unfixed. Do not let them mask a *new* one, and do not report them as clean: @@ -197,7 +211,9 @@ git check-ignore -q .secrets/probe && echo ".secrets/ ignored" || echo "!! .secr these are **source files**, not credential files. The private-key grep matches `test_credential_issuance.py`, whose fixture is the literal string `-----BEGIN PRIVATE KEY-----\nnonsense\n-----END PRIVATE KEY-----`, used to assert -that an unreadable key produces a 503 carrying no key material. +that an unreadable key produces a 503 carrying no key material — **and this file**, +`VERIFY.md`, which matches because the previous sentence quotes that fixture. Two +hits, both benign, one of them self-referential. ## 6. Regenerate STATUS.md diff --git a/docs/PREMISES.md b/docs/PREMISES.md index df0ee4e..b3393eb 100644 --- a/docs/PREMISES.md +++ b/docs/PREMISES.md @@ -119,6 +119,27 @@ shape of the second. than failure.** The gate did not lint `tests/`. It did not type-check `tests/`. It did not touch the website. It ran an installer dry-run that returned early from every step. Each gap was invisible precisely because the gate was trusted as total. + +**2026-08-17 added a new shape of falsification, and it is worse than the others.** +The gate ran, CI ran, CI *failed* — and no one read it for eight days, across a +published `v1.0.0` release. Every prior instance was a check that did not exist. This +was a check that existed, executed, and reported red into a void, because +`scripts/generate_status.py` shells out to `gh` and reports `UNVERIFIABLE` where `gh` +is absent. "I could not look" is honest and scans as "nothing is wrong". + +The current known gaps, enumerated so that an unlisted absence is not mistaken for an +all-clear (kept in sync with the README's "What we cannot see"): + +- `install.ps1` has **never been executed by anything**; it is only ever read. Every + Windows install defect so far was found by a person, not by the gate. +- The repository **cannot read its own CI** without `gh` on the PATH. Fix known + (REST API fallback), not yet made. +- **Branches get no CI** — the workflow triggers on `push` to `main` and on PRs only. +- The local gate is **one OS and one interpreter**; platform-specific defects are + structurally invisible to it. Three so far: cp1252 encoding, CRLF line endings, + wall-clock resolution. +- **`docker-compose.test.yml` has never run.** + **Confidence:** high that it catches what it checks; **low that anyone knows what it does not check**. The correct posture toward this file's own subject. @@ -135,12 +156,39 @@ interpretation of the project's own history rather than a claim about the world. is listed anyway because it drives more process than anything else on this page, and process justified by an unfalsifiable belief is worth naming as such. +## P10 — Sending a prompt to a peer's machine is an acceptable trade for pooling + +**Supports:** the whole multi-machine framing; whatever survives of P1's federation +half after the desk review. +**Evidence:** none gathered. This premise was surfaced by the 2026-08-14 desk review +as "the privacy paradox" and sat outside this register until 2026-08-17, which is +itself the finding — the register's own instruction is that an unregistered +assumption is one nobody can attack. + +The tension is direct. The motivation for running models locally is usually *"nothing +leaves hardware I own."* Routing a request to somebody else's node breaks exactly that +property. P6 constrains what this **code persists**; it says nothing about where a +prompt **travels**, and the two are routinely conflated. + +**Falsifier:** the users who want local inference want it for privacy, in which case +pooling across other people's machines is not a smaller version of the same product — +it is the opposite product, and the addressable set is only people who trust every +host in their pool. Note this does **not** fire for the self-hosted-fleet case +([D6](decisions/D6-is-there-a-network.md)), where every machine belongs to the same +person or organisation. It fires precisely for the cross-party pooling the desk review +identified as the one surviving differentiator. +**Confidence:** **low, and load-bearing.** If P10 fails, cross-party pooling fails +with it, and P2 has already been moved to low confidence — which would leave the +project's differentiator resting on two low-confidence premises at once. + --- ## How to attack this list -- Pick the premise with the lowest stated confidence (**P2**), and ask whether the - people it describes exist. +- Pick either of the lowest-confidence premises (**P2**, **P10**) and ask whether the + people they describe exist. They are now the same question from two sides: P2 asks + whether anyone needs this to reach a machine, P10 asks whether anyone who does would + accept where their prompt goes. A single answer can falsify both. - Pick the one with the largest downstream commitment (**P3**), and check the inputs against a real electricity bill and a real card. - Pick the one whose falsifier says "none available" (**P9**), and ask whether the @@ -162,8 +210,9 @@ routes a whole request to one node); the codebase refutes that specific claim. S review's addendum. **Neither run closes D7** — two models gathered external evidence; neither is an external human judge. -A candidate new premise surfaced and is not yet in this register: **the privacy -paradox** — routing a prompt to a *peer's* machine breaks the "nothing leaves hardware -I own" property that motivates local AI (P6 covers only what this code persists, not -where a prompt travels). If the product continues, that belongs here as its own -falsifiable claim. +The candidate premise that review surfaced — **the privacy paradox** — was registered +as **P10** on 2026-08-17. It had sat outside this file for three days while the file's +own argument is that an unregistered assumption is one nobody can attack. + +Last updated 2026-08-17: P8 gained the enumerated verification gaps, P10 was added. +**Still reviewed only by the author, and still the problem.**