forge-pipeline 0.6.0 → 0.7.0

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/forge CHANGED
@@ -62,6 +62,7 @@ Usage:
62
62
  forge clean Remove .forge/ directory and branches
63
63
 
64
64
  Options:
65
+ -f FILE Read task description from a file
65
66
  --auto Skip approval gate, fully autonomous
66
67
  --max-workers N Max parallel workers per lead (default: 4)
67
68
  --max-leads N Max parallel leads (default: 4)
@@ -74,7 +75,8 @@ Options:
74
75
  Examples:
75
76
  forge init my-app
76
77
  forge start Add user authentication with JWT
77
- forge start Refactor the payment module to use Stripe
78
+ forge start -f prompt.txt
79
+ cat feedback.txt | forge start
78
80
  forge --auto start Build a REST API with CRUD endpoints
79
81
  EOF
80
82
  }
@@ -549,6 +551,7 @@ USER_PROMPT=""
549
551
  SUBCOMMAND=""
550
552
  INIT_PROJECT=""
551
553
  LOGS_AGENT=""
554
+ PROMPT_FILE=""
552
555
  PROMPT_ARGS=()
553
556
 
554
557
  while [[ $# -gt 0 ]]; do
@@ -579,11 +582,18 @@ while [[ $# -gt 0 ]]; do
579
582
  [ -n "$INIT_PROJECT" ] && shift
580
583
  break
581
584
  ;;
585
+ -f)
586
+ PROMPT_FILE="$2"; shift 2 ;;
582
587
  start|run)
583
588
  SUBCOMMAND="$1"
584
589
  shift
585
- # Everything remaining is the prompt
586
- PROMPT_ARGS+=("$@")
590
+ # Check for -f after start
591
+ if [[ "${1:-}" == "-f" ]]; then
592
+ PROMPT_FILE="$2"; shift 2
593
+ else
594
+ # Everything remaining is the prompt
595
+ PROMPT_ARGS+=("$@")
596
+ fi
587
597
  break
588
598
  ;;
589
599
  status)
@@ -611,9 +621,18 @@ while [[ $# -gt 0 ]]; do
611
621
  esac
612
622
  done
613
623
 
614
- # Join prompt args into a single string
615
- if [ ${#PROMPT_ARGS[@]} -gt 0 ]; then
624
+ # Resolve prompt from args, file, or stdin
625
+ if [ -n "$PROMPT_FILE" ]; then
626
+ if [ ! -f "$PROMPT_FILE" ]; then
627
+ log_error "Prompt file not found: $PROMPT_FILE"
628
+ exit 1
629
+ fi
630
+ USER_PROMPT="$(cat "$PROMPT_FILE")"
631
+ elif [ ${#PROMPT_ARGS[@]} -gt 0 ]; then
616
632
  USER_PROMPT="${PROMPT_ARGS[*]}"
633
+ elif [ ! -t 0 ]; then
634
+ # stdin is piped — read from it
635
+ USER_PROMPT="$(cat)"
617
636
  fi
618
637
 
619
638
  # Re-export updated values after argument parsing
package/lib/agent.sh CHANGED
@@ -56,40 +56,10 @@ spawn_agent_foreground() {
56
56
  local done_file="${forge_root}/.forge/status/${name}.done"
57
57
 
58
58
  cd "$worktree_path" && \
59
- claude -p "$(cat /tmp/forge-prompt-"${name}".md)" --output-format stream-json --allowedTools "$allowed_tools" 2>&1 | \
59
+ claude -p "$(cat /tmp/forge-prompt-"${name}".md)" --output-format text --allowedTools "$allowed_tools" 2>&1 | \
60
60
  while IFS= read -r line; do
61
- # Extract text content from stream-json and display in real-time
62
- local type
63
- type="$(echo "$line" | jq -r '.type // empty' 2>/dev/null)"
64
- case "$type" in
65
- assistant)
66
- echo "$line" >> "$log_file"
67
- local content
68
- content="$(echo "$line" | jq -r '.message.content[]? | select(.type=="text") | .text // empty' 2>/dev/null)"
69
- if [ -n "$content" ]; then
70
- printf '%s\n' "$content"
71
- fi
72
- ;;
73
- content_block_delta)
74
- echo "$line" >> "$log_file"
75
- local delta
76
- delta="$(echo "$line" | jq -r '.delta.text // empty' 2>/dev/null)"
77
- if [ -n "$delta" ]; then
78
- printf '%s' "$delta"
79
- fi
80
- ;;
81
- result)
82
- echo "$line" >> "$log_file"
83
- local result_text
84
- result_text="$(echo "$line" | jq -r '.result // empty' 2>/dev/null)"
85
- if [ -n "$result_text" ]; then
86
- printf '\n%s\n' "$result_text"
87
- fi
88
- ;;
89
- *)
90
- echo "$line" >> "$log_file"
91
- ;;
92
- esac
61
+ printf '%s\n' "$line"
62
+ echo "$line" >> "$log_file"
93
63
  done
94
64
 
95
65
  echo "done" > "$done_file"
@@ -62,8 +62,31 @@ IMPORTANT: Your previous attempt produced invalid JSON in plan.json. Please ensu
62
62
  leads_count="$(json_get "${FORGE_ROOT}/.forge/plan.json" "leads | length")"
63
63
 
64
64
  if [[ -z "$leads_count" || "$leads_count" -lt 1 ]]; then
65
- log_error "plan.json must contain a 'leads' array with at least 1 entry (found: ${leads_count:-0})"
66
- return 1
65
+ log_warn "plan.json has no leads (found: ${leads_count:-0}). Retrying coordinator..."
66
+
67
+ local retry_prompt="${prompt}
68
+
69
+ CRITICAL ERROR: Your previous attempt did NOT write a valid plan.json file with a 'leads' array. The file either doesn't exist or has 0 leads.
70
+
71
+ You MUST:
72
+ 1. Use the Write tool to create ${FORGE_ROOT}/.forge/plan.json
73
+ 2. The JSON must have a top-level 'leads' array with at least 1 lead
74
+ 3. Each lead must have a 'workers' array
75
+ 4. Do NOT just describe the plan in text — actually write the JSON file"
76
+
77
+ spawn_agent_foreground "coordinator" "$FORGE_ROOT" "$retry_prompt" "$(build_allowed_tools coordinator)"
78
+
79
+ # Validate again
80
+ if [[ ! -f "${FORGE_ROOT}/.forge/plan.json" ]]; then
81
+ log_error "Coordinator did not produce plan.json on retry"
82
+ return 1
83
+ fi
84
+
85
+ leads_count="$(json_get "${FORGE_ROOT}/.forge/plan.json" "leads | length")"
86
+ if [[ -z "$leads_count" || "$leads_count" -lt 1 ]]; then
87
+ log_error "plan.json still has no leads after retry (found: ${leads_count:-0})"
88
+ return 1
89
+ fi
67
90
  fi
68
91
 
69
92
  # ── Log plan summary ─────────────────────────────────────────────────
package/lib/prompts.sh CHANGED
@@ -314,7 +314,9 @@ generate_coordinator_prompt() {
314
314
 
315
315
  # Instruction
316
316
  prompt+="## INSTRUCTION"$'\n\n'
317
- prompt+="Write your implementation plan to ${FORGE_ROOT}/.forge/plan.json"$'\n'
317
+ prompt+="You MUST write the plan as valid JSON to this exact path: ${FORGE_ROOT}/.forge/plan.json"$'\n\n'
318
+ prompt+="Use the Write tool to create the file. The JSON MUST have a top-level \"leads\" array with at least 1 entry."$'\n'
319
+ prompt+="Do NOT just describe the plan in text. You MUST create the actual JSON file using the Write tool."$'\n'
318
320
 
319
321
  prompt+="$ANTI_ATTRIBUTION_RULES"
320
322
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forge-pipeline",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Autonomous multi-agent coding pipeline",
5
5
  "bin": {
6
6
  "forge": "./bin/forge.js"