commit - 36ff1dbc2ebdbcd1ec00a70eeb4a3f5382e195cf
commit + d37c6289137cc9ab2fb068f9e633d3ea779caddb
blob - 5d698d507c141ae6341126006fb465c715709410
blob + c6e43f01290a4b45639b4af3b288fe98541f8991
--- AGENTS.md
+++ AGENTS.md
### 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
.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
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
+#!/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