返回 DeepSeek-Reasonix
layers.go
根目录 / tools / repolint / layers.go
1 package main
2
3 import (
4 "fmt"
5 "path"
6 "strings"
7 )
8
9 const modulePrefix = "reasonix/"
10
11 // Transport-agnostic control.Controller sits behind every frontend; nothing
12 // below it may reach up. See REASONIX.md.
13 var frontends = []string{
14 "internal/acp",
15 "internal/boot",
16 "internal/bot",
17 "internal/botruntime",
18 "internal/cli",
19 "internal/serve",
20 }
21
22 // Utility layer: these packages carry no knowledge of the kernel and must
23 // stay importable from anywhere without dragging a dependency graph along.
24 var leaves = []string{
25 "internal/ablation",
26 "internal/agentpreset",
27 "internal/billing",
28 "internal/diff",
29 "internal/extension/rpcwire",
30 "internal/extensioncontract",
31 "internal/filelock",
32 "internal/fileref",
33 "internal/fileutil",
34 "internal/fileutil/encoding",
35 "internal/frontmatter",
36 "internal/i18n",
37 "internal/mcpdiag",
38 "internal/nilutil",
39 "internal/planmode",
40 "internal/proc",
41 "internal/releaseasset",
42 "internal/retrieval",
43 "internal/shellparse",
44 "internal/store",
45 "internal/sysproxy",
46
47 "internal/textutil",
48 }
49
50 func checkLayering(imports map[string][]importRef) []Finding {
51 var out []Finding
52 for _, rel := range sortedKeys(imports) {
53 pkg := path.Dir(rel)
54 for _, ref := range imports[rel] {
55 dep, ok := strings.CutPrefix(ref.path, modulePrefix)
56 if !ok {
57 continue
58 }
59 if msg := violates(pkg, dep); msg != "" {
60 out = append(out, Finding{rel, ref.line, ruleLayering, msg, 1})
61 }
62 }
63 }
64 return out
65 }
66
67 func violates(pkg, dep string) string {
68 switch {
69 case matches(leaves, pkg):
70 return fmt.Sprintf("%s is a utility-layer package and must not import %s", pkg, dep)
71 case under(dep, "internal/control") && !matches(frontends, pkg) && !under(pkg, "internal/control") && !host(pkg):
72 return fmt.Sprintf("%s may not import %s: the controller is reachable from frontends and entrypoints only", pkg, dep)
73 case matches(frontends, dep) && !matches(frontends, pkg) && !host(pkg):
74 return fmt.Sprintf("%s may not import the %s frontend: move shared behavior below the controller", pkg, dep)
75 }
76 return ""
77 }
78
79 func host(pkg string) bool { return under(pkg, "cmd") || under(pkg, "desktop") }
80
81 func under(pkg, root string) bool { return pkg == root || strings.HasPrefix(pkg, root+"/") }
82
83 func matches(roots []string, pkg string) bool {
84 for _, root := range roots {
85 if under(pkg, root) {
86 return true
87 }
88 }
89 return false
90 }
91
91 lines GO