Playbook: Repo Consistency Audit

When to run

  • After onboarding a new repo (verify new-repo-setup.md checklist was fully completed)
  • Monthly — first Monday of the month
  • After any bulk change to .claude/ infrastructure in p24-infra (settings/commands template change)
  • When a Claude session reports “missing skill” or permission errors in a project VS Code window

Repos in scope

RepoLocal cloneStack
radieu/p24-infraC:\code_2026\p24-infraDevOps / infra
radieu/et-operational-platformd:\code_2026\et-oper\et-operational-platformNext.js
radieu/Art-AgencyC:\code_2026\Art-AgencyNext.js
p24-infra/brandpilotC:\code_2026\brandpilot\brandpilotNext.js (org: p24-infra, not radieu)
radieu/whatsup-android-chat-pullerC:\code_2026\whatsup-android-chat-pullerKotlin + Python
radieu/radekkonarski-personal-brandC:\code_2026\radekkonarski-personal-brandContent / n8n
radieu/amazon-kdp-tangod:\code_2026\amazon-kdp-tangoPython CLI

Audit script

Run this entire block in PowerShell to get a full snapshot:

$repos = @(
  @{ name="p24-infra";                    path="C:\code_2026\p24-infra";                                  gh="radieu/p24-infra" },
  @{ name="et-operational-platform";      path="d:\code_2026\et-oper\et-operational-platform";            gh="radieu/et-operational-platform" },
  @{ name="Art-Agency";                   path="C:\code_2026\Art-Agency";                                 gh="radieu/Art-Agency" },
  @{ name="brandpilot";                   path="C:\code_2026\brandpilot\brandpilot";                      gh="radieu/brandpilot" },
  @{ name="whatsup-android-chat-puller";  path="C:\code_2026\whatsup-android-chat-puller";                gh="radieu/whatsup-android-chat-puller" },
  @{ name="radekkonarski-personal-brand"; path="C:\code_2026\radekkonarski-personal-brand";               gh="radieu/radekkonarski-personal-brand" },
  @{ name="amazon-kdp-tango";             path="d:\code_2026\amazon-kdp-tango";                           gh="radieu/amazon-kdp-tango" }
)
 
$REQUIRED_LABELS  = @("bug","enhancement","plan","human-action","queued","ai-review-queued","ai-review-rejected","patch")
$REQUIRED_MILESTONES = @("Triage","Design","In Progress","Review","Staging","Main")
$REQUIRED_COMMANDS = @("sr.md","commit.md","create-pr.md")
 
foreach ($r in $repos) {
  $p = $r.path
  Write-Host "`n=== $($r.name) ===" -ForegroundColor Cyan
 
  # --- LOCAL CHECKS ---
  $settingsJson     = Test-Path "$p\.claude\settings.json"
  $settingsLocal    = Test-Path "$p\.claude\settings.local.json"
  $claudeMd         = Test-Path "$p\CLAUDE.md"
  $gitattributes    = Test-Path "$p\.gitattributes"
  $hasSopsLfRule    = if ($gitattributes) { (Get-Content "$p\.gitattributes") -match "eol=lf" } else { $false }
  $cmdDir           = "$p\.claude\commands"
  $commands         = if (Test-Path $cmdDir) { (Get-ChildItem $cmdDir -Filter "*.md").Name } else { @() }
 
  if (-not $settingsJson)  { Write-Host "  [CRITICAL] .claude/settings.json MISSING" -ForegroundColor Red }
  if ($settingsLocal -and -not $settingsJson) { Write-Host "  [WARN]     has settings.local.json but not settings.json — not committed, agents get no auto-approvals" -ForegroundColor Yellow }
  if (-not $claudeMd)      { Write-Host "  [CRITICAL] CLAUDE.md MISSING" -ForegroundColor Red }
  if (-not $gitattributes) { Write-Host "  [WARN]     .gitattributes MISSING (risk: CRLF in scripts/SOPS files)" -ForegroundColor Yellow }
  elseif (-not $hasSopsLfRule) { Write-Host "  [WARN]     .gitattributes exists but no eol=lf rule" -ForegroundColor Yellow }
 
  foreach ($cmd in $REQUIRED_COMMANDS) {
    if ($commands -notcontains $cmd) {
      Write-Host "  [WARN]     .claude/commands/$cmd MISSING — /$(($cmd -replace '\.md$','')) unavailable in VS Code" -ForegroundColor Yellow
    }
  }
  if ($commands.Count -gt 0) { Write-Host "  [OK]       $($commands.Count) commands: $($commands -join ', ')" -ForegroundColor Green }
 
  # --- GITHUB CHECKS ---
  $defaultBranch = gh repo view $r.gh --json defaultBranchRef --jq ".defaultBranchRef.name" 2>$null
  $labels        = gh label list --repo $r.gh --json name --jq "[.[].name]" 2>$null | ConvertFrom-Json
  $milestones    = gh api "repos/$($r.gh)/milestones?state=all&per_page=50" --jq "[.[].title]" 2>$null | ConvertFrom-Json
 
  if ($defaultBranch -eq "master") { Write-Host "  [WARN]     default branch is 'master' — should be 'main' or 'dev'" -ForegroundColor Yellow }
  elseif ($defaultBranch -eq "main" -and $r.name -ne "p24-infra") { Write-Host "  [INFO]     default branch is 'main' (consider 'dev' for PR-first workflow)" -ForegroundColor DarkYellow }
 
  foreach ($lbl in $REQUIRED_LABELS) {
    if ($labels -notcontains $lbl) { Write-Host "  [WARN]     label '$lbl' MISSING" -ForegroundColor Yellow }
  }
 
  foreach ($ms in $REQUIRED_MILESTONES) {
    if ($milestones -notcontains $ms) { Write-Host "  [WARN]     milestone '$ms' MISSING" -ForegroundColor Yellow }
  }
 
  # Detect duplicate/legacy milestones
  $dupes = $milestones | Group-Object { $_.ToLower() } | Where-Object { $_.Count -gt 1 }
  foreach ($d in $dupes) { Write-Host "  [BUG]      duplicate milestones (case): $($d.Group -join ', ')" -ForegroundColor Red }
 
  $legacyMs = $milestones | Where-Object { $_ -in @("triage","To Review","Done","Dev","Blocked","pending-for-ai","ai-processing","rc-testing","human-todo","RC","rc1","RC1") }
  foreach ($lm in $legacyMs) { Write-Host "  [INFO]     legacy/non-standard milestone: '$lm'" -ForegroundColor DarkYellow }
}

Gap taxonomy

CRITICAL — blocks agent operation

  • Missing CLAUDE.md — agent has no project context; will hallucinate conventions
  • Missing .claude/settings.json — every tool call prompts; skills fail mid-execution

WARN — degrades developer experience

  • Missing required command (sr.md, commit.md, create-pr.md) — skill unavailable in VS Code
  • Missing standard label — issue pipeline skills fail or silently skip labelling
  • Missing standard milestone — create-pr.md / worker fails to set milestone
  • .gitattributes missing or no eol=lf — CRLF corruption risk for shell scripts and SOPS files on Windows
  • settings.local.json instead of settings.json — un-committed; new clones / CI agents have no auto-approvals

BUG — data corruption

  • Duplicate milestones (case-variant e.g. triage + Triage) — worker scripts that match by name will hit wrong milestone

INFO — tech debt

  • Default branch master — old convention; rename to main
  • Default branch main in app repos — p24-infra workflow expects dev as integration branch for PRs
  • Legacy milestones left over from old pipeline versions

Remediation quick-reference

Add missing .claude/settings.json

See docs/playbooks/new-repo-setup.md §Step 5b — copy template, adjust stack-specific entries.

Add missing command

$target = "C:\code_2026\<repo>\.claude\commands"
Copy-Item "C:\code_2026\p24-infra\.claude\commands\sr.md"     "$target\sr.md"
Copy-Item "C:\code_2026\p24-infra\.claude\commands\commit.md" "$target\commit.md"
# create-pr.md: use p24-infra version only if repo uses the same Projects board
# otherwise use whatsup-android-chat-puller version as template
Copy-Item "C:\code_2026\whatsup-android-chat-puller\.claude\commands\create-pr.md" "$target\create-pr.md"

Add missing label

$repo = "radieu/<repo>"
gh label create "plan"              --repo $repo --color "5319E7" --description "Design/planning issue"
gh label create "human-action"      --repo $repo --color "fbca04" --description "Waiting for human decision or action"
gh label create "queued"            --repo $repo --color "0e8a16" --description "Queued for implementation"
gh label create "ai-review-queued"  --repo $repo --color "0075ca" --description "PR queued for AI auto-review"
gh label create "ai-review-rejected" --repo $repo --color "d93f0b" --description "PR rejected by AI review"
gh label create "patch"             --repo $repo --color "e4e669" --description "Small fix or tweak"

Add missing standard milestones

$repo = "radieu/<repo>"
foreach ($ms in @("Triage","Design","In Progress","Review","Staging","Main")) {
  gh api "repos/$repo/milestones" -X POST -f title="$ms" 2>$null | Out-Null
}

Fix duplicate milestones

# List all, close the lower-case/legacy duplicate manually (cannot delete milestones via gh cli — use API)
$repo = "radieu/<repo>"
$dup = gh api "repos/$repo/milestones?state=all" --jq "[.[] | select(.title == \"triage\")] | .[].number" 2>$null
gh api "repos/$repo/milestones/$dup" -X PATCH -f state=closed 2>$null

Add gitattributes LF rule

$path = "C:\code_2026\<repo>"
$rule = "`n# Force LF for shell scripts and SOPS files`n*.sh text eol=lf`nsecrets/*.env.sops text eol=lf`n"
[System.IO.File]::WriteAllText("$path\.gitattributes",
  (Get-Content "$path\.gitattributes" -Raw -ErrorAction SilentlyContinue) + $rule,
  [System.Text.UTF8Encoding]::new($false))

Rename default branch master → main

$repo = "radieu/<repo>"
$local = "d:\code_2026\<repo>"
git -C $local checkout -b main master
git -C $local push origin main
gh api "repos/$repo" -X PATCH -f default_branch=main
git -C $local push origin --delete master

Findings snapshot — 2026-06-28

Reposettings.jsonsr.mdcommit.mdcreate-pr.mdgitattributesdefault branchlabel gapsmilestone issues
p24-inframain (by design)plan, queued, ai-review-queuednone
et-operational-platformmainplan, human-action, queued, ai-review-queuedmany legacy + duplicates
Art-Agency❌ (has settings.local.json)mainplan, queued, ai-review-queuedcorruption: “System.Collections.Hashtable.title” milestone
brandpilot?plan, queued, ai-review-queuedunknown
whatsup-android-chat-pullerdev ✅ai-review-queuednone
radekkonarski-personal-brandmainplan, queued, ai-review-queuednone
amazon-kdp-tangomaster ❌plan, human-action, queued, ai-review-queuedonly has “RC”

Priority fix list (from findings)

P1 — Critical:

  • Art-Agency: rename settings.local.jsonsettings.json (commit it) — or create fresh settings.json

P2 — Warn, blocks skills:

  • brandpilot: add sr.md
  • radekkonarski-personal-brand: add sr.md, commit.md, create-pr.md
  • amazon-kdp-tango: add sr.md, commit.md, create-pr.md

P2 — Data bugs:

  • et-operational-platform: close/delete legacy milestones (triage duplicate, To Review, Done, Blocked, pending-for-ai, ai-processing, rc-testing, Dev, human-todo, rc1, RC)
  • Art-Agency: delete corrupted System.Collections.Hashtable.title milestone

P3 — Standards:

  • All repos except p24-infra + whatsup: add standard labels (plan, queued, ai-review-queued, ai-review-rejected, patch)
  • All repos except p24-infra + radekkonarski-brand: add .gitattributes with LF rule
  • amazon-kdp-tango: rename default branch mastermain; add full standard milestone set
  • et-operational-platform, Art-Agency, radekkonarski-personal-brand: set default branch to dev

Escalation

If audit script fails with authentication error: gh auth status — ensure authenticated as radieu. If milestone deletion fails via API: delete manually in GitHub Settings → Milestones. If .gitattributes change triggers unexpected diffs: run git add --renormalize . once and commit.