Skip to content

Commit df31eb6

Browse files
author
Test User
committed
feat: Complete Phase 5 - Workflow Guidance Engine
- Created internal/workflow/recommender.go with GetNextStep function - Implemented action-to-recommendation mapping for 20+ actions - Maps completed actions to recommended next steps following perfect workflow - Added GetWorkflowSequence() and GetCurrentStep() helper functions - Updated TUI app.go to call recommender after successful actions - Enhanced SuccessMsg to include Action field for tracking - Added RecommendationMsg type for displaying recommendations - Created renderRecommendation() function with styled display (green border) - Updated all TUI action handlers to track actions: * project_created, plan_complete, design_complete * feature_implemented, tests_passed, review_approved * deployment_complete, documents_generated, design_system_applied * api_keys_configured, security_scan_complete, progress_updated * idea_discussed, fix_complete, publish_started, dev_server_started - Recommendations guide users through perfect workflow sequence: Plan → Design → Code → Test → Review → Deploy - Recommendations displayed in styled box after each successful action
1 parent 0b9bd24 commit df31eb6

File tree

3 files changed

+295
-27
lines changed

3 files changed

+295
-27
lines changed

internal/tui/app.go

Lines changed: 76 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55

66
"github.com/DoPlan-dev/CLI/internal/tui/screens"
7+
"github.com/DoPlan-dev/CLI/internal/workflow"
78
tea "github.com/charmbracelet/bubbletea"
89
"github.com/charmbracelet/lipgloss"
910
)
@@ -65,7 +66,7 @@ func (a *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
6566
if err := a.executor.RunDevServer(); err != nil {
6667
return screens.ErrorMsg{Error: err}
6768
}
68-
return screens.SuccessMsg{Message: "Dev server started"}
69+
return screens.SuccessMsg{Message: "Dev server started", Action: "dev_server_started"}
6970
},
7071
)
7172
case "undo":
@@ -74,7 +75,7 @@ func (a *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
7475
if err := a.executor.UndoLastAction(); err != nil {
7576
return screens.ErrorMsg{Error: err}
7677
}
77-
return screens.SuccessMsg{Message: "Last action undone"}
78+
return screens.SuccessMsg{Message: "Last action undone", Action: "action_undone"}
7879
},
7980
)
8081
case "create":
@@ -83,7 +84,7 @@ func (a *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
8384
if err := a.executor.CreateNewProject(); err != nil {
8485
return screens.ErrorMsg{Error: err}
8586
}
86-
return screens.SuccessMsg{Message: "New project created"}
87+
return screens.SuccessMsg{Message: "New project created", Action: "project_created"}
8788
},
8889
)
8990
case "deploy":
@@ -92,7 +93,7 @@ func (a *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
9293
if err := a.executor.DeployProject(); err != nil {
9394
return screens.ErrorMsg{Error: err}
9495
}
95-
return screens.SuccessMsg{Message: "Deployment started"}
96+
return screens.SuccessMsg{Message: "Deployment started", Action: "deployment_started"}
9697
},
9798
)
9899
case "publish":
@@ -101,7 +102,7 @@ func (a *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
101102
if err := a.executor.PublishPackage(); err != nil {
102103
return screens.ErrorMsg{Error: err}
103104
}
104-
return screens.SuccessMsg{Message: "Package publishing started"}
105+
return screens.SuccessMsg{Message: "Package publishing started", Action: "publish_started"}
105106
},
106107
)
107108
case "security":
@@ -110,7 +111,7 @@ func (a *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
110111
if err := a.executor.RunSecurityScan(); err != nil {
111112
return screens.ErrorMsg{Error: err}
112113
}
113-
return screens.SuccessMsg{Message: "Security scan completed"}
114+
return screens.SuccessMsg{Message: "Security scan completed", Action: "security_scan_complete"}
114115
},
115116
)
116117
case "fix":
@@ -119,7 +120,7 @@ func (a *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
119120
if err := a.executor.AutoFix(); err != nil {
120121
return screens.ErrorMsg{Error: err}
121122
}
122-
return screens.SuccessMsg{Message: "Auto-fix completed"}
123+
return screens.SuccessMsg{Message: "Auto-fix completed", Action: "fix_complete"}
123124
},
124125
)
125126
case "discuss":
@@ -128,7 +129,7 @@ func (a *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
128129
if err := a.executor.DiscussIdea(); err != nil {
129130
return screens.ErrorMsg{Error: err}
130131
}
131-
return screens.SuccessMsg{Message: "Idea discussion completed"}
132+
return screens.SuccessMsg{Message: "Idea discussion completed", Action: "idea_discussed"}
132133
},
133134
)
134135
case "generate":
@@ -137,7 +138,7 @@ func (a *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
137138
if err := a.executor.GenerateDocuments(); err != nil {
138139
return screens.ErrorMsg{Error: err}
139140
}
140-
return screens.SuccessMsg{Message: "Documents generated"}
141+
return screens.SuccessMsg{Message: "Documents generated", Action: "documents_generated"}
141142
},
142143
)
143144
case "plan":
@@ -146,7 +147,7 @@ func (a *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
146147
if err := a.executor.CreatePlan(); err != nil {
147148
return screens.ErrorMsg{Error: err}
148149
}
149-
return screens.SuccessMsg{Message: "Plan created"}
150+
return screens.SuccessMsg{Message: "Plan created", Action: "plan_complete"}
150151
},
151152
)
152153
case "progress":
@@ -155,7 +156,7 @@ func (a *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
155156
if err := a.executor.UpdateProgress(); err != nil {
156157
return screens.ErrorMsg{Error: err}
157158
}
158-
return screens.SuccessMsg{Message: "Progress updated"}
159+
return screens.SuccessMsg{Message: "Progress updated", Action: "progress_updated"}
159160
},
160161
)
161162
case "design":
@@ -164,7 +165,7 @@ func (a *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
164165
if err := a.executor.ApplyDesign(); err != nil {
165166
return screens.ErrorMsg{Error: err}
166167
}
167-
return screens.SuccessMsg{Message: "Design system generated"}
168+
return screens.SuccessMsg{Message: "Design system generated", Action: "design_system_applied"}
168169
},
169170
)
170171
case "keys":
@@ -173,7 +174,7 @@ func (a *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
173174
if err := a.executor.ManageAPIKeys(); err != nil {
174175
return screens.ErrorMsg{Error: err}
175176
}
176-
return screens.SuccessMsg{Message: "API keys managed"}
177+
return screens.SuccessMsg{Message: "API keys managed", Action: "api_keys_configured"}
177178
},
178179
)
179180
case "integration":
@@ -198,24 +199,45 @@ func (a *App) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
198199
return a, nil
199200

200201
case screens.SuccessMsg:
201-
// Show success message and return to menu
202+
// Show success message
202203
fmt.Printf("✅ %s\n", msg.Message)
204+
205+
// Get recommended next step if action is provided
206+
if msg.Action != "" {
207+
title, description := workflow.GetNextStep(msg.Action)
208+
if title != "" {
209+
// Return recommendation message
210+
return a, func() tea.Msg {
211+
return screens.RecommendationMsg{
212+
Title: title,
213+
Description: description,
214+
}
215+
}
216+
}
217+
}
218+
203219
a.current = "menu"
204220
return a, nil
205221

206-
case screens.BackToMenuMsg:
207-
a.current = "menu"
208-
return a, nil
209-
case screens.OpenKeysManagementMsg:
210-
// Open keys management
211-
return a, tea.Sequence(
212-
func() tea.Msg {
213-
if err := a.executor.ManageAPIKeys(); err != nil {
214-
return screens.ErrorMsg{Error: err}
215-
}
216-
return screens.SuccessMsg{Message: "API keys managed"}
217-
},
218-
)
222+
case screens.RecommendationMsg:
223+
// Display recommendation and return to menu
224+
renderRecommendation(msg.Title, msg.Description)
225+
a.current = "menu"
226+
return a, nil
227+
228+
case screens.BackToMenuMsg:
229+
a.current = "menu"
230+
return a, nil
231+
case screens.OpenKeysManagementMsg:
232+
// Open keys management
233+
return a, tea.Sequence(
234+
func() tea.Msg {
235+
if err := a.executor.ManageAPIKeys(); err != nil {
236+
return screens.ErrorMsg{Error: err}
237+
}
238+
return screens.SuccessMsg{Message: "API keys managed", Action: "api_keys_configured"}
239+
},
240+
)
219241
}
220242

221243
// Delegate to current screen
@@ -281,6 +303,33 @@ func (a *App) View() string {
281303
)
282304
}
283305

306+
// renderRecommendation displays a recommended next step in a styled box
307+
func renderRecommendation(title, description string) {
308+
// Define styles
309+
borderStyle := lipgloss.NewStyle().
310+
Border(lipgloss.RoundedBorder()).
311+
BorderForeground(lipgloss.Color("#10b981")). // Green border (success color)
312+
Padding(1, 2).
313+
Width(60)
314+
315+
titleStyle := lipgloss.NewStyle().
316+
Foreground(lipgloss.Color("#10b981")).
317+
Bold(true).
318+
MarginBottom(1)
319+
320+
descriptionStyle := lipgloss.NewStyle().
321+
Foreground(lipgloss.Color("#ffffff")).
322+
MarginTop(1)
323+
324+
// Build the recommendation box
325+
content := titleStyle.Render("💡 Recommended Next Step: " + title)
326+
content += "\n\n"
327+
content += descriptionStyle.Render(description)
328+
329+
box := borderStyle.Render(content)
330+
fmt.Println("\n" + box + "\n")
331+
}
332+
284333
// Run starts the TUI with default executor
285334
func Run() error {
286335
return RunWithExecutor(nil)

internal/tui/screens/menu.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,5 +198,12 @@ type ErrorMsg struct {
198198
// SuccessMsg is sent when an action succeeds
199199
type SuccessMsg struct {
200200
Message string
201+
Action string // The action that was completed (e.g., "plan_complete", "feature_implemented")
202+
}
203+
204+
// RecommendationMsg is sent to display a recommended next step
205+
type RecommendationMsg struct {
206+
Title string
207+
Description string
201208
}
202209

0 commit comments

Comments
 (0)