Skip to content

Commit 480fef4

Browse files
committed
fix(mcp): improve plan clarify/generate TUI formatting
- Questions shown as numbered Decisions with clear separators - Ready state shows 'What will be built' + approve prompt - Generate result uses table format for task list - Remove raw JSON payload dump from clarification output
1 parent 0b0afa4 commit 480fef4

1 file changed

Lines changed: 43 additions & 52 deletions

File tree

internal/mcp/presenter.go

Lines changed: 43 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -742,60 +742,54 @@ func FormatClarifyResult(result *app.ClarifyResult) string {
742742

743743
var sb strings.Builder
744744

745-
// Ready status
746745
if result.IsReadyToPlan {
746+
// Ready state: concise, actionable
747747
sb.WriteString("## ✅ Ready to Generate Plan\n\n")
748+
if result.ClarifySessionID != "" {
749+
sb.WriteString(fmt.Sprintf("**Session**: `%s` | **Round**: %d\n\n", result.ClarifySessionID, result.RoundIndex))
750+
}
751+
if result.GoalSummary != "" {
752+
sb.WriteString(fmt.Sprintf("**Goal**: %s\n\n", result.GoalSummary))
753+
}
754+
if result.EnrichedGoal != "" {
755+
sb.WriteString("### What will be built\n")
756+
sb.WriteString(result.EnrichedGoal)
757+
sb.WriteString("\n\n")
758+
}
759+
sb.WriteString("> Approve this specification, then the plan will be generated with tasks.\n")
748760
} else {
749-
sb.WriteString("## 🔍 Clarification Needed\n\n")
750-
}
751-
752-
if result.ClarifySessionID != "" {
753-
sb.WriteString(fmt.Sprintf("**Clarify Session**: `%s`\n", result.ClarifySessionID))
754-
sb.WriteString(fmt.Sprintf("**Round**: %d\n\n", result.RoundIndex))
755-
}
756-
757-
// Goal summary
758-
if result.GoalSummary != "" {
759-
sb.WriteString(fmt.Sprintf("**Goal**: %s\n\n", result.GoalSummary))
760-
}
761+
// Needs clarification: show questions prominently
762+
sb.WriteString("## 🔍 Decisions Needed Before Planning\n\n")
763+
if result.ClarifySessionID != "" {
764+
sb.WriteString(fmt.Sprintf("**Session**: `%s` | **Round**: %d\n\n", result.ClarifySessionID, result.RoundIndex))
765+
}
766+
if result.GoalSummary != "" {
767+
sb.WriteString(fmt.Sprintf("**Goal**: %s\n\n", result.GoalSummary))
768+
}
761769

762-
// Questions (if not ready)
763-
if len(result.Questions) > 0 && !result.IsReadyToPlan {
764-
sb.WriteString("### Questions\n")
765-
for i, q := range result.Questions {
766-
sb.WriteString(fmt.Sprintf("%d. %s\n", i+1, q))
770+
// Questions with clear formatting
771+
if len(result.Questions) > 0 {
772+
for i, q := range result.Questions {
773+
sb.WriteString(fmt.Sprintf("### Decision %d\n", i+1))
774+
sb.WriteString(fmt.Sprintf("%s\n\n", q))
775+
}
767776
}
768-
sb.WriteString("\n")
769-
}
770777

771-
// Enriched goal draft is always shown so user/agent can refine every round.
772-
if result.EnrichedGoal != "" {
773-
sb.WriteString("### Enriched Specification\n")
774-
sb.WriteString(result.EnrichedGoal)
775-
sb.WriteString("\n\n")
776-
if result.IsReadyToPlan {
777-
sb.WriteString("> **Next**: Call `plan` with action=`generate`, this `enriched_goal`, and `clarify_session_id` to create tasks.\n")
778+
// Show enriched spec as collapsible context
779+
if result.EnrichedGoal != "" {
780+
sb.WriteString("### Draft Specification\n")
781+
sb.WriteString(result.EnrichedGoal)
782+
sb.WriteString("\n\n")
778783
}
779-
}
780784

781-
if !result.IsReadyToPlan && result.ClarifySessionID != "" {
782-
sb.WriteString("### Next Clarify Call Payload\n")
783-
sb.WriteString("```json\n")
784-
sb.WriteString("{\n")
785-
sb.WriteString(" \"action\": \"clarify\",\n")
786-
sb.WriteString(fmt.Sprintf(" \"clarify_session_id\": \"%s\",\n", result.ClarifySessionID))
787-
sb.WriteString(" \"answers\": [\n")
788-
sb.WriteString(" {\"question\": \"<question>\", \"answer\": \"<answer>\"}\n")
789-
sb.WriteString(" ]\n")
790-
sb.WriteString("}\n")
791-
sb.WriteString("```\n")
785+
sb.WriteString("> Answer the decisions above, or say **auto** to let TaskWing choose.\n")
792786
}
793787

794788
if result.MaxRoundsReached {
795-
sb.WriteString("\n⚠️ Clarification reached maximum rounds before becoming ready.\n")
789+
sb.WriteString("\n⚠️ Maximum clarification rounds reached.\n")
796790
}
797791

798-
// Context used
792+
// Context transparency: show what knowledge was consulted
799793
if result.ContextUsed != "" {
800794
sb.WriteString(fmt.Sprintf("\n*%s*\n", result.ContextUsed))
801795
}
@@ -820,25 +814,22 @@ func FormatGenerateResult(result *app.GenerateResult) string {
820814
var sb strings.Builder
821815

822816
sb.WriteString("## ✅ Plan Generated\n\n")
823-
sb.WriteString(fmt.Sprintf("**Plan ID**: `%s`\n", result.PlanID))
824-
sb.WriteString(fmt.Sprintf("**Goal**: %s\n\n", result.Goal))
817+
sb.WriteString(fmt.Sprintf("**Plan**: `%s`\n", result.PlanID))
818+
sb.WriteString(fmt.Sprintf("**Goal**: %s\n", result.Goal))
819+
sb.WriteString(fmt.Sprintf("**Tasks**: %d\n\n", len(result.Tasks)))
825820

826-
// Tasks
821+
// Tasks as a table for scannability
827822
if len(result.Tasks) > 0 {
828-
sb.WriteString("### Tasks\n")
823+
sb.WriteString("| # | Task | Priority |\n")
824+
sb.WriteString("|---|------|----------|\n")
829825
for i, t := range result.Tasks {
830-
sb.WriteString(fmt.Sprintf("%d. **%s** (P%d)\n", i+1, t.Title, t.Priority))
831-
if t.Description != "" {
832-
desc := truncate(t.Description, 100)
833-
sb.WriteString(fmt.Sprintf(" %s\n", desc))
834-
}
826+
sb.WriteString(fmt.Sprintf("| %d | %s | P%d |\n", i+1, t.Title, t.Priority))
835827
}
836828
sb.WriteString("\n")
837829
}
838830

839-
// Hint
840831
if result.Hint != "" {
841-
sb.WriteString(fmt.Sprintf("> **Hint**: %s\n", result.Hint))
832+
sb.WriteString(fmt.Sprintf("> %s\n", result.Hint))
842833
}
843834

844835
return strings.TrimSpace(sb.String())

0 commit comments

Comments
 (0)