state invariant 7 as a rule the gate can hold
"Every feature is a leaf" was enforced by listing the pairs that happen to exist today: content, render and web may not import ext, plus a separate check for siblings. A list only forbids what is already there — a core package added next month could import a feature and pass, which is how an invariant rots while staying technically true. One positive rule now: only cmd/ may import internal/ext/…. It covers packages that do not exist yet and catches a sibling import in the same breath, since a feature importing another feature is the other way one stops being deletable. Four rules become one. Watched rejecting both kinds before keeping it — a core package importing a feature, and a feature importing its sibling — and watched passing the tree as it stands. Test files are excluded, which is right: the demo's own test wires features on purpose. Queue entry G5. It was the last architecture invariant held only by hand.
This commit is contained in:
+10
-6
@@ -333,14 +333,18 @@ layer() { # $1 = importing layer, $2..$n = layers it may not import
|
||||
done
|
||||
}
|
||||
violations=$(
|
||||
layer content render web ext
|
||||
layer render web ext
|
||||
layer web ext
|
||||
layer content render web
|
||||
layer render web
|
||||
echo "$pairs" | awk -v c="$mod/cmd" 'index($2,c)==1 && index($1,c)!=1 {print $1" → "$2}'
|
||||
)
|
||||
# Sibling imports between features are what make an agent's read set compound (ADR-0027).
|
||||
siblings=$(echo "$pairs" | awk -v e="$mod/internal/ext/" '
|
||||
index($1,e)==1 && index($2,e)==1 && $1!=$2 {print $1" → "$2}')
|
||||
# Invariant 7, as a rule rather than a list: a feature is a leaf, so `cmd/` is the *only* thing that may
|
||||
# import one. Stated positively, this also covers a core package that does not exist yet — the enumeration
|
||||
# above cannot, and the day someone adds `internal/foo` it would import `internal/ext` unnoticed. Sibling
|
||||
# imports between features fail here too: they are what make an agent's read set compound (ADR-0027), and
|
||||
# they are the other way a feature stops being deletable. Test files are excluded by `go list .Imports`,
|
||||
# which is right — the demo's own test exercises features on purpose (ADR-0069).
|
||||
siblings=$(echo "$pairs" | awk -v e="$mod/internal/ext/" -v c="$mod/cmd" '
|
||||
index($2,e)==1 && index($1,c)!=1 {print $1" → "$2}')
|
||||
if [ -n "$violations$siblings" ]; then
|
||||
bad "import boundary violated (conventions.md layering): $(echo "$violations$siblings" | tr '\n' ' ')"
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user