@@ -88,27 +88,13 @@ func promptMCPRegistration() {
8888 }
8989 }
9090
91- // Use custom template to hide "type to filter" and typed characters
92- restore := useMultiSelectTemplateNoFilter ()
93- defer restore ()
94-
9591 fmt .Println ()
9692 printTitle ("MCP" , "Register Symphony as an MCP server" )
9793 fmt .Println (indent ("Symphony MCP provides code convention tools for AI assistants" ))
98- fmt .Println (indent ("(Use arrows to move, space to select, enter to submit)" ))
9994 fmt .Println ()
10095
101- // Multi-select prompt for tools
102- var selectedTools []string
103- prompt := & survey.MultiSelect {
104- Message : "Select vibe coding tools to integrate:" ,
105- Options : mcpToolOptions ,
106- }
107-
108- if err := survey .AskOne (prompt , & selectedTools ); err != nil {
109- fmt .Println ("Skipped MCP registration" )
110- return
111- }
96+ // Use Select with toggle behavior - Enter toggles selection, "Submit" confirms
97+ selectedTools := selectToolsWithEnterToggle (mcpToolOptions )
11298
11399 // If no tools selected, skip
114100 if len (selectedTools ) == 0 {
@@ -414,9 +400,12 @@ func getClaudeCodeInstructions() string {
414400
415401**Check MCP Status**: Verify Symphony MCP server is active. If unavailable, warn the user and do not proceed.
416402
417- **Query Conventions**: Use ` + "`mcp__symphony__list_convention`" + ` to retrieve relevant rules.
418- - Select appropriate category: security, style, documentation, error_handling, architecture, performance, testing
403+ **Query Categories First**: Use ` + "`mcp__symphony__list_category`" + ` to get available categories.
404+ - **IMPORTANT**: Do NOT invent category names. Only use categories returned by list_category.
405+
406+ **Query Conventions**: Use ` + "`mcp__symphony__list_convention`" + ` with a category from list_category.
419407- Filter by languages as needed
408+
420409**After Updating Rules/Categories**: If you add/edit/remove conventions or categories, run ` + "`mcp__symphony__convert`" + ` to regenerate derived policy and linter configs (then re-run validation if needed).
421410
422411### 2. After Writing Code
@@ -428,11 +417,12 @@ func getClaudeCodeInstructions() string {
428417## Workflow
429418
4304191. Verify Symphony MCP is active
431- 2. Query conventions for your task
432- 3. Write code
433- 4. Validate with Symphony
434- 5. Fix violations
435- 6. Commit
420+ 2. Query categories (list_category)
421+ 3. Query conventions with valid category (list_convention)
422+ 4. Write code
423+ 5. Validate with Symphony
424+ 6. Fix violations
425+ 7. Commit
436426` + symphonySectionEnd + "\n "
437427}
438428
@@ -453,22 +443,15 @@ alwaysApply: true
453443
454444### Before Code Generation
4554451. **Verify Symphony MCP is active** - If not available, stop and warn user
456- 2. **Query conventions** - Use ` + "`symphony/list_convention`" + ` with appropriate category and language
457- 3. **After updating conventions/categories** - Use ` + "`symphony/convert`" + ` to regenerate derived policy and linter configs
446+ 2. **Query categories first** - Use ` + "`symphony/list_category`" + ` to get available categories
447+ - **IMPORTANT**: Do NOT invent category names. Only use categories returned by list_category.
448+ 3. **Query conventions** - Use ` + "`symphony/list_convention`" + ` with a category from step 2
449+ 4. **After updating conventions/categories** - Use ` + "`symphony/convert`" + ` to regenerate derived policy and linter configs
458450
459451### After Code Generation
4604521. **Validate all changes** - Use ` + "`symphony/validate_code`" + `
4614532. **Fix violations** - Address issues before committing
462454
463- ## Convention Categories
464- - security
465- - style
466- - documentation
467- - error_handling
468- - architecture
469- - performance
470- - testing
471-
472455---
473456
474457*Auto-generated by Symphony*
@@ -491,20 +474,119 @@ This project uses Symphony MCP for automated code convention management.
491474
492475### Before Writing Code
4934761. Verify Symphony MCP server is active. If not available, warn user and stop.
494- 2. Query relevant conventions using symphony/list_convention tool.
495- - Categories: security, style, documentation, error_handling, architecture, performance, testing
496- - Filter by programming language
497- 3. If you add/edit/remove conventions or categories, run symphony/convert (then validate again if needed).
477+ 2. Query available categories using symphony/list_category tool.
478+ - **IMPORTANT**: Do NOT invent category names. Only use categories returned by list_category.
479+ 3. Query relevant conventions using symphony/list_convention tool with a category from step 2.
480+ - Filter by programming language as needed
481+ 4. If you add/edit/remove conventions or categories, run symphony/convert (then validate again if needed).
498482
499483### After Writing Code
5004841. Always validate changes using symphony/validate_code tool (validates all git changes)
5014852. Fix any violations found
5024863. Only commit after validation passes
503487
504488## Workflow
505- Check MCP → Query Conventions → Write Code → Validate → Fix → Commit
489+ Check MCP → Query Categories → Query Conventions → Write Code → Validate → Fix → Commit
506490
507491---
508492Auto-generated by Symphony
509493`
510494}
495+
496+ // selectToolsWithEnterToggle allows users to select tools using Enter key to toggle
497+ // and "Submit" option to confirm selection
498+ func selectToolsWithEnterToggle (tools []string ) []string {
499+ selected := make (map [string ]bool )
500+ lastChoice := "" // Track last selected option to maintain cursor position
501+
502+ // Use custom template to hide message output
503+ restore := useSelectTemplateNoMessage ()
504+ defer restore ()
505+
506+ // Print header once with cyan hint
507+ fmt .Printf ("Select tools to integrate: %s\n " , colorize (cyan , "[Enter: toggle]" ))
508+
509+ for {
510+ // Count selected items
511+ count := 0
512+ for _ , v := range selected {
513+ if v {
514+ count ++
515+ }
516+ }
517+
518+ // Build submit option with count
519+ var submitOption string
520+ if count > 0 {
521+ submitOption = fmt .Sprintf ("✓ Submit (%d selected)" , count )
522+ } else {
523+ submitOption = "✓ Submit"
524+ }
525+
526+ // Build options with selection indicators
527+ options := make ([]string , 0 , len (tools )+ 1 )
528+ for _ , tool := range tools {
529+ if selected [tool ] {
530+ options = append (options , fmt .Sprintf ("[x] %s" , tool ))
531+ } else {
532+ options = append (options , fmt .Sprintf ("[ ] %s" , tool ))
533+ }
534+ }
535+ options = append (options , submitOption )
536+
537+ // Find default option index based on last choice
538+ defaultOption := options [0 ]
539+ if lastChoice != "" {
540+ for _ , opt := range options {
541+ // Match by tool name (ignore [x]/[ ] prefix and submit option changes)
542+ if strings .HasPrefix (lastChoice , "✓" ) && strings .HasPrefix (opt , "✓" ) {
543+ defaultOption = opt
544+ break
545+ }
546+ for _ , tool := range tools {
547+ if strings .Contains (lastChoice , tool ) && strings .Contains (opt , tool ) {
548+ defaultOption = opt
549+ break
550+ }
551+ }
552+ }
553+ }
554+
555+ // Show selection prompt
556+ var choice string
557+ prompt := & survey.Select {
558+ Message : "" ,
559+ Options : options ,
560+ Default : defaultOption ,
561+ }
562+
563+ if err := survey .AskOne (prompt , & choice ); err != nil {
564+ // User cancelled
565+ return nil
566+ }
567+
568+ lastChoice = choice
569+
570+ // Check if Submit was selected
571+ if strings .HasPrefix (choice , "✓ Submit" ) {
572+ break
573+ }
574+
575+ // Toggle the selected tool
576+ for _ , tool := range tools {
577+ if strings .Contains (choice , tool ) {
578+ selected [tool ] = ! selected [tool ]
579+ break
580+ }
581+ }
582+ }
583+
584+ // Collect selected tools
585+ var result []string
586+ for _ , tool := range tools {
587+ if selected [tool ] {
588+ result = append (result , tool )
589+ }
590+ }
591+ return result
592+ }
0 commit comments