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 +31 -29
- package/bin/claudefsd-analyze-brief-personas +31 -9
- package/bin/claudefsd-create-plan +67 -10
- package/bin/claudefsd-dev +1 -1
- package/bin/claudefsd-interview +199 -88
- package/package.json +2 -4
- package/bin/claudefsd-create-plan-from-requirements +0 -87
- package/bin/claudefsd-interview-fast +0 -434
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 "
|
|
33
|
+
echo "3" # Create plan from requirements
|
|
34
34
|
elif [ -f docs/QUESTIONS.md ] && [ ! -f docs/PLAN.md ]; then
|
|
35
|
-
echo "3" # Create plan
|
|
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 [
|
|
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 "
|
|
73
|
+
echo " 3) Create plan - Generate development plan from requirements"
|
|
72
74
|
elif [ -f docs/QUESTIONS.md ]; then
|
|
73
|
-
echo "
|
|
75
|
+
echo " 3) Create plan - Generate plan from answered questions"
|
|
74
76
|
else
|
|
75
|
-
echo "
|
|
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
|
-
#
|
|
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
|
|
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
|
|
9
|
-
|
|
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="$
|
|
104
|
+
prompt_file="$PROMPTS_DIR/interview_dba_adapted.txt"
|
|
83
105
|
display_name="Database Administrator"
|
|
84
106
|
;;
|
|
85
107
|
TECHNICAL_ARCHITECT)
|
|
86
|
-
prompt_file="$
|
|
108
|
+
prompt_file="$PROMPTS_DIR/interview_technical_architect.txt"
|
|
87
109
|
display_name="Technical Architect"
|
|
88
110
|
;;
|
|
89
111
|
UX_EXPERT)
|
|
90
|
-
prompt_file="$
|
|
112
|
+
prompt_file="$PROMPTS_DIR/interview_ux_expert.txt"
|
|
91
113
|
display_name="UX Expert"
|
|
92
114
|
;;
|
|
93
115
|
SOFTWARE_ENGINEER)
|
|
94
|
-
prompt_file="$
|
|
116
|
+
prompt_file="$PROMPTS_DIR/interview_software_engineer.txt"
|
|
95
117
|
display_name="Software Engineer"
|
|
96
118
|
;;
|
|
97
119
|
FRONTEND_DEVELOPER)
|
|
98
|
-
prompt_file="$
|
|
120
|
+
prompt_file="$PROMPTS_DIR/interview_frontend_developer.txt"
|
|
99
121
|
display_name="Frontend Developer"
|
|
100
122
|
;;
|
|
101
123
|
DEVOPS_ENGINEER)
|
|
102
|
-
prompt_file="$
|
|
124
|
+
prompt_file="$PROMPTS_DIR/interview_devops_engineer.txt"
|
|
103
125
|
display_name="DevOps Engineer"
|
|
104
126
|
;;
|
|
105
127
|
SECURITY_EXPERT)
|
|
106
|
-
prompt_file="$
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 "
|
|
77
|
-
|
|
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 "
|
|
80
|
-
echo "
|
|
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 .
|
package/bin/claudefsd-interview
CHANGED
|
@@ -1,12 +1,35 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
exec "$(dirname "$0")/claudefsd-interview-fast" "$@"
|
|
3
|
+
set -e
|
|
5
4
|
|
|
6
|
-
#
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
120
|
-
|
|
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
|
|
135
|
-
local qa_summary="Data: $dba_count questions | Architecture: $ta_count questions | UX: $ux_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 "$
|
|
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
|
|
154
|
-
|
|
155
|
-
# Validate decision
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
#
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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
|
-
|
|
172
|
-
echo "SOFTWARE_ENGINEER" # Default fallback
|
|
200
|
+
TECHNICAL_ARCHITECT|TECHNICALARCHITECT|TA)
|
|
201
|
+
next_persona="TECHNICAL_ARCHITECT"
|
|
173
202
|
;;
|
|
174
|
-
|
|
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
|
-
|
|
193
|
-
|
|
206
|
+
SOFTWARE_ENGINEER|SOFTWAREENGINEER|SE)
|
|
207
|
+
next_persona="SOFTWARE_ENGINEER"
|
|
194
208
|
;;
|
|
195
|
-
|
|
196
|
-
|
|
209
|
+
FRONTEND_DEVELOPER|FRONTENDDEVELOPER|FE)
|
|
210
|
+
next_persona="FRONTEND_DEVELOPER"
|
|
197
211
|
;;
|
|
198
|
-
|
|
199
|
-
|
|
212
|
+
DEVOPS_ENGINEER|DEVOPSENGINEER|DEVOPS)
|
|
213
|
+
next_persona="DEVOPS_ENGINEER"
|
|
200
214
|
;;
|
|
201
|
-
|
|
202
|
-
|
|
215
|
+
SECURITY_EXPERT|SECURITYEXPERT|SECURITY)
|
|
216
|
+
next_persona="SECURITY_EXPERT"
|
|
203
217
|
;;
|
|
204
|
-
|
|
205
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
228
|
-
|
|
229
|
-
|
|
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}
|
|
306
|
-
echo -e "${GREEN}
|
|
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 "-
|
|
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
|
-
#
|
|
328
|
-
|
|
329
|
-
|
|
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"
|
|
434
|
+
next_persona="SOFTWARE_ENGINEER"
|
|
435
|
+
echo "$next_persona" > "$PERSONA_CACHE"
|
|
342
436
|
fi
|
|
343
437
|
fi
|
|
344
438
|
|
|
345
|
-
#
|
|
346
|
-
|
|
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.
|
|
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
|