Skip to content

Structure

structure

Structure rules — file and directory existence checks.

DirectoryExistsRule dataclass

Bases: ProjectRule

Rule that checks if a required directory exists.

Not decorated with @register_rule — this rule is consumed by axm-init checklist checks, not auto-discovered during audits. The category property is set manually for the same reason.

Source code in packages/axm-audit/src/axm_audit/core/rules/structure.py
@dataclass
class DirectoryExistsRule(ProjectRule):
    """Rule that checks if a required directory exists.

    Not decorated with ``@register_rule`` — this rule is consumed by
    ``axm-init`` checklist checks, not auto-discovered during audits.
    The ``category`` property is set manually for the same reason.
    """

    dir_name: str

    @property
    def rule_id(self) -> str:
        """Unique identifier for this rule."""
        return f"DIR_EXISTS_{self.dir_name}"

    @property
    def category(self) -> str:
        """Scoring category for this rule."""
        return "structure"

    def check(self, project_path: Path) -> CheckResult:
        """Check if the directory exists in the project."""
        target = project_path / self.dir_name
        if target.exists() and target.is_dir():
            return CheckResult(
                rule_id=self.rule_id,
                passed=True,
                message=f"{self.dir_name}/ exists",
            )
        return CheckResult(
            rule_id=self.rule_id,
            passed=False,
            message=f"{self.dir_name}/ not found",
        )
category property

Scoring category for this rule.

rule_id property

Unique identifier for this rule.

check(project_path)

Check if the directory exists in the project.

Source code in packages/axm-audit/src/axm_audit/core/rules/structure.py
def check(self, project_path: Path) -> CheckResult:
    """Check if the directory exists in the project."""
    target = project_path / self.dir_name
    if target.exists() and target.is_dir():
        return CheckResult(
            rule_id=self.rule_id,
            passed=True,
            message=f"{self.dir_name}/ exists",
        )
    return CheckResult(
        rule_id=self.rule_id,
        passed=False,
        message=f"{self.dir_name}/ not found",
    )

FileExistsRule dataclass

Bases: ProjectRule

Rule that checks if a required file exists.

Not decorated with @register_rule — this rule is consumed by axm-init checklist checks, not auto-discovered during audits. The category property is set manually for the same reason.

Source code in packages/axm-audit/src/axm_audit/core/rules/structure.py
@dataclass
class FileExistsRule(ProjectRule):
    """Rule that checks if a required file exists.

    Not decorated with ``@register_rule`` — this rule is consumed by
    ``axm-init`` checklist checks, not auto-discovered during audits.
    The ``category`` property is set manually for the same reason.
    """

    file_name: str

    @property
    def rule_id(self) -> str:
        """Unique identifier for this rule."""
        return f"FILE_EXISTS_{self.file_name}"

    @property
    def category(self) -> str:
        """Scoring category for this rule."""
        return "structure"

    def check(self, project_path: Path) -> CheckResult:
        """Check if the file exists in the project."""
        target = project_path / self.file_name
        if target.exists() and target.is_file():
            return CheckResult(
                rule_id=self.rule_id,
                passed=True,
                message=f"{self.file_name} exists",
            )
        return CheckResult(
            rule_id=self.rule_id,
            passed=False,
            message=f"{self.file_name} not found",
        )
category property

Scoring category for this rule.

rule_id property

Unique identifier for this rule.

check(project_path)

Check if the file exists in the project.

Source code in packages/axm-audit/src/axm_audit/core/rules/structure.py
def check(self, project_path: Path) -> CheckResult:
    """Check if the file exists in the project."""
    target = project_path / self.file_name
    if target.exists() and target.is_file():
        return CheckResult(
            rule_id=self.rule_id,
            passed=True,
            message=f"{self.file_name} exists",
        )
    return CheckResult(
        rule_id=self.rule_id,
        passed=False,
        message=f"{self.file_name} not found",
    )

PyprojectCompletenessRule dataclass

Bases: ProjectRule

Validate PEP 621 field completeness in pyproject.toml.

Checks 9 fields: name, version/dynamic, description, requires-python, license, authors, classifiers, urls, readme. Scoring: (fields_present / 9) x 100.

Source code in packages/axm-audit/src/axm_audit/core/rules/structure.py
@dataclass
@register_rule("structure")
class PyprojectCompletenessRule(ProjectRule):
    """Validate PEP 621 field completeness in pyproject.toml.

    Checks 9 fields: name, version/dynamic, description, requires-python,
    license, authors, classifiers, urls, readme.
    Scoring: (fields_present / 9) x 100.
    """

    @property
    def rule_id(self) -> str:
        """Unique identifier for this rule."""
        return "STRUCTURE_PYPROJECT"

    def check(self, project_path: Path) -> CheckResult:
        """Check pyproject.toml completeness."""
        pyproject_path = project_path / "pyproject.toml"
        if not pyproject_path.exists():
            return CheckResult(
                rule_id=self.rule_id,
                passed=False,
                message="pyproject.toml not found",
                severity=Severity.ERROR,
                details={"fields_present": 0, "total_fields": 9, "score": 0},
                fix_hint="Create pyproject.toml with PEP 621 metadata",
            )

        try:
            data = tomllib.loads(pyproject_path.read_text())
        except (tomllib.TOMLDecodeError, OSError):
            return CheckResult(
                rule_id=self.rule_id,
                passed=False,
                message="pyproject.toml parse error",
                severity=Severity.ERROR,
                details={"fields_present": 0, "total_fields": 9, "score": 0},
                fix_hint="Fix pyproject.toml syntax",
            )

        present = _count_fields(data.get("project", {}))
        score = int((present / _TOTAL_FIELDS) * 100)

        return CheckResult(
            rule_id=self.rule_id,
            passed=score >= PASS_THRESHOLD,
            message=f"pyproject.toml completeness: {present}/{_TOTAL_FIELDS} fields",
            severity=Severity.WARNING if score < PASS_THRESHOLD else Severity.INFO,
            details={
                "fields_present": present,
                "total_fields": _TOTAL_FIELDS,
                "score": score,
            },
            fix_hint=(
                "Add missing PEP 621 fields to [project]"
                if score < PASS_THRESHOLD
                else None
            ),
        )
rule_id property

Unique identifier for this rule.

check(project_path)

Check pyproject.toml completeness.

Source code in packages/axm-audit/src/axm_audit/core/rules/structure.py
def check(self, project_path: Path) -> CheckResult:
    """Check pyproject.toml completeness."""
    pyproject_path = project_path / "pyproject.toml"
    if not pyproject_path.exists():
        return CheckResult(
            rule_id=self.rule_id,
            passed=False,
            message="pyproject.toml not found",
            severity=Severity.ERROR,
            details={"fields_present": 0, "total_fields": 9, "score": 0},
            fix_hint="Create pyproject.toml with PEP 621 metadata",
        )

    try:
        data = tomllib.loads(pyproject_path.read_text())
    except (tomllib.TOMLDecodeError, OSError):
        return CheckResult(
            rule_id=self.rule_id,
            passed=False,
            message="pyproject.toml parse error",
            severity=Severity.ERROR,
            details={"fields_present": 0, "total_fields": 9, "score": 0},
            fix_hint="Fix pyproject.toml syntax",
        )

    present = _count_fields(data.get("project", {}))
    score = int((present / _TOTAL_FIELDS) * 100)

    return CheckResult(
        rule_id=self.rule_id,
        passed=score >= PASS_THRESHOLD,
        message=f"pyproject.toml completeness: {present}/{_TOTAL_FIELDS} fields",
        severity=Severity.WARNING if score < PASS_THRESHOLD else Severity.INFO,
        details={
            "fields_present": present,
            "total_fields": _TOTAL_FIELDS,
            "score": score,
        },
        fix_hint=(
            "Add missing PEP 621 fields to [project]"
            if score < PASS_THRESHOLD
            else None
        ),
    )