Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions flow.plugin.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ source "$FLOW_PLUGIN_DIR/lib/ai-usage.zsh"
source "$FLOW_PLUGIN_DIR/lib/help-browser.zsh"
source "$FLOW_PLUGIN_DIR/lib/inventory.zsh"
source "$FLOW_PLUGIN_DIR/lib/teaching-utils.zsh"
source "$FLOW_PLUGIN_DIR/lib/teach-style-helpers.zsh"
source "$FLOW_PLUGIN_DIR/lib/keychain-helpers.zsh"
source "$FLOW_PLUGIN_DIR/lib/backup-helpers.zsh"
source "$FLOW_PLUGIN_DIR/lib/cache-helpers.zsh"
Expand Down
257 changes: 256 additions & 1 deletion lib/dispatchers/teach-dispatcher.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -4638,6 +4638,252 @@ ${FLOW_COLORS[bold]}LEARN MORE${FLOW_COLORS[reset]}
EOF
}

# =============================================================================
# TEACHING STYLE COMMANDS (v6.3.0 - Teaching Style Consolidation)
# =============================================================================

_teach_style() {
local subcmd="${1:-show}"
shift 2>/dev/null

case "$subcmd" in
show|s|"")
_teach_style_show "$@"
;;
check|c)
_teach_style_check "$@"
;;
help|--help|-h)
_teach_style_help
;;
*)
_teach_error "Unknown style command: $subcmd"
_teach_style_help
return 1
;;
esac
}

_teach_style_show() {
# Color fallbacks
if [[ -z "$_C_BOLD" ]]; then
_C_BOLD='\033[1m'
_C_DIM='\033[2m'
_C_NC='\033[0m'
_C_GREEN='\033[32m'
_C_YELLOW='\033[33m'
_C_CYAN='\033[36m'
fi

echo ""
echo -e "${_C_BOLD}╭─────────────────────────────────────────────╮${_C_NC}"
echo -e "${_C_BOLD}│ 📚 Teaching Style Configuration │${_C_NC}"
echo -e "${_C_BOLD}╰─────────────────────────────────────────────╯${_C_NC}"
echo ""

# Find source
if ! typeset -f _teach_find_style_source >/dev/null 2>&1; then
echo " ${FLOW_COLORS[error]}✗${FLOW_COLORS[reset]} Teaching style helpers not loaded"
return 1
fi

local source
source=$(_teach_find_style_source "." 2>/dev/null)

if [[ -z "$source" ]]; then
echo " ${FLOW_COLORS[warning]}⚠${FLOW_COLORS[reset]} No teaching style configured"
echo ""
echo " ${FLOW_COLORS[muted]}Add a teaching_style section to .flow/teach-config.yml${FLOW_COLORS[reset]}"
echo " ${FLOW_COLORS[muted]}See: docs/reference/REFCARD-TEACH-CONFIG-SCHEMA.md${FLOW_COLORS[reset]}"
echo ""
return 0
fi

local path="${source%%:*}"
local type="${source##*:}"

# Source info
echo -e " ${_C_BOLD}Source:${_C_NC} $path"
case "$type" in
teach-config)
echo -e " ${_C_BOLD}Type:${_C_NC} ${_C_GREEN}Unified config${_C_NC} (recommended)"
;;
legacy-md)
if _teach_style_is_redirect "."; then
echo -e " ${_C_BOLD}Type:${_C_NC} ${_C_YELLOW}Redirect shim${_C_NC} → .flow/teach-config.yml"
else
echo -e " ${_C_BOLD}Type:${_C_NC} ${_C_YELLOW}Legacy markdown${_C_NC} (consider migrating)"
fi
;;
esac
echo ""

# Display key settings
if ! command -v yq &>/dev/null; then
echo " ${FLOW_COLORS[error]}✗${FLOW_COLORS[reset]} yq required to display settings"
return 1
fi

local approach=$(_teach_get_style "pedagogical_approach.primary" 2>/dev/null)
local formality=$(_teach_get_style "explanation_style.formality" 2>/dev/null)
local proof_style=$(_teach_get_style "explanation_style.proof_style" 2>/dev/null)
local code_style=$(_teach_get_style "content_preferences.code_style" 2>/dev/null)
local tools=$(_teach_get_style "content_preferences.computational_tools" 2>/dev/null)
local exam_fmt=$(_teach_get_style "assessment_philosophy.exam_format" 2>/dev/null)

echo -e " ${_C_BOLD}Key Settings:${_C_NC}"
[[ -n "$approach" && "$approach" != "null" ]] && echo -e " Approach: ${_C_CYAN}$approach${_C_NC}"
[[ -n "$formality" && "$formality" != "null" ]] && echo -e " Formality: ${_C_CYAN}$formality${_C_NC}"
[[ -n "$proof_style" && "$proof_style" != "null" ]] && echo -e " Proofs: ${_C_CYAN}$proof_style${_C_NC}"
[[ -n "$code_style" && "$code_style" != "null" ]] && echo -e " Code style: ${_C_CYAN}$code_style${_C_NC}"
[[ -n "$tools" && "$tools" != "null" ]] && echo -e " Tools: ${_C_CYAN}$tools${_C_NC}"
[[ -n "$exam_fmt" && "$exam_fmt" != "null" ]] && echo -e " Exams: ${_C_CYAN}$exam_fmt${_C_NC}"
echo ""

# Show command overrides summary
if [[ "$type" == "teach-config" && -f ".flow/teach-config.yml" ]]; then
local overrides
overrides=$(yq '.teaching_style.command_overrides // ""' ".flow/teach-config.yml" 2>/dev/null)
if [[ -n "$overrides" && "$overrides" != "null" && "$overrides" != "" ]]; then
local -a cmds
cmds=($(yq '.teaching_style.command_overrides | keys | .[]' ".flow/teach-config.yml" 2>/dev/null))
if (( ${#cmds} > 0 )); then
echo -e " ${_C_BOLD}Command Overrides:${_C_NC}"
for cmd in "${cmds[@]}"; do
echo -e " ${_C_CYAN}$cmd${_C_NC}"
done
echo ""
fi
fi
fi
}

_teach_style_check() {
echo ""
echo "Running teaching style validation..."
echo ""

if ! typeset -f _teach_find_style_source >/dev/null 2>&1; then
echo " ${FLOW_COLORS[error]}✗${FLOW_COLORS[reset]} Teaching style helpers not loaded"
return 1
fi

local -i issues=0

# 1. Check source exists
local source
source=$(_teach_find_style_source "." 2>/dev/null)

if [[ -z "$source" ]]; then
echo " ${FLOW_COLORS[warning]}⚠${FLOW_COLORS[reset]} No teaching style configured"
((issues++))
else
local path="${source%%:*}"
local type="${source##*:}"
echo " ${FLOW_COLORS[success]}✓${FLOW_COLORS[reset]} Source: $path ($type)"

# 2. Check yq can parse it
if command -v yq &>/dev/null; then
if [[ "$type" == "teach-config" ]]; then
if yq '.teaching_style' "$path" &>/dev/null; then
echo " ${FLOW_COLORS[success]}✓${FLOW_COLORS[reset]} YAML syntax valid"
else
echo " ${FLOW_COLORS[error]}✗${FLOW_COLORS[reset]} YAML parse error in teaching_style"
((issues++))
fi
fi

# 3. Check required sub-sections
local approach=$(_teach_get_style "pedagogical_approach" 2>/dev/null)
if [[ -z "$approach" || "$approach" == "null" ]]; then
echo " ${FLOW_COLORS[warning]}⚠${FLOW_COLORS[reset]} Missing: pedagogical_approach"
((issues++))
else
echo " ${FLOW_COLORS[success]}✓${FLOW_COLORS[reset]} Has pedagogical_approach"
fi

local explanation=$(_teach_get_style "explanation_style" 2>/dev/null)
if [[ -z "$explanation" || "$explanation" == "null" ]]; then
echo " ${FLOW_COLORS[warning]}⚠${FLOW_COLORS[reset]} Missing: explanation_style"
((issues++))
else
echo " ${FLOW_COLORS[success]}✓${FLOW_COLORS[reset]} Has explanation_style"
fi

local content=$(_teach_get_style "content_preferences" 2>/dev/null)
if [[ -z "$content" || "$content" == "null" ]]; then
echo " ${FLOW_COLORS[warning]}⚠${FLOW_COLORS[reset]} Missing: content_preferences"
((issues++))
else
echo " ${FLOW_COLORS[success]}✓${FLOW_COLORS[reset]} Has content_preferences"
fi
else
echo " ${FLOW_COLORS[warning]}⚠${FLOW_COLORS[reset]} yq not installed (brew install yq)"
((issues++))
fi

# 4. Check redirect shim consistency
if [[ "$type" == "teach-config" && -f ".claude/teaching-style.local.md" ]]; then
if _teach_style_is_redirect "."; then
echo " ${FLOW_COLORS[success]}✓${FLOW_COLORS[reset]} Legacy shim has redirect"
else
echo " ${FLOW_COLORS[warning]}⚠${FLOW_COLORS[reset]} Legacy file exists without redirect"
((issues++))
fi
fi
fi

echo ""
if (( issues == 0 )); then
echo " ${FLOW_COLORS[success]}✓ All checks passed${FLOW_COLORS[reset]}"
else
echo " ${FLOW_COLORS[warning]}△ $issues issue(s) found${FLOW_COLORS[reset]}"
fi
echo ""

return $((issues > 0 ? 1 : 0))
}

_teach_style_help() {
# Color fallbacks
if [[ -z "$_C_BOLD" ]]; then
_C_BOLD='\033[1m'
_C_DIM='\033[2m'
_C_NC='\033[0m'
_C_GREEN='\033[32m'
_C_YELLOW='\033[33m'
_C_CYAN='\033[36m'
fi

echo -e "
${_C_BOLD}╭─────────────────────────────────────────────╮${_C_NC}
${_C_BOLD}│ teach style - Teaching Style Management │${_C_NC}
${_C_BOLD}╰─────────────────────────────────────────────╯${_C_NC}

${_C_GREEN}🔥 MOST COMMON${_C_NC}:
${_C_CYAN}teach style${_C_NC} Show current teaching style
${_C_CYAN}teach style check${_C_NC} Validate configuration

${_C_YELLOW}💡 QUICK EXAMPLES${_C_NC}:
${_C_DIM}\$${_C_NC} teach style ${_C_DIM}# Display settings${_C_NC}
${_C_DIM}\$${_C_NC} teach style show ${_C_DIM}# Same as above${_C_NC}
${_C_DIM}\$${_C_NC} teach style check ${_C_DIM}# Validate config${_C_NC}

${_C_BOLD}SUBCOMMANDS${_C_NC}:
${_C_CYAN}show${_C_NC} (default) Display current style source and key settings
${_C_CYAN}check${_C_NC} Validate teaching style configuration

${_C_BOLD}RESOLUTION ORDER${_C_NC}:
1. .flow/teach-config.yml → teaching_style section (preferred)
2. .claude/teaching-style.local.md → YAML frontmatter (legacy)

${_C_YELLOW}💡 TIP${_C_NC}: Consolidate your teaching style into .flow/teach-config.yml
for a single source of truth.

${_C_DIM}📚 See also: teach config, teach doctor${_C_NC}
"
}

_teach_dispatcher_help() {
# Color fallbacks
if [[ -z "$_C_BOLD" ]]; then
Expand Down Expand Up @@ -4684,6 +4930,7 @@ ${_C_BLUE}📋 SETUP & CONFIGURATION${_C_NC}:
${_C_CYAN}teach templates${_C_NC} Template management
${_C_CYAN}teach macros${_C_NC} LaTeX macro management
${_C_CYAN}teach prompt${_C_NC} AI prompt management
${_C_CYAN}teach style${_C_NC} Teaching style management
${_C_CYAN}teach migrate-config${_C_NC} Extract lesson plans

${_C_BLUE}📋 CONTENT CREATION${_C_NC} ${_C_DIM}(Scholar AI)${_C_NC}:
Expand Down Expand Up @@ -4719,7 +4966,7 @@ ${_C_MAGENTA}💡 TIP${_C_NC}: Content generation requires Scholar plugin
${_C_DIM} hw=assignment syl=syllabus rb=rubric fb=feedback${_C_NC}
${_C_DIM} Quality: val=validate concept=analyze prof=profiles cl=clean${_C_NC}
${_C_DIM} Manage: d=deploy s=status w=week bk=backup a=archive${_C_NC}
${_C_DIM} Tools: pl=plan tmpl=templates m=macros pr=prompt migrate=migrate-config${_C_NC}
${_C_DIM} Tools: pl=plan tmpl=templates m=macros pr=prompt st=style migrate=migrate-config${_C_NC}

${_C_DIM}📚 See also:${_C_NC}
${_C_CYAN}qu${_C_NC} - Quarto commands (qu preview, qu render)
Expand Down Expand Up @@ -4977,6 +5224,14 @@ teach() {
esac
;;

# Teaching style management (v6.3.0 - Teaching Style Consolidation)
style|st)
case "$1" in
--help|-h|help) _teach_style_help; return 0 ;;
*) _teach_style "$@" ;;
esac
;;

*)
_teach_error "Unknown command: $cmd"
echo ""
Expand Down
77 changes: 77 additions & 0 deletions lib/dispatchers/teach-doctor-impl.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ _teach_doctor() {
echo ""
fi
_teach_doctor_check_macros
if [[ "$json" == "false" ]]; then
echo ""
fi
_teach_doctor_check_teaching_style

# Output results
if [[ "$json" == "true" ]]; then
Expand Down Expand Up @@ -731,5 +735,78 @@ _teach_doctor_check_macros() {
fi
}

# Check teaching style configuration (v6.3.0 - Teaching Style Consolidation)
_teach_doctor_check_teaching_style() {
if [[ "$json" == "false" ]]; then
echo "Teaching Style:"
fi

# Ensure helpers are loaded
if ! typeset -f _teach_find_style_source >/dev/null 2>&1; then
_teach_doctor_warn "Teaching style helpers not loaded"
json_results+=("{\"check\":\"teaching_style\",\"status\":\"warn\",\"message\":\"helpers not loaded\"}")
return 0
fi

local source
source=$(_teach_find_style_source "." 2>/dev/null)

if [[ -z "$source" ]]; then
_teach_doctor_warn "No teaching style configured" "Add teaching_style section to .flow/teach-config.yml"
json_results+=("{\"check\":\"teaching_style\",\"status\":\"warn\",\"message\":\"not configured\"}")
return 0
fi

local path="${source%%:*}"
local type="${source##*:}"

case "$type" in
teach-config)
_teach_doctor_pass "Teaching style in .flow/teach-config.yml"
json_results+=("{\"check\":\"teaching_style_source\",\"status\":\"pass\",\"message\":\"teach-config.yml\"}")

# Check key sub-sections
local approach
approach=$(_teach_get_style "pedagogical_approach.primary" "." 2>/dev/null)
if [[ -n "$approach" && "$approach" != "null" ]]; then
_teach_doctor_pass "Pedagogical approach: $approach"
json_results+=("{\"check\":\"teaching_style_approach\",\"status\":\"pass\",\"message\":\"$approach\"}")
fi

# Check for command overrides
local overrides
overrides=$(yq '.teaching_style.command_overrides // ""' ".flow/teach-config.yml" 2>/dev/null)
if [[ -n "$overrides" && "$overrides" != "null" && "$overrides" != "" ]]; then
local override_count
override_count=$(yq '.teaching_style.command_overrides | keys | length' ".flow/teach-config.yml" 2>/dev/null)
_teach_doctor_pass "Command overrides: $override_count command(s)"
json_results+=("{\"check\":\"command_overrides\",\"status\":\"pass\",\"message\":\"$override_count commands\"}")
fi

# Check if legacy redirect shim exists
if _teach_style_is_redirect "."; then
_teach_doctor_pass "Legacy shim detected (redirect active)"
json_results+=("{\"check\":\"teaching_style_shim\",\"status\":\"pass\",\"message\":\"redirect active\"}")
elif [[ -f ".claude/teaching-style.local.md" ]]; then
_teach_doctor_warn "Legacy .claude/teaching-style.local.md exists without redirect" \
"Consider migrating to .flow/teach-config.yml or adding _redirect: true"
json_results+=("{\"check\":\"teaching_style_shim\",\"status\":\"warn\",\"message\":\"no redirect\"}")
fi
;;
legacy-md)
# Check if it's a redirect shim
if _teach_style_is_redirect "."; then
_teach_doctor_warn "Using redirect shim but .flow/teach-config.yml has no teaching_style" \
"Add teaching_style section to .flow/teach-config.yml"
json_results+=("{\"check\":\"teaching_style_source\",\"status\":\"warn\",\"message\":\"shim without target\"}")
else
_teach_doctor_warn "Using legacy .claude/teaching-style.local.md" \
"Migrate to .flow/teach-config.yml for unified config"
json_results+=("{\"check\":\"teaching_style_source\",\"status\":\"warn\",\"message\":\"legacy location\"}")
fi
;;
esac
}

# Help function for teach doctor
# MOVED to lib/dispatchers/teach-dispatcher.zsh (comprehensive-help branch)
Loading