Skip to content
zit Artifact [d3aecf1256]
Login

Artifact [d3aecf1256]

Artifact d3aecf12565618a6b678eeff534230c88dbe5a02486beafcdbdf1eac9b258292:


//! Fossil interop smoke check — the one sanctioned use of the real `fossil`
//! binary. `fossil` is invoked nowhere else in this tree.
//!
//! Policy, enforced by this file's shape, not by convention:
//!   - Every byte handed to fossil is zit's OWN output (`artifact.create` /
//!     `delta.create` over an RFC fixture) -- never the raw RFC transcription,
//!     never anything fossil produced.
//!   - fossil may only CONFIRM an RFC-cited zit expectation. A scenario that
//!     would require comparing zit bytes to fossil-AUTHORED bytes (e.g.
//!     `fossil test-delta-create`) does not belong here.
//!   - On any mismatch, print the diff and the RFC citation and exit 1. This
//!     file never adjusts zit to match fossil -- a mismatch is an operator
//!     decision (RFC misread vs RFC wrong), recorded in the untracked
//!     ambiguities ledger, not "fixed" in place.
//!
//! Milestone-manual: this executable lives solely behind `zig build smoke`.
//! `zig build test` compiles it (catching type errors) but never runs its
//! scenarios; it is not imported by `root.zig`'s test aggregation.

const std = @import("std");
const zit = @import("zit");
const artifact = zit.artifact;
const delta = zit.delta;
const build_options = @import("build_options");
const net = std.Io.net;

/// The compiled `zit` binary, threaded in by build.zig (a `LazyPath`, always
/// rebuilt first). `build_options.zit_exe` is relative to the build root, which
/// is this process's cwd; S5 resolves it to an absolute path before spawning it
/// as a subprocess (`zit init/add/commit/pack/serve`). Confined to S5 — the
/// other scenarios drive only the `zit` LIBRARY, never the binary.
const zit_exe: []const u8 = build_options.zit_exe;

// ---------------------------------------------------------------------------
// RFC fixtures -- the same vectors src/artifact.zig's own tests cite.
// ---------------------------------------------------------------------------

const a1_1_manifest = @embedFile("rfc_vectors/artifact_a1_1_sha1_manifest.txt");
const a1_2_technote = @embedFile("rfc_vectors/artifact_a1_2_sha3_technote.txt");
const a3_manifest = @embedFile("rfc_vectors/artifact_a3_rcard_manifest.txt");

/// §5/Appendix B.1 delta worked-example pair (102/151-byte sizes), reused
/// verbatim from delta.zig's own "create() then apply() round-trips the
/// target" test so S4 exercises the same RFC-cited content.
const delta_source = "The quick brown fox jumps over the lazy dog. A Fossil delta encodes byte-level differences compactly.\n";
const delta_target = "The quick brown fox jumps over the sleeping fox. A Fossil delta encodes byte-level differences compactly.\n An example delta target with appended tail.\n";

const ManifestScenario = struct {
    name: []const u8,
    citation: []const u8,
    fixture: []const u8,
    algo: artifact.HashAlgo,
};

const manifest_scenarios = [_]ManifestScenario{
    .{ .name = "S1", .citation = "§A.1.1/§A.2", .fixture = a1_1_manifest, .algo = .sha1 },
    .{ .name = "S2", .citation = "§A.1.2", .fixture = a1_2_technote, .algo = .sha3_256 },
    .{ .name = "S3", .citation = "§A.3", .fixture = a3_manifest, .algo = .sha3_256 },
};

pub fn main(init: std.process.Init) !void {
    const gpa = init.gpa;
    const io = init.io;

    var stdout_buffer: [4096]u8 = undefined;
    var stdout_writer: std.Io.File.Writer = .init(.stdout(), io, &stdout_buffer);
    const out = &stdout_writer.interface;

    if (!fossilAvailable(gpa, io)) {
        try out.writeAll("fossil not found — smoke is milestone-manual\n");
        try out.flush();
        return;
    }

    var arena_state = std.heap.ArenaAllocator.init(gpa);
    defer arena_state.deinit();
    const arena = arena_state.allocator();

    const tmp_root = try tempRoot(arena, init.environ_map.*);
    std.Io.Dir.cwd().deleteTree(io, tmp_root) catch {};
    try std.Io.Dir.cwd().createDirPath(io, tmp_root);
    defer std.Io.Dir.cwd().deleteTree(io, tmp_root) catch {};

    var env = try init.environ_map.clone(gpa);
    defer env.deinit();
    const home_dir = try std.fs.path.join(arena, &.{ tmp_root, "home" });
    try std.Io.Dir.cwd().createDirPath(io, home_dir);
    try env.put("FOSSIL_HOME", home_dir);

    var all_pass = true;

    for (manifest_scenarios) |sc| {
        const pass = runManifestScenario(arena, gpa, io, tmp_root, &env, out, sc) catch |err| blk: {
            try out.print("FAIL {s} ({s}): unexpected error running scenario: {s}\n", .{ sc.name, sc.citation, @errorName(err) });
            break :blk false;
        };
        all_pass = all_pass and pass;
    }

    const s4_pass = runDeltaScenario(arena, gpa, io, tmp_root, &env, out) catch |err| blk: {
        try out.print("FAIL S4 (§5/§Appendix B.1): unexpected error running scenario: {s}\n", .{@errorName(err)});
        break :blk false;
    };
    all_pass = all_pass and s4_pass;

    const s5_pass = runCloneFromRepackedScenario(arena, gpa, io, tmp_root, &env, out) catch |err| blk: {
        try out.print("FAIL S5 (§7.5/§3): unexpected error running scenario: {s}\n", .{@errorName(err)});
        break :blk false;
    };
    all_pass = all_pass and s5_pass;

    const s6_pass = runOpenFromFossilServerScenario(arena, gpa, io, tmp_root, &env, out) catch |err| blk: {
        try out.print("FAIL S6 (§3.7/§4): unexpected error running scenario: {s}\n", .{@errorName(err)});
        break :blk false;
    };
    all_pass = all_pass and s6_pass;

    try out.flush();
    if (!all_pass) std.process.exit(1);
}

// ---------------------------------------------------------------------------
// Preflight
// ---------------------------------------------------------------------------

fn fossilAvailable(gpa: std.mem.Allocator, io: std.Io) bool {
    const res = std.process.run(gpa, io, .{ .argv = &.{ "fossil", "version" } }) catch return false;
    defer gpa.free(res.stdout);
    defer gpa.free(res.stderr);
    return okExit(res.term);
}

fn tempRoot(arena: std.mem.Allocator, env: std.process.Environ.Map) ![]const u8 {
    const base = env.get("TMPDIR") orelse "/tmp";
    const trimmed = std.mem.trimEnd(u8, base, "/");
    return std.fs.path.join(arena, &.{ trimmed, "zit-smoke" });
}

// ---------------------------------------------------------------------------
// fossil process helper
// ---------------------------------------------------------------------------

fn okExit(term: std.process.Child.Term) bool {
    return switch (term) {
        .exited => |code| code == 0,
        else => false,
    };
}

fn runFossil(
    gpa: std.mem.Allocator,
    io: std.Io,
    argv: []const []const u8,
    cwd_path: []const u8,
    env: *const std.process.Environ.Map,
) !std.process.RunResult {
    return std.process.run(gpa, io, .{
        .argv = argv,
        .cwd = .{ .path = cwd_path },
        .environ_map = env,
    });
}

/// First whitespace-delimited token of `text` (the hash column of
/// `fossil sha1sum`/`sha3sum` output: "<hash>  <path>\n").
fn firstToken(text: []const u8) []const u8 {
    const end = std.mem.indexOfAny(u8, text, " \t\r\n") orelse text.len;
    return text[0..end];
}

// ---------------------------------------------------------------------------
// Failure reporting -- never authored from fossil's side, only printed.
// ---------------------------------------------------------------------------

fn printBytesPreview(out: *std.Io.Writer, label: []const u8, bytes: []const u8) !void {
    try out.print("  {s} (len {d}): ", .{ label, bytes.len });
    const max = @min(bytes.len, 96);
    for (bytes[0..max]) |b| try out.print("{x:0>2}", .{b});
    if (bytes.len > max) try out.writeAll("...");
    try out.writeAll("\n");
}

fn firstDiffOffset(a: []const u8, b: []const u8) ?usize {
    const n = @min(a.len, b.len);
    var i: usize = 0;
    while (i < n) : (i += 1) {
        if (a[i] != b[i]) return i;
    }
    if (a.len != b.len) return n;
    return null;
}

fn printDiffWindow(out: *std.Io.Writer, zit_bytes: []const u8, fossil_bytes: []const u8) !void {
    const off = firstDiffOffset(zit_bytes, fossil_bytes) orelse return;
    const start = if (off > 16) off - 16 else 0;
    const zit_end = @min(zit_bytes.len, off + 16);
    const fossil_end = @min(fossil_bytes.len, off + 16);
    try out.print("  first diff at byte {d}\n", .{off});
    try out.writeAll("  zit    : ");
    for (zit_bytes[start..zit_end]) |b| try out.print("{x:0>2}", .{b});
    try out.writeAll("\n  fossil : ");
    for (fossil_bytes[start..fossil_end]) |b| try out.print("{x:0>2}", .{b});
    try out.writeAll("\n");
}

fn printMismatchFooter(out: *std.Io.Writer, citation: []const u8) !void {
    try out.print("  RFC citation: {s}\n", .{citation});
    try out.writeAll(
        \\  Fossil disagrees with zit's RFC-cited expectation. Operator decides
        \\  RFC-misread vs RFC-wrong; record in ambiguities.md. Never change zit
        \\  to match fossil.
        \\
    );
}

// ---------------------------------------------------------------------------
// S1/S2/S3 -- manifest scenarios (parse -> create -> confirm via fossil)
// ---------------------------------------------------------------------------

fn runManifestScenario(
    arena: std.mem.Allocator,
    gpa: std.mem.Allocator,
    io: std.Io,
    tmp_root: []const u8,
    env: *const std.process.Environ.Map,
    out: *std.Io.Writer,
    sc: ManifestScenario,
) !bool {
    // zit's own product: the artifact fed to fossil is `create()`'s output,
    // never the raw RFC transcription (§6.2 round-trip; the two happen to be
    // byte-identical for S1/S3 and a strict-lexical reorder for S2, but the
    // input to fossil is always what zit itself wrote).
    var m = try artifact.parse(gpa, sc.fixture);
    defer m.deinit();
    const zit_bytes = try artifact.create(&m, gpa);
    defer gpa.free(zit_bytes);

    var name_buf: [64]u8 = undefined;
    const zit_name = artifact.artifactName(sc.algo, zit_bytes, &name_buf);

    const base = try std.fs.path.join(arena, &.{ tmp_root, sc.name });
    const repo_dir = try std.fs.path.join(arena, &.{ base, "repo" });
    const checkout_dir = try std.fs.path.join(arena, &.{ base, "checkout" });
    try std.Io.Dir.cwd().createDirPath(io, repo_dir);
    try std.Io.Dir.cwd().createDirPath(io, checkout_dir);

    const manifest_path = try std.fs.path.join(arena, &.{ repo_dir, "manifest.txt" });
    try std.Io.Dir.cwd().writeFile(io, .{ .sub_path = manifest_path, .data = zit_bytes });

    // fossil test-parse-manifest: repo-free syntactic accept (§4/§5). Exit is
    // 0 either way -- the VERDICT TEXT is what confirms zit's parse.
    {
        const res = try runFossil(gpa, io, &.{ "fossil", "test-parse-manifest", manifest_path }, repo_dir, env);
        defer gpa.free(res.stdout);
        defer gpa.free(res.stderr);
        if (std.mem.indexOf(u8, res.stdout, "reports the input is ok") == null) {
            try out.print("FAIL {s} ({s}): fossil test-parse-manifest did not report the input well-formed\n", .{ sc.name, sc.citation });
            try printBytesPreview(out, "zit bytes", zit_bytes);
            try out.print("  fossil verdict: {s}\n", .{res.stdout});
            try printMismatchFooter(out, sc.citation);
            return false;
        }
    }

    // fossil {sha1,sha3}sum: confirms zit's own artifactName computation.
    {
        const sum_cmd = if (sc.algo == .sha1) "sha1sum" else "sha3sum";
        const res = try runFossil(gpa, io, &.{ "fossil", sum_cmd, manifest_path }, repo_dir, env);
        defer gpa.free(res.stdout);
        defer gpa.free(res.stderr);
        const fossil_name = firstToken(res.stdout);
        if (!std.mem.eql(u8, fossil_name, zit_name)) {
            try out.print("FAIL {s} ({s}): fossil {s} disagrees with zit's artifactName\n", .{ sc.name, sc.citation, sum_cmd });
            try out.print("  zit name:    {s}\n", .{zit_name});
            try out.print("  fossil name: {s}\n", .{fossil_name});
            try printMismatchFooter(out, sc.citation);
            return false;
        }
    }

    // init + open + put + retrieve: confirms zit's create() output
    // round-trips through fossil's own content store under the given name.
    const repo_fossil = try std.fs.path.join(arena, &.{ repo_dir, "r.fossil" });
    const init_argv: []const []const u8 = if (sc.algo == .sha1)
        &.{ "fossil", "init", "--sha1", repo_fossil }
    else
        &.{ "fossil", "init", repo_fossil };
    {
        const res = try runFossil(gpa, io, init_argv, repo_dir, env);
        defer gpa.free(res.stdout);
        defer gpa.free(res.stderr);
        if (!okExit(res.term)) {
            try out.print("FAIL {s} ({s}): fossil init failed\n  stderr: {s}\n", .{ sc.name, sc.citation, res.stderr });
            try printMismatchFooter(out, sc.citation);
            return false;
        }
    }
    {
        const res = try runFossil(gpa, io, &.{ "fossil", "open", repo_fossil }, checkout_dir, env);
        defer gpa.free(res.stdout);
        defer gpa.free(res.stderr);
        if (!okExit(res.term)) {
            try out.print("FAIL {s} ({s}): fossil open failed\n  stderr: {s}\n", .{ sc.name, sc.citation, res.stderr });
            try printMismatchFooter(out, sc.citation);
            return false;
        }
    }
    {
        const res = try runFossil(gpa, io, &.{ "fossil", "test-content-put", manifest_path }, checkout_dir, env);
        defer gpa.free(res.stdout);
        defer gpa.free(res.stderr);
        if (!okExit(res.term)) {
            try out.print("FAIL {s} ({s}): fossil test-content-put failed\n  stderr: {s}\n", .{ sc.name, sc.citation, res.stderr });
            try printMismatchFooter(out, sc.citation);
            return false;
        }
    }

    const artifact_out_path = try std.fs.path.join(arena, &.{ checkout_dir, "out.bin" });
    {
        const res = try runFossil(gpa, io, &.{ "fossil", "artifact", zit_name, "out.bin" }, checkout_dir, env);
        defer gpa.free(res.stdout);
        defer gpa.free(res.stderr);
        if (!okExit(res.term)) {
            try out.print("FAIL {s} ({s}): fossil artifact could not resolve zit's name {s}\n  stderr: {s}\n", .{ sc.name, sc.citation, zit_name, res.stderr });
            try printMismatchFooter(out, sc.citation);
            return false;
        }
    }

    const fossil_bytes = try std.Io.Dir.cwd().readFileAlloc(io, artifact_out_path, gpa, .limited(1 << 20));
    defer gpa.free(fossil_bytes);
    if (!std.mem.eql(u8, zit_bytes, fossil_bytes)) {
        try out.print("FAIL {s} ({s}): fossil artifact returned bytes different from zit's create() output\n", .{ sc.name, sc.citation });
        try printBytesPreview(out, "zit bytes", zit_bytes);
        try printBytesPreview(out, "fossil bytes", fossil_bytes);
        try printDiffWindow(out, zit_bytes, fossil_bytes);
        try printMismatchFooter(out, sc.citation);
        return false;
    }

    try out.print("PASS {s} ({s}): zit's create() output confirmed by fossil (name {s})\n", .{ sc.name, sc.citation, zit_name });
    return true;
}

// ---------------------------------------------------------------------------
// S4 -- delta round-trip (never compared against fossil test-delta-create;
// fossil only applies zit's own delta and confirms the reconstructed target)
// ---------------------------------------------------------------------------

fn runDeltaScenario(
    arena: std.mem.Allocator,
    gpa: std.mem.Allocator,
    io: std.Io,
    tmp_root: []const u8,
    env: *const std.process.Environ.Map,
    out: *std.Io.Writer,
) !bool {
    const citation = "§5/§Appendix B.1";

    const zit_delta = try delta.create(gpa, delta_source, delta_target);
    defer gpa.free(zit_delta);

    // zit's own apply() must already reconstruct the target -- fossil only
    // ever confirms this, never establishes it.
    const self_applied = try delta.apply(gpa, delta_source, zit_delta);
    defer gpa.free(self_applied);
    std.debug.assert(std.mem.eql(u8, self_applied, delta_target));

    const base = try std.fs.path.join(arena, &.{ tmp_root, "S4" });
    try std.Io.Dir.cwd().createDirPath(io, base);
    const src_path = try std.fs.path.join(arena, &.{ base, "src.bin" });
    const delta_path = try std.fs.path.join(arena, &.{ base, "zit.delta" });
    const out_path = try std.fs.path.join(arena, &.{ base, "out.bin" });

    try std.Io.Dir.cwd().writeFile(io, .{ .sub_path = src_path, .data = delta_source });
    try std.Io.Dir.cwd().writeFile(io, .{ .sub_path = delta_path, .data = zit_delta });

    {
        const res = try runFossil(gpa, io, &.{ "fossil", "test-delta-apply", src_path, delta_path, out_path }, base, env);
        defer gpa.free(res.stdout);
        defer gpa.free(res.stderr);
        if (!okExit(res.term)) {
            try out.print("FAIL S4 ({s}): fossil test-delta-apply rejected zit's delta.create() output\n  stderr: {s}\n", .{ citation, res.stderr });
            try printBytesPreview(out, "zit delta", zit_delta);
            try printMismatchFooter(out, citation);
            return false;
        }
    }

    const fossil_out = try std.Io.Dir.cwd().readFileAlloc(io, out_path, gpa, .limited(1 << 20));
    defer gpa.free(fossil_out);
    if (!std.mem.eql(u8, fossil_out, delta_target)) {
        try out.print("FAIL S4 ({s}): fossil test-delta-apply produced bytes different from zit's target\n", .{citation});
        try printBytesPreview(out, "zit target", delta_target);
        try printBytesPreview(out, "fossil bytes", fossil_out);
        try printDiffWindow(out, delta_target, fossil_out);
        try printMismatchFooter(out, citation);
        return false;
    }

    try out.print("PASS S4 ({s}): fossil test-delta-apply reconstructs zit's delta.create() target\n", .{citation});
    return true;
}

// ---------------------------------------------------------------------------
// S5 -- clone from a re-packed store (§7.5, covering the §3
// serve-regenerated-delta note). The one scenario that drives the real `zit`
// BINARY: build a repo, evolve a file so its blob is stored as a delta, run
// `zit pack` so that delta is REGENERATED against our size-minimizing base, then
// serve the repacked store and have the real `fossil` client CLONE it. fossil
// hash-verifies every artifact it reconstructs on receipt, so a clone that exits
// 0 proves the regenerated delta container zit serves reconstructs byte-for-byte
// over the wire; the checked-out file is compared to zit's own committed bytes as
// the final oracle. Every byte fossil sees is zit's own output — fossil only
// confirms, never authors (the file policy at the top of this file).
// ---------------------------------------------------------------------------

/// Loopback port for S5's `zit serve` (distinct from the e2e ports 47251-47253
/// so a stray concurrent run does not collide).
const s5_serve_port: u16 = 47311;

/// Build the S5 file blob: 200 similar lines so `zit pack`'s best-of-N base
/// selection produces a profitable delta. `changed` mutates one line and appends
/// a tail, so the second commit's blob deltifies well against the first.
fn buildBlob(arena: std.mem.Allocator, changed: bool) ![]u8 {
    var aw = std.Io.Writer.Allocating.init(arena); // arena-owned; no deinit
    var i: usize = 0;
    while (i < 200) : (i += 1) {
        if (changed and i == 50) {
            try aw.writer.print("line {d}: CHANGED CONTENT for the regenerated-delta smoke\n", .{i});
        } else {
            try aw.writer.print("line {d}: the quick brown fox jumps over the lazy dog number {d}\n", .{ i, i });
        }
    }
    if (changed) try aw.writer.writeAll("line 200: appended tail exercises the delta insert op\n");
    return aw.toOwnedSlice();
}

/// Absolute path to the compiled `zit` binary. `zit_exe` is relative to the
/// build root (this process's cwd); a spawned child chdirs before exec, so it
/// must be resolved first. Allocated on `arena`.
fn zitAbsPath(arena: std.mem.Allocator, io: std.Io) ![]const u8 {
    const cwd_abs = try std.process.currentPathAlloc(io, arena);
    return std.fs.path.resolve(arena, &.{ cwd_abs, zit_exe });
}

/// Blocking `zit <tail...>` with cwd `cwd_path` and the shared smoke env
/// (FOSSIL_HOME set). Caller owns `result.stdout`/`result.stderr`.
fn runZit(
    gpa: std.mem.Allocator,
    io: std.Io,
    abs_exe: []const u8,
    cwd_path: []const u8,
    env: *const std.process.Environ.Map,
    tail: []const []const u8,
) !std.process.RunResult {
    var argv_buf: [8][]const u8 = undefined;
    argv_buf[0] = abs_exe;
    std.debug.assert(tail.len <= argv_buf.len - 1);
    for (tail, argv_buf[1..][0..tail.len]) |src, *dst| dst.* = src;
    return std.process.run(gpa, io, .{
        .argv = argv_buf[0 .. 1 + tail.len],
        .cwd = .{ .path = cwd_path },
        .environ_map = env,
    });
}

/// Spawn `zit serve --port <port>` detached, cwd `cwd_path` (so `discoverRoot`
/// finds `cwd_path/.zit`). stdout/stderr discarded — driven purely over the
/// socket. Caller `kill`s the returned child.
fn spawnZitServe(
    io: std.Io,
    abs_exe: []const u8,
    cwd_path: []const u8,
    env: *const std.process.Environ.Map,
    port_str: []const u8,
) !std.process.Child {
    return std.process.spawn(io, .{
        .argv = &.{ abs_exe, "serve", "--port", port_str },
        .cwd = .{ .path = cwd_path },
        .environ_map = env,
        .stdout = .ignore,
        .stderr = .ignore,
    });
}

/// Bounded wait for a server to bind: retry-connect to the loopback port
/// until accepted or a wall-clock deadline elapses (never a fixed sleep). A
/// successful TCP connect proves the listener is up.
fn waitForListen(io: std.Io, port: u16) !void {
    const addr = net.IpAddress.parseIp4("127.0.0.1", port) catch return error.BadTestAddress;
    const deadline_ns: i96 = 15_000_000_000; // 15 s cap — orders of magnitude of slack
    const start = std.Io.Clock.now(.awake, io).nanoseconds;
    while (true) {
        if (addr.connect(io, .{ .mode = .stream })) |stream| {
            stream.close(io);
            return;
        } else |_| {}
        if (std.Io.Clock.now(.awake, io).nanoseconds - start > deadline_ns) return error.ServerNeverBound;
    }
}

/// The count parsed from `zit pack`'s "<N> re-deltaed" clause, or null if the
/// clause is absent. Used to assert S5's fixture still forces a REGENERATED
/// delta (so the scenario keeps testing serve-of-a-regenerated-delta, not just a
/// full-form clone).
fn reDeltaCount(text: []const u8) ?usize {
    const idx = std.mem.indexOf(u8, text, " re-deltaed") orelse return null;
    var start = idx;
    while (start > 0 and std.ascii.isDigit(text[start - 1])) start -= 1;
    if (start == idx) return null;
    return std.fmt.parseInt(usize, text[start..idx], 10) catch null;
}

/// Run `zit <tail...>` and fail the scenario (printing stderr) unless it exits 0.
/// Returns the captured result on success (caller frees), or null on failure
/// (already freed + reported).
fn zitStep(
    gpa: std.mem.Allocator,
    io: std.Io,
    out: *std.Io.Writer,
    abs_exe: []const u8,
    cwd_path: []const u8,
    env: *const std.process.Environ.Map,
    tail: []const []const u8,
    label: []const u8,
) !?std.process.RunResult {
    const res = try runZit(gpa, io, abs_exe, cwd_path, env, tail);
    if (!okExit(res.term)) {
        try out.print("FAIL S5 (§7.5/§3): {s} failed\n  stderr: {s}\n", .{ label, res.stderr });
        try printMismatchFooter(out, "§7.5/§3");
        gpa.free(res.stdout);
        gpa.free(res.stderr);
        return null;
    }
    return res;
}

fn runCloneFromRepackedScenario(
    arena: std.mem.Allocator,
    gpa: std.mem.Allocator,
    io: std.Io,
    tmp_root: []const u8,
    env: *const std.process.Environ.Map,
    out: *std.Io.Writer,
) !bool {
    const citation = "§7.5/§3";
    const abs_exe = try zitAbsPath(arena, io);

    const base = try std.fs.path.join(arena, &.{ tmp_root, "S5" });
    const src_dir = try std.fs.path.join(arena, &.{ base, "src" });
    try std.Io.Dir.cwd().createDirPath(io, src_dir);

    // A source repo with two check-ins of an evolving file: the second blob is
    // stored as a delta, giving `pack` something to re-base.
    {
        const r = (try zitStep(gpa, io, out, abs_exe, src_dir, env, &.{"init"}, "zit init")) orelse return false;
        gpa.free(r.stdout);
        gpa.free(r.stderr);
    }
    const blob_path = try std.fs.path.join(arena, &.{ src_dir, "big.txt" });
    const seed = try buildBlob(arena, false);
    try std.Io.Dir.cwd().writeFile(io, .{ .sub_path = blob_path, .data = seed });
    inline for (.{
        .{ &[_][]const u8{ "add", "big.txt" }, "zit add (seed)" },
        .{ &[_][]const u8{ "commit", "-m", "seed", "--user", "u" }, "zit commit (seed)" },
    }) |step| {
        const r = (try zitStep(gpa, io, out, abs_exe, src_dir, env, step[0], step[1])) orelse return false;
        gpa.free(r.stdout);
        gpa.free(r.stderr);
    }
    const edited = try buildBlob(arena, true);
    try std.Io.Dir.cwd().writeFile(io, .{ .sub_path = blob_path, .data = edited });
    inline for (.{
        .{ &[_][]const u8{ "add", "big.txt" }, "zit add (grow)" },
        .{ &[_][]const u8{ "commit", "-m", "grow", "--user", "u" }, "zit commit (grow)" },
    }) |step| {
        const r = (try zitStep(gpa, io, out, abs_exe, src_dir, env, step[0], step[1])) orelse return false;
        gpa.free(r.stdout);
        gpa.free(r.stderr);
    }

    // Re-pack: every artifact is re-deltified against our chosen base, so a
    // served delta container is REGENERATED, not the one the write path stored.
    {
        const r = (try zitStep(gpa, io, out, abs_exe, src_dir, env, &.{"pack"}, "zit pack")) orelse return false;
        defer gpa.free(r.stdout);
        defer gpa.free(r.stderr);
        const n = reDeltaCount(r.stdout) orelse {
            try out.print("FAIL S5 ({s}): could not parse pack's re-delta count\n  pack stdout: {s}\n", .{ citation, r.stdout });
            return false;
        };
        if (n == 0) {
            try out.print("FAIL S5 ({s}): pack regenerated no delta — the fixture no longer exercises a served regenerated delta container\n  pack stdout: {s}\n", .{ citation, r.stdout });
            return false;
        }
    }

    // Serve the repacked store; the real fossil client clones it over the wire.
    const port_str = try std.fmt.allocPrint(arena, "{d}", .{s5_serve_port});
    var server = try spawnZitServe(io, abs_exe, src_dir, env, port_str);
    defer server.kill(io);
    waitForListen(io, s5_serve_port) catch {
        try out.print("FAIL S5 ({s}): zit serve never bound 127.0.0.1:{d}\n", .{ citation, s5_serve_port });
        return false;
    };

    // A bare-root URL: a conformant `fossil clone` POSTs to "/" (sync §4). This
    // is the fossil-client-from-root case e2e explicitly defers to smoke.
    const url = try std.fmt.allocPrint(arena, "http://127.0.0.1:{d}/", .{s5_serve_port});
    const clone_repo = try std.fs.path.join(arena, &.{ base, "verify.fossil" });
    {
        const res = try runFossil(gpa, io, &.{ "fossil", "clone", url, clone_repo }, base, env);
        defer gpa.free(res.stdout);
        defer gpa.free(res.stderr);
        if (!okExit(res.term)) {
            try out.print("FAIL S5 ({s}): fossil clone from the repacked zit store failed\n  stderr: {s}\n", .{ citation, res.stderr });
            try printMismatchFooter(out, citation);
            return false;
        }
    }

    // Check out the clone (autosync off — the server is about to be killed) so
    // fossil reconstructs the file from the artifacts it received.
    const co_dir = try std.fs.path.join(arena, &.{ base, "co" });
    try std.Io.Dir.cwd().createDirPath(io, co_dir);
    {
        const res = try runFossil(gpa, io, &.{ "fossil", "open", "--nosync", clone_repo }, co_dir, env);
        defer gpa.free(res.stdout);
        defer gpa.free(res.stderr);
        if (!okExit(res.term)) {
            try out.print("FAIL S5 ({s}): fossil open of the clone failed\n  stderr: {s}\n", .{ citation, res.stderr });
            try printMismatchFooter(out, citation);
            return false;
        }
    }

    // THE PROOF: fossil's reconstructed file == zit's own committed bytes. A
    // regenerated delta that dropped or corrupted a byte fails here.
    const co_blob = try std.fs.path.join(arena, &.{ co_dir, "big.txt" });
    const fossil_bytes = try std.Io.Dir.cwd().readFileAlloc(io, co_blob, gpa, .limited(1 << 20));
    defer gpa.free(fossil_bytes);
    if (!std.mem.eql(u8, edited, fossil_bytes)) {
        try out.print("FAIL S5 ({s}): fossil clone from the repacked store did not reconstruct zit's committed bytes\n", .{citation});
        try printBytesPreview(out, "zit committed", edited);
        try printBytesPreview(out, "fossil clone", fossil_bytes);
        try printDiffWindow(out, edited, fossil_bytes);
        try printMismatchFooter(out, citation);
        return false;
    }

    try out.print("PASS S5 ({s}): fossil clone from a repacked zit store reconstructs zit's committed bytes byte-for-byte\n", .{citation});
    return true;
}

// ---------------------------------------------------------------------------
// S6 -- clone → open against a real fossil SERVER (sync §3.7/§4, P3-F3). The
// mirror of S5: there zit served and fossil cloned; here fossil serves and the
// real `zit` binary clones AND opens, so the working tree zit materializes is
// the thing under test. This is the half of the clone story digest-set equality
// cannot see — a repository can converge perfectly on the wire and still be
// unusable if nothing turns it into files on disk.
//
// The file policy at the top of this file holds: the compared bytes are OUR OWN
// (we author `s6_payload`, hand it to `fossil add`/`fossil commit`, and compare
// it to what zit materializes). fossil is the container and the transport in
// between; it never authors a byte of the oracle. A mismatch means zit's
// artifact reconstruction or its working-tree materialization dropped or
// corrupted content that fossil carried faithfully.
// ---------------------------------------------------------------------------

/// Loopback port for S6's `fossil server` (distinct from S5's and from every
/// e2e port so a stray concurrent run cannot collide).
const s6_serve_port: u16 = 47312;

/// The bytes S6 round-trips. Authored here, never by fossil: multi-line with a
/// trailing newline, so a materialization that mangled line endings or dropped
/// the tail is caught.
const s6_payload =
    \\line one of the fossil-served source tree
    \\line two, so a truncation is visible
    \\line three
    \\
;

/// Run `fossil <argv...>` and fail the scenario (printing stderr) unless it
/// exits 0. Returns true on success; the caller aborts the scenario on false.
fn fossilStep(
    gpa: std.mem.Allocator,
    io: std.Io,
    out: *std.Io.Writer,
    argv: []const []const u8,
    cwd_path: []const u8,
    env: *const std.process.Environ.Map,
    label: []const u8,
) !bool {
    const res = try runFossil(gpa, io, argv, cwd_path, env);
    defer gpa.free(res.stdout);
    defer gpa.free(res.stderr);
    if (!okExit(res.term)) {
        try out.print("FAIL S6 (§3.7/§4): {s} failed\n  stderr: {s}\n", .{ label, res.stderr });
        return false;
    }
    return true;
}

fn runOpenFromFossilServerScenario(
    arena: std.mem.Allocator,
    gpa: std.mem.Allocator,
    io: std.Io,
    tmp_root: []const u8,
    env: *const std.process.Environ.Map,
    out: *std.Io.Writer,
) !bool {
    const citation = "§3.7/§4";
    const abs_exe = try zitAbsPath(arena, io);

    const base = try std.fs.path.join(arena, &.{ tmp_root, "S6" });
    const co_dir = try std.fs.path.join(arena, &.{ base, "co" });
    try std.Io.Dir.cwd().createDirPath(io, co_dir);
    const repo_path = try std.fs.path.join(arena, &.{ base, "source.fossil" });

    // A real fossil repository holding one check-in of OUR bytes.
    if (!try fossilStep(gpa, io, out, &.{ "fossil", "init", repo_path }, base, env, "fossil init")) return false;
    if (!try fossilStep(gpa, io, out, &.{ "fossil", "open", "--nosync", repo_path }, co_dir, env, "fossil open")) return false;
    const payload_path = try std.fs.path.join(arena, &.{ co_dir, "big.txt" });
    try std.Io.Dir.cwd().writeFile(io, .{ .sub_path = payload_path, .data = s6_payload });
    if (!try fossilStep(gpa, io, out, &.{ "fossil", "add", "big.txt" }, co_dir, env, "fossil add")) return false;
    if (!try fossilStep(
        gpa,
        io,
        out,
        &.{ "fossil", "commit", "-m", "s6 seed", "--user-override", "u", "--no-warnings" },
        co_dir,
        env,
        "fossil commit",
    )) return false;

    // Serve it with the real fossil server and clone it with the real zit
    // binary over the bare-root URL (sync §4: the client posts the repo URL path
    // unchanged and MUST NOT append /xfer).
    const port_str = try std.fmt.allocPrint(arena, "{d}", .{s6_serve_port});
    var server = std.process.spawn(io, .{
        .argv = &.{ "fossil", "server", "--port", port_str, repo_path },
        .cwd = .{ .path = base },
        .environ_map = env,
        .stdout = .ignore,
        .stderr = .ignore,
    }) catch |err| {
        try out.print("FAIL S6 ({s}): could not spawn fossil server: {s}\n", .{ citation, @errorName(err) });
        return false;
    };
    defer server.kill(io);
    // The same retry-connect wait S5 uses: a successful TCP connect proves the
    // listener is up, whichever binary owns it.
    waitForListen(io, s6_serve_port) catch {
        try out.print("FAIL S6 ({s}): fossil server never bound 127.0.0.1:{d}\n", .{ citation, s6_serve_port });
        return false;
    };

    const url = try std.fmt.allocPrint(arena, "http://127.0.0.1:{d}/", .{s6_serve_port});
    {
        const r = (try zitStep(gpa, io, out, abs_exe, base, env, &.{ "clone", url, "cloned" }, "zit clone (from fossil server)")) orelse return false;
        gpa.free(r.stdout);
        gpa.free(r.stderr);
    }

    // OPEN: the clone's checkout is still unborn, so this is what turns the
    // converged repository into a working tree.
    const cloned_dir = try std.fs.path.join(arena, &.{ base, "cloned" });
    {
        const r = (try zitStep(gpa, io, out, abs_exe, cloned_dir, env, &.{"open"}, "zit open")) orelse return false;
        defer gpa.free(r.stdout);
        defer gpa.free(r.stderr);
        if (std.mem.indexOf(u8, r.stdout, "trunk") == null) {
            try out.print("FAIL S6 ({s}): zit open did not report opening trunk\n  stdout: {s}\n", .{ citation, r.stdout });
            return false;
        }
    }

    // THE PROOF: the file zit materialized == the bytes we committed through
    // fossil. A dropped artifact, a mis-reconstructed delta, or a materialization
    // that never wrote the file fails here.
    const opened_blob = try std.fs.path.join(arena, &.{ cloned_dir, "big.txt" });
    const zit_bytes = std.Io.Dir.cwd().readFileAlloc(io, opened_blob, gpa, .limited(1 << 20)) catch |err| {
        try out.print("FAIL S6 ({s}): zit open left no readable big.txt in the cloned tree: {s}\n", .{ citation, @errorName(err) });
        try printMismatchFooter(out, citation);
        return false;
    };
    defer gpa.free(zit_bytes);
    if (!std.mem.eql(u8, s6_payload, zit_bytes)) {
        try out.print("FAIL S6 ({s}): the tree zit opened does not match the bytes committed through fossil\n", .{citation});
        try printBytesPreview(out, "committed", s6_payload);
        try printBytesPreview(out, "zit opened", zit_bytes);
        try printDiffWindow(out, s6_payload, zit_bytes);
        try printMismatchFooter(out, citation);
        return false;
    }

    try out.print("PASS S6 ({s}): zit clone+open against a real fossil server materializes the committed bytes byte-for-byte\n", .{citation});
    return true;
}