Rechecked at ba1a7b8f on 2026-09-21. The CONTRIBUTING.md anchor moved
from :149-156 to :162-169 (35b3c1a, #454). #430 and #450 have both closed.
The contradiction the issue is about is unchanged.
CLAUDE.md:23-29 requires a full workspace test run before any commit. CONTRIBUTING.md:162-169 describes a fallback for contributors who cannot build the GUI workspace members. Neither file says which governs a contributor whose machine cannot run the first one, and a contributor stopped work for two days to ask.
$ sed -n '23,29p' CLAUDE.md
## Pre-Commit Gate
**`cargo nextest run --workspace --locked` must pass with zero failures before
any commit.** Fix every failing test — do not commit with known
pre-existing failures. If a test asserts the wrong value, fix the test
assertion to match the code (or fix the code if the test is right); do
not skip or ignore the test.
$ sed -n '162,169p' CONTRIBUTING.md
The GUI workspace members still need the platform libraries named in CI. If
you cannot install those, do not estimate a count or edit the evidence metadata
by hand. Leave `tests/evidence/workspace-tests.json` and the three prose files
untouched. In the PR body, name the command you could not run and the missing
tool or system library that blocked it. A maintainer will run the full suite and
regenerate all four files before merge. This is the supported fallback; an
honest missing measurement is better than metadata that describes a run which
never happened.
The CONTRIBUTING.md passage grants its fallback for one artifact, the test-count metadata. It says nothing about the commit itself, which is what CLAUDE.md forbids.
Why it matters
The wall is the workspace layout, not any contributor's setup. apps/sysknife-shell/src-tauri is a workspace member, so --workspace compiles the Tauri crate and needs WebKit and GTK even when the change touches neither:
$ cargo metadata --no-deps --format-version 1 | python3 -c "import sys,json; d=json.load(sys.stdin); print([p['name'] for p in d['packages']])"
['sysknife-core', 'sysknife-brain', 'sysknife-types', 'sysknife-proto', 'sysknife-daemon', 'sysknife-daemon-test', 'sysknife-shell', 'sysknife-cli']
CONTRIBUTING.md:38 says GUI work is paused, so the crate that blocks the gate is the crate nobody is meant to be working on.
This has already cost time. On #338 a contributor named both documents, asked which applied, and waited rather than opening a draft:
CLAUDE.md requires cargo nextest run --workspace --locked to pass before any commit, while CONTRIBUTING.md documents a maintainer fallback when GUI libraries are unavailable. This WSL environment has Rust/Cargo but lacks the GUI development libraries and a live PostgreSQL service.
Three contributors in the ten days before that were blocked by build environment rather than by difficulty. Every hour spent on this question is an hour not spent on the patch, and it is spent by the people least able to guess the answer.
Scope
State the precedence where a contributor looks, which is CONTRIBUTING.md, and generalise the fallback past the test-count artifact:
CLAUDE.md is the rule for whoever merges to main, where the full suite is reachable. CONTRIBUTING.md is the contributor contract and wins when the two disagree. Say that in both files, in one sentence each.
- Say what a contributor runs instead: the package-scoped tests, Clippy and formatting they can run, plus
scripts/ci-local.sh --no-postgres, whose INCOMPLETE line already names the gate that did not run (docs/developer-guide.md:402-407).
- Say what goes in the pull request body: every command they could not run and what blocked it. That sentence already exists for the test count and needs to apply to the commit.
One open question the writer has to settle rather than paper over: whether --exclude sysknife-shell is the recommended local invocation. sysknife-shell is the package name, per the cargo metadata output above. Nobody has confirmed that exclusion produces a clean run on a host without the libraries, so either test it on such a host and document the result, or leave it out. Do not write it down untested; a command in the contributor guide that fails on the machine it was written for is worse than no command.
Tests first
scripts/check_evidence_claims.py reads CONTRIBUTING.md and docs/developer-guide.md, so there is somewhere to put this:
$ grep -n '"CONTRIBUTING.md"\|"docs/developer-guide.md"' scripts/check_evidence_claims.py
59: "CONTRIBUTING.md",
67: "docs/developer-guide.md",
88:STORY_COVERAGE_FILE = "CONTRIBUTING.md"
The flag the new passage should name is real, and its own usage line already documents it:
$ grep -n -- '--no-postgres' scripts/ci-local.sh | head -4
26:Usage: scripts/ci-local.sh [--fast] [--no-postgres] [--install-hooks] [--help]
33: --no-postgres Skip the required postgres-contract job even when a
51: --no-postgres) run_postgres=false ;;
354: record SKIP "${label} (--no-postgres)"
Pin the precedence sentence. Assert that CONTRIBUTING.md contains a statement naming itself as the contributor contract, and fail when it disappears. A prose guard is weak on its own, which is why the second one matters more.
Pin the two commands to the tree. Assert that every shell command the new passage tells a contributor to run exists: scripts/ci-local.sh accepts --no-postgres, and the flag appears in its own --help. Prove the guard bites by renaming the flag in a scratch copy and watching the check go red. That is the assertion that stops this passage going stale the way the pre-commit description in #430 did.
Do not assert the GUI libraries are missing. A test that depends on the host lacking WebKit passes on CI for the wrong reason and fails on a maintainer's laptop. Keep the assertions on the documents and the flags.
Worth knowing before you start
#430 and #450 have both closed since I filed this, as fab9053 and 736f945.
Nothing else is open against docs/developer-guide.md, so the coordination
problem I warned about here is gone. Say in your pull request which lines you
touched anyway.
Difficulty
easy. Prose in two files and a guard in Python. No Rust, no VM, no provider, no credentials, and the irony is that this issue is one a contributor without the GUI libraries can finish.
Getting started
CONTRIBUTING.md
has the build and test commands. The one that matters here is
bash scripts/ci-local.sh --no-postgres, which you should run once and read
before writing about it. No CLA and no copyright waiver. The project is MIT.
CLAUDE.md:23-29requires a full workspace test run before any commit.CONTRIBUTING.md:162-169describes a fallback for contributors who cannot build the GUI workspace members. Neither file says which governs a contributor whose machine cannot run the first one, and a contributor stopped work for two days to ask.The
CONTRIBUTING.mdpassage grants its fallback for one artifact, the test-count metadata. It says nothing about the commit itself, which is whatCLAUDE.mdforbids.Why it matters
The wall is the workspace layout, not any contributor's setup.
apps/sysknife-shell/src-tauriis a workspace member, so--workspacecompiles the Tauri crate and needs WebKit and GTK even when the change touches neither:CONTRIBUTING.md:38says GUI work is paused, so the crate that blocks the gate is the crate nobody is meant to be working on.This has already cost time. On #338 a contributor named both documents, asked which applied, and waited rather than opening a draft:
Three contributors in the ten days before that were blocked by build environment rather than by difficulty. Every hour spent on this question is an hour not spent on the patch, and it is spent by the people least able to guess the answer.
Scope
State the precedence where a contributor looks, which is
CONTRIBUTING.md, and generalise the fallback past the test-count artifact:CLAUDE.mdis the rule for whoever merges tomain, where the full suite is reachable.CONTRIBUTING.mdis the contributor contract and wins when the two disagree. Say that in both files, in one sentence each.scripts/ci-local.sh --no-postgres, whoseINCOMPLETEline already names the gate that did not run (docs/developer-guide.md:402-407).One open question the writer has to settle rather than paper over: whether
--exclude sysknife-shellis the recommended local invocation.sysknife-shellis the package name, per thecargo metadataoutput above. Nobody has confirmed that exclusion produces a clean run on a host without the libraries, so either test it on such a host and document the result, or leave it out. Do not write it down untested; a command in the contributor guide that fails on the machine it was written for is worse than no command.Tests first
scripts/check_evidence_claims.pyreadsCONTRIBUTING.mdanddocs/developer-guide.md, so there is somewhere to put this:The flag the new passage should name is real, and its own usage line already documents it:
Pin the precedence sentence. Assert that
CONTRIBUTING.mdcontains a statement naming itself as the contributor contract, and fail when it disappears. A prose guard is weak on its own, which is why the second one matters more.Pin the two commands to the tree. Assert that every shell command the new passage tells a contributor to run exists:
scripts/ci-local.shaccepts--no-postgres, and the flag appears in its own--help. Prove the guard bites by renaming the flag in a scratch copy and watching the check go red. That is the assertion that stops this passage going stale the way the pre-commit description in #430 did.Do not assert the GUI libraries are missing. A test that depends on the host lacking WebKit passes on CI for the wrong reason and fails on a maintainer's laptop. Keep the assertions on the documents and the flags.
Worth knowing before you start
#430 and #450 have both closed since I filed this, as
fab9053and736f945.Nothing else is open against
docs/developer-guide.md, so the coordinationproblem I warned about here is gone. Say in your pull request which lines you
touched anyway.
Difficulty
easy. Prose in two files and a guard in Python. No Rust, no VM, no provider, no credentials, and the irony is that this issue is one a contributor without the GUI libraries can finish.Getting started
CONTRIBUTING.md
has the build and test commands. The one that matters here is
bash scripts/ci-local.sh --no-postgres, which you should run once and readbefore writing about it. No CLA and no copyright waiver. The project is MIT.