report-generator
Compiles diagnostic findings from all diagnostic skills into structured markdown reports with health grades (A-F), executive summaries, categorized findings, and archives them in memory/{site-name}/ with latest.md and archive/ rotation.
No fetch-and-execute, destructive, credential, exfiltration or rules-override patterns in 1 files, checked on Oct 20, 2026. This is not a guarantee of safety. How the scan works.
npx degit Shaisolaris/solaris-dev-shop/employees/specialized/wordpress-master/diagnostics/report-generator .claude/skills/report-generator12 alternatives · Best docs & writing skills · Author? Prove this skill
SKILL.md
# Report Generator Skill
This skill takes findings from all diagnostic skills (core-integrity, config-security, user-audit, version-audit, malware-scan, code-quality) and compiles them into a single structured markdown report with a health grade, executive summary, and categorized findings. It handles archive rotation so previous reports are preserved.
## Section 1: Input
### Finding Format
Accept findings from all diagnostic skills as JSON arrays. Each finding object has these fields:
```json
{
"id": "SECR-CHECKSUMS-001",
"severity": "Critical",
"category": "Security",
"title": "Modified core file detected",
"summary": "A core WordPress file has been changed from its original version, which could indicate a security breach.",
"detail": "wp-includes/version.php has been modified. Checksum mismatch detected via wp core verify-checksums. File size differs from expected: 2847 bytes vs 2340 bytes expected.",
"location": "wp-includes/version.php",
"fix": "Run `wp core download --force` to restore original core files, or manually compare the file to identify intentional customizations."
}
```
### Required Fields
| Field | Type | Description |
|-------|------|-------------|
| `id` | string | Deterministic finding ID for cross-scan tracking |
| `severity` | string | One of: `Critical`, `Warning`, `Info` |
| `category` | string | One of: `Security`, `Code Quality`, `Version & Compatibility`, `Suspicious Code` |
| `title` | string | Short descriptive title |
| `summary` | string | One-sentence non-technical explanation |
| `detail` | string | Technical explanation with evidence |
| `location` | string | File path, file:line, or command reference |
| `fix` | string | Concrete remediation steps or code snippet |
### Category Sources
Each category maps to specific diagnostic skills:
- **Security**: Findings from `diagnostic-core-integrity`, `diagnostic-config-security`, `diagnostic-user-audit`
- **Code Quality**: Findings from `diagnostic-code-quality`
- **Version & Compatibility**: Findings from `diagnostic-version-audit`
- **Suspicious Code**: Findings from `diagnostic-malware-scan`
### Aggregating Findings
Collect findings from each skill into a single combined JSON array:
```bash
# Each diagnostic skill produces a findings array. Combine them:
COMBINED_FINDINGS='[]'
# Append each skill's output (each is a JSON array of finding objects)
COMBINED_FINDINGS=$(echo "$COMBINED_FINDINGS" "$CORE_INTEGRITY_FINDINGS" | jq -s 'add')
COMBINED_FINDINGS=$(echo "$COMBINED_FINDINGS" "$CONFIG_SECURITY_FINDINGS" | jq -s 'add')
COMBINED_FINDINGS=$(echo "$COMBINED_FINDINGS" "$USER_AUDIT_FINDINGS" | jq -s 'add')
COMBINED_FINDINGS=$(echo "$COMBINED_FINDINGS" "$VERSION_AUDIT_FINDINGS" | jq -s 'add')
COMBINED_FINDINGS=$(echo "$COMBINED_FINDINGS" "$MALWARE_SCAN_FINDINGS" | jq -s 'add')
COMBINED_FINDINGS=$(echo "$COMBINED_FINDINGS" "$CODE_QUALITY_FINDINGS" | jq -s 'add')
```
## Section 2: Health Grade Calculation
Count findings by severity, then apply the grading matrix deterministically.
### Counting
```bash
CRITICAL_COUNT=$(echo "$COMBINED_FINDINGS" | jq '[.[] | select(.severity == "Critical")] | length')
WARNING_COUNT=$(echo "$COMBINED_FINDINGS" | jq '[.[] | select(.severity == "Warning")] | length')
INFO_COUNT=$(echo "$COMBINED_FINDINGS" | jq '[.[] | select(.severity == "Info")] | length')
```
### Grading Matrix
Apply these rules **in order** (first match wins):
| Grade | Condition |
|-------|-----------|
| **F** | 4 or more critical findings |
| **D** | 2-3 critical findings |
| **C** | Exactly 1 critical finding OR 5+ warnings (with 0 critical) |
| **B** | No critical findings AND 3 or more warnings |
| **A** | No critical findings AND 2 or fewer warnings |
### Grade Calculation Logic
```bash
if [ "$CRITICAL_COUNT" -ge 4 ]; then
HEALTH_GRADE="F"
elif [ "$CRITICAL_COUNT" -ge 2 ]; then
HEALTH_GRADE="D"
elif [ "$CRITICAL_COUNT" -eq 1 ]; then
HEALTH_GRADE="C"
elif [ "$WARNING_COUNT" -ge 5 ]; then
HEALTH_GRADE="C"
elif [ "$WARNING_COUNT" -ge 3 ]; then
HEALTH_GRADE="B"
else
HEALTH_GRADE="A"
fi
```
### Severity Scale Reference
- **Critical**: Actively exploitable or causing immediate risk. Act now.
- **Warning**: Should be fixed but not immediately dangerous. Plan to address.
- **Info**: Awareness item, best practice recommendation. Nice to have.
## Section 3: Report Markdown Template
Generate a report with this exact structure. Replace all `{placeholders}` with actual values.
```markdown
# WordPress Diagnostic Report: {site-name}
**Date:** {YYYY-MM-DD}
**Health Grade:** {A-F}
**Site:** {site-url}
## Executive Summary
{2-3 sentences: overall health assessment, critical finding count, top concern. Written for non-technical reader.}
### Finding Summary
| Severity | Count |
|----------|-------|
| Critical | {N} |
| Warning | {N} |
| Info | {N} |
## Security Findings
{For each finding where category == "Security", sorted by severity (Critical first):}
### {finding.id}: {finding.title}
**Severity:** {finding.severity}
**Summary:** {finding.summary}
**Detail:** {finding.detail}
**Location:** {finding.location}
**Fix:** {finding.fix}
## Code Quality Findings
{For each finding where category == "Code Quality", sorted by severity (Critical first):}
### {finding.id}: {finding.title}
**Severity:** {finding.severity}
**Summary:** {finding.summary}
**Detail:** {finding.detail}
**Location:** {finding.location}
**Fix:** {finding.fix}
## Version & Compatibility
{For each finding where category == "Version & Compatibility", sorted by severity (Critical first):}
### {finding.id}: {finding.title}
**Severity:** {finding.severity}
**Summary:** {finding.summary}
**Detail:** {finding.detail}
**Location:** {finding.location}
**Fix:** {finding.fix}
## Suspicious Code
{For each finding where category == "Suspicious Code", sorted by severity (Critical first):}
### {finding.id}: {finding.title}
**Severity:** {finding.severity}
**Summary:** {finding.summary}
**Detail:** {finding.detail}
**Location:** {finding.location}
**Fix:** {finding.fix}
```
**If no findings exist in a category, show under that heading:**
```markdown
No issues found.
```
### Executive Summary Guidelines
The executive summary must be 2-3 sentences written for a non-technical reader:
1. **Sentence 1:** Overall health assessment using the grade ("Your site received a grade of B, indicating generally good health with some areas for improvement.")
2. **Sentence 2:** Critical finding count and top concern if any ("We found 0 critical issues but 4 warnings, primarily related to outdated plugins.")
3. **Sentence 3 (optional):** Most impactful recommendation ("The most important action is to update your plugins to their latest versions.")
### Sorting Findings Within Categories
Within each category section, sort findings by severity in this order:
1. Critical (first)
2. Warning (second)
3. Info (last)
Within the same severity level, maintain the order received from the diagnostic skills.
## Section 4: Archive Management
Before writing a new report, archive the previous one if it exists.
### Archive Rotation Process
```bash
SITE_NAME="{site-name}"
MEMORY_DIR="memory/${SITE_NAME}"
LATEST="${MEMORY_DIR}/latest.md"
ARCHIVE_DIR="${MEMORY_DIR}/archive"
mkdir -p "$ARCHIVE_DIR"
if [ -f "$LATEST" ]; then
TIMESTAMP=$(date +%Y-%m-%d)
ARCHIVE_PATH="${ARCHIVE_DIR}/scan-${TIMESTAMP}.md"
if [ -f "$ARCHIVE_PATH" ]; then
TIMESTAMP=$(date +%Y-%m-%d-%H%M%S)
ARCHIVE_PATH="${ARCHIVE_DIR}/scan-${TIMESTAMP}.md"
fi
mv "$LATEST" "$ARCHIVE_PATH"
fi
```
### Directory Structure
```
memory/
{site-name}/
latest.md # Most recent scan report (full markdown)
archive/
scan-2026-02-16.md # Previous scans, timestamped
scan-2026-02-16-143022.md # Same-day second scan
```
### Write New Report
After archiving, write the generated report:
```bash
# Write the compiled report to latest.md
cat > "$LATEST" << 'REPORT_EOF'
{generated report content}
REPORT_EOF
```
### Archive Listing
To show available archives for a site:
```bash
SITE_NAME="{site-name}"
ARCHIVE_DIR="memory/${SITE_NAME}/archive"
if [ -d "$ARCHIVE_DIR" ]; then
echo "Previous scans:"
ls -1 "$ARCHIVE_DIR" | sort -r | while read -r file; do
SCAN_DATE=$(echo "$file" | sed 's/scan-//' | sed 's/\.md//')
echo " - $SCAN_DATE"
done
else
echo "No previous scans found."
fi
```
## Section 5: Finding ID Reference
Finding IDs enable tracking the same issue across multiple scans. If the same issue exists in the same location, it gets the same ID -- enabling diff between reports.
### ID Format by Category
| Category | Prefix | Source Skills | Example |
|----------|--------|--------------|---------|
| Security | `SECR-{CHECK}-{hash}` | core-integrity, config-security, user-audit | `SECR-CHECKSUMS-a1b2c3` |
| Code Quality | `CODE-{CHECK}-{hash}` | diagnostic-code-quality | `CODE-SQLI-d4e5f6` |
| Version & Compatibility | `DIAG-{CHECK}-{hash}` | version-audit | `DIAG-OUTDATED-g7h8i9` |
| Suspicious Code | `SUSP-{CHECK}-{hash}` | malware-scan | `SUSP-EVAL-j0k1l2` |
### ID Generation Rules
1. **Prefix**: Based on category (SECR, CODE, DIAG, SUSP)
2. **CHECK**: Short identifier for the specific check type (e.g. CHECKSUMS, SQLI, OUTDATED, EVAL)
3. **Hash**: Short hash derived from the finding's location (file path + line number if applicable). Use first 6 characters of the location's MD5 hash.
### Cross-Scan Tracking
Same issue + same location = same ID across scans. This enables:
- **Tracking fixes**: A finding present in scan 1 but absent in scan 2 was fixed
- **Detecting regressions**: A finding absent in scan 1 but present in scan 2 is a regression
- **Progress reports**: Compare finding counts across scans to show improvement over time
### Generating Deterministic IDs
```bash
# Generate a finding ID
CATEGORY_PREFIX="SECR" # or CODE, DIAG, SUSP
CHECK_NAME="CHECKSUMS"
LOCATION="wp-includes/version.php"
HASH=$(echo -n "$LOCATION" | md5 | cut -c1-6)
FINDING_ID="${CATEGORY_PREFIX}-${CHECK_NAME}-${HASH}"
# Result: SECR-CHECKSUMS-a1b2c3
```
## Return Value
After generating and saving the report, return the path to the generated report file:
```
memory/{site-name}/latest.md
```
Also output a brief summary for inline display:
```
Report generated: Health Grade {GRADE} | {CRITICAL} critical, {WARNING} warning, {INFO} info findings
Saved to: memory/{site-name}/latest.md
```
If a previous report was archived, also note:
```
Previous report archived to: memory/{site-name}/archive/scan-{date}.md
```Shown under the source repo’s MIT license. Read the full folder on GitHub.