- Create Economist SubmissionTracking package correctly: * mainArticle = full blog post content * coverLetter = 216-word SIR— letter * Links to blog post via blogPostId - Archive 'Letter to The Economist' from blog posts (it's the cover letter) - Fix date display on article cards (use published_at) - Target publication already displaying via blue badge Database changes: - Make blogPostId optional in SubmissionTracking model - Economist package ID: 68fa85ae49d4900e7f2ecd83 - Le Monde package ID: 68fa2abd2e6acd5691932150 Next: Enhanced modal with tabs, validation, export 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
147 lines
4.7 KiB
Bash
Executable file
147 lines
4.7 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
# Tractatus Governance Files Deployment Script
|
|
# Syncs .claude/ directory files to production
|
|
|
|
set -e
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Configuration
|
|
SSH_KEY="$HOME/.ssh/tractatus_deploy"
|
|
REMOTE_USER="ubuntu"
|
|
REMOTE_HOST="vps-93a693da.vps.ovh.net"
|
|
REMOTE_PATH="/var/www/tractatus"
|
|
LOCAL_CLAUDE_DIR=".claude"
|
|
|
|
echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
echo -e "${YELLOW} TRACTATUS GOVERNANCE FILES DEPLOYMENT${NC}"
|
|
echo -e "${YELLOW}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
echo ""
|
|
|
|
# Check if .claude directory exists
|
|
if [ ! -d "$LOCAL_CLAUDE_DIR" ]; then
|
|
echo -e "${RED}✗ Error: .claude directory not found${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${GREEN}[1/4] PRE-DEPLOYMENT CHECKS${NC}"
|
|
echo ""
|
|
|
|
# Check for instruction-history.json
|
|
if [ ! -f "$LOCAL_CLAUDE_DIR/instruction-history.json" ]; then
|
|
echo -e "${RED}✗ Error: instruction-history.json not found${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${GREEN}✓ instruction-history.json found${NC}"
|
|
|
|
# Get file info
|
|
FILE_SIZE=$(du -h "$LOCAL_CLAUDE_DIR/instruction-history.json" | cut -f1)
|
|
INSTRUCTION_COUNT=$(node -e "
|
|
const fs = require('fs');
|
|
const data = JSON.parse(fs.readFileSync('$LOCAL_CLAUDE_DIR/instruction-history.json', 'utf8'));
|
|
const active = data.instructions.filter(i => i.active !== false).length;
|
|
console.log(active);
|
|
")
|
|
|
|
echo -e "${GREEN}✓ File size: $FILE_SIZE${NC}"
|
|
echo -e "${GREEN}✓ Active instructions: $INSTRUCTION_COUNT${NC}"
|
|
echo ""
|
|
|
|
# Check SSH connection
|
|
echo -e "${GREEN}[2/4] CHECKING CONNECTION${NC}"
|
|
echo ""
|
|
|
|
if ! ssh -i "$SSH_KEY" -o ConnectTimeout=5 "${REMOTE_USER}@${REMOTE_HOST}" "echo 'Connection OK'" 2>/dev/null; then
|
|
echo -e "${RED}✗ Error: Cannot connect to production server${NC}"
|
|
exit 1
|
|
fi
|
|
|
|
echo -e "${GREEN}✓ SSH connection successful${NC}"
|
|
echo ""
|
|
|
|
# Show what will be deployed
|
|
echo -e "${GREEN}[3/4] FILES TO DEPLOY${NC}"
|
|
echo ""
|
|
echo " Source: $LOCAL_CLAUDE_DIR/"
|
|
echo " Destination: ${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}/.claude/"
|
|
echo ""
|
|
echo " Files:"
|
|
echo " - instruction-history.json ($FILE_SIZE, $INSTRUCTION_COUNT rules)"
|
|
echo " - session-state.json (if exists)"
|
|
echo " - token-checkpoints.json (if exists)"
|
|
echo " - metrics/ (if exists)"
|
|
echo " - backups/ (if exists)"
|
|
echo ""
|
|
|
|
# Confirmation
|
|
read -p "Continue with deployment? (yes/NO): " confirm
|
|
if [ "$confirm" != "yes" ]; then
|
|
echo -e "${YELLOW}Deployment cancelled${NC}"
|
|
exit 0
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "${GREEN}[4/4] DEPLOYING${NC}"
|
|
echo ""
|
|
|
|
# Create backup on production first
|
|
echo "Creating backup on production..."
|
|
ssh -i "$SSH_KEY" "${REMOTE_USER}@${REMOTE_HOST}" "
|
|
cd $REMOTE_PATH/.claude
|
|
if [ -f instruction-history.json ]; then
|
|
cp instruction-history.json instruction-history.json.backup-\$(date +%Y%m%d-%H%M%S)
|
|
echo '✓ Backup created'
|
|
fi
|
|
"
|
|
|
|
# Deploy files
|
|
echo "Deploying governance files..."
|
|
rsync -avz --progress \
|
|
-e "ssh -i $SSH_KEY" \
|
|
--exclude='*.log' \
|
|
--exclude='temp/' \
|
|
"$LOCAL_CLAUDE_DIR/" \
|
|
"${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}/.claude/"
|
|
|
|
echo ""
|
|
|
|
# Verify deployment
|
|
echo "Verifying deployment..."
|
|
REMOTE_COUNT=$(ssh -i "$SSH_KEY" "${REMOTE_USER}@${REMOTE_HOST}" "
|
|
cd $REMOTE_PATH
|
|
node -e \"
|
|
const fs = require('fs');
|
|
const data = JSON.parse(fs.readFileSync('.claude/instruction-history.json', 'utf8'));
|
|
const active = data.instructions.filter(i => i.active !== false).length;
|
|
console.log(active);
|
|
\"
|
|
")
|
|
|
|
if [ "$REMOTE_COUNT" = "$INSTRUCTION_COUNT" ]; then
|
|
echo -e "${GREEN}✓ Verification successful${NC}"
|
|
echo -e "${GREEN} Local: $INSTRUCTION_COUNT active rules${NC}"
|
|
echo -e "${GREEN} Remote: $REMOTE_COUNT active rules${NC}"
|
|
else
|
|
echo -e "${YELLOW}⚠ Warning: Count mismatch${NC}"
|
|
echo -e "${YELLOW} Local: $INSTRUCTION_COUNT active rules${NC}"
|
|
echo -e "${YELLOW} Remote: $REMOTE_COUNT active rules${NC}"
|
|
fi
|
|
|
|
echo ""
|
|
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
echo -e "${GREEN} DEPLOYMENT COMPLETE${NC}"
|
|
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
echo ""
|
|
echo "Next steps:"
|
|
echo "1. Run sync on production:"
|
|
echo " ssh -i $SSH_KEY ${REMOTE_USER}@${REMOTE_HOST} 'cd $REMOTE_PATH && node scripts/sync-instructions-to-db.js --force'"
|
|
echo ""
|
|
echo "2. Verify sync health:"
|
|
echo " curl -s https://agenticgovernance.digital/health"
|
|
echo ""
|