Architecture fitness functions for openboot. Each *_test.go file enforces one
project-level invariant documented in CLAUDE.md.
This is the Architecture Fitness Harness described in Martin Fowler's Harness Engineering for Coding Agents: cheap, fast, deterministic computational sensors that block architectural drift introduced by either humans or AI agents.
Each rule has two pieces:
- A test in
*_test.gothat walks the AST of every file underinternal/andcmd/and collects call sites matching a forbidden pattern. - A baseline file under
baseline/<rule-name>.txtlisting existing violations as<file>:<line>. The test fails only on new violations — entries in the baseline pass silently.
Stale baseline entries (the code was fixed but the line was not removed from the baseline) are logged but do not fail the test.
| Rule | Test | Baseline | Source convention |
|---|---|---|---|
no-direct-exec |
exec_test.go |
yes | "Do not call exec.Command directly from feature code" |
no-raw-http |
http_test.go |
yes | "Use httputil.Do() — handles 429 + Retry-After" |
no-os-getenv-home |
envhome_test.go |
no (hard rule) | "Use os.UserHomeDir() — never hardcode ~ or /Users/..." |
# Normal run (CI, pre-push, local).
go test ./internal/archtest/...
# After an intentional change that adds a violation, regenerate baseline:
ARCHTEST_UPDATE_BASELINE=1 go test ./internal/archtest/...
git add internal/archtest/baseline/When the regeneration adds entries, the commit message should explain why the new call site is justified — those baseline diffs are the audit trail.
- Add
<name>_test.gowith aTest<Name>function. - Use
walkProductionFiles+findCalls/findIdentUses(or hand-roll anast.Inspect) to collect violations. - Decide:
- Hard rule (currently zero violations and should stay that way) —
fail immediately on any hit. See
envhome_test.go. - Soft rule (baseline existing call sites) — call
enforce(t, rule, found). Generate the baseline once withARCHTEST_UPDATE_BASELINE=1.
- Hard rule (currently zero violations and should stay that way) —
fail immediately on any hit. See
- Document the rule in CLAUDE.md "Project-specific conventions" so agents read it before writing code.
Lint config can express "no calls to X". It cannot express "no calls to X
except in these packages, with this allowlist of existing call sites"
without a custom analyzer. forbidigo comes close but is global. archtest
is project-scoped and grows with conventions specific to this codebase.