cat:run-retrospective
Run scheduled retrospective analysis, derive action items, and track effectiveness
What this skill does
# Run Retrospective
## Purpose
Execute scheduled retrospective analysis on accumulated mistakes. Identifies patterns, evaluates
action item effectiveness, derives new action items, and creates escalations for ineffective fixes.
Implements the full workflow defined in `retrospectives.json`.
## When to Use
- Automatically triggered by `learn-from-mistakes` when thresholds met
- Manually invoked with `/cat:run-retrospective`
- After significant project milestones
- When pattern recurrence is suspected
## Trigger Conditions
Retrospective is triggered when EITHER condition is met:
```yaml
triggers:
time_based: days_since_last_retrospective >= trigger_interval_days # default: 14
count_based: mistake_count_since_last >= mistake_count_threshold # default: 10
```
## Workflow
### 1. Check Trigger Conditions
```bash
RETRO_DIR=".claude/cat/retrospectives"
INDEX_FILE="$RETRO_DIR/index.json"
# Get config and state from index.json
INTERVAL=$(jq -r '.config.trigger_interval_days' "$INDEX_FILE")
THRESHOLD=$(jq -r '.config.mistake_count_threshold' "$INDEX_FILE")
LAST_RETRO=$(jq -r '.last_retrospective // empty' "$INDEX_FILE")
MISTAKES_SINCE=$(jq -r '.mistake_count_since_last' "$INDEX_FILE")
# Calculate days since last retrospective
if [[ -n "$LAST_RETRO" && "$LAST_RETRO" != "null" ]]; then
LAST_EPOCH=$(date -d "$LAST_RETRO" +%s 2>/dev/null || echo 0)
else
LAST_EPOCH=0
fi
NOW_EPOCH=$(date +%s)
DAYS_SINCE=$(( (NOW_EPOCH - LAST_EPOCH) / 86400 ))
# Check triggers
if [[ $DAYS_SINCE -ge $INTERVAL ]] || [[ $MISTAKES_SINCE -ge $THRESHOLD ]]; then
echo "RETROSPECTIVE TRIGGERED"
echo " Days since last: $DAYS_SINCE (threshold: $INTERVAL)"
echo " Mistakes since last: $MISTAKES_SINCE (threshold: $THRESHOLD)"
else
echo "No retrospective needed"
echo " Days since last: $DAYS_SINCE / $INTERVAL"
echo " Mistakes since last: $MISTAKES_SINCE / $THRESHOLD"
exit 0
fi
```
### 2. Gather Mistakes for Analysis
```bash
# Aggregate ALL mistakes since last retrospective across all split files
if [[ -n "$LAST_RETRO" && "$LAST_RETRO" != "null" ]]; then
MISTAKES_TO_ANALYZE=$(cat "$RETRO_DIR"/mistakes-*.json 2>/dev/null | \
jq -s --arg last "$LAST_RETRO" \
'[.[].mistakes[] | select(.timestamp > $last)]')
else
# No previous retrospective - analyze all mistakes
MISTAKES_TO_ANALYZE=$(cat "$RETRO_DIR"/mistakes-*.json 2>/dev/null | \
jq -s '[.[].mistakes[]]')
fi
MISTAKE_COUNT=$(echo "$MISTAKES_TO_ANALYZE" | jq 'length')
echo "Analyzing $MISTAKE_COUNT mistakes since $LAST_RETRO"
```
### 3. Analyze by Category
```yaml
category_analysis:
query: |
# Use pre-aggregated MISTAKES_TO_ANALYZE from step 2
echo "$MISTAKES_TO_ANALYZE" | jq '
group_by(.category)
| map({category: .[0].category, count: length, ids: [.[].id]})
| sort_by(-.count)
'
output_format:
- category: protocol_violation
count: 7
ids: [M028, M034, M035, ...]
- category: build_failure
count: 4
ids: [M029, M030, ...]
```
### 4. Check Action Item Effectiveness
For each existing action item with `status: implemented`:
```yaml
effectiveness_check:
for_each_action_item:
# Find mistakes matching this action's pattern AFTER completion
query: |
COMPLETED=$(jq -r --arg id "A004" '.action_items[] | select(.id == $id) | .completed_date' "$INDEX_FILE")
PATTERN=$(jq -r --arg id "A004" '.action_items[] | select(.id == $id) | .pattern_id' "$INDEX_FILE")
# Count post-fix mistakes across all split files
POST_FIX=$(cat "$RETRO_DIR"/mistakes-*.json 2>/dev/null | \
jq -s --arg pattern "$PATTERN" --arg completed "$COMPLETED" \
'[.[].mistakes[] | select(.pattern_keywords | contains([$pattern])) | select(.timestamp > $completed)] | length')
verdicts:
effective: post_fix_count == 0
partially_effective: post_fix_count > 0 AND post_fix_count < pre_fix_count
ineffective: post_fix_count >= pre_fix_count
escalate: post_fix_count >= recurrence_after_fix_threshold # default: 1
```
### 5. Identify New Patterns
```yaml
pattern_identification:
steps:
- Group unaddressed mistakes by category
- Look for common keywords across mistakes
- Check if pattern matches existing pattern_id
- If new pattern with >= 2 occurrences, create PATTERN-XXX
new_pattern_template:
pattern_id: "PATTERN-007"
pattern: "{category}"
occurrences_total: 3
occurrences_after_fix: 0
first_seen: "{earliest_timestamp}"
last_seen: "{latest_timestamp}"
last_action_date: null
status: "new"
effectiveness: "pending"
preventions: []
related_action_items: []
note: "{description of pattern}"
```
### 6. Derive Action Items
For each identified pattern without an action item:
```yaml
action_item_derivation:
priority_rules:
high:
- Pattern count >= 5
- Category is git_operation_failure or protocol_violation
- Escalation of previous action
medium:
- Pattern count >= 3
- Category is build_failure or test_failure
low:
- Pattern count >= 2
- Category is documentation or detection_gap
action_template:
id: "A008"
priority: "{calculated}"
description: "{derived from pattern analysis}"
category: "{pattern_category}"
pattern_id: "PATTERN-007"
status: "open"
created_date: "{now}"
completed_date: null
related_mistakes: ["M042", "M043", "M044"]
effectiveness_check:
mistakes_before: 3
mistakes_after: null
post_fix_mistakes: []
verdict: "pending"
```
### 7. Create Escalations
When action item is ineffective:
```yaml
escalation:
trigger: effectiveness_verdict == "escalate" OR "ineffective"
template:
id: "ESCALATE-{date}-{seq}"
original_action_id: "A004"
original_fix_description: "{from action item}"
failure_analysis:
expected_result: "{what the fix was supposed to do}"
actual_result: "{N} new failures in period"
root_cause: "{analyze why fix didn't work}"
gap_identified: "{what was missing}"
proposed_solution:
approach: "{defense-in-depth|alternative|enhancement}"
description: "{new proposed fix}"
prevention_type: "{code|hook|skill|threshold}"
layers: ["{layer1}", "{layer2}"]
priority: "high"
status: "open"
```
### 8. Update index.json and Create Retrospective Record
```bash
# Get current year-month for retrospective split file
YEAR_MONTH=$(date +%Y-%m)
RETRO_SPLIT_FILE="$RETRO_DIR/retrospectives-${YEAR_MONTH}.json"
TIMESTAMP=$(date -Iseconds)
# Initialize retrospective split file if needed
if [ ! -f "$RETRO_SPLIT_FILE" ]; then
echo "{\"period\":\"$YEAR_MONTH\",\"retrospectives\":[]}" > "$RETRO_SPLIT_FILE"
# Add to index
jq --arg f "retrospectives-${YEAR_MONTH}.json" \
'if (.files.retrospectives | index($f)) then . else .files.retrospectives += [$f] | .files.retrospectives |= sort end' \
"$INDEX_FILE" > "$INDEX_FILE.tmp" && mv "$INDEX_FILE.tmp" "$INDEX_FILE"
fi
# Get next retrospective ID across all split files
MAX_RETRO_NUM=$(cat "$RETRO_DIR"/retrospectives-*.json 2>/dev/null | \
jq -s '[.[].retrospectives[].id] | map(select(startswith("R")) | ltrimstr("R") | tonumber) | max // 0')
RETRO_ID="R$(printf '%03d' $((MAX_RETRO_NUM + 1)))"
# Build and append retrospective entry to split file
jq --arg id "$RETRO_ID" \
--arg ts "$TIMESTAMP" \
--arg trigger "$TRIGGER_TYPE" \
--arg period "${LAST_RETRO} to ${TIMESTAMP}" \
--argjson count "$MISTAKE_COUNT" \
--argjson findings "$FINDINGS_JSON" \
'.retrospectives += [{
id: $id,
timestamp: $ts,
trigger: $trigger,
period_analyzed: $period,
mistakes_analyzed: $count,
summary: "...",
findings: $findings
}]' "$RETRO_SPLIT_FILE" > "$RETRO_SPLIT_FILE.tmp" && mv "$RETRO_SPLIT_FILE.tmp" "$RETRO_SPLIT_FILE"
# Update index.json with new state
jq --arg ts "$TIMESTAMP" \
'.last_retrospective = $ts | .mistake_count_since_last = 0' \
"$INDEX_FILE" Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.