Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ecosystem.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#
# Criterion 1 of `RELEASE-CRITERIA-1.0.md` names three soak subjects, and this
# is the second: "one full run per day for every day of the window, all exiting
# 0, on all four release triples", owned by Ash (WLA-7). What a run *is* lives
# 0, on all four release triples". What a run *is* lives
# in `scripts/ecosystem-check.sh` -- sharpie built and tested, Foundry's own
# check, and every published release installed, compiled against and tested,
# plainly and under stress -- so that it means the same on a laptop as here.
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ jobs:
conformance:
name: conformance (${{ matrix.triple }})
runs-on: ${{ matrix.os }}
# Minutes, not hours: `wsharp check` over the 64 rejection cases twice is
# Minutes, not hours: `wsharp check` over the 68 rejection cases twice is
# seconds. The budget is the build.
timeout-minutes: 60
strategy:
Expand Down
11 changes: 6 additions & 5 deletions .github/workflows/release-gates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -256,11 +256,12 @@ jobs:

# Gate 6d. Every command the repository tells a contributor to run works.
#
# The three commands are `CLAUDE.md`'s, verbatim, in its order -- the build
# before the test because the case suite's AOT pass links against an archive
# `cargo test` does not build. The third is issue #8 and fails today; this job
# is what turns that from an afternoon lost per contributor into a red check
# with an owner.
# The first two are `CLAUDE.md`'s, verbatim, in its order -- the build before
# the test because the case suite's AOT pass links against an archive `cargo
# test` does not build. The third, a filtered build, is the regression guard
# for issue #8 (fixed): a test-name filter used to pull `wsharp-start`, which
# defines `main`, into a test harness and fail to link. This job keeps that
# from coming back as an afternoon lost per contributor.
#
# No `nix-shell` wrapper: `CLAUDE.md` uses it because a bare NixOS box has no
# `cc`, and the GitHub runner has one already. The commands inside are what
Expand Down
30 changes: 14 additions & 16 deletions COMPATIBILITY.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# What W# 1.0 promises

**Status: in force for the v1.0 campaign.** The terms — which surfaces are
frozen, and for how long — are fixed in
**Applies from v1.0.0.** The terms — which surfaces are frozen, and for how long
— are fixed in
[Part five of RELEASE-CRITERIA-1.0.md](RELEASE-CRITERIA-1.0.md#part-five-the-api-and-stability-freeze).
This file states the same promise to users, surface by surface. If the two ever
disagree, Part five is the one that is right and this file gets fixed.
Expand Down Expand Up @@ -261,11 +261,12 @@ extracting anything.**

**Not promised:** that the digest is *signed*. A sidecar protects against a
corrupted or truncated transfer and not against whoever can serve the tarball,
because they can serve the sidecar too. `RELEASE-CRITERIA-1.0.md` criterion 5
puts the signing question to Johnny before the tag; **whichever way it is
decided, this section states the answer plainly rather than leaving it to be
inferred.** Until it is decided, the honest reading of this paragraph is the
weaker one.
because they can serve the sidecar too. **1.0 ships with the digest sidecar, and
the integrity it promises is against transport corruption, not against a
compromised distribution point** (decided 2026-09-26; criterion 7 of
`RELEASE-CRITERIA-1.0.md`). Signing — minisign or cosign, with the public key in
the installer and the signature verified before the digest — is scheduled for
1.1.

**Not promised.** Reproducible builds. A third party cannot rebuild an artefact
and get the same bytes; see `LIMITATIONS.md`.
Expand Down Expand Up @@ -298,12 +299,9 @@ repository with one workflow (`deploy.yml`) that publishes and does not check.
Gate 6a of `RELEASE-CRITERIA-1.0.md` — every documented example is a real file
executed in CI — therefore does not reach it as things stand.

**This is fixable rather than a reason to narrow the promise**, and the proposal
is a check workflow in that repository which clones `sinisterMage/WSharp` at the
tag and runs `scripts/check-doc-examples.sh` over `content/docs/**`, using the
same `<!-- from: examples/fib.ws -->` marker convention. That makes the site's
examples the same files the case suite runs.

Until that job exists and is green, **the 1.0 documentation promise covers the
in-repository documentation**, and the release notes say so. This sentence is
the one to delete once the job lands.
**The 1.0 documentation promise covers the in-repository documentation**, and
the release notes say so. Extending it to the site needs a check workflow in that
repository which clones `sinisterMage/WSharp` at the tag and runs
`scripts/check-doc-examples.sh` over `content/docs/**`, using the same
`<!-- from: examples/fib.ws -->` marker convention, so that the site's examples
are the same files the case suite runs.
66 changes: 30 additions & 36 deletions LIMITATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,9 @@
**Status: live, against `wsharp 0.2.3`.** Every limitation below was verified
against that release and the output shown is what it printed.

**The six tracked issues are dispositioned, and all six are documented
limitations.** Criterion 4 of [RELEASE-CRITERIA-1.0.md](RELEASE-CRITERIA-1.0.md)
is the gate; each entry now carries a **Disposition** line stating the call and
the reason for it, so the decision is readable here rather than only in an issue
thread. Not one of them was closed on a comment: each has the entry below and,
where one can exist, a named `tests/cases` guard.
The six issues tracked by criterion 4 of
[RELEASE-CRITERIA-1.0.md](RELEASE-CRITERIA-1.0.md) are all documented
limitations; each entry's **Disposition** line says why.

A guard for a limitation is an uncomfortable-looking test — it asserts that
something does *not* work. That is the point. A limitation nothing checks can
Expand Down Expand Up @@ -36,15 +33,12 @@ program at two in the morning.
| [#14](https://github.com/sinisterMage/WSharp/issues/14) | `net.shutdown` does not stop an acceptor on the BSDs | Documented — kernel behaviour, and the API does not offer the operation | `tests/cases/err_shutdown_listener.ws`, `tests/cases/net_poller.ws` |
| [#15](https://github.com/sinisterMage/WSharp/issues/15) | `std/tls` cannot verify a chain through a P-521 key | Documented — 521 bits is not a whole number of 32-bit limbs | `tests/cases/x509_p521.ws` |

Each row's reasoning is in its entry below, under **Disposition**. Four of the
cases named — `err_computed_const.ws`, `const_array_alias.ws`,
`err_shutdown_listener.ws` and `x509_p521.ws` — were written for this file and did
not exist before: a limitation nobody checked was a limitation that could drift.
Each row's reasoning is in its entry below, under **Disposition**.

## How to read an entry

Every entry carries four things, and an entry missing any of them is not
finished:
Every entry carries the fields below — **Disposition** only where an issue asked
for fix-or-document — and an entry missing one it needs is not finished:

| Field | Means |
|---|---|
Expand Down Expand Up @@ -356,9 +350,9 @@ as uncomparable with a diagnostic naming the field
is still here.** Until the bound landed, the program above died on a signal
with no W# diagnostic and no exit
status a program could act on. By clause 3 of the P1 definition in
`RELEASE-CRITERIA-1.0.md` that is a P1 whatever the documentation says — Johnny
ruled on 2026-09-26 that clause 3 carries no exemption for documented behaviour,
because documentation changes who is surprised, not what the process does. Form
`RELEASE-CRITERIA-1.0.md` that is a P1 whatever the documentation says: clause 3
carries no exemption for documented behaviour (decided 2026-09-26), because
documentation changes who is surprised, not what the process does. Form
C says the same thing from the other side: a limitation whose behaviour is a
crash is not documentable, so it gets bounded into a diagnostic first and the
bound is what gets documented. This entry is that bound.
Expand Down Expand Up @@ -466,10 +460,9 @@ is a language decision, not one to slip in under a freeze.
`try` does anywhere: both `First` and `Last` then reach the caller. Or write the
error set down, `!{First, Last}i64`.

**Disposition: documented limitation for 1.0, pending the language owner's
confirmation on #62.** The rule is also stated in `CLAUDE.md` ("`return f(x)`
unifies two error sets; `try f(x); return;` widens one"), which is where
`std/tls`'s dispatchers learnt to be written the second way.
**Disposition: documented limitation for 1.0.** Whether to change the rule is an
open language decision on #62. `std/tls`'s message dispatchers use `try` for
exactly this reason.

**Guarded by** `tests/cases/err_tail_call_error_set.ws`, the refusal, and
`tests/cases/tail_call_error_set_try.ws`, the workaround reaching both errors.
Expand Down Expand Up @@ -713,9 +706,9 @@ backend this project actually tests, not a rewrite of the walk.
**Disposition: documented limitation**, and of the six it is the one that is a
*scope statement* rather than an unfinished piece. A supported platform is not a
`cfg` arm: it is a register read, a Cranelift backend this project tests, and a CI
job on real hardware that a release is held to. Adding one during the 1.0 campaign
would mean shipping a platform whose collector nobody had watched fail, which is
the opposite of what the campaign is for.
job on real hardware that a release is held to. Adding one for 1.0 would mean
shipping a platform whose collector nobody had watched fail, which is the
opposite of what 1.0 is for.

**Guarded by** two mechanisms, neither of which is a `tests/cases` entry — a case
cannot be written for an architecture that does not build. The
Expand Down Expand Up @@ -749,8 +742,7 @@ The reason it is worth an entry rather than a line in the README is **who meets
it**. `cc` on a Windows machine is whatever is first on `PATH`, and a developer
machine with Git for Windows, MSYS2 or a MinGW toolchain installed has one there
without having chosen it. GitHub's `windows-latest` image is exactly that
machine, which is how this was found: criterion 7's Windows row failed on it
while the same release built fine under clang.
machine.

**Why.** The Windows flags are not decoration. `-Xlinker -subsystem:console` is
there because clang picks a subsystem by looking for `main` in the *objects* it
Expand All @@ -762,10 +754,10 @@ the static CRT is not a near miss. Both are written out at
`crates/wsharp-cli/src/link.rs:91`.

Supporting GNU `ld` as well means a second set of flags, selected by detecting
the linker flavour, and a second Windows link configuration to keep green — on
a platform where, per the note in `CLAUDE.md`, almost nothing can be checked
from the machines this project is developed on. The released artefact is
`x86_64-pc-windows-msvc`, and MSVC is the toolchain that target names.
the linker flavour, and a second Windows link configuration to keep green.
Windows is covered by CI, so that would be a second Windows CI configuration as
well. The released artefact is `x86_64-pc-windows-msvc`, and MSVC is the
toolchain that target names.

**Workaround.** Use clang, which drives the MSVC linker and libraries: install
the Visual Studio Build Tools for those, `winget install LLVM.LLVM` for clang,
Expand All @@ -789,8 +781,8 @@ answer on Windows and says that `cc` is MinGW, what to install, and how to set

**Guarded by** `link::tests::a_mingw_link_failure_is_told_apart_from_an_msvc_one`,
which holds the recognition to #41's own linker output and to the MSVC linker's,
on every platform. Criterion 7's Windows row no longer meets MinGW at all: it
sets `CC=clang`, the documented toolchain. There is deliberately no `tests/cases`
on every platform. The Windows clean-machine install check sets `CC=clang`, the
documented toolchain. There is deliberately no `tests/cases`
entry: a case cannot assert which C compiler is first on `PATH` without becoming
a case about the machine it ran on.

Expand All @@ -805,23 +797,25 @@ bytes. What is published is a digest per artefact, and the promise is that the
digest matches the bytes served.

**Why.** A Rust release build is not bit-identical across machines without work
the 1.0 campaign has not scoped.
1.0 has not scoped.

**Workaround.** Verify the published digest, which both installers do before
extracting.

**Tracked.** Stated as a non-promise in `RELEASE-CRITERIA-1.0.md`, "What this
document does not promise".
**Tracked.** Stated as a non-promise in
[COMPATIBILITY.md](COMPATIBILITY.md#release-artefacts-and-the-feed), "Release
artefacts and the feed".

## The runtime's C symbols are not a stable ABI

**What.** The `ws_*` symbols in `libwsharp_start.a` and the runtime archive are
an internal boundary between the compiler and its own runtime. Linking against
them from outside is not supported and they may change in a patch release.

**Tracked.** Stated as a non-promise in `RELEASE-CRITERIA-1.0.md`; repeated here
because the symbols are visible in a built binary and therefore look like an
interface.
**Tracked.** Stated as a non-promise in
[COMPATIBILITY.md](COMPATIBILITY.md#what-is-outside-the-promise-entirely), "What
is outside the promise entirely"; repeated here because the symbols are visible
in a built binary and therefore look like an interface.

---

Expand Down
18 changes: 7 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -978,16 +978,12 @@ Numbered by the original feature list:

Since that list ran out, two things.

**Raython**, an MVC framework, which is a design rather than a program so far
and whose repository is private. Its author settled every "can W# do this?" by
running the compiler rather than from memory, and left 28 probes behind as the
record. The design ends with nine things it wanted from the language and one
thing that was a bug: a conversion inside an abstract-typed body pinned that
parameter to the converted type, and with a second overload beside it that got
past inference and produced IR Cranelift refused. All ten are closed, which is
where `--emit=api`, `std/map`, a linear `str.join`, `net.shutdown`, `os.exit`,
`fs.modified_at`, struct `==` and `main` returning ending the process came from.
Item 14 of [ROADMAP.md](ROADMAP.md) is the write-up.
**Raython**, an MVC framework designed against W#, exercised the language with 28
probe programs; the nine things it asked of the language and the one bug it found
are all closed, which is where `--emit=api`, `std/map`, a linear `str.join`,
`net.shutdown`, `os.exit`, `fs.modified_at`, struct `==` and `main` returning
ending the process came from. Item 14 of [ROADMAP.md](ROADMAP.md) is the
write-up.

And [**sharpie**](https://github.com/sinisterMage/sharpie), a version manager,
the second real program written in W#. It finds releases by reading this
Expand Down Expand Up @@ -1015,7 +1011,7 @@ Four documents govern it, and each has one job:

| File | Answers |
|---|---|
| [RELEASE-CRITERIA-1.0.md](RELEASE-CRITERIA-1.0.md) | What 1.0 has to be true of, how each thing is measured, who owns it, and what proof closes it |
| [RELEASE-CRITERIA-1.0.md](RELEASE-CRITERIA-1.0.md) | What 1.0 has to be true of, how each thing is measured, and what proof closes it |
| [COMPATIBILITY.md](COMPATIBILITY.md) | What 1.0 promises not to break, surface by surface, and for how long |
| [LIMITATIONS.md](LIMITATIONS.md) | What W# does not do, with a workaround or the word *None* |
| [docs/defects.md](docs/defects.md) | Where a defect lands, what severity it gets, and what happens to it after that |
Expand Down
Loading
Loading