claude-fsd 1.3.15 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/claudefsd +78 -20
- package/bin/claudefsd-create-plan-from-requirements +87 -0
- package/bin/claudefsd-dev +19 -6
- package/bin/claudefsd-interview +354 -0
- package/package.json +1 -1
package/bin/claudefsd
CHANGED
|
@@ -27,12 +27,14 @@ save_editor_preference() {
|
|
|
27
27
|
get_default_choice() {
|
|
28
28
|
if [ ! -f BRIEF.md ]; then
|
|
29
29
|
echo "0"
|
|
30
|
-
elif [ ! -f docs/QUESTIONS.md ]; then
|
|
31
|
-
echo "1"
|
|
32
|
-
elif [ ! -f docs/PLAN.md ]; then
|
|
33
|
-
echo "2"
|
|
30
|
+
elif [ ! -f docs/REQUIREMENTS.md ] && [ ! -f docs/QUESTIONS.md ]; then
|
|
31
|
+
echo "1" # Interactive interview
|
|
32
|
+
elif [ -f docs/REQUIREMENTS.md ] && [ ! -f docs/PLAN.md ]; then
|
|
33
|
+
echo "2" # Create plan from requirements
|
|
34
|
+
elif [ -f docs/QUESTIONS.md ] && [ ! -f docs/PLAN.md ]; then
|
|
35
|
+
echo "3" # Create plan (old flow)
|
|
34
36
|
else
|
|
35
|
-
echo "
|
|
37
|
+
echo "4" # Development mode
|
|
36
38
|
fi
|
|
37
39
|
}
|
|
38
40
|
|
|
@@ -51,17 +53,46 @@ show_menu() {
|
|
|
51
53
|
if [ ! -f BRIEF.md ]; then
|
|
52
54
|
echo " 0) Create project brief - Start your project with a BRIEF.md file"
|
|
53
55
|
fi
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
|
|
57
|
+
# Check if we should show new or old interview flow
|
|
58
|
+
if [ -f docs/INTERVIEW-SESSION.json ]; then
|
|
59
|
+
local session_status=$(jq -r '.status' docs/INTERVIEW-SESSION.json 2>/dev/null || echo "unknown")
|
|
60
|
+
if [ "$session_status" = "in_progress" ]; then
|
|
61
|
+
echo " 1) Interactive interview - Resume existing interview session"
|
|
62
|
+
else
|
|
63
|
+
echo " 1) Interactive interview - Gather requirements through expert Q&A"
|
|
64
|
+
fi
|
|
65
|
+
else
|
|
66
|
+
echo " 1) Interactive interview - Gather requirements through expert Q&A [NEW!]"
|
|
67
|
+
fi
|
|
68
|
+
|
|
69
|
+
# Show create plan option based on what exists
|
|
70
|
+
if [ -f docs/REQUIREMENTS.md ]; then
|
|
71
|
+
echo " 2) Create plan - Generate development plan from requirements"
|
|
72
|
+
elif [ -f docs/QUESTIONS.md ]; then
|
|
73
|
+
echo " 2) Create plan - Generate plan from answered questions (legacy)"
|
|
74
|
+
else
|
|
75
|
+
echo " 2) [Requires interview or questions first]"
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
echo " 3) Batch questions - Generate all questions at once (legacy)"
|
|
79
|
+
echo " 4) Development mode - AI agents work on coding tasks"
|
|
80
|
+
echo " 5) Exit"
|
|
58
81
|
echo
|
|
59
82
|
|
|
60
83
|
# Show status of required files
|
|
61
84
|
echo "Current status:"
|
|
62
85
|
[ -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"
|
|
63
87
|
[ -f docs/QUESTIONS.md ] && echo " ✓ docs/QUESTIONS.md exists" || echo " ✗ docs/QUESTIONS.md missing"
|
|
64
88
|
[ -f docs/PLAN.md ] && echo " ✓ docs/PLAN.md exists" || echo " ✗ docs/PLAN.md missing"
|
|
89
|
+
|
|
90
|
+
# Show interview session status if exists
|
|
91
|
+
if [ -f docs/INTERVIEW-SESSION.json ]; then
|
|
92
|
+
local session_status=$(jq -r '.status' docs/INTERVIEW-SESSION.json 2>/dev/null || echo "unknown")
|
|
93
|
+
local total_questions=$(jq -r '.question_count.total' docs/INTERVIEW-SESSION.json 2>/dev/null || echo "0")
|
|
94
|
+
echo " 📝 Interview session: $session_status ($total_questions questions)"
|
|
95
|
+
fi
|
|
65
96
|
echo
|
|
66
97
|
}
|
|
67
98
|
|
|
@@ -179,14 +210,41 @@ if [ $# -eq 0 ]; then
|
|
|
179
210
|
|
|
180
211
|
open_with_editor "BRIEF.md"
|
|
181
212
|
echo
|
|
182
|
-
echo -e "${GREEN}Brief created! Run claudefsd again to
|
|
213
|
+
echo -e "${GREEN}Brief created! Run claudefsd again to start the interview.${NC}"
|
|
183
214
|
else
|
|
184
215
|
echo -e "${RED}BRIEF.md already exists!${NC}"
|
|
185
216
|
exit 1
|
|
186
217
|
fi
|
|
187
218
|
;;
|
|
188
219
|
1)
|
|
189
|
-
|
|
220
|
+
# Interactive interview
|
|
221
|
+
if [ ! -f BRIEF.md ]; then
|
|
222
|
+
echo -e "${RED}No BRIEF.md found. Please create a project brief first.${NC}"
|
|
223
|
+
exit 1
|
|
224
|
+
fi
|
|
225
|
+
echo -e "${GREEN}Starting interactive interview...${NC}"
|
|
226
|
+
echo
|
|
227
|
+
exec "$(dirname "$0")/claudefsd-interview"
|
|
228
|
+
;;
|
|
229
|
+
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
|
|
247
|
+
echo -e "${GREEN}Analyzing brief and generating questions (batch mode)...${NC}"
|
|
190
248
|
echo
|
|
191
249
|
"$(dirname "$0")/claudefsd-analyze-brief"
|
|
192
250
|
|
|
@@ -204,17 +262,12 @@ if [ $# -eq 0 ]; then
|
|
|
204
262
|
exec "$(dirname "$0")/claudefsd-create-plan"
|
|
205
263
|
fi
|
|
206
264
|
;;
|
|
207
|
-
|
|
208
|
-
echo -e "${GREEN}Creating plan from answered questions...${NC}"
|
|
209
|
-
echo
|
|
210
|
-
exec "$(dirname "$0")/claudefsd-create-plan"
|
|
211
|
-
;;
|
|
212
|
-
3)
|
|
265
|
+
4)
|
|
213
266
|
echo -e "${GREEN}Starting development mode...${NC}"
|
|
214
267
|
echo
|
|
215
268
|
exec "$(dirname "$0")/claudefsd-dev"
|
|
216
269
|
;;
|
|
217
|
-
|
|
270
|
+
5)
|
|
218
271
|
echo "Goodbye!"
|
|
219
272
|
exit 0
|
|
220
273
|
;;
|
|
@@ -226,6 +279,10 @@ if [ $# -eq 0 ]; then
|
|
|
226
279
|
else
|
|
227
280
|
# If arguments provided, pass them through to the appropriate command
|
|
228
281
|
case "$1" in
|
|
282
|
+
interview)
|
|
283
|
+
shift
|
|
284
|
+
exec "$(dirname "$0")/claudefsd-interview" "$@"
|
|
285
|
+
;;
|
|
229
286
|
dev)
|
|
230
287
|
shift
|
|
231
288
|
exec "$(dirname "$0")/claudefsd-dev" "$@"
|
|
@@ -244,8 +301,9 @@ else
|
|
|
244
301
|
echo "Usage: claudefsd [command]"
|
|
245
302
|
echo
|
|
246
303
|
echo "Commands:"
|
|
247
|
-
echo "
|
|
248
|
-
echo "
|
|
304
|
+
echo " interview - Interactive requirements gathering"
|
|
305
|
+
echo " analyze-brief - Analyze brief and generate questions (legacy)"
|
|
306
|
+
echo " create-plan - Create plan from requirements or questions"
|
|
249
307
|
echo " dev - Run development mode"
|
|
250
308
|
echo
|
|
251
309
|
echo "Run without arguments for interactive mode."
|
|
@@ -0,0 +1,87 @@
|
|
|
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."
|
package/bin/claudefsd-dev
CHANGED
|
@@ -112,6 +112,8 @@ Please proceed with your analysis and task identification based on the project d
|
|
|
112
112
|
# Define the developer prompt
|
|
113
113
|
DEVELOPER_PROMPT="
|
|
114
114
|
$MEGATHINKING_MODE
|
|
115
|
+
**ULTRA-THINKING DIRECTIVE**: Before beginning, engage in extended deep thinking about the task implications, architectural considerations, and optimal approach. This is a potentially \$1M+ scale project that demands exceptional thoroughness.
|
|
116
|
+
|
|
115
117
|
You are an AI developer working within an automated development environment. Your role is to complete tasks, plan implementations, and maintain high-quality code. Here is the specific task you need to complete:
|
|
116
118
|
|
|
117
119
|
<next_task>
|
|
@@ -125,8 +127,9 @@ IMPORTANT: Before starting the task, you MUST read and understand:
|
|
|
125
127
|
|
|
126
128
|
Please follow these steps to complete the task:
|
|
127
129
|
|
|
128
|
-
1. Analyze the task and plan your approach. In your thinking block, create an implementation plan wrapped in <implementation_plan> tags. Include:
|
|
130
|
+
1. **DEEP TASK ANALYSIS**: Analyze the task and plan your approach. In your thinking block, create an implementation plan wrapped in <implementation_plan> tags. Include:
|
|
129
131
|
- A detailed breakdown of the task into clear, actionable steps
|
|
132
|
+
- Whether this task would benefit from parallel agent decomposition
|
|
130
133
|
- For each step, identify:
|
|
131
134
|
* Potential challenges and proposed solutions
|
|
132
135
|
* Architectural implications
|
|
@@ -136,11 +139,21 @@ Please follow these steps to complete the task:
|
|
|
136
139
|
* Potential edge cases and how to handle them
|
|
137
140
|
* A minimal, focused testing strategy (avoid extensive test infrastructure)
|
|
138
141
|
|
|
139
|
-
2.
|
|
142
|
+
2. **EXECUTION STRATEGY**: Choose between:
|
|
143
|
+
- **Single Agent Deep Work**: For focused sequential tasks requiring deep thinking
|
|
144
|
+
- **Parallel Agent Coordination**: For multi-faceted tasks that can be decomposed
|
|
145
|
+
|
|
146
|
+
If choosing parallel agents, use the Task tool to spawn focused sub-agents:
|
|
147
|
+
- Core implementation agent
|
|
148
|
+
- Test coverage agent
|
|
149
|
+
- Error handling agent
|
|
150
|
+
- Documentation agent
|
|
151
|
+
|
|
152
|
+
3. Execute the necessary changes or Bash commands to complete the task. Use parallel agents for dev work when appropriate to increase efficiency.
|
|
140
153
|
|
|
141
|
-
|
|
154
|
+
4. If a linter is defined for this project, run it and include the output in <linter_output> tags.
|
|
142
155
|
|
|
143
|
-
|
|
156
|
+
5. Describe the changes you've made in <changes> tags. Include:
|
|
144
157
|
- A summary of implemented changes
|
|
145
158
|
- Explanation of architectural decisions
|
|
146
159
|
- Potential areas of concern or future considerations
|
|
@@ -149,9 +162,9 @@ Please follow these steps to complete the task:
|
|
|
149
162
|
- How edge cases were addressed
|
|
150
163
|
- Outline of the testing strategy
|
|
151
164
|
|
|
152
|
-
|
|
165
|
+
6. Add any questions for future reference to the QUESTIONS.md file. Summarize these additions in <questions_update> tags.
|
|
153
166
|
|
|
154
|
-
|
|
167
|
+
7. Add any ideas for future improvements or features to the IDEAS.md file. Summarize these additions in <ideas_update> tags.
|
|
155
168
|
|
|
156
169
|
Important guidelines:
|
|
157
170
|
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
set -e
|
|
4
|
+
|
|
5
|
+
# Check dependencies
|
|
6
|
+
$(dirname "$0")/claudefsd-check-dependencies
|
|
7
|
+
|
|
8
|
+
# Colors for output
|
|
9
|
+
GREEN='\033[0;32m'
|
|
10
|
+
YELLOW='\033[0;33m'
|
|
11
|
+
BLUE='\033[0;34m'
|
|
12
|
+
RED='\033[0;31m'
|
|
13
|
+
NC='\033[0m' # No Color
|
|
14
|
+
|
|
15
|
+
# Create necessary directories
|
|
16
|
+
mkdir -p docs
|
|
17
|
+
mkdir -p logs
|
|
18
|
+
mkdir -p prompts
|
|
19
|
+
|
|
20
|
+
# Session file paths
|
|
21
|
+
SESSION_FILE="docs/INTERVIEW-SESSION.json"
|
|
22
|
+
QUESTIONS_FILE="docs/QUESTIONS.md"
|
|
23
|
+
REQUIREMENTS_FILE="docs/REQUIREMENTS.md"
|
|
24
|
+
|
|
25
|
+
# Check for BRIEF.md
|
|
26
|
+
if [ ! -f BRIEF.md ]; then
|
|
27
|
+
echo -e "${RED}No BRIEF.md file found. Please create one first.${NC}"
|
|
28
|
+
exit 1
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Function to initialize session
|
|
32
|
+
init_session() {
|
|
33
|
+
local session_id="interview_$(date +%Y%m%d_%H%M%S)"
|
|
34
|
+
cat > "$SESSION_FILE" <<EOF
|
|
35
|
+
{
|
|
36
|
+
"session_id": "$session_id",
|
|
37
|
+
"started_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
|
38
|
+
"last_updated": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
|
|
39
|
+
"status": "in_progress",
|
|
40
|
+
"question_count": {
|
|
41
|
+
"total": 0,
|
|
42
|
+
"by_persona": {
|
|
43
|
+
"DBA": 0,
|
|
44
|
+
"TECHNICAL_ARCHITECT": 0,
|
|
45
|
+
"UX_EXPERT": 0,
|
|
46
|
+
"SOFTWARE_ENGINEER": 0,
|
|
47
|
+
"DEVOPS_ENGINEER": 0,
|
|
48
|
+
"SECURITY_EXPERT": 0
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
"current_question": null
|
|
52
|
+
}
|
|
53
|
+
EOF
|
|
54
|
+
|
|
55
|
+
# Initialize QUESTIONS.md
|
|
56
|
+
echo "# Project Interview Questions and Answers" > "$QUESTIONS_FILE"
|
|
57
|
+
echo "" >> "$QUESTIONS_FILE"
|
|
58
|
+
echo "## Interview Session: $session_id" >> "$QUESTIONS_FILE"
|
|
59
|
+
echo "" >> "$QUESTIONS_FILE"
|
|
60
|
+
|
|
61
|
+
echo -e "${GREEN}New interview session started: $session_id${NC}"
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# Function to load session
|
|
65
|
+
load_session() {
|
|
66
|
+
if [ -f "$SESSION_FILE" ]; then
|
|
67
|
+
# Check if session is complete
|
|
68
|
+
local status=$(jq -r '.status' "$SESSION_FILE")
|
|
69
|
+
if [ "$status" = "complete" ]; then
|
|
70
|
+
echo -e "${YELLOW}Previous interview session is complete.${NC}"
|
|
71
|
+
read -p "Start a new interview? (y/n) " -n 1 -r
|
|
72
|
+
echo
|
|
73
|
+
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
74
|
+
init_session
|
|
75
|
+
else
|
|
76
|
+
echo "Exiting."
|
|
77
|
+
exit 0
|
|
78
|
+
fi
|
|
79
|
+
else
|
|
80
|
+
echo -e "${BLUE}Resuming existing interview session...${NC}"
|
|
81
|
+
local session_id=$(jq -r '.session_id' "$SESSION_FILE")
|
|
82
|
+
local total_questions=$(jq -r '.question_count.total' "$SESSION_FILE")
|
|
83
|
+
echo -e "${BLUE}Session: $session_id | Questions asked: $total_questions${NC}"
|
|
84
|
+
fi
|
|
85
|
+
else
|
|
86
|
+
init_session
|
|
87
|
+
fi
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# Function to update session
|
|
91
|
+
update_session() {
|
|
92
|
+
local persona="$1"
|
|
93
|
+
local question="$2"
|
|
94
|
+
|
|
95
|
+
# Update counts
|
|
96
|
+
local total=$(jq -r '.question_count.total' "$SESSION_FILE")
|
|
97
|
+
local persona_count=$(jq -r ".question_count.by_persona.$persona" "$SESSION_FILE")
|
|
98
|
+
|
|
99
|
+
total=$((total + 1))
|
|
100
|
+
persona_count=$((persona_count + 1))
|
|
101
|
+
|
|
102
|
+
# Update session file
|
|
103
|
+
jq ".question_count.total = $total | \
|
|
104
|
+
.question_count.by_persona.$persona = $persona_count | \
|
|
105
|
+
.last_updated = \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\" | \
|
|
106
|
+
.current_question = {\"persona\": \"$persona\", \"question\": \"$question\", \"asked_at\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" \
|
|
107
|
+
"$SESSION_FILE" > "$SESSION_FILE.tmp" && mv "$SESSION_FILE.tmp" "$SESSION_FILE"
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
# Function to get coordinator decision
|
|
111
|
+
get_coordinator_decision() {
|
|
112
|
+
local brief_content=$(cat BRIEF.md)
|
|
113
|
+
local all_qa=$(tail -n +4 "$QUESTIONS_FILE" | head -n -2 || echo "No questions asked yet.")
|
|
114
|
+
local recent_qa=$(tail -n 20 "$QUESTIONS_FILE" | head -n -2 || echo "No questions asked yet.")
|
|
115
|
+
|
|
116
|
+
# Get counts
|
|
117
|
+
local total=$(jq -r '.question_count.total' "$SESSION_FILE")
|
|
118
|
+
local dba_count=$(jq -r '.question_count.by_persona.DBA' "$SESSION_FILE")
|
|
119
|
+
local ta_count=$(jq -r '.question_count.by_persona.TECHNICAL_ARCHITECT' "$SESSION_FILE")
|
|
120
|
+
local ux_count=$(jq -r '.question_count.by_persona.UX_EXPERT' "$SESSION_FILE")
|
|
121
|
+
local se_count=$(jq -r '.question_count.by_persona.SOFTWARE_ENGINEER' "$SESSION_FILE")
|
|
122
|
+
local devops_count=$(jq -r '.question_count.by_persona.DEVOPS_ENGINEER' "$SESSION_FILE")
|
|
123
|
+
local security_count=$(jq -r '.question_count.by_persona.SECURITY_EXPERT' "$SESSION_FILE")
|
|
124
|
+
|
|
125
|
+
# Create Q&A summary by domain (simplified for now)
|
|
126
|
+
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"
|
|
127
|
+
|
|
128
|
+
# Read coordinator prompt
|
|
129
|
+
local coordinator_prompt=$(cat prompts/interview_coordinator.txt)
|
|
130
|
+
|
|
131
|
+
# Replace tokens
|
|
132
|
+
coordinator_prompt="${coordinator_prompt//\{brief_content\}/$brief_content}"
|
|
133
|
+
coordinator_prompt="${coordinator_prompt//\{total_questions\}/$total}"
|
|
134
|
+
coordinator_prompt="${coordinator_prompt//\{dba_count\}/$dba_count}"
|
|
135
|
+
coordinator_prompt="${coordinator_prompt//\{ta_count\}/$ta_count}"
|
|
136
|
+
coordinator_prompt="${coordinator_prompt//\{ux_count\}/$ux_count}"
|
|
137
|
+
coordinator_prompt="${coordinator_prompt//\{se_count\}/$se_count}"
|
|
138
|
+
coordinator_prompt="${coordinator_prompt//\{devops_count\}/$devops_count}"
|
|
139
|
+
coordinator_prompt="${coordinator_prompt//\{security_count\}/$security_count}"
|
|
140
|
+
coordinator_prompt="${coordinator_prompt//\{recent_qa_history\}/$recent_qa}"
|
|
141
|
+
coordinator_prompt="${coordinator_prompt//\{qa_summary_by_domain\}/$qa_summary}"
|
|
142
|
+
|
|
143
|
+
# Get coordinator decision
|
|
144
|
+
local decision=$(claude --model sonnet -p "$coordinator_prompt" 2>/dev/null | tail -1)
|
|
145
|
+
echo "$decision"
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
# Function to get question from persona
|
|
149
|
+
get_persona_question() {
|
|
150
|
+
local persona="$1"
|
|
151
|
+
local brief_content=$(cat BRIEF.md)
|
|
152
|
+
local all_qa=$(tail -n +4 "$QUESTIONS_FILE" || echo "No questions asked yet.")
|
|
153
|
+
|
|
154
|
+
# Get persona-specific history
|
|
155
|
+
local persona_qa=$(grep -A1 "\[$persona\]:" "$QUESTIONS_FILE" || echo "No previous questions from this persona.")
|
|
156
|
+
|
|
157
|
+
# Select appropriate prompt file
|
|
158
|
+
local prompt_file=""
|
|
159
|
+
case $persona in
|
|
160
|
+
DBA)
|
|
161
|
+
prompt_file="prompts/interview_dba_adapted.txt"
|
|
162
|
+
;;
|
|
163
|
+
TECHNICAL_ARCHITECT)
|
|
164
|
+
prompt_file="prompts/interview_technical_architect.txt"
|
|
165
|
+
;;
|
|
166
|
+
UX_EXPERT)
|
|
167
|
+
prompt_file="prompts/interview_ux_expert.txt"
|
|
168
|
+
;;
|
|
169
|
+
SOFTWARE_ENGINEER)
|
|
170
|
+
prompt_file="prompts/interview_software_engineer.txt"
|
|
171
|
+
;;
|
|
172
|
+
DEVOPS_ENGINEER)
|
|
173
|
+
prompt_file="prompts/interview_devops_engineer.txt"
|
|
174
|
+
;;
|
|
175
|
+
SECURITY_EXPERT)
|
|
176
|
+
prompt_file="prompts/interview_security_expert.txt"
|
|
177
|
+
;;
|
|
178
|
+
esac
|
|
179
|
+
|
|
180
|
+
if [ ! -f "$prompt_file" ]; then
|
|
181
|
+
echo "Error: Prompt file not found for $persona"
|
|
182
|
+
return 1
|
|
183
|
+
fi
|
|
184
|
+
|
|
185
|
+
# Read prompt template
|
|
186
|
+
local prompt_template=$(cat "$prompt_file")
|
|
187
|
+
|
|
188
|
+
# Replace tokens
|
|
189
|
+
prompt_template="${prompt_template//\{brief_content\}/$brief_content}"
|
|
190
|
+
prompt_template="${prompt_template//\{all_qa_history\}/$all_qa}"
|
|
191
|
+
prompt_template="${prompt_template//\{dba_qa_history\}/$persona_qa}"
|
|
192
|
+
prompt_template="${prompt_template//\{ta_qa_history\}/$persona_qa}"
|
|
193
|
+
prompt_template="${prompt_template//\{ux_qa_history\}/$persona_qa}"
|
|
194
|
+
prompt_template="${prompt_template//\{se_qa_history\}/$persona_qa}"
|
|
195
|
+
prompt_template="${prompt_template//\{devops_qa_history\}/$persona_qa}"
|
|
196
|
+
prompt_template="${prompt_template//\{security_qa_history\}/$persona_qa}"
|
|
197
|
+
|
|
198
|
+
# Get question from Claude
|
|
199
|
+
local question=$(claude --model sonnet -p "$prompt_template" 2>/dev/null | tail -1)
|
|
200
|
+
echo "$question"
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
# Function to save Q&A
|
|
204
|
+
save_qa() {
|
|
205
|
+
local persona="$1"
|
|
206
|
+
local question="$2"
|
|
207
|
+
local answer="$3"
|
|
208
|
+
local q_num=$(jq -r '.question_count.total' "$SESSION_FILE")
|
|
209
|
+
|
|
210
|
+
echo "" >> "$QUESTIONS_FILE"
|
|
211
|
+
echo "### Q$q_num [$persona]: $question" >> "$QUESTIONS_FILE"
|
|
212
|
+
echo "**Answer**: $answer" >> "$QUESTIONS_FILE"
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
# Function to display progress
|
|
216
|
+
show_progress() {
|
|
217
|
+
echo ""
|
|
218
|
+
echo -e "${BLUE}=== Interview Progress ===${NC}"
|
|
219
|
+
|
|
220
|
+
local total=$(jq -r '.question_count.total' "$SESSION_FILE")
|
|
221
|
+
echo -e "Total questions: ${GREEN}$total${NC}"
|
|
222
|
+
|
|
223
|
+
echo -e "\nQuestions by expert:"
|
|
224
|
+
echo -e " Database Admin: $(jq -r '.question_count.by_persona.DBA' "$SESSION_FILE")"
|
|
225
|
+
echo -e " Technical Architect: $(jq -r '.question_count.by_persona.TECHNICAL_ARCHITECT' "$SESSION_FILE")"
|
|
226
|
+
echo -e " UX Expert: $(jq -r '.question_count.by_persona.UX_EXPERT' "$SESSION_FILE")"
|
|
227
|
+
echo -e " Software Engineer: $(jq -r '.question_count.by_persona.SOFTWARE_ENGINEER' "$SESSION_FILE")"
|
|
228
|
+
echo -e " DevOps Engineer: $(jq -r '.question_count.by_persona.DEVOPS_ENGINEER' "$SESSION_FILE")"
|
|
229
|
+
echo -e " Security Expert: $(jq -r '.question_count.by_persona.SECURITY_EXPERT' "$SESSION_FILE")"
|
|
230
|
+
|
|
231
|
+
echo ""
|
|
232
|
+
if [ $total -lt 10 ]; then
|
|
233
|
+
echo -e "${YELLOW}Minimum recommended: 10-15 questions${NC}"
|
|
234
|
+
elif [ $total -gt 25 ]; then
|
|
235
|
+
echo -e "${YELLOW}Consider wrapping up - you have plenty of information!${NC}"
|
|
236
|
+
else
|
|
237
|
+
echo -e "${GREEN}Good progress - keep going or type 'done' when ready${NC}"
|
|
238
|
+
fi
|
|
239
|
+
echo ""
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
# Function to consolidate requirements
|
|
243
|
+
consolidate_requirements() {
|
|
244
|
+
echo -e "\n${GREEN}Consolidating requirements...${NC}"
|
|
245
|
+
|
|
246
|
+
local consolidation_prompt="
|
|
247
|
+
You are a technical writer consolidating interview responses into a comprehensive requirements document.
|
|
248
|
+
|
|
249
|
+
=== PROJECT BRIEF ===
|
|
250
|
+
$(cat BRIEF.md)
|
|
251
|
+
|
|
252
|
+
=== INTERVIEW Q&A ===
|
|
253
|
+
$(cat "$QUESTIONS_FILE")
|
|
254
|
+
|
|
255
|
+
=== INSTRUCTIONS ===
|
|
256
|
+
Create a comprehensive requirements document that:
|
|
257
|
+
1. Organizes all requirements by category (functional, technical, operational, etc.)
|
|
258
|
+
2. Removes redundancy while preserving all important details
|
|
259
|
+
3. Clarifies any ambiguities found in the Q&A
|
|
260
|
+
4. Highlights key decisions and constraints
|
|
261
|
+
5. Identifies any gaps that may need addressing
|
|
262
|
+
|
|
263
|
+
Format the output as a clean, well-structured markdown document suitable for feeding into project planning.
|
|
264
|
+
"
|
|
265
|
+
|
|
266
|
+
claude --model opus -p "$consolidation_prompt" > "$REQUIREMENTS_FILE"
|
|
267
|
+
|
|
268
|
+
echo -e "${GREEN}Requirements consolidated in $REQUIREMENTS_FILE${NC}"
|
|
269
|
+
|
|
270
|
+
# Mark session as complete
|
|
271
|
+
jq '.status = "complete"' "$SESSION_FILE" > "$SESSION_FILE.tmp" && mv "$SESSION_FILE.tmp" "$SESSION_FILE"
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
# Main interview loop
|
|
275
|
+
main() {
|
|
276
|
+
echo -e "${GREEN}<� Claude FSD Interactive Interview System${NC}"
|
|
277
|
+
echo -e "${GREEN}============================================${NC}"
|
|
278
|
+
echo ""
|
|
279
|
+
|
|
280
|
+
# Load or init session
|
|
281
|
+
load_session
|
|
282
|
+
|
|
283
|
+
echo -e "\n${YELLOW}Instructions:${NC}"
|
|
284
|
+
echo "- Answer each question concisely (1-2 sentences recommended)"
|
|
285
|
+
echo "- Type 'done' or 'exit' when you have answered enough questions"
|
|
286
|
+
echo "- Press Ctrl+D to finish the interview"
|
|
287
|
+
echo "- Your progress is automatically saved after each answer"
|
|
288
|
+
echo ""
|
|
289
|
+
|
|
290
|
+
# Show current progress
|
|
291
|
+
show_progress
|
|
292
|
+
|
|
293
|
+
# Main loop
|
|
294
|
+
while true; do
|
|
295
|
+
# Get coordinator decision
|
|
296
|
+
echo -e "${BLUE}Consulting project coordinator...${NC}"
|
|
297
|
+
local next_persona=$(get_coordinator_decision)
|
|
298
|
+
|
|
299
|
+
# Check if complete
|
|
300
|
+
if [ "$next_persona" = "COMPLETE" ]; then
|
|
301
|
+
echo -e "\n${GREEN}The coordinator believes we have sufficient information!${NC}"
|
|
302
|
+
read -p "Would you like to conclude the interview? (y/n) " -n 1 -r
|
|
303
|
+
echo
|
|
304
|
+
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
305
|
+
consolidate_requirements
|
|
306
|
+
break
|
|
307
|
+
else
|
|
308
|
+
echo "Continuing with more questions..."
|
|
309
|
+
next_persona="SOFTWARE_ENGINEER" # Default to SE if user wants more
|
|
310
|
+
fi
|
|
311
|
+
fi
|
|
312
|
+
|
|
313
|
+
# Get question from selected persona
|
|
314
|
+
echo -e "\n${BLUE}[$next_persona] is preparing a question...${NC}"
|
|
315
|
+
local question=$(get_persona_question "$next_persona")
|
|
316
|
+
|
|
317
|
+
# Update session with current question
|
|
318
|
+
update_session "$next_persona" "$question"
|
|
319
|
+
|
|
320
|
+
# Display question
|
|
321
|
+
echo -e "\n${GREEN}[$next_persona]${NC} $question"
|
|
322
|
+
|
|
323
|
+
# Get answer
|
|
324
|
+
echo -n "> "
|
|
325
|
+
read -r answer
|
|
326
|
+
|
|
327
|
+
# Check for exit commands
|
|
328
|
+
if [[ "$answer" =~ ^(done|exit|quit)$ ]]; then
|
|
329
|
+
echo -e "\n${YELLOW}Interview concluded by user.${NC}"
|
|
330
|
+
consolidate_requirements
|
|
331
|
+
break
|
|
332
|
+
fi
|
|
333
|
+
|
|
334
|
+
# Save Q&A
|
|
335
|
+
save_qa "$next_persona" "$question" "$answer"
|
|
336
|
+
|
|
337
|
+
# Show progress periodically
|
|
338
|
+
local total=$(jq -r '.question_count.total' "$SESSION_FILE")
|
|
339
|
+
if [ $((total % 5)) -eq 0 ]; then
|
|
340
|
+
show_progress
|
|
341
|
+
fi
|
|
342
|
+
done
|
|
343
|
+
|
|
344
|
+
echo -e "\n${GREEN}Interview complete!${NC}"
|
|
345
|
+
echo "- Questions saved in: $QUESTIONS_FILE"
|
|
346
|
+
echo "- Requirements saved in: $REQUIREMENTS_FILE"
|
|
347
|
+
echo "- Next step: Run 'claudefsd' to create project plan"
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
# Handle Ctrl+D
|
|
351
|
+
trap 'echo -e "\n${YELLOW}Interview ended.${NC}"; consolidate_requirements; exit 0' EOF
|
|
352
|
+
|
|
353
|
+
# Run main
|
|
354
|
+
main
|