···11+# Human Test Plan: MM-64 Nix Flake + devenv Dev Shell
22+33+**Branch:** MM-64
44+**Base commit:** 0638285
55+**HEAD commit:** 1cc5cbb
66+**Generated:** 2026-03-07
77+88+---
99+1010+## Prerequisites
1111+1212+- macOS machine with Nix installed (multi-user or single-user)
1313+- The `ezpds` repository cloned and checked out at the MM-64 branch (commit `1cc5cbb` or later)
1414+- `direnv` installed and hooked into the user's shell (for HV-3)
1515+- Access to a Linux x86_64 machine or CI runner with Nix installed (for HV-1)
1616+- `rustup` installed outside of Nix (for HV-2)
1717+- All automated operational tests passing
1818+1919+**Note:** All `nix develop` commands require the `--impure` flag due to devenv's requirement to access `$PWD`. Without it, devenv fails with "devenv was not able to determine the current directory".
2020+2121+---
2222+2323+## Phase 1: Static File Verification
2424+2525+| Step | Action | Expected |
2626+|------|--------|----------|
2727+| 1.1 | Open `flake.nix` and inspect the `outputs` attribute | Only `devShells` is defined. No `packages`, `nixosModules`, `nixosConfigurations`, or other outputs present. |
2828+| 1.2 | Open `flake.nix` and inspect the `inputs.systems` attribute | Set to `github:nix-systems/default`, which provides `aarch64-darwin`, `x86_64-darwin`, `x86_64-linux`, and `aarch64-linux`. |
2929+| 1.3 | Open `rust-toolchain.toml` | Contains `channel = "stable"` and `components = ["rustfmt", "clippy", "rust-analyzer"]`. |
3030+| 1.4 | Open `devenv.nix` | Contains `languages.rust.enable = true`, `toolchainFile = ./rust-toolchain.toml`, and packages list with `just`, `cargo-audit`, `sqlite`, `pkg-config`. Also sets `LIBSQLITE3_SYS_USE_PKG_CONFIG = "1"`. |
3131+| 1.5 | Open `.envrc` | Contains exactly `use flake` (one line). |
3232+| 1.6 | Run `git status` from repo root | `.envrc`, `flake.nix`, `devenv.nix`, `rust-toolchain.toml`, `flake.lock`, `.gitignore` are all tracked (not untracked or modified). |
3333+3434+---
3535+3636+## Phase 2: Operational Verification (macOS)
3737+3838+| Step | Action | Expected |
3939+|------|--------|----------|
4040+| 2.1 | `nix develop --impure --command bash -c 'echo "shell activated"'` | Prints "shell activated" and exits with code 0. devenv task output may appear on stderr (normal). |
4141+| 2.2 | `nix develop --impure --command bash -c 'rustc --version'` | Prints `rustc 1.94.0 (...)` or a similar stable version. No "nightly" or "beta" in the output. |
4242+| 2.3 | `nix develop --impure --command bash -c 'cargo --version && rust-analyzer --version && cargo clippy --version && rustfmt --version && just --version && cargo audit --version'` | All six commands succeed (exit 0). Each prints a version string. |
4343+| 2.4 | `nix develop --impure --command bash -c 'sqlite3 --version && pkg-config --libs sqlite3'` | sqlite3 prints a version (3.x.x). pkg-config prints `-L/nix/store/.../lib -lsqlite3`. Both succeed. |
4444+| 2.5 | `nix develop --impure --command bash -c 'echo $LIBSQLITE3_SYS_USE_PKG_CONFIG'` | Prints `1`. |
4545+4646+---
4747+4848+## End-to-End: Fresh Clone to Working Dev Shell
4949+5050+**Purpose:** Validates that a new contributor can go from `git clone` to a fully working development environment with zero manual dependency installation beyond Nix itself.
5151+5252+1. Clone the repository to a temporary directory: `git clone <repo-url> /tmp/ezpds-test && cd /tmp/ezpds-test && git checkout MM-64`
5353+2. Run `nix develop --impure --command bash -c 'rustc --version && cargo --version && just --version && sqlite3 --version'`
5454+3. **Expected:** First run may take several minutes (downloading Nix store paths). All four commands succeed. The Rust version is stable.
5555+4. Run `nix develop --impure --command cargo check` from the repo root.
5656+5. **Expected:** Cargo resolves dependencies and type-checks the workspace. Exit code 0. Confirms the toolchain, sqlite3 headers, and pkg-config all integrate correctly for an actual build.
5757+6. Clean up: `rm -rf /tmp/ezpds-test`
5858+5959+---
6060+6161+## End-to-End: direnv Integration
6262+6363+**Purpose:** Validates that `.envrc` + `use flake` provides automatic shell activation when entering the project directory.
6464+6565+1. Ensure direnv is installed: `direnv version` (should print a version).
6666+2. Ensure direnv is hooked into your shell. For zsh, verify `eval "$(direnv hook zsh)"` is in `~/.zshrc`. For bash, verify `eval "$(direnv hook bash)"` is in `~/.bashrc`.
6767+3. Navigate to repo root: `cd /path/to/ezpds`
6868+4. Run `direnv allow` to approve the `.envrc` file.
6969+5. Navigate away: `cd /tmp`
7070+6. Navigate back: `cd /path/to/ezpds`
7171+7. **Expected:** direnv prints loading/activation messages. After activation completes, run `which rustc` — it should point to a path inside `/nix/store/`, not a system rustc.
7272+8. Run `rustc --version` — should match the stable version seen in Phase 2 tests.
7373+7474+---
7575+7676+## Human Verification Required
7777+7878+| ID | Criterion | Why Manual | Steps |
7979+|----|-----------|------------|-------|
8080+| HV-1 | MM-64.AC1.2: Dev shell activates on Linux (x86_64-linux) | Cannot test on macOS; requires a Linux machine or CI runner | On an x86_64-linux machine with Nix installed, clone the repo, checkout MM-64, and run `nix develop --impure --command bash -c 'rustc --version && echo "Linux shell OK"'`. Expected: exit code 0, stable rustc version printed, "Linux shell OK" printed. |
8181+| HV-2 | MM-64.AC3.2: rustup reads rust-toolchain.toml without Nix | Must run outside the Nix shell on a machine with rustup installed | 1. Ensure rustup is installed (`rustup --version` outside any Nix shell). 2. From repo root, without entering `nix develop`, run `rustup show`. 3. Expected: output includes "stable" as the active toolchain, references `rust-toolchain.toml` as the override source, and shows a Rust version consistent with the stable channel. |
8282+| HV-3 | MM-64.AC4.2: direnv activates shell on `cd` | Requires an interactive shell session with direnv hooked in | See "End-to-End: direnv Integration" above. Key pass condition: after `direnv allow` and re-entering the directory, `which rustc` resolves to a `/nix/store/` path. |
8383+8484+---
8585+8686+## Traceability
8787+8888+| Acceptance Criterion | Automated | Manual Step |
8989+|----------------------|-----------|-------------|
9090+| MM-64.AC1.1: nix develop succeeds on macOS | PASS | Phase 2, Step 2.1 |
9191+| MM-64.AC1.2: nix develop succeeds on Linux | N/A | HV-1 |
9292+| MM-64.AC2.1: rustc is stable | PASS | Phase 2, Step 2.2 |
9393+| MM-64.AC2.2: cargo available | PASS | Phase 2, Step 2.3 |
9494+| MM-64.AC2.3: rust-analyzer available | PASS | Phase 2, Step 2.3 |
9595+| MM-64.AC2.4: clippy available | PASS | Phase 2, Step 2.3 |
9696+| MM-64.AC2.5: rustfmt available | PASS | Phase 2, Step 2.3 |
9797+| MM-64.AC2.6: just available | PASS | Phase 2, Step 2.3 |
9898+| MM-64.AC2.7: cargo-audit available | PASS | Phase 2, Step 2.3 |
9999+| MM-64.AC2.8: sqlite3 + pkg-config | PASS | Phase 2, Step 2.4 |
100100+| MM-64.AC3.1: Rust version matches rust-toolchain.toml | PASS | Phase 2, Step 2.2 |
101101+| MM-64.AC3.2: rustup reads rust-toolchain.toml | N/A | HV-2 |
102102+| MM-64.AC4.1: .envrc tracked with `use flake` | PASS | Phase 1, Step 1.5 |
103103+| MM-64.AC4.2: direnv activates on cd | N/A | HV-3 |
104104+| MM-64.AC5.1: flake.lock tracked by git | PASS | Phase 1, Step 1.6 |
105105+| MM-64.AC6.1: no packages output | PASS | Phase 1, Step 1.1 |
106106+| MM-64.AC6.2: no nixosModules output | PASS | Phase 1, Step 1.1 |