forge-pipeline 0.4.1 → 0.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/forge CHANGED
@@ -246,17 +246,25 @@ show_plan_summary() {
246
246
  }
247
247
 
248
248
  wait_for_approval() {
249
- printf "${BOLD}${YELLOW}Approve and continue? [Y/n] ${RESET}"
249
+ printf " ${BOLD}[Y]${RESET} Approve and continue\n"
250
+ printf " ${BOLD}[f]${RESET} Give feedback (architect + challenger will revise)\n"
251
+ printf " ${BOLD}[n]${RESET} Abort\n"
252
+ echo ""
253
+ printf "${BOLD}${YELLOW}Your choice [Y/f/n]: ${RESET}"
250
254
  local answer
251
255
  read -r answer </dev/tty
252
256
  case "$answer" in
257
+ f|F|feedback)
258
+ return 1 # signal feedback requested
259
+ ;;
253
260
  n|N|no|No|NO)
254
- log_info "Aborted. Edit .forge/spec/spec.md, then run 'forge start' again."
261
+ log_info "Aborted. Run 'forge start' again when ready."
255
262
  exit 0
256
263
  ;;
257
264
  *)
258
265
  log_success "Approved. Continuing..."
259
266
  echo ""
267
+ return 0
260
268
  ;;
261
269
  esac
262
270
  }
@@ -636,26 +644,63 @@ run_pipeline() {
636
644
  # Preflight
637
645
  preflight_check
638
646
 
639
- # Phase 0: Spec Creation
647
+ # Phase 0: Spec Creation (with feedback loop)
640
648
  run_phase_spec "$user_prompt" || { log_error "Phase 0 failed"; exit 1; }
641
649
  check_global_timeout
642
650
 
643
- # ── Approval gate (after spec, before planning + execution) ──
644
- if [ "$AUTO_APPROVE" = true ]; then
645
- log_info "Auto-approve enabled, skipping review."
651
+ if [ "$AUTO_APPROVE" != true ]; then
652
+ while true; do
653
+ echo ""
654
+ printf "${BOLD}${CYAN}═══════════════════════════════════════${RESET}\n"
655
+ printf "${BOLD}${CYAN} SPEC REVIEW${RESET}\n"
656
+ printf "${BOLD}${CYAN}═══════════════════════════════════════${RESET}\n"
657
+ echo ""
658
+ echo " The spec has been written to:"
659
+ printf " ${BOLD}.forge/spec/spec.md${RESET}\n"
660
+ echo ""
661
+ echo " Review it, then choose an option below."
662
+ echo ""
663
+
664
+ if wait_for_approval; then
665
+ break # approved
666
+ fi
667
+
668
+ # Feedback requested — collect it
669
+ echo ""
670
+ printf "${BOLD}${YELLOW}Enter your feedback (press Enter twice to submit):${RESET}\n"
671
+ local feedback=""
672
+ local empty_count=0
673
+ while IFS= read -r line </dev/tty; do
674
+ if [ -z "$line" ]; then
675
+ empty_count=$((empty_count + 1))
676
+ if [ "$empty_count" -ge 1 ] && [ -n "$feedback" ]; then
677
+ break
678
+ fi
679
+ else
680
+ empty_count=0
681
+ fi
682
+ if [ -n "$feedback" ]; then
683
+ feedback="${feedback}\n${line}"
684
+ else
685
+ feedback="$line"
686
+ fi
687
+ done
688
+
689
+ if [ -z "$feedback" ]; then
690
+ log_warn "No feedback provided. Showing options again."
691
+ continue
692
+ fi
693
+
694
+ # Save feedback and run single revision pass
695
+ printf '%b\n' "$feedback" > "$FORGE_ROOT/.forge/spec/user-feedback.md"
696
+ log_info "Feedback saved. Revising spec..."
697
+ echo ""
698
+
699
+ run_phase_spec_revise || { log_error "Spec revision failed"; exit 1; }
700
+ check_global_timeout
701
+ done
646
702
  else
647
- echo ""
648
- printf "${BOLD}${CYAN}═══════════════════════════════════════${RESET}\n"
649
- printf "${BOLD}${CYAN} SPEC REVIEW${RESET}\n"
650
- printf "${BOLD}${CYAN}═══════════════════════════════════════${RESET}\n"
651
- echo ""
652
- echo " The spec has been written to:"
653
- echo " ${BOLD}.forge/spec/spec.md${RESET}"
654
- echo ""
655
- echo " Review it, then approve to continue."
656
- echo " If you edit the spec, changes will be used as-is."
657
- echo ""
658
- wait_for_approval
703
+ log_info "Auto-approve enabled, skipping review."
659
704
  fi
660
705
 
661
706
  # Phase 1: Planning
@@ -107,3 +107,40 @@ run_phase_spec() {
107
107
 
108
108
  return 0
109
109
  }
110
+
111
+ ##
112
+ # Single-pass spec revision from user feedback.
113
+ # Runs one architect pass (with user feedback) + one challenger pass.
114
+ ##
115
+ run_phase_spec_revise() {
116
+ log_phase "0" "SPEC REVISION (user feedback)"
117
+
118
+ # ── Architect revision with user feedback ─────────────────────
119
+ local prompt
120
+ prompt="$(generate_architect_revision_prompt)"
121
+
122
+ spawn_agent_foreground "architect" "$FORGE_ROOT" "$prompt" "$(build_allowed_tools architect)"
123
+
124
+ if [[ ! -f "${FORGE_ROOT}/.forge/spec/spec.md" ]]; then
125
+ log_error "Architect did not produce spec.md during revision"
126
+ return 1
127
+ fi
128
+
129
+ # ── Challenger validation ─────────────────────────────────────
130
+ local challenger_prompt
131
+ challenger_prompt="$(generate_challenger_prompt)"
132
+
133
+ spawn_agent_foreground "challenger" "$FORGE_ROOT" "$challenger_prompt" "$(build_allowed_tools challenger)"
134
+
135
+ if [[ -f "${FORGE_ROOT}/.forge/spec/review.json" ]]; then
136
+ local verdict
137
+ verdict="$(json_get "${FORGE_ROOT}/.forge/spec/review.json" "verdict")"
138
+ if [[ "$verdict" == "approved" ]]; then
139
+ log_success "Revised spec approved by challenger"
140
+ else
141
+ log_warn "Challenger flagged issues but proceeding (user-driven revision)"
142
+ fi
143
+ fi
144
+
145
+ return 0
146
+ }
package/lib/prompts.sh CHANGED
@@ -147,6 +147,21 @@ generate_architect_prompt() {
147
147
  prompt+="$key_files"
148
148
  prompt+=$'\n```\n\n'
149
149
 
150
+ # User feedback (from approval gate, if any)
151
+ if [[ -f "${FORGE_ROOT}/.forge/spec/user-feedback.md" ]]; then
152
+ prompt+="## USER FEEDBACK"$'\n\n'
153
+ prompt+="The user reviewed a previous version of the spec and provided this feedback. Address it carefully:"$'\n\n'
154
+ prompt+=$(cat "${FORGE_ROOT}/.forge/spec/user-feedback.md" 2>/dev/null)
155
+ prompt+=$'\n\n'
156
+ fi
157
+
158
+ # Previous spec (if re-running after feedback)
159
+ if [[ -f "${FORGE_ROOT}/.forge/spec/spec.md" ]]; then
160
+ prompt+="## PREVIOUS SPEC (revise this)"$'\n\n'
161
+ prompt+=$(cat "${FORGE_ROOT}/.forge/spec/spec.md" 2>/dev/null)
162
+ prompt+=$'\n\n'
163
+ fi
164
+
150
165
  # Instruction
151
166
  prompt+="## INSTRUCTION"$'\n\n'
152
167
  prompt+="Write your spec to ${FORGE_ROOT}/.forge/spec/spec.md"$'\n'
@@ -188,9 +203,17 @@ generate_architect_revision_prompt() {
188
203
  prompt+=$(cat "${FORGE_ROOT}/.forge/repo-tree.txt" 2>/dev/null)
189
204
  prompt+=$'\n```\n\n'
190
205
 
206
+ # User feedback (from approval gate, if any)
207
+ if [[ -f "${FORGE_ROOT}/.forge/spec/user-feedback.md" ]]; then
208
+ prompt+="## USER FEEDBACK"$'\n\n'
209
+ prompt+="The user also provided direct feedback. Prioritize this over challenger feedback:"$'\n\n'
210
+ prompt+=$(cat "${FORGE_ROOT}/.forge/spec/user-feedback.md" 2>/dev/null)
211
+ prompt+=$'\n\n'
212
+ fi
213
+
191
214
  # Instruction
192
215
  prompt+="## INSTRUCTION"$'\n\n'
193
- prompt+="Update your spec at ${FORGE_ROOT}/.forge/spec/spec.md addressing the challenger's feedback."$'\n'
216
+ prompt+="Update your spec at ${FORGE_ROOT}/.forge/spec/spec.md addressing all feedback."$'\n'
194
217
 
195
218
  prompt+="$ANTI_ATTRIBUTION_RULES"
196
219
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forge-pipeline",
3
- "version": "0.4.1",
3
+ "version": "0.5.1",
4
4
  "description": "Autonomous multi-agent coding pipeline",
5
5
  "bin": {
6
6
  "forge": "./bin/forge.js"