pointbreak 0.9.0

Durable terminal code review for changes humans and coding agents collaborate on together
Documentation
{
  description = "Pointbreak development environment";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
  };

  outputs =
    { nixpkgs, ... }:
    let
      # Systems the dev shell is built for: Linux and macOS on x86_64 and arm64.
      systems = [
        "aarch64-linux"
        "x86_64-linux"
        "aarch64-darwin"
        "x86_64-darwin"
      ];
      forEachSystem = f: nixpkgs.lib.genAttrs systems (system: f nixpkgs.legacyPackages.${system});

      # cocogitto pinned to 6.5.0 to match CI (.github/workflows/*: cargo binstall
      # cocogitto@6.5.0) and mise.toml. nixpkgs ships 7.0.0, which this repo is NOT
      # ready for: cog 7 changes the release tag lifecycle the signed-tag finalizer
      # depends on (scripts/finalize-cocogitto-release-tag.sh:64) and adds native
      # scope validation the commit-msg hook still shims by hand (cog.toml:63-67).
      # Moving to cog 7 means bumping the flake, the three CI pins, removing that
      # shim, and re-validating `just release-bump-selftest` together in a
      # dedicated PR.
      mkCocogitto =
        pkgs:
        pkgs.cocogitto.overrideAttrs (_: rec {
          version = "6.5.0";
          src = pkgs.fetchFromGitHub {
            owner = "cocogitto";
            repo = "cocogitto";
            tag = version;
            hash = "sha256-aAVoPPeuJN6QPcuc3oBF93dP6U+74bAoSDw93XR01Vo=";
          };
          cargoDeps = pkgs.rustPlatform.fetchCargoVendor {
            inherit src;
            name = "cocogitto-${version}-vendor";
            hash = "sha256-yDpZHkRKsWXXHuSKnzhGrjsFLUFZEpC23tcU3FeUZK8=";
          };
          # 6.5.0's completion subcommand differs from 7.x; completions aren't
          # needed here, so skip the postInstall that generates them.
          postInstall = "";
        });
    in
    {
      # `nix fmt` formats the flake with the canonical RFC-166 formatter.
      formatter = forEachSystem (pkgs: pkgs.nixfmt);

      devShells = forEachSystem (
        pkgs:
        let
          cocogitto = mkCocogitto pkgs;
        in
        {
          default = pkgs.mkShell {
            # Everything on PATH inside `nix develop`.
            packages = with pkgs; [
              # --- Rust ---
              # rustup (not a fixed rustc) because the Justfile/CI use BOTH
              # `cargo +stable` (build/test/clippy) and `cargo +nightly` (rustfmt,
              # which relies on unstable_features). Pinning a single rustc in Nix
              # can't serve both channels; rustup keeps rust-toolchain.toml as the
              # source of truth for stable and installs each channel on demand (see
              # RUSTUP_AUTO_INSTALL in the shellHook).
              rustup

              # --- Dev tooling (mirrors mise.toml [tools]) ---
              just
              cargo-nextest
              cargo-edit
              cocogitto # `cog`, pinned to 6.5.0 for CI parity — see mkCocogitto above
              gh
              jq
              nodejs_22

              # --- Native build deps ---
              # libsqlite3-sys / rusqlite / zstd / lmdb-master3-sys all compile
              # bundled C, so cargo needs a working C toolchain and pkg-config.
              # NixOS has no global cc; mkShell's stdenv provides one, and these make
              # it explicit.
              pkg-config
              git # used by build.rs (identity capture) and by cog hooks
            ];

            shellHook = ''
              # Let `cargo +stable` and `cargo +nightly` install their toolchain on
              # first use instead of erroring. stable comes from rust-toolchain.toml;
              # nightly (needed by `just fmt`) is fetched the first time it's invoked.
              export RUSTUP_AUTO_INSTALL=1

              # Replicate mise's `[env] _.path`: prefer freshly-built binaries.
              # Guarded so re-sourcing the hook doesn't stack duplicate entries.
              case ":$PATH:" in
                *":$PWD/target/debug:"*) ;;
                *) export PATH="$PWD/target/release:$PWD/target/debug:$PATH" ;;
              esac

              # Install cocogitto's commit-msg / pre-push hooks once (mise did this via
              # a postinstall step). Idempotent: only runs when the hook is missing.
              if [ -d .git ] && [ ! -f .git/hooks/commit-msg ]; then
                cog install-hook --all >/dev/null 2>&1 \
                  && echo "pointbreak: installed cocogitto git hooks"
              fi

              echo "pointbreak dev shell — rustup $(rustup --version 2>/dev/null | awk '{print $2}'), just, nextest, cog, node $(node --version)"
            '';
          };
        }
      );

      # `nix flake check` builds every derivation under `checks`. This one realises
      # the pinned cocogitto (proving the from-source pin still compiles on a clean
      # machine) and asserts the version-critical tools resolve, so a broken pin or
      # version drift fails the flake rather than only surfacing in a live shell.
      checks = forEachSystem (
        pkgs:
        let
          cocogitto = mkCocogitto pkgs;
        in
        {
          devshell-tools =
            pkgs.runCommand "devshell-tools-check"
              {
                nativeBuildInputs = [
                  cocogitto
                  pkgs.nodejs_22
                  pkgs.just
                  pkgs.cargo-nextest
                ];
              }
              ''
                # rustup is intentionally excluded: it insists on a writable HOME
                # to create ~/.rustup, which the build sandbox denies. Its presence
                # is already covered by evaluating the devShell.
                cog --version | grep -qw 6.5.0
                node --version | grep -q '^v22\.'
                just --version >/dev/null
                cargo-nextest nextest --version >/dev/null
                touch "$out"
              '';
        }
      );
    };
}