Unified Agent + reusable Go agent core.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: Add Telegram bot persona initialization and progress tracking prompts

Lyric 8abcf83b e9011303

+333 -53
+6 -10
cmd/mistermorph/telegramcmd/command.go
··· 1651 1651 "steps_total": total, 1652 1652 "progress_percent": int(float64(completed) / float64(total) * 100), 1653 1653 } 1654 - b, _ := json.Marshal(payload) 1655 - 1656 - system := "You write very short, casual progress updates for a Telegram chat. " + 1657 - "Keep it conversational and concise (1 short sentence, max 2). " + 1658 - "Use the same language as the task. " + 1659 - "Use Telegram MarkdownV2 and wrap identifiers/paths in backticks. " + 1660 - "Do not mention tools, internal steps, or that you are an AI. " + 1661 - "Include the completed step and, if present, the next step." 1654 + systemPrompt, userPrompt, err := renderTelegramPlanProgressPrompts(payload) 1655 + if err != nil { 1656 + return "", err 1657 + } 1662 1658 1663 1659 req := llm.Request{ 1664 1660 Model: model, 1665 1661 ForceJSON: false, 1666 1662 Messages: []llm.Message{ 1667 - {Role: "system", Content: system}, 1668 - {Role: "user", Content: "Generate a progress update for this plan step:\n" + string(b)}, 1663 + {Role: "system", Content: systemPrompt}, 1664 + {Role: "user", Content: userPrompt}, 1669 1665 }, 1670 1666 Parameters: map[string]any{ 1671 1667 "max_tokens": 4096,
+20 -43
cmd/mistermorph/telegramcmd/init_flow.go
··· 2 2 3 3 import ( 4 4 "context" 5 - "encoding/json" 6 5 "errors" 7 6 "fmt" 8 7 "os" ··· 132 131 }, 133 132 "question_count": map[string]int{"min": 4, "max": 7}, 134 133 } 135 - rawPayload, _ := json.Marshal(payload) 136 - 137 - systemPrompt := strings.Join([]string{ 138 - "You design onboarding questions for an assistant persona bootstrap.", 139 - "Return JSON only: {\"questions\":[string,...]}.", 140 - "Use the same language as user_text for all questions.", 141 - "Questions must collect enough info to fill identity Name/Creature/Vibe/Emoji and soul Core Truths/Boundaries/Vibe.", 142 - "If info is likely missing, ask preference-oriented questions that allow reasonable inference.", 143 - "Do not include explanations, only concise questions.", 144 - }, " ") 134 + systemPrompt, userPrompt, err := renderInitQuestionsPrompts(payload) 135 + if err != nil { 136 + return defaultInitQuestions(userText), err 137 + } 145 138 146 139 res, err := client.Chat(ctx, llm.Request{ 147 140 Model: strings.TrimSpace(model), 148 141 ForceJSON: true, 149 142 Messages: []llm.Message{ 150 143 {Role: "system", Content: systemPrompt}, 151 - {Role: "user", Content: string(rawPayload)}, 144 + {Role: "user", Content: userPrompt}, 152 145 }, 153 146 Parameters: map[string]any{ 154 147 "temperature": 0.4, ··· 216 209 "user_answer": strings.TrimSpace(userAnswer), 217 210 }, 218 211 } 219 - rawPayload, _ := json.Marshal(payload) 220 - 221 - systemPrompt := strings.Join([]string{ 222 - "You are replying in Telegram private chat immediately after persona bootstrap.", 223 - "Use identity_markdown and soul_markdown as authoritative persona.", 224 - "Reply naturally in the same language as user_answer.", 225 - "Keep it concise (1-3 short sentences), warm and conversational.", 226 - "Do NOT mention initialization flow, files, status fields, or internal process.", 227 - }, " ") 212 + systemPrompt, userPrompt, err := renderInitPostGreetingPrompts(payload) 213 + if err != nil { 214 + return fallbackPostInitGreeting(userAnswer, fallback), err 215 + } 228 216 229 217 res, err := client.Chat(ctx, llm.Request{ 230 218 Model: strings.TrimSpace(model), 231 219 ForceJSON: false, 232 220 Messages: []llm.Message{ 233 221 {Role: "system", Content: systemPrompt}, 234 - {Role: "user", Content: string(rawPayload)}, 222 + {Role: "user", Content: userPrompt}, 235 223 }, 236 224 Parameters: map[string]any{ 237 225 "temperature": 0.7, ··· 275 263 "user_text": strings.TrimSpace(userText), 276 264 "questions": normalized, 277 265 } 278 - rawPayload, _ := json.Marshal(payload) 279 - 280 - systemPrompt := strings.Join([]string{ 281 - "You are sending a Telegram private message that asks persona-setup questions.", 282 - "Use the same language as user_text.", 283 - "Write naturally and conversationally, not as a workflow/status message.", 284 - "Do not mention initialization, files, status fields, or internal process.", 285 - "Ask the listed questions clearly and invite user to answer in one reply.", 286 - }, " ") 266 + systemPrompt, userPrompt, err := renderInitQuestionMessagePrompts(payload) 267 + if err != nil { 268 + return fallbackInitQuestionMessage(normalized, userText), err 269 + } 287 270 288 271 res, err := client.Chat(ctx, llm.Request{ 289 272 Model: strings.TrimSpace(model), 290 273 ForceJSON: false, 291 274 Messages: []llm.Message{ 292 275 {Role: "system", Content: systemPrompt}, 293 - {Role: "user", Content: string(rawPayload)}, 276 + {Role: "user", Content: userPrompt}, 294 277 }, 295 278 Parameters: map[string]any{ 296 279 "temperature": 0.7, ··· 343 326 "soul": []string{"core_truths", "boundaries", "vibe"}, 344 327 }, 345 328 } 346 - rawPayload, _ := json.Marshal(payload) 347 - 348 - systemPrompt := strings.Join([]string{ 349 - "You fill assistant persona fields from onboarding answers.", 350 - "Return JSON only with schema:", 351 - "{\"identity\":{\"name\":string,\"creature\":string,\"vibe\":string,\"emoji\":string},\"soul\":{\"core_truths\":[string],\"boundaries\":[string],\"vibe\":string}}.", 352 - "Never leave required fields empty.", 353 - "If user input is insufficient, infer plausible values from available context and produce complete output.", 354 - "core_truths and boundaries should each contain 3-6 concise items.", 355 - }, " ") 329 + systemPrompt, userPrompt, err := renderInitFillPrompts(payload) 330 + if err != nil { 331 + return fallback, nil 332 + } 356 333 357 334 res, err := client.Chat(ctx, llm.Request{ 358 335 Model: strings.TrimSpace(model), 359 336 ForceJSON: true, 360 337 Messages: []llm.Message{ 361 338 {Role: "system", Content: systemPrompt}, 362 - {Role: "user", Content: string(rawPayload)}, 339 + {Role: "user", Content: userPrompt}, 363 340 }, 364 341 Parameters: map[string]any{ 365 342 "temperature": 0.5,
+100
cmd/mistermorph/telegramcmd/init_prompts.go
··· 1 + package telegramcmd 2 + 3 + import ( 4 + _ "embed" 5 + "encoding/json" 6 + "text/template" 7 + 8 + "github.com/quailyquaily/mistermorph/internal/prompttmpl" 9 + ) 10 + 11 + //go:embed prompts/init_questions_system.tmpl 12 + var initQuestionsSystemPromptTemplateSource string 13 + 14 + //go:embed prompts/init_questions_user.tmpl 15 + var initQuestionsUserPromptTemplateSource string 16 + 17 + //go:embed prompts/init_fill_system.tmpl 18 + var initFillSystemPromptTemplateSource string 19 + 20 + //go:embed prompts/init_fill_user.tmpl 21 + var initFillUserPromptTemplateSource string 22 + 23 + //go:embed prompts/init_question_message_system.tmpl 24 + var initQuestionMessageSystemPromptTemplateSource string 25 + 26 + //go:embed prompts/init_question_message_user.tmpl 27 + var initQuestionMessageUserPromptTemplateSource string 28 + 29 + //go:embed prompts/init_post_greeting_system.tmpl 30 + var initPostGreetingSystemPromptTemplateSource string 31 + 32 + //go:embed prompts/init_post_greeting_user.tmpl 33 + var initPostGreetingUserPromptTemplateSource string 34 + 35 + var initPromptTemplateFuncs = template.FuncMap{ 36 + "toJSON": func(v any) (string, error) { 37 + b, err := json.Marshal(v) 38 + if err != nil { 39 + return "", err 40 + } 41 + return string(b), nil 42 + }, 43 + } 44 + 45 + var initQuestionsSystemPromptTemplate = prompttmpl.MustParse("telegram_init_questions_system", initQuestionsSystemPromptTemplateSource, nil) 46 + var initQuestionsUserPromptTemplate = prompttmpl.MustParse("telegram_init_questions_user", initQuestionsUserPromptTemplateSource, initPromptTemplateFuncs) 47 + var initFillSystemPromptTemplate = prompttmpl.MustParse("telegram_init_fill_system", initFillSystemPromptTemplateSource, nil) 48 + var initFillUserPromptTemplate = prompttmpl.MustParse("telegram_init_fill_user", initFillUserPromptTemplateSource, initPromptTemplateFuncs) 49 + var initQuestionMessageSystemPromptTemplate = prompttmpl.MustParse("telegram_init_question_message_system", initQuestionMessageSystemPromptTemplateSource, nil) 50 + var initQuestionMessageUserPromptTemplate = prompttmpl.MustParse("telegram_init_question_message_user", initQuestionMessageUserPromptTemplateSource, initPromptTemplateFuncs) 51 + var initPostGreetingSystemPromptTemplate = prompttmpl.MustParse("telegram_init_post_greeting_system", initPostGreetingSystemPromptTemplateSource, nil) 52 + var initPostGreetingUserPromptTemplate = prompttmpl.MustParse("telegram_init_post_greeting_user", initPostGreetingUserPromptTemplateSource, initPromptTemplateFuncs) 53 + 54 + func renderInitQuestionsPrompts(payload map[string]any) (string, string, error) { 55 + systemPrompt, err := prompttmpl.Render(initQuestionsSystemPromptTemplate, struct{}{}) 56 + if err != nil { 57 + return "", "", err 58 + } 59 + userPrompt, err := prompttmpl.Render(initQuestionsUserPromptTemplate, payload) 60 + if err != nil { 61 + return "", "", err 62 + } 63 + return systemPrompt, userPrompt, nil 64 + } 65 + 66 + func renderInitFillPrompts(payload map[string]any) (string, string, error) { 67 + systemPrompt, err := prompttmpl.Render(initFillSystemPromptTemplate, struct{}{}) 68 + if err != nil { 69 + return "", "", err 70 + } 71 + userPrompt, err := prompttmpl.Render(initFillUserPromptTemplate, payload) 72 + if err != nil { 73 + return "", "", err 74 + } 75 + return systemPrompt, userPrompt, nil 76 + } 77 + 78 + func renderInitQuestionMessagePrompts(payload map[string]any) (string, string, error) { 79 + systemPrompt, err := prompttmpl.Render(initQuestionMessageSystemPromptTemplate, struct{}{}) 80 + if err != nil { 81 + return "", "", err 82 + } 83 + userPrompt, err := prompttmpl.Render(initQuestionMessageUserPromptTemplate, payload) 84 + if err != nil { 85 + return "", "", err 86 + } 87 + return systemPrompt, userPrompt, nil 88 + } 89 + 90 + func renderInitPostGreetingPrompts(payload map[string]any) (string, string, error) { 91 + systemPrompt, err := prompttmpl.Render(initPostGreetingSystemPromptTemplate, struct{}{}) 92 + if err != nil { 93 + return "", "", err 94 + } 95 + userPrompt, err := prompttmpl.Render(initPostGreetingUserPromptTemplate, payload) 96 + if err != nil { 97 + return "", "", err 98 + } 99 + return systemPrompt, userPrompt, nil 100 + }
+76
cmd/mistermorph/telegramcmd/init_prompts_test.go
··· 1 + package telegramcmd 2 + 3 + import ( 4 + "strings" 5 + "testing" 6 + ) 7 + 8 + func TestRenderInitQuestionsPrompts(t *testing.T) { 9 + payload := map[string]any{ 10 + "user_text": "hello", 11 + "required_targets": map[string]any{ 12 + "identity": []string{"Name", "Creature", "Vibe", "Emoji"}, 13 + "soul": []string{"Core Truths", "Boundaries", "Vibe"}, 14 + }, 15 + } 16 + sys, user, err := renderInitQuestionsPrompts(payload) 17 + if err != nil { 18 + t.Fatalf("renderInitQuestionsPrompts() error = %v", err) 19 + } 20 + if !strings.Contains(sys, "Return JSON only") { 21 + t.Fatalf("system prompt missing contract: %q", sys) 22 + } 23 + if !strings.Contains(user, "\"user_text\":\"hello\"") { 24 + t.Fatalf("user prompt missing payload: %q", user) 25 + } 26 + } 27 + 28 + func TestRenderInitFillPrompts(t *testing.T) { 29 + payload := map[string]any{ 30 + "user_answer": "I want you to be concise.", 31 + } 32 + sys, user, err := renderInitFillPrompts(payload) 33 + if err != nil { 34 + t.Fatalf("renderInitFillPrompts() error = %v", err) 35 + } 36 + if !strings.Contains(sys, "\"identity\"") || !strings.Contains(sys, "\"soul\"") { 37 + t.Fatalf("system prompt missing schema: %q", sys) 38 + } 39 + if !strings.Contains(user, "\"user_answer\":\"I want you to be concise.\"") { 40 + t.Fatalf("user prompt missing payload: %q", user) 41 + } 42 + } 43 + 44 + func TestRenderInitQuestionMessagePrompts(t *testing.T) { 45 + payload := map[string]any{ 46 + "user_text": "Hi", 47 + "questions": []string{"Q1", "Q2"}, 48 + } 49 + sys, user, err := renderInitQuestionMessagePrompts(payload) 50 + if err != nil { 51 + t.Fatalf("renderInitQuestionMessagePrompts() error = %v", err) 52 + } 53 + if !strings.Contains(sys, "persona-setup questions") { 54 + t.Fatalf("system prompt missing intent: %q", sys) 55 + } 56 + if !strings.Contains(user, "\"questions\":[\"Q1\",\"Q2\"]") { 57 + t.Fatalf("user prompt missing questions: %q", user) 58 + } 59 + } 60 + 61 + func TestRenderInitPostGreetingPrompts(t *testing.T) { 62 + payload := map[string]any{ 63 + "identity_markdown": "# IDENTITY", 64 + "soul_markdown": "# SOUL", 65 + } 66 + sys, user, err := renderInitPostGreetingPrompts(payload) 67 + if err != nil { 68 + t.Fatalf("renderInitPostGreetingPrompts() error = %v", err) 69 + } 70 + if !strings.Contains(sys, "persona bootstrap") { 71 + t.Fatalf("system prompt missing context: %q", sys) 72 + } 73 + if !strings.Contains(user, "\"identity_markdown\":\"# IDENTITY\"") { 74 + t.Fatalf("user prompt missing payload: %q", user) 75 + } 76 + }
+40
cmd/mistermorph/telegramcmd/plan_progress_prompts.go
··· 1 + package telegramcmd 2 + 3 + import ( 4 + _ "embed" 5 + "encoding/json" 6 + "text/template" 7 + 8 + "github.com/quailyquaily/mistermorph/internal/prompttmpl" 9 + ) 10 + 11 + //go:embed prompts/plan_progress_system.tmpl 12 + var planProgressSystemPromptTemplateSource string 13 + 14 + //go:embed prompts/plan_progress_user.tmpl 15 + var planProgressUserPromptTemplateSource string 16 + 17 + var planProgressPromptTemplateFuncs = template.FuncMap{ 18 + "toJSON": func(v any) (string, error) { 19 + b, err := json.Marshal(v) 20 + if err != nil { 21 + return "", err 22 + } 23 + return string(b), nil 24 + }, 25 + } 26 + 27 + var planProgressSystemPromptTemplate = prompttmpl.MustParse("telegram_plan_progress_system", planProgressSystemPromptTemplateSource, nil) 28 + var planProgressUserPromptTemplate = prompttmpl.MustParse("telegram_plan_progress_user", planProgressUserPromptTemplateSource, planProgressPromptTemplateFuncs) 29 + 30 + func renderTelegramPlanProgressPrompts(payload map[string]any) (string, string, error) { 31 + systemPrompt, err := prompttmpl.Render(planProgressSystemPromptTemplate, struct{}{}) 32 + if err != nil { 33 + return "", "", err 34 + } 35 + userPrompt, err := prompttmpl.Render(planProgressUserPromptTemplate, payload) 36 + if err != nil { 37 + return "", "", err 38 + } 39 + return systemPrompt, userPrompt, nil 40 + }
+27
cmd/mistermorph/telegramcmd/plan_progress_prompts_test.go
··· 1 + package telegramcmd 2 + 3 + import ( 4 + "strings" 5 + "testing" 6 + ) 7 + 8 + func TestRenderTelegramPlanProgressPrompts(t *testing.T) { 9 + payload := map[string]any{ 10 + "task": "prepare release notes", 11 + "completed_step": "collect changelog", 12 + "next_step": "draft summary", 13 + } 14 + sys, user, err := renderTelegramPlanProgressPrompts(payload) 15 + if err != nil { 16 + t.Fatalf("renderTelegramPlanProgressPrompts() error = %v", err) 17 + } 18 + if !strings.Contains(sys, "casual progress updates for a Telegram chat") { 19 + t.Fatalf("system prompt missing guidance: %q", sys) 20 + } 21 + if !strings.Contains(user, "Generate a progress update for this plan step:") { 22 + t.Fatalf("user prompt missing instruction: %q", user) 23 + } 24 + if !strings.Contains(user, "\"task\":\"prepare release notes\"") { 25 + t.Fatalf("user prompt missing task payload: %q", user) 26 + } 27 + }
+6
cmd/mistermorph/telegramcmd/prompts/init_fill_system.tmpl
··· 1 + You fill assistant persona fields from onboarding answers. 2 + Return JSON only with schema: 3 + {"identity":{"name":string,"creature":string,"vibe":string,"emoji":string},"soul":{"core_truths":[string],"boundaries":[string],"vibe":string}}. 4 + Never leave required fields empty. 5 + If user input is insufficient, infer plausible values from available context and produce complete output. 6 + core_truths and boundaries should each contain 3-6 concise items.
+1
cmd/mistermorph/telegramcmd/prompts/init_fill_user.tmpl
··· 1 + {{ toJSON . }}
+5
cmd/mistermorph/telegramcmd/prompts/init_post_greeting_system.tmpl
··· 1 + You are replying in Telegram private chat immediately after persona bootstrap. 2 + Use identity_markdown and soul_markdown as authoritative persona. 3 + Reply naturally in the same language as user_answer. 4 + Keep it concise (1-3 short sentences), warm and conversational. 5 + Do NOT mention initialization flow, files, status fields, or internal process.
+1
cmd/mistermorph/telegramcmd/prompts/init_post_greeting_user.tmpl
··· 1 + {{ toJSON . }}
+5
cmd/mistermorph/telegramcmd/prompts/init_question_message_system.tmpl
··· 1 + You are sending a Telegram private message that asks persona-setup questions. 2 + Use the same language as user_text. 3 + Write naturally and conversationally, not as a workflow/status message. 4 + Do not mention initialization, files, status fields, or internal process. 5 + Ask the listed questions clearly and invite user to answer in one reply.
+1
cmd/mistermorph/telegramcmd/prompts/init_question_message_user.tmpl
··· 1 + {{ toJSON . }}
+6
cmd/mistermorph/telegramcmd/prompts/init_questions_system.tmpl
··· 1 + You design onboarding questions for an assistant persona bootstrap. 2 + Return JSON only: {"questions":[string,...]}. 3 + Use the same language as user_text for all questions. 4 + Questions must collect enough info to fill identity Name/Creature/Vibe/Emoji and soul Core Truths/Boundaries/Vibe. 5 + If info is likely missing, ask preference-oriented questions that allow reasonable inference. 6 + Do not include explanations, only concise questions.
+1
cmd/mistermorph/telegramcmd/prompts/init_questions_user.tmpl
··· 1 + {{ toJSON . }}
+6
cmd/mistermorph/telegramcmd/prompts/plan_progress_system.tmpl
··· 1 + You write very short, casual progress updates for a Telegram chat. 2 + Keep it conversational and concise (1 short sentence, max 2). 3 + Use the same language as the task. 4 + Use Telegram MarkdownV2 and wrap identifiers/paths in backticks. 5 + Do not mention tools, internal steps, or that you are an AI. 6 + Include the completed step and, if present, the next step.
+2
cmd/mistermorph/telegramcmd/prompts/plan_progress_user.tmpl
··· 1 + Generate a progress update for this plan step: 2 + {{ toJSON . }}
+30
docs/prompt.md
··· 94 94 | `agent/prompts/system.tmpl` | system | Renders the main system prompt (Identity, Blocks, Tools, response format, Rules). | 95 95 | `agent/prompts/intent_system.tmpl` | system | Constrains intent inference output schema (JSON contract). | 96 96 | `agent/prompts/intent_user.tmpl` | user | Carries `task/history` plus built-in intent inference rules. | 97 + | `telegramcmd/prompts/init_questions_system.tmpl` | system | Defines output contract for Telegram persona-bootstrap question generation. | 98 + | `telegramcmd/prompts/init_questions_user.tmpl` | user | Carries draft identity/soul context, user text, and required target fields for init question generation. | 99 + | `telegramcmd/prompts/init_fill_system.tmpl` | system | Defines output contract for Telegram persona field filling. | 100 + | `telegramcmd/prompts/init_fill_user.tmpl` | user | Carries draft identity/soul content, user answers, and Telegram context for persona field filling. | 101 + | `telegramcmd/prompts/init_question_message_system.tmpl` | system | Defines style/constraints for natural Telegram init question messages. | 102 + | `telegramcmd/prompts/init_question_message_user.tmpl` | user | Carries user text plus normalized question list for init question message generation. | 103 + | `telegramcmd/prompts/init_post_greeting_system.tmpl` | system | Defines style/constraints for immediate post-init Telegram greeting generation. | 104 + | `telegramcmd/prompts/init_post_greeting_user.tmpl` | user | Carries finalized identity/soul markdown plus init context for post-init greeting generation. | 105 + | `telegramcmd/prompts/plan_progress_system.tmpl` | system | Defines style/constraints for Telegram plan-progress rewrite messages. | 106 + | `telegramcmd/prompts/plan_progress_user.tmpl` | user | Carries plan progress payload (task, completed/next step, progress stats) for rewrite. | 97 107 | `telegramcmd/prompts/memory_draft_system.tmpl` | system | Defines the output contract for single-session memory draft generation. | 98 108 | `telegramcmd/prompts/memory_draft_user.tmpl` | user | Carries session context, dialogue snippets, existing tasks/follow-ups, and summarization rules. | 99 109 | `telegramcmd/prompts/memory_merge_system.tmpl` | system | Defines the output contract for same-day short-term memory merge. | ··· 172 182 ### 8) Telegram init question generation 173 183 174 184 - File/Function: `cmd/mistermorph/telegramcmd/init_flow.go` / `buildInitQuestions(...)` 185 + - Templates: 186 + - `cmd/mistermorph/telegramcmd/prompts/init_questions_system.tmpl` 187 + - `cmd/mistermorph/telegramcmd/prompts/init_questions_user.tmpl` 188 + - Renderer: `cmd/mistermorph/telegramcmd/init_prompts.go` 175 189 - Purpose: generate onboarding questions for persona bootstrap 176 190 - Primary input: draft `IDENTITY.md`, draft `SOUL.md`, user text, required target fields 177 191 - Output: `{"questions": [...]}` ··· 180 194 ### 9) Telegram init field filling 181 195 182 196 - File/Function: `cmd/mistermorph/telegramcmd/init_flow.go` / `buildInitFill(...)` 197 + - Templates: 198 + - `cmd/mistermorph/telegramcmd/prompts/init_fill_system.tmpl` 199 + - `cmd/mistermorph/telegramcmd/prompts/init_fill_user.tmpl` 200 + - Renderer: `cmd/mistermorph/telegramcmd/init_prompts.go` 183 201 - Purpose: fill persona fields from onboarding answers 184 202 - Primary input: draft identity/soul markdown, questions, user answer, telegram context 185 203 - Output: `initFillOutput` (identity + soul field values) ··· 188 206 ### 10) Telegram init question message rewriting 189 207 190 208 - File/Function: `cmd/mistermorph/telegramcmd/init_flow.go` / `generateInitQuestionMessage(...)` 209 + - Templates: 210 + - `cmd/mistermorph/telegramcmd/prompts/init_question_message_system.tmpl` 211 + - `cmd/mistermorph/telegramcmd/prompts/init_question_message_user.tmpl` 212 + - Renderer: `cmd/mistermorph/telegramcmd/init_prompts.go` 191 213 - Purpose: rewrite question list into natural conversational Telegram text 192 214 - Primary input: user text + normalized questions 193 215 - Output: plain text message ··· 196 218 ### 11) Telegram post-init greeting generation 197 219 198 220 - File/Function: `cmd/mistermorph/telegramcmd/init_flow.go` / `generatePostInitGreeting(...)` 221 + - Templates: 222 + - `cmd/mistermorph/telegramcmd/prompts/init_post_greeting_system.tmpl` 223 + - `cmd/mistermorph/telegramcmd/prompts/init_post_greeting_user.tmpl` 224 + - Renderer: `cmd/mistermorph/telegramcmd/init_prompts.go` 199 225 - Purpose: generate immediate natural greeting after persona bootstrap 200 226 - Primary input: finalized identity/soul markdown + init context 201 227 - Output: plain text message ··· 252 278 ### 16) Telegram plan-progress message rewriting 253 279 254 280 - File/Function: `cmd/mistermorph/telegramcmd/command.go` / `generateTelegramPlanProgressMessage(...)` 281 + - Templates: 282 + - `cmd/mistermorph/telegramcmd/prompts/plan_progress_system.tmpl` 283 + - `cmd/mistermorph/telegramcmd/prompts/plan_progress_user.tmpl` 284 + - Renderer: `cmd/mistermorph/telegramcmd/plan_progress_prompts.go` 255 285 - Purpose: rewrite step progress into short casual Telegram updates 256 286 - Primary input: task text, plan summary/progress stats, completed/next step info 257 287 - Output: plain text message