Artifact e2488f089f4732bbd4bd56ced000d5af17406663634e5ad66f3c515b9837b8e1:
- File
.github/workflows/ci.yml
— part of check-in
[f1e10128f8]
at
2026-08-05 21:55:32
on branch sub-manifest
— citations: re-section four claims from §4.1 to sync §7.7
All four assert that the artifact hash names the uncompressed, fully reconstructed bytes, and cited §4.1 for it. No §4.1 in any of the five drafts says that -- §4.1 defines the container. The statement is sync §7.7 L1465, "Integrity hashes reconstructed artifact bytes, not wire payload."
These were the ones the re-key pass returned unresolved rather than guessing at: wrong section, not drifted lines, so no line range would have been right. Naming the draft because §7.7 also exists in artifact-format.
Baseline 481 to 477. test 3495/3495, fmt. Issue #18. (user: dmestas, size: 9072) [annotate] [blame] [check-ins using]
name: ci # Every push on every branch, plus pull requests. Deliberately unfiltered: the # 0.1.0 release is developed on `release-0.1`, and a default-branch-only gate # would leave the entire release unverified until the merge that is supposed to # be the safe part. on: push: pull_request: # Least privilege: the battery only reads the checkout. Without an explicit # block the job inherits whatever the repo/org default grants, which is # read/write on many configurations. permissions: contents: read # Unfiltered `push:` plus `pull_request:` means a PR branch runs the whole # battery twice per push. Superseded runs are cancelled rather than left to # finish against a commit nobody is waiting on. concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true # One release gate across the native macOS/ARM64 and Linux x86-64/ARM64 # platforms. Each label set is intentionally precise: Linux legs remain queued # until the corresponding self-hosted runner is registered; they never fall # back to a hosted or arbitrary self-hosted machine. jobs: battery: strategy: fail-fast: false matrix: include: - os: macOS arch: ARM64 runner: mac-mini-zit zig_target: aarch64-macos zig_shasum: b23d70deaa879b5c2d486ed3316f7eaa53e84acf6fc9cc747de152450d401489 - os: Linux arch: X64 runner: linux-x64-zit zig_target: x86_64-linux zig_shasum: 70e49664a74374b48b51e6f3fdfbf437f6395d42509050588bd49abe52ba3d00 - os: Linux arch: ARM64 runner: linux-arm64-zit zig_target: aarch64-linux zig_shasum: ea4b09bfb22ec6f6c6ceac57ab63efb6b46e17ab08d21f69f3a48b38e1534f17 runs-on: [self-hosted, "${{ matrix.os }}", "${{ matrix.arch }}", "${{ matrix.runner }}"] # An explicit ceiling, per the bounded-waits rule: every wait needs an # interval and a timeout. Without this the job inherits GitHub's 360-minute # default, so a hang — most plausibly smoke's spawned server never exiting — # turns a red gate into a six-hour silent stall instead of a failure. timeout-minutes: 20 env: # Kept in lockstep with src/ci_test.zig's `pinned_zig_version` and # `pinned_zig_shasums`, which fail `zig build test` if this file drifts. # These are the target-specific published digests from # ziglang.org/download/index.json. ZIG_VERSION: 0.16.0 ZIG_TARGET: ${{ matrix.zig_target }} ZIG_SHASUM: ${{ matrix.zig_shasum }} steps: - uses: actions/checkout@v5 # A `§X.Y Lnnn` citation that resolves to the wrong paragraph is worse # than no citation: it looks authoritative, so the next person checking a # normative claim against it is told the wrong thing. Line numbers rot # every time a draft is re-rendered to apply an erratum, and nothing # noticed until a sweep found most of them wrong. # # A RATCHET, not a gate on zero: the backlog is real and is being worked # down, so this pins the count and fails in BOTH directions -- a new # broken citation, or a fixed one whose baseline was not lowered. Needs # no toolchain, so it runs before the Zig install and fails fast. - name: Check draft citations run: python3 scripts/check-citations.py --baseline 477 # smoke drives the real fossil binary — it is the only step that proves # the conformance claim against the reference implementation rather than # against our own reading of the RFCs. Fossil is provisioned by each # self-hosted runner image, so print the actual version used by the gate. - name: Verify fossil run: | set -euo pipefail command -v fossil >/dev/null 2>&1 || { echo "fossil is not installed on this runner; smoke cannot run." >&2 echo "provision fossil in this self-hosted runner image." >&2 exit 1 } fossil version # Installed by hand rather than through a setup action: the toolchain is # one tarball, the URL is stable, and verifying the published digest here # is both simpler and stronger than trusting a third-party action to pin # the same thing. `sha256sum` is standard on Linux; macOS supplies # `shasum`, so select the available native checksum tool. - name: Install Zig ${{ env.ZIG_VERSION }} run: | set -euo pipefail tarball="zig-${ZIG_TARGET}-${ZIG_VERSION}.tar.xz" curl -fsSL -o "$tarball" "https://ziglang.org/download/${ZIG_VERSION}/${tarball}" if command -v sha256sum >/dev/null 2>&1; then actual="$(sha256sum "$tarball" | awk '{print $1}')" else actual="$(shasum -a 256 "$tarball" | awk '{print $1}')" fi if [ "$actual" != "${ZIG_SHASUM}" ]; then echo "zig tarball digest mismatch: expected ${ZIG_SHASUM}, got ${actual}" >&2 exit 1 fi tar -xf "$tarball" echo "${GITHUB_WORKSPACE}/zig-${ZIG_TARGET}-${ZIG_VERSION}" >> "$GITHUB_PATH" - name: Zig version run: zig version # `--check build.zig src` rather than `--check .`: the bare dot walks # .zig-cache/ and zig-out/, whose generated sources are not ours to # format. Naming the source roots keeps the check meaning the same thing # on a cold runner and in a warm local tree. - name: Format check run: zig fmt --check build.zig src - name: Build run: zig build # The battery runs each step explicitly. Local semantics are deliberately # unchanged: e2e staying compile-only under `zig build test` is a good # inner-loop design, so CI names the steps rather than the build graph # being rewired to fold them in. - name: Unit tests run: zig build test - name: End-to-end tests run: zig build e2e - name: Native Git import differential tests timeout-minutes: 5 run: zig build git-import-e2e - name: Deterministic simulation run: zig build dst # The seeded fuzz corpus, bounded. The targets also reach `zig build test` # through fixed-seed smoke cases, but this step exercises every registered # target through the real fuzz runner. # # `zig build fuzz` runs ONE target per invocation, so this sweeps them. # `--list` exits successfully and writes the complete registration table; # unlike scraping a failed bare invocation, its output is not truncated by # Zig's build-failure summary on Linux. A target added to fuzz_tests.zig is # therefore fuzzed automatically, with no second list to drift out of sync. # # Seed and rounds are fixed, not random: a red CI run has to be # reproducible verbatim on a developer machine. Deeper sweeps belong to # the out-of-band runner with its own budget. - name: Seeded fuzz sweep timeout-minutes: 10 env: FUZZ_SEED: 1 # 100, not 2000. Per-target cost varies by ~276x across the corpus — # artifact_parse_garbage runs 100 rounds in 0.18s while # logstore_pack_same_path_round_trip takes 49s, because it performs a # full store pack per round. The original 2000 was extrapolated from # one cheap target and made the sweep unable to finish inside this # step's own timeout: that single target alone would need ~16 minutes. # Measured at 100 rounds the whole sweep is ~76s, which is the budget # this number is chosen against, not a guess. # # What this buys is REGRESSION DETECTION — every target still runs # clean on every push. It is not a bug hunt: finding new defects needs # depth, and depth belongs in an out-of-band run with its own budget, # where a 30-minute sweep costs nobody a merge. FUZZ_ROUNDS: 100 run: | set -euo pipefail targets="$(zig build fuzz -- --list)" if [ -z "${targets}" ]; then echo "no fuzz targets enumerated — the usage format changed and this sweep is vacuous" >&2 exit 1 fi count=0 for target in ${targets}; do echo "fuzz: ${target} (seed ${FUZZ_SEED}, rounds ${FUZZ_ROUNDS})" zig build fuzz -- "${target}" --seed "${FUZZ_SEED}" --rounds "${FUZZ_ROUNDS}" count=$((count + 1)) done echo "fuzz sweep: ${count} targets at seed ${FUZZ_SEED}" # The tightest per-step bound in the battery, and deliberately so: smoke # spawns a server, which is the one step that can hang without producing # output. The job ceiling would eventually catch it; this catches it while # the log still reads as a failed step rather than a dead run. - name: Fossil interop smoke timeout-minutes: 5 run: zig build smoke