Capstone Radar
SkillAI & modelsUnified A-F grading and ship/no-ship decisions for the 6-skill radar family (5 companions + capstone). Aggregates handoffs from data-model, ui-path, roundtrip, time-bomb, and ui-enhancer; owns 5 grep-reliable domains; tracks velocity; celebrates improvements. Triggers: "capstone radar", "can I ship", "grade codebase", "/capstone-radar".
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Capstone Radar skill
What this skill tells your AI
The instructions your AI receives, as published by terryc21/radar-suite in skills/capstone-radar/SKILL.md and read by ahel’s review.
Capstone Radar is the aggregator + gap filler for the 6-skill radar family (5 companions + capstone). It consumes findings from 5 companion skills, runs its own scans for 5 domains the companions don't cover, grades everything on one unified scale, and makes the ship/no-ship decision.
It does NOT:
- Re-scan domains already covered by companion skills
- Dispatch Axiom auditor agents
- Produce separate reports for domains companions already cover
Usage
| Command | Description |
|---|---|
/capstone-radar | Full analysis — checks everything and reads companion handoffs |
/capstone-radar quick | Quick check — own domains only, ignores companion results |
/capstone-radar report | No scanning, re-grade from existing handoff files only |
/capstone-radar diff | Compare against previous audit — show resolved/new issues |
--trust-all | Override staleness decay -- treat all companion handoffs as Fresh |
--show-suppressed | Show findings suppressed by known-intentional entries |
Diff Command
Audit comparison — compare current codebase against a previous audit to show what changed.
Usage
/capstone-radar diff
/capstone-radar diff 2026-03-15
How It Works
- Find previous audit — Read the most recent (or specified date)
.agents/research/*-capstone-audit.md - Parse previous findings — Extract all issues from the GRADES_YAML block and findings tables
- Re-check each finding:
- Read the file at the reported line number
- Check if the problematic pattern still exists
- Classify as: ✅ RESOLVED, 🔴 STILL OPEN, 📁 FILE CHANGED
- Scan for new issues — Quick grep scan for new violations not in previous report
- Output diff summary
Output Format
Audit Diff: 2026-03-15 → 2026-03-29
Summary:
✅ Resolved: 8 issues fixed since last audit
🔴 Still Open: 3 issues remain
🆕 New: 2 new issues detected
📁 Changed: 4 files modified (may need re-verification)
Grade Trend:
Overall: B [83] → B+ [87] ↑
Code Hygiene: B- → A- ↑
Security Basics: A → A (stable)
Test Health: C → C+ ↑
Resolved Issues:
| # | Finding | Was | File | Resolved By |
|---|---------|-----|------|-------------|
| 1 | TODO marker in production | 🟡 HIGH | CloudSyncManager.swift:142 | Commit abc123 |
Still Open:
| # | Finding | Urgency | File | Age |
|---|---------|---------|------|-----|
| 1 | Force unwrap in error path | 🟡 HIGH | BackupManager.swift:89 | 14 days |
New Issues:
| # | Finding | Urgency | Risk: Fix | Risk: No Fix | ROI | Blast Radius | Fix Effort | Status |
When to Use
- Pre-release check — "What's changed since our last audit?"
- Progress tracking — Verify issues are being resolved over time
- Regression detection — Catch new issues introduced since last audit
Velocity Tracking
If 3+ previous audits exist, show trend line:
Grade Velocity (last 5 audits):
Build 21: C+ [78]
Build 22: B- [80]
Build 23: B [84]
Build 24: B+ [87]
Build 25: B+ [88] ← current
Trend: Improving (+2.5 pts/build avg)
Projection: A- by Build 28 at current rate
Skill Introduction (MANDATORY — run before anything else)
On first invocation, ask the user three questions in a single AskUserQuestion call:
Question 1: "What's your experience level with Swift/SwiftUI?"
- Beginner — New to Swift. Plain language, analogies, define terms on first use.
- Intermediate — Comfortable with SwiftUI basics. Standard terms, explain non-obvious patterns.
- Experienced (Recommended) — Fluent with SwiftUI. Concise findings, no definitions.
- Senior/Expert — Deep expertise. Terse, file:line only, skip explanations.
Question 2: "Which audit mode?"
- Full (Recommended) — Full analysis — checks everything and reads findings from other audits you've run
- Quick — Quick check — only looks at its own areas, ignores other audit results
- Report only — No scanning, just re-grade from existing handoff files
Question 3: "Include user impact explanations?"
- No (default) — Table only. Findings speak for themselves.
- Yes — After the table, each finding gets a 3-line explanation: what's wrong, the fix, and how a user experiences it before/after.
Can also be toggled mid-session with --explain / --no-explain. See radar-suite-core.md § Experience-Level Output Rules for format and rules.
Experience-adapted explanations for Capstone Radar:
-
Beginner: "Capstone Radar is the final check before your app goes to the App Store. It combines results from 5 other audit tools (if you've run them) with its own security, testing, and code quality checks, then gives your whole app a letter grade and tells you if it's safe to ship. Think of it as the building inspector who reviews all the specialist reports plus checks the things no one else covered."
-
Intermediate: "Capstone Radar aggregates findings from 5 companion skills (data-model-radar, ui-path-radar, roundtrip-radar, ui-enhancer-radar, time-bomb-radar) and adds its own scans for security, test health, code hygiene, dependencies, and build health. It grades 11 weighted inputs on one scale (5 own + 5 consumed + 1 cross-domain synthesis), tracks trends across runs, and makes a ship/no-ship recommendation."
-
Experienced: "Aggregator + gap filler for the radar family. Consumes 5 companion handoffs, owns 5 grep-reliable domains, unified A-F grading across 11 weighted inputs, velocity tracking, risk heatmap, ship/no-ship decision."
-
Senior/Expert: "5 owned + 5 consumed + 1 cross-domain = 11 weighted domains. Velocity. Heatmap. Ship/no-ship."
Store the experience level as USER_EXPERIENCE and apply to ALL output for the session.
Shared Patterns
See radar-suite-core.md for: Tier System, Pipeline UX Enhancements, Table Format, Plain Language Communication, Work Receipts, Contradiction Detection, Finding Classification, Audit Methodology, Context Exhaustion, Progress Banner, Issue Rating Tables, Handoff YAML schema, Known-Intentional Suppression, Pattern Reintroduction Detection, Experience-Level Output Rules, Implementation Sort Algorithm, short_title requirement.
Tier Awareness (MANDATORY -- read before any scanning)
Read .radar-suite/session-prefs.yaml for the tier field. Capstone behavior adapts based on the active tier:
Tier 3 (Full Pipeline)
All 5 companion skills are expected. If a handoff is missing, treat it as an error (not "not audited"):
ERROR: data-model-radar handoff missing. Full pipeline requires all 5 companions.
Options: [Re-run data-model-radar / Continue without it (grade will be partial)]
Before starting own scans, emit the Pre-Capstone Summary (see radar-suite-core.md Pipeline UX Enhancements #5):
- Read all 5 handoff files
- Emit the consolidated findings table (skill, count, critical/high/medium/low breakdown)
- Show top findings by urgency with
RS-NNN (short_title) - Ask: "Review summary before capstone grading? [Enter to continue / Review details]"
Tier 2 (Targeted Pipeline)
Read tier_skills from session prefs to know which skills were in the subset. Only expect handoffs for those skills. For skills not in the subset:
- Mark as "not in scope" (not "not audited")
- Grade is scoped to audited domains only
- Emit: "Partial audit: [N] of 5 skills ran. Grade reflects audited domains only. Missing coverage: [list of excluded skills]."
Weight redistribution: redistribute missing domain weights proportionally to audited domains (same as existing missing-handoff logic).
Tier 1 / No Tier / Standalone
Existing behavior. Missing handoffs show "Not audited -- run [skill-name] for coverage."
Pre-Scan Startup (MANDATORY — before Step 1)
-
Known-intentional suppression: Run the protocol in
radar-suite-core.md § Known-Intentional Suppression. Core owns this — do not restate the steps here. (Note: companion findings already excluded at the companion level; capstone only filters its own domain scans through this protocol.) -
Pattern reintroduction detection: Run the protocol in
radar-suite-core.md § Pattern Reintroduction Detection. Core owns this. -
Experience-level auto-apply (capstone-radar local): If
USER_EXPERIENCE= Beginner, auto-setEXPLAIN_FINDINGS = trueand default sort toimpact. If Senior/Expert, default sort toeffort. Apply all output rules fromradar-suite-core.md § Experience-Level Output Rules.
Step 1: Project Metrics
Collect:
- File counts —
Glob pattern="**/*.swift"(exclude Tests, Pods, .build, DerivedData) - LOC estimate — file count x 150, or
wc -lfor accuracy - Architecture — detect MVVM/MVC/TCA by scanning for ViewModel, Controller, Reducer
- Persistence layer — SwiftData, Core Data, GRDB, UserDefaults, Realm
- Test infrastructure — Swift Testing vs XCTest, unit test count, UI test count
- Build number — read from CLAUDE.md (search for "Current Version" or build number), or from Info.plist
- Team detection —
git shortlog -sn --no-merges | wc -l. Store asTEAM_SIZE.
Ensure output directories exist: mkdir -p .agents/research .agents/ui-audit
Print one-line summary:
Project: {files} Swift files (~{loc} LOC) | {arch} | {persistence} | Tests: {unit}/{ui} | Build: {number} | Contributors: {count}
Step 2: Previous Audit Check
Glob pattern=".agents/research/*-capstone-audit.md"
Glob pattern=".agents/research/*-codebase-audit.md"
If previous reports exist, parse ALL GRADES_YAML HTML comment blocks for velocity tracking. Build an array of dated snapshots sorted by date. Store as HISTORY.
Step 3: Companion Handoff Consumption (Tier-Aware)
Read the unified ledger and handoff files. Which files to read depends on the active tier (see Tier Awareness above). In Tier 2, read only handoffs for skills listed in tier_skills. In Tier 3, read all 5. In Tier 1/standalone, read whatever exists.
Read .radar-suite/ledger.yaml (if exists) — unified cross-skill finding store
Read .agents/ui-audit/data-model-radar-handoff.yaml (if exists)
Read .radar-suite/time-bomb-radar-handoff.yaml (if exists)
Read .agents/ui-audit/ui-path-radar-handoff.yaml (if exists)
Read .agents/ui-audit/roundtrip-radar-handoff.yaml (if exists)
Read .agents/ui-audit/ui-enhancer-radar-handoff.yaml (if exists)
Ledger integration: When the ledger exists, use it as the primary source of cross-skill findings. Handoff YAMLs provide per-skill detail (serialization coverage, cross-cutting patterns) that the ledger doesn't store. Capstone should reference findings by RS-NNN ID when available.
For each handoff found:
- Parse
for_capstone_radar.blockers[]— extractfindingandurgency(CRITICAL or HIGH) - Backward compat: Also accept
for_release_ready_radar.blockers[]key - Parse companion-specific extras:
- data-model-radar:
serialization_coverage(model field coverage stats) - roundtrip-radar:
cross_cutting_patterns[](patterns affecting multiple workflows)
- data-model-radar:
- Record which companions were found vs missing
Score consumed domains: Start at 95 (generous baseline — companion ran a full audit and only escalated the worst items). Deduct:
- Per CRITICAL blocker: -15
- Per HIGH blocker: -8
- Floor at 0
Missing handoffs (tier-dependent messaging):
- Tier 3: "ERROR: [skill] handoff missing. Full pipeline requires all 5 companions." (see Tier Awareness)
- Tier 2: If skill was in
tier_skills, treat as error. If not, mark "Not in scope" (expected absence). - Tier 1 / standalone: "Not audited -- run [skill-name] for coverage."
In all cases, weight is redistributed proportionally to audited domains.
Print companion status:
Companions: data-model-radar [found/missing] | ui-path-radar [found/missing] | roundtrip-radar [found/missing] | time-bomb-radar [found/missing] | ui-enhancer-radar [found/missing]
Skip this step if mode = Quick.
Companion Handoff Quality Assessment
When a companion handoff is found, check its audit_depth and _verified flags (if present):
audit_depth: full+ all targets_verified: true→ Full credit (start at 95, deduct per blocker)audit_depth: partialor some targets_verified: false→ Reduced credit (start at 85, deduct per blocker). Note in report: "Partial audit — [domain] grade is provisional."- No depth/verified flags (older handoff format) → Treat as partial. Note: "Handoff from older skill version — depth not verified."
Do not give full credit for unverified companion work. A handoff that says "backup verified, CSV not checked" should not produce an A for the Model Layer domain. The unverified targets represent unknown risk.
Companion Handoff Staleness Decay
After assessing quality, calculate staleness for each companion handoff:
staleness_score = (days_since_handoff * 0.3) + (commits_since_handoff * 0.1)
Where:
days_since_handoff= calendar days since the handoff'stimestampfieldcommits_since_handoff= output ofgit rev-list --count <handoff_commit>..HEAD(usegit log --oneline --since="<timestamp>"if commit hash unavailable)
| Score | Label | Behavior |
|---|---|---|
| 0-2 | Fresh | Full trust -- use handoff as-is |
| 2-5 | Aging | Trust grades, but spot-check HIGH findings (read the file, verify pattern still exists) |
| 5-10 | Stale | Downgrade companion grades by one letter. Spot-check all CRITICAL + HIGH findings. |
| 10+ | Expired | Ignore handoff entirely. Recommend re-running the companion skill. |
Freshness summary (print in companion status output):
Companion freshness:
data-model-radar: Fresh (1 day, 3 commits)
ui-path-radar: Aging (8 days, 12 commits)
roundtrip-radar: Stale (22 days, 47 commits) — grades downgraded by one letter
time-bomb-radar: Fresh (2 days, 5 commits)
ui-enhancer-radar: Expired (35 days, 89 commits) — handoff ignored, re-run recommended
Spot-check protocol (for Aging and Stale handoffs):
- Read the finding's file at the cited line range
- Check if the pattern still exists (grep the finding's work receipt pattern if available)
- If pattern gone → mark finding as
possibly-resolved (stale handoff)and exclude from grade calculation - If pattern still present → mark as
re-verifiedand keep the finding
--trust-all flag: Overrides staleness calculation. All companions treated as Fresh regardless of age. Use when you know nothing has changed since the last audit.
Stale/Expired companions are flagged in the "Next Steps" section of the report.
Step 3.5: Axis Classification Consumption (MANDATORY — after companion handoffs, before risk-ranking)
New in v1.1 (axis framework). Every companion handoff now includes an
axis_summaryblock and every finding includes anaxisfield. Capstone splits findings by axis before grading: only axis_1 findings count toward the A-F grade. axis_2 and axis_3 findings land in a separate Hygiene Backlog section.
What to read
For each companion handoff found in Step 3, read:
axis_summary(top-level block) — counts by axischecks_performed(top-level block) — what the companion scannedaxis(per-finding field) — classification for each findingbefore_after_experience.audience(per-finding field) — surface in the report
What to do
-
Split findings by axis into two buckets:
- fix_before_shipping — all findings where
axis == axis_1_bug - hygiene_backlog — all findings where
axis in (axis_2_scatter, axis_3_dead_code, axis_3_smelly)
- fix_before_shipping — all findings where
-
Verify schema gate compliance. For each finding in either bucket, confirm it has:
- A non-empty
better_approachfield - A file:line citation matching regex
[A-Za-z0-9_/+.-]+\.swift:\d+in thebetter_approachbody - A
pattern_citation_lookupentry inverification_log - A
before_after_experiencewithaudienceset
Findings failing the gate are still displayed but are tagged
coaching incompleteand excluded from the top-10 prioritized list. This makes bad coaching visible rather than silently dropped. - A non-empty
-
Aggregate
checks_performedacross all companions into a single "Audit Coverage" block:Audit Coverage: source_roots: Sources/ files scanned: 588 (ui-path), 588 (roundtrip), 120 (capstone own) patterns ran: reachability_trace, whole_file_scan, branch_enumeration, pattern_citation_lookup patterns skipped: source_root_introspection (single-root project) -
Count
rejected_no_citationacross all handoffs. If any radar rejected findings at the gate, surface this prominently — it means the radar had candidate findings it could not coach.
Grade impact rule (CRITICAL)
Only axis_1_bug findings affect the A-F grade. axis_2 and axis_3 findings are NOT counted for grading. The grade cap rules from radar-suite-core.md apply only to axis_1 findings:
- CRITICAL axis_1 findings cap grade at C
- HIGH axis_1 findings cap grade at B+
A codebase with 0 axis_1 findings but 50 axis_2 findings can still grade A. Hygiene debt does not block shipping.
Backward compatibility
Handoffs from older radar versions (pre-v1.1) lack the axis_summary block and the per-finding axis field. For these:
- Treat all findings as
axis_1_bug(the pre-v1.1 default behavior) - Note in the "Audit Coverage" section:
"ui-enhancer-radar handoff is pre-axis (v1.0.x); all findings counted as axis_1" - Do not retroactively infer axis; old handoffs are preserved as-is
Step 3.6: Risk-Ranking (MANDATORY — before own domain scans)
Before running grep patterns, determine where to go deep vs quick. The default behavior is to run all grep patterns with equal effort — but some domains have more risk than others based on context.
Check These Signals
Signal 1: Prior findings.
Read HISTORY from Step 2. If previous audits scored a domain below B, go deep on verification for that domain this time. Also check memory for known issues (e.g., prior session found test health concerns → verify test patterns more carefully).
Signal 2: Companion handoff gaps. If a companion handoff flagged issues that touch an owned domain (e.g., data-model-radar found security-relevant patterns), escalate that owned domain to deep verification.
Signal 3: Codebase size signals. If Step 1 found >500 Swift files, Security Basics grep will produce many candidates. Plan for heavier verification time on that domain. If test-to-source ratio is below 0.2, Test Health needs deep investigation, not just file counting.
Risk-Ranking Output
Before Step 4, print:
Risk Ranking for Own Domains:
DEEP VERIFY:
- [domain] (reason: [signal])
- [domain] (reason: [signal])
STANDARD:
- [domain]
- [domain]
LOW RISK:
- [domain]
Deep verify means: read every grep candidate in context (20+ lines), classify each as CONFIRMED/FALSE_POSITIVE/INTENTIONAL. Don't report counts — report classified findings.
Standard means: read a sample of grep candidates (top 5 per pattern), classify those, extrapolate. Label as (sampled) in the report.
Low risk means: report counts with spot-check of top 3 candidates. Label as (spot-checked) in the report.
Step 4: Own Domain Scans
Run grep-based scans for the 5 domains capstone owns. Apply Verification Rule (Step 5) to every hit. Follow the risk-ranking from Step 3.6 — deep-verify domains go first and get full candidate classification.
Shared Grep Patterns
Code Hygiene grep-sufficient:
Grep pattern="// TODO|// FIXME|// HACK|// XXX" glob="**/*.swift" output_mode="count"
Grep pattern="as!" glob="**/*.swift"
Grep pattern="try!" glob="**/*.swift"
Also check file sizes: Glob pattern="**/*.swift" then read line counts for files that appear large. Flag files >1000 lines.
Test Health grep-sufficient:
Grep pattern="import Testing" glob="**/*Test*.swift" output_mode="count"
Grep pattern="import XCTest" glob="**/*Test*.swift" output_mode="count"
Grep pattern="Thread\.sleep|sleep\(" glob="**/*Test*.swift"
Glob pattern="**/*Tests.swift"
Glob pattern="**/*Test.swift"
Calculate test-to-source ratio: test files / (total swift files - test files).
Security Basics grep-sufficient:
Grep pattern="(api[_-]?key|secret[_-]?key|password|token)\s*[:=]\s*[\"'][^\"']+[\"']" glob="**/*.swift" -i
Grep pattern="UserDefaults.*\.(password|token|secret|apiKey)" glob="**/*.swift" -i
Grep pattern="http://(?!localhost|127\.0\.0\.1)" glob="**/*.swift"
Dependency Health grep-sufficient:
stat -f "%Sm" -t "%Y-%m-%d" Package.resolved 2>/dev/null || echo "no Package.resolved"
Grep pattern="\.exact\(|\.upToNextMajor\(|\.upToNextMinor\(|from:" path="Package.swift" output_mode="content"
Count packages in Package.resolved.
Build Health grep-sufficient:
find . -name "*.xcscheme" -not -path "*/.build/*" | wc -l
Grep pattern="targets?:" path="Package.swift" output_mode="content"
Verification Template (MANDATORY for own domain scans)
Before grading each owned domain, produce this table:
| Pattern | Grep Run? | Hits | Classified | Confirmed | False Positive | Receipt |
|---------|-----------|------|------------|-----------|----------------|---------|
| TODO/FIXME | ? | | | | | |
| try! | ? | | | | | |
| as! | ? | | | | | |
| hardcoded secrets | ? | | | | | |
| http:// URLs | ? | | | | | |
Rules:
- Every pattern in the scan list must appear in this table
?means the grep wasn't run yet — cannot grade until all are filled- Hits ≠ Findings. Every hit must be classified (Confirmed / False Positive / Intentional)
- The grade comes from Confirmed count, not Hits count
- If Hits > 0 but Classified = 0, the domain was not actually audited
Per-Domain Scoring
Start at 100 points. Deduct per CONFIRMED finding:
| Severity | HIGH Conf | MED Conf | LOW Conf |
|---|---|---|---|
| CRITICAL | -15 | -10 | -3 |
| HIGH | -8 | -5 | -1 |
| MEDIUM | -3 | -2 | 0 |
| LOW | -1 | -1 | 0 |
Step 5: Verification Rule
Grep patterns produce candidates, NOT confirmed issues. Before reporting:
- Read the flagged file — minimum 20 lines of context
- Check structural context — pattern may be safe in its actual scope
- Classify: CONFIRMED, FALSE_POSITIVE, or INTENTIONAL
- Never report grep counts as issue counts — classify each hit
- Only CONFIRMED findings appear in the report
Common false positives:
try!in test setup code — acceptable in testshttp://in XML namespaces or comments — not an endpointsleep()in test helpers for async settling — may be intentionalTODOmarkers that reference completed work — stale commentsas!in exhaustive switch cases — compiler-guaranteed safe- Hardcoded "password" in UI label strings — not a credential
Step 6: Cross-Domain Correlation
6.1 Risk Heatmap by File
Collect ALL file paths from ALL findings (own 5 domains + companion handoffs). Count domain appearances per file. Report files appearing in 3+ domains:
Risk Heatmap — Files with findings in 3+ domains:
{file1} — {domain1}, {domain2}, {domain3} ({N} domains)
{file2} — {domain1}, {domain2}, {domain3} ({N} domains)
These {N} files account for {X}% of all findings.
6.2 Team Enrichment
If TEAM_SIZE > 1:
- For each heatmap file, run
git log --format="%an" --since="30 days ago" -- {file} | sort -uto find recent contributors - Add ownership info:
{file} — {N} domains, {M} contributors this month, {owner or "no clear owner"}
6.3 Cross-Cutting Patterns
If roundtrip-radar handoff includes cross_cutting_patterns[], incorporate them. Flag patterns that affect 3+ workflows.
Step 6.5: Dependency Graph Construction
Shortened here. Read the whole file on GitHub.
Signals
- GitHub stars
- 20
- Forks
- 1
- Last commit
- Aug 2026
ahel review
K1binfo
installs-packages (in radar-suite-core.md)
Automated review, not a security audit. Ruleset v1+k2.
Advanced
- Catalog kind
- skill
- Gateway key
capstone-radar- Source
- github.com/terryc21/radar-suite