Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions .no-mistakes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
# HEAD-continuity guard; see docs/architecture.md "No-mistakes gate authority boundary."
disable_project_settings: true

# Pin lint and the portable behavior suite to the same deterministic commands
# the Linux CI jobs run, instead of leaving them to no-mistakes' default handling.
# Pin lint to the deterministic command the Linux CI job runs, and load test
# policy only from target main instead of the untrusted branch under review.
# CI separately owns platform-specific compatibility lanes, including the stock
# macOS Bash snapshot checks. Without a configured
# commands.lint, the gate's lint step never ran the deterministic
Expand All @@ -19,13 +19,14 @@ disable_project_settings: true
# them. commands.lint delegates to bin/fm-lint.sh, the single owner of the lint
# definition that .github/workflows/ci.yml also invokes, so local can never
# diverge from CI again (parity asserted by tests/fm-lint.test.sh).
# The test command mirrors the Linux behavior job in .github/workflows/ci.yml:
# iterate every tests/*.test.sh, run each, and fail the step if any one exits
# non-zero (an agent-driven test step has crashed the daemon). The e2e tests need
# tmux on PATH, which the firstmate environment provides.
# The target-main selector may shadow an exact focused mapping, but gate-shadow
# always runs the complete suite once and propagates every failure.
# A selector-introducing change has no target-main selector to load yet, so its
# bootstrap path runs this fixed complete-suite command once instead.
# The e2e tests need tmux on PATH, which the firstmate environment provides.
commands:
lint: 'bin/fm-lint.sh'
test: 'command -v tmux >/dev/null || { echo "tmux is required for e2e tests" >&2; exit 1; }; tmux -V; rc=0; for t in tests/*.test.sh; do echo "== $t =="; bash "$t" || rc=1; done; exit "$rc"'
test: 'umask 077; tmp_dir=$(mktemp -d "${TMPDIR:-/tmp}/fm-test-select-gate.XXXXXX") || exit 70; cleanup() { rm -rf -- "$tmp_dir"; }; signal_exit() { exit 70; }; trap cleanup EXIT; trap signal_exit HUP INT TERM; git clone --quiet --filter=blob:none --no-checkout --depth=1 --branch main https://github.com/xLabs-OS/firstmate "$tmp_dir/target" || exit 70; target_selector=$(git -C "$tmp_dir/target" ls-tree -r --name-only HEAD -- bin/fm-test-select.sh) || exit 70; if [ "$target_selector" = bin/fm-test-select.sh ]; then git -C "$tmp_dir/target" show HEAD:bin/fm-test-select.sh > "$tmp_dir/selector" || exit 70; chmod 500 "$tmp_dir/selector" || exit 70; bash "$tmp_dir/selector" gate-shadow; elif [ -z "$target_selector" ]; then printf "%s\\n" "fm-test-select: target main has no selector; running complete bootstrap suite" >&2; command -v tmux >/dev/null || { echo "tmux is required for e2e tests" >&2; exit 1; }; tmux -V; rc=0; for t in tests/*.test.sh; do echo "== $t =="; bash "$t" || rc=1; done; exit "$rc"; else exit 70; fi'

# Keep test evidence out of this repo; it stays in a temp dir instead.
test:
Expand Down
6 changes: 4 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,16 @@ Check and test the toolbelt before pushing:
```sh
for script in bin/*.sh bin/backends/*.sh; do bash -n "$script"; done # syntax-check the toolbelt
bin/fm-lint.sh # lint the toolbelt and behavior tests; the single owner CI and the no-mistakes gate both run
for test_script in tests/*.test.sh; do bash "$test_script"; done # behavior tests, matching CI and no-mistakes commands.test
bin/fm-test-select.sh local # path-aware local feedback with fail-closed complete fallback
[ "$(readlink CLAUDE.md)" = "AGENTS.md" ]
[ "$(readlink .claude/skills)" = "../.agents/skills" ]
tmp=$(mktemp -d) && printf 'done: smoke\n' > "$tmp/smoke.status" && FM_STATE_OVERRIDE="$tmp" FM_SIGNAL_GRACE=1 FM_POLL=1 FM_HEARTBEAT=999999 bin/fm-watch-arm.sh # watcher re-arm smoke test (prints arm status, then an actionable signal)
```

Focused selection is local feedback only; no-mistakes still runs the complete suite once before delivery.
Running a specific test directly remains useful as supplementary feedback while developing its subject.
Discover tests by listing `tests/*.test.sh`: each is a self-contained bash script named `<subject>.test.sh`, and its header comment describes what it covers, so run one directly to focus on a subject.
Tests that need a real optional backend or an explicit opt-in (real herdr/zellij/cmux smoke tests, the live Pi regression) skip themselves and print the tool or environment gate needed to enable them, so the run-all loop above is always safe.
Tests that need a real optional backend or an explicit opt-in (real herdr/zellij/cmux smoke tests, the live Pi regression) skip themselves and print the tool or environment gate needed to enable them, so the selector's complete fallback remains safe.

## Questions

Expand Down
Loading