diff --git a/docs/docs/conduct/index.md b/docs/docs/conduct/index.md index 404d4a6..febe0f8 100644 --- a/docs/docs/conduct/index.md +++ b/docs/docs/conduct/index.md @@ -4,3 +4,5 @@ How work is done in Comline's repositories. - [Branch rules](branch-rules.md): how changes reach a default branch, the required checks, review, and accepting a benchmark regression. +- [Phases and promises](phases.md): early days, previews and the 1.0 + announcement, and what is promised in each. diff --git a/docs/docs/conduct/phases.md b/docs/docs/conduct/phases.md new file mode 100644 index 0000000..077cf46 --- /dev/null +++ b/docs/docs/conduct/phases.md @@ -0,0 +1,57 @@ +# Phases and promises + +What Comline promises, and when. Decided 2026-10-27. + +## Phases + +- **Early days,** which is now. +- **Previews,** smaller announcements before 1.0. Still early days. +- **The 1.0 announcement,** which is what sets stability. + +## Always + +- Correctness, conformance, performance and safety are never lowered. +- The [branch rules](branch-rules.md) and required checks apply. +- A change to wire behaviour comes with conformance vectors, and every + runtime passes them. + +## Early days + +Until the 1.0 announcement. + +- Every version is `0.x`. +- Anything may break: + - APIs and generated code; + - the C ABI, where a minor bump counts as breaking; + - the IR and config formats. +- Wire formats (`packed@1`, `datagram@2`, `jsonrpc@1`, `comline@1`) may change + their bytes in place, but only in one cascade: + - the vectors change; + - every runtime (Rust, TypeScript, the simulator) passes them; + - all of it before anything merges. +- No deprecation periods. +- Everything is consumed by git revision, with pins such as `VECTORS_REV` and + the comline-core revision. +- No registry publishing, no release workflow, no prebuilt binaries. +- Proposals may still change. + +## Previews + +- Smaller announcements before 1.0. +- They keep the early-days rules and say so: `0.x`, breaks allowed. + +## From the 1.0 announcement + +- Semver: a break needs a major version. +- Anything users rely on is marked deprecated, with its replacement already + available, in at least one minor release before the major that removes it. + The changelog says so both times. +- A wire format's bytes never change again. A change is a new `@N`. +- The C ABI's structs are frozen within a major. Status codes and flags are + append-only. +- Packages go to registries (npm, crates.io, …) under ComlineProject-owned + names. + - Published from CI with trusted publishing (OIDC), no long-lived tokens. + - Reproducible builds, with published checksums. + - Inter-repo development may keep using git revisions. +- Background: [Ownership & packaging](../design/runtime-repo-structure.md#ownership-packaging). diff --git a/docs/docs/design/runtime-repo-structure.md b/docs/docs/design/runtime-repo-structure.md index de31db8..4341f4b 100644 --- a/docs/docs/design/runtime-repo-structure.md +++ b/docs/docs/design/runtime-repo-structure.md @@ -166,7 +166,8 @@ overhead with no payoff, so `comline-core` and `comline-codegen` are consumed by git rev — the way `generation` and `cli` already consume `core`. The cost is coordinated rev bumps across repos (and one `comline-core` in any given tree, so the CLI composes targets pinned to the same rev). Publishing to crates.io is a -later call, not a prerequisite for anything below. +later call, not a prerequisite for anything below; the +[phases page](../conduct/phases.md) says when. ### Why the reversal @@ -215,9 +216,10 @@ Steps 2–3 are the real prerequisites for a *second* target repo. `generation`' G3 in [Generation → G3](generation.md#g3-split-to-per-language-repos) is steps 1 + 4 + 5 + 6 from the codegen side. -**Publishing to crates.io** stays an open call for later. If the coordinated -git-rev bumps across `comline-` repos get painful, that is the trigger to -revisit — releasing `comline-core` and `comline-codegen` with semver is the fix, +**Publishing to crates.io** stays an open call for later; registries come +with the 1.0 rules on the [phases page](../conduct/phases.md). If the +coordinated git-rev bumps across `comline-` repos get painful, that is the +trigger to revisit — releasing `comline-core` and `comline-codegen` with semver is the fix, and it slots in without reordering anything here. ## Ownership & packaging diff --git a/docs/docs/proposals/index.md b/docs/docs/proposals/index.md index 7811c75..8084afd 100755 --- a/docs/docs/proposals/index.md +++ b/docs/docs/proposals/index.md @@ -74,7 +74,8 @@ reference. One proposal in three stages, read in order: handshake, framings and connection state machine behind a stable C ABI and WASM, built from one crate. ***accepted***, steps 1–3 built: the core changes, the C ABI at 0.1 ([reference](../reference/c-abi.md)), and its - vectors, fuzzing and benchmarks. Bindings and ABI 1.0 are next. + vectors, fuzzing and benchmarks. Bindings are next: TypeScript through wasm. The ABI stays `0.x` until the + [1.0 announcement](../conduct/phases.md). - [Stage 3 — generated codecs](shared-runtime-core/generated-codecs.md): native per-type codecs and protocol glue rendered from one plan in the codegen kernel. *under discussion.* diff --git a/docs/docs/proposals/shared-runtime-core/core-interface.md b/docs/docs/proposals/shared-runtime-core/core-interface.md index c1e8e88..2071fb6 100644 --- a/docs/docs/proposals/shared-runtime-core/core-interface.md +++ b/docs/docs/proposals/shared-runtime-core/core-interface.md @@ -160,8 +160,8 @@ else on this page is as proposed. The glue also reserves its regions on every call, not up front, and returns copies, so no view of wasm memory outlives a call. - **Deferred:** - - `comline_connection_size` and `comline_connection_init` come after 1.0, as a - minor addition; + - `comline_connection_size` and `comline_connection_init` are a later + addition; - `comline@2`'s negotiation comes before 1.0 if it changes the event struct. ### Found along the way @@ -420,7 +420,7 @@ The FFI layer is for every other language, and Rust never pays for it. serde_json. See [Found along the way](#found-along-the-way). - A host with no allocator story of its own (embedded C, Zig) can get a later `comline_connection_size(cfg)` / `comline_connection_init(mem, …)` - pair. That is a minor ABI addition, **after 1.0**, not part of it. + pair. That is a later addition, not part of the ABI as built. **Panics never cross.** - Since Rust 1.81, a panic unwinding out of an `extern "C"` function aborts @@ -468,6 +468,9 @@ The FFI layer is for every other language, and Rust never pays for it. first use. - **Before 1.0, a minor counts as a major.** A binding built against `0.n` accepts only `0.n`, so nothing pre-release is mistaken for compatible. +- **The freeze comes with the project's 1.0 announcement,** not with a + milestone of the ABI's own ([phases](../../conduct/phases.md)). The ABI stays + `0.x` until then. - **Structs are frozen within a major.** New data comes through new functions or new flag bits. A `struct_size` field is not used, because every binding would have to honour it. @@ -627,9 +630,11 @@ addition, not a replacement. ## Distribution -**This is a sketch and an open question.** It needs its own pass before the -release workflow and prebuilt binaries ([rollout](#rollout) step 5). Nothing -in it is built. +**This is a sketch and an open question.** Nothing in it is built. + +- Releases, registries and prebuilt binaries follow the post-1.0 rules on the + [phases page](../../conduct/phases.md). +- Until then, bindings pin a runtime revision. **Targets.** Prebuilt binaries per triple, from `runtime`'s release workflow: @@ -714,7 +719,7 @@ stays a separate idea. **Settled by the build:** - **Handle memory for no-allocator hosts:** `comline_connection_size` / - `comline_connection_init` come after 1.0, as a minor addition. + `comline_connection_init` are a later addition. - **`max_waiting` overflow:** an error to the caller of `encode_request`, `COMLINE_ERR_BUSY`. Queueing is the binding's job. - **Whether `jsonrpc@1`'s `serde_json` dependency fits the no-`std` FFI @@ -725,8 +730,8 @@ stays a separate idea. **Still open:** - **Whether `comline@2`'s negotiation** (protocol numbers handed out at the - handshake) changes the event struct. If so, it should land before ABI 1.0 - freezes. + handshake) changes the event struct. If so, it should land before 1.0, + when the ABI freezes. - **`pyo3` vs `cffi` for Python,** and whether a second binding surface is ever worth it. Decided by gates, but the default needs picking. - **Go without cgo:** wazero against pure Go, measured on the same @@ -748,13 +753,12 @@ Steps 1–3 are done ([What's built](#whats-built)). 3. **A C test binding** in `runtime` CI runs the conformance vectors through the C ABI and the wasm32 build: **done.** C and Node replay the same 65 cases as Rust. This proves the boundary before any language depends on it. -4. **The first two real bindings, chosen to stress the boundary:** - - **TypeScript**, through WASM and napi: stage 4's question; - - **Go**, through cgo: the most expensive call. - Both run the stage 1 gates against the TypeScript runtime and a pure-Go - baseline. -5. **ABI 1.0** once both bindings pass, then the release workflow and - prebuilt binaries. +4. **The first real binding: TypeScript, through WASM** (stage 4). Each + piece moves only where instruction counts show the core costs no more than + the TypeScript it replaces. napi and Go (cgo, the most expensive call) + come later, chosen by those numbers. +5. **Bindings pin a runtime revision.** Releases and prebuilt binaries come + with the 1.0 rules ([phases](../../conduct/phases.md)). 6. **Further languages** each bring a binding and a generator backend in their own repo. diff --git a/docs/docs/proposals/shared-runtime-core/index.md b/docs/docs/proposals/shared-runtime-core/index.md index 18bd420..6d792ac 100644 --- a/docs/docs/proposals/shared-runtime-core/index.md +++ b/docs/docs/proposals/shared-runtime-core/index.md @@ -112,7 +112,7 @@ Split the work by what can cross a language boundary cheaply. | Stage | Page | State | |---|---|---| | 1 | [Verification: differential fuzzing and benchmark gates](verification.md) | accepted, in progress | -| 2 | [One protocol core: a C ABI and WASM from one crate](core-interface.md) | accepted; rollout steps 1–3 built, bindings and ABI 1.0 next; see the [C ABI reference](../../reference/c-abi.md) | +| 2 | [One protocol core: a C ABI and WASM from one crate](core-interface.md) | accepted; rollout steps 1–3 built, bindings next: TypeScript through wasm; see the [C ABI reference](../../reference/c-abi.md) | | 3 | [Codecs and protocol glue generated from one plan](generated-codecs.md) | proposal | | 4 | Move TypeScript onto the core where the benchmarks allow | agreed | | 5 | Clean up the leftovers and the documents that contradict this | agreed | @@ -129,6 +129,10 @@ rule CI enforces. Without it, stages 2–4 would be judged by opinion. vectors, fuzzing and gates. - The browser has no native option at all. The playground simulator already runs the core there. +- The current plan is TypeScript through wasm only, each piece moving only + where instruction counts show the core is at least as fast. napi and Go + come later, chosen by those numbers. The C ABI stays `0.x` until the project + announces 1.0 ([phases](../../conduct/phases.md)). **Stage 5: the cleanup.** - **Remove or split `runtime/core/src/package_abi`.** It pulls `abi_stable` diff --git a/docs/docs/reference/c-abi.md b/docs/docs/reference/c-abi.md index aefa533..cc933b2 100644 --- a/docs/docs/reference/c-abi.md +++ b/docs/docs/reference/c-abi.md @@ -5,7 +5,8 @@ for the `comline@1` handshake, the connection framings (`datagram@2`, `jsonrpc@1`), envelopes, connection state and frame limits. Codecs, transports, async and dispatch stay in each host. -- **ABI version 0.1.** It is not frozen; see [Version](#version). +- **ABI version 0.1.** It is not frozen; it freezes when the project announces + 1.0 ([phases](../conduct/phases.md)). See [Version](#version). - **Source:** [`runtime/ffi`](https://github.com/ComlineProject/runtime/tree/main/runtime/ffi) in the runtime repository. - **Header:** [`include/comline.h`](https://github.com/ComlineProject/runtime/blob/main/runtime/ffi/include/comline.h). @@ -30,6 +31,8 @@ header disagree, the header is right. - **Before 1.0, a minor counts as a major.** A host built against `0.1` accepts only `0.1`. The JS glue does exactly this. +- **The freeze comes with the project's 1.0 announcement,** not with an ABI + milestone of its own ([phases](../conduct/phases.md)). - The major changes when a signature, a struct layout or the meaning of a code changes. The minor changes when functions, codes or flag bits are added. - Structs are frozen within a major. New data comes through new functions or new @@ -430,8 +433,9 @@ a 1% rise, like the core's benches. Both sides of each pair are gated. ## Not here yet - **`comline_connection_size` and `comline_connection_init`,** for a host that - supplies the handle's memory. After 1.0. + supplies the handle's memory. A later addition. - **`comline@2`'s negotiation** hands protocol numbers out at the handshake and - may change the event struct. If it does, it lands before 1.0 freezes the ABI. + may change the event struct. If it does, it lands before the 1.0 + announcement freezes the ABI. - **Bindings.** No language binds the ABI yet; the JS glue is the only host code, and it is a thin wrapper, not a binding. diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index ffcc99f..7a846e1 100755 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -147,6 +147,7 @@ nav: - Conduct: - 'conduct/index.md' - 'Branch rules': 'conduct/branch-rules.md' + - 'Phases and promises': 'conduct/phases.md' extra_css: - stylesheets/nav.css?v=21 # bump on every nav.css change — it is not cache-busted otherwise