---
sync_policy: engine_only
---
package {{basePackage}};

import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.lang.ArchRule;

import static com.tngtech.archunit.library.dependencies.SlicesRuleDefinition.slices;
import static com.tngtech.archunit.library.Architectures.layeredArchitecture;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;

/**
 * 架构约束测试 — SoloForge 脚手架生成。
 *
 * 依赖 ArchUnit（需在 pom.xml/build.gradle 加: com.tngtech.archunit:archunit-junit5）。
 * 运行: mvn test 或 gradle test。
 * 任何架构违规都会让构建失败——即架构适应度函数（Architecture Fitness Function）。
 * 与 SoloForge gate 的 external_command 执行器配合：测试失败 → gate hard_fail。
 */
@AnalyzeClasses(packages = "{{basePackage}}")
public class ArchitectureRulesTest {

    /** 分层依赖: controller → service → persistence/entity，禁止反向访问 */
    @ArchTest
    static final ArchRule 分层依赖方向 = layeredArchitecture()
        .consideringAllDependencies()
        .layer("Controller").definedBy("..controller..")
        .layer("Service").definedBy("..service..")
        .layer("Persistence").definedBy("..mapper..")
        .layer("Entity").definedBy("..entity..")
        .whereLayer("Controller").mayNotBeAccessedByAnyLayer()
        .whereLayer("Service").mayOnlyBeAccessedByLayers("Controller")
        .whereLayer("Persistence").mayOnlyBeAccessedByLayers("Service")
        .whereLayer("Entity").mayOnlyBeAccessedByLayers("Service", "Persistence");

    /** 禁止包间循环依赖 */
    @ArchTest
    static final ArchRule 禁止循环依赖 = slices()
        .matching("{{basePackage}}.(*)..")
        .should().beFreeOfCycles();

    /** Controller 禁止直接依赖 Servlet API（应通过 Spring 的抽象层） */
    @ArchTest
    static final ArchRule Controller禁止依赖Servlet = noClasses()
        .that().resideInAPackage("..controller..")
        .should().dependOnClassesThat().resideInAnyPackage("javax.servlet..", "jakarta.servlet..");
}
