forge-pipeline 0.1.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/lib/prompts.sh ADDED
@@ -0,0 +1,554 @@
1
+ #!/usr/bin/env bash
2
+ # ─────────────────────────────────────────────────────────────
3
+ # Forge – prompt generation and template substitution
4
+ # Handles prompt assembly for all agent roles.
5
+ # ─────────────────────────────────────────────────────────────
6
+
7
+ [[ -n "${_PROMPTS_SH_LOADED:-}" ]] && return
8
+ _PROMPTS_SH_LOADED=1
9
+
10
+ source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/utils.sh"
11
+
12
+ FORGE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
13
+
14
+ # ── Anti-attribution rules (appended to every agent prompt) ──
15
+
16
+ ANTI_ATTRIBUTION_RULES='
17
+ ---
18
+
19
+ ## STRICT RULES — ATTRIBUTION AND COMMIT MESSAGES
20
+
21
+ These rules are NON-NEGOTIABLE and override any other instructions:
22
+
23
+ 1. **NEVER mention AI, Claude, Anthropic, LLM, GPT, or any AI assistant** in:
24
+ - Commit messages
25
+ - Code comments
26
+ - Documentation or generated files
27
+ - Variable names, function names, or string literals
28
+ - PR titles, PR descriptions, or branch names
29
+
30
+ 2. **Commit messages must look human-written** using conventional commits:
31
+ - `feat: add user authentication endpoints`
32
+ - `fix: resolve race condition in cart service`
33
+ - `refactor: extract validation logic into shared utils`
34
+ - `test: add integration tests for payment flow`
35
+ - `docs: update API documentation`
36
+
37
+ 3. **Do NOT add any attribution headers** such as:
38
+ - "Co-Authored-By" with any AI name
39
+ - "Generated by" anything
40
+ - "Created with" any tool name
41
+ - Any similar attribution to automated tools
42
+
43
+ 4. **Do NOT reference this pipeline** in any output code, comments, or commits. No mentions of "forge pipeline", "autonomous agents", or "automated coding".
44
+
45
+ 5. **Code comments should be natural** — explain the "why", not reference how the code was produced.
46
+ '
47
+
48
+ # ── Augment tools integration ────────────────────────────────
49
+
50
+ get_augment_tools_flag() {
51
+ local config_file="${FORGE_ROOT}/.forge/config.json"
52
+ if [[ ! -f "$config_file" ]]; then
53
+ echo ""
54
+ return
55
+ fi
56
+
57
+ local augment_available
58
+ augment_available=$(jq -r '(.augment_available // .AUGMENT_AVAILABLE) // empty' "$config_file" 2>/dev/null)
59
+
60
+ if [[ "$augment_available" == "true" ]]; then
61
+ local tool_name
62
+ tool_name=$(jq -r '(.augment_tool_name // .AUGMENT_TOOL_NAME) // empty' "$config_file" 2>/dev/null)
63
+ if [[ -n "$tool_name" ]]; then
64
+ echo "$tool_name"
65
+ return
66
+ fi
67
+ fi
68
+
69
+ echo ""
70
+ }
71
+
72
+ # ── Build allowed tools per role ─────────────────────────────
73
+
74
+ build_allowed_tools() {
75
+ local role="$1"
76
+ local augment_tool
77
+ augment_tool=$(get_augment_tools_flag)
78
+
79
+ local tools=""
80
+
81
+ case "$role" in
82
+ worker)
83
+ tools="Read,Write,Bash"
84
+ ;;
85
+ lead)
86
+ tools="Read,Write,Bash"
87
+ ;;
88
+ auditor_senior)
89
+ tools="Read,Bash(find),Bash(cat),Bash(grep),Bash(wc),Bash(ls)"
90
+ ;;
91
+ auditor_junior)
92
+ tools="Read,Bash(find),Bash(cat),Bash(grep),Bash(ls)"
93
+ ;;
94
+ architect)
95
+ tools="Read,Write,Bash(find),Bash(cat),Bash(ls),Bash(head)"
96
+ ;;
97
+ challenger)
98
+ tools="Read,Write,Bash(find),Bash(cat),Bash(ls)"
99
+ ;;
100
+ coordinator)
101
+ tools="Read,Write,Bash(find),Bash(cat),Bash(ls)"
102
+ ;;
103
+ integration)
104
+ tools="Read,Write,Bash"
105
+ ;;
106
+ fix)
107
+ tools="Read,Write,Bash"
108
+ ;;
109
+ *)
110
+ log_warn "Unknown role '$role' – defaulting to Read,Bash"
111
+ tools="Read,Bash"
112
+ ;;
113
+ esac
114
+
115
+ if [[ -n "$augment_tool" ]]; then
116
+ tools="${tools},${augment_tool}"
117
+ fi
118
+
119
+ echo "$tools"
120
+ }
121
+
122
+ # ── Architect prompt ─────────────────────────────────────────
123
+
124
+ generate_architect_prompt() {
125
+ local prompt=""
126
+
127
+ # Base template
128
+ prompt+=$(cat "${FORGE_DIR}/prompts/architect_spec.md" 2>/dev/null)
129
+ prompt+=$'\n\n'
130
+
131
+ # User requirement
132
+ prompt+="## USER REQUIREMENT"$'\n\n'
133
+ prompt+=$(cat "${FORGE_ROOT}/.forge/spec/requirement.md" 2>/dev/null)
134
+ prompt+=$'\n\n'
135
+
136
+ # Existing repo structure
137
+ prompt+="## EXISTING REPO STRUCTURE"$'\n\n'
138
+ prompt+='```'$'\n'
139
+ prompt+=$(cat "${FORGE_ROOT}/.forge/repo-tree.txt" 2>/dev/null)
140
+ prompt+=$'\n```\n\n'
141
+
142
+ # Existing key files
143
+ prompt+="## EXISTING KEY FILES"$'\n\n'
144
+ prompt+='```'$'\n'
145
+ local key_files
146
+ key_files=$(cd "${FORGE_ROOT}" && cat README.md package.json pyproject.toml Cargo.toml go.mod 2>/dev/null || echo "New project")
147
+ prompt+="$key_files"
148
+ prompt+=$'\n```\n\n'
149
+
150
+ # Instruction
151
+ prompt+="## INSTRUCTION"$'\n\n'
152
+ prompt+="Write your spec to ${FORGE_ROOT}/.forge/spec/spec.md"$'\n'
153
+
154
+ prompt+="$ANTI_ATTRIBUTION_RULES"
155
+
156
+ echo "$prompt"
157
+ }
158
+
159
+ # ── Architect revision prompt ────────────────────────────────
160
+
161
+ generate_architect_revision_prompt() {
162
+ local prompt=""
163
+
164
+ # Base template
165
+ prompt+=$(cat "${FORGE_DIR}/prompts/architect_spec.md" 2>/dev/null)
166
+ prompt+=$'\n\n'
167
+
168
+ prompt+="**NOTE: This is a REVISION pass. Review the challenger's feedback and update your spec accordingly.**"$'\n\n'
169
+
170
+ # Current spec
171
+ prompt+="## YOUR CURRENT SPEC"$'\n\n'
172
+ prompt+=$(cat "${FORGE_ROOT}/.forge/spec/spec.md" 2>/dev/null)
173
+ prompt+=$'\n\n'
174
+
175
+ # Challenger's review
176
+ prompt+="## CHALLENGER'S REVIEW"$'\n\n'
177
+ prompt+=$(cat "${FORGE_ROOT}/.forge/spec/review.json" 2>/dev/null)
178
+ prompt+=$'\n\n'
179
+
180
+ # User requirement
181
+ prompt+="## USER REQUIREMENT"$'\n\n'
182
+ prompt+=$(cat "${FORGE_ROOT}/.forge/spec/requirement.md" 2>/dev/null)
183
+ prompt+=$'\n\n'
184
+
185
+ # Existing repo structure
186
+ prompt+="## EXISTING REPO STRUCTURE"$'\n\n'
187
+ prompt+='```'$'\n'
188
+ prompt+=$(cat "${FORGE_ROOT}/.forge/repo-tree.txt" 2>/dev/null)
189
+ prompt+=$'\n```\n\n'
190
+
191
+ # Instruction
192
+ prompt+="## INSTRUCTION"$'\n\n'
193
+ prompt+="Update your spec at ${FORGE_ROOT}/.forge/spec/spec.md addressing the challenger's feedback."$'\n'
194
+
195
+ prompt+="$ANTI_ATTRIBUTION_RULES"
196
+
197
+ echo "$prompt"
198
+ }
199
+
200
+ # ── Challenger prompt ────────────────────────────────────────
201
+
202
+ generate_challenger_prompt() {
203
+ local prompt=""
204
+
205
+ # Base template
206
+ prompt+=$(cat "${FORGE_DIR}/prompts/challenger_review.md" 2>/dev/null)
207
+ prompt+=$'\n\n'
208
+
209
+ # Original user requirement
210
+ prompt+="## ORIGINAL USER REQUIREMENT"$'\n\n'
211
+ prompt+=$(cat "${FORGE_ROOT}/.forge/spec/requirement.md" 2>/dev/null)
212
+ prompt+=$'\n\n'
213
+
214
+ # Architect's spec
215
+ prompt+="## ARCHITECT'S SPEC"$'\n\n'
216
+ prompt+=$(cat "${FORGE_ROOT}/.forge/spec/spec.md" 2>/dev/null)
217
+ prompt+=$'\n\n'
218
+
219
+ # Existing repo structure
220
+ prompt+="## EXISTING REPO STRUCTURE"$'\n\n'
221
+ prompt+='```'$'\n'
222
+ prompt+=$(cat "${FORGE_ROOT}/.forge/repo-tree.txt" 2>/dev/null)
223
+ prompt+=$'\n```\n\n'
224
+
225
+ # Instruction
226
+ prompt+="## INSTRUCTION"$'\n\n'
227
+ prompt+="Write your review to ${FORGE_ROOT}/.forge/spec/review.json"$'\n'
228
+
229
+ prompt+="$ANTI_ATTRIBUTION_RULES"
230
+
231
+ echo "$prompt"
232
+ }
233
+
234
+ # ── Coordinator prompt ───────────────────────────────────────
235
+
236
+ generate_coordinator_prompt() {
237
+ local prompt=""
238
+
239
+ # Base template
240
+ prompt+=$(cat "${FORGE_DIR}/prompts/coordinator_plan.md" 2>/dev/null)
241
+ prompt+=$'\n\n'
242
+
243
+ # Approved technical spec
244
+ prompt+="## APPROVED TECHNICAL SPEC"$'\n\n'
245
+ prompt+=$(cat "${FORGE_ROOT}/.forge/spec/spec.md" 2>/dev/null)
246
+ prompt+=$'\n\n'
247
+
248
+ # Original user requirement
249
+ prompt+="## ORIGINAL USER REQUIREMENT"$'\n\n'
250
+ prompt+=$(cat "${FORGE_ROOT}/.forge/spec/requirement.md" 2>/dev/null)
251
+ prompt+=$'\n\n'
252
+
253
+ # Repo structure
254
+ prompt+="## REPO STRUCTURE"$'\n\n'
255
+ prompt+='```'$'\n'
256
+ prompt+=$(cat "${FORGE_ROOT}/.forge/repo-tree.txt" 2>/dev/null)
257
+ prompt+=$'\n```\n\n'
258
+
259
+ # Existing key files
260
+ prompt+="## EXISTING KEY FILES"$'\n\n'
261
+ prompt+='```'$'\n'
262
+ local key_files
263
+ key_files=$(cd "${FORGE_ROOT}" && cat README.md package.json pyproject.toml Cargo.toml go.mod 2>/dev/null || echo "New project")
264
+ prompt+="$key_files"
265
+ prompt+=$'\n```\n\n'
266
+
267
+ # JSON schema for plan.json
268
+ prompt+="## PLAN JSON SCHEMA"$'\n\n'
269
+ prompt+='The plan.json file MUST follow this exact schema:'$'\n\n'
270
+ prompt+='```json'$'\n'
271
+ prompt+='{
272
+ "project_type": "greenfield | incremental",
273
+ "leads": [
274
+ {
275
+ "name": "lead-<module-name>",
276
+ "module": "<module-name>",
277
+ "description": "<what this lead is responsible for>",
278
+ "dependencies": ["<other lead names this depends on, if any>"],
279
+ "workers": [
280
+ {
281
+ "name": "worker-<task-name>",
282
+ "task": "<concise task description>",
283
+ "files": ["<list of files this worker will create or modify>"],
284
+ "spec_excerpt": "<relevant portion of the spec for this task>"
285
+ }
286
+ ]
287
+ }
288
+ ]
289
+ }'
290
+ prompt+=$'\n```\n\n'
291
+
292
+ # Instruction
293
+ prompt+="## INSTRUCTION"$'\n\n'
294
+ prompt+="Write your implementation plan to ${FORGE_ROOT}/.forge/plan.json"$'\n'
295
+
296
+ prompt+="$ANTI_ATTRIBUTION_RULES"
297
+
298
+ echo "$prompt"
299
+ }
300
+
301
+ # ── Lead prompt ──────────────────────────────────────────────
302
+
303
+ generate_lead_prompt() {
304
+ local lead_name="$1"
305
+ local lead_json="$2"
306
+
307
+ local module_name
308
+ module_name=$(echo "$lead_json" | jq -r '.module // .name' 2>/dev/null)
309
+
310
+ local workers_json
311
+ workers_json=$(echo "$lead_json" | jq -c '.workers // []' 2>/dev/null)
312
+
313
+ local prompt=""
314
+
315
+ # Base template
316
+ local template
317
+ template=$(cat "${FORGE_DIR}/prompts/lead.md" 2>/dev/null)
318
+
319
+ if [[ -n "$template" ]]; then
320
+ # Perform substitutions
321
+ template="${template//\{MODULE_NAME\}/$module_name}"
322
+ template="${template//\{WORKER_DEFINITIONS_FROM_PLAN\}/$workers_json}"
323
+ prompt+="$template"
324
+ else
325
+ prompt+="# Lead Agent: ${lead_name}"$'\n'
326
+ prompt+="Module: ${module_name}"$'\n\n'
327
+ fi
328
+
329
+ prompt+=$'\n\n'
330
+
331
+ # Spec content for reference
332
+ prompt+="## TECHNICAL SPEC"$'\n\n'
333
+ prompt+=$(cat "${FORGE_ROOT}/.forge/spec/spec.md" 2>/dev/null)
334
+ prompt+=$'\n\n'
335
+
336
+ # Worker definitions
337
+ prompt+="## WORKER DEFINITIONS"$'\n\n'
338
+ prompt+='```json'$'\n'
339
+ prompt+="$workers_json"
340
+ prompt+=$'\n```\n\n'
341
+
342
+ # Workflow instructions
343
+ prompt+="## DETAILED WORKFLOW INSTRUCTIONS"$'\n\n'
344
+ prompt+="You are the lead for module **${module_name}**. You are running as a Claude Code instance inside a git worktree at \`${FORGE_ROOT}/.forge/worktrees/${lead_name}\`. Follow these steps exactly:"$'\n\n'
345
+
346
+ prompt+="### Step 1: Create worktrees for each worker"$'\n'
347
+ prompt+="For each worker in your workers list, create a git worktree branching off YOUR lead branch:"$'\n'
348
+ prompt+='```bash'$'\n'
349
+ prompt+="cd ${FORGE_ROOT}"$'\n'
350
+ prompt+="git worktree add ${FORGE_ROOT}/.forge/worktrees/<worker-name> -b forge/<worker-name> forge/${lead_name}"$'\n'
351
+ prompt+='```'$'\n\n'
352
+
353
+ prompt+="### Step 2: Write task spec files"$'\n'
354
+ prompt+="For each worker, write a detailed task specification as a markdown file. Include the task description, file list, and relevant spec excerpts from the worker definitions above."$'\n'
355
+ prompt+='```bash'$'\n'
356
+ prompt+="mkdir -p ${FORGE_ROOT}/.forge/tasks"$'\n'
357
+ prompt+="# Write detailed task to ${FORGE_ROOT}/.forge/tasks/<worker-name>.md"$'\n'
358
+ prompt+='```'$'\n'
359
+ prompt+="The task file should contain everything the worker needs: what to build, which files to create/modify, relevant API contracts, data models, conventions to follow, and a reminder to commit changes when done."$'\n\n'
360
+
361
+ prompt+="### Step 3: Spawn workers via tmux"$'\n'
362
+ prompt+="Launch each worker as a separate Claude Code instance in its own tmux session. IMPORTANT: Use \`forge-\` prefix for session names."$'\n'
363
+ prompt+='```bash'$'\n'
364
+ prompt+="# For each worker:"$'\n'
365
+ prompt+="touch ${FORGE_ROOT}/.forge/status/<worker-name>.expected"$'\n'
366
+ prompt+="tmux new-session -d -s \"forge-<worker-name>\" \\"$'\n'
367
+ prompt+=" \"cd ${FORGE_ROOT}/.forge/worktrees/<worker-name> && claude -p \\\"\\\$(cat ${FORGE_ROOT}/.forge/tasks/<worker-name>.md)\\\" --allowedTools 'Read,Write,Bash' 2>&1 | tee ${FORGE_ROOT}/.forge/logs/<worker-name>.log; echo done > ${FORGE_ROOT}/.forge/status/<worker-name>.done\""$'\n'
368
+ prompt+='```'$'\n\n'
369
+
370
+ prompt+="### Step 4: Poll for worker completion"$'\n'
371
+ prompt+="Monitor workers by checking for .done files. Poll every 30 seconds:"$'\n'
372
+ prompt+='```bash'$'\n'
373
+ prompt+="# Loop until all workers are done"$'\n'
374
+ prompt+="while true; do"$'\n'
375
+ prompt+=" done_count=\$(ls ${FORGE_ROOT}/.forge/status/worker-*.done 2>/dev/null | wc -l | tr -d ' ')"$'\n'
376
+ prompt+=" expected_count=\$(ls ${FORGE_ROOT}/.forge/status/worker-*.expected 2>/dev/null | wc -l | tr -d ' ')"$'\n'
377
+ prompt+=" echo \"Workers: \${done_count}/\${expected_count} done\""$'\n'
378
+ prompt+=" [ \"\$done_count\" -ge \"\$expected_count\" ] && break"$'\n'
379
+ prompt+=" sleep 30"$'\n'
380
+ prompt+="done"$'\n'
381
+ prompt+='```'$'\n'
382
+ prompt+="Also check if any tmux session died without creating a .done file — if so, the worker crashed. You may respawn it (max 2 retries)."$'\n\n'
383
+
384
+ prompt+="### Step 5: Review each worker's output"$'\n'
385
+ prompt+="For each completed worker, review its changes:"$'\n'
386
+ prompt+='```bash'$'\n'
387
+ prompt+="cd ${FORGE_ROOT}/.forge/worktrees/<worker-name>"$'\n'
388
+ prompt+="git log --oneline forge/${lead_name}..HEAD"$'\n'
389
+ prompt+="git diff forge/${lead_name}..HEAD"$'\n'
390
+ prompt+='```'$'\n'
391
+ prompt+="Check: Does the code match the task spec? Is it well-structured? Are there obvious bugs?"$'\n'
392
+ prompt+="If a worker's output is poor, write fix instructions and respawn (max 2 retries per worker)."$'\n\n'
393
+
394
+ prompt+="### Step 6: Merge all worker branches into your lead branch"$'\n'
395
+ prompt+="After all workers pass review, merge them sequentially:"$'\n'
396
+ prompt+='```bash'$'\n'
397
+ prompt+="cd ${FORGE_ROOT}/.forge/worktrees/${lead_name}"$'\n'
398
+ prompt+="git merge --no-ff forge/<worker-name> -m \"Merge <worker-name> implementation\""$'\n'
399
+ prompt+="# Repeat for each worker"$'\n'
400
+ prompt+='```'$'\n'
401
+ prompt+="Resolve any merge conflicts if they occur (they should be rare since workers own exclusive files)."$'\n\n'
402
+
403
+ prompt+="### Step 7: Write review and signal completion"$'\n'
404
+ prompt+='```bash'$'\n'
405
+ prompt+="# Write a review summary"$'\n'
406
+ prompt+="cat > ${FORGE_ROOT}/.forge/reviews/${lead_name}-review.json << 'EOF'"$'\n'
407
+ prompt+='{"lead": "'"${lead_name}"'", "module": "'"${module_name}"'", "status": "complete", "workers_merged": [...], "issues": [...]}'$'\n'
408
+ prompt+="EOF"$'\n\n'
409
+ prompt+="# Signal completion"$'\n'
410
+ prompt+="echo \"done\" > ${FORGE_ROOT}/.forge/status/${lead_name}.done"$'\n'
411
+ prompt+='```'$'\n\n'
412
+
413
+ prompt+="## FORGE_ROOT"$'\n\n'
414
+ prompt+="All absolute paths use: \`${FORGE_ROOT}\`"$'\n'
415
+ prompt+="Your worktree is at: \`${FORGE_ROOT}/.forge/worktrees/${lead_name}\`"$'\n'
416
+ prompt+="Your branch is: \`forge/${lead_name}\`"$'\n'
417
+
418
+ prompt+="$ANTI_ATTRIBUTION_RULES"
419
+
420
+ echo "$prompt"
421
+ }
422
+
423
+ # ── Worker prompt ────────────────────────────────────────────
424
+
425
+ generate_worker_prompt() {
426
+ local worker_name="$1"
427
+ local task_description="$2"
428
+ local file_list="$3"
429
+ local spec_excerpt="$4"
430
+
431
+ local prompt=""
432
+
433
+ # Base template
434
+ local template
435
+ template=$(cat "${FORGE_DIR}/prompts/worker.md" 2>/dev/null)
436
+
437
+ if [[ -n "$template" ]]; then
438
+ template="${template//\{TASK_DESCRIPTION\}/$task_description}"
439
+ template="${template//\{FILE_LIST\}/$file_list}"
440
+ template="${template//\{SPEC_EXCERPT_RELEVANT_TO_THIS_TASK\}/$spec_excerpt}"
441
+ prompt+="$template"
442
+ else
443
+ prompt+="# Worker Agent: ${worker_name}"$'\n\n'
444
+ prompt+="## TASK DESCRIPTION"$'\n\n'
445
+ prompt+="$task_description"$'\n\n'
446
+ prompt+="## FILES TO WORK ON"$'\n\n'
447
+ prompt+="$file_list"$'\n\n'
448
+ prompt+="## RELEVANT SPEC EXCERPT"$'\n\n'
449
+ prompt+="$spec_excerpt"$'\n\n'
450
+ fi
451
+
452
+ prompt+=$'\n\n'
453
+
454
+ # Completion instruction
455
+ prompt+="## COMPLETION"$'\n\n'
456
+ prompt+="When done, commit all changes and create the completion marker:"$'\n'
457
+ prompt+='```bash'$'\n'
458
+ prompt+="touch ${FORGE_ROOT}/.forge/status/${worker_name}.done"$'\n'
459
+ prompt+='```'$'\n'
460
+
461
+ prompt+="$ANTI_ATTRIBUTION_RULES"
462
+
463
+ echo "$prompt"
464
+ }
465
+
466
+ # ── Senior auditor prompt ───────────────────────────────────
467
+
468
+ generate_senior_auditor_prompt() {
469
+ local prompt=""
470
+
471
+ # Base template
472
+ prompt+=$(cat "${FORGE_DIR}/prompts/senior_auditor.md" 2>/dev/null)
473
+ prompt+=$'\n\n'
474
+
475
+ # Context
476
+ prompt+="## CONTEXT"$'\n\n'
477
+ prompt+="You are auditing the fully integrated codebase after all modules have been merged."$'\n'
478
+ prompt+="Review the entire project for correctness, consistency, and completeness."$'\n\n'
479
+
480
+ # FORGE_ROOT
481
+ prompt+="## FORGE_ROOT"$'\n\n'
482
+ prompt+="All absolute paths use: ${FORGE_ROOT}"$'\n\n'
483
+
484
+ # Spec for reference
485
+ prompt+="## APPROVED SPEC"$'\n\n'
486
+ prompt+=$(cat "${FORGE_ROOT}/.forge/spec/spec.md" 2>/dev/null)
487
+ prompt+=$'\n\n'
488
+
489
+ # Plan for reference
490
+ prompt+="## IMPLEMENTATION PLAN"$'\n\n'
491
+ prompt+=$(cat "${FORGE_ROOT}/.forge/plan.json" 2>/dev/null)
492
+ prompt+=$'\n\n'
493
+
494
+ # Instruction
495
+ prompt+="## INSTRUCTION"$'\n\n'
496
+ prompt+="Write the consolidated audit report to ${FORGE_ROOT}/.forge/audit/consolidated-audit.json"$'\n'
497
+ prompt+="Write the audit plan to ${FORGE_ROOT}/.forge/audit/senior-audit-plan.json"$'\n'
498
+ prompt+="Each junior auditor should write their findings to ${FORGE_ROOT}/.forge/audit/junior-{name}.json"$'\n'
499
+
500
+ prompt+="$ANTI_ATTRIBUTION_RULES"
501
+
502
+ echo "$prompt"
503
+ }
504
+
505
+ # ── Final report prompt ─────────────────────────────────────
506
+
507
+ generate_final_report_prompt() {
508
+ local user_prompt="$1"
509
+
510
+ local prompt=""
511
+
512
+ # Base template
513
+ prompt+=$(cat "${FORGE_DIR}/prompts/coordinator_final.md" 2>/dev/null)
514
+ prompt+=$'\n\n'
515
+
516
+ # Original task
517
+ prompt+="## ORIGINAL TASK"$'\n\n'
518
+ prompt+="$user_prompt"$'\n\n'
519
+
520
+ # Approved spec
521
+ prompt+="## APPROVED SPEC"$'\n\n'
522
+ prompt+=$(cat "${FORGE_ROOT}/.forge/spec/spec.md" 2>/dev/null)
523
+ prompt+=$'\n\n'
524
+
525
+ # Plan
526
+ prompt+="## IMPLEMENTATION PLAN"$'\n\n'
527
+ prompt+=$(cat "${FORGE_ROOT}/.forge/plan.json" 2>/dev/null)
528
+ prompt+=$'\n\n'
529
+
530
+ # Lead reviews
531
+ prompt+="## LEAD REVIEWS"$'\n\n'
532
+ local lead_reviews
533
+ lead_reviews=$(cat "${FORGE_ROOT}"/.forge/reviews/*.json 2>/dev/null || echo "No lead reviews available")
534
+ prompt+="$lead_reviews"$'\n\n'
535
+
536
+ # Audit results
537
+ prompt+="## AUDIT RESULTS"$'\n\n'
538
+ prompt+=$(cat "${FORGE_ROOT}/.forge/audit/consolidated-audit.json" 2>/dev/null || echo "No audit results available")
539
+ prompt+=$'\n\n'
540
+
541
+ # Fix reports
542
+ prompt+="## FIX REPORTS"$'\n\n'
543
+ local fix_reports
544
+ fix_reports=$(cat "${FORGE_ROOT}"/.forge/fixes/*.json 2>/dev/null || echo "No fix reports available")
545
+ prompt+="$fix_reports"$'\n\n'
546
+
547
+ # Instruction
548
+ prompt+="## INSTRUCTION"$'\n\n'
549
+ prompt+="Write the final project report to ${FORGE_ROOT}/.forge/DONE.md"$'\n'
550
+
551
+ prompt+="$ANTI_ATTRIBUTION_RULES"
552
+
553
+ echo "$prompt"
554
+ }