#!/bin/bash # run-turn.sh - Manual orchestration of a discussion turn # # This script demonstrates how all the SmartTools chain together. # It does exactly what `discussions turn feature.md` would do, # but each step is visible and debuggable. # # Usage: ./scripts/run-turn.sh path/to/discussion.md set -e # Exit immediately if any command fails # Validate command line argument if [ -z "$1" ]; then echo "Usage: $0 " exit 1 fi DISCUSSION="$1" # Path to the discussion markdown file WORKDIR=$(mktemp -d) # Create temporary working directory echo "=== Discussion Turn Script ===" echo "Discussion: $DISCUSSION" echo "Work directory: $WORKDIR" echo "" # 1. Parse current state echo "Step 1: Parsing discussion..." cat "$DISCUSSION" | discussion-parser > "$WORKDIR/state.json" # Parse discussion into JSON echo " Parsed state saved to $WORKDIR/state.json" cat "$WORKDIR/state.json" | jq -r '" Title: \(.metadata.title)"' # Extract title cat "$WORKDIR/state.json" | jq -r '" Phase: \(.metadata.phase)"' # Extract phase cat "$WORKDIR/state.json" | jq -r '" Votes: READY=\(.vote_summary.READY) CHANGES=\(.vote_summary.CHANGES) REJECT=\(.vote_summary.REJECT)"' # Show current votes echo "" # 2. Determine who should respond echo "Step 2: Routing mentions..." cat "$WORKDIR/state.json" | discussion-mention-router > "$WORKDIR/routing.json" # Route mentions to participants PARTICIPANTS=$(cat "$WORKDIR/routing.json" | jq -r '.participants_to_call | join(", ")') # Get comma-separated list echo " Participants to call: $PARTICIPANTS" echo "" # 3. Call each participant (could be parallel in async Python) echo "Step 3: Calling participants..." echo "[]" > "$WORKDIR/responses.json" # Initialize empty responses array # Loop through each participant that should respond for PARTICIPANT in $(cat "$WORKDIR/routing.json" | jq -r '.participants_to_call[]'); do TOOL="discussion-$PARTICIPANT" # Construct tool name from participant # Check if tool exists if ! command -v "$TOOL" &> /dev/null; then echo " Warning: $TOOL not found, skipping" continue fi echo " Calling $TOOL..." # Call participant tool with discussion content, fallback to NO_RESPONSE sentinel RESPONSE=$(cat "$DISCUSSION" | $TOOL --callout "Please review and provide feedback" 2>/dev/null || echo '{"sentinel": "NO_RESPONSE"}') # Check for valid JSON if echo "$RESPONSE" | jq -e . > /dev/null 2>&1; then # Check for NO_RESPONSE sentinel if [ "$(echo "$RESPONSE" | jq -r '.sentinel // empty')" = "NO_RESPONSE" ]; then echo " -> No response" else # Add author field and append to responses AUTHOR="AI-$(echo "$PARTICIPANT" | sed 's/\b\(.\)/\u\1/g')" # Capitalize participant name RESPONSE_WITH_AUTHOR=$(echo "$RESPONSE" | jq --arg a "$AUTHOR" '. + {author: $a}') # Append to responses array cat "$WORKDIR/responses.json" | jq --argjson r "$RESPONSE_WITH_AUTHOR" '. + [$r]' > "$WORKDIR/responses.json.tmp" mv "$WORKDIR/responses.json.tmp" "$WORKDIR/responses.json" VOTE=$(echo "$RESPONSE" | jq -r '.vote // "no vote"') # Extract vote or default echo " -> Vote: $VOTE" fi else echo " -> Invalid response (not JSON)" fi done echo "" # 4. Show collected responses echo "Step 4: Collected responses:" cat "$WORKDIR/responses.json" | jq -r '.[] | " \(.author): \(.vote // "no vote")"' # Display author and vote echo "" # 5. Append responses to discussion (dry run - don't modify original) echo "Step 5: Appending responses (dry run)..." # Combine original discussion with responses and append using turn-appender (cat "$DISCUSSION"; echo "---RESPONSES---"; cat "$WORKDIR/responses.json") | discussion-turn-appender > "$WORKDIR/discussion-updated.md" echo " Updated discussion saved to $WORKDIR/discussion-updated.md" echo "" # 6. Count votes and check consensus echo "Step 6: Counting votes..." # Parse updated discussion and count votes cat "$WORKDIR/discussion-updated.md" | discussion-parser | discussion-vote-counter > "$WORKDIR/votes.json" cat "$WORKDIR/votes.json" | jq -r '" READY: \(.vote_summary.READY), CHANGES: \(.vote_summary.CHANGES), REJECT: \(.vote_summary.REJECT)"' cat "$WORKDIR/votes.json" | jq -r '" Consensus reached: \(.consensus.reached)"' cat "$WORKDIR/votes.json" | jq -r 'if .consensus.reason then " Reason: \(.consensus.reason)" else empty end' echo "" # 7. Check if status should change echo "Step 7: Checking status promotion..." CURRENT_STATUS=$(cat "$WORKDIR/state.json" | jq -r '.metadata.status // "OPEN"') # Get current status CURRENT_PHASE=$(cat "$WORKDIR/state.json" | jq -r '.metadata.phase // "initial_feedback"') # Get current phase # Check if status should be promoted based on votes cat "$WORKDIR/votes.json" | discussion-status-promoter --current-status "$CURRENT_STATUS" --current-phase "$CURRENT_PHASE" > "$WORKDIR/promotion.json" SHOULD_PROMOTE=$(cat "$WORKDIR/promotion.json" | jq -r '.should_promote') if [ "$SHOULD_PROMOTE" = "true" ]; then NEW_STATUS=$(cat "$WORKDIR/promotion.json" | jq -r '.new_status') echo " Status should be promoted: $CURRENT_STATUS -> $NEW_STATUS" else echo " No status change needed" fi echo "" # Summary echo "=== Turn Complete ===" echo "" echo "Files created in $WORKDIR:" ls -la "$WORKDIR" # List all created files echo "" echo "To apply changes, run:" echo " cp $WORKDIR/discussion-updated.md $DISCUSSION" # Copy updated discussion back echo "" echo "To clean up:" echo " rm -rf $WORKDIR" # Remove temporary directory