Skip to content

Commit 4eb7c34

Browse files
mstrathmanclaude
andcommitted
chore: public-readiness pass
- Remove every reference to the internal design spec (RFC 0005 section numbers, draft mentions, the predict_version "spec":"0005-draft" field and its SQLITE_PREDICT_SPEC define): the public contract is the docs site; comments now describe the behavior in place - Reword overused "honest" phrasing across README, docs site, benchmarks, C comments, and the PR template - Add Dependabot config (actions, website npm, node binding, cargo, pip) - Add bug-report and feature-request issue forms - Add crates.io/PyPI/npm version badges to the README Repo settings applied via API (not in this diff): de-receipted the repo description, set homepage + topics, disabled wiki/projects, enabled Dependabot security updates, default workflow token now read-only, and a protect-main ruleset blocks force pushes and branch deletion. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
1 parent dd2e306 commit 4eb7c34

35 files changed

Lines changed: 163 additions & 93 deletions
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Bug report
2+
description: Something behaves incorrectly, crashes, or contradicts the docs.
3+
labels: [bug]
4+
body:
5+
- type: input
6+
id: version
7+
attributes:
8+
label: Version
9+
description: Output of `SELECT predict_version()`, or the package version.
10+
placeholder: v0.0.1-alpha.6
11+
validations:
12+
required: true
13+
- type: input
14+
id: platform
15+
attributes:
16+
label: Platform
17+
description: OS/arch and how you installed (pip, npm, cargo, prebuilt binary, amalgamation).
18+
placeholder: macOS arm64, pip install sqlite-predict
19+
validations:
20+
required: true
21+
- type: textarea
22+
id: repro
23+
attributes:
24+
label: Reproduction
25+
description: The smallest SQL that shows the problem. Include table DDL and a few rows of data if the shape matters.
26+
render: sql
27+
validations:
28+
required: true
29+
- type: textarea
30+
id: expected
31+
attributes:
32+
label: Expected vs actual
33+
description: What you expected, and what happened instead (paste the full error message, they are designed to be pasted).
34+
validations:
35+
required: true
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: Feature request
2+
description: A capability, model, or interface you need that does not exist yet.
3+
labels: [enhancement]
4+
body:
5+
- type: textarea
6+
id: problem
7+
attributes:
8+
label: What are you trying to do?
9+
description: The task in your own terms, ideally with the SQL you wish you could write.
10+
validations:
11+
required: true
12+
- type: textarea
13+
id: today
14+
attributes:
15+
label: What do you do today instead?
16+
description: Workarounds, external tools, or "nothing, it blocks me".
17+
- type: textarea
18+
id: shape
19+
attributes:
20+
label: Proposed shape (optional)
21+
description: If you have an opinion on the SQL surface or options, sketch it.

‎.github/dependabot.yml‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: github-actions
4+
directory: /
5+
schedule:
6+
interval: weekly
7+
- package-ecosystem: npm
8+
directory: /website
9+
schedule:
10+
interval: weekly
11+
groups:
12+
site:
13+
patterns: ["*"]
14+
- package-ecosystem: npm
15+
directory: /bindings/node
16+
schedule:
17+
interval: weekly
18+
- package-ecosystem: cargo
19+
directory: /
20+
schedule:
21+
interval: weekly
22+
- package-ecosystem: pip
23+
directory: /tests
24+
schedule:
25+
interval: weekly

‎.github/pull_request_template.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- Thanks for contributing. Please keep this checklist honest. -->
1+
<!-- Thanks for contributing. Please keep this checklist accurate. -->
22

33
## What and why
44

‎ARCHITECTURE.md‎

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Source layout:
2020
| `predict-registry.c` | the model registry (`_predict_models`) and content hashing |
2121
| `predict-onnx.c` | ONNX runtime backend (opt-in build only); the only file that links onnxruntime |
2222
| `predict-student.c` | the native student **serving** runtime: blob (de)serialization and tree / forest / MLP inference (`predict0_tree_run`). The serve side of the train/serve boundary |
23-
| `predict-student.h` | the shared student-model **format**: the tree/forest/MLP structs and the runtime entry points both sides agree on (RFC §4.1.3) |
23+
| `predict-student.h` | the shared student-model **format**: the tree/forest/MLP structs and the runtime entry points both sides agree on |
2424
| `predict-distill.c` | the **training** side: the CART / gradient-boosting / MLP trainers, the `distill_predict()` vtab, and the `distill_forecast()` vtab that fits the forecast student. Builds student blobs that `predict-student.c` serves |
2525
| `predict-internal.h` | shared types, contract constants, error codes, internal prototypes |
2626
| `vendor/sha256.c` | a self-contained FIPS 180-4 SHA-256 |
@@ -89,7 +89,7 @@ bytes run. Both run on CPU. A GPU build (`make loadable-onnx-gpu`,
8989
fp16/int8 precision; the provider-options symbols are in every onnxruntime
9090
C API, so it compiles and links against the CPU onnxruntime for a CI
9191
compile-check, while real GPU execution is validated on a dedicated GPU job.
92-
GPU results are honestly distinguishable from the deterministic CPU path
92+
GPU results stay distinguishable from the deterministic CPU path
9393
(provider and precision are explicit options, never silent fallbacks).
9494
Even so, the `benchmarks/` numbers (and the TabFM→ONNX eval in
9595
`benchmarks/results/tabfm-onnx.md`) are why the default answer for a
@@ -130,19 +130,19 @@ a `tree`-runtime model to the native runtime in the same file, which tells a
130130
single tree (`PSTREE` blob) from a forest (`PSGBT` blob) from a net (`PSMLP`
131131
blob) by magic and needs
132132
no onnxruntime. The blob formats are little-endian and normatively specified
133-
and versioned (RFC §4.1.3, `PSTREE01` / `PSGBT01` / `PSMLP01`), so a stored student stays
133+
and versioned (`PSTREE01` / `PSGBT01` / `PSMLP01`), so a stored student stays
134134
servable across upgrades, snapshots, and forks, and a serving-only module can
135135
execute a blob it never trained. They are rigorously bounds-checked on read,
136136
because the registry is
137-
writable by any SQL caller (RFC §6.2): a hand-crafted blob is rejected,
137+
writable by any SQL caller: a hand-crafted blob is rejected,
138138
never crashed on. The student is native and deterministic, like the stat
139139
models.
140140

141141
Forecasting has its own student. `distill_forecast()` (`predict-distill.c`)
142142
fits a regression MLP that maps an instance-normalized context window of `nfeat`
143143
recent values to `nquant` quantiles per horizon step, distilled from a teacher's
144144
forecasts over sliding windows. It is stored as a fourth student blob (`PSFCST`,
145-
RFC §4.1.3) and served not by `predict()` but by `forecast()`
145+
the same registry format) and served not by `predict()` but by `forecast()`
146146
(`predict-forecast.c`), which extracts the most recent window, normalizes it by
147147
its own mean and standard deviation (so one student serves series of any
148148
magnitude), applies the net, and de-normalizes. When the student carries a
@@ -164,13 +164,4 @@ fp16 inference is not bit-reproducible across machines (different hardware
164164
and kernels round differently). Cross-machine, cross-backend bit-equality
165165
is never claimed (see `benchmarks/notes.md`).
166166

167-
## Spec alignment
168-
169-
The design spec (RFC 0005) has been amended to match the implemented
170-
surface: the `ts-stat`/`tabular-stat` model kinds, the aggregate calling
171-
convention for `forecast` and `detect_anomalies`, null option values
172-
meaning "key omitted," and the removal of receipts (that design is
173-
preserved in the RFC's Appendix D). Section references in this document
174-
follow the amended numbering.
175-
176167
[tvf]: https://www.sqlite.org/vtab.html#tabfunc2

‎CHANGELOG.md‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4747
self-correcting error. The receipts/replay system explored during
4848
development (in-DB anchored receipts, then input-digest commitments,
4949
then document receipts) was removed before release: prediction is the
50-
product, provenance was drag; the designs live in git history and the
51-
RFC's deferred appendix. The model registry (`_predict_models`) remains:
50+
product, provenance was drag; the designs live in git history. The
51+
model registry (`_predict_models`) remains:
5252
content-addressed models and distilled students, hashes verified before
5353
deserialization.
5454
- **Auto model selection, conformal intervals, and `backtest()`.**
@@ -91,8 +91,8 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
9191
- `distill_forecast()` trains a native **forecast student**: a regression net
9292
that maps an instance-normalized context window to future values, distilled
9393
from a teacher's forecasts (a foundation model run offline, or any per-window
94-
teacher) over sliding windows. It registers a `PSFCST` inline BLOB (RFC 0005
95-
§4.1.6) that `forecast()` serves natively, with no teacher and no onnxruntime,
94+
teacher) over sliding windows. It registers a `PSFCST` inline BLOB
95+
that `forecast()` serves natively, with no teacher and no onnxruntime,
9696
deterministically and in microseconds. The student is a **DLinear/TiDE-style
9797
net**: a direct linear map from the context to the fan (which carries the
9898
seasonal-naive + trend structure) plus a small, scaled nonlinear residual. A
@@ -131,7 +131,7 @@ project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
131131
rank; there is no forecast/interval. On a broad 200-series TSB-AD-U sample it
132132
scores 0.44 median VUS-PR (at the published SOTA level) versus the theta
133133
residual detector's 0.23 -- roughly 2x on the typical series, all in zero-
134-
dependency C. Two honest caveats: the *mean* gap is
134+
dependency C. Two caveats: the *mean* gap is
135135
much smaller (0.41 vs 0.38) because sub-pca fails badly on weakly-periodic or
136136
very long series where the fixed-window PCA does not fit, so the two are partly
137137
complementary; and on a subset filtered to moderate-length periodic series the

‎README.md‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
[![CI](https://github.com/PureStorage-OpenConnect/sqlite-predict/actions/workflows/ci.yml/badge.svg)](https://github.com/PureStorage-OpenConnect/sqlite-predict/actions/workflows/ci.yml)
44
[![License: MIT OR Apache-2.0](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](#license)
5+
[![crates.io](https://img.shields.io/crates/v/sqlite-predict.svg)](https://crates.io/crates/sqlite-predict)
6+
[![PyPI](https://img.shields.io/pypi/v/sqlite-predict.svg)](https://pypi.org/project/sqlite-predict/)
7+
[![npm](https://img.shields.io/npm/v/sqlite-predict.svg)](https://www.npmjs.com/package/sqlite-predict)
58
![C99](https://img.shields.io/badge/C99-zero%20dependencies-brightgreen.svg)
69

710
**Prediction as a SQL primitive.** `forecast()`, `detect_anomalies()`, and
@@ -32,7 +35,7 @@ that lives inside your database and runs anywhere.
3235

3336
## Is it accurate?
3437

35-
Yes, and the numbers are honest and reproducible (`benchmarks/`), not a demo on
38+
Yes, and the numbers are measured and reproducible (`benchmarks/`), not a demo on
3639
a toy series.
3740

3841
- **Forecasting.** A Chronos foundation model distilled into a zero-dependency
@@ -166,7 +169,7 @@ SELECT avg(coverage) FROM backtest('SELECT ts, value FROM readings', 6,
166169
## Models
167170

168171
The default build is **pure C with no dependencies**. It ships small,
169-
honest statistical models:
172+
well-studied statistical models:
170173

171174
- `theta-classic` (the Theta method) and `stub-seasonal-naive` for `forecast()`
172175
and `detect_anomalies()`; `tsb` (Teunter-Syntetos-Babai) for

‎benchmarks/compare_tabular.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
Candidates: Google TabFM (local weights under models/tabfm, downloaded
44
from google/tabfm-1.0.0-pytorch — license tabfm-non-commercial-v1.0,
5-
benchmark/evaluation use), plus honest floors (majority class / global
5+
benchmark/evaluation use), plus baseline floors (majority class / global
66
mean) and a pure-python 5-NN so wins are attributable. The extension's
77
predict() column joins when M4 lands. Unavailable candidates are
88
reported SKIPPED, never silently dropped.

‎benchmarks/forecast_distill.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424
GENERICITY. Every hyperparameter is a fixed function of the seasonal period M
2525
(R=2M recent lags, min-origin 3M, stride M/2), and M comes from dataset
2626
metadata, not from tuning. The SAME pipeline runs on all three regimes. This is
27-
the honest test: on m4_hourly the FM beats the stat floor, so distillation
27+
the real test: on m4_hourly the FM beats the stat floor, so distillation
2828
should help; on tourism_monthly the FM does not beat our stat model (see
29-
forecast.md), so an honest method must NOT manufacture a win there. Nothing is
29+
forecast.md), so a sound method must NOT manufacture a win there. Nothing is
3030
selected on the test window.
3131
3232
FM forecasts are cached per (dataset, series, origin) under

‎benchmarks/forecast_native.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
This is the end-to-end proof that a *capable* student recovers most of a
55
forecast FM's edge, where a tree student could not. Chronos labels sliding
66
context windows (offline, cached); `distill_forecast` fits a multi-output
7-
regression MLP (PSFCST, RFC 0005 §4.1.6) that reproduces the teacher; then
7+
regression MLP (a PSFCST blob) that reproduces the teacher; then
88
`forecast()` serves that native student with no teacher and no onnxruntime.
99
1010
On m4_hourly (80 series, context 256, horizon 48):

0 commit comments

Comments
 (0)