claude-fsd 1.4.4 → 1.4.6

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/bin/claudefsd CHANGED
@@ -28,11 +28,11 @@ get_default_choice() {
28
28
  if [ ! -f BRIEF.md ]; then
29
29
  echo "0"
30
30
  elif [ ! -f docs/REQUIREMENTS.md ] && [ ! -f docs/QUESTIONS.md ]; then
31
- echo "1" # Interactive interview
31
+ echo "1" # Interactive interview (recommended)
32
32
  elif [ -f docs/REQUIREMENTS.md ] && [ ! -f docs/PLAN.md ]; then
33
- echo "2" # Create plan from requirements
33
+ echo "3" # Create plan from requirements
34
34
  elif [ -f docs/QUESTIONS.md ] && [ ! -f docs/PLAN.md ]; then
35
- echo "3" # Create plan (old flow)
35
+ echo "3" # Create plan from questions
36
36
  else
37
37
  echo "4" # Development mode
38
38
  fi
@@ -63,19 +63,20 @@ show_menu() {
63
63
  echo " 1) Interactive interview - Gather requirements through expert Q&A"
64
64
  fi
65
65
  else
66
- echo " 1) Interactive interview - Gather requirements through expert Q&A [NEW!]"
66
+ echo " 1) Interactive interview - Gather requirements through expert Q&A [RECOMMENDED]"
67
67
  fi
68
68
 
69
+ echo " 2) Batch questions - Generate all questions at once (alternative to interview)"
70
+
69
71
  # Show create plan option based on what exists
70
72
  if [ -f docs/REQUIREMENTS.md ]; then
71
- echo " 2) Create plan - Generate development plan from requirements"
73
+ echo " 3) Create plan - Generate development plan from requirements"
72
74
  elif [ -f docs/QUESTIONS.md ]; then
73
- echo " 2) Create plan - Generate plan from answered questions (legacy)"
75
+ echo " 3) Create plan - Generate plan from answered questions"
74
76
  else
75
- echo " 2) [Requires interview or questions first]"
77
+ echo " 3) [Requires interview or questions first]"
76
78
  fi
77
79
 
78
- echo " 3) Batch questions - Generate all questions at once (legacy)"
79
80
  echo " 4) Development mode - AI agents work on coding tasks"
80
81
  echo " 5) Exit"
81
82
  echo
@@ -83,9 +84,6 @@ show_menu() {
83
84
  # Show status of required files
84
85
  echo "Current status:"
85
86
  [ -f BRIEF.md ] && echo " ✓ BRIEF.md exists" || echo " ✗ BRIEF.md missing"
86
- [ -f docs/REQUIREMENTS.md ] && echo " ✓ docs/REQUIREMENTS.md exists" || echo " ✗ docs/REQUIREMENTS.md missing"
87
- [ -f docs/QUESTIONS.md ] && echo " ✓ docs/QUESTIONS.md exists" || echo " ✗ docs/QUESTIONS.md missing"
88
- [ -f docs/PLAN.md ] && echo " ✓ docs/PLAN.md exists" || echo " ✗ docs/PLAN.md missing"
89
87
 
90
88
  # Show interview session status if exists
91
89
  if [ -f docs/INTERVIEW-SESSION.json ]; then
@@ -93,6 +91,10 @@ show_menu() {
93
91
  local total_questions=$(jq -r '.question_count.total' docs/INTERVIEW-SESSION.json 2>/dev/null || echo "0")
94
92
  echo " 📝 Interview session: $session_status ($total_questions questions)"
95
93
  fi
94
+
95
+ [ -f docs/REQUIREMENTS.md ] && echo " ✓ docs/REQUIREMENTS.md exists" || echo " ✗ docs/REQUIREMENTS.md missing"
96
+ [ -f docs/QUESTIONS.md ] && echo " ✓ docs/QUESTIONS.md exists" || echo " ✗ docs/QUESTIONS.md missing"
97
+ [ -f docs/PLAN.md ] && echo " ✓ docs/PLAN.md exists" || echo " ✗ docs/PLAN.md missing"
96
98
  echo
97
99
  }
98
100
 
@@ -227,23 +229,7 @@ if [ $# -eq 0 ]; then
227
229
  exec "$(dirname "$0")/claudefsd-interview"
228
230
  ;;
229
231
  2)
230
- # Create plan - check what source to use
231
- if [ -f docs/REQUIREMENTS.md ]; then
232
- echo -e "${GREEN}Creating plan from requirements...${NC}"
233
- echo
234
- # Use requirements-based planning
235
- exec "$(dirname "$0")/claudefsd-create-plan-from-requirements"
236
- elif [ -f docs/QUESTIONS.md ]; then
237
- echo -e "${GREEN}Creating plan from answered questions...${NC}"
238
- echo
239
- exec "$(dirname "$0")/claudefsd-create-plan"
240
- else
241
- echo -e "${RED}No requirements or questions found. Please run the interview first.${NC}"
242
- exit 1
243
- fi
244
- ;;
245
- 3)
246
- # Legacy batch questions
232
+ # Batch questions
247
233
  echo -e "${GREEN}Analyzing brief and generating questions (batch mode)...${NC}"
248
234
  echo
249
235
  "$(dirname "$0")/claudefsd-analyze-brief"
@@ -257,7 +243,23 @@ if [ $# -eq 0 ]; then
257
243
  open_with_editor "docs/QUESTIONS.md"
258
244
 
259
245
  echo
260
- echo -e "${GREEN}Questions saved. After answering them, run 'claudefsd' again and select option 2 to create the plan.${NC}"
246
+ echo -e "${GREEN}Questions saved. After answering them, run 'claudefsd' again and select option 3 to create the plan.${NC}"
247
+ fi
248
+ ;;
249
+ 3)
250
+ # Create plan - check what source to use
251
+ if [ -f docs/REQUIREMENTS.md ]; then
252
+ echo -e "${GREEN}Creating plan from requirements...${NC}"
253
+ echo
254
+ # Use requirements-based planning
255
+ exec "$(dirname "$0")/claudefsd-create-plan-from-requirements"
256
+ elif [ -f docs/QUESTIONS.md ]; then
257
+ echo -e "${GREEN}Creating plan from answered questions...${NC}"
258
+ echo
259
+ exec "$(dirname "$0")/claudefsd-create-plan"
260
+ else
261
+ echo -e "${RED}No requirements or questions found. Please run the interview or generate questions first.${NC}"
262
+ exit 1
261
263
  fi
262
264
  ;;
263
265
  4)
@@ -5,9 +5,31 @@ set -e
5
5
  # Check dependencies
6
6
  $(dirname "$0")/claudefsd-check-dependencies
7
7
 
8
- # Get script directory and project root
9
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
8
+ # Get the actual location of this script (resolving symlinks)
9
+ if command -v realpath >/dev/null 2>&1; then
10
+ SCRIPT_PATH="$(realpath "$0")"
11
+ elif command -v readlink >/dev/null 2>&1; then
12
+ # macOS doesn't have realpath by default, but has readlink
13
+ SCRIPT_PATH="$0"
14
+ while [ -L "$SCRIPT_PATH" ]; do
15
+ SCRIPT_PATH="$(readlink "$SCRIPT_PATH")"
16
+ done
17
+ SCRIPT_PATH="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)/$(basename "$SCRIPT_PATH")"
18
+ else
19
+ # Fallback if neither command is available
20
+ SCRIPT_PATH="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")"
21
+ fi
22
+
23
+ # Get the directory containing the script and its parent (package root)
24
+ SCRIPT_DIR="$(dirname "$SCRIPT_PATH")"
10
25
  PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
26
+ PROMPTS_DIR="$PROJECT_ROOT/prompts"
27
+
28
+ # Verify prompts directory exists
29
+ if [ ! -d "$PROMPTS_DIR" ]; then
30
+ echo "Error: Could not locate prompts directory at $PROMPTS_DIR"
31
+ exit 1
32
+ fi
11
33
 
12
34
  mkdir -p docs
13
35
  mkdir -p logs
@@ -79,31 +101,31 @@ for persona in "${PERSONA_ARRAY[@]}"; do
79
101
  # Map persona to prompt file
80
102
  case $persona in
81
103
  DATABASE_ADMINISTRATOR|DBA)
82
- prompt_file="$PROJECT_ROOT/prompts/interview_dba_adapted.txt"
104
+ prompt_file="$PROMPTS_DIR/interview_dba_adapted.txt"
83
105
  display_name="Database Administrator"
84
106
  ;;
85
107
  TECHNICAL_ARCHITECT)
86
- prompt_file="$PROJECT_ROOT/prompts/interview_technical_architect.txt"
108
+ prompt_file="$PROMPTS_DIR/interview_technical_architect.txt"
87
109
  display_name="Technical Architect"
88
110
  ;;
89
111
  UX_EXPERT)
90
- prompt_file="$PROJECT_ROOT/prompts/interview_ux_expert.txt"
112
+ prompt_file="$PROMPTS_DIR/interview_ux_expert.txt"
91
113
  display_name="UX Expert"
92
114
  ;;
93
115
  SOFTWARE_ENGINEER)
94
- prompt_file="$PROJECT_ROOT/prompts/interview_software_engineer.txt"
116
+ prompt_file="$PROMPTS_DIR/interview_software_engineer.txt"
95
117
  display_name="Software Engineer"
96
118
  ;;
97
119
  FRONTEND_DEVELOPER)
98
- prompt_file="$PROJECT_ROOT/prompts/interview_frontend_developer.txt"
120
+ prompt_file="$PROMPTS_DIR/interview_frontend_developer.txt"
99
121
  display_name="Frontend Developer"
100
122
  ;;
101
123
  DEVOPS_ENGINEER)
102
- prompt_file="$PROJECT_ROOT/prompts/interview_devops_engineer.txt"
124
+ prompt_file="$PROMPTS_DIR/interview_devops_engineer.txt"
103
125
  display_name="DevOps Engineer"
104
126
  ;;
105
127
  SECURITY_EXPERT)
106
- prompt_file="$PROJECT_ROOT/prompts/interview_security_expert.txt"
128
+ prompt_file="$PROMPTS_DIR/interview_security_expert.txt"
107
129
  display_name="Security Expert"
108
130
  ;;
109
131
  *)
@@ -17,32 +17,36 @@ if [ ! -f BRIEF.md ]; then
17
17
  exit 1
18
18
  fi
19
19
 
20
- if [ ! -f docs/QUESTIONS.md ]; then
21
- echo "No docs/QUESTIONS.md file found. Please run 'claudefsd analyze-brief' first to generate questions."
20
+ if [ ! -f docs/QUESTIONS.md ] && [ ! -f docs/REQUIREMENTS.md ]; then
21
+ echo "No docs/QUESTIONS.md or docs/REQUIREMENTS.md found."
22
+ echo "Please run either:"
23
+ echo " - 'claudefsd analyze-brief' to generate questions, or"
24
+ echo " - 'claudefsd interview' to conduct an interactive interview"
22
25
  exit 1
23
26
  fi
24
27
 
25
28
  LOGFILE="logs/claude-$(date +%Y%m%d_%H%M%S).txt"
26
29
 
27
30
  echo -e "\033[32m==================================================================\033[0m"
28
- echo -e "\033[32m== CREATING PLAN FROM ANSWERED QUESTIONS\033[0m"
31
+ echo -e "\033[32m== CREATING PLAN FROM PROJECT INPUTS\033[0m"
29
32
  echo -e "\033[32m==================================================================\033[0m"
30
33
 
31
34
  prompt2="
32
35
  Read all of these documents if they exist:
33
36
  - BRIEF.md -- the project brief
37
+ - docs/QUESTIONS.md -- the project questions (with answers) from analyze-brief or interview
38
+ - docs/REQUIREMENTS.md -- consolidated requirements from interview process
34
39
  - docs/CLAUDE-NOTES.md -- AI's working notes and understanding
35
40
  - docs/PLAN.md -- the project plan
36
- - docs/QUESTIONS.md -- the project questions (with answers)
37
41
  - docs/IDEAS.md -- the backlog of future ideas
38
42
  - docs/WEBTESTS.md -- the project web tests
39
43
  - README.md -- the project README
40
44
 
41
45
  Your job, as a megathinking architect and project manager, is to create the project plan and working notes.
42
46
 
43
- 1. Read through the BRIEF.md and the answered questions in docs/QUESTIONS.md.
47
+ 1. Read through the BRIEF.md and any available requirements/questions (docs/QUESTIONS.md and/or docs/REQUIREMENTS.md).
44
48
  2. Update or create docs/CLAUDE-NOTES.md with your interpretation and understanding of the project.
45
- 3. Update or create docs/PLAN.md with a detailed implementation plan based on the brief and answered questions.
49
+ 3. Update or create docs/PLAN.md with a detailed implementation plan based on all available inputs.
46
50
 
47
51
  The CLAUDE-NOTES.md should contain:
48
52
  - Your understanding of the project goals and requirements
@@ -73,11 +77,64 @@ claude --model opus --dangerously-skip-permissions -p "$prompt2" | tee >(cat > $
73
77
 
74
78
  # Only run codex if available
75
79
  if command -v codex >/dev/null 2>&1; then
76
- echo "Running codex o3 (results won't display)..."
77
- codex -m o3 --full-auto -q "$prompt2" > $LOGFILE-ba4
80
+ echo ""
81
+ echo -e "\033[33m==================================================================\033[0m"
82
+ echo -e "\033[33m== RUNNING O3-PRO FOR DEEP STRATEGIC PLANNING\033[0m"
83
+ echo -e "\033[33m==================================================================\033[0m"
84
+ echo "⏳ This will take several minutes as o3-pro deeply analyzes the project..."
85
+ echo " o3-pro excels at strategic thinking and will create a comprehensive plan."
86
+ echo ""
87
+
88
+ # Prepare comprehensive context for o3-pro
89
+ o3_prompt="You are an elite software architect and strategic planner using o3-pro's advanced reasoning capabilities.
90
+
91
+ CONTEXT DOCUMENTS:
92
+ $([ -f BRIEF.md ] && echo "=== PROJECT BRIEF ===" && cat BRIEF.md && echo "")
93
+ $([ -f docs/QUESTIONS.md ] && echo "=== QUESTIONS & ANSWERS ===" && cat docs/QUESTIONS.md && echo "")
94
+ $([ -f docs/REQUIREMENTS.md ] && echo "=== CONSOLIDATED REQUIREMENTS ===" && cat docs/REQUIREMENTS.md && echo "")
95
+ $([ -f docs/INTERVIEW-SESSION.json ] && echo "=== INTERVIEW METADATA ===" && cat docs/INTERVIEW-SESSION.json && echo "")
96
+ $([ -f docs/CLAUDE-NOTES.md ] && echo "=== EXISTING NOTES ===" && cat docs/CLAUDE-NOTES.md && echo "")
97
+ $([ -f docs/IDEAS.md ] && echo "=== IDEAS BACKLOG ===" && cat docs/IDEAS.md && echo "")
98
+ $([ -f README.md ] && echo "=== README ===" && cat README.md && echo "")
99
+
100
+ TASK:
101
+ Using your deep strategic reasoning, create a comprehensive project architecture and implementation plan.
102
+
103
+ 1. ARCHITECTURAL ANALYSIS (docs/CLAUDE-NOTES.md):
104
+ - System architecture and key design decisions
105
+ - Technology stack justification
106
+ - Critical technical challenges and mitigation strategies
107
+ - Integration points and dependencies
108
+ - Performance and scalability considerations
109
+ - Security architecture
110
+ - Long-term maintainability strategy
111
+
112
+ 2. IMPLEMENTATION PLAN (docs/PLAN.md):
113
+ - Phased development approach with clear milestones
114
+ - Detailed task breakdown with dependencies
115
+ - Risk assessment for each phase
116
+ - Testing strategy integrated into each phase
117
+ - Infrastructure needs (proportional to project size)
118
+ - Performance benchmarks and acceptance criteria
119
+
120
+ Remember:
121
+ - Think strategically about the entire system lifecycle
122
+ - Consider edge cases and failure modes
123
+ - Plan for iterative development and feedback loops
124
+ - Keep infrastructure proportional to project complexity
125
+ - Prioritize robustness and maintainability
126
+
127
+ Take your time to think deeply about the optimal approach."
128
+
129
+ echo "Running codex o3-pro (this may take 3-5 minutes)..."
130
+ codex -m o3-pro --full-auto -q "$o3_prompt" | tee $LOGFILE-ba4
131
+ echo ""
132
+ echo "✅ o3-pro strategic planning complete!"
78
133
  else
79
- echo "Warning: codex not found, skipping enhanced planning"
80
- echo "Codex not available, skipping o3 analysis" > $LOGFILE-ba4
134
+ echo ""
135
+ echo -e "\033[33mNote: Install 'codex' CLI to enable o3-pro strategic planning for enhanced results.\033[0m"
136
+ echo "Proceeding with standard planning using Claude Opus..."
137
+ echo "Codex not available, skipping o3-pro strategic analysis" > $LOGFILE-ba4
81
138
  fi
82
139
 
83
140
  echo -e "\033[32m==================================================================\033[0m"
package/bin/claudefsd-dev CHANGED
@@ -221,7 +221,7 @@ Your final output should consist only of the execution details, linter output, c
221
221
  # also run it in the background because it's very slow
222
222
  # Only run if codex is available
223
223
  if command -v codex >/dev/null 2>&1; then
224
- (codex --full-auto -q "
224
+ (codex --full-auto -m o3 -q "
225
225
  You are the team's static code reviewer.
226
226
  A developer has completed this task: $nexttask
227
227
  The developer's notes are at $LOGFILE-developer .
@@ -1,12 +1,35 @@
1
1
  #!/bin/bash
2
2
 
3
- # Use the fast version which prepares questions in background
4
- exec "$(dirname "$0")/claudefsd-interview-fast" "$@"
3
+ set -e
5
4
 
6
- # Get the directory where this script is located
7
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
8
- # Get the parent directory (project root)
5
+ # Check dependencies
6
+ $(dirname "$0")/claudefsd-check-dependencies
7
+
8
+ # Get the actual location of this script (resolving symlinks)
9
+ if command -v realpath >/dev/null 2>&1; then
10
+ SCRIPT_PATH="$(realpath "$0")"
11
+ elif command -v readlink >/dev/null 2>&1; then
12
+ # macOS doesn't have realpath by default, but has readlink
13
+ SCRIPT_PATH="$0"
14
+ while [ -L "$SCRIPT_PATH" ]; do
15
+ SCRIPT_PATH="$(readlink "$SCRIPT_PATH")"
16
+ done
17
+ SCRIPT_PATH="$(cd "$(dirname "$SCRIPT_PATH")" && pwd)/$(basename "$SCRIPT_PATH")"
18
+ else
19
+ # Fallback if neither command is available
20
+ SCRIPT_PATH="$(cd "$(dirname "$0")" && pwd)/$(basename "$0")"
21
+ fi
22
+
23
+ # Get the directory containing the script and its parent (package root)
24
+ SCRIPT_DIR="$(dirname "$SCRIPT_PATH")"
9
25
  PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
26
+ PROMPTS_DIR="$PROJECT_ROOT/prompts"
27
+
28
+ # Verify prompts directory exists
29
+ if [ ! -d "$PROMPTS_DIR" ]; then
30
+ echo -e "${RED}Error: Could not locate prompts directory at $PROMPTS_DIR${NC}"
31
+ exit 1
32
+ fi
10
33
 
11
34
  # Colors for output
12
35
  GREEN='\033[0;32m'
@@ -18,12 +41,15 @@ NC='\033[0m' # No Color
18
41
  # Create necessary directories
19
42
  mkdir -p docs
20
43
  mkdir -p logs
21
- mkdir -p "$PROJECT_ROOT/prompts"
44
+ # prompts directory is part of the package, no need to create
45
+ mkdir -p tmp
22
46
 
23
47
  # Session file paths
24
48
  SESSION_FILE="docs/INTERVIEW-SESSION.json"
25
49
  QUESTIONS_FILE="docs/QUESTIONS.md"
26
50
  REQUIREMENTS_FILE="docs/REQUIREMENTS.md"
51
+ QUESTION_CACHE="tmp/next_question.txt"
52
+ PERSONA_CACHE="tmp/next_persona.txt"
27
53
 
28
54
  # Check for BRIEF.md
29
55
  if [ ! -f BRIEF.md ]; then
@@ -47,6 +73,7 @@ init_session() {
47
73
  "TECHNICAL_ARCHITECT": 0,
48
74
  "UX_EXPERT": 0,
49
75
  "SOFTWARE_ENGINEER": 0,
76
+ "FRONTEND_DEVELOPER": 0,
50
77
  "DEVOPS_ENGINEER": 0,
51
78
  "SECURITY_EXPERT": 0
52
79
  }
@@ -116,8 +143,8 @@ update_session() {
116
143
  "$SESSION_FILE" > "$SESSION_FILE.tmp" && mv "$SESSION_FILE.tmp" "$SESSION_FILE"
117
144
  }
118
145
 
119
- # Function to get coordinator decision
120
- get_coordinator_decision() {
146
+ # Background function to prepare next question
147
+ prepare_next_question_bg() {
121
148
  local brief_content=$(cat BRIEF.md)
122
149
  local all_qa=$(tail -n +4 "$QUESTIONS_FILE" 2>/dev/null || echo "No questions asked yet.")
123
150
  local recent_qa=$(tail -n 20 "$QUESTIONS_FILE" 2>/dev/null || echo "No questions asked yet.")
@@ -128,14 +155,15 @@ get_coordinator_decision() {
128
155
  local ta_count=$(jq -r '.question_count.by_persona.TECHNICAL_ARCHITECT' "$SESSION_FILE")
129
156
  local ux_count=$(jq -r '.question_count.by_persona.UX_EXPERT' "$SESSION_FILE")
130
157
  local se_count=$(jq -r '.question_count.by_persona.SOFTWARE_ENGINEER' "$SESSION_FILE")
158
+ local frontend_count=$(jq -r '.question_count.by_persona.FRONTEND_DEVELOPER' "$SESSION_FILE")
131
159
  local devops_count=$(jq -r '.question_count.by_persona.DEVOPS_ENGINEER' "$SESSION_FILE")
132
160
  local security_count=$(jq -r '.question_count.by_persona.SECURITY_EXPERT' "$SESSION_FILE")
133
161
 
134
- # Create Q&A summary by domain (simplified for now)
135
- local qa_summary="Data: $dba_count questions | Architecture: $ta_count questions | UX: $ux_count questions | Engineering: $se_count questions | DevOps: $devops_count questions | Security: $security_count questions"
162
+ # Create Q&A summary by domain
163
+ local qa_summary="Data: $dba_count questions | Architecture: $ta_count questions | UX: $ux_count questions | Backend: $se_count questions | Frontend: $frontend_count questions | DevOps: $devops_count questions | Security: $security_count questions"
136
164
 
137
165
  # Read coordinator prompt
138
- local coordinator_prompt=$(cat "$PROJECT_ROOT/prompts/interview_coordinator.txt")
166
+ local coordinator_prompt=$(cat "$PROMPTS_DIR/interview_coordinator.txt")
139
167
 
140
168
  # Replace tokens
141
169
  coordinator_prompt="${coordinator_prompt//\{brief_content\}/$brief_content}"
@@ -144,89 +172,133 @@ get_coordinator_decision() {
144
172
  coordinator_prompt="${coordinator_prompt//\{ta_count\}/$ta_count}"
145
173
  coordinator_prompt="${coordinator_prompt//\{ux_count\}/$ux_count}"
146
174
  coordinator_prompt="${coordinator_prompt//\{se_count\}/$se_count}"
175
+ coordinator_prompt="${coordinator_prompt//\{frontend_count\}/$frontend_count}"
147
176
  coordinator_prompt="${coordinator_prompt//\{devops_count\}/$devops_count}"
148
177
  coordinator_prompt="${coordinator_prompt//\{security_count\}/$security_count}"
149
178
  coordinator_prompt="${coordinator_prompt//\{recent_qa_history\}/$recent_qa}"
150
179
  coordinator_prompt="${coordinator_prompt//\{qa_summary_by_domain\}/$qa_summary}"
151
180
 
152
181
  # Get coordinator decision
153
- local decision=$(claude --model sonnet -p "$coordinator_prompt" 2>/dev/null | tail -1)
154
-
155
- # Validate decision
156
- if [ -z "$decision" ]; then
157
- echo -e "${RED}Error: No decision from coordinator${NC}" >&2
158
- echo "SOFTWARE_ENGINEER" # Default fallback
159
- return
160
- fi
161
-
162
- # Clean up decision (remove any whitespace)
163
- decision=$(echo "$decision" | tr -d ' \n\r')
164
-
165
- # Validate it's a known persona or COMPLETE
166
- case "$decision" in
167
- DBA|TECHNICAL_ARCHITECT|UX_EXPERT|SOFTWARE_ENGINEER|DEVOPS_ENGINEER|SECURITY_EXPERT|COMPLETE)
168
- echo "$decision"
182
+ local next_persona=$(claude --model sonnet -p "$coordinator_prompt" 2>/dev/null | tail -1)
183
+
184
+ # Validate and clean decision - remove spaces, newlines, and markdown formatting
185
+ next_persona=$(echo "$next_persona" | tr -d ' \n\r' | sed 's/[*_`]//g')
186
+
187
+ # Also handle cases where it might be prefixed with ** or __
188
+ next_persona="${next_persona#**}"
189
+ next_persona="${next_persona%**}"
190
+ next_persona="${next_persona#__}"
191
+ next_persona="${next_persona%__}"
192
+
193
+ # Normalize persona names (handle cases with/without underscores)
194
+ # Use tr for uppercase conversion (portable across bash versions)
195
+ next_persona_upper=$(echo "$next_persona" | tr '[:lower:]' '[:upper:]')
196
+ case "$next_persona_upper" in
197
+ DBA|DATABASE_ADMINISTRATOR)
198
+ next_persona="DBA"
169
199
  ;;
170
- *)
171
- echo -e "${RED}Error: Invalid decision from coordinator: $decision${NC}" >&2
172
- echo "SOFTWARE_ENGINEER" # Default fallback
200
+ TECHNICAL_ARCHITECT|TECHNICALARCHITECT|TA)
201
+ next_persona="TECHNICAL_ARCHITECT"
173
202
  ;;
174
- esac
175
- }
176
-
177
- # Function to get question from persona
178
- get_persona_question() {
179
- local persona="$1"
180
- local brief_content=$(cat BRIEF.md)
181
- local all_qa=$(tail -n +4 "$QUESTIONS_FILE" || echo "No questions asked yet.")
182
-
183
- # Get persona-specific history
184
- local persona_qa=$(grep -A1 "\[$persona\]:" "$QUESTIONS_FILE" || echo "No previous questions from this persona.")
185
-
186
- # Select appropriate prompt file
187
- local prompt_file=""
188
- case $persona in
189
- DBA)
190
- prompt_file="$PROJECT_ROOT/prompts/interview_dba_adapted.txt"
203
+ UX_EXPERT|UXEXPERT|UX)
204
+ next_persona="UX_EXPERT"
191
205
  ;;
192
- TECHNICAL_ARCHITECT)
193
- prompt_file="$PROJECT_ROOT/prompts/interview_technical_architect.txt"
206
+ SOFTWARE_ENGINEER|SOFTWAREENGINEER|SE)
207
+ next_persona="SOFTWARE_ENGINEER"
194
208
  ;;
195
- UX_EXPERT)
196
- prompt_file="$PROJECT_ROOT/prompts/interview_ux_expert.txt"
209
+ FRONTEND_DEVELOPER|FRONTENDDEVELOPER|FE)
210
+ next_persona="FRONTEND_DEVELOPER"
197
211
  ;;
198
- SOFTWARE_ENGINEER)
199
- prompt_file="$PROJECT_ROOT/prompts/interview_software_engineer.txt"
212
+ DEVOPS_ENGINEER|DEVOPSENGINEER|DEVOPS)
213
+ next_persona="DEVOPS_ENGINEER"
200
214
  ;;
201
- DEVOPS_ENGINEER)
202
- prompt_file="$PROJECT_ROOT/prompts/interview_devops_engineer.txt"
215
+ SECURITY_EXPERT|SECURITYEXPERT|SECURITY)
216
+ next_persona="SECURITY_EXPERT"
203
217
  ;;
204
- SECURITY_EXPERT)
205
- prompt_file="$PROJECT_ROOT/prompts/interview_security_expert.txt"
218
+ COMPLETE|DONE|FINISHED)
219
+ next_persona="COMPLETE"
220
+ ;;
221
+ *)
222
+ echo "Warning: Invalid coordinator decision '$next_persona', using SOFTWARE_ENGINEER" >&2
223
+ next_persona="SOFTWARE_ENGINEER"
206
224
  ;;
207
225
  esac
208
226
 
209
- if [ ! -f "$prompt_file" ]; then
210
- echo "Error: Prompt file not found for $persona"
211
- return 1
212
- fi
213
-
214
- # Read prompt template
215
- local prompt_template=$(cat "$prompt_file")
216
-
217
- # Replace tokens
218
- prompt_template="${prompt_template//\{brief_content\}/$brief_content}"
219
- prompt_template="${prompt_template//\{all_qa_history\}/$all_qa}"
220
- prompt_template="${prompt_template//\{dba_qa_history\}/$persona_qa}"
221
- prompt_template="${prompt_template//\{ta_qa_history\}/$persona_qa}"
222
- prompt_template="${prompt_template//\{ux_qa_history\}/$persona_qa}"
223
- prompt_template="${prompt_template//\{se_qa_history\}/$persona_qa}"
224
- prompt_template="${prompt_template//\{devops_qa_history\}/$persona_qa}"
225
- prompt_template="${prompt_template//\{security_qa_history\}/$persona_qa}"
227
+ echo "$next_persona" > "$PERSONA_CACHE"
226
228
 
227
- # Get question from Claude
228
- local question=$(claude --model sonnet -p "$prompt_template" 2>/dev/null | tail -1)
229
- echo "$question"
229
+ # If not complete, get the question
230
+ if [ "$next_persona" != "COMPLETE" ]; then
231
+ # Get persona-specific history
232
+ local persona_qa=$(grep -A1 "\[$next_persona\]:" "$QUESTIONS_FILE" 2>/dev/null || echo "No previous questions from this persona.")
233
+
234
+ # Select appropriate prompt file
235
+ local prompt_file=""
236
+ case $next_persona in
237
+ DBA)
238
+ prompt_file="$PROMPTS_DIR/interview_dba_adapted.txt"
239
+ ;;
240
+ TECHNICAL_ARCHITECT)
241
+ prompt_file="$PROMPTS_DIR/interview_technical_architect.txt"
242
+ ;;
243
+ UX_EXPERT)
244
+ prompt_file="$PROMPTS_DIR/interview_ux_expert.txt"
245
+ ;;
246
+ SOFTWARE_ENGINEER)
247
+ prompt_file="$PROMPTS_DIR/interview_software_engineer.txt"
248
+ ;;
249
+ FRONTEND_DEVELOPER)
250
+ prompt_file="$PROMPTS_DIR/interview_frontend_developer.txt"
251
+ ;;
252
+ DEVOPS_ENGINEER)
253
+ prompt_file="$PROMPTS_DIR/interview_devops_engineer.txt"
254
+ ;;
255
+ SECURITY_EXPERT)
256
+ prompt_file="$PROMPTS_DIR/interview_security_expert.txt"
257
+ ;;
258
+ esac
259
+
260
+ if [ -f "$prompt_file" ]; then
261
+ # Gather all existing project documents
262
+ local existing_docs=""
263
+ if [ -f "docs/PLAN.md" ]; then
264
+ existing_docs="${existing_docs}$(printf '=== EXISTING PLAN ===\n')$(cat docs/PLAN.md)$(printf '\n\n')"
265
+ fi
266
+ if [ -f "docs/REQUIREMENTS.md" ]; then
267
+ existing_docs="${existing_docs}$(printf '=== EXISTING REQUIREMENTS ===\n')$(cat docs/REQUIREMENTS.md)$(printf '\n\n')"
268
+ fi
269
+ if [ -f "docs/CLAUDE-NOTES.md" ]; then
270
+ existing_docs="${existing_docs}$(printf '=== EXISTING TECHNICAL NOTES ===\n')$(cat docs/CLAUDE-NOTES.md)$(printf '\n\n')"
271
+ fi
272
+ if [ -f "README.md" ]; then
273
+ existing_docs="${existing_docs}$(printf '=== README ===\n')$(cat README.md)$(printf '\n\n')"
274
+ fi
275
+
276
+ # Read prompt template
277
+ local prompt_template=$(cat "$prompt_file")
278
+
279
+ # Add existing docs context if any exist
280
+ if [ -n "$existing_docs" ]; then
281
+ prompt_template="$(printf 'EXISTING PROJECT DOCUMENTATION:\n')${existing_docs}$(printf '\n')${prompt_template}"
282
+ fi
283
+
284
+ # Replace tokens
285
+ prompt_template="${prompt_template//\{brief_content\}/$brief_content}"
286
+ prompt_template="${prompt_template//\{all_qa_history\}/$all_qa}"
287
+ prompt_template="${prompt_template//\{dba_qa_history\}/$persona_qa}"
288
+ prompt_template="${prompt_template//\{ta_qa_history\}/$persona_qa}"
289
+ prompt_template="${prompt_template//\{ux_qa_history\}/$persona_qa}"
290
+ prompt_template="${prompt_template//\{se_qa_history\}/$persona_qa}"
291
+ prompt_template="${prompt_template//\{frontend_qa_history\}/$persona_qa}"
292
+ prompt_template="${prompt_template//\{devops_qa_history\}/$persona_qa}"
293
+ prompt_template="${prompt_template//\{security_qa_history\}/$persona_qa}"
294
+
295
+ # Get question from Claude
296
+ local question=$(claude --model sonnet -p "$prompt_template" 2>/dev/null | tail -1)
297
+ echo "$question" > "$QUESTION_CACHE"
298
+
299
+ # Question is ready in cache, no output needed
300
+ fi
301
+ fi
230
302
  }
231
303
 
232
304
  # Function to save Q&A
@@ -254,6 +326,7 @@ show_progress() {
254
326
  echo -e " Technical Architect: $(jq -r '.question_count.by_persona.TECHNICAL_ARCHITECT' "$SESSION_FILE")"
255
327
  echo -e " UX Expert: $(jq -r '.question_count.by_persona.UX_EXPERT' "$SESSION_FILE")"
256
328
  echo -e " Software Engineer: $(jq -r '.question_count.by_persona.SOFTWARE_ENGINEER' "$SESSION_FILE")"
329
+ echo -e " Frontend Developer: $(jq -r '.question_count.by_persona.FRONTEND_DEVELOPER' "$SESSION_FILE")"
257
330
  echo -e " DevOps Engineer: $(jq -r '.question_count.by_persona.DEVOPS_ENGINEER' "$SESSION_FILE")"
258
331
  echo -e " Security Expert: $(jq -r '.question_count.by_persona.SECURITY_EXPERT' "$SESSION_FILE")"
259
332
 
@@ -302,8 +375,8 @@ Format the output as a clean, well-structured markdown document suitable for fee
302
375
 
303
376
  # Main interview loop
304
377
  main() {
305
- echo -e "${GREEN}<� Claude FSD Interactive Interview System${NC}"
306
- echo -e "${GREEN}============================================${NC}"
378
+ echo -e "${GREEN}🎙️ Claude FSD Interactive Interview System (Fast Mode)${NC}"
379
+ echo -e "${GREEN}======================================================${NC}"
307
380
  echo ""
308
381
 
309
382
  # Load or init session
@@ -311,7 +384,8 @@ main() {
311
384
 
312
385
  echo -e "\n${YELLOW}Instructions:${NC}"
313
386
  echo "- Answer each question concisely (1-2 sentences recommended)"
314
- echo "- Your progress is automatically saved after each answer"
387
+ echo "- The next question is prepared while you answer (faster!)"
388
+ echo "- Your progress is automatically saved"
315
389
  echo ""
316
390
  echo -e "${YELLOW}To finish the interview:${NC}"
317
391
  echo " • Type 'done' or 'exit' and press Enter"
@@ -322,11 +396,30 @@ main() {
322
396
  # Show current progress
323
397
  show_progress
324
398
 
399
+ # Background process PID
400
+ bg_pid=""
401
+ first_question=true
402
+
325
403
  # Main loop
326
404
  while true; do
327
- # Get coordinator decision
328
- echo -e "${BLUE}Consulting project coordinator...${NC}"
329
- local next_persona=$(get_coordinator_decision)
405
+ # Only wait for background if there's one running and we have no cached question
406
+ if [ -n "$bg_pid" ] && [ ! -f "$QUESTION_CACHE" ]; then
407
+ if [ "$first_question" = "true" ]; then
408
+ echo -e "${BLUE}Preparing first question...${NC}"
409
+ fi
410
+ wait $bg_pid 2>/dev/null || true
411
+ bg_pid=""
412
+ fi
413
+
414
+ # Start preparing next question in background (for next iteration)
415
+ if [ ! -f "$QUESTION_CACHE" ]; then
416
+ prepare_next_question_bg &
417
+ bg_pid=$!
418
+ wait $bg_pid # Must wait if we don't have a question yet
419
+ fi
420
+
421
+ # Read cached persona and question
422
+ local next_persona=$(cat "$PERSONA_CACHE" 2>/dev/null || echo "SOFTWARE_ENGINEER")
330
423
 
331
424
  # Check if complete
332
425
  if [ "$next_persona" = "COMPLETE" ]; then
@@ -338,13 +431,13 @@ main() {
338
431
  break
339
432
  else
340
433
  echo "Continuing with more questions..."
341
- next_persona="SOFTWARE_ENGINEER" # Default to SE if user wants more
434
+ next_persona="SOFTWARE_ENGINEER"
435
+ echo "$next_persona" > "$PERSONA_CACHE"
342
436
  fi
343
437
  fi
344
438
 
345
- # Get question from selected persona
346
- echo -e "\n${BLUE}[$next_persona] is preparing a question...${NC}"
347
- local question=$(get_persona_question "$next_persona")
439
+ # Read the prepared question
440
+ local question=$(cat "$QUESTION_CACHE" 2>/dev/null || echo "What are the main goals of this project?")
348
441
 
349
442
  # Update session with current question
350
443
  update_session "$next_persona" "$question"
@@ -352,17 +445,29 @@ main() {
352
445
  # Display question
353
446
  echo -e "\n${GREEN}[$next_persona]${NC} $question"
354
447
 
448
+ # Clear cache files for next iteration
449
+ rm -f "$PERSONA_CACHE" "$QUESTION_CACHE"
450
+
451
+ # Start preparing next question immediately in background
452
+ prepare_next_question_bg &
453
+ bg_pid=$!
454
+ first_question=false
455
+
355
456
  # Get answer
356
457
  echo -e "${YELLOW}Your answer (or 'done' to finish):${NC}"
357
458
  echo -n "> "
358
459
  if ! read -r answer; then
359
460
  # EOF detected (Ctrl+D)
461
+ # Kill background process
462
+ [ -n "$bg_pid" ] && kill $bg_pid 2>/dev/null || true
360
463
  return 1
361
464
  fi
362
465
 
363
466
  # Check for exit commands
364
467
  if [[ "$answer" =~ ^(done|exit|quit)$ ]]; then
365
468
  echo -e "\n${YELLOW}Interview concluded by user.${NC}"
469
+ # Kill background process
470
+ [ -n "$bg_pid" ] && kill $bg_pid 2>/dev/null || true
366
471
  consolidate_requirements
367
472
  break
368
473
  fi
@@ -377,6 +482,9 @@ main() {
377
482
  fi
378
483
  done
379
484
 
485
+ # Clean up background process
486
+ [ -n "$bg_pid" ] && kill $bg_pid 2>/dev/null || true
487
+
380
488
  echo -e "\n${GREEN}Interview complete!${NC}"
381
489
  echo "- Questions saved in: $QUESTIONS_FILE"
382
490
  echo "- Requirements saved in: $REQUIREMENTS_FILE"
@@ -384,7 +492,10 @@ main() {
384
492
  }
385
493
 
386
494
  # Handle Ctrl+C as hard stop
387
- trap 'echo -e "\n${RED}Interview cancelled.${NC}"; exit 1' INT
495
+ trap 'echo -e "\n${RED}Interview cancelled.${NC}"; [ -n "$bg_pid" ] && kill $bg_pid 2>/dev/null || true; exit 1' INT
496
+
497
+ # Clean up cache files on exit
498
+ trap 'rm -f "$PERSONA_CACHE" "$QUESTION_CACHE"' EXIT
388
499
 
389
500
  # Run main function and handle EOF
390
501
  if main; then
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-fsd",
3
- "version": "1.4.4",
3
+ "version": "1.4.6",
4
4
  "description": "Claude Full Self Drive tools for autonomous AI-powered development",
5
5
  "bin": {
6
6
  "claude-fsd": "bin/claude-fsd",
@@ -8,11 +8,9 @@
8
8
  "claudefsd-check-dependencies": "bin/claudefsd-check-dependencies",
9
9
  "claudefsd-dev": "bin/claudefsd-dev",
10
10
  "claudefsd-interview": "bin/claudefsd-interview",
11
- "claudefsd-interview-fast": "bin/claudefsd-interview-fast",
12
11
  "claudefsd-analyze-brief": "bin/claudefsd-analyze-brief",
13
12
  "claudefsd-analyze-brief-personas": "bin/claudefsd-analyze-brief-personas",
14
- "claudefsd-create-plan": "bin/claudefsd-create-plan",
15
- "claudefsd-create-plan-from-requirements": "bin/claudefsd-create-plan-from-requirements"
13
+ "claudefsd-create-plan": "bin/claudefsd-create-plan"
16
14
  },
17
15
  "files": [
18
16
  "bin/",
@@ -1,87 +0,0 @@
1
- #!/bin/bash
2
-
3
- set -e
4
-
5
- # Check dependencies
6
- $(dirname "$0")/claudefsd-check-dependencies
7
-
8
- mkdir -p logs
9
-
10
- # Use a temporary directory for tmp files, as codex is sandboxed to this directory
11
- mkdir -p tmp
12
- export TMPDIR=tmp/
13
-
14
- # look for required files
15
- if [ ! -f BRIEF.md ]; then
16
- echo "No BRIEF.md file found, please create one first"
17
- exit 1
18
- fi
19
-
20
- if [ ! -f docs/REQUIREMENTS.md ]; then
21
- echo "No docs/REQUIREMENTS.md file found. Please run 'claudefsd interview' first to generate requirements."
22
- exit 1
23
- fi
24
-
25
- LOGFILE="logs/claude-$(date +%Y%m%d_%H%M%S).txt"
26
-
27
- echo -e "\033[32m==================================================================\033[0m"
28
- echo -e "\033[32m== CREATING PLAN FROM REQUIREMENTS\033[0m"
29
- echo -e "\033[32m==================================================================\033[0m"
30
-
31
- prompt="
32
- Read all of these documents if they exist:
33
- - BRIEF.md -- the project brief
34
- - docs/REQUIREMENTS.md -- consolidated requirements from interview
35
- - docs/CLAUDE-NOTES.md -- AI's working notes and understanding
36
- - docs/IDEAS.md -- the backlog of future ideas
37
- - docs/WEBTESTS.md -- the project web tests
38
- - README.md -- the project README
39
-
40
- Your job, as a megathinking architect and project manager, is to create the project plan and working notes.
41
-
42
- 1. Read through the BRIEF.md and the consolidated requirements in docs/REQUIREMENTS.md.
43
- 2. Update or create docs/CLAUDE-NOTES.md with your interpretation and understanding of the project.
44
- 3. Update or create docs/PLAN.md with a detailed implementation plan based on the brief and requirements.
45
-
46
- The CLAUDE-NOTES.md should contain:
47
- - Your understanding of the project goals and requirements
48
- - Key technical decisions and rationale
49
- - Important assumptions and constraints
50
- - Areas that may need future clarification
51
-
52
- The PLAN.md should contain:
53
- - Ordered list of development tasks with [ ] checkboxes
54
- - Each task should be specific and actionable
55
- - Include proportional infrastructure setup (basic linting + pre-commit hooks)
56
- - Group related tasks into logical phases
57
-
58
- INFRASTRUCTURE PROPORTIONALITY RULES:
59
- - Basic linter + pre-commit hooks: Always include for any project
60
- - Tests: Should be ≤50% the size of functional code (not 3x larger!)
61
- - For simple shell scripts (~200-500 lines): Basic integration tests only
62
- - For complex systems (>1000 lines): More comprehensive testing
63
- - NO enterprise patterns for simple solutions (file locking, complex CI, monolithic architectures)
64
- - Follow existing claude-fsd pattern: separate focused scripts, not monoliths
65
- - FAIL LOUD - simple error handling, exit on failure
66
- - Choose infrastructure complexity appropriate to solution size
67
- "
68
-
69
- # run architect
70
- echo "Running claude with opus model..."
71
- claude --model opus --dangerously-skip-permissions -p "$prompt" | tee >(cat > $LOGFILE-architect)
72
-
73
- # Only run codex if available
74
- if command -v codex >/dev/null 2>&1; then
75
- echo "Running codex o3 (results won't display)..."
76
- codex -m o3 --full-auto -q "$prompt" > $LOGFILE-architect-o3
77
- else
78
- echo "Warning: codex not found, skipping enhanced planning"
79
- echo "Codex not available, skipping o3 analysis" > $LOGFILE-architect-o3
80
- fi
81
-
82
- echo -e "\033[32m==================================================================\033[0m"
83
- echo -e "\033[32m== PLAN CREATION COMPLETE\033[0m"
84
- echo -e "\033[32m==================================================================\033[0m"
85
- echo "Plan created in docs/PLAN.md"
86
- echo "Working notes saved in docs/CLAUDE-NOTES.md"
87
- echo "You can now run 'claudefsd dev' to start the development process."
@@ -1,434 +0,0 @@
1
- #!/bin/bash
2
-
3
- set -e
4
-
5
- # Check dependencies
6
- $(dirname "$0")/claudefsd-check-dependencies
7
-
8
- # Get the directory where this script is located
9
- SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
10
- # Get the parent directory (project root)
11
- PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
12
-
13
- # Colors for output
14
- GREEN='\033[0;32m'
15
- YELLOW='\033[0;33m'
16
- BLUE='\033[0;34m'
17
- RED='\033[0;31m'
18
- NC='\033[0m' # No Color
19
-
20
- # Create necessary directories
21
- mkdir -p docs
22
- mkdir -p logs
23
- mkdir -p "$PROJECT_ROOT/prompts"
24
- mkdir -p tmp
25
-
26
- # Session file paths
27
- SESSION_FILE="docs/INTERVIEW-SESSION.json"
28
- QUESTIONS_FILE="docs/QUESTIONS.md"
29
- REQUIREMENTS_FILE="docs/REQUIREMENTS.md"
30
- QUESTION_CACHE="tmp/next_question.txt"
31
- PERSONA_CACHE="tmp/next_persona.txt"
32
-
33
- # Check for BRIEF.md
34
- if [ ! -f BRIEF.md ]; then
35
- echo -e "${RED}No BRIEF.md file found. Please create one first.${NC}"
36
- exit 1
37
- fi
38
-
39
- # Function to initialize session
40
- init_session() {
41
- local session_id="interview_$(date +%Y%m%d_%H%M%S)"
42
- cat > "$SESSION_FILE" <<EOF
43
- {
44
- "session_id": "$session_id",
45
- "started_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
46
- "last_updated": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
47
- "status": "in_progress",
48
- "question_count": {
49
- "total": 0,
50
- "by_persona": {
51
- "DBA": 0,
52
- "TECHNICAL_ARCHITECT": 0,
53
- "UX_EXPERT": 0,
54
- "SOFTWARE_ENGINEER": 0,
55
- "FRONTEND_DEVELOPER": 0,
56
- "DEVOPS_ENGINEER": 0,
57
- "SECURITY_EXPERT": 0
58
- }
59
- },
60
- "current_question": null
61
- }
62
- EOF
63
-
64
- # Initialize QUESTIONS.md
65
- echo "# Project Interview Questions and Answers" > "$QUESTIONS_FILE"
66
- echo "" >> "$QUESTIONS_FILE"
67
- echo "## Interview Session: $session_id" >> "$QUESTIONS_FILE"
68
- echo "" >> "$QUESTIONS_FILE"
69
-
70
- echo -e "${GREEN}New interview session started: $session_id${NC}"
71
- }
72
-
73
- # Function to load session
74
- load_session() {
75
- if [ -f "$SESSION_FILE" ]; then
76
- # Check if session is complete
77
- local status=$(jq -r '.status' "$SESSION_FILE")
78
- if [ "$status" = "complete" ]; then
79
- echo -e "${YELLOW}Previous interview session is complete.${NC}"
80
- read -p "Start a new interview? (y/n) " -n 1 -r
81
- echo
82
- if [[ $REPLY =~ ^[Yy]$ ]]; then
83
- init_session
84
- else
85
- echo "Exiting."
86
- exit 0
87
- fi
88
- else
89
- echo -e "${BLUE}Resuming existing interview session...${NC}"
90
- local session_id=$(jq -r '.session_id' "$SESSION_FILE")
91
- local total_questions=$(jq -r '.question_count.total' "$SESSION_FILE")
92
- echo -e "${BLUE}Session: $session_id | Questions asked: $total_questions${NC}"
93
- fi
94
- else
95
- init_session
96
- fi
97
- }
98
-
99
- # Function to update session
100
- update_session() {
101
- local persona="$1"
102
- local question="$2"
103
-
104
- # Validate persona
105
- if [ -z "$persona" ]; then
106
- echo -e "${RED}Error: Empty persona in update_session${NC}"
107
- return 1
108
- fi
109
-
110
- # Update counts
111
- local total=$(jq -r '.question_count.total' "$SESSION_FILE")
112
- local persona_count=$(jq -r ".question_count.by_persona.$persona" "$SESSION_FILE" 2>/dev/null || echo "0")
113
-
114
- total=$((total + 1))
115
- persona_count=$((persona_count + 1))
116
-
117
- # Update session file
118
- jq ".question_count.total = $total | \
119
- .question_count.by_persona.$persona = $persona_count | \
120
- .last_updated = \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\" | \
121
- .current_question = {\"persona\": \"$persona\", \"question\": \"$question\", \"asked_at\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" \
122
- "$SESSION_FILE" > "$SESSION_FILE.tmp" && mv "$SESSION_FILE.tmp" "$SESSION_FILE"
123
- }
124
-
125
- # Background function to prepare next question
126
- prepare_next_question_bg() {
127
- local brief_content=$(cat BRIEF.md)
128
- local all_qa=$(tail -n +4 "$QUESTIONS_FILE" 2>/dev/null || echo "No questions asked yet.")
129
- local recent_qa=$(tail -n 20 "$QUESTIONS_FILE" 2>/dev/null || echo "No questions asked yet.")
130
-
131
- # Get counts
132
- local total=$(jq -r '.question_count.total' "$SESSION_FILE")
133
- local dba_count=$(jq -r '.question_count.by_persona.DBA' "$SESSION_FILE")
134
- local ta_count=$(jq -r '.question_count.by_persona.TECHNICAL_ARCHITECT' "$SESSION_FILE")
135
- local ux_count=$(jq -r '.question_count.by_persona.UX_EXPERT' "$SESSION_FILE")
136
- local se_count=$(jq -r '.question_count.by_persona.SOFTWARE_ENGINEER' "$SESSION_FILE")
137
- local frontend_count=$(jq -r '.question_count.by_persona.FRONTEND_DEVELOPER' "$SESSION_FILE")
138
- local devops_count=$(jq -r '.question_count.by_persona.DEVOPS_ENGINEER' "$SESSION_FILE")
139
- local security_count=$(jq -r '.question_count.by_persona.SECURITY_EXPERT' "$SESSION_FILE")
140
-
141
- # Create Q&A summary by domain
142
- local qa_summary="Data: $dba_count questions | Architecture: $ta_count questions | UX: $ux_count questions | Backend: $se_count questions | Frontend: $frontend_count questions | DevOps: $devops_count questions | Security: $security_count questions"
143
-
144
- # Read coordinator prompt
145
- local coordinator_prompt=$(cat "$PROJECT_ROOT/prompts/interview_coordinator.txt")
146
-
147
- # Replace tokens
148
- coordinator_prompt="${coordinator_prompt//\{brief_content\}/$brief_content}"
149
- coordinator_prompt="${coordinator_prompt//\{total_questions\}/$total}"
150
- coordinator_prompt="${coordinator_prompt//\{dba_count\}/$dba_count}"
151
- coordinator_prompt="${coordinator_prompt//\{ta_count\}/$ta_count}"
152
- coordinator_prompt="${coordinator_prompt//\{ux_count\}/$ux_count}"
153
- coordinator_prompt="${coordinator_prompt//\{se_count\}/$se_count}"
154
- coordinator_prompt="${coordinator_prompt//\{frontend_count\}/$frontend_count}"
155
- coordinator_prompt="${coordinator_prompt//\{devops_count\}/$devops_count}"
156
- coordinator_prompt="${coordinator_prompt//\{security_count\}/$security_count}"
157
- coordinator_prompt="${coordinator_prompt//\{recent_qa_history\}/$recent_qa}"
158
- coordinator_prompt="${coordinator_prompt//\{qa_summary_by_domain\}/$qa_summary}"
159
-
160
- # Get coordinator decision
161
- local next_persona=$(claude --model sonnet -p "$coordinator_prompt" 2>/dev/null | tail -1)
162
-
163
- # Validate and clean decision - remove spaces, newlines, and markdown formatting
164
- next_persona=$(echo "$next_persona" | tr -d ' \n\r' | sed 's/[*_`]//g')
165
-
166
- # Also handle cases where it might be prefixed with ** or __
167
- next_persona="${next_persona#**}"
168
- next_persona="${next_persona%**}"
169
- next_persona="${next_persona#__}"
170
- next_persona="${next_persona%__}"
171
-
172
- case "$next_persona" in
173
- DBA|TECHNICAL_ARCHITECT|UX_EXPERT|SOFTWARE_ENGINEER|FRONTEND_DEVELOPER|DEVOPS_ENGINEER|SECURITY_EXPERT|COMPLETE)
174
- ;;
175
- *)
176
- echo "Warning: Invalid coordinator decision '$next_persona', using SOFTWARE_ENGINEER" >&2
177
- next_persona="SOFTWARE_ENGINEER"
178
- ;;
179
- esac
180
-
181
- echo "$next_persona" > "$PERSONA_CACHE"
182
-
183
- # If not complete, get the question
184
- if [ "$next_persona" != "COMPLETE" ]; then
185
- # Get persona-specific history
186
- local persona_qa=$(grep -A1 "\[$next_persona\]:" "$QUESTIONS_FILE" 2>/dev/null || echo "No previous questions from this persona.")
187
-
188
- # Select appropriate prompt file
189
- local prompt_file=""
190
- case $next_persona in
191
- DBA)
192
- prompt_file="$PROJECT_ROOT/prompts/interview_dba_adapted.txt"
193
- ;;
194
- TECHNICAL_ARCHITECT)
195
- prompt_file="$PROJECT_ROOT/prompts/interview_technical_architect.txt"
196
- ;;
197
- UX_EXPERT)
198
- prompt_file="$PROJECT_ROOT/prompts/interview_ux_expert.txt"
199
- ;;
200
- SOFTWARE_ENGINEER)
201
- prompt_file="$PROJECT_ROOT/prompts/interview_software_engineer.txt"
202
- ;;
203
- FRONTEND_DEVELOPER)
204
- prompt_file="$PROJECT_ROOT/prompts/interview_frontend_developer.txt"
205
- ;;
206
- DEVOPS_ENGINEER)
207
- prompt_file="$PROJECT_ROOT/prompts/interview_devops_engineer.txt"
208
- ;;
209
- SECURITY_EXPERT)
210
- prompt_file="$PROJECT_ROOT/prompts/interview_security_expert.txt"
211
- ;;
212
- esac
213
-
214
- if [ -f "$prompt_file" ]; then
215
- # Read prompt template
216
- local prompt_template=$(cat "$prompt_file")
217
-
218
- # Replace tokens
219
- prompt_template="${prompt_template//\{brief_content\}/$brief_content}"
220
- prompt_template="${prompt_template//\{all_qa_history\}/$all_qa}"
221
- prompt_template="${prompt_template//\{dba_qa_history\}/$persona_qa}"
222
- prompt_template="${prompt_template//\{ta_qa_history\}/$persona_qa}"
223
- prompt_template="${prompt_template//\{ux_qa_history\}/$persona_qa}"
224
- prompt_template="${prompt_template//\{se_qa_history\}/$persona_qa}"
225
- prompt_template="${prompt_template//\{frontend_qa_history\}/$persona_qa}"
226
- prompt_template="${prompt_template//\{devops_qa_history\}/$persona_qa}"
227
- prompt_template="${prompt_template//\{security_qa_history\}/$persona_qa}"
228
-
229
- # Get question from Claude
230
- local question=$(claude --model sonnet -p "$prompt_template" 2>/dev/null | tail -1)
231
- echo "$question" > "$QUESTION_CACHE"
232
- fi
233
- fi
234
- }
235
-
236
- # Function to save Q&A
237
- save_qa() {
238
- local persona="$1"
239
- local question="$2"
240
- local answer="$3"
241
- local q_num=$(jq -r '.question_count.total' "$SESSION_FILE")
242
-
243
- echo "" >> "$QUESTIONS_FILE"
244
- echo "### Q$q_num [$persona]: $question" >> "$QUESTIONS_FILE"
245
- echo "**Answer**: $answer" >> "$QUESTIONS_FILE"
246
- }
247
-
248
- # Function to display progress
249
- show_progress() {
250
- echo ""
251
- echo -e "${BLUE}=== Interview Progress ===${NC}"
252
-
253
- local total=$(jq -r '.question_count.total' "$SESSION_FILE")
254
- echo -e "Total questions: ${GREEN}$total${NC}"
255
-
256
- echo -e "\nQuestions by expert:"
257
- echo -e " Database Admin: $(jq -r '.question_count.by_persona.DBA' "$SESSION_FILE")"
258
- echo -e " Technical Architect: $(jq -r '.question_count.by_persona.TECHNICAL_ARCHITECT' "$SESSION_FILE")"
259
- echo -e " UX Expert: $(jq -r '.question_count.by_persona.UX_EXPERT' "$SESSION_FILE")"
260
- echo -e " Software Engineer: $(jq -r '.question_count.by_persona.SOFTWARE_ENGINEER' "$SESSION_FILE")"
261
- echo -e " Frontend Developer: $(jq -r '.question_count.by_persona.FRONTEND_DEVELOPER' "$SESSION_FILE")"
262
- echo -e " DevOps Engineer: $(jq -r '.question_count.by_persona.DEVOPS_ENGINEER' "$SESSION_FILE")"
263
- echo -e " Security Expert: $(jq -r '.question_count.by_persona.SECURITY_EXPERT' "$SESSION_FILE")"
264
-
265
- echo ""
266
- if [ $total -lt 10 ]; then
267
- echo -e "${YELLOW}Minimum recommended: 10-15 questions${NC}"
268
- elif [ $total -gt 25 ]; then
269
- echo -e "${YELLOW}Consider wrapping up - you have plenty of information!${NC}"
270
- else
271
- echo -e "${GREEN}Good progress - keep going or type 'done' when ready${NC}"
272
- fi
273
- echo ""
274
- }
275
-
276
- # Function to consolidate requirements
277
- consolidate_requirements() {
278
- echo -e "\n${GREEN}Consolidating requirements...${NC}"
279
-
280
- local consolidation_prompt="
281
- You are a technical writer consolidating interview responses into a comprehensive requirements document.
282
-
283
- === PROJECT BRIEF ===
284
- $(cat BRIEF.md)
285
-
286
- === INTERVIEW Q&A ===
287
- $(cat "$QUESTIONS_FILE")
288
-
289
- === INSTRUCTIONS ===
290
- Create a comprehensive requirements document that:
291
- 1. Organizes all requirements by category (functional, technical, operational, etc.)
292
- 2. Removes redundancy while preserving all important details
293
- 3. Clarifies any ambiguities found in the Q&A
294
- 4. Highlights key decisions and constraints
295
- 5. Identifies any gaps that may need addressing
296
-
297
- Format the output as a clean, well-structured markdown document suitable for feeding into project planning.
298
- "
299
-
300
- claude --model opus -p "$consolidation_prompt" > "$REQUIREMENTS_FILE"
301
-
302
- echo -e "${GREEN}Requirements consolidated in $REQUIREMENTS_FILE${NC}"
303
-
304
- # Mark session as complete
305
- jq '.status = "complete"' "$SESSION_FILE" > "$SESSION_FILE.tmp" && mv "$SESSION_FILE.tmp" "$SESSION_FILE"
306
- }
307
-
308
- # Main interview loop
309
- main() {
310
- echo -e "${GREEN}🎙️ Claude FSD Interactive Interview System (Fast Mode)${NC}"
311
- echo -e "${GREEN}======================================================${NC}"
312
- echo ""
313
-
314
- # Load or init session
315
- load_session
316
-
317
- echo -e "\n${YELLOW}Instructions:${NC}"
318
- echo "- Answer each question concisely (1-2 sentences recommended)"
319
- echo "- The next question is prepared while you answer (faster!)"
320
- echo "- Your progress is automatically saved"
321
- echo ""
322
- echo -e "${YELLOW}To finish the interview:${NC}"
323
- echo " • Type 'done' or 'exit' and press Enter"
324
- echo " • Press Ctrl+D (EOF)"
325
- echo " • Press Ctrl+C to cancel without saving"
326
- echo ""
327
-
328
- # Show current progress
329
- show_progress
330
-
331
- # Background process PID
332
- bg_pid=""
333
-
334
- # Main loop
335
- while true; do
336
- # Start preparing next question in background
337
- prepare_next_question_bg &
338
- bg_pid=$!
339
-
340
- # If this is the first question, wait for it
341
- if [ ! -f "$PERSONA_CACHE" ] || [ ! -f "$QUESTION_CACHE" ]; then
342
- echo -e "${BLUE}Preparing first question...${NC}"
343
- wait $bg_pid
344
- fi
345
-
346
- # Read cached persona and question
347
- local next_persona=$(cat "$PERSONA_CACHE" 2>/dev/null || echo "SOFTWARE_ENGINEER")
348
-
349
- # Check if complete
350
- if [ "$next_persona" = "COMPLETE" ]; then
351
- echo -e "\n${GREEN}The coordinator believes we have sufficient information!${NC}"
352
- read -p "Would you like to conclude the interview? (y/n) " -n 1 -r
353
- echo
354
- if [[ $REPLY =~ ^[Yy]$ ]]; then
355
- consolidate_requirements
356
- break
357
- else
358
- echo "Continuing with more questions..."
359
- next_persona="SOFTWARE_ENGINEER"
360
- echo "$next_persona" > "$PERSONA_CACHE"
361
- fi
362
- fi
363
-
364
- # Wait for question to be ready if needed
365
- if [ -n "$bg_pid" ]; then
366
- wait $bg_pid 2>/dev/null || true
367
- fi
368
-
369
- local question=$(cat "$QUESTION_CACHE" 2>/dev/null || echo "What are the main goals of this project?")
370
-
371
- # Update session with current question
372
- update_session "$next_persona" "$question"
373
-
374
- # Display question
375
- echo -e "\n${GREEN}[$next_persona]${NC} $question"
376
-
377
- # Start preparing next question immediately
378
- rm -f "$PERSONA_CACHE" "$QUESTION_CACHE"
379
- prepare_next_question_bg &
380
- bg_pid=$!
381
-
382
- # Get answer
383
- echo -e "${YELLOW}Your answer (or 'done' to finish):${NC}"
384
- echo -n "> "
385
- if ! read -r answer; then
386
- # EOF detected (Ctrl+D)
387
- # Kill background process
388
- [ -n "$bg_pid" ] && kill $bg_pid 2>/dev/null || true
389
- return 1
390
- fi
391
-
392
- # Check for exit commands
393
- if [[ "$answer" =~ ^(done|exit|quit)$ ]]; then
394
- echo -e "\n${YELLOW}Interview concluded by user.${NC}"
395
- # Kill background process
396
- [ -n "$bg_pid" ] && kill $bg_pid 2>/dev/null || true
397
- consolidate_requirements
398
- break
399
- fi
400
-
401
- # Save Q&A
402
- save_qa "$next_persona" "$question" "$answer"
403
-
404
- # Show progress periodically
405
- local total=$(jq -r '.question_count.total' "$SESSION_FILE")
406
- if [ $((total % 5)) -eq 0 ]; then
407
- show_progress
408
- fi
409
- done
410
-
411
- # Clean up background process
412
- [ -n "$bg_pid" ] && kill $bg_pid 2>/dev/null || true
413
-
414
- echo -e "\n${GREEN}Interview complete!${NC}"
415
- echo "- Questions saved in: $QUESTIONS_FILE"
416
- echo "- Requirements saved in: $REQUIREMENTS_FILE"
417
- echo "- Next step: Run 'claudefsd' to create project plan"
418
- }
419
-
420
- # Handle Ctrl+C as hard stop
421
- trap 'echo -e "\n${RED}Interview cancelled.${NC}"; [ -n "$bg_pid" ] && kill $bg_pid 2>/dev/null || true; exit 1' INT
422
-
423
- # Clean up cache files on exit
424
- trap 'rm -f "$PERSONA_CACHE" "$QUESTION_CACHE"' EXIT
425
-
426
- # Run main function and handle EOF
427
- if main; then
428
- exit 0
429
- else
430
- # If main returns false (EOF detected), consolidate and exit
431
- echo -e "\n${YELLOW}Interview ended.${NC}"
432
- consolidate_requirements
433
- exit 0
434
- fi