Update project docs and problem notes
This commit is contained in:
357
scripts/monitor.sh
Executable file
357
scripts/monitor.sh
Executable file
@@ -0,0 +1,357 @@
|
||||
#!/bin/bash
|
||||
# MD Hub Secure - Progress Monitor
|
||||
# Watches the project directory and updates docs/STATUS.md with progress
|
||||
# Exits if no filesystem changes detected between iterations
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_DIR="/Users/tim/developer/md-hub-secure"
|
||||
DOCS_DIR="$PROJECT_DIR/docs"
|
||||
STATUS_FILE="$DOCS_DIR/STATUS.md"
|
||||
HASH_FILE="$DOCS_DIR/.last_state_hash"
|
||||
ITERATION=0
|
||||
MAX_ITERATIONS=1000 # Safety limit
|
||||
START_TIME=$(date +%s)
|
||||
|
||||
# Colors for terminal output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
log() {
|
||||
echo -e "${BLUE}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1" >&2
|
||||
}
|
||||
|
||||
warn() {
|
||||
echo -e "${YELLOW}[$(date '+%Y-%m-%d %H:%M:%S')] WARNING:${NC} $1" >&2
|
||||
}
|
||||
|
||||
error() {
|
||||
echo -e "${RED}[$(date '+%Y-%m-%d %H:%M:%S')] ERROR:${NC} $1" >&2
|
||||
}
|
||||
|
||||
success() {
|
||||
echo -e "${GREEN}[$(date '+%Y-%m-%d %H:%M:%S')]${NC} $1" >&2
|
||||
}
|
||||
|
||||
# Compute hash of all tracked files (excluding node_modules, .git, etc.)
|
||||
compute_state_hash() {
|
||||
find "$PROJECT_DIR" \
|
||||
-type f \
|
||||
-not -path '*/node_modules/*' \
|
||||
-not -path '*/.git/*' \
|
||||
-not -path '*/data/*' \
|
||||
-not -path '*/vendor/*' \
|
||||
-not -name '.last_state_hash' \
|
||||
-not -name 'STATUS.md' \
|
||||
-not -name '*.lock' \
|
||||
| sort \
|
||||
| xargs stat -f '%m %N' 2>/dev/null \
|
||||
| md5 -q
|
||||
}
|
||||
|
||||
# Check if filesystem changed
|
||||
has_changes() {
|
||||
local current_hash
|
||||
current_hash=$(compute_state_hash)
|
||||
|
||||
if [[ -f "$HASH_FILE" ]]; then
|
||||
local last_hash
|
||||
last_hash=$(cat "$HASH_FILE")
|
||||
if [[ "$current_hash" == "$last_hash" ]]; then
|
||||
return 1 # No changes
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "$current_hash" > "$HASH_FILE"
|
||||
return 0 # Changes detected (or first run)
|
||||
}
|
||||
|
||||
# Count lines of code by language
|
||||
analyze_codebase() {
|
||||
log "Analyzing codebase..."
|
||||
|
||||
local go_files=0
|
||||
local go_lines=0
|
||||
local ts_files=0
|
||||
local ts_lines=0
|
||||
local md_files=0
|
||||
local md_lines=0
|
||||
local total_files=0
|
||||
local docker_files=0
|
||||
|
||||
# Count Go files
|
||||
if command -v find &> /dev/null; then
|
||||
go_files=$(find "$PROJECT_DIR" -name '*.go' -not -path '*/vendor/*' -not -path '*/node_modules/*' | wc -l)
|
||||
go_lines=$(find "$PROJECT_DIR" -name '*.go' -not -path '*/vendor/*' -not -path '*/node_modules/*' -exec cat {} + 2>/dev/null | wc -l)
|
||||
|
||||
ts_files=$(find "$PROJECT_DIR" -name '*.ts' -o -name '*.tsx' | grep -v node_modules | wc -l)
|
||||
ts_lines=$(find "$PROJECT_DIR" -name '*.ts' -o -name '*.tsx' | grep -v node_modules | xargs cat 2>/dev/null | wc -l)
|
||||
|
||||
md_files=$(find "$PROJECT_DIR" -name '*.md' | wc -l)
|
||||
md_lines=$(find "$PROJECT_DIR" -name '*.md' -exec cat {} + 2>/dev/null | wc -l)
|
||||
|
||||
docker_files=$(find "$PROJECT_DIR" -name 'Dockerfile*' -o -name 'docker-compose*' | wc -l)
|
||||
|
||||
total_files=$(find "$PROJECT_DIR" -type f -not -path '*/node_modules/*' -not -path '*/.git/*' -not -path '*/data/*' | wc -l)
|
||||
fi
|
||||
|
||||
echo "$go_files|$go_lines|$ts_files|$ts_lines|$md_files|$md_lines|$total_files|$docker_files"
|
||||
}
|
||||
|
||||
# Check git status if available
|
||||
check_git_status() {
|
||||
if [[ -d "$PROJECT_DIR/.git" ]]; then
|
||||
cd "$PROJECT_DIR"
|
||||
local branch=$(git branch --show-current 2>/dev/null || echo "unknown")
|
||||
local uncommitted=$(git status --short 2>/dev/null | wc -l | tr -d ' ')
|
||||
local last_commit=$(git log -1 --format="%h - %s (%cr)" 2>/dev/null || echo "No commits yet")
|
||||
echo "$branch|$uncommitted|$last_commit"
|
||||
else
|
||||
echo "no-git|0|N/A"
|
||||
fi
|
||||
}
|
||||
|
||||
# Check if Docker is configured
|
||||
check_docker() {
|
||||
if [[ -f "$PROJECT_DIR/docker-compose.yml" ]]; then
|
||||
echo "yes"
|
||||
else
|
||||
echo "no"
|
||||
fi
|
||||
}
|
||||
|
||||
# Check milestone progress
|
||||
check_milestones() {
|
||||
local completed=0
|
||||
local in_progress=0
|
||||
local total=6
|
||||
|
||||
if [[ -f "$DOCS_DIR/milestones/milestone-01-foundation.md" ]]; then
|
||||
# Check for markers in milestone files
|
||||
for i in $(seq 1 6); do
|
||||
local file="$DOCS_DIR/milestones/milestone-0${i}-*.md"
|
||||
if ls $file 1> /dev/null 2>&1; then
|
||||
if grep -q "COMPLETED" $file 2>/dev/null; then
|
||||
completed=$((completed + 1))
|
||||
elif grep -q "IN_PROGRESS" $file 2>/dev/null; then
|
||||
in_progress=$((in_progress + 1))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo "$completed|$in_progress|$total"
|
||||
}
|
||||
|
||||
# Generate code review comments
|
||||
generate_code_review() {
|
||||
log "Scanning for code review items..."
|
||||
|
||||
local review=""
|
||||
|
||||
# Check for TODO/FIXME/XXX in code
|
||||
if find "$PROJECT_DIR" -name '*.go' -o -name '*.ts' -o -name '*.tsx' | grep -v node_modules | xargs grep -n 'TODO\|FIXME\|XXX\|HACK' 2>/dev/null | head -20 > /tmp/todos.txt; then
|
||||
local todo_count=$(wc -l < /tmp/todos.txt | tr -d ' ')
|
||||
if [[ $todo_count -gt 0 ]]; then
|
||||
review+="### Action Items Found ($todo_count)\n\n"
|
||||
review+="| File | Line | Comment |\n"
|
||||
review+="|------|------|---------|\n"
|
||||
while IFS=: read -r file line comment; do
|
||||
# Extract just the filename
|
||||
local fname=$(basename "$file")
|
||||
review+="| $fname | $line | $comment |\n"
|
||||
done < /tmp/todos.txt
|
||||
review+="\n"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for security issues
|
||||
if find "$PROJECT_DIR" -name '*.go' | xargs grep -l 'http.Get\|http.Post\|ioutil.ReadFile' 2>/dev/null | head -5 > /tmp/security.txt; then
|
||||
local sec_count=$(wc -l < /tmp/security.txt | tr -d ' ')
|
||||
if [[ $sec_count -gt 0 ]]; then
|
||||
review+="### Security Review Notes\n\n"
|
||||
review+="- Found $sec_count files using potentially unsafe operations\n"
|
||||
review+="- Ensure all HTTP requests have timeouts\n"
|
||||
review+="- Validate all file paths before reading\n\n"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for error handling
|
||||
if find "$PROJECT_DIR" -name '*.go' | xargs grep -n '_ = ' 2>/dev/null | head -10 > /tmp/errors.txt; then
|
||||
local err_count=$(wc -l < /tmp/errors.txt | tr -d ' ')
|
||||
if [[ $err_count -gt 0 ]]; then
|
||||
review+="### Error Handling ($err_count ignored errors)\n\n"
|
||||
review+="Several errors are being silently ignored. Consider handling or logging these.\n\n"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo -e "$review"
|
||||
}
|
||||
|
||||
# Generate the status report
|
||||
generate_status() {
|
||||
local iteration=$1
|
||||
local now=$(date '+%Y-%m-%d %H:%M:%S UTC')
|
||||
local elapsed=$(( $(date +%s) - START_TIME ))
|
||||
local elapsed_str="$((elapsed / 3600))h $(((elapsed % 3600) / 60))m"
|
||||
|
||||
# Gather metrics
|
||||
IFS='|' read -r go_files go_lines ts_files ts_lines md_files md_lines total_files docker_files <<< "$(analyze_codebase)"
|
||||
IFS='|' read -r git_branch uncommitted last_commit <<< "$(check_git_status)"
|
||||
IFS='|' read -r completed in_progress total_milestones <<< "$(check_milestones)"
|
||||
local has_docker=$(check_docker)
|
||||
|
||||
# Generate code review
|
||||
local review=$(generate_code_review)
|
||||
|
||||
# Calculate progress percentage
|
||||
local progress=$((completed * 100 / total_milestones))
|
||||
|
||||
cat > "$STATUS_FILE" << EOF
|
||||
# Project Status Report
|
||||
|
||||
**Generated:** $now
|
||||
**Monitoring Duration:** $elapsed_str
|
||||
**Iteration:** $iteration
|
||||
**Branch:** $git_branch
|
||||
|
||||
## Quick Stats
|
||||
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Total Files | $total_files |
|
||||
| Go Files | $go_files (${go_lines} lines) |
|
||||
| TypeScript Files | $ts_files (${ts_lines} lines) |
|
||||
| Markdown Files | $md_files (${md_lines} lines) |
|
||||
| Docker Config | $has_docker |
|
||||
| Uncommitted Changes | $uncommitted |
|
||||
| Milestones Complete | $completed/$total_milestones (${progress}%) |
|
||||
|
||||
## Recent Activity
|
||||
|
||||
**Last Commit:** $last_commit
|
||||
|
||||
## Milestone Progress
|
||||
|
||||
- [ ] Milestone 1: Foundation
|
||||
- [ ] Milestone 2: Sync Protocol
|
||||
- [ ] Milestone 3: Authentication
|
||||
- [ ] Milestone 4: Collaboration
|
||||
- [ ] Milestone 5: Search & UI
|
||||
- [ ] Milestone 6: Production
|
||||
|
||||
**Current Focus:** $([[ $in_progress -gt 0 ]] && echo "In Progress" || echo "Not Started")
|
||||
|
||||
$review
|
||||
|
||||
## Notes for Human Review
|
||||
|
||||
EOF
|
||||
|
||||
# Add contextual notes based on what we see
|
||||
if [[ $go_files -eq 0 ]]; then
|
||||
echo ">> **No Go files found.** Codex may be working on other aspects or hasn't started yet." >> "$STATUS_FILE"
|
||||
elif [[ $go_files -lt 5 ]]; then
|
||||
echo ">> **Early stage.** Only $go_files Go files exist. Foundation work likely in progress." >> "$STATUS_FILE"
|
||||
else
|
||||
echo ">> **Active development.** $go_files Go files with ${go_lines} lines of code." >> "$STATUS_FILE"
|
||||
fi
|
||||
|
||||
if [[ $uncommitted -gt 0 ]]; then
|
||||
echo ">> **$uncommitted uncommitted changes** detected. Codex may be mid-work." >> "$STATUS_FILE"
|
||||
fi
|
||||
|
||||
if [[ -n "$review" ]]; then
|
||||
echo ">> **Code review items found.** See Action Items above." >> "$STATUS_FILE"
|
||||
fi
|
||||
|
||||
cat >> "$STATUS_FILE" << EOF
|
||||
|
||||
## Files Changed This Session
|
||||
|
||||
EOF
|
||||
|
||||
# List recently modified files
|
||||
if [[ -f "$HASH_FILE" ]]; then
|
||||
find "$PROJECT_DIR" \
|
||||
-type f \
|
||||
-mtime -0.007 \
|
||||
-not -path '*/node_modules/*' \
|
||||
-not -path '*/.git/*' \
|
||||
-not -path '*/data/*' \
|
||||
-not -name '.last_state_hash' \
|
||||
-not -name 'STATUS.md' \
|
||||
| sort | head -20 \
|
||||
| sed 's|^| - |' >> "$STATUS_FILE" || true
|
||||
fi
|
||||
|
||||
cat >> "$STATUS_FILE" << EOF
|
||||
|
||||
---
|
||||
|
||||
*This report auto-generated by MD Hub Secure progress monitor.*
|
||||
*Next update in ~10 minutes or when filesystem changes detected.*
|
||||
EOF
|
||||
|
||||
success "Status report updated: $STATUS_FILE"
|
||||
}
|
||||
|
||||
# Main monitoring loop
|
||||
main() {
|
||||
log "Starting MD Hub Secure progress monitor..."
|
||||
log "Project: $PROJECT_DIR"
|
||||
log "Watching for filesystem changes every 10 minutes"
|
||||
log "Press Ctrl+C to stop, or wait for auto-exit on inactivity"
|
||||
|
||||
# Ensure docs directory exists
|
||||
mkdir -p "$DOCS_DIR"
|
||||
|
||||
while true; do
|
||||
ITERATION=$((ITERATION + 1))
|
||||
|
||||
if [[ $ITERATION -gt $MAX_ITERATIONS ]]; then
|
||||
warn "Maximum iterations ($MAX_ITERATIONS) reached. Stopping."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log "Iteration $ITERATION - checking for changes..."
|
||||
|
||||
if [[ $ITERATION -gt 1 ]] && ! has_changes; then
|
||||
warn "No filesystem changes detected since last check."
|
||||
warn "Stopping monitor (Codex may have finished or is inactive)."
|
||||
|
||||
# Add final note to status
|
||||
cat >> "$STATUS_FILE" << EOF
|
||||
|
||||
## Monitor Stopped
|
||||
|
||||
**Stopped:** $(date '+%Y-%m-%d %H:%M:%S UTC')
|
||||
**Reason:** No filesystem activity detected
|
||||
|
||||
No changes were observed between this check and the previous one.
|
||||
This could mean:
|
||||
- Codex has completed work
|
||||
- Codex is paused or idle
|
||||
- No files have been modified recently
|
||||
|
||||
To restart monitoring, run: `./scripts/monitor.sh`
|
||||
EOF
|
||||
exit 0
|
||||
fi
|
||||
|
||||
generate_status $ITERATION
|
||||
|
||||
success "Iteration $ITERATION complete. Sleeping for 10 minutes..."
|
||||
sleep 600 # 10 minutes
|
||||
done
|
||||
}
|
||||
|
||||
# Handle signals
|
||||
trap 'error "Monitor interrupted"; exit 1' INT TERM
|
||||
|
||||
# Run main loop
|
||||
main
|
||||
Reference in New Issue
Block a user