@cyperx/clawforge 1.4.1 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/VERSION +1 -1
- package/bin/clawforge +2 -0
- package/bin/clawforge-dashboard +0 -0
- package/bin/deps.sh +70 -0
- package/bin/spawn-agent.sh +10 -9
- package/bin/sprint.sh +5 -1
- package/bin/swarm.sh +33 -1
- package/package.json +1 -1
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.
|
|
1
|
+
1.5.1
|
package/bin/clawforge
CHANGED
|
@@ -83,6 +83,7 @@ Power Features (v1.2):
|
|
|
83
83
|
|
|
84
84
|
Web Dashboard (v1.4):
|
|
85
85
|
web Launch web dashboard (accessible from phone/browser)
|
|
86
|
+
deps Show task dependency graph / blocked tasks
|
|
86
87
|
|
|
87
88
|
Developer Experience (v1.3):
|
|
88
89
|
profile Manage reusable agent profiles (presets)
|
|
@@ -250,6 +251,7 @@ doctor) exec "${BIN_DIR}/doctor.sh" "$@" ;;
|
|
|
250
251
|
export) exec "${BIN_DIR}/export.sh" "$@" ;;
|
|
251
252
|
completions) exec "${BIN_DIR}/completions.sh" "$@" ;;
|
|
252
253
|
web) exec "${BIN_DIR}/web.sh" "$@" ;;
|
|
254
|
+
deps) exec "${BIN_DIR}/deps.sh" "$@" ;;
|
|
253
255
|
logs) exec "${BIN_DIR}/logs.sh" "$@" ;;
|
|
254
256
|
on-complete) exec "${BIN_DIR}/on-complete.sh" "$@" ;;
|
|
255
257
|
|
package/bin/clawforge-dashboard
CHANGED
|
Binary file
|
package/bin/deps.sh
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# deps.sh — Show task dependency graph and blocked tasks
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
5
|
+
source "${SCRIPT_DIR}/../lib/common.sh"
|
|
6
|
+
|
|
7
|
+
usage(){ cat <<EOF
|
|
8
|
+
Usage: clawforge deps [options]
|
|
9
|
+
|
|
10
|
+
Show dependency graph for active tasks.
|
|
11
|
+
|
|
12
|
+
Options:
|
|
13
|
+
--json Output JSON graph
|
|
14
|
+
--blocked Show only blocked tasks
|
|
15
|
+
--help Show help
|
|
16
|
+
EOF
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
JSON_OUTPUT=false
|
|
20
|
+
BLOCKED_ONLY=false
|
|
21
|
+
while [[ $# -gt 0 ]]; do
|
|
22
|
+
case "$1" in
|
|
23
|
+
--json) JSON_OUTPUT=true; shift ;;
|
|
24
|
+
--blocked) BLOCKED_ONLY=true; shift ;;
|
|
25
|
+
--help|-h) usage; exit 0 ;;
|
|
26
|
+
*) log_error "Unknown option: $1"; usage; exit 1 ;;
|
|
27
|
+
esac
|
|
28
|
+
done
|
|
29
|
+
|
|
30
|
+
_ensure_registry
|
|
31
|
+
tasks=$(jq '.tasks' "$REGISTRY_FILE" 2>/dev/null || echo '[]')
|
|
32
|
+
|
|
33
|
+
if $JSON_OUTPUT; then
|
|
34
|
+
jq -n --argjson tasks "$tasks" '
|
|
35
|
+
{
|
|
36
|
+
nodes: ($tasks | map({id:.id, short_id:.short_id, description:.description, status:.status})),
|
|
37
|
+
edges: ($tasks | map(select(.depends_on != null) | {from:.depends_on, to:.id}))
|
|
38
|
+
}'
|
|
39
|
+
exit 0
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
echo "Dependency Graph"
|
|
43
|
+
echo ""
|
|
44
|
+
count=$(echo "$tasks" | jq 'length')
|
|
45
|
+
if [[ "$count" == "0" ]]; then
|
|
46
|
+
echo "(no active tasks)"
|
|
47
|
+
exit 0
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
echo "$tasks" | jq -r '.[] | [.id, (.short_id//0|tostring), (.description//"—"), (.status//"—"), (.depends_on//"")] | @tsv' | while IFS=$' ' read -r id sid desc status dep; do
|
|
51
|
+
if $BLOCKED_ONLY; then
|
|
52
|
+
[[ -z "$dep" ]] && continue
|
|
53
|
+
dep_status=$(echo "$tasks" | jq -r --arg d "$dep" '.[] | select(.id==$d) | .status' 2>/dev/null || true)
|
|
54
|
+
[[ "$dep_status" == "done" ]] && continue
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
if [[ -n "$dep" ]]; then
|
|
58
|
+
dep_sid=$(echo "$tasks" | jq -r --arg d "$dep" '.[] | select(.id==$d) | (.short_id//0|tostring)' 2>/dev/null || echo "?")
|
|
59
|
+
dep_status=$(echo "$tasks" | jq -r --arg d "$dep" '.[] | select(.id==$d) | .status' 2>/dev/null || echo "?")
|
|
60
|
+
blocked=""
|
|
61
|
+
[[ "$dep_status" != "done" ]] && blocked=" [blocked]"
|
|
62
|
+
echo " #$sid ($status)$blocked"
|
|
63
|
+
echo " └─ waits for #$dep_sid ($dep_status)"
|
|
64
|
+
echo " $desc"
|
|
65
|
+
else
|
|
66
|
+
echo " #$sid ($status)"
|
|
67
|
+
echo " $desc"
|
|
68
|
+
fi
|
|
69
|
+
echo ""
|
|
70
|
+
done
|
package/bin/spawn-agent.sh
CHANGED
|
@@ -24,7 +24,7 @@ EOF
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
# ── Parse args ─────────────────────────────────────────────────────────
|
|
27
|
-
REPO="" BRANCH="" TASK="" AGENT="" MODEL="" EFFORT="" DRY_RUN=false AFTER=""
|
|
27
|
+
REPO="" BRANCH="" TASK="" AGENT="" MODEL="" EFFORT="" DRY_RUN=false AFTER="" DEP_ID=""
|
|
28
28
|
|
|
29
29
|
while [[ $# -gt 0 ]]; do
|
|
30
30
|
case "$1" in
|
|
@@ -49,26 +49,27 @@ done
|
|
|
49
49
|
|
|
50
50
|
# ── Wait for dependency ──────────────────────────────────────────────
|
|
51
51
|
if [[ -n "$AFTER" ]]; then
|
|
52
|
-
|
|
52
|
+
DEP_ID=$(resolve_task_id "$AFTER")
|
|
53
|
+
[[ -z "$DEP_ID" ]] && { log_error "Dependency '$AFTER' not found"; exit 1; }
|
|
54
|
+
log_info "Waiting for task $AFTER ($DEP_ID) to complete before spawning..."
|
|
53
55
|
WAIT_TIMEOUT=${CLAWFORGE_DEP_TIMEOUT:-3600} # 1 hour default
|
|
54
56
|
ELAPSED=0
|
|
55
57
|
INTERVAL=5
|
|
56
58
|
while [[ $ELAPSED -lt $WAIT_TIMEOUT ]]; do
|
|
57
|
-
DEP_STATUS
|
|
58
|
-
if [[ "$AFTER" =~ ^[0-9]+$ ]]; then
|
|
59
|
-
DEP_STATUS=$(jq -r --argjson sid "$AFTER" '.tasks[] | select(.short_id == $sid) | .status' "$REGISTRY_FILE" 2>/dev/null || true)
|
|
60
|
-
else
|
|
61
|
-
DEP_STATUS=$(jq -r --arg id "$AFTER" '.tasks[] | select(.id == $id) | .status' "$REGISTRY_FILE" 2>/dev/null || true)
|
|
62
|
-
fi
|
|
59
|
+
DEP_STATUS=$(jq -r --arg id "$DEP_ID" '.tasks[] | select(.id == $id) | .status' "$REGISTRY_FILE" 2>/dev/null || true)
|
|
63
60
|
case "$DEP_STATUS" in
|
|
64
61
|
done)
|
|
65
62
|
log_info "Dependency $AFTER completed. Spawning..."
|
|
66
63
|
break
|
|
67
64
|
;;
|
|
68
|
-
failed|timeout|cancelled)
|
|
65
|
+
failed|timeout|cancelled|stopped)
|
|
69
66
|
log_error "Dependency $AFTER ended with status: $DEP_STATUS. Aborting spawn."
|
|
70
67
|
exit 1
|
|
71
68
|
;;
|
|
69
|
+
"")
|
|
70
|
+
log_error "Dependency $AFTER not found in registry."
|
|
71
|
+
exit 1
|
|
72
|
+
;;
|
|
72
73
|
*)
|
|
73
74
|
sleep $INTERVAL
|
|
74
75
|
ELAPSED=$((ELAPSED + INTERVAL))
|
package/bin/sprint.sh
CHANGED
|
@@ -21,6 +21,7 @@ Arguments:
|
|
|
21
21
|
Flags:
|
|
22
22
|
--quick Patch mode: auto-branch, auto-merge, skip review, targeted tests
|
|
23
23
|
--branch <name> Override auto-generated branch name
|
|
24
|
+
--after <id> Wait for task <id> to complete before starting
|
|
24
25
|
--agent <name> Agent to use: claude or codex (default: auto-detect)
|
|
25
26
|
--model <model> Model override
|
|
26
27
|
--routing <strategy> Model routing: auto, cheap, or quality (--model overrides)
|
|
@@ -47,7 +48,7 @@ EOF
|
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
# ── Parse args ────────────────────────────────────────────────────────
|
|
50
|
-
REPO="" TASK="" BRANCH="" AGENT="" MODEL="" QUICK=false AUTO_MERGE=false DRY_RUN=false
|
|
51
|
+
REPO="" TASK="" BRANCH="" AGENT="" MODEL="" QUICK=false AUTO_MERGE=false DRY_RUN=false AFTER=""
|
|
51
52
|
TEMPLATE="" CI_LOOP=false MAX_CI_RETRIES=3 BUDGET="" JSON_OUTPUT=false NOTIFY=false WEBHOOK="" ROUTING=""
|
|
52
53
|
AUTO_CLEAN=false
|
|
53
54
|
TIMEOUT_MIN=""
|
|
@@ -57,6 +58,7 @@ while [[ $# -gt 0 ]]; do
|
|
|
57
58
|
case "$1" in
|
|
58
59
|
--quick) QUICK=true; shift ;;
|
|
59
60
|
--branch) BRANCH="$2"; shift 2 ;;
|
|
61
|
+
--after) AFTER="$2"; shift 2 ;;
|
|
60
62
|
--agent) AGENT="$2"; shift 2 ;;
|
|
61
63
|
--model) MODEL="$2"; shift 2 ;;
|
|
62
64
|
--routing) ROUTING="$2"; shift 2 ;;
|
|
@@ -177,6 +179,7 @@ if $DRY_RUN; then
|
|
|
177
179
|
echo " Auto-merge: $AUTO_MERGE"
|
|
178
180
|
echo " Quick: $QUICK"
|
|
179
181
|
[[ -n "$ROUTING" ]] && echo " Routing: $ROUTING"
|
|
182
|
+
[[ -n "$AFTER" ]] && echo " After: $AFTER"
|
|
180
183
|
echo ""
|
|
181
184
|
echo "Would execute:"
|
|
182
185
|
echo " 1. Scope task"
|
|
@@ -223,6 +226,7 @@ fi
|
|
|
223
226
|
SPAWN_ARGS=(--repo "$REPO_ABS" --branch "$BRANCH" --task "$PROMPT")
|
|
224
227
|
[[ -n "${AGENT:-}" ]] && SPAWN_ARGS+=(--agent "$AGENT")
|
|
225
228
|
[[ -n "${SPAWN_MODEL:-}" ]] && SPAWN_ARGS+=(--model "$SPAWN_MODEL")
|
|
229
|
+
[[ -n "${AFTER:-}" ]] && SPAWN_ARGS+=(--after "$AFTER")
|
|
226
230
|
|
|
227
231
|
TASK_JSON=$("${SCRIPT_DIR}/spawn-agent.sh" "${SPAWN_ARGS[@]}" 2>/dev/null || true)
|
|
228
232
|
|
package/bin/swarm.sh
CHANGED
|
@@ -22,6 +22,7 @@ Flags:
|
|
|
22
22
|
--repos <paths> Comma-separated repo paths (one agent per repo, skips decomposition)
|
|
23
23
|
--repos-file <path> File with repo paths, one per line
|
|
24
24
|
--routing <strategy> Model routing: auto, cheap, or quality
|
|
25
|
+
--after <id> Wait for task <id> to complete before starting swarm
|
|
25
26
|
--max-agents <N> Cap parallel agents (default: 3)
|
|
26
27
|
--agent <name> Force specific agent for all sub-tasks
|
|
27
28
|
--auto-merge Merge each PR automatically after CI + review
|
|
@@ -48,7 +49,7 @@ EOF
|
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
# ── Parse args ────────────────────────────────────────────────────────
|
|
51
|
-
REPO="" TASK="" MAX_AGENTS=3 AGENT="" AUTO_MERGE=false DRY_RUN=false SKIP_CONFIRM=false
|
|
52
|
+
REPO="" TASK="" MAX_AGENTS=3 AGENT="" AUTO_MERGE=false DRY_RUN=false SKIP_CONFIRM=false AFTER=""
|
|
52
53
|
TEMPLATE="" CI_LOOP=false MAX_CI_RETRIES=3 BUDGET="" JSON_OUTPUT=false NOTIFY=false WEBHOOK=""
|
|
53
54
|
REPOS="" REPOS_FILE="" ROUTING="" MULTI_REPO=false AUTO_CLEAN=false TIMEOUT_MIN=""
|
|
54
55
|
POSITIONAL=()
|
|
@@ -58,6 +59,7 @@ while [[ $# -gt 0 ]]; do
|
|
|
58
59
|
--repos) REPOS="$2"; shift 2 ;;
|
|
59
60
|
--repos-file) REPOS_FILE="$2"; shift 2 ;;
|
|
60
61
|
--routing) ROUTING="$2"; shift 2 ;;
|
|
62
|
+
--after) AFTER="$2"; shift 2 ;;
|
|
61
63
|
--max-agents) MAX_AGENTS="$2"; shift 2 ;;
|
|
62
64
|
--agent) AGENT="$2"; shift 2 ;;
|
|
63
65
|
--auto-merge) AUTO_MERGE=true; shift ;;
|
|
@@ -137,6 +139,36 @@ if $MULTI_REPO; then
|
|
|
137
139
|
REPO="${REPO_LIST[0]}"
|
|
138
140
|
fi
|
|
139
141
|
|
|
142
|
+
|
|
143
|
+
# ── Dependency wait (optional) ──────────────────────────────────────
|
|
144
|
+
if [[ -n "$AFTER" ]]; then
|
|
145
|
+
DEP_ID=$(resolve_task_id "$AFTER")
|
|
146
|
+
[[ -z "$DEP_ID" ]] && { log_error "Dependency '$AFTER' not found"; exit 1; }
|
|
147
|
+
log_info "Waiting for task $AFTER ($DEP_ID) to complete before swarm starts..."
|
|
148
|
+
WAIT_TIMEOUT=${CLAWFORGE_DEP_TIMEOUT:-3600}
|
|
149
|
+
ELAPSED=0
|
|
150
|
+
INTERVAL=5
|
|
151
|
+
while [[ $ELAPSED -lt $WAIT_TIMEOUT ]]; do
|
|
152
|
+
DEP_STATUS=$(jq -r --arg id "$DEP_ID" '.tasks[] | select(.id == $id) | .status' "$REGISTRY_FILE" 2>/dev/null || true)
|
|
153
|
+
case "$DEP_STATUS" in
|
|
154
|
+
done) break ;;
|
|
155
|
+
failed|timeout|cancelled|stopped)
|
|
156
|
+
log_error "Dependency $AFTER ended with status: $DEP_STATUS. Aborting swarm."
|
|
157
|
+
exit 1
|
|
158
|
+
;;
|
|
159
|
+
"")
|
|
160
|
+
log_error "Dependency $AFTER not found in registry."
|
|
161
|
+
exit 1
|
|
162
|
+
;;
|
|
163
|
+
*) sleep $INTERVAL; ELAPSED=$((ELAPSED + INTERVAL)) ;;
|
|
164
|
+
esac
|
|
165
|
+
done
|
|
166
|
+
if [[ $ELAPSED -ge $WAIT_TIMEOUT ]]; then
|
|
167
|
+
log_error "Dependency wait timed out after ${WAIT_TIMEOUT}s"
|
|
168
|
+
exit 1
|
|
169
|
+
fi
|
|
170
|
+
fi
|
|
171
|
+
|
|
140
172
|
# ── Resolve repo (single-repo mode) ─────────────────────────────────
|
|
141
173
|
if [[ -z "$REPO" ]]; then
|
|
142
174
|
REPO=$(detect_repo) || { log_error "No --repo and no git repo found from cwd"; exit 1; }
|