diff --git a/HARNESS.md b/HARNESS.md index a0d5cfc..26cd0e2 100644 --- a/HARNESS.md +++ b/HARNESS.md @@ -124,8 +124,9 @@ is a codebase still navigable by `go doc` and `git log` alone, years from now, w instead of `log/slog`, `panic()` outside `cmd/`, and `time.Now()` outside a `clock.go` are stated absolutely in `conventions.md`, so they exit non-zero. That last one exists because a Stage that reads the clock without an expiry would serve staleness invisibly. A rule enforced as a suggestion teaches the agent to read every rule as one. -Softer signals — `fmt.Errorf` without `%w`, `interface{}`, nesting past 4, exported-and-referenced- -once — stay advisory. +Softer signals stay advisory: `fmt.Errorf` without `%w`, nesting past 4, exported-and-referenced-once, +and `any` in an **exported** signature — only exported, because ADR-0002 mandates an open page object, +so unexported code reading frontmatter takes `any` legitimately and forever. **STATUS markers in `docs/architecture.md`** give the target shape *and* what is legal today, so the agent can read the endgame without building toward it. diff --git a/scripts/verify.sh b/scripts/verify.sh index 0f4ce65..6351836 100755 --- a/scripts/verify.sh +++ b/scripts/verify.sh @@ -379,9 +379,11 @@ if [ -n "$panics" ]; then bad "panic() outside cmd/ — request-time failure deg head_ "smells (advisory)" nowrap=$(echo "$gofiles" | xargs grep -n 'fmt\.Errorf(' 2>/dev/null | grep -v '%w' | wc -l | tr -d ' ') [ "${nowrap:-0}" -gt 0 ] && note "$nowrap fmt.Errorf without %w (wrap at package boundaries)" -# -H forces the filename even for a single file; comment lines are prose, where "any" is a word -anyuse=$(echo "$gofiles" | grep -v '_test\.go$' | xargs grep -Hn 'interface{}\|\bany\b' 2>/dev/null | - grep -vE ':[[:space:]]*//' | grep -v 'map\[string\]any' | cut -d: -f1 | sort -u || true) +# Only exported signatures: conventions.md bans interface{} as an API escape hatch, but ADR-0002 mandates +# an open page object, so unexported code reading Extra legitimately takes any and always will. +anyuse=$(echo "$gofiles" | grep -v '_test\.go$' | + xargs grep -HnE '^func (\([^)]*\) )?[A-Z][A-Za-z0-9_]*\(.*(\bany\b|interface\{\})' 2>/dev/null | + cut -d: -f1 | sort -u || true) [ -n "$anyuse" ] && note "interface{} or any present (no empty interface for flexibility): $(echo "$anyuse" | tr '\n' ' ')" deep=$(echo "$gofiles" | xargs awk '/^\t\t\t\t\t[^\t}]/ {print FILENAME; nextfile}' 2>/dev/null | sort -u || true) [ -n "$deep" ] && note "nesting past 4 (conventions.md): $(echo "$deep" | tr '\n' ' ')"