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.

AreaCountComplianceKey Gap
Skills (universal + registry)42FullNone
Commands (universal + registry)17FullNone
Agents (universal + registry)15Full1 stale reference
Hooks (declarations)12FullAbsolute paths in settings.json
Hooks (git-level)1PartialCopy instead of symlink
Scripts12+Partialbob-install.sh not idempotent
Templates12FullNone
Provision manifests15FullNone
Global settings1PartialAbsolute paths, no update mechanism
Project settingsautoPartialTemplate embedded in cdi script
Machine settings1Non-compliantStale, no generation mechanism
Runbooks4PartialManual steps that could be automated

Principle Assessment

Declarativity: 85%

Most state is JSON or markdown. Gaps:

  • Project settings.json template embedded in claude-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.json is gitignored (by design, but stale)
  • Machine-specific overrides not tracked

Reproducibility: 70%

Fresh installs work well. Gaps on incremental:

  • cdi prompts 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.sh fails if already installed
  • Idempotency not explicitly documented on most scripts
  • Git hook installation uses copy + diff (fragile)

Portability: 65%

Main blocker:

  • settings.json hooks 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)
  • --diff shows only actual changes needed
  • Running provision twice produces identical state
  • Verdict: provisioning is fully idempotent

Fix Issues Filed

GapIssuePriority
GAP-1: Hook path portability#49p3-medium
GAP-2: Git hook symlinks#52p3-medium
GAP-3: Settings template#50p3-medium
GAP-7: bob-install.sh#51p4-low
Pre-existing: Dangling symlinks#44p2-high

Gaps 4–6 and 8 are lower priority and tracked as notes in this audit rather than separate issues.