Major overhaul of onboarding system with adaptive topic selection based on user context and keywords. Addresses 8 critical gaps identified by technical- writer agent challenge. Core Changes: - Adaptive matrix: core topics (always) + adaptive topics (keyword-triggered) - Security-first: moved sandbox_native_guide to beginner_5min (before commands) - Time budget validation: all 18 profiles validated at 6-8 min/topic - Quiz integration: positioned as exit activity in Phase 4 wrap-up - New learn_security goal with 2 profiles (beginner_15min, advanced_60min) Technical Improvements: - Added onboarding_matrix_meta for version tracking and maintenance triggers - Created validation script (validate-onboarding.sh) with 6 automated checks - Created automation script (detect-new-onboarding-topics.sh) for monthly reviews - Fixed 8 missing deep_dive keys (rules, workflow, fix, architecture, etc.) - Removed duplicate deep_dive section causing validation failures Documentation: - README.md: version 3.23.0, harmonized counts (106 templates, 49 evaluations) - CHANGELOG.md: comprehensive v3.23.0 entry with all changes - Onboarding-prompt.md: updated Phase 1.5, 2, 4 with adaptive logic - Reference.yaml: 180+ lines added for adaptive architecture Validation: - All 18 profiles pass time budget constraints (30-50% buffer maintained) - All deep_dive keys verified (no missing references) - Version synchronized across 6 files via sync-version.sh Challenge: technical-writer agent identified 8 gaps in initial analysis Result: Full adaptive approach implemented, all gaps addressed Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
196 lines
6.5 KiB
Bash
Executable file
196 lines
6.5 KiB
Bash
Executable file
#!/usr/bin/env bash
|
||
# detect-new-onboarding-topics.sh
|
||
# Detects CRITICAL/HIGH VALUE topics from resource evaluations not covered in onboarding_matrix
|
||
# Part of adaptive onboarding maintenance automation (v2.0.0, guide v3.23.0+)
|
||
# Usage: Run monthly or before releases to ensure new important topics are discoverable
|
||
|
||
set -euo pipefail
|
||
|
||
# Colors for output
|
||
RED='\033[0;31m'
|
||
GREEN='\033[0;32m'
|
||
YELLOW='\033[1;33m'
|
||
BLUE='\033[0;34m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# Paths
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||
REFERENCE_YAML="$REPO_ROOT/machine-readable/reference.yaml"
|
||
EVALUATIONS_DIR="$REPO_ROOT/docs/resource-evaluations"
|
||
|
||
# Helper functions
|
||
info() {
|
||
echo -e "${BLUE}ℹ️ $1${NC}"
|
||
}
|
||
|
||
success() {
|
||
echo -e "${GREEN}✅ $1${NC}"
|
||
}
|
||
|
||
gap() {
|
||
echo -e "${YELLOW}⚠️ $1${NC}"
|
||
}
|
||
|
||
critical_gap() {
|
||
echo -e "${RED}🚨 $1${NC}"
|
||
}
|
||
|
||
# Main scan
|
||
scan_evaluations() {
|
||
info "Scanning resource evaluations for CRITICAL (5/5) and HIGH VALUE (4/5) topics..."
|
||
echo ""
|
||
|
||
# Extract all keys referenced in onboarding_matrix
|
||
local matrix_keys
|
||
matrix_keys=$(python3 <<'EOF'
|
||
import yaml
|
||
import sys
|
||
|
||
with open(sys.argv[1]) as f:
|
||
data = yaml.safe_load(f)
|
||
|
||
matrix = data.get('onboarding_matrix', {})
|
||
|
||
# Collect all keys
|
||
referenced = set()
|
||
for goal, levels in matrix.items():
|
||
for level, profile in levels.items():
|
||
if isinstance(profile, dict):
|
||
if 'core' in profile:
|
||
referenced.update(profile['core'])
|
||
if 'adaptive' in profile:
|
||
for item in profile['adaptive']:
|
||
if isinstance(item, dict) and 'topics' in item:
|
||
topics = item['topics']
|
||
if isinstance(topics, list):
|
||
referenced.update(topics)
|
||
else:
|
||
referenced.add(topics)
|
||
elif isinstance(profile, list):
|
||
referenced.update(profile)
|
||
|
||
print('|'.join(sorted(referenced)))
|
||
EOF
|
||
"$REFERENCE_YAML")
|
||
|
||
# Check deep_dive keys
|
||
local deep_dive_keys
|
||
deep_dive_keys=$(python3 -c "import yaml; print('|'.join(yaml.safe_load(open('$REFERENCE_YAML')).get('deep_dive', {}).keys()))")
|
||
|
||
# Scan evaluation files
|
||
local critical_topics=()
|
||
local high_topics=()
|
||
local gaps=()
|
||
local critical_gaps=()
|
||
|
||
if [ ! -d "$EVALUATIONS_DIR" ]; then
|
||
info "No evaluations directory found at $EVALUATIONS_DIR"
|
||
return 0
|
||
fi
|
||
|
||
for eval_file in "$EVALUATIONS_DIR"/*.md; do
|
||
if [ ! -f "$eval_file" ]; then
|
||
continue
|
||
fi
|
||
|
||
# Extract score (look for "**Score**: X/5" or "Score: X/5")
|
||
local score
|
||
score=$(grep -oE '\*\*Score\*\*:?\s*[0-9]/5|Score:?\s*[0-9]/5' "$eval_file" | head -1 | grep -oE '[0-9]' || echo "0")
|
||
|
||
# Extract topic/key (look for deep_dive references in evaluation)
|
||
local topic_key
|
||
topic_key=$(basename "$eval_file" .md | sed 's/-evaluation$//' | sed 's/-/_/g')
|
||
|
||
# Check if it's CRITICAL or HIGH VALUE
|
||
if [ "$score" -eq 5 ]; then
|
||
critical_topics+=("$topic_key")
|
||
# Check if in deep_dive
|
||
if [[ "$deep_dive_keys" == *"$topic_key"* ]]; then
|
||
# Check if in matrix
|
||
if [[ "$matrix_keys" != *"$topic_key"* ]]; then
|
||
critical_gaps+=("$topic_key (5/5 CRITICAL, file: $(basename "$eval_file"))")
|
||
fi
|
||
fi
|
||
elif [ "$score" -eq 4 ]; then
|
||
high_topics+=("$topic_key")
|
||
# Check if in deep_dive
|
||
if [[ "$deep_dive_keys" == *"$topic_key"* ]]; then
|
||
# Check if in matrix
|
||
if [[ "$matrix_keys" != *"$topic_key"* ]]; then
|
||
gaps+=("$topic_key (4/5 HIGH VALUE, file: $(basename "$eval_file"))")
|
||
fi
|
||
fi
|
||
fi
|
||
done
|
||
|
||
# Report
|
||
echo "📊 Summary:"
|
||
echo " - CRITICAL (5/5) topics found: ${#critical_topics[@]}"
|
||
echo " - HIGH VALUE (4/5) topics found: ${#high_topics[@]}"
|
||
echo ""
|
||
|
||
if [ ${#critical_gaps[@]} -gt 0 ]; then
|
||
critical_gap "Found ${#critical_gaps[@]} CRITICAL topics NOT in any onboarding profile:"
|
||
for gap_item in "${critical_gaps[@]}"; do
|
||
echo " - $gap_item"
|
||
done
|
||
echo ""
|
||
fi
|
||
|
||
if [ ${#gaps[@]} -gt 0 ]; then
|
||
gap "Found ${#gaps[@]} HIGH VALUE topics NOT in any onboarding profile:"
|
||
for gap_item in "${gaps[@]}"; do
|
||
echo " - $gap_item"
|
||
done
|
||
echo ""
|
||
fi
|
||
|
||
if [ ${#critical_gaps[@]} -eq 0 ] && [ ${#gaps[@]} -eq 0 ]; then
|
||
success "All CRITICAL and HIGH VALUE topics are covered in onboarding_matrix!"
|
||
echo ""
|
||
info "Covered topics:"
|
||
for topic in "${critical_topics[@]}"; do
|
||
if [[ "$matrix_keys" == *"$topic"* ]]; then
|
||
echo " ✅ $topic (5/5 CRITICAL)"
|
||
fi
|
||
done
|
||
for topic in "${high_topics[@]}"; do
|
||
if [[ "$matrix_keys" == *"$topic"* ]]; then
|
||
echo " ✅ $topic (4/5 HIGH VALUE)"
|
||
fi
|
||
done
|
||
return 0
|
||
else
|
||
echo "💡 Action required:"
|
||
echo " Review the gaps above and consider adding them to relevant profiles in:"
|
||
echo " $REFERENCE_YAML (onboarding_matrix section)"
|
||
echo ""
|
||
echo " See design doc: claudedocs/adaptive-onboarding-design.md"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# Main
|
||
main() {
|
||
echo "════════════════════════════════════════════════════════════════"
|
||
echo " Onboarding Topics Gap Detection (v2.0.0)"
|
||
echo "════════════════════════════════════════════════════════════════"
|
||
echo ""
|
||
|
||
scan_evaluations
|
||
local exit_code=$?
|
||
|
||
echo ""
|
||
echo "════════════════════════════════════════════════════════════════"
|
||
if [ $exit_code -eq 0 ]; then
|
||
success "No gaps detected - onboarding is up-to-date!"
|
||
else
|
||
gap "Gaps detected - review and update onboarding_matrix"
|
||
fi
|
||
echo "════════════════════════════════════════════════════════════════"
|
||
|
||
exit $exit_code
|
||
}
|
||
|
||
main "$@"
|