agentleFS
greglas75greglas75/zuvo/skills/structure-audit/SKILL.md

structure-audit

Skill7 starsChanged 27 days agoMITView on GitHub

Codebase structure and organization audit across 13 dimensions (SA1-SA13): directory consistency, naming conventions, folder depth, colocation, barrel exports, separation of concerns, file size distribution, dead code, complexity distribution, duplication, root organization, documentation, hotspots. Tool-driven with CodeSift primary and CLI fallbacks (cloc, knip, dep-cruiser, jscpd, eslint, git mining). Flags: full (default), [path], --naming, --size, --dead-code, --duplication, --hotspots, --quick, --fix.

  • Reads credentials

1 other project uses a version of this.

Adopted by

Most recently taken up by

The file

Show its rules and text

We split this skill into the rules it gives an agent

39 rules. About 0 are common, 22 are distinctive, and 17 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈22

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 17

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Read these files before any work begins:

    line 67
  2. Distinctive:

    If file 1, 2, 4, or 5 is missing, STOP.

    line 90
  3. Very specific:

    Read ../../shared/includes/env-compat.md for agent dispatch patterns, path resolution, and progress tracking across all supported platforms.

    line 94
  4. Very specific:

    Read ../../shared/includes/codesift-setup.md for the full initialization sequence.

    line 98
  5. Very specific:

    Summary: Run the CodeSift setup from codesift-setup.md at skill start.

    line 100
  6. Distinctive:

    Use the deterministic preload helper: Before issuing any ToolSearch, run:

    line 102
  7. Distinctive:

    After the audit report is written and the Validity Gate block is printed, the audit is NOT complete until:

    line 145
  8. Very specific:

    If you reach the Run line and stop without calling append-runlog: the audit is INVALID regardless of finding count.

    line 153
  9. Very specific:

    Run external tools. Save all outputs to zuvo/audits/structure-audit-{YYYY-MM-DD}/.

    line 263
  10. Very specific:

    Verify output: check for "SUM" key in JSON, not exit code.

    line 277
  11. Very specific:

    Verify output: check for "modules.*cruised" or violation text.

    line 304
  12. Very specific:

    Verify output: check statistics.total.sources > 0 in JSON.

    line 320
  13. Very specific:

    Project ESLint config (preferred): Check for existing config.

    line 333
  14. Distinctive:

    After all tools, print:

    line 341
  15. Distinctive:

    FALLBACK (no CodeSift): Run git mining scripts directly.

    line 359
  16. Very specific:

    Scope: All grep/glob commands target $CODE_SCOPE for SA1-SA10.

    line 386
  17. Very specific:

    Check framework conventions (Next.js: no pages/ alongside app/)

    line 393
  18. Very specific:

    Check type suffix consistency (.service.ts, .controller.ts)

    line 400
  19. Very specific:

    Check type files: centralized types/ vs co-located *.types.ts

    line 413
  20. Distinctive:

    Check constants/utils used by single module but stored centrally

    line 414
  21. Very specific:

    Check for barrel chains (index.ts re-exporting from another index.ts)

    line 422
  22. Distinctive:

    Check tsconfig paths vs actual usage

    line 424
  23. Distinctive:

    Run fitness function rules:

    line 430
  24. Distinctive:

    F4:: Test utility imports in production code

    line 434
  25. Distinctive:

    Use cloc per-file data. Exclude non-code files from size analysis.

    line 445
  26. Distinctive:

    Check for tracked temp files (.tmp-*, .env.local, *.log)

    line 457
  27. Distinctive:

    Check .gitignore completeness for detected stack

    line 458
  28. Distinctive:

    Check for scripts at root vs scripts/ directory

    line 459
  29. Distinctive:

    Check for README.md with setup instructions

    line 465
  30. Very specific:

    Check for docs/adr/ directory (if project >50 files)

    line 467
  31. Distinctive:

    Check for OpenAPI/Swagger spec (if API project)

    line 468
  32. Distinctive:

    Check for CONTRIBUTING.md (if >3 git contributors)

    line 469
  33. Distinctive:

    Import pollution: SA5 god barrel + SA8 unused exports

    line 545
  34. Very specific:

    Every HIGH and CRITICAL finding goes through backlog-add, one call per finding (../../shared/includes/backlog-protocol.md "Filing from a …

    line 563
  35. Very specific:

    Only if --fix argument was provided: After the report is saved, and before the 5.3 backlog calls:

    line 573
  36. Distinctive:

    Delete files with MEDIUM confidence

    line 585
  37. Distinctive:

    Before printing the final output block, verify every item.

    line 606
  38. Distinctive:

    Run: <ISO-8601-Z> structure-audit <project> <N-critical> <N-total> <VERDICT> - <N>-dimensions <NOTES> <BRANCH> <SHA7> <INCLUDES> <TIER>

    line 658
  39. Distinctive:

    If the wrapper exits non-zero: do NOT manually append to runs.log.

    line 676

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

zuvo:structure-audit — Codebase Structure & Organization Audit

Quantitative structural health assessment across 13 measurable dimensions. Every finding is backed by tool output or grep evidence -- no subjective opinions without data. Generates a scored report with prioritized action items.

Scope: Periodic health checks, pre-refactor reconnaissance, onboarding orientation, post-sprint cleanup, release readiness. Out of scope: Design patterns and SOLID (zuvo:architecture), per-file code quality (zuvo:code-audit), test quality (zuvo:test-audit), runtime performance (zuvo:performance-audit).

Mandatory File Loading

Read these files before any work begins:

Dispatch follows ../../shared/includes/execution-policy.md through env-compat. Reuse existing authorization within that policy; session restrictions take precedence. Run each required gate and report its actual independence or an unmet requirement.

  1. ../../shared/includes/codesift-setup.md -- CodeSift discovery and tool selection
  2. ../../shared/includes/env-compat.md -- Agent dispatch and environment adaptation
  3. ../../rules/file-limits.md -- Size limits for SA7 file categorization
  4. ../../shared/includes/run-logger.md -- Run logging contract
  5. ../../shared/includes/retrospective.md -- Retrospective protocol

Print the checklist:

CORE FILES LOADED:
  1. codesift-setup.md   -- [READ | MISSING -> STOP]
  2. env-compat.md       -- [READ | MISSING -> STOP]
  3. file-limits.md      -- [READ | MISSING -> use defaults: 300L service, 200L component]
  4. run-logger.md       -- [READ | MISSING -> STOP]
  5. retrospective.md    -- [READ | MISSING -> STOP]

If file 1, 2, 4, or 5 is missing, STOP. File 3 has a documented fallback.

Environment Compatibility

Read ../../shared/includes/env-compat.md for agent dispatch patterns, path resolution, and progress tracking across all supported platforms.

CodeSift Integration

Read ../../shared/includes/codesift-setup.md for the full initialization sequence.

Summary: Run the CodeSift setup from codesift-setup.md at skill start. CodeSift tools are the primary analysis engine for SA8 (dead code), SA9 (complexity), SA10 (duplication), and SA13 (hotspots). If unavailable, fall back to CLI tools and grep heuristics.

Use the deterministic preload helper. Before issuing any ToolSearch, run:

~/.zuvo/compute-preload structure-audit "$PWD"

Copy the printed [CodeSift matching trace] block verbatim and issue the printed ToolSearch(query="select:...") line without modification. Math gate: [CodeSift loaded] tools=N must equal [Expected after load] tools=N from the helper. If they differ → [PRELOAD MATH MISMATCH] and abort before Phase 1.


MANDATORY TOOL CALLS — Audit Validity Gate

This audit is INVALID if any tool below is skipped when its trigger condition holds. "DEFERRED", "N/A", "no diff vs prior audit" are NOT valid reasons. The presence of trigger artifacts (a code file list, language detection, dep manifest) is what dictates the call — never delta or risk.

Required tool list

ToolTriggerReasonSkip allowed?
detect_communitiesAlways (any project with code files)SA6 separation of concerns — module boundary discoveryNO
check_boundariesAlwaysSA8 boundary violations between detected communitiesNO
classify_rolesAlwaysHub/leaf/bridge symbol classification — needed for SA1+SA6 evidenceNO
fan_in_fan_outAlwaysSA8 coupling distribution; flags god modules and orphansNO
architecture_summaryAlwaysHigh-level project shape — required for executive summary sectionNO
analyze_complexityAlwaysSA9 cyclomatic complexity distribution (CRITICAL GATE if outliers)NO
analyze_hotspotsAlwaysSA13 churn × complexity (last 90 days by default)NO
find_dead_codeAlwaysSA8 unused exports across the symbol graphNO
find_clonesAlwaysSA10 duplication ≥0.7 similarityNO
find_unused_importsAlwaysSA5 barrel-export hygieneNO
audit_scanAlwaysCompound CQ-pattern check covering several SA gates in one callNO
detect_hono_modulesHono framework detectedSA6 Hono-specific module discoveryNO when Hono
nest_auditNestJS framework detectedSA6 NestJS module + DI graphNO when NestJS
Stack-specific tools (python_audit, php_project_audit, kotlin trace_*)Language detectedLanguage-specific structural patternsNO when language matches

Forbidden escape hatches

ValueForbidden whenRequired value instead
detect_communities: DEFERREDEVERdetect_communities: <community_count> communities
analyze_complexity: skipped (no diff vs prior)EVERanalyze_complexity: <max_cc> max, <count_above_20> outliers
find_dead_code: N/AEVERfind_dead_code: <count> unused exports
codesift: unavailablemcp__codesift__* was in deferred-tools session-start bannercodesift: deferred-not-preloaded (FAILURE: skill required preload)
retrospective: skippedEVERretrospective: appended (retros.log + retros.md)

Required POSTAMBLE — retrospective + verify-audit gates

After the audit report is written and the Validity Gate block is printed, the audit is NOT complete until:

  1. zuvo/audits/structure-audit-<date>.md is on disk — at the project root (zuvo/ resolves via git rev-parse --show-toplevel; override $ZUVO_OUTPUT_DIR. See ../../shared/includes/report-output-location.md).
  2. ~/.zuvo/append-runlog is called with the Run line — this triggers BOTH gates:
    • retro-gate: requires a matching RETRO: entry in ~/.zuvo/retros.log for skill=structure-audit project=<this>. If missing → exit 2, runs.log NOT appended. Load retrospective.md, fill 9 fields, run the bash append commands, then re-run append-runlog.
    • audit-content gate: runs ~/.zuvo/verify-audit on the report. Every finding section must contain at least one path/to/file.ext:LINE citation that resolves in the current tree. Findings without citations get rejected. If rejected → fix the report (add file:line per finding), re-run append-runlog.
  3. Print RETRO_APPENDED: retros.log=YES retros.md=YES (verified) and confirm exit 0 from append-runlog.

If you reach the Run line and stop without calling append-runlog: the audit is INVALID regardless of finding count. The Validity Gate's gate_status flips to FAIL — postamble incomplete and the verdict overrides to INCOMPLETE.

Mandatory acknowledgment (REQUIRED — print verbatim before Phase 0)

Mandatory-tools-acknowledgment: I will run detect_communities + check_boundaries + classify_roles + fan_in_fan_out + architecture_summary + analyze_complexity + analyze_hotspots + find_dead_code + find_clones + find_unused_imports + audit_scan + stack-specific structural tools (detect_hono_modules/nest_audit/python_audit/etc. when language/framework is detected) in this audit. Each finding will cite a `path/to/file.ext:LINE` resolving in the current tree.

Phase 0: Parse $ARGUMENTS and Detect Stack

0.1 Arguments

ArgumentBehaviorDimensions
fullAudit entire project (all 13 dimensions)SA1-SA13
[path]Scope to specific directorySA1-SA13 (scoped)
--namingNaming conventions onlySA2
--sizeFile size distribution onlySA7
--dead-codeDead code and barrel analysisSA5 + SA8
--duplicationCode duplication onlySA10
--hotspotsGit-based hotspot analysis onlySA13
--quickSkip external tooling and git miningSA1-SA8, SA11-SA12 (SA9/SA10/SA13 = N/A)
--fixAuto-fix after audit: delete unused (high confidence), .gitignore, renameAll + fix phase

Default: full

0.2 Stack Detection

Detect language, framework, and project type from config files. Be restrictive -- a few stray .ts files in a non-JS project do not make it TypeScript.

StackRequired signalsSA Impact
TypeScriptpackage.json AND (tsconfig.json OR >10 .ts/.tsx files)Full JS/TS tooling (knip, dep-cruiser, madge, eslint)
JavaScriptpackage.json AND >10 .js/.jsx files AND no tsconfig.jsonJS tools (knip, dep-cruiser, madge, eslint)
Next.jsJS/TS AND next in package.json depsSA1: App Router conventions, SA3: deep routes expected
NestJSTypeScript AND (nest-cli.json OR @nestjs/core in deps)SA2: suffix conventions, SA1: module structure
Pythonpyproject.toml OR requirements.txt AND >5 .py filesSA9: radon, SA8: vulture, no knip/madge
PHPcomposer.json AND >5 .php filesSA9: phpmd, SA10: phpcpd
Monorepoturbo.json OR nx.json OR pnpm-workspace.yamlSA1: per-package evaluation
GenericNone of aboveGrep-only analysis, JS/TS tools = N/A

Ignore for detection: files in dist/, node_modules/, coverage/, .next/, __pycache__/, .venv/, .git/.

0.3 Source Root and Code Scope

Two separate concepts:

  • $REPO_ROOT -- always . (project root). Used for SA11 (root org), SA12 (docs), .gitignore checks.
  • $CODE_SCOPE -- directories containing source code to analyze. Used for SA1-SA10, SA13, and all tools.

Detect $CODE_SCOPE:

SignalCODE_SCOPE
src/ exists with >5 code filessrc/
app/ exists with code (Next.js, no src/)app/
lib/ exists as main source dirlib/
backend/ + frontend/Per-app: backend/src/ and frontend/src/
packages/*/src/ (monorepo)Per-package
None of above but code files at root. (project root)

0.3.1 Build Code File List (ALWAYS)

Build a canonical file list as the single source of truth for all tools and analyses. Never let tools decide what to scan independently.

CODE_FILE_LIST="/tmp/structure-audit-code-files.txt"

find "$CODE_SCOPE" -type f \( \
  -name "*.ts" -o -name "*.tsx" -o -name "*.js" -o -name "*.jsx" \
  -o -name "*.py" -o -name "*.php" -o -name "*.go" -o -name "*.rs" \
  -o -name "*.java" -o -name "*.rb" -o -name "*.swift" \) \
  -not -path "*/node_modules/*" -not -path "*/dist/*" -not -path "*/.next/*" \
  -not -path "*/coverage/*" -not -path "*/__pycache__/*" -not -path "*/.venv/*" \
  -not -path "*/.git/*" \
  > "$CODE_FILE_LIST"

CODE_FILE_COUNT=$(wc -l < "$CODE_FILE_LIST" 2>/dev/null || echo 0)

Derive unique directories for tools that need directory arguments:

CODE_DIR_LIST="/tmp/structure-audit-code-dirs.txt"
while IFS= read -r file; do
  dirname "$file"
done < "$CODE_FILE_LIST" | sort -u | head -20 > "$CODE_DIR_LIST"

0.4 Code Density Check

ConditionMode
CODE_FILE_COUNT >= 10FULL AUDIT -- all SA1-SA13
CODE_FILE_COUNT = 1-9LIMITED AUDIT -- SA1-SA4, SA11-SA12 only. Print: "Scope has <10 code files. Running limited audit."
CODE_FILE_COUNT = 0NO-CODE MODE -- only markdown/config/docs. Run SA11 + SA12 only. Print: "No source code files. Running documentation audit only."

Print:

Stack: [detected] | Framework: [detected] | Monorepo: [yes/no]
Code scope: [path] | Code files: [N] | Mode: [FULL/LIMITED/NO-CODE]
Dimensions: [which SA dimensions will run]

Phase 1: Tool Execution

Run external tools. Save all outputs to zuvo/audits/structure-audit-{YYYY-MM-DD}/.

Skip if: --quick mode (SA9/SA10/SA13 = N/A), LIMITED/NO-CODE mode, or code density < 10.

CodeSift is the primary engine. Tools 1.2 (dead code), 1.4 (duplication), 1.5 (complexity) try CodeSift first. Phase 2 (hotspots) also uses CodeSift analyze_hotspots first. Fall back to CLI tools only if CodeSift is unavailable.

JS/TS tool gate (fallback tools only): Fallback tools 1.2 (knip) and 1.3 (dep-cruiser) require BOTH: (a) package.json exists, AND (b) stack detected as JavaScript or TypeScript. Tool 1.1 (cloc) and 1.4 fallback (jscpd) are stack-agnostic.

1.1 cloc (ALWAYS -- uses code file list)

npx cloc --json --by-file --list-file="$CODE_FILE_LIST"

Feeds: SA7 (file size distribution), SA13 (hotspot LOC component). Verify output: check for "SUM" key in JSON, not exit code.

1.2 Dead Code Detection (SA5, SA8)

PRIMARY (CodeSift):

find_dead_code(repo, file_pattern="*.{ts,tsx}")

Parse: unused exports count, unused files list, confidence per entry.

FALLBACK (no CodeSift) -- knip (JS/TS only):

npx knip --reporter json

Fallback: grep-based export tracing (MEDIUM confidence).

1.3 dependency-cruiser (JS/TS only -- fallback tool)

Gate: package.json exists AND JS/TS stack detected. Otherwise: N/A.

tr '\n' '\0' < "$CODE_DIR_LIST" | xargs -0 npx --yes dependency-cruiser \
  --no-config --output-type err \
  --do-not-follow "node_modules" \
  --exclude "^(dist|docs|coverage|\.next)"

Feeds: SA6 (layer violations), SA8 (circular deps, orphans). Verify output: check for "modules.*cruised" or violation text. 0 modules cruised = TOOL_EMPTY.

1.4 Code Duplication (SA10)

PRIMARY (CodeSift):

find_clones(repo, min_similarity=0.7, file_pattern="*.{ts,tsx}")

FALLBACK (no CodeSift) -- jscpd (all languages):

tr '\n' '\0' < "$CODE_DIR_LIST" | xargs -0 npx --yes jscpd \
  --min-lines 10 --reporters json \
  --ignore "**/node_modules/**,**/dist/**,**/*.md,**/*.json" \
  --output zuvo/audits/

Verify output: check statistics.total.sources > 0 in JSON.

1.5 Complexity Distribution (SA9)

PRIMARY (CodeSift):

analyze_complexity(repo, top_n=20, file_pattern="*.{ts,tsx}")

FALLBACK (no CodeSift) -- ESLint complexity (JS/TS only):

Try in order, stop at first success:

  1. Project ESLint config (preferred): Check for existing config. Use it with --rule 'complexity: [warn, 15]'.
  2. Standalone (plain JavaScript only): --no-config-lookup on .js/.jsx files.
  3. Grep heuristic (last resort): nesting depth via indentation analysis.

Never use --no-config-lookup on .ts/.tsx files -- it cannot parse TypeScript without a parser config.

Tool Summary

After all tools, print:

Tools: cloc [OK/SKIP] | dead-code [CodeSift/knip/SKIP] | dep-cruiser [OK/SKIP] | duplication [CodeSift/jscpd/SKIP] | complexity [CodeSift/eslint/SKIP]
Code files scanned: [N] | Non-code excluded: [dirs]

Phase 2: Git Mining (SA13)

Skip if: --quick mode, LIMITED/NO-CODE mode, git history < 3 months, or non-git repository. Mark SA13 as N/A.

PRIMARY (CodeSift):

analyze_hotspots(repo, since_days=180)

Parse: hotspot files (change frequency x complexity), temporal coupling pairs, churn scores.

FALLBACK (no CodeSift): Run git mining scripts directly.

2.1 Change Frequency

git log --since="6 months ago" --name-only --format="" -- $CODE_SCOPE | sort | uniq -c | sort -rn | head -30

Top 30 most-changed files. Combine with cloc LOC for hotspot score.

2.2 Temporal Coupling

Analyze co-change patterns among top 100 most-changed files. Flag pairs with >50% co-change rate in different modules.

2.3 Shotgun Surgery

Count unique directories per commit. Median > 3 directories indicates shotgun surgery.

2.4 Developer Congestion

For each hotspot file from 2.1, count unique authors. >5 authors on a low-health file is a congestion finding.


Phase 3: Structural Analysis

Grep and Read based analysis for dimensions that do not need external tooling. Two-step detection: grep finds CANDIDATES, Read VERIFIES. Never score from grep alone.

Scope: All grep/glob commands target $CODE_SCOPE for SA1-SA10. SA11-SA12 use $REPO_ROOT.

3.1 SA1 -- Directory Pattern Consistency

  1. List top-level directories under $CODE_SCOPE
  2. Classify each as LAYER, FEATURE, INFRASTRUCTURE, or FRAMEWORK
  3. Mixed patterns at same level = finding
  4. Check framework conventions (Next.js: no pages/ alongside app/)

3.2 SA2 -- File Naming Conventions

  1. Glob all source files. Classify filename case (kebab, camel, pascal, snake).
  2. Mixed case in same directory = finding
  3. Count .test.ts vs .spec.ts. Both > 10% = mixed convention.
  4. Check type suffix consistency (.service.ts, .controller.ts)

3.3 SA3 -- Folder Depth and Nesting

  1. Compute max and average depth from file tree (code files only)
  2. Filter out framework-deep paths (Next.js App Router routes)
  3. Directories with >50 source files = flat explosion
  4. Single-file directories = unnecessary nesting

3.4 SA4 -- Colocation

  1. For each test file, determine co-located (same dir) or centralized (tests/)
  2. 20% in each category = mixed colocation

  3. Check type files: centralized types/ vs co-located *.types.ts
  4. Check constants/utils used by single module but stored centrally

3.5 SA5 -- Barrel Exports and Import Hygiene

Skip if: LIMITED or NO-CODE mode.

  1. Count index.ts files. >30 exports = god barrel
  2. Merge with dead code detection output for unused export counts
  3. Check for barrel chains (index.ts re-exporting from another index.ts)
  4. Grep for deep relative imports (>3 levels of ../)
  5. Check tsconfig paths vs actual usage

3.6 SA6 -- Separation of Concerns (CRITICAL GATE)

Skip if: LIMITED or NO-CODE mode.

Run fitness function rules:

  1. F1: ORM imports in .tsx/.vue files (CRITICAL if in components)
  2. F2: Controller-to-controller imports
  3. F3: Service importing from controller
  4. F4: Test utility imports in production code
  5. F5: fetch/axios in component files (not hooks)
  6. F6: process.env outside config layer
  7. F7: Module envy (>60% imports from single other module)

Each grep hit is a CANDIDATE. Read surrounding context to verify.

3.7 SA7 -- File Size Distribution (CRITICAL GATE)

Skip if: LIMITED or NO-CODE mode.

  1. Use cloc per-file data. Exclude non-code files from size analysis.
  2. Classify each file by type (component, service, hook, util)
  3. Apply 1.2x tolerance factor, compare to category limit from file-limits.md
  4. 3x+ = CRITICAL, 2-3x = HIGH, 1-2x = MEDIUM
  5. Compute distribution: median, P90, P99, max
  6. God module detection: >3x median files + generic name + high coupling

3.8 SA11 -- Configuration and Root Organization

Uses $REPO_ROOT.

  1. Count root-level files. Categorize (essential, dotfiles, stale, artifacts)
  2. Check for tracked temp files (.tmp-*, .env.local, *.log)
  3. Check .gitignore completeness for detected stack
  4. Check for scripts at root vs scripts/ directory

3.9 SA12 -- Documentation Structure

Uses $REPO_ROOT.

  1. Check for README.md with setup instructions
  2. Check for CHANGELOG.md
  3. Check for docs/adr/ directory (if project >50 files)
  4. Check for OpenAPI/Swagger spec (if API project)
  5. Check for CONTRIBUTING.md (if >3 git contributors)

Phase 4: Scoring

4.1 Per-Dimension Scoring

For each SA1-SA13:

  1. Apply scoring rubric (0 = violated, 1 = weak, 2 = acceptable, 3 = strong)
  2. Note N/A dimensions (exclude from denominator)
  3. Provide 1-line evidence for each score
  4. In LIMITED mode: SA5-SA10, SA13 are all N/A
  5. In NO-CODE mode: SA1-SA10, SA13 are all N/A

4.2 Critical Gate Check

GateTriggerResult
SA6 = 0ORM in UI components, no service layerFAIL
SA7 = 03+ production files exceed 3x category limitFAIL
SA8 = 0Circular deps in core production modules (confirmed)FAIL

Any gate = 0 means overall grade = FAIL regardless of total score. In LIMITED/NO-CODE mode, gates are N/A.

4.3 Total Score

raw_score = sum of all scored dimensions
available_max = 100 - sum of N/A dimension weights
normalized_score = (raw_score / available_max) * 100

4.4 Grade Assignment

RangeGrade
>= 85A
70-84B
50-69C
< 50D
Any gate = 0FAIL

4.5 SQALE Debt Ratio (secondary metric)

remediation_minutes = sum(LOW:5 + MEDIUM:15 + HIGH:30 + CRITICAL:60 per finding)
debt_ratio = remediation_minutes / (total_LOC * 30)
Debt RatioRating
0-5%A
6-10%B
11-20%C
21-50%D
51%+E

Phase 5: Report and Action Plan

REQUIRED: emit the Tool Availability Block (template in ../../shared/includes/codesift-setup.md) at the top of the report, after the title and before findings. Auditing degraded runs depends on this — do NOT skip it. The standard table replaces ad-hoc "tools used" prose in META.

5.1 Report Sections

  1. META -- date, stack, scope, code files count, mode (FULL/LIMITED/NO-CODE), tools used, LOC count
  2. Score Table -- SA1-SA13 with scores, max, gate status
  3. Critical Gates -- PASS/FAIL with evidence for SA6, SA7, SA8
  4. Grade -- letter grade + debt ratio
  5. Tool Outputs Summary -- key numbers from each tool
  6. Findings -- sorted by severity, with fix and effort estimates
  7. Cross-Cutting Patterns -- compound risk patterns:
    • Structural bottleneck: SA7 god file + SA8 circular + SA13 hotspot
    • Hidden coupling: SA13 temporal coupling + SA6 module envy
    • Import pollution: SA5 god barrel + SA8 unused exports
    • Untestable hotspot: SA13 hotspot + SA7 oversized + SA4 no co-location
    • Missing abstraction: SA10 high duplication + SA13 shotgun surgery
    • Abandoned attic: SA8 dead code + SA11 stale config + SA11 temp files
  8. Hotspot Analysis -- SA13 table (if applicable)
  9. Top 5 Action Items -- sorted by Impact/Effort ratio
  10. Recommended Next Skills -- based on findings

5.2 Save Report

mkdir -p audit-results

Save to: zuvo/audits/structure-audit-YYYY-MM-DD.md — at the project root (zuvo/ resolves via git rev-parse --show-toplevel; override $ZUVO_OUTPUT_DIR. See ../../shared/includes/report-output-location.md).

5.3 Backlog Integration

Every HIGH and CRITICAL finding goes through backlog-add, one call per finding (../../shared/includes/backlog-protocol.md "Filing from a skill"; the checkout the helper writes to, the bars and the dedupe are the protocol's, so compute no fingerprint and restate nothing).

A Generic write per finding: ~/.zuvo/backlog-add --repo "$R" --class <C> --conf <N> --source structure-audit --file "$F" --line <n> [--anchor "$A"] --severity <level> --title "$T". <level> is critical or high, the finding's own severity. <N> is 85 for a HIGH-confidence finding (tool-confirmed, or read and verified) and 60 for a MEDIUM-confidence one (a grep-based fallback, as 1.2 labels it). <C> is the finding's own class: SIZE (SA7, a file over its size limit), DUP (SA10), CPLX (SA9, SA13), DEAD (unused exports and dead files, SA5), and CQ for every other dimension: SA1-SA4, SA6 (layer violations, a critical gate), SA8 (circular dependencies, a critical gate), SA11 and SA12. None of these takes an --anchor. Where the finding sits: a layer violation (SA6) cites the file and line of the offending import; a cycle (SA8) cites the first file of the cycle in path order and lists the others in --evidence "$E"; a directory-level finding (SA1-SA4, SA11, SA12) cites the first affected path in path order, --line 1, with a "Whole file: ..." or "Directory: ..." title ("The location rule"). A finding that is a defect with a wrong output rather than a structure problem is a BUG, which takes --anchor "$A", copied from the line that shows it. Assign "$R", "$F" and "$T" before each call, "$A" only when you pass --anchor and "$E" only when you pass --evidence, as "Free text goes through a variable" in that section says; an empty value you pass is a bug, and backlog-add refuses a missing required field (REFUSED missing-field:<f>). Report the B- or F-id each call prints and Recorded: N (backlog: a, ledger: b) ("The report line" in backlog-protocol.md), plus each NOT PERSISTED (<reason>) by name; on a non-zero exit act on the protocol's exit table, and never append by hand.

Resolved entries (Closing, not removing): with --fix, run 5.4 BEFORE these calls and file only the findings it left unresolved (the calls need the cited file to exist, and a file 5.4 deleted or renamed would leave an entry pointing nowhere). An open entry from an earlier audit that this run re-read and found fixed is closed, never removed. --fix does not commit, so there is no <sha7> to write: leave such an entry open, note the fix in the report, and let whoever commits the fix close it (backlog-protocol.md "How to Persist Findings" step 3: tick the box - [x] and append [FIXED <sha7>], the one hand edit the protocol sanctions; no helper ticks). When the fix is already committed, that tick is a single edit, it is not a wrote= path, this audit does not stage it, and the report names each ticked entry. Moving a closed entry to the archive is the helper's job (~/.zuvo/backlog-archive.py archive, which append-runlog runs at the end of the run), never done by hand.

This audit does not commit: it stages nothing. It lists the wrote= paths backlog-add printed as Backlog writes: <path>, ... (Backlog writes: none when there are none), in its report for the user when it runs standalone, and in its report for the calling skill's closing commit to carry when another skill runs it (backlog-protocol.md "Filing from a skill", Committing what backlog-add wrote).

5.4 Auto-Fix Mode (--fix)

Only if --fix argument was provided. After the report is saved, and before the 5.3 backlog calls:

Fix TypeConditionAction
Delete unused filesDead code detection with HIGH confidence onlyrm with confirmation
Add .gitignore patternsMissing stack-specific patternsAppend to .gitignore
Rename convention violationsClear case mismatch (1-3 files)git mv with import updates

NEVER auto-fix:

  • Split oversized files (requires zuvo:refactor)
  • Restructure directories (requires design decisions)
  • Fix circular dependencies (requires zuvo:architecture analysis)
  • Delete files with MEDIUM confidence

Confirm each fix with the user before executing.


Next-Action Routing

FindingActionCommand
SA5 Dead code CRITICALRemove dead codezuvo:structure-audit [path] --fix
SA8 Circular dependenciesArchitecture reviewzuvo:architecture --mode review [path]
SA10 Excessive duplicationExtract shared codezuvo:refactor [file]
SA13 Hot file (high churn + complexity)Refactor hot filezuvo:refactor [file]
SA7 God module detectedSplit oversized filezuvo:refactor [file]
SA6 Layer violationsArchitecture analysiszuvo:architecture --mode review

Completion Gate Check

Before printing the final output block, verify every item. Unfinished items = pipeline incomplete.

COMPLETION GATE CHECK
[ ] Code density mode printed (FULL/LIMITED/NO-CODE)
[ ] Tool summary printed: cloc/dead-code/dep-cruiser/duplication/complexity
[ ] SA6 fitness functions ran
[ ] SA7 file size uses cloc data with category classification
[ ] Critical gates printed: SA6, SA7, SA8
[ ] Report saved to zuvo/audits/
[ ] Run: line printed and appended to log

STRUCTURE-AUDIT COMPLETE

Grade: [A/B/C/D/FAIL] | Score: [N] / [MAX] Mode: [FULL/LIMITED/NO-CODE] | Stack: [detected] Dimensions: [N scored] | Critical gates: [PASS/FAIL] Findings: [N critical] / [N total]

Validity Gate (REQUIRED — print BEFORE Run line, AFTER retro append)

VALIDITY GATE
  triggers_held:
    code_files: yes(<count>)
    language: <typescript|python|php|kotlin|javascript|...>
    framework: <nextjs|nestjs|astro|hono|react|django|flask|...|none>
  required_tool_calls:
    detect_communities: [<N> communities | NOT_CALLED — VIOLATES_TRIGGER]
    check_boundaries: [<N> violations | NOT_CALLED — VIOLATES_TRIGGER]
    classify_roles: [<hub>/<leaf>/<bridge> distribution | NOT_CALLED — VIOLATES_TRIGGER]
    fan_in_fan_out: [<max_in>/<max_out> outliers | NOT_CALLED — VIOLATES_TRIGGER]
    architecture_summary: [<modules>/<files> | NOT_CALLED — VIOLATES_TRIGGER]
    analyze_complexity: [<max_cc> max, <outliers_above_20> outliers | NOT_CALLED — VIOLATES_TRIGGER]
    analyze_hotspots: [<top_N> hotspots in 90d | NOT_CALLED — VIOLATES_TRIGGER]
    find_dead_code: [<N> unused exports | NOT_CALLED — VIOLATES_TRIGGER]
    find_clones: [<N> clone clusters ≥0.7 | NOT_CALLED — VIOLATES_TRIGGER]
    find_unused_imports: [<N> unused imports | NOT_CALLED — VIOLATES_TRIGGER]
    audit_scan: [<N> compound findings | NOT_CALLED — VIOLATES_TRIGGER]
    stack_specific (nest_audit/detect_hono_modules/python_audit/etc.): [<result> | not_required | NOT_CALLED — VIOLATES_TRIGGER]
  postamble:
    retros_log_appended: [yes(bytes_added=N) | NOT_APPENDED — VIOLATES_REQUIRED_POSTAMBLE]
    retros_md_appended: [yes(entry_count=N) | NOT_APPENDED — VIOLATES_REQUIRED_POSTAMBLE]
    verify_audit_pass: [yes(<verified>/<total> findings) | NOT_RUN | REJECTED]
  gate_status: [PASS | FAIL — <which gates missing>]

If gate_status = FAIL, override the VERDICT below to INCOMPLETE regardless of finding count, append [VALIDITY GATE FAIL] to the Run line NOTES column, and record the incomplete Process item (backlog-protocol.md "Filing from a skill"): ~/.zuvo/backlog-add --repo "$R" --class PROCESS --conf 90 --source structure-audit --target subject:structure-audit-incomplete --title "$T", with T the fixed title structure-audit run INCOMPLETE: validity gate failed, the same words on every run and no date; this run's reason goes in the report, never in the title. Assign "$R" and "$T" before the call, as "Free text goes through a variable" in that section says; an empty value is a bug, and backlog-add refuses a missing required field (REFUSED missing-field:<f>). It is kept in the findings ledger, not ticketed. File it before the report's Backlog writes: line is printed, so its wrote= paths are on that line: decide gate_status from every field the report can already fill (all but postamble) before the report is written, and file the item then. Only a postamble field that fails after the report is saved files it at this gate (a repeat bumps the same record); the Validity Gate block then carries its F-id on a line incomplete-item: <F-id> and its paths on a line Backlog writes (gate): <path>, … | none.

The Validity Gate must be printed AFTER the retro append and ~/.zuvo/append-runlog call (so postamble fields can be filled with yes(verified)). Printing it before guarantees NOT_APPENDED.

Run: <ISO-8601-Z> structure-audit <project> <N-critical> <N-total> <VERDICT> - <N>-dimensions <NOTES> <BRANCH> <SHA7> <INCLUDES> <TIER>

Retrospective (REQUIRED — load + fill BEFORE the Run line append)

Load ../../shared/includes/retrospective.md if not already loaded. Follow the retrospective protocol: gate check → 9 structured questions → TSV emit → markdown append to ~/.zuvo/retros.md AND ~/.zuvo/retros.log.

Then append the Run line via the retro-gated wrapper:

printf '%b\n' "$RUN_LINE" | ~/.zuvo/append-runlog

The wrapper:

  • Verifies the matching RETRO: entry in retros.log (skill+project). Missing → exit 2, runs.log NOT appended.
  • Runs ~/.zuvo/verify-audit on the audit report. Findings without file:line citations → exit 2, audit REJECTED.
  • On both pass: appends to runs.log and prints confirmation.

If the wrapper exits non-zero: do NOT manually append to runs.log. Fix the cause (add retro, add file:line citations, etc.) and re-run.

VERDICT: PASS (0 critical findings), WARN (1-3 critical), FAIL (4+ critical), INCOMPLETE (Validity Gate FAIL).

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.