bin/ 230 CLI tools (ask-*, br-*, agent-*, roadid, carpool) scripts/ 99 automation scripts fleet/ Node configs and deployment workers/ Cloudflare Worker sources (roadpay, road-search, squad webhooks) roadc/ RoadC programming language roadnet/ Mesh network (5 APs, WireGuard) operator/ Memory system scripts config/ System configs dotfiles/ Shell configs docs/ Documentation BlackRoad OS — Pave Tomorrow. RoadChain-SHA2048: d1a24f55318d338b RoadChain-Identity: alexa@sovereign RoadChain-Full: d1a24f55318d338b24b60bad7be39286379c76ae5470817482100cb0ddbbcb97e147d07ac7243da0a9f0363e4e5c833d612b9c0df3a3cd20802465420278ef74875a5b77f55af6fe42a931b8b635b3d0d0b6bde9abf33dc42eea52bc03c951406d8cbe49f1a3d29b26a94dade05e9477f34a7d4d4c6ec4005c3c2ac54e73a68440c512c8e83fd9b1fe234750b898ef8f4032c23db173961fe225e67a0432b5293a9714f76c5c57ed5fdf35b9fb40fd73c03ebf88b7253c6a0575f5afb6a6b49b3bda310602fb1ef676859962dad2aebbb2875814b30eee0a8ba195e482d4cbc91d8819e7f38f6db53e8063401649c77bb994371473cabfb917fb53e8cbe73d60
637 lines
22 KiB
Bash
Executable File
637 lines
22 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# BlackRoad Task Marketplace - Where Claudes find work!
|
|
# A revolutionary system for multi-Claude coordination at scale
|
|
# Now powered by SQLite for 100x faster operations
|
|
|
|
TASKS_DB="$HOME/.blackroad/memory/tasks.db"
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
PURPLE='\033[0;35m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
# Check for SQLite DB — backward compatibility
|
|
check_db() {
|
|
if [[ ! -f "$TASKS_DB" ]] || [[ ! -s "$TASKS_DB" ]]; then
|
|
echo -e "${RED}Database not found or empty at $TASKS_DB${NC}"
|
|
echo -e "${YELLOW}Initialize with:${NC} ${CYAN}$0 init${NC}"
|
|
echo -e "${YELLOW}Or migrate with:${NC} ${CYAN}~/blackroad-operator/scripts/memory/migrate-tasks-to-sqlite.sh${NC}"
|
|
exit 1
|
|
fi
|
|
# Verify schema exists
|
|
local has_table
|
|
has_table=$(sqlite3 "$TASKS_DB" "SELECT count(*) FROM sqlite_master WHERE type='table' AND name='tasks';" 2>/dev/null)
|
|
if [[ "$has_table" != "1" ]]; then
|
|
echo -e "${RED}Database exists but has no tasks table. Re-initialize:${NC}"
|
|
echo -e " ${CYAN}$0 init${NC}"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Helper: run a query
|
|
sql() {
|
|
sqlite3 "$TASKS_DB" "$@"
|
|
}
|
|
|
|
# Initialize marketplace (create DB + schema if needed)
|
|
init_marketplace() {
|
|
mkdir -p "$(dirname "$TASKS_DB")"
|
|
|
|
# Check if DB already has the tasks table
|
|
if [[ -f "$TASKS_DB" ]] && [[ -s "$TASKS_DB" ]]; then
|
|
local has_table
|
|
has_table=$(sqlite3 "$TASKS_DB" "SELECT count(*) FROM sqlite_master WHERE type='table' AND name='tasks';" 2>/dev/null)
|
|
if [[ "$has_table" == "1" ]]; then
|
|
echo -e "${GREEN}Task Marketplace already initialized at $TASKS_DB${NC}"
|
|
return
|
|
fi
|
|
fi
|
|
# Remove empty/corrupt DB file if present
|
|
rm -f "$TASKS_DB"
|
|
|
|
sqlite3 "$TASKS_DB" <<'SQL'
|
|
CREATE TABLE IF NOT EXISTS tasks (
|
|
task_id TEXT PRIMARY KEY,
|
|
title TEXT NOT NULL,
|
|
description TEXT DEFAULT '',
|
|
priority TEXT DEFAULT 'medium',
|
|
tags TEXT DEFAULT 'general',
|
|
skills TEXT DEFAULT 'any',
|
|
status TEXT NOT NULL DEFAULT 'available',
|
|
posted_at TEXT,
|
|
posted_by TEXT DEFAULT 'unknown',
|
|
claimed_by TEXT,
|
|
claimed_at TEXT,
|
|
timeout_at TEXT,
|
|
completed_at TEXT,
|
|
result TEXT
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_tasks_status ON tasks(status);
|
|
CREATE INDEX IF NOT EXISTS idx_tasks_priority ON tasks(priority);
|
|
CREATE INDEX IF NOT EXISTS idx_tasks_claimed_by ON tasks(claimed_by);
|
|
CREATE INDEX IF NOT EXISTS idx_tasks_posted_at ON tasks(posted_at);
|
|
|
|
CREATE VIRTUAL TABLE IF NOT EXISTS tasks_fts USING fts5(
|
|
task_id,
|
|
title,
|
|
description,
|
|
tags
|
|
);
|
|
SQL
|
|
|
|
echo -e "${GREEN}Task Marketplace initialized at $TASKS_DB${NC}"
|
|
}
|
|
|
|
# Post a new task
|
|
post_task() {
|
|
local task_id="$1"
|
|
local title="$2"
|
|
local description="$3"
|
|
local priority="${4:-medium}"
|
|
local tags="${5:-general}"
|
|
local skills="${6:-any}"
|
|
|
|
if [[ -z "$task_id" || -z "$title" ]]; then
|
|
echo -e "${RED}Usage: post <task-id> <title> <description> [priority] [tags] [skills]${NC}"
|
|
return 1
|
|
fi
|
|
|
|
check_db
|
|
|
|
local timestamp
|
|
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")
|
|
local posted_by="${MY_CLAUDE:-unknown}"
|
|
|
|
local esc_id esc_title esc_desc esc_priority esc_tags esc_skills esc_posted_by
|
|
esc_id=$(echo "$task_id" | sed "s/'/''/g")
|
|
esc_title=$(echo "$title" | sed "s/'/''/g")
|
|
esc_desc=$(echo "$description" | sed "s/'/''/g")
|
|
esc_priority=$(echo "$priority" | sed "s/'/''/g")
|
|
esc_tags=$(echo "$tags" | sed "s/'/''/g")
|
|
esc_skills=$(echo "$skills" | sed "s/'/''/g")
|
|
esc_posted_by=$(echo "$posted_by" | sed "s/'/''/g")
|
|
|
|
sql "BEGIN TRANSACTION;
|
|
INSERT INTO tasks (task_id, title, description, priority, tags, skills, status, posted_at, posted_by)
|
|
VALUES ('$esc_id', '$esc_title', '$esc_desc', '$esc_priority', '$esc_tags', '$esc_skills', 'available', '$timestamp', '$esc_posted_by')
|
|
ON CONFLICT(task_id) DO UPDATE SET
|
|
title=excluded.title, description=excluded.description, priority=excluded.priority,
|
|
tags=excluded.tags, skills=excluded.skills, posted_at=excluded.posted_at, posted_by=excluded.posted_by;
|
|
DELETE FROM tasks_fts WHERE task_id='$esc_id';
|
|
INSERT INTO tasks_fts (task_id, title, description, tags)
|
|
VALUES ('$esc_id', '$esc_title', '$esc_desc', '$esc_tags');
|
|
COMMIT;"
|
|
|
|
# Log to memory system
|
|
if [[ -x ~/memory-system.sh ]]; then
|
|
~/memory-system.sh log task-posted "$task_id" "New task: $title (Priority: $priority, Skills: $skills, Tags: $tags)" 2>/dev/null || true
|
|
fi
|
|
|
|
echo -e "${GREEN}Task posted: ${CYAN}$task_id${NC}"
|
|
echo -e " ${BLUE}Title:${NC} $title"
|
|
echo -e " ${BLUE}Priority:${NC} $priority"
|
|
echo -e " ${BLUE}Skills:${NC} $skills"
|
|
}
|
|
|
|
# List available tasks
|
|
list_tasks() {
|
|
local filter_priority="$1"
|
|
local filter_tags="$2"
|
|
|
|
check_db
|
|
|
|
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
|
|
echo -e "${CYAN}║ BLACKROAD TASK MARKETPLACE ║${NC}"
|
|
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
|
|
echo ""
|
|
|
|
local available_count claimed_count completed_count
|
|
available_count=$(sql "SELECT COUNT(*) FROM tasks WHERE status='available';")
|
|
claimed_count=$(sql "SELECT COUNT(*) FROM tasks WHERE status='claimed';")
|
|
completed_count=$(sql "SELECT COUNT(*) FROM tasks WHERE status='completed';")
|
|
|
|
echo -e "${GREEN}Available:${NC} $available_count ${YELLOW}In Progress:${NC} $claimed_count ${BLUE}Completed:${NC} $completed_count"
|
|
echo ""
|
|
|
|
if [[ "$available_count" -eq 0 ]]; then
|
|
echo -e "${YELLOW}No tasks available. Post one with: ./memory-task-marketplace.sh post <task-id> <title> <description>${NC}"
|
|
return
|
|
fi
|
|
|
|
echo -e "${PURPLE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
|
|
# Build query with optional filters
|
|
local where="WHERE status='available'"
|
|
if [[ -n "$filter_priority" ]]; then
|
|
where="$where AND priority='$(echo "$filter_priority" | sed "s/'/''/g")'"
|
|
fi
|
|
if [[ -n "$filter_tags" ]]; then
|
|
where="$where AND tags LIKE '%$(echo "$filter_tags" | sed "s/'/''/g")%'"
|
|
fi
|
|
|
|
local IFS=$'\n'
|
|
local rows
|
|
rows=$(sql -separator '|' "SELECT task_id, title, priority, tags, skills, posted_at FROM tasks $where ORDER BY
|
|
CASE priority WHEN 'urgent' THEN 0 WHEN 'high' THEN 1 WHEN 'medium' THEN 2 WHEN 'low' THEN 3 ELSE 4 END,
|
|
posted_at DESC;")
|
|
|
|
for row in $rows; do
|
|
local task_id title priority tags skills posted_at
|
|
task_id=$(echo "$row" | cut -d'|' -f1)
|
|
title=$(echo "$row" | cut -d'|' -f2)
|
|
priority=$(echo "$row" | cut -d'|' -f3)
|
|
tags=$(echo "$row" | cut -d'|' -f4)
|
|
skills=$(echo "$row" | cut -d'|' -f5)
|
|
posted_at=$(echo "$row" | cut -d'|' -f6)
|
|
|
|
# Priority color
|
|
local priority_color="$NC"
|
|
case "$priority" in
|
|
high|urgent) priority_color="$RED" ;;
|
|
medium) priority_color="$YELLOW" ;;
|
|
low) priority_color="$GREEN" ;;
|
|
esac
|
|
|
|
echo -e "${CYAN}$task_id${NC}"
|
|
echo -e " ${BLUE}Title:${NC} $title"
|
|
echo -e " ${BLUE}Priority:${NC} ${priority_color}$priority${NC}"
|
|
echo -e " ${BLUE}Skills:${NC} $skills"
|
|
echo -e " ${BLUE}Tags:${NC} $tags"
|
|
echo -e " ${BLUE}Posted:${NC} $posted_at"
|
|
echo -e " ${GREEN}Claim with:${NC} ./memory-task-marketplace.sh claim $task_id"
|
|
echo ""
|
|
done
|
|
|
|
echo -e "${PURPLE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
}
|
|
|
|
# Claim a task
|
|
claim_task() {
|
|
local task_id="$1"
|
|
local claude_id="${2:-${MY_CLAUDE:-unknown}}"
|
|
local timeout_minutes="${3:-30}"
|
|
|
|
if [[ -z "$task_id" ]]; then
|
|
echo -e "${RED}Usage: claim <task-id> [claude-id] [timeout-minutes]${NC}"
|
|
return 1
|
|
fi
|
|
|
|
check_db
|
|
|
|
# Check task exists and is available
|
|
local current_status
|
|
current_status=$(sql "SELECT status FROM tasks WHERE task_id='$(echo "$task_id" | sed "s/'/''/g")';")
|
|
|
|
if [[ -z "$current_status" ]]; then
|
|
echo -e "${RED}Task not found: $task_id${NC}"
|
|
echo -e "${YELLOW}Available tasks:${NC}"
|
|
sql "SELECT ' - ' || task_id FROM tasks WHERE status='available' LIMIT 20;"
|
|
return 1
|
|
fi
|
|
|
|
if [[ "$current_status" != "available" ]]; then
|
|
echo -e "${RED}Task $task_id is not available (status: $current_status)${NC}"
|
|
return 1
|
|
fi
|
|
|
|
local timestamp timeout_at
|
|
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")
|
|
timeout_at=$(date -u -v+"${timeout_minutes}"M +"%Y-%m-%dT%H:%M:%S.%3NZ" 2>/dev/null || date -u -d "+${timeout_minutes} minutes" +"%Y-%m-%dT%H:%M:%S.%3NZ")
|
|
|
|
sql "BEGIN TRANSACTION;
|
|
UPDATE tasks SET
|
|
status='claimed',
|
|
claimed_by='$(echo "$claude_id" | sed "s/'/''/g")',
|
|
claimed_at='$timestamp',
|
|
timeout_at='$timeout_at'
|
|
WHERE task_id='$(echo "$task_id" | sed "s/'/''/g")' AND status='available';
|
|
COMMIT;"
|
|
|
|
# Log to memory
|
|
if [[ -x ~/memory-system.sh ]]; then
|
|
~/memory-system.sh log task-claimed "$task_id" "Claimed by $claude_id (timeout: ${timeout_minutes}m)" 2>/dev/null || true
|
|
fi
|
|
|
|
echo -e "${GREEN}Task claimed: ${CYAN}$task_id${NC}"
|
|
echo -e " ${BLUE}Claimed by:${NC} $claude_id"
|
|
echo -e " ${BLUE}Timeout:${NC} ${timeout_minutes} minutes ($timeout_at)"
|
|
echo -e " ${YELLOW}Complete with:${NC} ./memory-task-marketplace.sh complete $task_id"
|
|
}
|
|
|
|
# Complete a task
|
|
complete_task() {
|
|
local task_id="$1"
|
|
local result="${2:-Success}"
|
|
|
|
if [[ -z "$task_id" ]]; then
|
|
echo -e "${RED}Usage: complete <task-id> [result]${NC}"
|
|
return 1
|
|
fi
|
|
|
|
check_db
|
|
|
|
local current_status
|
|
current_status=$(sql "SELECT status FROM tasks WHERE task_id='$(echo "$task_id" | sed "s/'/''/g")';")
|
|
|
|
if [[ "$current_status" != "claimed" ]]; then
|
|
echo -e "${RED}Claimed task not found: $task_id (status: ${current_status:-not found})${NC}"
|
|
return 1
|
|
fi
|
|
|
|
local timestamp
|
|
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%S.%3NZ")
|
|
|
|
sql "BEGIN TRANSACTION;
|
|
UPDATE tasks SET
|
|
status='completed',
|
|
completed_at='$timestamp',
|
|
result='$(echo "$result" | sed "s/'/''/g")'
|
|
WHERE task_id='$(echo "$task_id" | sed "s/'/''/g")' AND status='claimed';
|
|
COMMIT;"
|
|
|
|
# Log to memory
|
|
if [[ -x ~/memory-system.sh ]]; then
|
|
~/memory-system.sh log task-completed "$task_id" "Completed: $result" 2>/dev/null || true
|
|
fi
|
|
|
|
echo -e "${GREEN}Task completed: ${CYAN}$task_id${NC}"
|
|
echo -e " ${BLUE}Result:${NC} $result"
|
|
}
|
|
|
|
# Release a task (if can't complete)
|
|
release_task() {
|
|
local task_id="$1"
|
|
local reason="${2:-No reason given}"
|
|
|
|
if [[ -z "$task_id" ]]; then
|
|
echo -e "${RED}Usage: release <task-id> [reason]${NC}"
|
|
return 1
|
|
fi
|
|
|
|
check_db
|
|
|
|
local current_status
|
|
current_status=$(sql "SELECT status FROM tasks WHERE task_id='$(echo "$task_id" | sed "s/'/''/g")';")
|
|
|
|
if [[ "$current_status" != "claimed" ]]; then
|
|
echo -e "${RED}Claimed task not found: $task_id (status: ${current_status:-not found})${NC}"
|
|
return 1
|
|
fi
|
|
|
|
sql "BEGIN TRANSACTION;
|
|
UPDATE tasks SET
|
|
status='available',
|
|
claimed_by=NULL,
|
|
claimed_at=NULL,
|
|
timeout_at=NULL
|
|
WHERE task_id='$(echo "$task_id" | sed "s/'/''/g")' AND status='claimed';
|
|
COMMIT;"
|
|
|
|
# Log to memory
|
|
if [[ -x ~/memory-system.sh ]]; then
|
|
~/memory-system.sh log task-released "$task_id" "Released: $reason" 2>/dev/null || true
|
|
fi
|
|
|
|
echo -e "${YELLOW}Task released: ${CYAN}$task_id${NC}"
|
|
echo -e " ${BLUE}Reason:${NC} $reason"
|
|
}
|
|
|
|
# Show tasks claimed by current Claude
|
|
my_tasks() {
|
|
check_db
|
|
|
|
local claude_id="${MY_CLAUDE:-unknown}"
|
|
|
|
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
|
|
echo -e "${CYAN}║ My Tasks ($claude_id) ║${NC}"
|
|
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
|
|
echo ""
|
|
|
|
local IFS=$'\n'
|
|
local rows
|
|
rows=$(sql -separator '|' "SELECT task_id, title, claimed_at, timeout_at FROM tasks
|
|
WHERE status='claimed' AND claimed_by='$(echo "$claude_id" | sed "s/'/''/g")'
|
|
ORDER BY claimed_at DESC;")
|
|
|
|
if [[ -z "$rows" ]]; then
|
|
echo -e "${YELLOW}No tasks claimed by you. Browse available tasks with: ./memory-task-marketplace.sh list${NC}"
|
|
return
|
|
fi
|
|
|
|
for row in $rows; do
|
|
local task_id title claimed_at timeout_at
|
|
task_id=$(echo "$row" | cut -d'|' -f1)
|
|
title=$(echo "$row" | cut -d'|' -f2)
|
|
claimed_at=$(echo "$row" | cut -d'|' -f3)
|
|
timeout_at=$(echo "$row" | cut -d'|' -f4)
|
|
|
|
echo -e "${CYAN}$task_id${NC}"
|
|
echo -e " ${BLUE}Title:${NC} $title"
|
|
echo -e " ${BLUE}Claimed:${NC} $claimed_at"
|
|
echo -e " ${BLUE}Timeout:${NC} $timeout_at"
|
|
echo -e " ${GREEN}Complete:${NC} ./memory-task-marketplace.sh complete $task_id"
|
|
echo ""
|
|
done
|
|
}
|
|
|
|
# Show statistics
|
|
show_stats() {
|
|
check_db
|
|
|
|
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
|
|
echo -e "${CYAN}║ Task Marketplace Statistics ║${NC}"
|
|
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
|
|
echo ""
|
|
|
|
local available_count claimed_count completed_count total
|
|
available_count=$(sql "SELECT COUNT(*) FROM tasks WHERE status='available';")
|
|
claimed_count=$(sql "SELECT COUNT(*) FROM tasks WHERE status='claimed';")
|
|
completed_count=$(sql "SELECT COUNT(*) FROM tasks WHERE status='completed';")
|
|
total=$(sql "SELECT COUNT(*) FROM tasks;")
|
|
|
|
echo -e "${GREEN}Total Tasks:${NC} $total"
|
|
echo -e "${YELLOW}Available:${NC} $available_count"
|
|
echo -e "${BLUE}Claimed:${NC} $claimed_count"
|
|
echo -e "${PURPLE}Completed:${NC} $completed_count"
|
|
echo ""
|
|
|
|
if [[ "$total" -gt 0 ]]; then
|
|
local completion_rate=$((completed_count * 100 / total))
|
|
echo -e "${GREEN}Completion Rate:${NC} ${completion_rate}%"
|
|
fi
|
|
|
|
echo ""
|
|
|
|
# Priority breakdown
|
|
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
|
echo -e "${BLUE}By Priority:${NC}"
|
|
local IFS=$'\n'
|
|
local prows
|
|
prows=$(sql -separator '|' "SELECT priority, COUNT(*) FROM tasks WHERE status='available' GROUP BY priority ORDER BY
|
|
CASE priority WHEN 'urgent' THEN 0 WHEN 'high' THEN 1 WHEN 'medium' THEN 2 WHEN 'low' THEN 3 ELSE 4 END;")
|
|
for row in $prows; do
|
|
local p c
|
|
p=$(echo "$row" | cut -d'|' -f1)
|
|
c=$(echo "$row" | cut -d'|' -f2)
|
|
echo -e " ${YELLOW}$p:${NC} $c"
|
|
done
|
|
|
|
echo ""
|
|
|
|
# Active workers
|
|
if [[ "$claimed_count" -gt 0 ]]; then
|
|
echo -e "${BLUE}Active Workers:${NC}"
|
|
local wrows
|
|
wrows=$(sql -separator '|' "SELECT claimed_by, task_id, title FROM tasks WHERE status='claimed' ORDER BY claimed_at DESC;")
|
|
for row in $wrows; do
|
|
local claimed_by task_id title
|
|
claimed_by=$(echo "$row" | cut -d'|' -f1)
|
|
task_id=$(echo "$row" | cut -d'|' -f2)
|
|
title=$(echo "$row" | cut -d'|' -f3)
|
|
echo -e " ${CYAN}$claimed_by${NC} -> $task_id: $title"
|
|
done
|
|
fi
|
|
|
|
echo ""
|
|
local db_size
|
|
db_size=$(du -h "$TASKS_DB" | cut -f1)
|
|
echo -e "${BLUE}Database size:${NC} $db_size"
|
|
}
|
|
|
|
# Search tasks using FTS5
|
|
search_tasks() {
|
|
local query="$1"
|
|
|
|
if [[ -z "$query" ]]; then
|
|
echo -e "${RED}Usage: search <query>${NC}"
|
|
echo -e " Example: search \"deploy api\""
|
|
return 1
|
|
fi
|
|
|
|
check_db
|
|
|
|
echo -e "${CYAN}╔════════════════════════════════════════════════════════════╗${NC}"
|
|
echo -e "${CYAN}║ Search Results: $query${NC}"
|
|
echo -e "${CYAN}╚════════════════════════════════════════════════════════════╝${NC}"
|
|
echo ""
|
|
|
|
local IFS=$'\n'
|
|
local rows
|
|
rows=$(sql -separator '|' "SELECT t.task_id, t.title, t.status, t.priority, t.tags, t.description
|
|
FROM tasks_fts f
|
|
JOIN tasks t ON t.task_id = f.task_id
|
|
WHERE tasks_fts MATCH '$(echo "$query" | sed "s/'/''/g")'
|
|
ORDER BY rank
|
|
LIMIT 50;")
|
|
|
|
if [[ -z "$rows" ]]; then
|
|
echo -e "${YELLOW}No tasks found matching: $query${NC}"
|
|
return
|
|
fi
|
|
|
|
local count=0
|
|
for row in $rows; do
|
|
local task_id title status priority tags description
|
|
task_id=$(echo "$row" | cut -d'|' -f1)
|
|
title=$(echo "$row" | cut -d'|' -f2)
|
|
status=$(echo "$row" | cut -d'|' -f3)
|
|
priority=$(echo "$row" | cut -d'|' -f4)
|
|
tags=$(echo "$row" | cut -d'|' -f5)
|
|
description=$(echo "$row" | cut -d'|' -f6)
|
|
|
|
local status_color="$NC"
|
|
case "$status" in
|
|
available) status_color="$GREEN" ;;
|
|
claimed) status_color="$YELLOW" ;;
|
|
completed) status_color="$PURPLE" ;;
|
|
esac
|
|
|
|
echo -e "${CYAN}$task_id${NC} [${status_color}$status${NC}]"
|
|
echo -e " ${BLUE}Title:${NC} $title"
|
|
echo -e " ${BLUE}Priority:${NC} $priority ${BLUE}Tags:${NC} $tags"
|
|
if [[ -n "$description" ]]; then
|
|
echo -e " ${BLUE}Description:${NC} ${description:0:120}"
|
|
fi
|
|
echo ""
|
|
((count++))
|
|
done
|
|
|
|
echo -e "${GREEN}Found $count matching tasks.${NC}"
|
|
}
|
|
|
|
# Cleanup completed tasks older than 30 days
|
|
cleanup_tasks() {
|
|
check_db
|
|
|
|
local cutoff_date
|
|
cutoff_date=$(date -u -v-30d +"%Y-%m-%dT%H:%M:%S" 2>/dev/null || date -u -d "-30 days" +"%Y-%m-%dT%H:%M:%S")
|
|
|
|
local to_delete
|
|
to_delete=$(sql "SELECT COUNT(*) FROM tasks WHERE status='completed' AND completed_at < '$cutoff_date';")
|
|
|
|
if [[ "$to_delete" -eq 0 ]]; then
|
|
echo -e "${GREEN}No completed tasks older than 30 days to clean up.${NC}"
|
|
return
|
|
fi
|
|
|
|
echo -e "${YELLOW}Found $to_delete completed tasks older than 30 days.${NC}"
|
|
|
|
sql "BEGIN TRANSACTION;
|
|
DELETE FROM tasks_fts WHERE task_id IN (SELECT task_id FROM tasks WHERE status='completed' AND completed_at < '$cutoff_date');
|
|
DELETE FROM tasks WHERE status='completed' AND completed_at < '$cutoff_date';
|
|
COMMIT;"
|
|
|
|
# Optimize DB after bulk delete
|
|
sql "VACUUM;"
|
|
|
|
echo -e "${GREEN}Purged $to_delete old completed tasks. Database vacuumed.${NC}"
|
|
}
|
|
|
|
# Show help
|
|
show_help() {
|
|
cat << EOF
|
|
${CYAN}╔════════════════════════════════════════════════════════════╗${NC}
|
|
${CYAN}║ BlackRoad Task Marketplace - Help ║${NC}
|
|
${CYAN}╚════════════════════════════════════════════════════════════╝${NC}
|
|
|
|
${GREEN}USAGE:${NC}
|
|
$0 <command> [options]
|
|
|
|
${GREEN}COMMANDS:${NC}
|
|
|
|
${BLUE}init${NC}
|
|
Initialize the task marketplace (creates SQLite DB)
|
|
|
|
${BLUE}post${NC} <task-id> <title> <description> [priority] [tags] [skills]
|
|
Post a new task
|
|
Priority: urgent|high|medium|low (default: medium)
|
|
Example: post auth-impl "Implement OAuth2" "Add OAuth2 auth" high backend backend-auth
|
|
|
|
${BLUE}list${NC} [priority] [tags]
|
|
List available tasks (optionally filtered)
|
|
Example: list high backend
|
|
|
|
${BLUE}claim${NC} <task-id> [claude-id] [timeout-minutes]
|
|
Claim a task to work on it (default timeout: 30 minutes)
|
|
Example: claim auth-impl claude-auth-specialist 60
|
|
|
|
${BLUE}complete${NC} <task-id> [result]
|
|
Mark a claimed task as completed
|
|
Example: complete auth-impl "OAuth2 implemented, tested, deployed"
|
|
|
|
${BLUE}release${NC} <task-id> [reason]
|
|
Release a claimed task back to available
|
|
Example: release auth-impl "Blocked on API deployment"
|
|
|
|
${BLUE}my-tasks${NC}
|
|
Show tasks claimed by you
|
|
|
|
${BLUE}stats${NC}
|
|
Show marketplace statistics
|
|
|
|
${BLUE}search${NC} <query>
|
|
Full-text search across task titles, descriptions, and tags
|
|
Example: search "deploy api"
|
|
|
|
${BLUE}cleanup${NC}
|
|
Purge completed tasks older than 30 days
|
|
|
|
${GREEN}WORKFLOW:${NC}
|
|
|
|
1. Someone posts tasks to the marketplace
|
|
2. Claudes browse available tasks (list) or search
|
|
3. Claude claims a task to work on it
|
|
4. Claude completes the task (or releases if blocked)
|
|
5. Task moves to completed!
|
|
|
|
EOF
|
|
}
|
|
|
|
# Main command router
|
|
case "$1" in
|
|
init)
|
|
init_marketplace
|
|
;;
|
|
post)
|
|
post_task "$2" "$3" "$4" "$5" "$6" "$7"
|
|
;;
|
|
list)
|
|
list_tasks "$2" "$3"
|
|
;;
|
|
claim)
|
|
claim_task "$2" "$3" "$4"
|
|
;;
|
|
complete)
|
|
complete_task "$2" "$3"
|
|
;;
|
|
release)
|
|
release_task "$2" "$3"
|
|
;;
|
|
my-tasks)
|
|
my_tasks
|
|
;;
|
|
stats)
|
|
show_stats
|
|
;;
|
|
search)
|
|
search_tasks "$2"
|
|
;;
|
|
cleanup)
|
|
cleanup_tasks
|
|
;;
|
|
help|--help|-h)
|
|
show_help
|
|
;;
|
|
*)
|
|
echo -e "${RED}Unknown command: $1${NC}"
|
|
echo -e "Run ${CYAN}$0 help${NC} for usage information"
|
|
exit 1
|
|
;;
|
|
esac
|