IaC Compliance Audit — 2026-02-19
Scope: Complete inventory and IaC assessment of all BoB tooling components. Reference: Prime Directive | Part of #28, #42
Summary
Overall IaC compliance: ~78%. Strong declarative foundations with gaps in portability and settings management.
| Area | Count | Compliance | Key Gap |
|---|---|---|---|
| Skills (universal + registry) | 42 | Full | None |
| Commands (universal + registry) | 17 | Full | None |
| Agents (universal + registry) | 15 | Full | 1 stale reference |
| Hooks (declarations) | 12 | Full | Absolute paths in settings.json |
| Hooks (git-level) | 1 | Partial | Copy instead of symlink |
| Scripts | 12+ | Partial | bob-install.sh not idempotent |
| Templates | 12 | Full | None |
| Provision manifests | 15 | Full | None |
| Global settings | 1 | Partial | Absolute paths, no update mechanism |
| Project settings | auto | Partial | Template embedded in cdi script |
| Machine settings | 1 | Non-compliant | Stale, no generation mechanism |
| Runbooks | 4 | Partial | Manual steps that could be automated |
Principle Assessment
Declarativity: 85%
Most state is JSON or markdown. Gaps:
- Project
settings.jsontemplate embedded inclaude-init.sh(not a standalone file) - Automation levels require runtime script execution (
switch-level.sh) - Some runbook steps are “do this manually” without automation
Version Control: 95%
Nearly everything in git. Exceptions:
settings.local.jsonis gitignored (by design, but stale)- Machine-specific overrides not tracked
Reproducibility: 70%
Fresh installs work well. Gaps on incremental:
cdiprompts on re-run (disruptive for scripts/CI)- Project settings don’t update when template changes
- No mechanism to propagate global hook updates to git-level hooks
Idempotency: 75%
Most scripts check before acting. Gaps:
bob-install.shfails if already installed- Idempotency not explicitly documented on most scripts
- Git hook installation uses copy + diff (fragile)
Portability: 65%
Main blocker:
settings.jsonhooks use absolute paths:/Users/paulirving/.claude/hooks/...- Not usable on another machine without path rewriting
Gaps Identified
GAP-1: Hook Path Portability (High)
settings.json declares hooks with absolute paths. These paths are correct for runtime (Claude Code requires them) but break CI validation and aren’t portable across machines. Workaround exists (check-hooks.sh remaps paths) but the root cause remains.
GAP-2: Git Hook Installation (Medium)
cdi copies the commit-msg hook from template instead of symlinking. Local copies don’t track updates to the global template. Uses fragile diff detection for re-copy.
GAP-3: Settings Template Embedded in Script (Medium)
Project settings.json template is a heredoc inside claude-init.sh. Changes to the template require modifying the script. Existing projects don’t get template updates on re-run.
GAP-4: Machine Settings Orphaned (Low)
settings.local.json (the global one in ~/.claude/) is stale (Jan 28). No generation mechanism, no documented merge strategy with settings.json, no template.
GAP-5: Automation Levels Require Runtime Switch (Medium)
Automation levels (Level 1/2/3) are set via switch-level.sh which writes to settings.local.json. The level isn’t part of the version-controlled settings.json. Not reproducible from git state alone.
GAP-6: Runbook Manual Steps (Low)
Runbooks contain “check manually” and “fix manually” steps that could be replaced with scripts or helper commands. Examples:
- “Check warp-drive state file manually” (agent-handoff)
- “Check migrations manually” (incident-response)
- “Manually create provisions manifest” (project-onboarding)
GAP-7: bob-install.sh Non-Idempotent (Low)
The shell profile installer fails if markers already exist. Requires manual removal before reinstall. No --force flag.
GAP-8: Stale Agent Reference (Low)
lessons-extractor.md referenced in claude-init.sh universal agents list but not present on filesystem.
Provisioning Idempotency Verification
Tested provision.sh with --status and --diff flags. Confirmed:
- State detection works (distinguishes registry links, universal links, local files, broken links)
--diffshows only actual changes needed- Running provision twice produces identical state
- Verdict: provisioning is fully idempotent
Fix Issues Filed
| Gap | Issue | Priority |
|---|---|---|
| GAP-1: Hook path portability | #49 | p3-medium |
| GAP-2: Git hook symlinks | #52 | p3-medium |
| GAP-3: Settings template | #50 | p3-medium |
| GAP-7: bob-install.sh | #51 | p4-low |
| Pre-existing: Dangling symlinks | #44 | p2-high |
Gaps 4–6 and 8 are lower priority and tracked as notes in this audit rather than separate issues.