Playbook: Repo Consistency Audit
When to run
- After onboarding a new repo (verify
new-repo-setup.mdchecklist 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
| Repo | Local clone | Stack |
|---|---|---|
radieu/p24-infra | C:\code_2026\p24-infra | DevOps / infra |
radieu/et-operational-platform | d:\code_2026\et-oper\et-operational-platform | Next.js |
radieu/Art-Agency | C:\code_2026\Art-Agency | Next.js |
p24-infra/brandpilot | C:\code_2026\brandpilot\brandpilot | Next.js (org: p24-infra, not radieu) |
radieu/whatsup-android-chat-puller | C:\code_2026\whatsup-android-chat-puller | Kotlin + Python |
radieu/radekkonarski-personal-brand | C:\code_2026\radekkonarski-personal-brand | Content / n8n |
radieu/amazon-kdp-tango | d:\code_2026\amazon-kdp-tango | Python 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 .gitattributesmissing or noeol=lf— CRLF corruption risk for shell scripts and SOPS files on Windowssettings.local.jsoninstead ofsettings.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 tomain - Default branch
mainin app repos — p24-infra workflow expectsdevas 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>$nullAdd 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 masterFindings snapshot — 2026-06-28
| Repo | settings.json | sr.md | commit.md | create-pr.md | gitattributes | default branch | label gaps | milestone issues |
|---|---|---|---|---|---|---|---|---|
| p24-infra | ✅ | ✅ | ✅ | ✅ | ✅ | main (by design) | plan, queued, ai-review-queued | none |
| et-operational-platform | ✅ | ✅ | ✅ | ✅ | ❌ | main | plan, human-action, queued, ai-review-queued | many legacy + duplicates |
| Art-Agency | ❌ (has settings.local.json) | ✅ | ✅ | ✅ | ❌ | main | plan, queued, ai-review-queued | corruption: “System.Collections.Hashtable.title” milestone |
| brandpilot | ✅ | ❌ | ✅ | ✅ | ❌ | ? | plan, queued, ai-review-queued | unknown |
| whatsup-android-chat-puller | ✅ | ✅ | ✅ | ✅ | ❌ | dev ✅ | ai-review-queued | none |
| radekkonarski-personal-brand | ✅ | ❌ | ❌ | ❌ | ✅ | main | plan, queued, ai-review-queued | none |
| amazon-kdp-tango | ✅ | ❌ | ❌ | ❌ | ❌ | master ❌ | plan, human-action, queued, ai-review-queued | only has “RC” |
Priority fix list (from findings)
P1 — Critical:
Art-Agency: renamesettings.local.json→settings.json(commit it) — or create fresh settings.json
P2 — Warn, blocks skills:
brandpilot: addsr.mdradekkonarski-personal-brand: addsr.md,commit.md,create-pr.mdamazon-kdp-tango: addsr.md,commit.md,create-pr.md
P2 — Data bugs:
et-operational-platform: close/delete legacy milestones (triageduplicate,To Review,Done,Blocked,pending-for-ai,ai-processing,rc-testing,Dev,human-todo,rc1,RC)Art-Agency: delete corruptedSystem.Collections.Hashtable.titlemilestone
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
.gitattributeswith LF rule amazon-kdp-tango: rename default branchmaster→main; add full standard milestone setet-operational-platform,Art-Agency,radekkonarski-personal-brand: set default branch todev
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.