Files
Agent-System-Dev/scripts/lint-boundaries.sh
T
weichenandCursor 937152a563 Add an architecture edge ratchet and waiting-state tokens
Why: New cross-layer imports and unused exports could land unnoticed, and confirm-waiting reused the success color.
Evidence: bash scripts/lint-boundaries.sh passed, including a probe that a new edge fails. Both design-guard tests passed. Knip counts stay at the baselines.
Impact: make test-boundaries now checks architecture edges. Frontend and ui test targets also run the knip ratchet.
Refs: feature/architecture-baseline
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-03 16:02:57 +00:00

101 lines
3.4 KiB
Bash
Executable File

#!/usr/bin/env bash
# 依赖边界:公开扩展 SDK 与示例不得导入后端 internal。
# pkg/extension/link 是唯一例外:下游空白导入它才能把 extension.Main 接到产品组合根。
set -euo pipefail
root=$(cd "$(dirname "$0")/.." && pwd)
fail=0
check() {
local path="$1"
if [ -d "$path" ] && grep -R -n --include='*.go' --include='*.ts' --include='*.tsx' 'agent-system-backend/internal' "$path" >/dev/null; then
echo "boundary: $path imports agent-system-backend/internal" >&2
grep -R -n --include='*.go' --include='*.ts' --include='*.tsx' 'agent-system-backend/internal' "$path" >&2
fail=1
fi
}
sdk="$root/modules/backend/pkg/extension"
if [ -d "$sdk" ]; then
hits=$(grep -R -n --include='*.go' 'agent-system-backend/internal' "$sdk" | grep -v '/link/' || true)
if [ -n "$hits" ]; then
echo "boundary: pkg/extension imports agent-system-backend/internal" >&2
echo "$hits" >&2
fail=1
fi
fi
check "$root/examples"
# 库间依赖棘轮:三个库的包导入兄弟库的配对,相对白名单只许减少、不许新增。
allow="$root/policy/lib-deps-allowlist.txt"
observed=$(mktemp)
recorded=$(mktemp)
trap 'rm -f "$observed" "$recorded"' EXIT
siblings=(agent-intent agent-native agent-squad)
for dir in deps/agent-intent deps/agent-native deps/agent-squad; do
mod=$(awk '/^module /{print $2; exit}' "$root/$dir/go.mod")
(
cd "$root/scripts"
go run lint-imports.go "$root/$dir"
) | while read -r importer rest; do
for imp in $rest; do
for sib in "${siblings[@]}"; do
case "$imp" in
"$sib"|"$sib"/*) ;;
*) continue ;;
esac
case "$importer" in
"$mod"|"$mod"/*) ;;
*) continue ;;
esac
if [ "$sib" != "$mod" ]; then
echo "$importer $imp"
fi
done
done
done
done | sort -u >"$observed"
grep -v -e '^#' -e '^$' "$allow" | sort -u >"$recorded" || true
new_pairs=$(comm -13 "$recorded" "$observed" || true)
if [ -n "$new_pairs" ]; then
echo "boundary: new sibling-library import pairs" >&2
echo "$new_pairs" >&2
fail=1
fi
stale_pairs=$(comm -23 "$recorded" "$observed" || true)
if [ -n "$stale_pairs" ]; then
echo "warn: sibling-library pairs no longer imported; delete from policy/lib-deps-allowlist.txt" >&2
echo "$stale_pairs" >&2
fi
# 核心模块的依赖图不得出现兄弟库。go list ./... 不进入带 go.mod 的子目录。
for dir in deps/agent-intent deps/agent-native deps/agent-squad; do
mod=$(awk '/^module /{print $2; exit}' "$root/$dir/go.mod")
deps_out=$(cd "$root/$dir" && GOWORK=off go list -deps ./...) || fail=1
for sib in "${siblings[@]}"; do
[ "$sib" = "$mod" ] && continue
if printf '%s\n' "$deps_out" | grep -E -q "^(${sib}|${sib}/)"; then
echo "boundary: $mod core depends on $sib" >&2
fail=1
fi
done
done
# agent-intent 只许被小队意图适配器和后端识别适配器导入。
while IFS= read -r f; do
grep -q '"agent-intent/' "$f" || continue
case "$f" in
*/deps/agent-squad/adapters/intent/*|*/modules/backend/internal/intentgate/*) ;;
*)
echo "boundary: $f imports agent-intent" >&2
fail=1
;;
esac
done < <(find "$root/deps/agent-native" "$root/deps/agent-squad" "$root/modules/backend" \
-path '*/deps/*' -prune -o -name '*.go' -print)
if [ "$fail" -ne 0 ]; then
exit 1
fi
bash "$root/scripts/lint-architecture.sh"
echo "boundaries ok"