Skip to content

Commit 9a5c93b

Browse files
committed
Phase 1 design: pin CI's checkpoint on a rebase, and name the local wheel's source
Signed-off-by: Adi Wadaskar <awadaskar@nvidia.com>
1 parent 44607bc commit 9a5c93b

1 file changed

Lines changed: 5 additions & 5 deletions

File tree

‎docs/design/rust-core/phase-1/design.md‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ packages/structured-data-models-client/src/sdm_client/
192192
- The client's build backend becomes maturin on the epic branch (decision B-D3); `main` is untouched.
193193
- `sdm_client._native` (decision A3) ships in the `structured-data-models-client` wheel, tagged `cp310-abi3`, built as `manylinux2014` x86_64, with third-party notices for every Rust dependency linked in.
194194
- The wheel build records its effective Rust target flags and fails if `target-cpu` is set (F7).
195-
- **Local native build (owner answer 5):** on the reference machine, `_native` is built for the host with maturin (macOS arm64; from T1.8, and by `gate.sh` once it lands) from the candidate's source commit, with the production features and `test-ops` off, installs it in each required semantic Python environment, and records its SHA-256 in runner identity; that build runs `python-core` for the reference comparisons and is never shipped. The shipped manylinux2014 x86_64 wheel is proven by `native-wheel`, `wheel-smoke` and the CI cells, never claimed to have run locally; locked check 3 runs the T1.17 containers with `--platform linux/amd64`. Full macOS distribution and platform certification stay with L8.
195+
- **Local native build (owner answer 5):** on the reference machine, `_native` is built for the host with maturin (macOS arm64; from T1.8, and by `gate.sh` once it lands) from the candidate's source commit, with the production features and `test-ops` off, installs it in each required semantic Python environment, and records its SHA-256 in runner identity; that build runs `python-core` for the reference comparisons and is never shipped. The shipped manylinux2014 x86_64 wheel is proven by `native-wheel`, `wheel-smoke` and the CI cells, and its only local run is locked check 3: `gate.sh` takes the `native-wheel` artifact CI built for the exact candidate SHA, checks its SHA-256 against CI's record, and runs the T1.17 containers on it with `--platform linux/amd64`; no `python-core` semantic comparison uses that wheel. Full macOS distribution and platform certification stay with L8.
196196
- `pyarrow>=10.0.1` becomes a base dependency; `pandas>=1.5` stays.
197197
- A version guard holds the Cargo version of `sdm-py` equal to the other four distributions; CI's `build` job builds four wheels as today and takes the client wheel from `native-wheel`, so "five wheels, one version" still holds.
198198
- Importing `sdm_client` never imports `_native`; only `_rust/` does, lazily, on a core route; a test holds this.
@@ -233,7 +233,7 @@ packages/structured-data-models-client/src/sdm_client/
233233
- `python-ref`: the reference environment, the oracle;
234234
- `python-core`: `SDM_CORE_ROUTES` set for the case's paths;
235235
- `python-old`: defaults on the phase branch; a smoke runner that must complete every case without a runner failure, and the comparison base in the runtime cells other than the reference's (H10).
236-
A runner failure is a process abort, an uncaught exception escaping the case recorder, or inability to emit a schema-valid observation; an exception thrown by the public call, a recorded `RuntimeError` included, is captured as that case's outcome with its class or code and stage, and the comparator decides whether it matches the effective expectation; a caught exception is not automatically an accepted outcome, and no register entry accepts a native panic or abort. It lacks the determinism fixes; a determinism-only difference names its case, field and approved comparison rule, with no blanket exemption.
236+
A runner failure is a process abort, an uncaught exception escaping the case recorder, or inability to emit a schema-valid observation; an exception thrown by the public call, a recorded `RuntimeError` included, is captured as that case's outcome with its class or code and stage, and the comparator decides whether it matches the effective expectation; a caught exception is not automatically an accepted outcome, and no register entry accepts a native panic or abort. An error naming a missing `_native` or an unknown forced route is a runner failure on every runner. It lacks the determinism fixes; a determinism-only difference names its case, field and approved comparison rule, with no blanket exemption.
237237
- `python-ref` loads the reference guard by path, calls `require_isolation()` before the first case and after the last, and records the reference commit, the environment hash and the guard result.
238238
- The scripted endpoint is one written rule served over localhost HTTP, reached by Python runners through the client's real transport, implemented in Python and in Rust and held together by a shared vector file.
239239
- **Driver capture (Q2):** a test-only capture in `run_python.py` wraps the connection the runner hands the source and records each statement, its typed parameters, the result each returns and provider-created temporary-relation bindings, derived cursors included, changing no value, order or execution count, with no change to reference code and no rerun of logged queries.
@@ -276,8 +276,8 @@ CI cells are named by runtime and are pinned local semantic cells chosen from [s
276276

277277
- Reference results are committed under `contract/reference/<reference-commit>.jsonl`, with the reference's frozen environment in `contract/reference-env.txt`, so CI compares without running the reference; `gate.sh` regenerates them on the reference machine when the reference, its environment or a case input changes, and at T1.20 and T1.36, and compares the semantic projection, not bytes or hashes, with identity checked separately (decision B-D8).
278278
- `contract/baselines/<cell>/<runner>.jsonl` holds each case's projected observation and its digest. Digests cover only the platform-independent projection `compare-policy.yaml` marks, and CI ratchets that projection; the remaining fields are baselined from the reference machine and ratcheted only by `gate.sh` there.
279-
- **The checkpoint** is the last reviewed landing a candidate builds on (H2, as the owner revised it). At package start, resolve the last reviewed phase-branch tip to `BASE_SHA`, before advancing that branch, and compute `CHECKPOINT_SHA = git merge-base CANDIDATE_SHA BASE_SHA`; record both immutable SHAs with the candidate evidence and pass that same `CHECKPOINT_SHA` to local, CI and owner-merge gate invocations (CI on a phase-branch push takes `BASE_SHA` from the push's previous tip). Never recompute it from a phase-branch ref that already contains the candidate; a non-bootstrap candidate equal to its checkpoint fails. Landing fast-forwards the phase branch to the exact tested candidate; if integration produces a different commit, that commit is tested against the saved checkpoint before acceptance. There is no tag, no promotion step and no separate accept commit.
280-
- **The checkpoint's harness judges (H2):** each gate run, in CI or `gate.sh`, checks the checkpoint out into a separate worktree, overlays only the checkpoint's observation projection and capture (`contract/runners/run_python.py`, and the case loader and observation writer in `sdm-testkit`) onto the candidate, and runs the checkpoint's `compare.py`, `ratchet.py`, L0 scripts and expectations against the candidate's observations; the candidate's own harness result is reported only. The pure-Rust host, its providers and the scripted endpoint are candidate code, protected and named in the `Reviewed-by:` trailer, because they grow with the contract. Lists that may only shrink (`KNOWN_DIFFERING`) live in a data file the overlaid test reads from the candidate; the checkpoint's ratchet accepts the file only as a subset of the checkpoint's. The owner's merge-time gate runs `gate.sh` itself from the checkpoint worktree.
279+
- **The checkpoint** is the last reviewed landing a candidate builds on (H2, as the owner revised it). At package start, resolve the last reviewed phase-branch tip to `BASE_SHA`, before advancing that branch, and compute `CHECKPOINT_SHA = git merge-base CANDIDATE_SHA BASE_SHA`; record both immutable SHAs with the candidate evidence and pass that same `CHECKPOINT_SHA` to local and owner-merge gate invocations. CI works the checkpoint out the same way and never reads it from evidence: on a topic branch `BASE_SHA` is the phase-branch tip at run time; on a phase-branch push it is the push's previous tip, and a push to the phase branch lands exactly one package. Never recompute it from a phase-branch ref that already contains the candidate; a non-bootstrap candidate equal to its checkpoint fails. Landing fast-forwards the phase branch to the exact tested candidate. If the phase branch advanced after `BASE_SHA`, the package is rebased onto the new tip and gated again with `BASE_SHA` reset to that tip and its new `CHECKPOINT_SHA` recorded; a saved checkpoint is reused only for a different integration commit whose merge base with the phase tip is still that checkpoint (for example, after adding a trailer). There is no tag, no promotion step and no separate accept commit.
280+
- **The checkpoint's harness judges (H2):** each gate run, in CI or `gate.sh`, checks the checkpoint out into a separate worktree, overlays only the checkpoint's observation projection and capture (`contract/runners/run_python.py`, and the case loader and observation writer in `sdm-testkit`) onto the candidate, and runs the checkpoint's `compare.py`, `ratchet.py`, L0 scripts and expectations against the candidate's observations; the candidate's own harness result is reported only. The pure-Rust host, its providers and the scripted endpoint are candidate code, protected and named in the `Reviewed-by:` trailer, because they grow with the contract. Lists that may only shrink (`KNOWN_DIFFERING`) live in a data file the corpus test reads from the candidate; the checkpoint's ratchet accepts the file only as a subset of the checkpoint's. The owner's merge-time gate runs `gate.sh` itself from the checkpoint worktree.
281281
- **Bootstrap and evolution:** until T1.14 lands there is no checkpoint harness; the candidate's harness runs, the independent reviewer inspects it, and no acceptance claim is made. T1.14's candidate runs the four fail-first controls before it lands, and from that landing the checkpoint's harness judges. A field or rule the checkpoint's harness does not know is reported, not gated, until the package adding it lands; a new check passes its positive and seeded-negative controls before it lands; a new case has no baseline, meets its reviewed effective expectation on admission and is protected from its landing; a missing baseline for an admitted case is an error.
282282
- **Protected paths:** `contract/protected-paths.txt`, read at the checkpoint, lists the cases, reference observations, `reference-env.txt`, register, comparison policy, availability, L1 expectation files (the PQL corpus and journey queries, zone, stream and hash vectors, vendored tzdata, layout vectors, goldens), the emulation allowlist, `deny.toml`, `clippy.toml`, `ci.yml`, `contract/runners/**`, `rust/crates/sdm-testkit/**`, the corpus test directory, `scripts/rust_core/**`, and `packages/**` except the seam files (`_rust/`, `_routing.py`, `_native.pyi`, the S0 hook in `query.py:_resolve`, the build metadata in `pyproject.toml`).
283283
- A package's landing commit carries a `Reviewed-by:` trailer naming the review run and every protected path the package changes; `gate.sh` fails on a protected change the trailer does not name. Additions and tightenings pass on that review; changing an existing case outcome needs a reviewer-approved register entry; a relaxation needs a decisions row whose status reads "approved by owner" with a date. Decision rows the executor writes never authorize a protected change.
@@ -357,7 +357,7 @@ Each readiness item (sections 1.1 to 1.14 of the planning input `A-readiness-aud
357357
| T1.11e | 1b | Comparator payload and result rules | The comparator's payload and result rules | `base.regression`'s observations compare field by field on all runners, its differences diagnostic until T1.29; on `python-core`, capture on and off give the same public projection; the measured statement counts confirm H9's rule; the owner check-in report is sent | `base.regression`, diagnostic |
358358
| T1.12 | 1a | S0 case corpus | Accept cases per task kind and profile, a refusal per validator family, date-literal and capability refusals, and boundary cases: the 4,300-digit limit on both sides, escapes, a D8 packed date and DT-9's query (both diagnostic until T1.6b), the deepest valid query and a start past 64 KB | Every case file validates in CI | Case validation |
359359
| T1.13 | 1a | S0 reference observations | `contract/reference/<commit>.jsonl` and `contract/reference-env.txt`, recorded after the guard update through `run_python.py` in `python-ref` mode directly until T1.14 lands `gate.sh` | The file carries the guard result and full identity, the observation schema validates it, and the comparator reads it | |
360-
| T1.14 | 1a | Ratchet, register v2, gate and first baselines | `ratchet.py`, `register.schema.json` for `sdm-register/2` with today's entries migrated, `register.py validate`, `compare-policy.yaml`, `availability.yaml`, `protected-paths.txt`, a minimal `gate.sh` running the checkpoint's harness from its own worktree; the first baselines | First, on the candidate, a corrupted expectation, a missing case, a skipped call and a missing native library each fail; then seeded checks: a changed answer passes with a reviewer-approved exact entry and fails without one; a new refusal fails without the owner; a removed case and a demotion to diagnostic fail; a relaxed rule, an availability downgrade or a field added as unavailable fails without an owner-approved row; a protected-path change not named in the `Reviewed-by:` trailer fails; a new case meeting its effective expectation passes without a baseline; a tightened rule passes; a branch-side baseline edit has no effect; an identity-only change passes; an ID added to `KNOWN_DIFFERING` fails; advancing the phase ref cannot erase a deliberately changed outcome or an unauthorized protected-path edit, and self-comparison is rejected; T1.14's output names the landing from which the checkpoint harness judges | Ratchet; register validation; protected paths; reference immutability |
360+
| T1.14 | 1a | Ratchet, register v2, gate and first baselines | `ratchet.py`, `register.schema.json` for `sdm-register/2` with today's entries migrated, `register.py validate`, `compare-policy.yaml`, `availability.yaml`, `protected-paths.txt`, a minimal `gate.sh` running the checkpoint's harness from its own worktree; the first baselines | First, on the candidate, a corrupted expectation, a missing case, a skipped call and a missing native library each fail; then seeded checks: a changed answer passes with a reviewer-approved exact entry and fails without one; a new refusal fails without the owner; a removed case and a demotion to diagnostic fail; a relaxed rule, an availability downgrade or a field added as unavailable fails without an owner-approved row; a protected-path change not named in the `Reviewed-by:` trailer fails; a new case meeting its effective expectation passes without a baseline; a tightened rule passes; a branch-side baseline edit has no effect; an identity-only change passes; an ID added to `KNOWN_DIFFERING` fails; advancing the phase ref cannot erase a deliberately changed outcome or an unauthorized protected-path edit, and self-comparison is rejected; a package rebased over another landing is judged against the new tip, and a push that lands two packages fails; T1.14's output names the landing from which the checkpoint harness judges | Ratchet; register validation; protected paths; reference immutability |
361361
| T1.15 | 1a | Coverage generator for S0 | `coverage.py` with rules 1 to 5 and 8, `--check`, `--gate S0` | `--check` and `--gate S0` pass; an unresolved ID and a dropped path each fail | Coverage `--check`, `--gate S0` |
362362
| T1.17 | 1a | Clean-container wheel smoke | `wheel-smoke` job | Passes on 3.10 with pyarrow 10.0.1, pandas 1.5.3 and NumPy 1.26.4, with the resolved environment recorded, and on 3.14 with the newest pyarrow; canonical inputs cross sharing their buffers and are released exactly; admitted types match the expected canonical schema with values and null masks kept; outputs stay valid after input collection, error and run destruction, over both the capsule and `_export_to_c` paths; busy and cancel behave through the binding | `wheel-smoke` |
363363
| T1.18 | 1a | L2 in CI and the status page | `rust-test` and `contract-python` per runtime cell running the L2 corpus with the checkpoint's comparator and ratchet; `status.py` | `rust-test` green once and `contract-python` green in every cell; the status page regenerates with every item listed under CI | The full S0 L2 corpus in every cell |

0 commit comments

Comments
 (0)