diff --git a/scripts/epic-execute-lib/design-phase.sh b/scripts/epic-execute-lib/design-phase.sh
index b66717afe..b0de9bdff 100644
--- a/scripts/epic-execute-lib/design-phase.sh
+++ b/scripts/epic-execute-lib/design-phase.sh
@@ -32,21 +32,30 @@ execute_design_phase() {
log ">>> DESIGN PHASE: $story_id"
+ # Story is inlined (small, bounded, and the planner needs it in full)
local story_contents=$(cat "$story_file")
- # Load architecture file if available
- local arch_contents=""
+ # Locate the architecture file but pass it by PATH, not embedded contents.
+ # architecture.md is the main unbounded size risk in this prompt.
+ local arch_file=""
for search_path in "$PROJECT_ROOT/docs/architecture.md" "$PROJECT_ROOT/docs/architecture/architecture.md" "$PROJECT_ROOT/architecture.md"; do
if [ -f "$search_path" ]; then
- arch_contents=$(cat "$search_path")
+ arch_file="$search_path"
break
fi
done
- # Load previous decisions for context
+ # Load previous decisions for context, bounded to the last 20KB
+ # (matches the dev phase; the decision log grows across the epic).
local decision_context=""
if type get_decision_log_context >/dev/null 2>&1; then
decision_context=$(get_decision_log_context)
+ local dec_size
+ dec_size=$(get_byte_size "$decision_context")
+ if [ "$dec_size" -gt 20000 ]; then
+ decision_context=$(printf '%s' "$decision_context" | tail -c 20000)
+ [ "$VERBOSE" = true ] && log_warn "Design: decision log truncated to last 20KB"
+ fi
fi
local design_prompt="You are a senior developer planning the implementation of a story.
@@ -74,9 +83,7 @@ $story_contents
## Architecture Reference
-
-$arch_contents
-
+**Read the architecture document at:** ${arch_file:-"(none found)"}
## Previous Decisions in This Epic
@@ -84,15 +91,12 @@ $arch_contents
$decision_context
-## Exploration Commands
+## Exploration
-First, explore the codebase to understand existing patterns:
-\`\`\`bash
-# Find similar implementations
-find . -type f -name \"*.ts\" -o -name \"*.js\" | head -20
-# Check project structure
-ls -la src/ 2>/dev/null || ls -la
-\`\`\`
+First, explore the codebase to understand existing patterns and conventions
+before planning. Use the repository's own structure and language to guide you
+(e.g. inspect the relevant source directories, find files similar to what this
+story touches, and follow existing patterns rather than introducing new ones).
## Required Output
@@ -137,6 +141,9 @@ Be specific and concrete. This plan will guide the implementation phase.
After outputting the design block, output exactly:
DESIGN COMPLETE: $story_id"
+ # Log prompt size in verbose mode (consistent with other phases)
+ log_prompt_size "$design_prompt" "design-phase"
+
if [ "$DRY_RUN" = true ]; then
echo "[DRY RUN] Would execute design phase for $story_id"
return 0
@@ -151,6 +158,10 @@ DESIGN COMPLETE: $story_id"
LAST_DESIGN=$(echo "$result" | sed -n '/DESIGN START/,/DESIGN END/p')
if [ -n "$LAST_DESIGN" ]; then
+ # Persist the plan to a per-story file so the dev phase can read it
+ # even after a resume (when the in-memory LAST_DESIGN is empty).
+ persist_design "$story_id" "$LAST_DESIGN"
+
# Save to decision log
if type append_to_decision_log >/dev/null 2>&1; then
append_to_decision_log "DESIGN" "$story_id" "$LAST_DESIGN"
@@ -164,6 +175,27 @@ DESIGN COMPLETE: $story_id"
fi
}
+# Persist a design plan to a per-story file under DESIGN_DIR.
+# Arguments:
+# $1 - story_id
+# $2 - design content
+persist_design() {
+ local story_id="$1"
+ local content="$2"
+
+ if [ -z "${DESIGN_DIR:-}" ]; then
+ return 0
+ fi
+
+ mkdir -p "$DESIGN_DIR" 2>/dev/null || true
+ local design_file="$DESIGN_DIR/${story_id}-design.md"
+ if printf '%s\n' "$content" > "$design_file" 2>/dev/null; then
+ [ "$VERBOSE" = true ] && log "Design plan saved: $design_file"
+ else
+ log_warn "Failed to persist design plan: $design_file"
+ fi
+}
+
# Get the last design for inclusion in dev phase prompt
# Returns the design output or empty string if not available
get_last_design() {
@@ -175,7 +207,17 @@ get_last_design() {
build_design_context_for_dev() {
local story_id="$1"
- if [ -z "$LAST_DESIGN" ]; then
+ # Prefer the in-memory plan; fall back to the persisted file so a resumed
+ # run (where LAST_DESIGN is empty) still gets the design context.
+ local design="$LAST_DESIGN"
+ if [ -z "$design" ] && [ -n "${DESIGN_DIR:-}" ]; then
+ local design_file="$DESIGN_DIR/${story_id}-design.md"
+ if [ -f "$design_file" ]; then
+ design=$(cat "$design_file")
+ fi
+ fi
+
+ if [ -z "$design" ]; then
echo ""
return
fi
@@ -186,7 +228,7 @@ build_design_context_for_dev() {
The following design was created in the planning phase. Follow this plan:
-$LAST_DESIGN
+$design
### Implementation Guidelines Based on Design
diff --git a/scripts/epic-execute.sh b/scripts/epic-execute.sh
index de799472f..a52a4f8f3 100755
--- a/scripts/epic-execute.sh
+++ b/scripts/epic-execute.sh
@@ -139,6 +139,8 @@ SPRINTS_DIR="$PROJECT_ROOT/docs/sprints"
EPICS_DIR="$PROJECT_ROOT/docs/epics"
UAT_DIR="$PROJECT_ROOT/docs/uat"
LOGS_DIR="$SPRINT_ARTIFACTS_DIR/logs"
+# Per-story design plans (persisted so dev phase can read them after resume)
+DESIGN_DIR="$SPRINT_ARTIFACTS_DIR/design"
# Temporary log file during execution - will be copied to LOGS_DIR on completion
LOG_FILE="/tmp/bmad-epic-execute-$$.log"