repo-audit¶
Plugin: core-standards
Category: Governance
Command: /repo-audit
/vt-c-repo-audit — Deployment Integrity Audit¶
The "Search & Destroy" skill from the Unified Repo Governance model.
Reference:
docs/unified repo approach.md
Purpose¶
Scans the repository for governance violations that could compromise deployment integrity: - Context artifacts leaking into deployable paths - Oversized files not tracked by Git LFS - Sandbox code that should have been promoted or removed - Build bundles containing non-production files - Missing traceability references - Hook script tampering, unauthorized hooks, and dangerous patterns
When to Use¶
- On demand: Run anytime to check governance compliance
- Before deployment:
/vt-c-5-finalizecalls this automatically - In CI/CD:
--ci-modefor non-interactive pipeline use - Self-correction:
--fixto automatically resolve violations
Prerequisites¶
.repo-manifest.yaml must exist. If absent, report:
No .repo-manifest.yaml found. Governance is not active.
Run /vt-c-repo-init to initialize unified repo governance.
Invocation¶
/vt-c-repo-audit # Interactive audit with full report
/vt-c-repo-audit --fix # Auto-fix violations where possible
/vt-c-repo-audit --ci-mode # Non-interactive, exit code 1 on critical failures
Execution Steps¶
Step 1: Load Manifest¶
Read .repo-manifest.yaml and parse:
- partitions.deployable.paths — production code zones
- partitions.context.paths — design/AI context zones
- partitions.sandbox.paths — draft code zones
- binary_rules — size thresholds and LFS extensions
- traceability — SPEC reference requirements
Step 2: Context Bleed Check¶
Scan all files in deployable paths for context artifacts:
Context indicators in deployable paths (CRITICAL):
- .md files with YAML frontmatter containing parent_prd:, personas:, status: draft
- Files matching known context patterns: *-persona.md, *-research.md, PRD*.md, PID*.md
- .design-state.yaml or .repo-manifest.yaml copies in src/
- Prototype HTML/CSS files in src/ (not component files)
Exceptions (allowed in deployable paths):
- README.md, CHANGELOG.md, LICENSE.md
- CLAUDE.md, AGENTS.md
- Code comments referencing SPEC IDs
- API documentation generated from code
Output per finding:
❌ CONTEXT BLEED: src/docs/user-research.md
Context artifact found in deployable partition (src/)
Fix: Move to docs/ or 02-Knowledge/
Step 3: File Size Check¶
Scan all files for oversized objects not tracked by LFS:
# Find files exceeding max_file_size_kb
find . -type f -size +{max_file_size_kb}k \
-not -path "./.git/*" \
-not -path "./node_modules/*"
For each oversized file:
- If extension matches lfs_extensions but NOT in .gitattributes → CRITICAL
- If in context paths → WARNING (large but won't deploy)
- If in deployable paths → CRITICAL (will bloat production)
Output:
⚠ OVERSIZED: assets/hero-image.png (2.3 MB)
Not tracked by Git LFS. Extension .png matches binary rules.
Fix: git lfs track "*.png" && git add .gitattributes
Step 4: LFS Compliance Check¶
Verify .gitattributes covers all extensions in binary_rules.lfs_extensions:
For each extension in manifest:
- Check .gitattributes contains matching LFS rule
- Check any existing files with that extension are LFS-tracked
Output:
❌ LFS MISSING: .sketch files not in .gitattributes
Manifest requires LFS tracking for .sketch
Fix: echo "*.sketch filter=lfs diff=lfs merge=lfs -text" >> .gitattributes
Step 5: Build Bundle Audit¶
If dist/, build/, .next/, or out/ directories exist:
Scan build output for context artifacts:
- .md files (except README/LICENSE)
- .yaml/.yml files (except configs)
- persona documents, research notes
- prototype files, specs files
- .design-state.yaml
Output:
❌ BUILD LEAK: dist/docs/PRD.md
Context artifact found in build output
Fix: Update build config to exclude docs/ from output
Step 6: Sandbox Status Check¶
Scan sandbox paths for stale code:
For files in sandbox paths:
- Last modified > 30 days ago → STALE WARNING
- Contains TODO/FIXME/HACK markers → NOTE
- Duplicated in deployable paths → CONFLICT WARNING
Output:
⚠ STALE SANDBOX: 04-prototyp/components/Dashboard.tsx
Last modified 45 days ago. Consider:
- /vt-c-promote to move to production
- Delete if no longer needed
Step 7: Traceability Check¶
Read traceability.require_spec_reference from manifest:
If true: Scan ALL commits to deployable paths (full enforcement).
If "new-only": Only scan commits AFTER traceability.cutoff_date:
ℹ Traceability mode: new-only (adopted {adoption.adopted_at})
{N} pre-governance commits exempt | Checking {M} post-governance commits
If false or absent: Skip traceability check entirely.
For each checked commit, verify message contains SPEC- prefix reference.
Also scan source files in deployable paths for SPEC- references in comments.
Output (full mode):
⚠ TRACEABILITY: 3 recent commits to src/ lack SPEC- references
- abc1234 "Add login form"
- def5678 "Fix button styling"
- ghi9012 "Update API handler"
Recommendation: Include SPEC-NNN in commit messages for traceability
Output (new-only mode):
⚠ TRACEABILITY (new-only, cutoff: 2026-02-13):
15 pre-governance commits — exempt
5 post-governance commits checked:
3 reference SPEC- IDs ✅
2 missing SPEC- references ⚠
Note: Consider upgrading to require_spec_reference: true
when all active features have SPEC IDs assigned.
Step 8: Hook Security Audit¶
Validates hook script integrity, location, permissions, and content against the trusted hooks manifest (configs/security/trusted-hooks.yaml).
Added by SPEC-053. Detects tampered, unauthorized, or dangerous hook scripts.
8a: Load Trusted Hooks Manifest¶
Read configs/security/trusted-hooks.yaml from the toolkit root (resolve via TOOLKIT_ROOT).
If the manifest file does not exist:
- Record finding: [WARN] No trusted hooks manifest found; hook integrity cannot be verified
- Continue with sub-steps 8e (network) and 8f (permissions) only — skip 8c (location), 8d (checksum), and 8g (unknown)
If the manifest exists:
- Parse approved_locations list
- Parse hooks map (keyed by relative path)
- Continue with all sub-steps
8b: Discover Hook Scripts¶
Scan these directories for .sh files and other executables:
plugins/*/scripts/— all plugin script directories (relative to repo root)~/.claude/hooks/— user-global deployed hooks
For each discovered file:
- If it is a symlink: resolve the target using readlink (macOS-compatible; follow chains until a real file is reached)
- Record both the symlink path and the resolved target path
- If the symlink is broken (target does not exist): record finding [CRITICAL] Broken hook symlink: <symlink> → <target> (target does not exist)
- If the file is a directory: skip it silently
Build a set of all discovered scripts with their resolved paths.
8c: Location Validation¶
For each discovered script (using resolved paths for symlinks):
- Check if the resolved path falls under one of the approved_locations entries from the manifest
- For ~/.claude/hooks/ symlinks: validate that the resolved target is in an approved location (e.g., plugins/core-standards/scripts/)
Finding for unapproved location:
8d: Checksum Verification¶
For each hook entry in the manifest:
1. Check if the file exists on disk
2. If it exists: compute shasum -a 256 <file> and compare against the manifest's sha256 value
3. If the file does not exist on disk: record a WARN finding
Finding for checksum mismatch:
Finding for missing file:
8e: Network Call Detection¶
For each discovered script, scan for outbound network call patterns using grep -n:
Patterns to match:
- Shell: curl, wget, nc (word boundary), netcat, ncat, socat
- Python: python.*http, requests\., urllib, http\.client
- Ruby: ruby.*net, Net::HTTP
- Node: node.*http, fetch(, XMLHttpRequest
Scan ALL lines including comments (commented-out network calls can be uncommented and are still a risk indicator).
Finding for network call detected:
If no network patterns are found in a script, no finding is reported for that script.
8f: Permission Audit¶
For each discovered script, check file permissions using macOS-compatible syntax:
Parse the octal permission value:
- If the group-write bit is set (second digit is 2, 3, 6, or 7) → WARN
- If the other-write bit is set (third digit is 2, 3, 6, or 7) → WARN
- Acceptable permissions: 700, 750, 755
- Unacceptable permissions: 775, 776, 777, etc.
Finding for overly permissive:
If a script has 755 or stricter permissions, no finding is reported.
8g: Unknown Hook Detection¶
Compare the set of discovered scripts against the manifest entries:
- For scripts in
plugins/*/scripts/: use the relative path from repo root as the key - For scripts in
~/.claude/hooks/that are symlinks: validate via their resolved target path (the source script should be in the manifest) - For scripts in
~/.claude/hooks/that are NOT symlinks (real files, not symlinks to plugin scripts): flag as unknown
Finding for unknown hook:
Step 9: Generate Report¶
╔══════════════════════════════════════════════════╗
║ REPO GOVERNANCE AUDIT REPORT ║
╠══════════════════════════════════════════════════╣
║ ║
║ Context Bleed: ✅ PASS (0 violations) ║
║ File Size: ⚠ WARN (2 oversized files) ║
║ LFS Compliance: ✅ PASS (all tracked) ║
║ Build Bundle: ✅ PASS (clean) ║
║ Sandbox Status: ⚠ WARN (1 stale file) ║
║ Traceability: ⚠ WARN (3 commits) ║
║ Hook Security: ✅ PASS (all hooks verified) ║
║ ║
║ Overall: ⚠ WARNINGS (no critical failures) ║
║ ║
╚══════════════════════════════════════════════════╝
Hook Security traffic light logic: - ✅ PASS (green): All hooks pass all checks — checksums match, no unknown hooks, no network calls, permissions OK - ⚠ WARN (yellow): Only WARN-severity findings — permission issues, missing manifest, manifest lists hook not found on disk - ❌ FAIL (red): Any CRITICAL finding — checksum mismatch, unknown hook, unapproved location, network call pattern, broken symlink
Step 10: Self-Correction (--fix mode)¶
If --fix flag is set, for each fixable violation:
- Context bleed: Move file to appropriate context path, update references
- Oversized files: Run
git lfs trackfor matching extensions - LFS missing: Add rules to
.gitattributes - Build leaks: Suggest build config changes (cannot auto-fix build tools)
- Hook permissions: Run
chmod 755 <script>to fix overly permissive hooks - Hook checksum mismatch: Cannot auto-fix — report "Manual review required: verify hook content is correct, then update manifest with
shasum -a 256 <script>" - Unknown hooks: Cannot auto-fix — report "Manual review required: add to
configs/security/trusted-hooks.yamlor remove the script" - Hook network calls: Cannot auto-fix — report "Manual review required: verify the network call is intentional"
Show summary of fixes applied:
Auto-fixed 3 violations:
✅ Moved src/research-notes.md → docs/research-notes.md
✅ Added *.sketch to .gitattributes (LFS tracking)
✅ Added *.psd to .gitattributes (LFS tracking)
Manual action needed:
⚠ Update build config to exclude docs/ from dist/
⚠ Add SPEC- references to 3 commit messages (cannot retrofix)
Step 11: CI Mode (--ci-mode)¶
When running in CI/CD pipeline: - No interactive prompts - Exit code 0 = PASS (no critical violations) - Exit code 1 = FAIL (critical violations found) - Warnings are logged but don't cause failure - Output is structured for CI log parsing
[REPO-AUDIT] Context Bleed: PASS
[REPO-AUDIT] File Size: WARN (2 files)
[REPO-AUDIT] LFS Compliance: PASS
[REPO-AUDIT] Build Bundle: PASS
[REPO-AUDIT] Sandbox Status: WARN (1 stale)
[REPO-AUDIT] Traceability: WARN (3 commits)
[REPO-AUDIT] Hook Security: PASS
[REPO-AUDIT] RESULT: PASS (0 critical, 7 warnings)