orchestrated-discussions/scripts/run-turn.sh

131 lines
5.5 KiB
Bash
Executable File

#!/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 <discussion.md>"
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