package main import ( "os" "path/filepath" "strings" "testing" ) func TestArchitectureSentinelNegativeCases(t *testing.T) { tests := []struct { name string importPath string want string }{ {"domain infrastructure import", "git.cin.su/m/Assistant/adapters/postgres", "domain imports forbidden /adapters/"}, {"cross-module implementation import", "git.cin.su/m/Assistant/modules/beta/domain", "cross-module implementation import beta"}, {"undeclared contract dependency", "git.cin.su/m/Assistant/contracts/beta", "undeclared contract dependency contracts.beta"}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { root := architectureFixture(t, test.importPath) err := checkArchitectureAt(root) if err == nil || !strings.Contains(err.Error(), test.want) { t.Fatalf("sentinel error = %v", err) } }) } } func TestArchitectureSentinelAcceptsDeclaredContractDependency(t *testing.T) { root := architectureFixture(t, "git.cin.su/m/Assistant/contracts/beta") registry := `{"registry_version":1,"semantic_generation":1,"architecture_generation":1,"modules":{"alpha":{"id":"mod.alpha","owns":[],"database_schema":"alpha","boundary_class":"remote_capable","may_depend_on":["contracts.beta"]},"beta":{"id":"mod.beta","owns":[],"database_schema":"beta","boundary_class":"remote_capable","may_depend_on":[]}}}` writeFixture(t, filepath.Join(root, "architecture", "architecture-registry.json"), registry) if err := checkArchitectureAt(root); err != nil { t.Fatalf("declared dependency rejected: %v", err) } } func TestPreflightRejectsProtectedPathBelowTierE(t *testing.T) { registry := Registry{ProtectedPaths: []string{"architecture/**", "security/**"}} taskPacket := TaskPacket{TaskID: "DEV-bad", RiskTier: "C", Intent: "weaken guardrail"} taskPacket.AllowedChangeScope.Paths = []string{"architecture/architecture-registry.json"} if err := validateTaskScope(taskPacket, registry); err == nil || !strings.Contains(err.Error(), "protected path") { t.Fatalf("protected path task error = %v", err) } taskPacket.RiskTier = "E" if err := validateTaskScope(taskPacket, registry); err != nil { t.Fatalf("Tier E protected path rejected: %v", err) } } func architectureFixture(t *testing.T, importPath string) string { t.Helper() root := t.TempDir() registry := `{"registry_version":1,"semantic_generation":1,"architecture_generation":1,"modules":{"alpha":{"id":"mod.alpha","owns":[],"database_schema":"alpha","boundary_class":"remote_capable","may_depend_on":[]},"beta":{"id":"mod.beta","owns":[],"database_schema":"beta","boundary_class":"remote_capable","may_depend_on":[]}}}` writeFixture(t, filepath.Join(root, "architecture", "architecture-registry.json"), registry) writeFixture(t, filepath.Join(root, "modules", "alpha", "domain", "fixture.go"), "package domain\nimport _ \""+importPath+"\"\n") return root } func writeFixture(t *testing.T, path, content string) { t.Helper() if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil { t.Fatal(err) } if err := os.WriteFile(path, []byte(content), 0o644); err != nil { t.Fatal(err) } }