Commit Diff


commit - 36ff1dbc2ebdbcd1ec00a70eeb4a3f5382e195cf
commit + d37c6289137cc9ab2fb068f9e633d3ea779caddb
blob - 5d698d507c141ae6341126006fb465c715709410
blob + c6e43f01290a4b45639b4af3b288fe98541f8991
--- AGENTS.md
+++ AGENTS.md
@@ -13,3 +13,13 @@ Five canonical roles, default strings (`needs-triage`,
 ### Domain docs
 
 Single-context: one `CONTEXT.md` and one `docs/adr/` at the repo root (created lazily). See `docs/agents/domain.md`.
+
+## Testing
+
+### Clean-room builds (the verification step)
+
+Verify every change with **`make check`** (which runs `./clean-check`), not an incremental `make`. It wipes all build artifacts, does a fresh **default** build, and runs every regress suite from scratch, exiting non-zero if the build or any suite fails.
+
+Use it on every rebuild you intend to trust. Incremental builds bit this project twice: a stale in-tree binary, and an `FUGU_DEBUG=1` build left in `src/` — which dies under `pledge(2)` and hangs `chat`/`compact`/`tui` (only those three exec the in-tree binaries; the rest compile their own copy into `regress/<suite>/obj/`). A clean-room run sidesteps both. See `.scratch/regress-debug-binary-gotcha`.
+
+Each suite is also runnable standalone: `make -C regress/<suite> regress`. Suites self-abort after a 15s alarm rather than hanging.
blob - 7ac86ed774c4324a94572ea3a4703c4bdd0aa43b
blob + e1a73701b6efa347e8a11093b00cbd1a9242c56e
--- Makefile
+++ Makefile
@@ -10,6 +10,13 @@ SUBDIR=	src
 
 .include <bsd.subdir.mk>
 
+# Clean-room build + full regress: the canonical verification step.  Wipes all
+# build artifacts, does a fresh DEFAULT build, runs every suite from scratch.
+# Fails non-zero on any build or test failure.  See ./clean-check.
+.PHONY: check
+check:
+	@sh ${.CURDIR}/clean-check
+
 # Package the working tree into the source distfile the port consumes: a clean
 # ${DISTNAME}.tar.gz (top directory ${DISTNAME}/, no build artifacts) written to
 # ${DISTDIR}.  Afterwards, in the port: `make makesum` to refresh distinfo, then
@@ -19,8 +26,8 @@ SUBDIR=	src
 dist:
 	rm -rf ${DISTNAME}
 	mkdir ${DISTNAME}
-	pax -rw LICENSE Makefile README.md docs etc man regress run-fugu src \
-	    ${DISTNAME}
+	pax -rw LICENSE Makefile README.md docs etc man regress run-fugu \
+	    clean-check src ${DISTNAME}
 	find ${DISTNAME} \( -name '*.o' -o -name '*.d' \) -exec rm -f {} +
 	find ${DISTNAME} -type d -name obj -exec rm -rf {} +
 	find ${DISTNAME}/regress -type f -name '*_test' -exec rm -f {} +
blob - /dev/null
blob + dfd805bd0cc28260c79fa613cb14b33e7391b828 (mode 755)
--- /dev/null
+++ clean-check
@@ -0,0 +1,53 @@
+#!/bin/sh
+#
+# clean-check -- clean-room build and full regress run.
+#
+# The canonical "did I break anything" check: wipe every build artifact, do a
+# fresh DEFAULT build, then run every regress suite from scratch.  Prefer this
+# over incremental `make` when verifying a change -- it sidesteps the two traps
+# this project hit with incremental builds: a stale in-tree binary, and an
+# FUGU_DEBUG=1 build left in src/ (which dies under pledge(2), hanging
+# chat/compact/tui).  See .scratch/regress-debug-binary-gotcha.
+#
+# Exits 0 only if the build is clean and every suite passes.
+
+set -u
+cd "$(dirname "$0")" || exit 1
+
+echo '== clean: removing all build artifacts =='
+if [ -d .git ]; then
+	git clean -fdX
+else
+	find . \( -name '*.o' -o -name '*.d' -o -name '*.core' \) -delete
+	find . -type d -name obj -prune -exec rm -rf {} +
+	rm -f src/parent/parse.c src/parent/parse.h \
+	      regress/parse/parse.c regress/parse/parse.h
+	rm -f src/parent/fugu src/ui/fugu-ui src/net/fugu-net \
+	      src/exec/fugu-exec src/fetch/fugu-fetch
+	rm -f regress/*/*_test
+fi
+
+echo '== build: src (DEFAULT flavor -- FUGU_DEBUG breaks chat/compact/tui) =='
+if ! ( cd src && make ); then
+	echo 'clean-check: BUILD FAILED' >&2
+	exit 1
+fi
+
+echo '== regress: every suite from clean =='
+fail=''
+for mk in regress/*/Makefile; do
+	d=${mk%/Makefile}
+	s=${d#regress/}
+	printf '\n--- %s ---\n' "$s"
+	if ! ( cd "$d" && timeout -k 5 60 make regress ); then
+		fail="$fail $s"
+	fi
+done
+
+echo
+if [ -z "$fail" ]; then
+	echo 'clean-check: PASS -- all suites green'
+else
+	echo "clean-check: FAIL --$fail" >&2
+	exit 1
+fi