ln-646-project-structure-auditor

Paths: File paths (shared/ , references/ , ../ln-* ) are relative to skills repo root. If not found at CWD, locate this SKILL.md directory and go up one level for repo root. If shared/ is missing, fetch files via WebFetch from https://raw.githubusercontent.com/levnikolaevich/claude-code-skills/master/skills/{path} .

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "ln-646-project-structure-auditor" with this command: npx skills add levnikolaevich/claude-code-skills/levnikolaevich-claude-code-skills-ln-646-project-structure-auditor

Paths: File paths (shared/ , references/ , ../ln-* ) are relative to skills repo root. If not found at CWD, locate this SKILL.md directory and go up one level for repo root. If shared/ is missing, fetch files via WebFetch from https://raw.githubusercontent.com/levnikolaevich/claude-code-skills/master/skills/{path} .

Project Structure Auditor

Type: L3 Worker

L3 Worker that audits the physical directory structure of a project against framework-specific conventions and hygiene best practices.

Purpose & Scope

  • Auto-detect tech stack and apply framework-specific structure rules

  • Audit 5 dimensions: file hygiene, ignore files, framework conventions, domain/layer organization, naming

  • Detect project rot: leftover artifacts, inconsistent naming, junk drawer directories

  • Complement code-level layer analysis with physical structure analysis

  • Score and report findings per standard audit_scoring.md formula

  • Output: file-based report to {output_dir}/646-structure[-{domain}].md

Out of Scope:

  • Code-level layer boundary violations (import analysis)

  • Platform artifact cleanup (removal of files)

  • Structure migration (creation/movement of directories)

  • Dependency vulnerability scanning

Input

  • codebase_root: string # Root directory to scan
  • output_dir: string # e.g., ".hex-skills/runtime-artifacts/runs/{run_id}/audit-report"

Domain-aware (optional, from coordinator)

  • domain_mode: "global" | "domain-aware" # Default: "global"
  • current_domain: string # e.g., "users", "billing" (only if domain-aware)
  • scan_path: string # e.g., "src/users/" (only if domain-aware)

Workflow

MANDATORY READ: Load shared/references/two_layer_detection.md for detection methodology. MANDATORY READ: Load shared/references/mcp_tool_preferences.md and shared/references/mcp_integration_patterns.md

Use hex-graph first when architecture summaries materially improve structure findings. Use hex-line first for local code, config, and manifest reads when available. If MCP is unavailable, unsupported, or not indexed, continue with built-in Read/Grep/Glob/Bash and state the fallback in the report.

Phase 1: Detect Tech Stack

MANDATORY READ: Load ../ln-700-project-bootstrap/references/stack_detection.md -- use Detection Algorithm, Frontend Detection, Backend Detection, Structure Detection.

scan_root = scan_path IF domain_mode == "domain-aware" ELSE codebase_root

Priority 1: Read docs/project/tech_stack.md if exists

IF exists(docs/project/tech_stack.md): tech_stack = parse(tech_stack.md)

Priority 2: Auto-detect from project files

ELSE: Check package.json -> React/Vue/Angular/Express/NestJS Check .csproj/.sln -> .NET Check pyproject.toml/requirements.txt -> Python/FastAPI/Django Check go.mod -> Go Check Cargo.toml -> Rust Check pnpm-workspace.yaml/turbo.json -> Monorepo

tech_stack = { language: "typescript" | "python" | "csharp" | "go" | ..., framework: "react" | "fastapi" | "aspnetcore" | ..., structure: "monolith" | "clean-architecture" | "monorepo" | ... }

Phase 2: File Hygiene Audit

MANDATORY READ: Load references/structure_rules.md -- use "File Hygiene Rules" section. Also reference: ../ln-724-artifact-cleaner/references/platform_artifacts.md (Platform Detection Matrix, Generic Prototype Artifacts).

Check 2.1: Build artifacts tracked in git

FOR EACH artifact_dir IN structure_rules.build_artifact_dirs: IF Glob("{scan_root}/**/{artifact_dir}"): findings.append(severity: "HIGH", issue: "Build artifact directory in repo", location: path, recommendation: "Add to .gitignore, remove from tracking")

Check 2.2: Temp/log files

FOR EACH pattern IN structure_rules.temp_junk_patterns: IF Glob("{scan_root}/**/{pattern}"): findings.append(severity: "MEDIUM", ...)

Check 2.3: Platform remnants (from platform_artifacts.md)

FOR EACH platform IN [Replit, StackBlitz, CodeSandbox, Glitch]: IF platform indicator files found: findings.append(severity: "MEDIUM", issue: "Platform remnant: {file}", principle: "File Hygiene / Platform Artifacts")

Check 2.4: Multiple lock files

lock_files = Glob("{scan_root}/{package-lock.json,yarn.lock,pnpm-lock.yaml,bun.lockb}") IF len(lock_files) > 1: findings.append(severity: "HIGH", issue: "Multiple lock files: {lock_files}", recommendation: "Keep one lock file matching your package manager")

Check 2.6: Large binaries tracked by git

FOR EACH file IN Glob("{scan_root}/**/*.{zip,tar,gz,rar,exe,dll,so,dylib,jar,war}"): findings.append(severity: "MEDIUM", issue: "Binary file tracked: {file}", recommendation: "Use Git LFS or remove from repository")

Phase 3: Ignore File Quality

MANDATORY READ: Load references/structure_rules.md -- use "Ignore File Rules" section. Also reference: ../ln-733-env-configurator/references/gitignore_secrets.template (secrets baseline), ../ln-731-docker-generator/references/dockerignore.template (dockerignore baseline).

Check 3.1: .gitignore exists

IF NOT exists(.gitignore): findings.append(severity: "HIGH", issue: "No .gitignore file") ELSE: content = Read(.gitignore)

Check 3.1a: Stack-specific entries present

required_entries = get_required_gitignore(tech_stack) FOR EACH entry IN required_entries: IF entry NOT covered in .gitignore: findings.append(severity: "MEDIUM", issue: ".gitignore missing: {entry}")

Check 3.1b: Secrets protection (compare with gitignore_secrets.template)

secrets_patterns = [".env", ".env.local", ".pem", ".key", "secrets/"] FOR EACH pattern IN secrets_patterns: IF pattern NOT in .gitignore: findings.append(severity: "HIGH", issue: ".gitignore missing secrets: {pattern}", principle: "Ignore Files / Secrets")

Check 3.1c: IDE/OS entries

ide_patterns = [".vscode/", ".idea/", "*.swp", ".DS_Store", "Thumbs.db"] missing_ide = [p for p in ide_patterns if p NOT covered in .gitignore] IF len(missing_ide) > 2: findings.append(severity: "LOW", issue: ".gitignore missing IDE/OS: {missing_ide}")

Check 3.2: .dockerignore

IF exists(Dockerfile) AND NOT exists(.dockerignore): findings.append(severity: "MEDIUM", issue: "Dockerfile exists but no .dockerignore", recommendation: "Create .dockerignore to reduce build context") ELIF exists(.dockerignore): FOR EACH required IN [node_modules, .git, .env, "*.log"]: IF required NOT in .dockerignore: findings.append(severity: "LOW", ...)

Phase 4: Framework Convention Compliance

MANDATORY READ: Load references/structure_rules.md -- use framework-specific section matching detected tech_stack.

rules = get_framework_rules(tech_stack, structure_rules.md)

Returns: {expected_dirs, forbidden_placements, co_location_rules}

Check 4.1: Expected directories exist

FOR EACH dir IN rules.expected_dirs WHERE dir.required == true: IF NOT exists(dir.path): findings.append(severity: "MEDIUM", issue: "Expected directory missing: {dir.path}", principle: "Framework Convention / {tech_stack.framework}")

Check 4.2: Source code in wrong locations

FOR EACH rule IN rules.forbidden_placements: matches = Glob(rule.glob_pattern, scan_root) FOR EACH match IN matches: IF match NOT IN rules.exceptions: findings.append(severity: "HIGH", issue: "Source file in wrong location: {match}", recommendation: "Move to {rule.expected_location}")

Check 4.3: Co-location rules (React feature folders)

IF tech_stack.framework IN ["react", "vue", "angular", "svelte"]: component_dirs = Glob("{scan_root}/**/components//") colocation_count = 0 FOR EACH dir IN component_dirs: has_test = Glob("{dir}/.{test,spec}.{ts,tsx,js,jsx}") IF has_test: colocation_count += 1

Only flag if project already uses co-location (>50%)

IF colocation_count > len(component_dirs) * 0.5: FOR EACH dir IN component_dirs: IF NOT has_test_for(dir): findings.append(severity: "LOW", issue: "Component missing co-located test: {dir}")

Phase 5: Domain/Layer Organization

Check 5.1: Junk drawer detection

junk_thresholds = structure_rules.junk_drawer_thresholds FOR EACH dir IN Glob("{scan_root}/**/"): dir_name = basename(dir) IF dir_name IN junk_thresholds: file_count = len(Glob("{dir}/.")) IF file_count > junk_thresholds[dir_name].max_files: findings.append(severity: junk_thresholds[dir_name].severity, issue: "Junk drawer directory: {dir} ({file_count} files)", principle: "Organization / Module Cohesion", recommendation: "Split into domain-specific modules or feature folders")

Check 5.2: Root directory cleanliness

root_files = Glob("{scan_root}/*") # Direct children only source_in_root = [f for f in root_files if f.ext IN source_extensions AND basename(f) NOT IN allowed_root_files] IF len(source_in_root) > 0: findings.append(severity: "MEDIUM", issue: "Source files in project root: {source_in_root}", recommendation: "Move to src/ or appropriate module directory")

config_in_root = [f for f in root_files if is_config_file(f)] IF len(config_in_root) > 15: findings.append(severity: "LOW", issue: "Excessive config files in root ({len(config_in_root)})", recommendation: "Move non-essential configs to config/ directory")

Check 5.3: Consistent module structure across domains

IF domain_mode == "global" AND len(detect_domains(scan_root)) >= 2: domains = detect_domains(scan_root) structures = {d.name: set(subdirectory_names(d.path)) for d in domains} all_subdirs = union(structures.values()) FOR EACH domain IN domains: missing = all_subdirs - structures[domain] IF 0 < len(missing) < len(all_subdirs) * 0.5: findings.append(severity: "LOW", issue: "Inconsistent domain structure: {domain.name} missing {missing}", recommendation: "Align domain module structures for consistency")

Phase 6: Naming Conventions

MANDATORY READ: Load references/structure_rules.md -- use "Naming Convention Rules" section.

naming_rules = get_naming_rules(tech_stack)

Returns: {file_case, dir_case, test_pattern, component_case}

Check 6.1: File naming consistency

violations = [] FOR EACH file IN Glob("{scan_root}/**/*.{ts,tsx,js,jsx,py,cs,go}"): expected_case = naming_rules.file_case IF is_component(file) AND NOT matches_case(basename(file), expected_case): violations.append(file)

IF len(violations) > 0: pct = len(violations) / total_source_files * 100 severity = "HIGH" if pct > 30 else "MEDIUM" if pct > 10 else "LOW" findings.append(severity, issue: "Naming violations: {len(violations)} files ({pct}%)", principle: "Naming / {naming_rules.file_case}")

Check 6.2: Directory naming consistency

dirs = get_all_source_dirs(scan_root) dir_cases = classify_cases(dirs) # Count per case style dominant = max(dir_cases) inconsistent = [d for d in dirs if case_of(d) != dominant] IF len(inconsistent) > 0: findings.append(severity: "LOW", issue: "Inconsistent directory naming: {len(inconsistent)} dirs use mixed case")

Check 6.3: Test file naming pattern

test_files = Glob("{scan_root}/**/*.{test,spec}.{ts,tsx,js,jsx}")

  • Glob("{scan_root}/**/*_test.{py,go}") IF len(test_files) > 0: patterns_used = detect_test_patterns(test_files) # .test. vs .spec. vs _test IF len(patterns_used) > 1: findings.append(severity: "LOW", issue: "Mixed test naming patterns: {patterns_used}", recommendation: "Standardize to {dominant_test_pattern}")

Phase 7: Score + Report + Return

MANDATORY READ: Load shared/references/audit_worker_core_contract.md , shared/references/audit_scoring.md , and shared/templates/audit_worker_report_template.md .

When summaryArtifactPath is present, write the JSON summary to that exact path. When summaryArtifactPath is absent, write the standalone runtime summary under .hex-skills/runtime-artifacts/runs/{run_id}/evaluation-worker/{worker}--{identifier}.json and optionally echo the same summary in structured output.

7a: Calculate score via shared formula

7b: Build report in memory using the shared audit worker template

7c: Populate DATA-EXTENDED with:

tech_stack

dimensions.file_hygiene / ignore_files / framework_conventions / domain_organization / naming_conventions

junk_drawers

naming_dominant_case

naming_violations_pct

7d: Write report (atomic single Write call)

Write to {output_dir}/ln-646--{identifier}.md

7e: Return summary

Report written: .hex-skills/runtime-artifacts/runs/{run_id}/audit-report/ln-646--{identifier}.md Score: X.X/10 | Issues: N (C:N H:N M:N L:N)

Scoring

MANDATORY READ: Load shared/references/audit_worker_core_contract.md and shared/references/audit_scoring.md .

Severity mapping:

  • HIGH: Build artifacts tracked, missing .gitignore, source in wrong location, multiple lock files, missing secrets in .gitignore. Exception: Build artifacts in Git LFS -> skip

  • MEDIUM: Missing framework dirs, junk drawers, temp files, platform remnants, missing stack-specific gitignore entries, naming violations >10%

  • LOW: IDE/OS patterns missing, inconsistent dir naming, mixed test patterns, minor config issues

Critical Rules

MANDATORY READ: Load shared/references/audit_worker_core_contract.md .

  • Auto-detect, never assume: Always detect tech stack before applying framework rules

  • No false positives on conventions: Apply framework rules ONLY for detected stack

  • Security-first: Missing secrets in .gitignore = HIGH

  • Complement, not overlap: Do NOT check import-level layer violations (separate worker scope)

  • Report only, never modify: Never move/delete files (separate migration/cleanup workers)

  • Reuse platform detection: Reference platform artifact patterns from references

  • Co-location awareness: Only flag missing co-location if project already uses the pattern (>50%)

  • Evidence always: Include file paths for every finding

Definition of Done

MANDATORY READ: Load shared/references/audit_worker_core_contract.md .

  • Tech stack detected (from docs/project/tech_stack.md or auto-detection)

  • File hygiene checked: build artifacts, temp files, platform remnants, lock files, binaries

  • Ignore files audited: .gitignore completeness, secrets protection, .dockerignore if Dockerfile present

  • Framework conventions applied: expected dirs, forbidden placements, co-location rules

  • Domain/layer organization checked: junk drawers, root cleanliness, cross-domain consistency

  • Naming conventions validated: file/dir/test naming patterns

  • If domain-aware: all Glob scoped to scan_path , findings tagged with domain

  • Score calculated per audit_scoring.md

  • Report written to {output_dir}/646-structure[-{domain}].md (atomic single Write call)

  • Summary written per contract

Reference Files

  • Structure rules: references/structure_rules.md

  • Stack detection: ../ln-700-project-bootstrap/references/stack_detection.md

  • Platform artifacts: ../ln-724-artifact-cleaner/references/platform_artifacts.md

  • Gitignore secrets: ../ln-733-env-configurator/references/gitignore_secrets.template

  • Dockerignore baseline: ../ln-731-docker-generator/references/dockerignore.template

Version: 1.0.0 Last Updated: 2026-02-28

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Security

ln-624-code-quality-auditor

No summary provided by upstream source.

Repository SourceNeeds Review
Security

ln-620-codebase-auditor

No summary provided by upstream source.

Repository SourceNeeds Review
Security

ln-626-dead-code-auditor

No summary provided by upstream source.

Repository SourceNeeds Review
Security

ln-621-security-auditor

No summary provided by upstream source.

Repository SourceNeeds Review