create-claude-kanban 2.0.4 → 3.1.0
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/dist/index.js +1066 -379
- package/package.json +1 -1
- package/templates/kanban.cjs +197 -1
- package/templates/kanban.html +569 -4
package/dist/index.js
CHANGED
|
@@ -6,33 +6,678 @@ import pc from "picocolors";
|
|
|
6
6
|
|
|
7
7
|
// src/prompts/project-info.ts
|
|
8
8
|
import * as p from "@clack/prompts";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
]
|
|
9
|
+
|
|
10
|
+
// src/i18n.ts
|
|
11
|
+
var lang = "en";
|
|
12
|
+
function setLang(l) {
|
|
13
|
+
lang = l;
|
|
14
|
+
}
|
|
15
|
+
function t(key, vars) {
|
|
16
|
+
let msg = messages[lang]?.[key] ?? key;
|
|
17
|
+
if (vars) {
|
|
18
|
+
for (const [k, v] of Object.entries(vars)) {
|
|
19
|
+
msg = msg.replaceAll(`{${k}}`, String(v));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return msg;
|
|
23
|
+
}
|
|
24
|
+
var messages = {
|
|
25
|
+
ko: {
|
|
26
|
+
// ─── common ───
|
|
27
|
+
"common.cancelled": "\uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.",
|
|
28
|
+
"common.error": "\uC624\uB958\uAC00 \uBC1C\uC0DD\uD588\uC2B5\uB2C8\uB2E4.",
|
|
29
|
+
"common.none": "\uC5C6\uC74C",
|
|
30
|
+
"common.noneParens": "(\uC5C6\uC74C)",
|
|
31
|
+
// ─── index.ts ───
|
|
32
|
+
"index.filesHeader": "\uC0DD\uC131 \uC644\uB8CC",
|
|
33
|
+
"index.fileKanbanServer": "\uCE78\uBC18 \uC11C\uBC84 (\uBA40\uD2F0\uD504\uB85C\uC81D\uD2B8)",
|
|
34
|
+
"index.fileKanbanUI": "\uCE78\uBC18 UI (\uD504\uB85C\uC81D\uD2B8 \uD0ED)",
|
|
35
|
+
"index.fileConfig": "\uC124\uC815 \uD30C\uC77C (\uD504\uB85C\uC81D\uD2B8 {count}\uAC1C)",
|
|
36
|
+
"index.fileAgents": "\uC5D0\uC774\uC804\uD2B8 \uD504\uB86C\uD504\uD2B8 {count}\uAC1C",
|
|
37
|
+
"index.fileContext": "\uD504\uB85C\uC81D\uD2B8 \uCEE8\uD14D\uC2A4\uD2B8",
|
|
38
|
+
"index.fileOrchestrator": "\uC624\uCF00\uC2A4\uD2B8\uB808\uC774\uD130 \uC124\uC815",
|
|
39
|
+
"index.fileEnv": "\uD658\uACBD\uBCC0\uC218 \uD15C\uD50C\uB9BF",
|
|
40
|
+
"index.startCmd": "\uB85C \uC2DC\uC791\uD558\uC138\uC694!",
|
|
41
|
+
// ─── scaffold.ts ───
|
|
42
|
+
"scaffold.dirCreating": "\uB514\uB809\uD1A0\uB9AC \uC0DD\uC131 \uC911...",
|
|
43
|
+
"scaffold.dirDone": "\uB514\uB809\uD1A0\uB9AC \uC0DD\uC131 \uC644\uB8CC",
|
|
44
|
+
"scaffold.kanbanServerCopying": "\uCE78\uBC18 \uC11C\uBC84 \uBCF5\uC0AC \uC911...",
|
|
45
|
+
"scaffold.kanbanServerDone": "\uCE78\uBC18 \uC11C\uBC84 \uBCF5\uC0AC \uC644\uB8CC",
|
|
46
|
+
"scaffold.kanbanUICopying": "\uCE78\uBC18 UI \uBCF5\uC0AC \uC911...",
|
|
47
|
+
"scaffold.kanbanUIDone": "\uCE78\uBC18 UI \uBCF5\uC0AC \uC644\uB8CC",
|
|
48
|
+
"scaffold.configCreating": "\uC124\uC815 \uD30C\uC77C \uC0DD\uC131 \uC911...",
|
|
49
|
+
"scaffold.configDone": "\uC124\uC815 \uD30C\uC77C \uC0DD\uC131 \uC644\uB8CC",
|
|
50
|
+
"scaffold.projectListCreating": "\uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D \uC0DD\uC131 \uC911...",
|
|
51
|
+
"scaffold.projectListDone": "\uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D \uC0DD\uC131 \uC644\uB8CC",
|
|
52
|
+
"scaffold.contextCreating": "\uD504\uB85C\uC81D\uD2B8 \uCEE8\uD14D\uC2A4\uD2B8 \uC0DD\uC131 \uC911...",
|
|
53
|
+
"scaffold.contextDone": "\uD504\uB85C\uC81D\uD2B8 \uCEE8\uD14D\uC2A4\uD2B8 \uC0DD\uC131 \uC644\uB8CC",
|
|
54
|
+
"scaffold.agentsCreating": "\uC5D0\uC774\uC804\uD2B8 \uD504\uB86C\uD504\uD2B8 \uC0DD\uC131 \uC911...",
|
|
55
|
+
"scaffold.agentsDone": "\uC5D0\uC774\uC804\uD2B8 \uD504\uB86C\uD504\uD2B8 {count}\uAC1C \uC0DD\uC131 \uC644\uB8CC",
|
|
56
|
+
"scaffold.orchestratorCreating": "\uC624\uCF00\uC2A4\uD2B8\uB808\uC774\uD130 \uC124\uC815 \uC0DD\uC131 \uC911...",
|
|
57
|
+
"scaffold.orchestratorDone": "\uC624\uCF00\uC2A4\uD2B8\uB808\uC774\uD130 \uC124\uC815 \uC0DD\uC131 \uC644\uB8CC",
|
|
58
|
+
"scaffold.envCreating": ".env.example \uC0DD\uC131 \uC911...",
|
|
59
|
+
"scaffold.envDone": ".env.example \uC0DD\uC131 \uC644\uB8CC",
|
|
60
|
+
"scaffold.noConstraints": "(\uC5C6\uC74C)",
|
|
61
|
+
// ─── prompts/project-info.ts ───
|
|
62
|
+
"projectInfo.phase": "Phase 1: \uD504\uB85C\uC81D\uD2B8 \uAE30\uBCF8 \uC815\uBCF4",
|
|
63
|
+
"projectInfo.nameMsg": "\uD504\uB85C\uC81D\uD2B8 \uC774\uB984?",
|
|
64
|
+
"projectInfo.nameValidation": "\uD504\uB85C\uC81D\uD2B8 \uC774\uB984\uC744 \uC785\uB825\uD558\uC138\uC694",
|
|
65
|
+
"projectInfo.descMsg": "\uD55C \uC904 \uC124\uBA85?",
|
|
66
|
+
"projectInfo.descPlaceholder": "\uD504\uB85C\uC81D\uD2B8 \uAC04\uB2E8 \uC124\uBA85",
|
|
67
|
+
"projectInfo.descValidation": "\uC124\uBA85\uC744 \uC785\uB825\uD558\uC138\uC694",
|
|
68
|
+
"projectInfo.typesMsg": "\uD504\uB85C\uC81D\uD2B8 \uC131\uACA9? (\uBCF5\uC218 \uC120\uD0DD \uAC00\uB2A5)",
|
|
69
|
+
"projectInfo.typeWebApp": "\uC6F9 \uC560\uD50C\uB9AC\uCF00\uC774\uC158 (SPA/SSR)",
|
|
70
|
+
"projectInfo.typeMobile": "\uBAA8\uBC14\uC77C \uC571 (React Native/Flutter)",
|
|
71
|
+
"projectInfo.typeApi": "API \uC11C\uBC84 / \uBC31\uC5D4\uB4DC",
|
|
72
|
+
"projectInfo.typeDataPipeline": "\uB370\uC774\uD130 \uD30C\uC774\uD504\uB77C\uC778",
|
|
73
|
+
"projectInfo.typeAiMl": "AI/ML \uD504\uB85C\uC81D\uD2B8",
|
|
74
|
+
"projectInfo.typeContent": "\uCF58\uD150\uCE20/\uB9C8\uCF00\uD305 \uC0AC\uC774\uD2B8",
|
|
75
|
+
"projectInfo.typeAdmin": "\uC0AC\uB0B4 \uB3C4\uAD6C / \uC5B4\uB4DC\uBBFC",
|
|
76
|
+
"projectInfo.typeLibrary": "\uB77C\uC774\uBE0C\uB7EC\uB9AC / SDK",
|
|
77
|
+
// ─── prompts/tech-stack.ts ───
|
|
78
|
+
"techStack.phase": "Phase 2: \uAE30\uC220 \uC2A4\uD0DD & \uAD6C\uC870",
|
|
79
|
+
"techStack.detectedTech": "\uAC10\uC9C0\uB41C \uAE30\uC220: {techs}",
|
|
80
|
+
"techStack.frontendMsg": "\uD504\uB860\uD2B8\uC5D4\uB4DC \uC2A4\uD0DD?",
|
|
81
|
+
"techStack.frontendNone": "\uC5C6\uC74C (\uBC31\uC5D4\uB4DC only)",
|
|
82
|
+
"techStack.backendMsg": "\uBC31\uC5D4\uB4DC / \uC778\uD504\uB77C? (\uBCF5\uC218 \uC120\uD0DD)",
|
|
83
|
+
"techStack.deployMsg": "\uBC30\uD3EC \uD658\uACBD?",
|
|
84
|
+
"techStack.deployDocker": "Docker \uC790\uCCB4 \uC11C\uBC84",
|
|
85
|
+
"techStack.deployUndecided": "\uC544\uC9C1 \uBBF8\uC815",
|
|
86
|
+
"techStack.detectedDirs": "\uAC10\uC9C0\uB41C \uB514\uB809\uD1A0\uB9AC:\n{dirs}",
|
|
87
|
+
"techStack.useDetected": "\uC774 \uAD6C\uC870\uB97C \uADF8\uB300\uB85C \uC0AC\uC6A9\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
|
|
88
|
+
"techStack.customDirsMsg": "\uB514\uB809\uD1A0\uB9AC \uAD6C\uC870 (\uC27C\uD45C \uAD6C\uBD84, \uC608: src/:\uC18C\uC2A4,docs/:\uBB38\uC11C)",
|
|
89
|
+
"techStack.customDirsPlaceholder": "src/:\uC18C\uC2A4 \uCF54\uB4DC, docs/:\uBB38\uC11C, tests/:\uD14C\uC2A4\uD2B8",
|
|
90
|
+
"techStack.mainDirsMsg": "\uC8FC\uC694 \uB514\uB809\uD1A0\uB9AC \uAD6C\uC870 (\uC27C\uD45C \uAD6C\uBD84, \uC608: src/:\uC18C\uC2A4,docs/:\uBB38\uC11C)",
|
|
91
|
+
// ─── prompts/context-files.ts ───
|
|
92
|
+
"contextFiles.phase": "Phase 3: \uAE30\uC874 \uCEE8\uD14D\uC2A4\uD2B8 \uD30C\uC77C",
|
|
93
|
+
"contextFiles.hasClaudeMdMsg": "CLAUDE.md \uB610\uB294 \uD504\uB85C\uC81D\uD2B8 \uAC00\uC774\uB4DC \uD30C\uC77C\uC774 \uC788\uB098\uC694?",
|
|
94
|
+
"contextFiles.hasClaudeMdYes": "\uC788\uC74C \u2192 \uACBD\uB85C \uC785\uB825",
|
|
95
|
+
"contextFiles.hasClaudeMdNo": "\uC5C6\uC74C \u2192 \uCD94\uAC00 \uC9C8\uBB38\uC73C\uB85C \uC218\uC9D1",
|
|
96
|
+
"contextFiles.claudeMdPathMsg": "CLAUDE.md \uACBD\uB85C?",
|
|
97
|
+
"contextFiles.fileNotFound": "\uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: {path}",
|
|
98
|
+
"contextFiles.summaryStack": "\uC2A4\uD0DD: {value}",
|
|
99
|
+
"contextFiles.summaryBackend": "\uBC31\uC5D4\uB4DC: {value}",
|
|
100
|
+
"contextFiles.summaryNaming": "\uB124\uC774\uBC0D: {value}",
|
|
101
|
+
"contextFiles.summaryTools": "\uB3C4\uAD6C: {value}",
|
|
102
|
+
"contextFiles.summaryFonts": "\uD3F0\uD2B8: {value}",
|
|
103
|
+
"contextFiles.parseSuccess": "\uD30C\uC77C \uBD84\uC11D \uC644\uB8CC:\n {summary}\n \u2192 \uC5D0\uC774\uC804\uD2B8 \uD504\uB86C\uD504\uD2B8\uC5D0 \uC790\uB3D9 \uBC18\uC601\uB429\uB2C8\uB2E4.",
|
|
104
|
+
"contextFiles.parseEmpty": "\uD30C\uC77C\uC744 \uC77D\uC5C8\uC9C0\uB9CC \uC790\uB3D9 \uD30C\uC2F1\uD560 \uD56D\uBAA9\uC774 \uC5C6\uC5C8\uC2B5\uB2C8\uB2E4. \uC218\uB3D9 \uC9C8\uBB38\uC744 \uC9C4\uD589\uD569\uB2C8\uB2E4.",
|
|
105
|
+
"contextFiles.parseError": "\uD30C\uC77C \uD30C\uC2F1 \uC911 \uC624\uB958 \uBC1C\uC0DD. \uC218\uB3D9 \uC9C8\uBB38\uC73C\uB85C \uC804\uD658\uD569\uB2C8\uB2E4.",
|
|
106
|
+
"contextFiles.codingStyleMsg": "\uCF54\uB529 \uC2A4\uD0C0\uC77C \uC120\uD638? (\uBCF5\uC218 \uC120\uD0DD)",
|
|
107
|
+
"contextFiles.concernsMsg": "\uC8FC\uC758\uD574\uC57C \uD560 \uC0AC\uD56D? (\uBCF5\uC218 \uC120\uD0DD)",
|
|
108
|
+
"contextFiles.refDocsMsg": "\uCD94\uAC00 \uCC38\uACE0 \uBB38\uC11C\uAC00 \uC788\uB098\uC694? (\uBCF5\uC218 \uC120\uD0DD)",
|
|
109
|
+
"contextFiles.docPathMsg": "{type} \uD30C\uC77C \uACBD\uB85C?",
|
|
110
|
+
"contextFiles.docPathValidation": "\uACBD\uB85C\uB97C \uC785\uB825\uD558\uC138\uC694",
|
|
111
|
+
// coding style options
|
|
112
|
+
"contextFiles.styleFunctional": "\uD568\uC218\uD615 \uCEF4\uD3EC\uB10C\uD2B8 only (\uD074\uB798\uC2A4 \uAE08\uC9C0)",
|
|
113
|
+
"contextFiles.styleNamedExport": "Named export \uC120\uD638",
|
|
114
|
+
"contextFiles.styleNoAny": "any \uD0C0\uC785 \uAE08\uC9C0 (unknown \uC120\uD638)",
|
|
115
|
+
"contextFiles.styleKoComment": "\uD55C\uAD6D\uC5B4 \uC8FC\uC11D / \uD55C\uAD6D\uC5B4 \uCEE4\uBC0B",
|
|
116
|
+
"contextFiles.styleEnComment": "\uC601\uBB38 \uC8FC\uC11D / \uC601\uBB38 \uCEE4\uBC0B",
|
|
117
|
+
"contextFiles.styleJsdoc": "JSDoc \uC8FC\uC11D",
|
|
118
|
+
"contextFiles.styleEslint": "ESLint + Prettier \uC801\uC6A9",
|
|
119
|
+
"contextFiles.styleDefault": "\uAE30\uBCF8\uAC12 \uC0AC\uC6A9 (\uBCC4\uB3C4 \uC120\uD638 \uC5C6\uC74C)",
|
|
120
|
+
// concern options
|
|
121
|
+
"contextFiles.concernI18n": "\uB2E4\uAD6D\uC5B4 \uC9C0\uC6D0 (i18n)",
|
|
122
|
+
"contextFiles.concernDarkMode": "\uB2E4\uD06C\uBAA8\uB4DC",
|
|
123
|
+
"contextFiles.concernA11y": "\uC811\uADFC\uC131 (a11y)",
|
|
124
|
+
"contextFiles.concernSeo": "SEO \uCD5C\uC801\uD654",
|
|
125
|
+
"contextFiles.concernPerformance": "\uC131\uB2A5 \uCD5C\uC801\uD654 (Core Web Vitals)",
|
|
126
|
+
"contextFiles.concernSecurity": "\uBCF4\uC548 (\uC778\uC99D/\uAD8C\uD55C/XSS/CSRF)",
|
|
127
|
+
"contextFiles.concernResponsive": "\uBAA8\uBC14\uC77C \uBC18\uC751\uD615 \uD544\uC218",
|
|
128
|
+
"contextFiles.concernNone": "\uC5C6\uC74C",
|
|
129
|
+
// reference doc options
|
|
130
|
+
"contextFiles.refApiSpec": "API \uBA85\uC138 (OpenAPI/Swagger)",
|
|
131
|
+
"contextFiles.refDesignSystem": "\uB514\uC790\uC778 \uC2DC\uC2A4\uD15C \uBB38\uC11C",
|
|
132
|
+
"contextFiles.refDbSchema": "DB \uC2A4\uD0A4\uB9C8 / ERD",
|
|
133
|
+
"contextFiles.refWbs": "\uAE30\uC874 WBS / \uD0DC\uC2A4\uD06C \uBAA9\uB85D",
|
|
134
|
+
"contextFiles.refBrandGuide": "\uBE0C\uB79C\uB4DC \uAC00\uC774\uB4DC\uB77C\uC778",
|
|
135
|
+
"contextFiles.refNone": "\uC5C6\uC74C",
|
|
136
|
+
// ─── prompts/agents.ts ───
|
|
137
|
+
"agents.phase": "Phase 4: \uC5D0\uC774\uC804\uD2B8 \uAD6C\uC131",
|
|
138
|
+
"agents.workTypeMsg": "\uC5B4\uB5A4 \uC791\uC5C5\uC744 \uC8FC\uB85C \uD558\uC2DC\uB098\uC694? (\uBCF5\uC218 \uC120\uD0DD)",
|
|
139
|
+
"agents.recommended": "\uC791\uC5C5 \uC720\uD615 \uAE30\uBC18 \uCD94\uCC9C \uC5D0\uC774\uC804\uD2B8:\n{list}\n \u25FC orchestrator \u2190 \uD56D\uC0C1 \uD3EC\uD568",
|
|
140
|
+
"agents.customizeMsg": "\uC5D0\uC774\uC804\uD2B8\uB97C \uCD94\uAC00/\uC81C\uAC70\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
|
|
141
|
+
"agents.selectMsg": "\uCD5C\uC885 \uC5D0\uC774\uC804\uD2B8 \uC120\uD0DD (orchestrator\uB294 \uD56D\uC0C1 \uD3EC\uD568)",
|
|
142
|
+
"agents.modelMsg": "\uC5D0\uC774\uC804\uD2B8 \uBAA8\uB378 \uAE30\uBCF8\uAC12?",
|
|
143
|
+
// work type options
|
|
144
|
+
"agents.workFrontend": "\uD504\uB860\uD2B8\uC5D4\uB4DC \uAC1C\uBC1C (UI/\uCEF4\uD3EC\uB10C\uD2B8)",
|
|
145
|
+
"agents.workBackend": "\uBC31\uC5D4\uB4DC \uAC1C\uBC1C (API/DB/\uC11C\uBC84)",
|
|
146
|
+
"agents.workQa": "\uD14C\uC2A4\uD2B8/QA (\uC720\uB2DB/E2E/\uC131\uB2A5)",
|
|
147
|
+
"agents.workDesign": "\uB514\uC790\uC778 \uC2DC\uC2A4\uD15C \uAD00\uB9AC",
|
|
148
|
+
"agents.workDevops": "DevOps / CI\xB7CD / \uBC30\uD3EC",
|
|
149
|
+
"agents.workResearch": "\uC870\uC0AC/\uBD84\uC11D/\uB9AC\uC11C\uCE58",
|
|
150
|
+
"agents.workDocs": "\uBB38\uC11C \uC791\uC131",
|
|
151
|
+
"agents.workContent": "\uCF58\uD150\uCE20 \uAE30\uD68D",
|
|
152
|
+
"agents.workStrategy": "\uC804\uB7B5/\uC544\uD0A4\uD14D\uCC98 \uC124\uACC4",
|
|
153
|
+
"agents.workItems": "\uBB38\uD56D/\uD034\uC988 \uAC1C\uBC1C",
|
|
154
|
+
// agent options
|
|
155
|
+
"agents.agentFrontend": "frontend \u2014 \uD504\uB860\uD2B8\uC5D4\uB4DC \uAC1C\uBC1C",
|
|
156
|
+
"agents.agentBackend": "backend \u2014 \uBC31\uC5D4\uB4DC \uAC1C\uBC1C",
|
|
157
|
+
"agents.agentQa": "qa \u2014 \uD14C\uC2A4\uD2B8/\uD488\uC9C8",
|
|
158
|
+
"agents.agentDesigner": "designer \u2014 \uB514\uC790\uC778 \uC2DC\uC2A4\uD15C",
|
|
159
|
+
"agents.agentDevops": "devops \u2014 \uC778\uD504\uB77C/\uBC30\uD3EC",
|
|
160
|
+
"agents.agentResearcher": "researcher \u2014 \uC870\uC0AC/\uBD84\uC11D",
|
|
161
|
+
"agents.agentStrategist": "strategist \u2014 \uC544\uD0A4\uD14D\uCC98/\uC804\uB7B5",
|
|
162
|
+
"agents.agentContentPlanner": "content-planner \u2014 \uCF58\uD150\uCE20 \uAE30\uD68D",
|
|
163
|
+
"agents.agentItemAuthor": "item-author \u2014 \uBB38\uD56D \uAC1C\uBC1C",
|
|
164
|
+
"agents.agentDocWriter": "doc-writer \u2014 \uBB38\uC11C \uC791\uC131",
|
|
165
|
+
// model options
|
|
166
|
+
"agents.modelSonnet": "sonnet (\uB300\uBD80\uBD84) + opus (orchestrator/strategist \uC790\uB3D9)",
|
|
167
|
+
"agents.modelOpus": "\uC804\uBD80 opus (\uACE0\uD488\uC9C8, \uBE44\uC6A9 \uB192\uC74C)",
|
|
168
|
+
"agents.modelSonnetOnly": "\uC804\uBD80 sonnet (\uADE0\uD615)",
|
|
169
|
+
// ─── prompts/orchestrator.ts ───
|
|
170
|
+
"orchestrator.phase": "Phase 5: \uC624\uCF00\uC2A4\uD2B8\uB808\uC774\uD130 \uCEE8\uD14D\uC2A4\uD2B8",
|
|
171
|
+
"orchestrator.goalsMsg": "{name} \uC624\uCF00\uC2A4\uD2B8\uB808\uC774\uD130\uAC00 \uC54C\uC544\uC57C \uD560 \uD504\uB85C\uC81D\uD2B8 \uBAA9\uD45C\uB294?",
|
|
172
|
+
"orchestrator.goalsPlaceholder": "\uC608: 2026\uB144 4\uC6D4 \uB860\uCE6D, \uACB0\uC81C \uC5F0\uB3D9 \uC644\uB8CC \uD544\uC218, \uBAA8\uBC14\uC77C \uBC18\uC751\uD615",
|
|
173
|
+
"orchestrator.goalsValidation": "\uBAA9\uD45C\uB97C \uC785\uB825\uD558\uC138\uC694",
|
|
174
|
+
"orchestrator.stageMsg": "\uD604\uC7AC \uD504\uB85C\uC81D\uD2B8 \uB2E8\uACC4\uB294?",
|
|
175
|
+
"orchestrator.constraintsMsg": "\uC791\uC5C5 \uC6B0\uC120\uC21C\uC704 \uB610\uB294 \uC81C\uC57D\uC0AC\uD56D? (\uC5C6\uC73C\uBA74 \uC5D4\uD130)",
|
|
176
|
+
"orchestrator.constraintsPlaceholder": "\uC608: .env \uCEE4\uBC0B \uAE08\uC9C0, \uD14C\uC2A4\uD2B8 \uCEE4\uBC84\uB9AC\uC9C0 80% \uC720\uC9C0",
|
|
177
|
+
// stage options
|
|
178
|
+
"orchestrator.stageIdea": "\uC544\uC774\uB514\uC5B4/\uAE30\uD68D \uB2E8\uACC4",
|
|
179
|
+
"orchestrator.stageDevPreMvp": "\uAC1C\uBC1C \uC9C4\uD589 \uC911 (MVP \uC804)",
|
|
180
|
+
"orchestrator.stageMvpDone": "MVP \uC644\uC131, \uAC1C\uC120 \uC911",
|
|
181
|
+
"orchestrator.stageProduction": "\uC6B4\uC601 \uC911 (\uC720\uC9C0\uBCF4\uC218/\uAE30\uB2A5 \uCD94\uAC00)",
|
|
182
|
+
"orchestrator.stageRefactor": "\uB9AC\uD329\uD1A0\uB9C1/\uB9C8\uC774\uADF8\uB808\uC774\uC158",
|
|
183
|
+
// ─── prompts/multi-project.ts ───
|
|
184
|
+
"multiProject.phase": "Phase 6: \uBA40\uD2F0\uD504\uB85C\uC81D\uD2B8 (\uC120\uD0DD)",
|
|
185
|
+
"multiProject.addMoreMsg": "\uCD94\uAC00 \uD504\uB85C\uC81D\uD2B8\uB97C \uB4F1\uB85D\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
|
|
186
|
+
"multiProject.addMoreNo": "\uC9C0\uAE08\uC740 1\uAC1C\uB9CC",
|
|
187
|
+
"multiProject.addMoreYes": "\uCD94\uAC00 \uB4F1\uB85D",
|
|
188
|
+
"multiProject.nameMsg": "\uCD94\uAC00 \uD504\uB85C\uC81D\uD2B8 \uC774\uB984?",
|
|
189
|
+
"multiProject.namePlaceholder": "\uD504\uB85C\uC81D\uD2B8 \uC774\uB984",
|
|
190
|
+
"multiProject.nameValidation": "\uC774\uB984\uC744 \uC785\uB825\uD558\uC138\uC694",
|
|
191
|
+
"multiProject.descMsg": "\uD55C \uC904 \uC124\uBA85?",
|
|
192
|
+
"multiProject.descPlaceholder": "\uD504\uB85C\uC81D\uD2B8 \uC124\uBA85",
|
|
193
|
+
"multiProject.colorMsg": "\uD0DC\uADF8 \uC0C9\uC0C1?",
|
|
194
|
+
"multiProject.agentMsg": "\uC5D0\uC774\uC804\uD2B8 \uAD6C\uC131?",
|
|
195
|
+
"multiProject.agentShared": "\uAE30\uBCF8 \uD504\uB85C\uC81D\uD2B8\uC640 \uB3D9\uC77C\uD55C \uC5D0\uC774\uC804\uD2B8 \uACF5\uC720",
|
|
196
|
+
"multiProject.agentSeparate": "\uC774 \uD504\uB85C\uC81D\uD2B8 \uC804\uC6A9 \uC5D0\uC774\uC804\uD2B8 \uBCC4\uB3C4 \uAD6C\uC131",
|
|
197
|
+
"multiProject.anotherMsg": "\uB610 \uB2E4\uB978 \uD504\uB85C\uC81D\uD2B8\uB97C \uCD94\uAC00\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
|
|
198
|
+
// color labels
|
|
199
|
+
"multiProject.colorBlue": "\uD30C\uB791",
|
|
200
|
+
"multiProject.colorGreen": "\uCD08\uB85D",
|
|
201
|
+
"multiProject.colorOrange": "\uC8FC\uD669",
|
|
202
|
+
"multiProject.colorPurple": "\uBCF4\uB77C",
|
|
203
|
+
"multiProject.colorRed": "\uBE68\uAC15",
|
|
204
|
+
"multiProject.colorPink": "\uBD84\uD64D",
|
|
205
|
+
"multiProject.colorTeal": "\uCCAD\uB85D",
|
|
206
|
+
// ─── prompts/infra.ts ───
|
|
207
|
+
"infra.phase": "Phase 7: \uC778\uD504\uB77C",
|
|
208
|
+
"infra.slackMsg": "Slack \uC5F0\uB3D9?",
|
|
209
|
+
"infra.slackYes": "\uC5F0\uB3D9\uD568 (Bot Token + Socket Mode)",
|
|
210
|
+
"infra.slackNo": "\uB098\uC911\uC5D0 \uC124\uC815",
|
|
211
|
+
"infra.slackCommandMsg": "Slack \uCEE4\uB9E8\uB4DC \uC774\uB984?",
|
|
212
|
+
"infra.portMsg": "\uCE78\uBC18 \uC11C\uBC84 \uD3EC\uD2B8?",
|
|
213
|
+
"infra.portValidation": "\uC720\uD6A8\uD55C \uD3EC\uD2B8 \uBC88\uD638\uB97C \uC785\uB825\uD558\uC138\uC694 (1-65535)",
|
|
214
|
+
"infra.targetDirMsg": "\uD30C\uC77C\uC744 \uC5B4\uB514\uC5D0 \uC0DD\uC131\uD560\uAE4C\uC694?",
|
|
215
|
+
"infra.targetDirPlaceholder": "(\uD604\uC7AC \uB514\uB809\uD1A0\uB9AC)",
|
|
216
|
+
// ─── generators/env-file.ts ───
|
|
217
|
+
"envGen.kanbanServer": "# \uCE78\uBC18 \uC11C\uBC84",
|
|
218
|
+
"envGen.slackIntegration": "# Slack \uC5F0\uB3D9",
|
|
219
|
+
"envGen.slackLater": "# Slack \uC5F0\uB3D9 (\uB098\uC911\uC5D0 \uC124\uC815)",
|
|
220
|
+
// ─── generators/project-context.ts ───
|
|
221
|
+
// frontend labels
|
|
222
|
+
"contextGen.frontendNone": "(\uC5C6\uC74C)",
|
|
223
|
+
// deploy labels
|
|
224
|
+
"contextGen.deployDocker": "Docker \uC790\uCCB4 \uC11C\uBC84",
|
|
225
|
+
"contextGen.deployUndecided": "\uBBF8\uC815",
|
|
226
|
+
// stage labels
|
|
227
|
+
"contextGen.stageIdea": "\uC544\uC774\uB514\uC5B4/\uAE30\uD68D \uB2E8\uACC4",
|
|
228
|
+
"contextGen.stageDevPreMvp": "\uAC1C\uBC1C \uC9C4\uD589 \uC911 (MVP \uC804)",
|
|
229
|
+
"contextGen.stageMvpDone": "MVP \uC644\uC131, \uAC1C\uC120 \uC911",
|
|
230
|
+
"contextGen.stageProduction": "\uC6B4\uC601 \uC911 (\uC720\uC9C0\uBCF4\uC218/\uAE30\uB2A5 \uCD94\uAC00)",
|
|
231
|
+
"contextGen.stageRefactor": "\uB9AC\uD329\uD1A0\uB9C1/\uB9C8\uC774\uADF8\uB808\uC774\uC158",
|
|
232
|
+
// project type labels
|
|
233
|
+
"contextGen.typeWebApp": "\uC6F9 \uC560\uD50C\uB9AC\uCF00\uC774\uC158",
|
|
234
|
+
"contextGen.typeMobile": "\uBAA8\uBC14\uC77C \uC571",
|
|
235
|
+
"contextGen.typeApi": "API \uC11C\uBC84",
|
|
236
|
+
"contextGen.typeDataPipeline": "\uB370\uC774\uD130 \uD30C\uC774\uD504\uB77C\uC778",
|
|
237
|
+
"contextGen.typeAiMl": "AI/ML",
|
|
238
|
+
"contextGen.typeContent": "\uCF58\uD150\uCE20/\uB9C8\uCF00\uD305",
|
|
239
|
+
"contextGen.typeAdmin": "\uC0AC\uB0B4 \uB3C4\uAD6C",
|
|
240
|
+
"contextGen.typeLibrary": "\uB77C\uC774\uBE0C\uB7EC\uB9AC/SDK",
|
|
241
|
+
// coding style labels
|
|
242
|
+
"contextGen.styleFunctional": "\uD568\uC218\uD615 \uCEF4\uD3EC\uB10C\uD2B8 only (\uD074\uB798\uC2A4 \uAE08\uC9C0)",
|
|
243
|
+
"contextGen.styleNamedExport": "Named export \uC120\uD638",
|
|
244
|
+
"contextGen.styleNoAny": "any \uD0C0\uC785 \uAE08\uC9C0 (unknown \uC120\uD638)",
|
|
245
|
+
"contextGen.styleKoComment": "\uD55C\uAD6D\uC5B4 \uC8FC\uC11D / \uD55C\uAD6D\uC5B4 \uCEE4\uBC0B",
|
|
246
|
+
"contextGen.styleEnComment": "\uC601\uBB38 \uC8FC\uC11D / \uC601\uBB38 \uCEE4\uBC0B",
|
|
247
|
+
"contextGen.styleJsdoc": "JSDoc \uC8FC\uC11D",
|
|
248
|
+
"contextGen.styleEslint": "ESLint + Prettier \uC801\uC6A9",
|
|
249
|
+
"contextGen.styleDefault": "\uAE30\uBCF8\uAC12 \uC0AC\uC6A9",
|
|
250
|
+
// concern labels
|
|
251
|
+
"contextGen.concernI18n": "\uB2E4\uAD6D\uC5B4 \uC9C0\uC6D0 (i18n)",
|
|
252
|
+
"contextGen.concernDarkMode": "\uB2E4\uD06C\uBAA8\uB4DC",
|
|
253
|
+
"contextGen.concernA11y": "\uC811\uADFC\uC131 (a11y)",
|
|
254
|
+
"contextGen.concernSeo": "SEO \uCD5C\uC801\uD654",
|
|
255
|
+
"contextGen.concernPerformance": "\uC131\uB2A5 \uCD5C\uC801\uD654 (Core Web Vitals)",
|
|
256
|
+
"contextGen.concernSecurity": "\uBCF4\uC548 (\uC778\uC99D/\uAD8C\uD55C/XSS/CSRF)",
|
|
257
|
+
"contextGen.concernResponsive": "\uBAA8\uBC14\uC77C \uBC18\uC751\uD615 \uD544\uC218",
|
|
258
|
+
"contextGen.concernNone": "\uC5C6\uC74C",
|
|
259
|
+
// generated document sections
|
|
260
|
+
"contextGen.title": "{name} \u2014 \uD504\uB85C\uC81D\uD2B8 \uCEE8\uD14D\uC2A4\uD2B8",
|
|
261
|
+
"contextGen.intro": "\uC774 \uBB38\uC11C\uB294 \uBAA8\uB4E0 \uC5D0\uC774\uC804\uD2B8\uAC00 \uACF5\uC720\uD558\uB294 \uD504\uB85C\uC81D\uD2B8 \uAE30\uBCF8 \uC815\uBCF4\uB2E4.\n\uAC01 \uC5D0\uC774\uC804\uD2B8\uB294 \uC774 \uBB38\uC11C\uB97C \uC219\uC9C0\uD55C \uC0C1\uD0DC\uC5D0\uC11C \uC790\uAE30 \uC5ED\uD560\uC744 \uC218\uD589\uD55C\uB2E4.",
|
|
262
|
+
"contextGen.sectionOverview": "\uD504\uB85C\uC81D\uD2B8 \uAC1C\uC694",
|
|
263
|
+
"contextGen.labelType": "\uC131\uACA9",
|
|
264
|
+
"contextGen.labelStage": "\uB2E8\uACC4",
|
|
265
|
+
"contextGen.sectionStack": "\uAE30\uC220 \uC2A4\uD0DD",
|
|
266
|
+
"contextGen.labelFrontend": "\uD504\uB860\uD2B8\uC5D4\uB4DC",
|
|
267
|
+
"contextGen.backendFallback": "(\uC9C1\uC811 \uC785\uB825\uD558\uC138\uC694)",
|
|
268
|
+
"contextGen.labelDeploy": "\uBC30\uD3EC",
|
|
269
|
+
"contextGen.sectionDirs": "\uB514\uB809\uD1A0\uB9AC \uAD6C\uC870",
|
|
270
|
+
"contextGen.defaultDirSrc": "\uC18C\uC2A4 \uCF54\uB4DC",
|
|
271
|
+
"contextGen.defaultDirDocs": "\uBB38\uC11C",
|
|
272
|
+
"contextGen.defaultDirTools": "\uAC1C\uBC1C \uB3C4\uAD6C",
|
|
273
|
+
"contextGen.sectionConventions": "\uCF54\uB529 \uCEE8\uBCA4\uC158",
|
|
274
|
+
"contextGen.noConventionsClaudeMd": "(CLAUDE.md\uC5D0\uC11C \uC790\uB3D9 \uCD94\uCD9C\uB41C \uCEE8\uBCA4\uC158 \uC5C6\uC74C)",
|
|
275
|
+
"contextGen.noConventionsManual": "(\uD504\uB85C\uC81D\uD2B8\uC5D0 \uB9DE\uAC8C \uC218\uC815\uD558\uC138\uC694)",
|
|
276
|
+
"contextGen.sectionBrand": "\uBE0C\uB79C\uB4DC/\uB514\uC790\uC778",
|
|
277
|
+
"contextGen.labelFonts": "\uD3F0\uD2B8",
|
|
278
|
+
"contextGen.labelColors": "\uC0C9\uC0C1",
|
|
279
|
+
"contextGen.labelI18n": "\uB2E4\uAD6D\uC5B4",
|
|
280
|
+
"contextGen.sectionGoals": "\uD504\uB85C\uC81D\uD2B8 \uBAA9\uD45C",
|
|
281
|
+
"contextGen.goalsPlaceholder": "(\uBAA9\uD45C\uB97C \uC785\uB825\uD558\uC138\uC694)",
|
|
282
|
+
"contextGen.sectionConstraints": "\uC81C\uC57D\uC0AC\uD56D",
|
|
283
|
+
"contextGen.constraintsPlaceholder": "(\uC81C\uC57D\uC0AC\uD56D \uC5C6\uC74C)",
|
|
284
|
+
"contextGen.sectionRefDocs": "\uCC38\uACE0 \uBB38\uC11C",
|
|
285
|
+
"contextGen.noRefDocs": "(\uC5C6\uC74C)",
|
|
286
|
+
"contextGen.sectionProtocol": "\uC791\uC5C5 \uD504\uB85C\uD1A0\uCF5C",
|
|
287
|
+
"contextGen.protocolKanban": "\uCE78\uBC18 \uC11C\uBC84",
|
|
288
|
+
"contextGen.protocolSlack": "Slack \uBCF4\uACE0",
|
|
289
|
+
"contextGen.protocolLogs": "\uB85C\uADF8 \uB514\uB809\uD1A0\uB9AC",
|
|
290
|
+
"contextGen.protocolStatus": "\uC0C1\uD0DC \uD50C\uB85C\uC6B0",
|
|
291
|
+
"contextGen.protocolInstruction": "\uBAA8\uB4E0 \uC5D0\uC774\uC804\uD2B8\uB294 \uC791\uC5C5 \uC2DC\uC791/\uC644\uB8CC \uC2DC \uB2E4\uC74C 3\uACF3\uC5D0 \uAE30\uB85D\uC744 \uB0A8\uAE34\uB2E4:",
|
|
292
|
+
"contextGen.protocolSlackReport": "Slack \uBCF4\uACE0",
|
|
293
|
+
"contextGen.protocolKanbanUpdate": "\uCE78\uBC18 \uC5C5\uB370\uC774\uD2B8",
|
|
294
|
+
"contextGen.protocolLogFile": "\uB85C\uADF8 \uD30C\uC77C",
|
|
295
|
+
"contextGen.protocolSlackExample": "\uBA54\uC2DC\uC9C0",
|
|
296
|
+
// ─── generators/agent-prompt.ts (base sections only) ───
|
|
297
|
+
"agentGen.projectLabel": "\uD504\uB85C\uC81D\uD2B8",
|
|
298
|
+
"agentGen.descLabel": "\uC124\uBA85",
|
|
299
|
+
"agentGen.kanbanApiLabel": "\uCE78\uBC18 API",
|
|
300
|
+
"agentGen.slackApiLabel": "Slack API",
|
|
301
|
+
"agentGen.logDirLabel": "\uB85C\uADF8 \uB514\uB809\uD1A0\uB9AC",
|
|
302
|
+
"agentGen.slackReportingDesc": "\uC791\uC5C5 \uC2DC\uC791\uACFC \uC644\uB8CC \uC2DC Slack\uC5D0 \uBCF4\uACE0\uD55C\uB2E4 (\uD0DC\uC2A4\uD06C \uC2A4\uB808\uB4DC\uB85C \uC790\uB3D9 \uC815\uB9AC):",
|
|
303
|
+
"agentGen.slackForbid": "`$SLACK_AGENT_WEBHOOK` \uC9C1\uC811 \uC0AC\uC6A9 \uAE08\uC9C0. \uBC18\uB4DC\uC2DC \uC704 API\uB97C \uD1B5\uD574 \uBCF4\uACE0.",
|
|
304
|
+
"agentGen.slackTaskIdNote": "`{TASK_ID}`\uB294 buildExecutorPrompt\uC5D0\uC11C \uC2E4\uC81C ID\uAC00 \uC8FC\uC785\uB41C\uB2E4.",
|
|
305
|
+
"agentGen.kanbanStart": "\uC2DC\uC791",
|
|
306
|
+
"agentGen.kanbanDone": "\uC644\uB8CC",
|
|
307
|
+
"agentGen.kanbanActiveForm": "\uC218\uD589 \uC911 \uC124\uBA85",
|
|
308
|
+
"agentGen.kanbanReportFormat": "\uC218\uD589 \uB0B4\uC5ED \uC694\uC57D 1\uC904. \uD6C4\uC18D: \uB2E4\uC74C \uC791\uC5C5 \uC81C\uC548",
|
|
309
|
+
"agentGen.reportDesc": "\uC644\uB8CC \uD6C4 \uBC18\uB4DC\uC2DC \uBCF4\uACE0\uC11C \uC791\uC131:",
|
|
310
|
+
"agentGen.reportPathLabel": "\uACBD\uB85C",
|
|
311
|
+
"agentGen.reportContentDesc": "\uB0B4\uC6A9: \uBCC0\uACBD \uD30C\uC77C \uBAA9\uB85D, \uBCC0\uACBD \uB0B4\uC6A9, \uAC80\uC99D \uACB0\uACFC, \uD6C4\uC18D \uC791\uC5C5",
|
|
312
|
+
"agentGen.fontsLabel": "\uD3F0\uD2B8",
|
|
313
|
+
"agentGen.colorsLabel": "\uC0C9\uC0C1",
|
|
314
|
+
// ─── utils/detect-structure.ts ───
|
|
315
|
+
"detect.src": "\uC18C\uC2A4 \uCF54\uB4DC",
|
|
316
|
+
"detect.app": "\uC571 \uC18C\uC2A4 (Next.js/Remix)",
|
|
317
|
+
"detect.pages": "\uD398\uC774\uC9C0 (Next.js)",
|
|
318
|
+
"detect.components": "\uCEF4\uD3EC\uB10C\uD2B8",
|
|
319
|
+
"detect.lib": "\uB77C\uC774\uBE0C\uB7EC\uB9AC/\uC720\uD2F8",
|
|
320
|
+
"detect.api": "API \uB77C\uC6B0\uD2B8",
|
|
321
|
+
"detect.server": "\uC11C\uBC84 \uCF54\uB4DC",
|
|
322
|
+
"detect.supabase": "Supabase (Edge Functions/\uB9C8\uC774\uADF8\uB808\uC774\uC158)",
|
|
323
|
+
"detect.firebase": "Firebase",
|
|
324
|
+
"detect.prisma": "Prisma \uC2A4\uD0A4\uB9C8",
|
|
325
|
+
"detect.docs": "\uBB38\uC11C",
|
|
326
|
+
"detect.tests": "\uD14C\uC2A4\uD2B8",
|
|
327
|
+
"detect.e2e": "E2E \uD14C\uC2A4\uD2B8",
|
|
328
|
+
"detect.cypress": "Cypress \uD14C\uC2A4\uD2B8",
|
|
329
|
+
"detect.public": "\uC815\uC801 \uD30C\uC77C",
|
|
330
|
+
"detect.static": "\uC815\uC801 \uD30C\uC77C",
|
|
331
|
+
"detect.assets": "\uC5D0\uC14B",
|
|
332
|
+
"detect.styles": "\uC2A4\uD0C0\uC77C",
|
|
333
|
+
"detect.scripts": "\uC2A4\uD06C\uB9BD\uD2B8",
|
|
334
|
+
"detect.tools": "\uAC1C\uBC1C \uB3C4\uAD6C",
|
|
335
|
+
"detect.github": "GitHub Actions"
|
|
336
|
+
},
|
|
337
|
+
en: {
|
|
338
|
+
// ─── common ───
|
|
339
|
+
"common.cancelled": "Cancelled.",
|
|
340
|
+
"common.error": "An error occurred.",
|
|
341
|
+
"common.none": "None",
|
|
342
|
+
"common.noneParens": "(None)",
|
|
343
|
+
// ─── index.ts ───
|
|
344
|
+
"index.filesHeader": "Files created",
|
|
345
|
+
"index.fileKanbanServer": "Kanban server (multi-project)",
|
|
346
|
+
"index.fileKanbanUI": "Kanban UI (project tabs)",
|
|
347
|
+
"index.fileConfig": "Config file ({count} projects)",
|
|
348
|
+
"index.fileAgents": "{count} agent prompts",
|
|
349
|
+
"index.fileContext": "Project context",
|
|
350
|
+
"index.fileOrchestrator": "Orchestrator config",
|
|
351
|
+
"index.fileEnv": "Env template",
|
|
352
|
+
"index.startCmd": "to get started!",
|
|
353
|
+
// ─── scaffold.ts ───
|
|
354
|
+
"scaffold.dirCreating": "Creating directories...",
|
|
355
|
+
"scaffold.dirDone": "Directories created",
|
|
356
|
+
"scaffold.kanbanServerCopying": "Copying kanban server...",
|
|
357
|
+
"scaffold.kanbanServerDone": "Kanban server copied",
|
|
358
|
+
"scaffold.kanbanUICopying": "Copying kanban UI...",
|
|
359
|
+
"scaffold.kanbanUIDone": "Kanban UI copied",
|
|
360
|
+
"scaffold.configCreating": "Generating config...",
|
|
361
|
+
"scaffold.configDone": "Config generated",
|
|
362
|
+
"scaffold.projectListCreating": "Generating project list...",
|
|
363
|
+
"scaffold.projectListDone": "Project list generated",
|
|
364
|
+
"scaffold.contextCreating": "Generating project context...",
|
|
365
|
+
"scaffold.contextDone": "Project context generated",
|
|
366
|
+
"scaffold.agentsCreating": "Generating agent prompts...",
|
|
367
|
+
"scaffold.agentsDone": "{count} agent prompts generated",
|
|
368
|
+
"scaffold.orchestratorCreating": "Generating orchestrator config...",
|
|
369
|
+
"scaffold.orchestratorDone": "Orchestrator config generated",
|
|
370
|
+
"scaffold.envCreating": "Generating .env.example...",
|
|
371
|
+
"scaffold.envDone": ".env.example generated",
|
|
372
|
+
"scaffold.noConstraints": "(None)",
|
|
373
|
+
// ─── prompts/project-info.ts ───
|
|
374
|
+
"projectInfo.phase": "Phase 1: Project basics",
|
|
375
|
+
"projectInfo.nameMsg": "Project name?",
|
|
376
|
+
"projectInfo.nameValidation": "Please enter a project name",
|
|
377
|
+
"projectInfo.descMsg": "One-line description?",
|
|
378
|
+
"projectInfo.descPlaceholder": "Brief project description",
|
|
379
|
+
"projectInfo.descValidation": "Please enter a description",
|
|
380
|
+
"projectInfo.typesMsg": "Project type? (multiple selection)",
|
|
381
|
+
"projectInfo.typeWebApp": "Web application (SPA/SSR)",
|
|
382
|
+
"projectInfo.typeMobile": "Mobile app (React Native/Flutter)",
|
|
383
|
+
"projectInfo.typeApi": "API server / Backend",
|
|
384
|
+
"projectInfo.typeDataPipeline": "Data pipeline",
|
|
385
|
+
"projectInfo.typeAiMl": "AI/ML project",
|
|
386
|
+
"projectInfo.typeContent": "Content/Marketing site",
|
|
387
|
+
"projectInfo.typeAdmin": "Internal tool / Admin",
|
|
388
|
+
"projectInfo.typeLibrary": "Library / SDK",
|
|
389
|
+
// ─── prompts/tech-stack.ts ───
|
|
390
|
+
"techStack.phase": "Phase 2: Tech stack & structure",
|
|
391
|
+
"techStack.detectedTech": "Detected: {techs}",
|
|
392
|
+
"techStack.frontendMsg": "Frontend stack?",
|
|
393
|
+
"techStack.frontendNone": "None (backend only)",
|
|
394
|
+
"techStack.backendMsg": "Backend / Infra? (multiple selection)",
|
|
395
|
+
"techStack.deployMsg": "Deployment?",
|
|
396
|
+
"techStack.deployDocker": "Docker self-hosted",
|
|
397
|
+
"techStack.deployUndecided": "Undecided",
|
|
398
|
+
"techStack.detectedDirs": "Detected directories:\n{dirs}",
|
|
399
|
+
"techStack.useDetected": "Use this structure as-is?",
|
|
400
|
+
"techStack.customDirsMsg": "Directory structure (comma-separated, e.g. src/:source,docs/:docs)",
|
|
401
|
+
"techStack.customDirsPlaceholder": "src/:source code, docs/:docs, tests/:tests",
|
|
402
|
+
"techStack.mainDirsMsg": "Main directory structure (comma-separated, e.g. src/:source,docs/:docs)",
|
|
403
|
+
// ─── prompts/context-files.ts ───
|
|
404
|
+
"contextFiles.phase": "Phase 3: Existing context files",
|
|
405
|
+
"contextFiles.hasClaudeMdMsg": "Do you have a CLAUDE.md or project guide file?",
|
|
406
|
+
"contextFiles.hasClaudeMdYes": "Yes \u2192 enter path",
|
|
407
|
+
"contextFiles.hasClaudeMdNo": "No \u2192 collect via questions",
|
|
408
|
+
"contextFiles.claudeMdPathMsg": "CLAUDE.md path?",
|
|
409
|
+
"contextFiles.fileNotFound": "File not found: {path}",
|
|
410
|
+
"contextFiles.summaryStack": "Stack: {value}",
|
|
411
|
+
"contextFiles.summaryBackend": "Backend: {value}",
|
|
412
|
+
"contextFiles.summaryNaming": "Naming: {value}",
|
|
413
|
+
"contextFiles.summaryTools": "Tools: {value}",
|
|
414
|
+
"contextFiles.summaryFonts": "Fonts: {value}",
|
|
415
|
+
"contextFiles.parseSuccess": "File analysis complete:\n {summary}\n \u2192 Will be auto-applied to agent prompts.",
|
|
416
|
+
"contextFiles.parseEmpty": "File was read but no auto-parsable items found. Proceeding with manual questions.",
|
|
417
|
+
"contextFiles.parseError": "Error parsing file. Switching to manual questions.",
|
|
418
|
+
"contextFiles.codingStyleMsg": "Coding style preferences? (multiple selection)",
|
|
419
|
+
"contextFiles.concernsMsg": "Concerns? (multiple selection)",
|
|
420
|
+
"contextFiles.refDocsMsg": "Any reference docs? (multiple selection)",
|
|
421
|
+
"contextFiles.docPathMsg": "{type} file path?",
|
|
422
|
+
"contextFiles.docPathValidation": "Please enter a path",
|
|
423
|
+
// coding style options
|
|
424
|
+
"contextFiles.styleFunctional": "Functional components only (no classes)",
|
|
425
|
+
"contextFiles.styleNamedExport": "Prefer named exports",
|
|
426
|
+
"contextFiles.styleNoAny": "No 'any' type (prefer unknown)",
|
|
427
|
+
"contextFiles.styleKoComment": "Korean comments / Korean commits",
|
|
428
|
+
"contextFiles.styleEnComment": "English comments / English commits",
|
|
429
|
+
"contextFiles.styleJsdoc": "JSDoc comments",
|
|
430
|
+
"contextFiles.styleEslint": "ESLint + Prettier enabled",
|
|
431
|
+
"contextFiles.styleDefault": "Default (no preference)",
|
|
432
|
+
// concern options
|
|
433
|
+
"contextFiles.concernI18n": "i18n (internationalization)",
|
|
434
|
+
"contextFiles.concernDarkMode": "Dark mode",
|
|
435
|
+
"contextFiles.concernA11y": "Accessibility (a11y)",
|
|
436
|
+
"contextFiles.concernSeo": "SEO optimization",
|
|
437
|
+
"contextFiles.concernPerformance": "Performance (Core Web Vitals)",
|
|
438
|
+
"contextFiles.concernSecurity": "Security (Auth/XSS/CSRF)",
|
|
439
|
+
"contextFiles.concernResponsive": "Mobile responsive required",
|
|
440
|
+
"contextFiles.concernNone": "None",
|
|
441
|
+
// reference doc options
|
|
442
|
+
"contextFiles.refApiSpec": "API spec (OpenAPI/Swagger)",
|
|
443
|
+
"contextFiles.refDesignSystem": "Design system docs",
|
|
444
|
+
"contextFiles.refDbSchema": "DB schema / ERD",
|
|
445
|
+
"contextFiles.refWbs": "Existing WBS / Task list",
|
|
446
|
+
"contextFiles.refBrandGuide": "Brand guidelines",
|
|
447
|
+
"contextFiles.refNone": "None",
|
|
448
|
+
// ─── prompts/agents.ts ───
|
|
449
|
+
"agents.phase": "Phase 4: Agent configuration",
|
|
450
|
+
"agents.workTypeMsg": "What work do you mainly do? (multiple selection)",
|
|
451
|
+
"agents.recommended": "Recommended agents based on work types:\n{list}\n \u25FC orchestrator \u2190 always included",
|
|
452
|
+
"agents.customizeMsg": "Customize agents?",
|
|
453
|
+
"agents.selectMsg": "Final agent selection (orchestrator always included)",
|
|
454
|
+
"agents.modelMsg": "Default agent model?",
|
|
455
|
+
// work type options
|
|
456
|
+
"agents.workFrontend": "Frontend development (UI/components)",
|
|
457
|
+
"agents.workBackend": "Backend development (API/DB/server)",
|
|
458
|
+
"agents.workQa": "Testing/QA (unit/E2E/perf)",
|
|
459
|
+
"agents.workDesign": "Design system management",
|
|
460
|
+
"agents.workDevops": "DevOps / CI\xB7CD / Deploy",
|
|
461
|
+
"agents.workResearch": "Research/Analysis",
|
|
462
|
+
"agents.workDocs": "Documentation",
|
|
463
|
+
"agents.workContent": "Content planning",
|
|
464
|
+
"agents.workStrategy": "Strategy/Architecture design",
|
|
465
|
+
"agents.workItems": "Quiz/Item development",
|
|
466
|
+
// agent options
|
|
467
|
+
"agents.agentFrontend": "frontend \u2014 Frontend dev",
|
|
468
|
+
"agents.agentBackend": "backend \u2014 Backend dev",
|
|
469
|
+
"agents.agentQa": "qa \u2014 Testing/Quality",
|
|
470
|
+
"agents.agentDesigner": "designer \u2014 Design system",
|
|
471
|
+
"agents.agentDevops": "devops \u2014 Infra/Deploy",
|
|
472
|
+
"agents.agentResearcher": "researcher \u2014 Research/Analysis",
|
|
473
|
+
"agents.agentStrategist": "strategist \u2014 Architecture/Strategy",
|
|
474
|
+
"agents.agentContentPlanner": "content-planner \u2014 Content planning",
|
|
475
|
+
"agents.agentItemAuthor": "item-author \u2014 Item authoring",
|
|
476
|
+
"agents.agentDocWriter": "doc-writer \u2014 Documentation",
|
|
477
|
+
// model options
|
|
478
|
+
"agents.modelSonnet": "sonnet (most) + opus (orchestrator/strategist auto)",
|
|
479
|
+
"agents.modelOpus": "All opus (high quality, higher cost)",
|
|
480
|
+
"agents.modelSonnetOnly": "All sonnet (balanced)",
|
|
481
|
+
// ─── prompts/orchestrator.ts ───
|
|
482
|
+
"orchestrator.phase": "Phase 5: Orchestrator context",
|
|
483
|
+
"orchestrator.goalsMsg": "What project goals should the {name} orchestrator know?",
|
|
484
|
+
"orchestrator.goalsPlaceholder": "e.g. Launch April 2026, payment integration required, mobile responsive",
|
|
485
|
+
"orchestrator.goalsValidation": "Please enter goals",
|
|
486
|
+
"orchestrator.stageMsg": "Current project stage?",
|
|
487
|
+
"orchestrator.constraintsMsg": "Priorities or constraints? (Enter to skip)",
|
|
488
|
+
"orchestrator.constraintsPlaceholder": "e.g. No .env commits, maintain 80% test coverage",
|
|
489
|
+
// stage options
|
|
490
|
+
"orchestrator.stageIdea": "Idea/Planning stage",
|
|
491
|
+
"orchestrator.stageDevPreMvp": "Development in progress (pre-MVP)",
|
|
492
|
+
"orchestrator.stageMvpDone": "MVP done, improving",
|
|
493
|
+
"orchestrator.stageProduction": "In production (maintenance/features)",
|
|
494
|
+
"orchestrator.stageRefactor": "Refactoring/Migration",
|
|
495
|
+
// ─── prompts/multi-project.ts ───
|
|
496
|
+
"multiProject.phase": "Phase 6: Multi-project (optional)",
|
|
497
|
+
"multiProject.addMoreMsg": "Add more projects?",
|
|
498
|
+
"multiProject.addMoreNo": "Just one for now",
|
|
499
|
+
"multiProject.addMoreYes": "Add more",
|
|
500
|
+
"multiProject.nameMsg": "Additional project name?",
|
|
501
|
+
"multiProject.namePlaceholder": "Project name",
|
|
502
|
+
"multiProject.nameValidation": "Please enter a name",
|
|
503
|
+
"multiProject.descMsg": "One-line description?",
|
|
504
|
+
"multiProject.descPlaceholder": "Project description",
|
|
505
|
+
"multiProject.colorMsg": "Tag color?",
|
|
506
|
+
"multiProject.agentMsg": "Agent configuration?",
|
|
507
|
+
"multiProject.agentShared": "Share agents with main project",
|
|
508
|
+
"multiProject.agentSeparate": "Separate agents for this project",
|
|
509
|
+
"multiProject.anotherMsg": "Add another project?",
|
|
510
|
+
// color labels
|
|
511
|
+
"multiProject.colorBlue": "Blue",
|
|
512
|
+
"multiProject.colorGreen": "Green",
|
|
513
|
+
"multiProject.colorOrange": "Orange",
|
|
514
|
+
"multiProject.colorPurple": "Purple",
|
|
515
|
+
"multiProject.colorRed": "Red",
|
|
516
|
+
"multiProject.colorPink": "Pink",
|
|
517
|
+
"multiProject.colorTeal": "Teal",
|
|
518
|
+
// ─── prompts/infra.ts ───
|
|
519
|
+
"infra.phase": "Phase 7: Infrastructure",
|
|
520
|
+
"infra.slackMsg": "Slack integration?",
|
|
521
|
+
"infra.slackYes": "Enable (Bot Token + Socket Mode)",
|
|
522
|
+
"infra.slackNo": "Set up later",
|
|
523
|
+
"infra.slackCommandMsg": "Slack command name?",
|
|
524
|
+
"infra.portMsg": "Kanban server port?",
|
|
525
|
+
"infra.portValidation": "Enter a valid port number (1-65535)",
|
|
526
|
+
"infra.targetDirMsg": "Where to generate files?",
|
|
527
|
+
"infra.targetDirPlaceholder": "(current directory)",
|
|
528
|
+
// ─── generators/env-file.ts ───
|
|
529
|
+
"envGen.kanbanServer": "# Kanban server",
|
|
530
|
+
"envGen.slackIntegration": "# Slack integration",
|
|
531
|
+
"envGen.slackLater": "# Slack integration (set up later)",
|
|
532
|
+
// ─── generators/project-context.ts ───
|
|
533
|
+
// frontend labels
|
|
534
|
+
"contextGen.frontendNone": "(None)",
|
|
535
|
+
// deploy labels
|
|
536
|
+
"contextGen.deployDocker": "Docker self-hosted",
|
|
537
|
+
"contextGen.deployUndecided": "Undecided",
|
|
538
|
+
// stage labels
|
|
539
|
+
"contextGen.stageIdea": "Idea/Planning stage",
|
|
540
|
+
"contextGen.stageDevPreMvp": "Development in progress (pre-MVP)",
|
|
541
|
+
"contextGen.stageMvpDone": "MVP done, improving",
|
|
542
|
+
"contextGen.stageProduction": "In production (maintenance/features)",
|
|
543
|
+
"contextGen.stageRefactor": "Refactoring/Migration",
|
|
544
|
+
// project type labels
|
|
545
|
+
"contextGen.typeWebApp": "Web application",
|
|
546
|
+
"contextGen.typeMobile": "Mobile app",
|
|
547
|
+
"contextGen.typeApi": "API server",
|
|
548
|
+
"contextGen.typeDataPipeline": "Data pipeline",
|
|
549
|
+
"contextGen.typeAiMl": "AI/ML",
|
|
550
|
+
"contextGen.typeContent": "Content/Marketing",
|
|
551
|
+
"contextGen.typeAdmin": "Internal tool",
|
|
552
|
+
"contextGen.typeLibrary": "Library/SDK",
|
|
553
|
+
// coding style labels
|
|
554
|
+
"contextGen.styleFunctional": "Functional components only (no classes)",
|
|
555
|
+
"contextGen.styleNamedExport": "Prefer named exports",
|
|
556
|
+
"contextGen.styleNoAny": "No 'any' type (prefer unknown)",
|
|
557
|
+
"contextGen.styleKoComment": "Korean comments/commits",
|
|
558
|
+
"contextGen.styleEnComment": "English comments/commits",
|
|
559
|
+
"contextGen.styleJsdoc": "JSDoc comments",
|
|
560
|
+
"contextGen.styleEslint": "ESLint + Prettier enabled",
|
|
561
|
+
"contextGen.styleDefault": "Default",
|
|
562
|
+
// concern labels
|
|
563
|
+
"contextGen.concernI18n": "i18n",
|
|
564
|
+
"contextGen.concernDarkMode": "Dark mode",
|
|
565
|
+
"contextGen.concernA11y": "Accessibility (a11y)",
|
|
566
|
+
"contextGen.concernSeo": "SEO optimization",
|
|
567
|
+
"contextGen.concernPerformance": "Performance (Core Web Vitals)",
|
|
568
|
+
"contextGen.concernSecurity": "Security (Auth/XSS/CSRF)",
|
|
569
|
+
"contextGen.concernResponsive": "Mobile responsive required",
|
|
570
|
+
"contextGen.concernNone": "None",
|
|
571
|
+
// generated document sections
|
|
572
|
+
"contextGen.title": "{name} \u2014 Project Context",
|
|
573
|
+
"contextGen.intro": "This document contains shared project information for all agents.\nEach agent performs its role with this context in mind.",
|
|
574
|
+
"contextGen.sectionOverview": "Project Overview",
|
|
575
|
+
"contextGen.labelType": "Type",
|
|
576
|
+
"contextGen.labelStage": "Stage",
|
|
577
|
+
"contextGen.sectionStack": "Tech Stack",
|
|
578
|
+
"contextGen.labelFrontend": "Frontend",
|
|
579
|
+
"contextGen.backendFallback": "(enter manually)",
|
|
580
|
+
"contextGen.labelDeploy": "Deploy",
|
|
581
|
+
"contextGen.sectionDirs": "Directory Structure",
|
|
582
|
+
"contextGen.defaultDirSrc": "Source code",
|
|
583
|
+
"contextGen.defaultDirDocs": "Docs",
|
|
584
|
+
"contextGen.defaultDirTools": "Dev tools",
|
|
585
|
+
"contextGen.sectionConventions": "Coding Conventions",
|
|
586
|
+
"contextGen.noConventionsClaudeMd": "(No conventions auto-extracted from CLAUDE.md)",
|
|
587
|
+
"contextGen.noConventionsManual": "(Customize for your project)",
|
|
588
|
+
"contextGen.sectionBrand": "Brand/Design",
|
|
589
|
+
"contextGen.labelFonts": "Fonts",
|
|
590
|
+
"contextGen.labelColors": "Colors",
|
|
591
|
+
"contextGen.labelI18n": "i18n",
|
|
592
|
+
"contextGen.sectionGoals": "Project Goals",
|
|
593
|
+
"contextGen.goalsPlaceholder": "(Enter your goals)",
|
|
594
|
+
"contextGen.sectionConstraints": "Constraints",
|
|
595
|
+
"contextGen.constraintsPlaceholder": "(No constraints)",
|
|
596
|
+
"contextGen.sectionRefDocs": "Reference Docs",
|
|
597
|
+
"contextGen.noRefDocs": "(None)",
|
|
598
|
+
"contextGen.sectionProtocol": "Work Protocol",
|
|
599
|
+
"contextGen.protocolKanban": "Kanban server",
|
|
600
|
+
"contextGen.protocolSlack": "Slack reporting",
|
|
601
|
+
"contextGen.protocolLogs": "Log directory",
|
|
602
|
+
"contextGen.protocolStatus": "Status flow",
|
|
603
|
+
"contextGen.protocolInstruction": "All agents must log to these 3 locations on task start/completion:",
|
|
604
|
+
"contextGen.protocolSlackReport": "Slack report",
|
|
605
|
+
"contextGen.protocolKanbanUpdate": "Kanban update",
|
|
606
|
+
"contextGen.protocolLogFile": "Log file",
|
|
607
|
+
"contextGen.protocolSlackExample": "message",
|
|
608
|
+
// ─── generators/agent-prompt.ts (base sections only) ───
|
|
609
|
+
"agentGen.projectLabel": "Project",
|
|
610
|
+
"agentGen.descLabel": "Description",
|
|
611
|
+
"agentGen.kanbanApiLabel": "Kanban API",
|
|
612
|
+
"agentGen.slackApiLabel": "Slack API",
|
|
613
|
+
"agentGen.logDirLabel": "Log directory",
|
|
614
|
+
"agentGen.slackReportingDesc": "Report to Slack on task start/completion (auto-threaded per task):",
|
|
615
|
+
"agentGen.slackForbid": "Do not use `$SLACK_AGENT_WEBHOOK` directly. Always report via the API above.",
|
|
616
|
+
"agentGen.slackTaskIdNote": "`{TASK_ID}` is injected with the actual ID by buildExecutorPrompt.",
|
|
617
|
+
"agentGen.kanbanStart": "Start",
|
|
618
|
+
"agentGen.kanbanDone": "Done",
|
|
619
|
+
"agentGen.kanbanActiveForm": "Active description",
|
|
620
|
+
"agentGen.kanbanReportFormat": "One-line summary. Follow-up: suggest next task",
|
|
621
|
+
"agentGen.reportDesc": "Write a report after completion:",
|
|
622
|
+
"agentGen.reportPathLabel": "Path",
|
|
623
|
+
"agentGen.reportContentDesc": "Content: changed files, changes, verification results, follow-up tasks",
|
|
624
|
+
"agentGen.fontsLabel": "Fonts",
|
|
625
|
+
"agentGen.colorsLabel": "Colors",
|
|
626
|
+
// ─── utils/detect-structure.ts ───
|
|
627
|
+
"detect.src": "Source code",
|
|
628
|
+
"detect.app": "App source (Next.js/Remix)",
|
|
629
|
+
"detect.pages": "Pages (Next.js)",
|
|
630
|
+
"detect.components": "Components",
|
|
631
|
+
"detect.lib": "Library/Utils",
|
|
632
|
+
"detect.api": "API routes",
|
|
633
|
+
"detect.server": "Server code",
|
|
634
|
+
"detect.supabase": "Supabase (Edge Functions/Migrations)",
|
|
635
|
+
"detect.firebase": "Firebase",
|
|
636
|
+
"detect.prisma": "Prisma schema",
|
|
637
|
+
"detect.docs": "Docs",
|
|
638
|
+
"detect.tests": "Tests",
|
|
639
|
+
"detect.e2e": "E2E tests",
|
|
640
|
+
"detect.cypress": "Cypress tests",
|
|
641
|
+
"detect.public": "Static files",
|
|
642
|
+
"detect.static": "Static files",
|
|
643
|
+
"detect.assets": "Assets",
|
|
644
|
+
"detect.styles": "Styles",
|
|
645
|
+
"detect.scripts": "Scripts",
|
|
646
|
+
"detect.tools": "Dev tools",
|
|
647
|
+
"detect.github": "GitHub Actions"
|
|
648
|
+
}
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
// src/prompts/project-info.ts
|
|
652
|
+
function getProjectTypeOptions() {
|
|
653
|
+
return [
|
|
654
|
+
{ value: "web-app", label: t("projectInfo.typeWebApp") },
|
|
655
|
+
{ value: "mobile", label: t("projectInfo.typeMobile") },
|
|
656
|
+
{ value: "api", label: t("projectInfo.typeApi") },
|
|
657
|
+
{ value: "data-pipeline", label: t("projectInfo.typeDataPipeline") },
|
|
658
|
+
{ value: "ai-ml", label: t("projectInfo.typeAiMl") },
|
|
659
|
+
{ value: "content", label: t("projectInfo.typeContent") },
|
|
660
|
+
{ value: "admin", label: t("projectInfo.typeAdmin") },
|
|
661
|
+
{ value: "library", label: t("projectInfo.typeLibrary") }
|
|
662
|
+
];
|
|
663
|
+
}
|
|
19
664
|
async function promptProjectInfo() {
|
|
20
|
-
p.log.step("
|
|
665
|
+
p.log.step(t("projectInfo.phase"));
|
|
21
666
|
const name = await p.text({
|
|
22
|
-
message: "
|
|
667
|
+
message: t("projectInfo.nameMsg"),
|
|
23
668
|
placeholder: "MyProject",
|
|
24
|
-
validate: (v) => v.trim() ? void 0 : "
|
|
669
|
+
validate: (v) => v.trim() ? void 0 : t("projectInfo.nameValidation")
|
|
25
670
|
});
|
|
26
671
|
if (p.isCancel(name)) return null;
|
|
27
672
|
const description = await p.text({
|
|
28
|
-
message: "
|
|
29
|
-
placeholder: "
|
|
30
|
-
validate: (v) => v.trim() ? void 0 : "
|
|
673
|
+
message: t("projectInfo.descMsg"),
|
|
674
|
+
placeholder: t("projectInfo.descPlaceholder"),
|
|
675
|
+
validate: (v) => v.trim() ? void 0 : t("projectInfo.descValidation")
|
|
31
676
|
});
|
|
32
677
|
if (p.isCancel(description)) return null;
|
|
33
678
|
const types = await p.multiselect({
|
|
34
|
-
message: "
|
|
35
|
-
options:
|
|
679
|
+
message: t("projectInfo.typesMsg"),
|
|
680
|
+
options: getProjectTypeOptions(),
|
|
36
681
|
required: true
|
|
37
682
|
});
|
|
38
683
|
if (p.isCancel(types)) return null;
|
|
@@ -49,33 +694,35 @@ import * as p2 from "@clack/prompts";
|
|
|
49
694
|
// src/utils/detect-structure.ts
|
|
50
695
|
import fs from "fs-extra";
|
|
51
696
|
import path from "path";
|
|
52
|
-
|
|
53
|
-
[
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
]
|
|
697
|
+
function getDirChecks() {
|
|
698
|
+
return [
|
|
699
|
+
["src", t("detect.src")],
|
|
700
|
+
["app", t("detect.app")],
|
|
701
|
+
["pages", t("detect.pages")],
|
|
702
|
+
["components", t("detect.components")],
|
|
703
|
+
["lib", t("detect.lib")],
|
|
704
|
+
["api", t("detect.api")],
|
|
705
|
+
["server", t("detect.server")],
|
|
706
|
+
["supabase", t("detect.supabase")],
|
|
707
|
+
["firebase", t("detect.firebase")],
|
|
708
|
+
["prisma", t("detect.prisma")],
|
|
709
|
+
["docs", t("detect.docs")],
|
|
710
|
+
["tests", t("detect.tests")],
|
|
711
|
+
["__tests__", t("detect.tests")],
|
|
712
|
+
["e2e", t("detect.e2e")],
|
|
713
|
+
["cypress", t("detect.cypress")],
|
|
714
|
+
["public", t("detect.public")],
|
|
715
|
+
["static", t("detect.static")],
|
|
716
|
+
["assets", t("detect.assets")],
|
|
717
|
+
["styles", t("detect.styles")],
|
|
718
|
+
["scripts", t("detect.scripts")],
|
|
719
|
+
["tools", t("detect.tools")],
|
|
720
|
+
[".github", t("detect.github")]
|
|
721
|
+
];
|
|
722
|
+
}
|
|
76
723
|
function detectStructure(targetDir) {
|
|
77
724
|
const dirs = [];
|
|
78
|
-
for (const [dirPath, desc] of
|
|
725
|
+
for (const [dirPath, desc] of getDirChecks()) {
|
|
79
726
|
const full = path.join(targetDir, dirPath);
|
|
80
727
|
if (fs.existsSync(full) && fs.statSync(full).isDirectory()) {
|
|
81
728
|
dirs.push({ path: `${dirPath}/`, description: desc });
|
|
@@ -98,39 +745,45 @@ function detectProjectSignals(targetDir) {
|
|
|
98
745
|
}
|
|
99
746
|
|
|
100
747
|
// src/prompts/tech-stack.ts
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
748
|
+
function getFrontendOptions() {
|
|
749
|
+
return [
|
|
750
|
+
{ value: "react-ts", label: "React + TypeScript" },
|
|
751
|
+
{ value: "nextjs", label: "Next.js" },
|
|
752
|
+
{ value: "vue-nuxt", label: "Vue / Nuxt" },
|
|
753
|
+
{ value: "svelte", label: "Svelte / SvelteKit" },
|
|
754
|
+
{ value: "angular", label: "Angular" },
|
|
755
|
+
{ value: "none", label: t("techStack.frontendNone") }
|
|
756
|
+
];
|
|
757
|
+
}
|
|
758
|
+
function getBackendOptions() {
|
|
759
|
+
return [
|
|
760
|
+
{ value: "supabase", label: "Supabase" },
|
|
761
|
+
{ value: "firebase", label: "Firebase" },
|
|
762
|
+
{ value: "node", label: "Node.js (Express/Fastify)" },
|
|
763
|
+
{ value: "python", label: "Python (FastAPI/Django)" },
|
|
764
|
+
{ value: "go", label: "Go" },
|
|
765
|
+
{ value: "postgresql", label: "PostgreSQL" },
|
|
766
|
+
{ value: "mysql", label: "MySQL" },
|
|
767
|
+
{ value: "mongodb", label: "MongoDB" },
|
|
768
|
+
{ value: "redis", label: "Redis" },
|
|
769
|
+
{ value: "aws", label: "AWS" },
|
|
770
|
+
{ value: "gcp", label: "GCP" },
|
|
771
|
+
{ value: "azure", label: "Azure" },
|
|
772
|
+
{ value: "docker", label: "Docker / K8s" }
|
|
773
|
+
];
|
|
774
|
+
}
|
|
775
|
+
function getDeployOptions() {
|
|
776
|
+
return [
|
|
777
|
+
{ value: "vercel", label: "Vercel" },
|
|
778
|
+
{ value: "netlify", label: "Netlify" },
|
|
779
|
+
{ value: "aws", label: "AWS (EC2/ECS/Lambda)" },
|
|
780
|
+
{ value: "gcp", label: "GCP (Cloud Run/App Engine)" },
|
|
781
|
+
{ value: "docker", label: t("techStack.deployDocker") },
|
|
782
|
+
{ value: "undecided", label: t("techStack.deployUndecided") }
|
|
783
|
+
];
|
|
784
|
+
}
|
|
132
785
|
async function promptTechStack(targetDir) {
|
|
133
|
-
p2.log.step("
|
|
786
|
+
p2.log.step(t("techStack.phase"));
|
|
134
787
|
const signals = detectProjectSignals(targetDir);
|
|
135
788
|
const hints = [];
|
|
136
789
|
if (signals.hasTypeScript) hints.push("TypeScript");
|
|
@@ -141,17 +794,17 @@ async function promptTechStack(targetDir) {
|
|
|
141
794
|
if (signals.hasDocker) hints.push("Docker");
|
|
142
795
|
if (signals.hasVercel) hints.push("Vercel");
|
|
143
796
|
if (hints.length > 0) {
|
|
144
|
-
p2.log.info(
|
|
797
|
+
p2.log.info(t("techStack.detectedTech", { techs: hints.join(", ") }));
|
|
145
798
|
}
|
|
146
799
|
const frontend = await p2.select({
|
|
147
|
-
message: "
|
|
148
|
-
options:
|
|
800
|
+
message: t("techStack.frontendMsg"),
|
|
801
|
+
options: getFrontendOptions(),
|
|
149
802
|
initialValue: signals.hasNextConfig ? "nextjs" : signals.hasPackageJson ? "react-ts" : "none"
|
|
150
803
|
});
|
|
151
804
|
if (p2.isCancel(frontend)) return null;
|
|
152
805
|
const backend = await p2.multiselect({
|
|
153
|
-
message: "
|
|
154
|
-
options:
|
|
806
|
+
message: t("techStack.backendMsg"),
|
|
807
|
+
options: getBackendOptions(),
|
|
155
808
|
required: false,
|
|
156
809
|
initialValues: [
|
|
157
810
|
...signals.hasSupabase ? ["supabase"] : [],
|
|
@@ -160,8 +813,8 @@ async function promptTechStack(targetDir) {
|
|
|
160
813
|
});
|
|
161
814
|
if (p2.isCancel(backend)) return null;
|
|
162
815
|
const deploy = await p2.select({
|
|
163
|
-
message: "
|
|
164
|
-
options:
|
|
816
|
+
message: t("techStack.deployMsg"),
|
|
817
|
+
options: getDeployOptions(),
|
|
165
818
|
initialValue: signals.hasVercel ? "vercel" : "undecided"
|
|
166
819
|
});
|
|
167
820
|
if (p2.isCancel(deploy)) return null;
|
|
@@ -169,26 +822,25 @@ async function promptTechStack(targetDir) {
|
|
|
169
822
|
let directories = detected;
|
|
170
823
|
if (detected.length > 0) {
|
|
171
824
|
const dirList = detected.map((d) => ` ${d.path.padEnd(18)} \u2190 ${d.description}`).join("\n");
|
|
172
|
-
p2.log.info(
|
|
173
|
-
${dirList}`);
|
|
825
|
+
p2.log.info(t("techStack.detectedDirs", { dirs: dirList }));
|
|
174
826
|
const useDetected = await p2.confirm({
|
|
175
|
-
message: "
|
|
827
|
+
message: t("techStack.useDetected"),
|
|
176
828
|
initialValue: true
|
|
177
829
|
});
|
|
178
830
|
if (p2.isCancel(useDetected)) return null;
|
|
179
831
|
if (!useDetected) {
|
|
180
832
|
const customDirs = await p2.text({
|
|
181
|
-
message: "
|
|
182
|
-
placeholder: "
|
|
833
|
+
message: t("techStack.customDirsMsg"),
|
|
834
|
+
placeholder: t("techStack.customDirsPlaceholder")
|
|
183
835
|
});
|
|
184
836
|
if (p2.isCancel(customDirs)) return null;
|
|
185
837
|
directories = parseDirectoryInput(customDirs);
|
|
186
838
|
}
|
|
187
839
|
} else {
|
|
188
840
|
const customDirs = await p2.text({
|
|
189
|
-
message: "
|
|
190
|
-
placeholder: "
|
|
191
|
-
initialValue: "
|
|
841
|
+
message: t("techStack.mainDirsMsg"),
|
|
842
|
+
placeholder: t("techStack.customDirsPlaceholder"),
|
|
843
|
+
initialValue: t("techStack.customDirsPlaceholder")
|
|
192
844
|
});
|
|
193
845
|
if (p2.isCancel(customDirs)) return null;
|
|
194
846
|
directories = parseDirectoryInput(customDirs);
|
|
@@ -234,22 +886,22 @@ function parseClaudeMd(filePath) {
|
|
|
234
886
|
if (matchAny(h, ["\uC2A4\uD0DD", "stack", "\uAE30\uC220", "tech"])) {
|
|
235
887
|
parseStack(content, ctx);
|
|
236
888
|
}
|
|
237
|
-
if (matchAny(h, ["\uCEE8\uBCA4\uC158", "convention", "\uADDC\uCE59", "rule", "\uC2A4\uD0C0\uC77C", "style guide", "\uCF54\uB529"])) {
|
|
889
|
+
if (matchAny(h, ["\uCEE8\uBCA4\uC158", "convention", "\uADDC\uCE59", "rule", "rules", "\uC2A4\uD0C0\uC77C", "style guide", "\uCF54\uB529", "coding"])) {
|
|
238
890
|
parseConventions(content, ctx);
|
|
239
891
|
}
|
|
240
|
-
if (matchAny(h, ["\uB514\uB809\uD1A0\uB9AC", "directory", "\uAD6C\uC870", "structure", "\uACBD\uB85C"])) {
|
|
892
|
+
if (matchAny(h, ["\uB514\uB809\uD1A0\uB9AC", "directory", "\uAD6C\uC870", "structure", "\uACBD\uB85C", "path", "paths"])) {
|
|
241
893
|
parsePaths(content, ctx);
|
|
242
894
|
}
|
|
243
|
-
if (matchAny(h, ["\uBCF4\uC548", "security", "\uC8FC\uC758", "caution", "\uAE08\uC9C0"])) {
|
|
895
|
+
if (matchAny(h, ["\uBCF4\uC548", "security", "\uC8FC\uC758", "caution", "\uAE08\uC9C0", "forbidden", "restriction"])) {
|
|
244
896
|
ctx.security.push(...extractListItems(content));
|
|
245
897
|
}
|
|
246
|
-
if (matchAny(h, ["\uD3F0\uD2B8", "font", "\uD0C0\uC774\uD3EC"])) {
|
|
898
|
+
if (matchAny(h, ["\uD3F0\uD2B8", "font", "\uD0C0\uC774\uD3EC", "typography", "typeface"])) {
|
|
247
899
|
ctx.fonts.push(...extractListItems(content));
|
|
248
900
|
}
|
|
249
|
-
if (matchAny(h, ["\uC0C9\uC0C1", "color", "palette", "\uBE0C\uB79C\uB4DC"])) {
|
|
901
|
+
if (matchAny(h, ["\uC0C9\uC0C1", "color", "palette", "\uBE0C\uB79C\uB4DC", "brand", "theme"])) {
|
|
250
902
|
extractColors(content, ctx);
|
|
251
903
|
}
|
|
252
|
-
if (matchAny(h, ["i18n", "\uAD6D\uC81C\uD654", "\uB2E4\uAD6D\uC5B4", "locale"])) {
|
|
904
|
+
if (matchAny(h, ["i18n", "\uAD6D\uC81C\uD654", "\uB2E4\uAD6D\uC5B4", "locale", "internationalization", "localization"])) {
|
|
253
905
|
ctx.i18n.push(...extractListItems(content));
|
|
254
906
|
}
|
|
255
907
|
}
|
|
@@ -300,8 +952,8 @@ function parseStack(content, ctx) {
|
|
|
300
952
|
const key = tableMatch[1].toLowerCase();
|
|
301
953
|
const val = tableMatch[2].trim();
|
|
302
954
|
if (key.includes("\uD504\uB860\uD2B8") || key.includes("front")) ctx.stack.frontend = val;
|
|
303
|
-
if (key.includes("\uBC31\uC5D4\uB4DC") || key.includes("back") || key.includes("\uC11C\uBC84")) ctx.stack.backend = val;
|
|
304
|
-
if (key.includes("\uBC30\uD3EC") || key.includes("deploy") || key.includes("\uD638\uC2A4\uD305")) ctx.stack.deploy = val;
|
|
955
|
+
if (key.includes("\uBC31\uC5D4\uB4DC") || key.includes("back") || key.includes("\uC11C\uBC84") || key.includes("server")) ctx.stack.backend = val;
|
|
956
|
+
if (key.includes("\uBC30\uD3EC") || key.includes("deploy") || key.includes("\uD638\uC2A4\uD305") || key.includes("hosting")) ctx.stack.deploy = val;
|
|
305
957
|
}
|
|
306
958
|
}
|
|
307
959
|
for (const item of items) {
|
|
@@ -321,7 +973,7 @@ function parseConventions(content, ctx) {
|
|
|
321
973
|
const items = extractListItems(content);
|
|
322
974
|
for (const item of items) {
|
|
323
975
|
const lower = item.toLowerCase();
|
|
324
|
-
if (lower.includes("case") || lower.includes("naming") || lower.includes("\uB124\uC774\uBC0D") || lower.includes("\uD30C\uC77C\uBA85")) {
|
|
976
|
+
if (lower.includes("case") || lower.includes("naming") || lower.includes("\uB124\uC774\uBC0D") || lower.includes("\uD30C\uC77C\uBA85") || lower.includes("filename")) {
|
|
325
977
|
ctx.conventions.naming.push(item);
|
|
326
978
|
} else if (lower.includes("lint") || lower.includes("prettier") || lower.includes("eslint") || lower.includes("vitest") || lower.includes("jest") || lower.includes("playwright")) {
|
|
327
979
|
ctx.conventions.tools.push(item);
|
|
@@ -364,56 +1016,62 @@ function extractColors(text7, ctx) {
|
|
|
364
1016
|
}
|
|
365
1017
|
|
|
366
1018
|
// src/prompts/context-files.ts
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
1019
|
+
function getCodingStyleOptions() {
|
|
1020
|
+
return [
|
|
1021
|
+
{ value: "functional-only", label: t("contextFiles.styleFunctional") },
|
|
1022
|
+
{ value: "named-export", label: t("contextFiles.styleNamedExport") },
|
|
1023
|
+
{ value: "no-any", label: t("contextFiles.styleNoAny") },
|
|
1024
|
+
{ value: "ko-comment", label: t("contextFiles.styleKoComment") },
|
|
1025
|
+
{ value: "en-comment", label: t("contextFiles.styleEnComment") },
|
|
1026
|
+
{ value: "jsdoc", label: t("contextFiles.styleJsdoc") },
|
|
1027
|
+
{ value: "eslint-prettier", label: t("contextFiles.styleEslint") },
|
|
1028
|
+
{ value: "default", label: t("contextFiles.styleDefault") }
|
|
1029
|
+
];
|
|
1030
|
+
}
|
|
1031
|
+
function getConcernOptions() {
|
|
1032
|
+
return [
|
|
1033
|
+
{ value: "i18n", label: t("contextFiles.concernI18n") },
|
|
1034
|
+
{ value: "dark-mode", label: t("contextFiles.concernDarkMode") },
|
|
1035
|
+
{ value: "a11y", label: t("contextFiles.concernA11y") },
|
|
1036
|
+
{ value: "seo", label: t("contextFiles.concernSeo") },
|
|
1037
|
+
{ value: "performance", label: t("contextFiles.concernPerformance") },
|
|
1038
|
+
{ value: "security", label: t("contextFiles.concernSecurity") },
|
|
1039
|
+
{ value: "responsive", label: t("contextFiles.concernResponsive") },
|
|
1040
|
+
{ value: "none", label: t("contextFiles.concernNone") }
|
|
1041
|
+
];
|
|
1042
|
+
}
|
|
1043
|
+
function getReferenceDocOptions() {
|
|
1044
|
+
return [
|
|
1045
|
+
{ value: "api-spec", label: t("contextFiles.refApiSpec") },
|
|
1046
|
+
{ value: "design-system", label: t("contextFiles.refDesignSystem") },
|
|
1047
|
+
{ value: "db-schema", label: t("contextFiles.refDbSchema") },
|
|
1048
|
+
{ value: "wbs", label: t("contextFiles.refWbs") },
|
|
1049
|
+
{ value: "brand-guide", label: t("contextFiles.refBrandGuide") },
|
|
1050
|
+
{ value: "none", label: t("contextFiles.refNone") }
|
|
1051
|
+
];
|
|
1052
|
+
}
|
|
395
1053
|
async function promptContextFiles(targetDir) {
|
|
396
|
-
p3.log.step("
|
|
1054
|
+
p3.log.step(t("contextFiles.phase"));
|
|
397
1055
|
let claudeMdPath;
|
|
398
1056
|
let parsedContext;
|
|
399
1057
|
let codingStyle = [];
|
|
400
1058
|
let concerns = [];
|
|
401
1059
|
const hasClaudeMd = await p3.select({
|
|
402
|
-
message: "
|
|
1060
|
+
message: t("contextFiles.hasClaudeMdMsg"),
|
|
403
1061
|
options: [
|
|
404
|
-
{ value: "yes", label: "
|
|
405
|
-
{ value: "no", label: "
|
|
1062
|
+
{ value: "yes", label: t("contextFiles.hasClaudeMdYes") },
|
|
1063
|
+
{ value: "no", label: t("contextFiles.hasClaudeMdNo") }
|
|
406
1064
|
]
|
|
407
1065
|
});
|
|
408
1066
|
if (p3.isCancel(hasClaudeMd)) return null;
|
|
409
1067
|
if (hasClaudeMd === "yes") {
|
|
410
1068
|
const mdPath = await p3.text({
|
|
411
|
-
message: "
|
|
1069
|
+
message: t("contextFiles.claudeMdPathMsg"),
|
|
412
1070
|
placeholder: "./CLAUDE.md",
|
|
413
1071
|
initialValue: "./CLAUDE.md",
|
|
414
1072
|
validate: (v) => {
|
|
415
1073
|
const resolved = path2.resolve(targetDir, v.trim());
|
|
416
|
-
return fs3.existsSync(resolved) ? void 0 :
|
|
1074
|
+
return fs3.existsSync(resolved) ? void 0 : t("contextFiles.fileNotFound", { path: resolved });
|
|
417
1075
|
}
|
|
418
1076
|
});
|
|
419
1077
|
if (p3.isCancel(mdPath)) return null;
|
|
@@ -421,53 +1079,51 @@ async function promptContextFiles(targetDir) {
|
|
|
421
1079
|
try {
|
|
422
1080
|
parsedContext = parseClaudeMd(claudeMdPath);
|
|
423
1081
|
const summary = [];
|
|
424
|
-
if (parsedContext.stack.frontend) summary.push(
|
|
425
|
-
if (parsedContext.stack.backend) summary.push(
|
|
426
|
-
if (parsedContext.conventions.naming.length) summary.push(
|
|
427
|
-
if (parsedContext.conventions.tools.length) summary.push(
|
|
428
|
-
if (parsedContext.fonts.length) summary.push(
|
|
1082
|
+
if (parsedContext.stack.frontend) summary.push(t("contextFiles.summaryStack", { value: parsedContext.stack.frontend }));
|
|
1083
|
+
if (parsedContext.stack.backend) summary.push(t("contextFiles.summaryBackend", { value: parsedContext.stack.backend }));
|
|
1084
|
+
if (parsedContext.conventions.naming.length) summary.push(t("contextFiles.summaryNaming", { value: parsedContext.conventions.naming.join(", ") }));
|
|
1085
|
+
if (parsedContext.conventions.tools.length) summary.push(t("contextFiles.summaryTools", { value: parsedContext.conventions.tools.join(", ") }));
|
|
1086
|
+
if (parsedContext.fonts.length) summary.push(t("contextFiles.summaryFonts", { value: parsedContext.fonts.join(", ") }));
|
|
429
1087
|
if (summary.length > 0) {
|
|
430
|
-
p3.log.success(
|
|
431
|
-
${summary.join("\n ")}
|
|
432
|
-
\u2192 \uC5D0\uC774\uC804\uD2B8 \uD504\uB86C\uD504\uD2B8\uC5D0 \uC790\uB3D9 \uBC18\uC601\uB429\uB2C8\uB2E4.`);
|
|
1088
|
+
p3.log.success(t("contextFiles.parseSuccess", { summary: summary.join("\n ") }));
|
|
433
1089
|
} else {
|
|
434
|
-
p3.log.info("
|
|
1090
|
+
p3.log.info(t("contextFiles.parseEmpty"));
|
|
435
1091
|
parsedContext = void 0;
|
|
436
1092
|
}
|
|
437
1093
|
} catch {
|
|
438
|
-
p3.log.warn("
|
|
1094
|
+
p3.log.warn(t("contextFiles.parseError"));
|
|
439
1095
|
parsedContext = void 0;
|
|
440
1096
|
}
|
|
441
1097
|
}
|
|
442
1098
|
if (!parsedContext) {
|
|
443
1099
|
const styleResult = await p3.multiselect({
|
|
444
|
-
message: "
|
|
445
|
-
options:
|
|
1100
|
+
message: t("contextFiles.codingStyleMsg"),
|
|
1101
|
+
options: getCodingStyleOptions(),
|
|
446
1102
|
required: false
|
|
447
1103
|
});
|
|
448
1104
|
if (p3.isCancel(styleResult)) return null;
|
|
449
1105
|
codingStyle = styleResult;
|
|
450
1106
|
const concernResult = await p3.multiselect({
|
|
451
|
-
message: "
|
|
452
|
-
options:
|
|
1107
|
+
message: t("contextFiles.concernsMsg"),
|
|
1108
|
+
options: getConcernOptions(),
|
|
453
1109
|
required: false
|
|
454
1110
|
});
|
|
455
1111
|
if (p3.isCancel(concernResult)) return null;
|
|
456
1112
|
concerns = concernResult;
|
|
457
1113
|
}
|
|
458
1114
|
const refDocTypes = await p3.multiselect({
|
|
459
|
-
message: "
|
|
460
|
-
options:
|
|
1115
|
+
message: t("contextFiles.refDocsMsg"),
|
|
1116
|
+
options: getReferenceDocOptions(),
|
|
461
1117
|
required: false
|
|
462
1118
|
});
|
|
463
1119
|
if (p3.isCancel(refDocTypes)) return null;
|
|
464
1120
|
const referenceDocs = [];
|
|
465
|
-
const selectedTypes = refDocTypes.filter((
|
|
1121
|
+
const selectedTypes = refDocTypes.filter((v) => v !== "none");
|
|
466
1122
|
for (const docType of selectedTypes) {
|
|
467
1123
|
const docPath = await p3.text({
|
|
468
|
-
message:
|
|
1124
|
+
message: t("contextFiles.docPathMsg", { type: docType }),
|
|
469
1125
|
placeholder: `./docs/${docType}`,
|
|
470
|
-
validate: (v) => v.trim() ? void 0 : "
|
|
1126
|
+
validate: (v) => v.trim() ? void 0 : t("contextFiles.docPathValidation")
|
|
471
1127
|
});
|
|
472
1128
|
if (p3.isCancel(docPath)) return null;
|
|
473
1129
|
referenceDocs.push({ type: docType, path: docPath.trim() });
|
|
@@ -495,40 +1151,46 @@ var WORK_TYPE_TO_AGENTS = {
|
|
|
495
1151
|
"strategy": ["strategist"],
|
|
496
1152
|
"items": ["item-author"]
|
|
497
1153
|
};
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
1154
|
+
function getWorkTypeOptions() {
|
|
1155
|
+
return [
|
|
1156
|
+
{ value: "frontend", label: t("agents.workFrontend") },
|
|
1157
|
+
{ value: "backend", label: t("agents.workBackend") },
|
|
1158
|
+
{ value: "qa", label: t("agents.workQa") },
|
|
1159
|
+
{ value: "design", label: t("agents.workDesign") },
|
|
1160
|
+
{ value: "devops", label: t("agents.workDevops") },
|
|
1161
|
+
{ value: "research", label: t("agents.workResearch") },
|
|
1162
|
+
{ value: "docs", label: t("agents.workDocs") },
|
|
1163
|
+
{ value: "content", label: t("agents.workContent") },
|
|
1164
|
+
{ value: "strategy", label: t("agents.workStrategy") },
|
|
1165
|
+
{ value: "items", label: t("agents.workItems") }
|
|
1166
|
+
];
|
|
1167
|
+
}
|
|
1168
|
+
function getAllAgentOptions() {
|
|
1169
|
+
return [
|
|
1170
|
+
{ value: "frontend", label: t("agents.agentFrontend") },
|
|
1171
|
+
{ value: "backend", label: t("agents.agentBackend") },
|
|
1172
|
+
{ value: "qa", label: t("agents.agentQa") },
|
|
1173
|
+
{ value: "designer", label: t("agents.agentDesigner") },
|
|
1174
|
+
{ value: "devops", label: t("agents.agentDevops") },
|
|
1175
|
+
{ value: "researcher", label: t("agents.agentResearcher") },
|
|
1176
|
+
{ value: "strategist", label: t("agents.agentStrategist") },
|
|
1177
|
+
{ value: "content-planner", label: t("agents.agentContentPlanner") },
|
|
1178
|
+
{ value: "item-author", label: t("agents.agentItemAuthor") },
|
|
1179
|
+
{ value: "doc-writer", label: t("agents.agentDocWriter") }
|
|
1180
|
+
];
|
|
1181
|
+
}
|
|
1182
|
+
function getModelOptions() {
|
|
1183
|
+
return [
|
|
1184
|
+
{ value: "sonnet", label: t("agents.modelSonnet") },
|
|
1185
|
+
{ value: "opus", label: t("agents.modelOpus") },
|
|
1186
|
+
{ value: "sonnet-only", label: t("agents.modelSonnetOnly") }
|
|
1187
|
+
];
|
|
1188
|
+
}
|
|
527
1189
|
async function promptAgents() {
|
|
528
|
-
p4.log.step("
|
|
1190
|
+
p4.log.step(t("agents.phase"));
|
|
529
1191
|
const workTypes = await p4.multiselect({
|
|
530
|
-
message: "
|
|
531
|
-
options:
|
|
1192
|
+
message: t("agents.workTypeMsg"),
|
|
1193
|
+
options: getWorkTypeOptions(),
|
|
532
1194
|
required: true
|
|
533
1195
|
});
|
|
534
1196
|
if (p4.isCancel(workTypes)) return null;
|
|
@@ -539,19 +1201,17 @@ async function promptAgents() {
|
|
|
539
1201
|
}
|
|
540
1202
|
const recommendedList = [...recommended];
|
|
541
1203
|
const recDisplay = recommendedList.map((a) => ` \u25FC ${a}`).join("\n");
|
|
542
|
-
p4.log.info(
|
|
543
|
-
${recDisplay}
|
|
544
|
-
\u25FC orchestrator \u2190 \uD56D\uC0C1 \uD3EC\uD568`);
|
|
1204
|
+
p4.log.info(t("agents.recommended", { list: recDisplay }));
|
|
545
1205
|
const customize = await p4.confirm({
|
|
546
|
-
message: "
|
|
1206
|
+
message: t("agents.customizeMsg"),
|
|
547
1207
|
initialValue: false
|
|
548
1208
|
});
|
|
549
1209
|
if (p4.isCancel(customize)) return null;
|
|
550
1210
|
let selectedAgents;
|
|
551
1211
|
if (customize) {
|
|
552
1212
|
const result = await p4.multiselect({
|
|
553
|
-
message: "
|
|
554
|
-
options:
|
|
1213
|
+
message: t("agents.selectMsg"),
|
|
1214
|
+
options: getAllAgentOptions(),
|
|
555
1215
|
initialValues: recommendedList.filter((a) => a !== "orchestrator"),
|
|
556
1216
|
required: true
|
|
557
1217
|
});
|
|
@@ -561,8 +1221,8 @@ ${recDisplay}
|
|
|
561
1221
|
selectedAgents = recommendedList;
|
|
562
1222
|
}
|
|
563
1223
|
const defaultModel = await p4.select({
|
|
564
|
-
message: "
|
|
565
|
-
options:
|
|
1224
|
+
message: t("agents.modelMsg"),
|
|
1225
|
+
options: getModelOptions()
|
|
566
1226
|
});
|
|
567
1227
|
if (p4.isCancel(defaultModel)) return null;
|
|
568
1228
|
const modelOverrides = {};
|
|
@@ -581,29 +1241,31 @@ ${recDisplay}
|
|
|
581
1241
|
|
|
582
1242
|
// src/prompts/orchestrator.ts
|
|
583
1243
|
import * as p5 from "@clack/prompts";
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
1244
|
+
function getStageOptions() {
|
|
1245
|
+
return [
|
|
1246
|
+
{ value: "idea", label: t("orchestrator.stageIdea") },
|
|
1247
|
+
{ value: "dev-pre-mvp", label: t("orchestrator.stageDevPreMvp") },
|
|
1248
|
+
{ value: "mvp-done", label: t("orchestrator.stageMvpDone") },
|
|
1249
|
+
{ value: "production", label: t("orchestrator.stageProduction") },
|
|
1250
|
+
{ value: "refactor", label: t("orchestrator.stageRefactor") }
|
|
1251
|
+
];
|
|
1252
|
+
}
|
|
591
1253
|
async function promptOrchestrator(projectName) {
|
|
592
|
-
p5.log.step("
|
|
1254
|
+
p5.log.step(t("orchestrator.phase"));
|
|
593
1255
|
const goals = await p5.text({
|
|
594
|
-
message:
|
|
595
|
-
placeholder: "
|
|
596
|
-
validate: (v) => v.trim() ? void 0 : "
|
|
1256
|
+
message: t("orchestrator.goalsMsg", { name: projectName }),
|
|
1257
|
+
placeholder: t("orchestrator.goalsPlaceholder"),
|
|
1258
|
+
validate: (v) => v.trim() ? void 0 : t("orchestrator.goalsValidation")
|
|
597
1259
|
});
|
|
598
1260
|
if (p5.isCancel(goals)) return null;
|
|
599
1261
|
const stage = await p5.select({
|
|
600
|
-
message: "
|
|
601
|
-
options:
|
|
1262
|
+
message: t("orchestrator.stageMsg"),
|
|
1263
|
+
options: getStageOptions()
|
|
602
1264
|
});
|
|
603
1265
|
if (p5.isCancel(stage)) return null;
|
|
604
1266
|
const constraints = await p5.text({
|
|
605
|
-
message: "
|
|
606
|
-
placeholder: "
|
|
1267
|
+
message: t("orchestrator.constraintsMsg"),
|
|
1268
|
+
placeholder: t("orchestrator.constraintsPlaceholder"),
|
|
607
1269
|
initialValue: ""
|
|
608
1270
|
});
|
|
609
1271
|
if (p5.isCancel(constraints)) return null;
|
|
@@ -616,22 +1278,24 @@ async function promptOrchestrator(projectName) {
|
|
|
616
1278
|
|
|
617
1279
|
// src/prompts/multi-project.ts
|
|
618
1280
|
import * as p6 from "@clack/prompts";
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
1281
|
+
function getColorOptions() {
|
|
1282
|
+
return [
|
|
1283
|
+
{ value: "#3B82F6", label: `${t("multiProject.colorBlue")} (#3B82F6)` },
|
|
1284
|
+
{ value: "#22C55E", label: `${t("multiProject.colorGreen")} (#22C55E)` },
|
|
1285
|
+
{ value: "#F97316", label: `${t("multiProject.colorOrange")} (#F97316)` },
|
|
1286
|
+
{ value: "#8B5CF6", label: `${t("multiProject.colorPurple")} (#8B5CF6)` },
|
|
1287
|
+
{ value: "#EF4444", label: `${t("multiProject.colorRed")} (#EF4444)` },
|
|
1288
|
+
{ value: "#EC4899", label: `${t("multiProject.colorPink")} (#EC4899)` },
|
|
1289
|
+
{ value: "#14B8A6", label: `${t("multiProject.colorTeal")} (#14B8A6)` }
|
|
1290
|
+
];
|
|
1291
|
+
}
|
|
628
1292
|
async function promptMultiProject() {
|
|
629
|
-
p6.log.step(
|
|
1293
|
+
p6.log.step(t("multiProject.phase"));
|
|
630
1294
|
const addMore = await p6.select({
|
|
631
|
-
message: "
|
|
1295
|
+
message: t("multiProject.addMoreMsg"),
|
|
632
1296
|
options: [
|
|
633
|
-
{ value: "no", label: "
|
|
634
|
-
{ value: "yes", label: "
|
|
1297
|
+
{ value: "no", label: t("multiProject.addMoreNo") },
|
|
1298
|
+
{ value: "yes", label: t("multiProject.addMoreYes") }
|
|
635
1299
|
]
|
|
636
1300
|
});
|
|
637
1301
|
if (p6.isCancel(addMore)) return null;
|
|
@@ -639,26 +1303,26 @@ async function promptMultiProject() {
|
|
|
639
1303
|
const projects = [];
|
|
640
1304
|
while (true) {
|
|
641
1305
|
const name = await p6.text({
|
|
642
|
-
message: "
|
|
643
|
-
placeholder: "
|
|
644
|
-
validate: (v) => v.trim() ? void 0 : "
|
|
1306
|
+
message: t("multiProject.nameMsg"),
|
|
1307
|
+
placeholder: t("multiProject.namePlaceholder"),
|
|
1308
|
+
validate: (v) => v.trim() ? void 0 : t("multiProject.nameValidation")
|
|
645
1309
|
});
|
|
646
1310
|
if (p6.isCancel(name)) return null;
|
|
647
1311
|
const desc = await p6.text({
|
|
648
|
-
message: "
|
|
649
|
-
placeholder: "
|
|
1312
|
+
message: t("multiProject.descMsg"),
|
|
1313
|
+
placeholder: t("multiProject.descPlaceholder")
|
|
650
1314
|
});
|
|
651
1315
|
if (p6.isCancel(desc)) return null;
|
|
652
1316
|
const color = await p6.select({
|
|
653
|
-
message: "
|
|
654
|
-
options:
|
|
1317
|
+
message: t("multiProject.colorMsg"),
|
|
1318
|
+
options: getColorOptions()
|
|
655
1319
|
});
|
|
656
1320
|
if (p6.isCancel(color)) return null;
|
|
657
1321
|
const shared = await p6.select({
|
|
658
|
-
message: "
|
|
1322
|
+
message: t("multiProject.agentMsg"),
|
|
659
1323
|
options: [
|
|
660
|
-
{ value: "yes", label: "
|
|
661
|
-
{ value: "no", label: "
|
|
1324
|
+
{ value: "yes", label: t("multiProject.agentShared") },
|
|
1325
|
+
{ value: "no", label: t("multiProject.agentSeparate") }
|
|
662
1326
|
]
|
|
663
1327
|
});
|
|
664
1328
|
if (p6.isCancel(shared)) return null;
|
|
@@ -671,7 +1335,7 @@ async function promptMultiProject() {
|
|
|
671
1335
|
sharedAgents: shared === "yes"
|
|
672
1336
|
});
|
|
673
1337
|
const another = await p6.confirm({
|
|
674
|
-
message: "
|
|
1338
|
+
message: t("multiProject.anotherMsg"),
|
|
675
1339
|
initialValue: false
|
|
676
1340
|
});
|
|
677
1341
|
if (p6.isCancel(another)) return null;
|
|
@@ -683,19 +1347,19 @@ async function promptMultiProject() {
|
|
|
683
1347
|
// src/prompts/infra.ts
|
|
684
1348
|
import * as p7 from "@clack/prompts";
|
|
685
1349
|
async function promptInfra(projectName) {
|
|
686
|
-
p7.log.step("
|
|
1350
|
+
p7.log.step(t("infra.phase"));
|
|
687
1351
|
const slackChoice = await p7.select({
|
|
688
|
-
message: "
|
|
1352
|
+
message: t("infra.slackMsg"),
|
|
689
1353
|
options: [
|
|
690
|
-
{ value: "yes", label: "
|
|
691
|
-
{ value: "no", label: "
|
|
1354
|
+
{ value: "yes", label: t("infra.slackYes") },
|
|
1355
|
+
{ value: "no", label: t("infra.slackNo") }
|
|
692
1356
|
]
|
|
693
1357
|
});
|
|
694
1358
|
if (p7.isCancel(slackChoice)) return null;
|
|
695
1359
|
let slackCommand = "";
|
|
696
1360
|
if (slackChoice === "yes") {
|
|
697
1361
|
const cmd = await p7.text({
|
|
698
|
-
message: "
|
|
1362
|
+
message: t("infra.slackCommandMsg"),
|
|
699
1363
|
placeholder: `/${projectName.toLowerCase().replace(/[^a-z0-9]/g, "")}`,
|
|
700
1364
|
initialValue: `/${projectName.toLowerCase().replace(/[^a-z0-9]/g, "")}`
|
|
701
1365
|
});
|
|
@@ -703,19 +1367,19 @@ async function promptInfra(projectName) {
|
|
|
703
1367
|
slackCommand = cmd.trim();
|
|
704
1368
|
}
|
|
705
1369
|
const portInput = await p7.text({
|
|
706
|
-
message: "
|
|
1370
|
+
message: t("infra.portMsg"),
|
|
707
1371
|
placeholder: "4040",
|
|
708
1372
|
initialValue: "4040",
|
|
709
1373
|
validate: (v) => {
|
|
710
1374
|
const n = parseInt(v, 10);
|
|
711
|
-
if (isNaN(n) || n < 1 || n > 65535) return "
|
|
1375
|
+
if (isNaN(n) || n < 1 || n > 65535) return t("infra.portValidation");
|
|
712
1376
|
return void 0;
|
|
713
1377
|
}
|
|
714
1378
|
});
|
|
715
1379
|
if (p7.isCancel(portInput)) return null;
|
|
716
1380
|
const targetDir = await p7.text({
|
|
717
|
-
message: "
|
|
718
|
-
placeholder:
|
|
1381
|
+
message: t("infra.targetDirMsg"),
|
|
1382
|
+
placeholder: `./ ${t("infra.targetDirPlaceholder")}`,
|
|
719
1383
|
initialValue: "./"
|
|
720
1384
|
});
|
|
721
1385
|
if (p7.isCancel(targetDir)) return null;
|
|
@@ -816,8 +1480,7 @@ var FRONTEND_LABELS = {
|
|
|
816
1480
|
nextjs: "Next.js",
|
|
817
1481
|
"vue-nuxt": "Vue / Nuxt",
|
|
818
1482
|
svelte: "Svelte / SvelteKit",
|
|
819
|
-
angular: "Angular"
|
|
820
|
-
none: "(\uC5C6\uC74C)"
|
|
1483
|
+
angular: "Angular"
|
|
821
1484
|
};
|
|
822
1485
|
var BACKEND_LABELS = {
|
|
823
1486
|
supabase: "Supabase",
|
|
@@ -831,142 +1494,154 @@ var BACKEND_LABELS = {
|
|
|
831
1494
|
redis: "Redis",
|
|
832
1495
|
aws: "AWS",
|
|
833
1496
|
gcp: "GCP",
|
|
834
|
-
azure: "Azure"
|
|
835
|
-
docker: "Docker / K8s"
|
|
836
|
-
};
|
|
837
|
-
var DEPLOY_LABELS = {
|
|
838
|
-
vercel: "Vercel",
|
|
839
|
-
netlify: "Netlify",
|
|
840
|
-
aws: "AWS",
|
|
841
|
-
gcp: "GCP",
|
|
842
|
-
docker: "Docker \uC790\uCCB4 \uC11C\uBC84",
|
|
843
|
-
undecided: "\uBBF8\uC815"
|
|
844
|
-
};
|
|
845
|
-
var STAGE_LABELS = {
|
|
846
|
-
idea: "\uC544\uC774\uB514\uC5B4/\uAE30\uD68D \uB2E8\uACC4",
|
|
847
|
-
"dev-pre-mvp": "\uAC1C\uBC1C \uC9C4\uD589 \uC911 (MVP \uC804)",
|
|
848
|
-
"mvp-done": "MVP \uC644\uC131, \uAC1C\uC120 \uC911",
|
|
849
|
-
production: "\uC6B4\uC601 \uC911 (\uC720\uC9C0\uBCF4\uC218/\uAE30\uB2A5 \uCD94\uAC00)",
|
|
850
|
-
refactor: "\uB9AC\uD329\uD1A0\uB9C1/\uB9C8\uC774\uADF8\uB808\uC774\uC158"
|
|
851
|
-
};
|
|
852
|
-
var PROJECT_TYPE_LABELS = {
|
|
853
|
-
"web-app": "\uC6F9 \uC560\uD50C\uB9AC\uCF00\uC774\uC158",
|
|
854
|
-
mobile: "\uBAA8\uBC14\uC77C \uC571",
|
|
855
|
-
api: "API \uC11C\uBC84",
|
|
856
|
-
"data-pipeline": "\uB370\uC774\uD130 \uD30C\uC774\uD504\uB77C\uC778",
|
|
857
|
-
"ai-ml": "AI/ML",
|
|
858
|
-
content: "\uCF58\uD150\uCE20/\uB9C8\uCF00\uD305",
|
|
859
|
-
admin: "\uC0AC\uB0B4 \uB3C4\uAD6C",
|
|
860
|
-
library: "\uB77C\uC774\uBE0C\uB7EC\uB9AC/SDK"
|
|
861
|
-
};
|
|
862
|
-
var CODING_STYLE_LABELS = {
|
|
863
|
-
"functional-only": "\uD568\uC218\uD615 \uCEF4\uD3EC\uB10C\uD2B8 only (\uD074\uB798\uC2A4 \uAE08\uC9C0)",
|
|
864
|
-
"named-export": "Named export \uC120\uD638",
|
|
865
|
-
"no-any": "any \uD0C0\uC785 \uAE08\uC9C0 (unknown \uC120\uD638)",
|
|
866
|
-
"ko-comment": "\uD55C\uAD6D\uC5B4 \uC8FC\uC11D / \uD55C\uAD6D\uC5B4 \uCEE4\uBC0B",
|
|
867
|
-
"en-comment": "\uC601\uBB38 \uC8FC\uC11D / \uC601\uBB38 \uCEE4\uBC0B",
|
|
868
|
-
jsdoc: "JSDoc \uC8FC\uC11D",
|
|
869
|
-
"eslint-prettier": "ESLint + Prettier \uC801\uC6A9",
|
|
870
|
-
default: "\uAE30\uBCF8\uAC12 \uC0AC\uC6A9"
|
|
871
|
-
};
|
|
872
|
-
var CONCERN_LABELS = {
|
|
873
|
-
i18n: "\uB2E4\uAD6D\uC5B4 \uC9C0\uC6D0 (i18n)",
|
|
874
|
-
"dark-mode": "\uB2E4\uD06C\uBAA8\uB4DC",
|
|
875
|
-
a11y: "\uC811\uADFC\uC131 (a11y)",
|
|
876
|
-
seo: "SEO \uCD5C\uC801\uD654",
|
|
877
|
-
performance: "\uC131\uB2A5 \uCD5C\uC801\uD654 (Core Web Vitals)",
|
|
878
|
-
security: "\uBCF4\uC548 (\uC778\uC99D/\uAD8C\uD55C/XSS/CSRF)",
|
|
879
|
-
responsive: "\uBAA8\uBC14\uC77C \uBC18\uC751\uD615 \uD544\uC218",
|
|
880
|
-
none: "\uC5C6\uC74C"
|
|
1497
|
+
azure: "Azure"
|
|
881
1498
|
};
|
|
1499
|
+
function getDeployLabels() {
|
|
1500
|
+
return {
|
|
1501
|
+
vercel: "Vercel",
|
|
1502
|
+
netlify: "Netlify",
|
|
1503
|
+
aws: "AWS",
|
|
1504
|
+
gcp: "GCP",
|
|
1505
|
+
docker: t("contextGen.deployDocker"),
|
|
1506
|
+
undecided: t("contextGen.deployUndecided")
|
|
1507
|
+
};
|
|
1508
|
+
}
|
|
1509
|
+
function getStageLabels() {
|
|
1510
|
+
return {
|
|
1511
|
+
idea: t("contextGen.stageIdea"),
|
|
1512
|
+
"dev-pre-mvp": t("contextGen.stageDevPreMvp"),
|
|
1513
|
+
"mvp-done": t("contextGen.stageMvpDone"),
|
|
1514
|
+
production: t("contextGen.stageProduction"),
|
|
1515
|
+
refactor: t("contextGen.stageRefactor")
|
|
1516
|
+
};
|
|
1517
|
+
}
|
|
1518
|
+
function getProjectTypeLabels() {
|
|
1519
|
+
return {
|
|
1520
|
+
"web-app": t("contextGen.typeWebApp"),
|
|
1521
|
+
mobile: t("contextGen.typeMobile"),
|
|
1522
|
+
api: t("contextGen.typeApi"),
|
|
1523
|
+
"data-pipeline": t("contextGen.typeDataPipeline"),
|
|
1524
|
+
"ai-ml": t("contextGen.typeAiMl"),
|
|
1525
|
+
content: t("contextGen.typeContent"),
|
|
1526
|
+
admin: t("contextGen.typeAdmin"),
|
|
1527
|
+
library: t("contextGen.typeLibrary")
|
|
1528
|
+
};
|
|
1529
|
+
}
|
|
1530
|
+
function getCodingStyleLabels() {
|
|
1531
|
+
return {
|
|
1532
|
+
"functional-only": t("contextGen.styleFunctional"),
|
|
1533
|
+
"named-export": t("contextGen.styleNamedExport"),
|
|
1534
|
+
"no-any": t("contextGen.styleNoAny"),
|
|
1535
|
+
"ko-comment": t("contextGen.styleKoComment"),
|
|
1536
|
+
"en-comment": t("contextGen.styleEnComment"),
|
|
1537
|
+
jsdoc: t("contextGen.styleJsdoc"),
|
|
1538
|
+
"eslint-prettier": t("contextGen.styleEslint"),
|
|
1539
|
+
default: t("contextGen.styleDefault")
|
|
1540
|
+
};
|
|
1541
|
+
}
|
|
1542
|
+
function getConcernLabels() {
|
|
1543
|
+
return {
|
|
1544
|
+
i18n: t("contextGen.concernI18n"),
|
|
1545
|
+
"dark-mode": t("contextGen.concernDarkMode"),
|
|
1546
|
+
a11y: t("contextGen.concernA11y"),
|
|
1547
|
+
seo: t("contextGen.concernSeo"),
|
|
1548
|
+
performance: t("contextGen.concernPerformance"),
|
|
1549
|
+
security: t("contextGen.concernSecurity"),
|
|
1550
|
+
responsive: t("contextGen.concernResponsive"),
|
|
1551
|
+
none: t("contextGen.concernNone")
|
|
1552
|
+
};
|
|
1553
|
+
}
|
|
882
1554
|
function generateProjectContext(answers) {
|
|
883
1555
|
const { project, techStack, contextFiles, orchestrator, infra } = answers;
|
|
884
|
-
const frontendLabel = FRONTEND_LABELS[techStack.frontend] || techStack.frontend;
|
|
1556
|
+
const frontendLabel = techStack.frontend === "none" ? t("contextGen.frontendNone") : FRONTEND_LABELS[techStack.frontend] || techStack.frontend;
|
|
885
1557
|
const backendList = techStack.backend.map((b) => `- ${BACKEND_LABELS[b] || b}`).join("\n");
|
|
886
|
-
const deployLabel =
|
|
887
|
-
const stageLabel =
|
|
888
|
-
const typeLabels = project.types.map((
|
|
889
|
-
const dirLines = techStack.directories.length > 0 ? techStack.directories.map((d) => `- \`${d.path}\` \u2014 ${d.description}`).join("\n") :
|
|
1558
|
+
const deployLabel = getDeployLabels()[techStack.deploy] || techStack.deploy;
|
|
1559
|
+
const stageLabel = getStageLabels()[orchestrator.stage] || orchestrator.stage;
|
|
1560
|
+
const typeLabels = project.types.map((pt) => getProjectTypeLabels()[pt] || pt).join(", ");
|
|
1561
|
+
const dirLines = techStack.directories.length > 0 ? techStack.directories.map((d) => `- \`${d.path}\` \u2014 ${d.description}`).join("\n") : `- \`src/\` \u2014 ${t("contextGen.defaultDirSrc")}
|
|
1562
|
+
- \`docs/\` \u2014 ${t("contextGen.defaultDirDocs")}
|
|
1563
|
+
- \`tools/\` \u2014 ${t("contextGen.defaultDirTools")}`;
|
|
890
1564
|
let conventionLines;
|
|
891
1565
|
if (contextFiles.parsedContext) {
|
|
892
1566
|
const pc2 = contextFiles.parsedContext;
|
|
893
1567
|
const items = [];
|
|
894
1568
|
if (pc2.conventions.naming.length) items.push(...pc2.conventions.naming.map((n) => `- ${n}`));
|
|
895
1569
|
if (pc2.conventions.style.length) items.push(...pc2.conventions.style.map((s) => `- ${s}`));
|
|
896
|
-
if (pc2.conventions.tools.length) items.push(...pc2.conventions.tools.map((
|
|
1570
|
+
if (pc2.conventions.tools.length) items.push(...pc2.conventions.tools.map((v) => `- ${v}`));
|
|
897
1571
|
if (pc2.security.length) items.push(...pc2.security.map((s) => `- \u26A0\uFE0F ${s}`));
|
|
898
|
-
conventionLines = items.length > 0 ? items.join("\n") :
|
|
1572
|
+
conventionLines = items.length > 0 ? items.join("\n") : `- ${t("contextGen.noConventionsClaudeMd")}`;
|
|
899
1573
|
} else {
|
|
1574
|
+
const CODING_STYLE_LABELS = getCodingStyleLabels();
|
|
1575
|
+
const CONCERN_LABELS = getConcernLabels();
|
|
900
1576
|
const styleItems = contextFiles.codingStyle.filter((s) => s !== "default").map((s) => `- ${CODING_STYLE_LABELS[s] || s}`);
|
|
901
1577
|
const concernItems = contextFiles.concerns.filter((c) => c !== "none").map((c) => `- ${CONCERN_LABELS[c] || c}`);
|
|
902
|
-
conventionLines = [...styleItems, ...concernItems].join("\n") ||
|
|
1578
|
+
conventionLines = [...styleItems, ...concernItems].join("\n") || `- ${t("contextGen.noConventionsManual")}`;
|
|
903
1579
|
}
|
|
904
|
-
const refDocLines = contextFiles.referenceDocs.length > 0 ? contextFiles.referenceDocs.map((d) => `- **${d.type}**: \`${d.path}\``).join("\n") :
|
|
905
|
-
const goalsSection = orchestrator.goals || "
|
|
906
|
-
const constraintsSection = orchestrator.constraints || "
|
|
1580
|
+
const refDocLines = contextFiles.referenceDocs.length > 0 ? contextFiles.referenceDocs.map((d) => `- **${d.type}**: \`${d.path}\``).join("\n") : `- ${t("contextGen.noRefDocs")}`;
|
|
1581
|
+
const goalsSection = orchestrator.goals || t("contextGen.goalsPlaceholder");
|
|
1582
|
+
const constraintsSection = orchestrator.constraints || t("contextGen.constraintsPlaceholder");
|
|
907
1583
|
let brandSection = "";
|
|
908
1584
|
if (contextFiles.parsedContext) {
|
|
909
1585
|
const pc2 = contextFiles.parsedContext;
|
|
910
1586
|
const items = [];
|
|
911
|
-
if (pc2.fonts.length) items.push(`-
|
|
912
|
-
if (pc2.colors.length) items.push(`-
|
|
913
|
-
if (pc2.i18n.length) items.push(`-
|
|
1587
|
+
if (pc2.fonts.length) items.push(`- **${t("contextGen.labelFonts")}**: ${pc2.fonts.join(", ")}`);
|
|
1588
|
+
if (pc2.colors.length) items.push(`- **${t("contextGen.labelColors")}**: ${pc2.colors.join(", ")}`);
|
|
1589
|
+
if (pc2.i18n.length) items.push(`- **${t("contextGen.labelI18n")}**: ${pc2.i18n.join(", ")}`);
|
|
914
1590
|
if (items.length) brandSection = `
|
|
915
|
-
##
|
|
1591
|
+
## ${t("contextGen.sectionBrand")}
|
|
916
1592
|
|
|
917
1593
|
${items.join("\n")}
|
|
918
1594
|
`;
|
|
919
1595
|
}
|
|
920
|
-
return `# ${project.name}
|
|
1596
|
+
return `# ${t("contextGen.title", { name: project.name })}
|
|
921
1597
|
|
|
922
|
-
|
|
923
|
-
\uAC01 \uC5D0\uC774\uC804\uD2B8\uB294 \uC774 \uBB38\uC11C\uB97C \uC219\uC9C0\uD55C \uC0C1\uD0DC\uC5D0\uC11C \uC790\uAE30 \uC5ED\uD560\uC744 \uC218\uD589\uD55C\uB2E4.
|
|
1598
|
+
${t("contextGen.intro")}
|
|
924
1599
|
|
|
925
|
-
##
|
|
1600
|
+
## ${t("contextGen.sectionOverview")}
|
|
926
1601
|
|
|
927
1602
|
${project.description}
|
|
928
1603
|
|
|
929
|
-
-
|
|
930
|
-
-
|
|
1604
|
+
- **${t("contextGen.labelType")}**: ${typeLabels}
|
|
1605
|
+
- **${t("contextGen.labelStage")}**: ${stageLabel}
|
|
931
1606
|
|
|
932
|
-
##
|
|
1607
|
+
## ${t("contextGen.sectionStack")}
|
|
933
1608
|
|
|
934
|
-
-
|
|
935
|
-
${backendList ||
|
|
936
|
-
-
|
|
1609
|
+
- **${t("contextGen.labelFrontend")}**: ${frontendLabel}
|
|
1610
|
+
${backendList || `- ${t("contextGen.backendFallback")}`}
|
|
1611
|
+
- **${t("contextGen.labelDeploy")}**: ${deployLabel}
|
|
937
1612
|
|
|
938
|
-
##
|
|
1613
|
+
## ${t("contextGen.sectionDirs")}
|
|
939
1614
|
|
|
940
1615
|
${dirLines}
|
|
941
1616
|
|
|
942
|
-
##
|
|
1617
|
+
## ${t("contextGen.sectionConventions")}
|
|
943
1618
|
|
|
944
1619
|
${conventionLines}
|
|
945
1620
|
${brandSection}
|
|
946
|
-
##
|
|
1621
|
+
## ${t("contextGen.sectionGoals")}
|
|
947
1622
|
|
|
948
1623
|
${goalsSection}
|
|
949
1624
|
|
|
950
|
-
##
|
|
1625
|
+
## ${t("contextGen.sectionConstraints")}
|
|
951
1626
|
|
|
952
1627
|
${constraintsSection}
|
|
953
1628
|
|
|
954
|
-
##
|
|
1629
|
+
## ${t("contextGen.sectionRefDocs")}
|
|
955
1630
|
|
|
956
1631
|
${refDocLines}
|
|
957
1632
|
|
|
958
|
-
##
|
|
1633
|
+
## ${t("contextGen.sectionProtocol")}
|
|
959
1634
|
|
|
960
|
-
-
|
|
961
|
-
-
|
|
962
|
-
-
|
|
963
|
-
-
|
|
1635
|
+
- **${t("contextGen.protocolKanban")}**: \`http://localhost:${infra.port}\`
|
|
1636
|
+
- **${t("contextGen.protocolSlack")}**: \`POST http://localhost:${infra.port}/api/tasks/{TASK_ID}/slack\`
|
|
1637
|
+
- **${t("contextGen.protocolLogs")}**: \`.claude/logs/\`
|
|
1638
|
+
- **${t("contextGen.protocolStatus")}**: pending \u2192 in_progress \u2192 in_review \u2192 completed
|
|
964
1639
|
|
|
965
|
-
|
|
1640
|
+
${t("contextGen.protocolInstruction")}
|
|
966
1641
|
|
|
967
|
-
1.
|
|
968
|
-
2.
|
|
969
|
-
3.
|
|
1642
|
+
1. **${t("contextGen.protocolSlackReport")}**: \`curl -s -X POST http://localhost:${infra.port}/api/tasks/{TASK_ID}/slack -H "Content-Type: application/json" -d '{"text":"${t("contextGen.protocolSlackExample")}"}' \`
|
|
1643
|
+
2. **${t("contextGen.protocolKanbanUpdate")}**: \`PUT http://localhost:${infra.port}/api/tasks/{id}\` (status, reportSummary, reportPath)
|
|
1644
|
+
3. **${t("contextGen.protocolLogFile")}**: \`.claude/logs/{YYYY-MM-DD}_{task-slug}.md\`
|
|
970
1645
|
`;
|
|
971
1646
|
}
|
|
972
1647
|
|
|
@@ -1156,30 +1831,30 @@ var AGENT_DISPLAY_NAMES = {
|
|
|
1156
1831
|
function buildBaseSections(answers) {
|
|
1157
1832
|
const port = answers.infra.port;
|
|
1158
1833
|
return `## Project Context
|
|
1159
|
-
-
|
|
1160
|
-
-
|
|
1161
|
-
-
|
|
1162
|
-
-
|
|
1163
|
-
-
|
|
1834
|
+
- **${t("agentGen.projectLabel")}**: ${answers.project.name}
|
|
1835
|
+
- **${t("agentGen.descLabel")}**: ${answers.project.description}
|
|
1836
|
+
- **${t("agentGen.kanbanApiLabel")}**: \`http://localhost:${port}/api/tasks\`
|
|
1837
|
+
- **${t("agentGen.slackApiLabel")}**: \`POST http://localhost:${port}/api/tasks/{TASK_ID}/slack\`
|
|
1838
|
+
- **${t("agentGen.logDirLabel")}**: \`.claude/logs/\`
|
|
1164
1839
|
|
|
1165
1840
|
## Slack Reporting
|
|
1166
|
-
|
|
1841
|
+
${t("agentGen.slackReportingDesc")}
|
|
1167
1842
|
\`\`\`bash
|
|
1168
1843
|
curl -s -X POST http://localhost:${port}/api/tasks/{TASK_ID}/slack \\
|
|
1169
|
-
-H "Content-Type: application/json" -d '{"text":"
|
|
1844
|
+
-H "Content-Type: application/json" -d '{"text":"${t("contextGen.protocolSlackExample")}"}'
|
|
1170
1845
|
\`\`\`
|
|
1171
|
-
|
|
1172
|
-
|
|
1846
|
+
${t("agentGen.slackForbid")}
|
|
1847
|
+
${t("agentGen.slackTaskIdNote")}
|
|
1173
1848
|
|
|
1174
1849
|
## Kanban Update
|
|
1175
|
-
1.
|
|
1176
|
-
2.
|
|
1177
|
-
3. reportSummary
|
|
1850
|
+
1. ${t("agentGen.kanbanStart")}: \`PUT /api/tasks/{id}\` \u2014 \`status: "in_progress"\`, \`activeForm: "${t("agentGen.kanbanActiveForm")}"\`
|
|
1851
|
+
2. ${t("agentGen.kanbanDone")}: \`PUT /api/tasks/{id}\` \u2014 \`status: "completed"\`, \`reportPath\`, \`reportSummary\`
|
|
1852
|
+
3. reportSummary: \`${t("agentGen.kanbanReportFormat")}\`
|
|
1178
1853
|
|
|
1179
1854
|
## Report File
|
|
1180
|
-
|
|
1181
|
-
-
|
|
1182
|
-
-
|
|
1855
|
+
${t("agentGen.reportDesc")}
|
|
1856
|
+
- ${t("agentGen.reportPathLabel")}: \`.claude/logs/{YYYY-MM-DD}_{task-slug}.md\`
|
|
1857
|
+
- ${t("agentGen.reportContentDesc")}`;
|
|
1183
1858
|
}
|
|
1184
1859
|
function buildConventionsSection(answers) {
|
|
1185
1860
|
const lines = [];
|
|
@@ -1187,10 +1862,10 @@ function buildConventionsSection(answers) {
|
|
|
1187
1862
|
if (ctx) {
|
|
1188
1863
|
if (ctx.conventions.naming.length) lines.push(...ctx.conventions.naming.map((n) => `- ${n}`));
|
|
1189
1864
|
if (ctx.conventions.style.length) lines.push(...ctx.conventions.style.map((s) => `- ${s}`));
|
|
1190
|
-
if (ctx.conventions.tools.length) lines.push(...ctx.conventions.tools.map((
|
|
1865
|
+
if (ctx.conventions.tools.length) lines.push(...ctx.conventions.tools.map((v) => `- ${v}`));
|
|
1191
1866
|
if (ctx.security.length) lines.push(...ctx.security.map((s) => `- \u26A0\uFE0F ${s}`));
|
|
1192
|
-
if (ctx.fonts.length) lines.push(`-
|
|
1193
|
-
if (ctx.colors.length) lines.push(`-
|
|
1867
|
+
if (ctx.fonts.length) lines.push(`- ${t("agentGen.fontsLabel")}: ${ctx.fonts.join(", ")}`);
|
|
1868
|
+
if (ctx.colors.length) lines.push(`- ${t("agentGen.colorsLabel")}: ${ctx.colors.join(", ")}`);
|
|
1194
1869
|
} else {
|
|
1195
1870
|
for (const s of answers.contextFiles.codingStyle) {
|
|
1196
1871
|
if (s !== "default") lines.push(`- ${s}`);
|
|
@@ -1253,13 +1928,13 @@ ${constraints}
|
|
|
1253
1928
|
// src/generators/env-file.ts
|
|
1254
1929
|
function generateEnvFile(answers) {
|
|
1255
1930
|
const lines = [
|
|
1256
|
-
"
|
|
1931
|
+
t("envGen.kanbanServer"),
|
|
1257
1932
|
`PORT=${answers.infra.port}`,
|
|
1258
1933
|
""
|
|
1259
1934
|
];
|
|
1260
1935
|
if (answers.infra.slackEnabled) {
|
|
1261
1936
|
lines.push(
|
|
1262
|
-
"
|
|
1937
|
+
t("envGen.slackIntegration"),
|
|
1263
1938
|
"SLACK_BOT_TOKEN=xoxb-...",
|
|
1264
1939
|
"SLACK_APP_TOKEN=xapp-...",
|
|
1265
1940
|
"SLACK_CHANNEL_ID=C...",
|
|
@@ -1268,7 +1943,7 @@ function generateEnvFile(answers) {
|
|
|
1268
1943
|
);
|
|
1269
1944
|
} else {
|
|
1270
1945
|
lines.push(
|
|
1271
|
-
"
|
|
1946
|
+
t("envGen.slackLater"),
|
|
1272
1947
|
"# SLACK_BOT_TOKEN=xoxb-...",
|
|
1273
1948
|
"# SLACK_APP_TOKEN=xapp-...",
|
|
1274
1949
|
"# SLACK_CHANNEL_ID=C...",
|
|
@@ -1304,7 +1979,7 @@ async function scaffold(answers) {
|
|
|
1304
1979
|
const targetDir = path5.resolve(answers.infra.targetDir);
|
|
1305
1980
|
const templatesDir = getTemplatesDir();
|
|
1306
1981
|
const s = p8.spinner();
|
|
1307
|
-
s.start("
|
|
1982
|
+
s.start(t("scaffold.dirCreating"));
|
|
1308
1983
|
await fs6.ensureDir(path5.join(targetDir, "tools"));
|
|
1309
1984
|
await fs6.ensureDir(path5.join(targetDir, ".claude", "agents"));
|
|
1310
1985
|
await fs6.ensureDir(path5.join(targetDir, ".claude", "logs"));
|
|
@@ -1312,29 +1987,29 @@ async function scaffold(answers) {
|
|
|
1312
1987
|
for (const proj of answers.additionalProjects) {
|
|
1313
1988
|
await fs6.ensureDir(path5.join(targetDir, ".claude", "tasks", proj.id));
|
|
1314
1989
|
}
|
|
1315
|
-
s.stop("
|
|
1316
|
-
s.start("
|
|
1990
|
+
s.stop(t("scaffold.dirDone"));
|
|
1991
|
+
s.start(t("scaffold.kanbanServerCopying"));
|
|
1317
1992
|
const kanbanSrc = path5.join(templatesDir, "kanban.cjs");
|
|
1318
1993
|
const kanbanDest = path5.join(targetDir, "tools", "kanban.cjs");
|
|
1319
1994
|
if (fs6.existsSync(kanbanSrc)) {
|
|
1320
1995
|
await fs6.copy(kanbanSrc, kanbanDest);
|
|
1321
1996
|
}
|
|
1322
|
-
s.stop("
|
|
1323
|
-
s.start("
|
|
1997
|
+
s.stop(t("scaffold.kanbanServerDone"));
|
|
1998
|
+
s.start(t("scaffold.kanbanUICopying"));
|
|
1324
1999
|
const htmlSrc = path5.join(templatesDir, "kanban.html");
|
|
1325
2000
|
const htmlDest = path5.join(targetDir, "tools", "kanban.html");
|
|
1326
2001
|
if (fs6.existsSync(htmlSrc)) {
|
|
1327
2002
|
await fs6.copy(htmlSrc, htmlDest);
|
|
1328
2003
|
}
|
|
1329
|
-
s.stop("
|
|
1330
|
-
s.start("
|
|
2004
|
+
s.stop(t("scaffold.kanbanUIDone"));
|
|
2005
|
+
s.start(t("scaffold.configCreating"));
|
|
1331
2006
|
const config = generateConfig(answers);
|
|
1332
2007
|
await fs6.writeFile(
|
|
1333
2008
|
path5.join(targetDir, "kanban.config.json"),
|
|
1334
2009
|
JSON.stringify(config, null, 2)
|
|
1335
2010
|
);
|
|
1336
|
-
s.stop("
|
|
1337
|
-
s.start("
|
|
2011
|
+
s.stop(t("scaffold.configDone"));
|
|
2012
|
+
s.start(t("scaffold.projectListCreating"));
|
|
1338
2013
|
const projects = config.projects.map((proj) => ({
|
|
1339
2014
|
...proj,
|
|
1340
2015
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -1343,15 +2018,15 @@ async function scaffold(answers) {
|
|
|
1343
2018
|
path5.join(targetDir, ".claude", "tasks", "_projects.json"),
|
|
1344
2019
|
JSON.stringify(projects, null, 2)
|
|
1345
2020
|
);
|
|
1346
|
-
s.stop("
|
|
1347
|
-
s.start("
|
|
2021
|
+
s.stop(t("scaffold.projectListDone"));
|
|
2022
|
+
s.start(t("scaffold.contextCreating"));
|
|
1348
2023
|
const projectContext = generateProjectContext(answers);
|
|
1349
2024
|
await fs6.writeFile(
|
|
1350
2025
|
path5.join(targetDir, ".claude", "agents", "_project-context.md"),
|
|
1351
2026
|
projectContext
|
|
1352
2027
|
);
|
|
1353
|
-
s.stop("
|
|
1354
|
-
s.start("
|
|
2028
|
+
s.stop(t("scaffold.contextDone"));
|
|
2029
|
+
s.start(t("scaffold.agentsCreating"));
|
|
1355
2030
|
for (const agent of answers.agents.selectedAgents) {
|
|
1356
2031
|
const model = getModelForAgent(agent, answers.agents.defaultModel, answers.agents.modelOverrides);
|
|
1357
2032
|
const prompt = generateAgentPrompt(agent, answers, model, templatesDir);
|
|
@@ -1360,8 +2035,8 @@ async function scaffold(answers) {
|
|
|
1360
2035
|
prompt
|
|
1361
2036
|
);
|
|
1362
2037
|
}
|
|
1363
|
-
s.stop(
|
|
1364
|
-
s.start("
|
|
2038
|
+
s.stop(t("scaffold.agentsDone", { count: answers.agents.selectedAgents.length }));
|
|
2039
|
+
s.start(t("scaffold.orchestratorCreating"));
|
|
1365
2040
|
const orchSrc = path5.join(templatesDir, "orchestrator.md");
|
|
1366
2041
|
if (fs6.existsSync(orchSrc)) {
|
|
1367
2042
|
let orchContent = await fs6.readFile(orchSrc, "utf-8");
|
|
@@ -1369,7 +2044,7 @@ async function scaffold(answers) {
|
|
|
1369
2044
|
orchContent = orchContent.replace(/\{\{port\}\}/g, String(answers.infra.port));
|
|
1370
2045
|
orchContent = orchContent.replace(/\{\{goals\}\}/g, answers.orchestrator.goals);
|
|
1371
2046
|
orchContent = orchContent.replace(/\{\{stage\}\}/g, answers.orchestrator.stage);
|
|
1372
|
-
orchContent = orchContent.replace(/\{\{constraints\}\}/g, answers.orchestrator.constraints ||
|
|
2047
|
+
orchContent = orchContent.replace(/\{\{constraints\}\}/g, answers.orchestrator.constraints || t("scaffold.noConstraints"));
|
|
1373
2048
|
const agentRows = answers.agents.selectedAgents.map((a) => {
|
|
1374
2049
|
const model = getModelForAgent(a, answers.agents.defaultModel, answers.agents.modelOverrides);
|
|
1375
2050
|
return `| ${a} | ${model} |`;
|
|
@@ -1380,14 +2055,14 @@ async function scaffold(answers) {
|
|
|
1380
2055
|
orchContent
|
|
1381
2056
|
);
|
|
1382
2057
|
}
|
|
1383
|
-
s.stop("
|
|
1384
|
-
s.start(".
|
|
2058
|
+
s.stop(t("scaffold.orchestratorDone"));
|
|
2059
|
+
s.start(t("scaffold.envCreating"));
|
|
1385
2060
|
const envContent = generateEnvFile(answers);
|
|
1386
2061
|
await fs6.writeFile(
|
|
1387
2062
|
path5.join(targetDir, ".env.example"),
|
|
1388
2063
|
envContent
|
|
1389
2064
|
);
|
|
1390
|
-
s.stop(".
|
|
2065
|
+
s.stop(t("scaffold.envDone"));
|
|
1391
2066
|
await initGit(targetDir);
|
|
1392
2067
|
}
|
|
1393
2068
|
|
|
@@ -1395,27 +2070,39 @@ async function scaffold(answers) {
|
|
|
1395
2070
|
async function main() {
|
|
1396
2071
|
console.log();
|
|
1397
2072
|
p9.intro(`${pc.bgCyan(pc.black(" create-claude-kanban "))} ${pc.dim("v2.0.0")}`);
|
|
2073
|
+
const langChoice = await p9.select({
|
|
2074
|
+
message: "Language / \uC5B8\uC5B4",
|
|
2075
|
+
options: [
|
|
2076
|
+
{ value: "en", label: "English" },
|
|
2077
|
+
{ value: "ko", label: "\uD55C\uAD6D\uC5B4" }
|
|
2078
|
+
]
|
|
2079
|
+
});
|
|
2080
|
+
if (p9.isCancel(langChoice)) {
|
|
2081
|
+
p9.cancel("Cancelled.");
|
|
2082
|
+
process.exit(0);
|
|
2083
|
+
}
|
|
2084
|
+
setLang(langChoice);
|
|
1398
2085
|
const answers = await runPrompts();
|
|
1399
2086
|
if (!answers) {
|
|
1400
|
-
p9.cancel("
|
|
2087
|
+
p9.cancel(t("common.cancelled"));
|
|
1401
2088
|
process.exit(0);
|
|
1402
2089
|
}
|
|
1403
2090
|
await scaffold(answers);
|
|
1404
2091
|
const projectCount = 1 + answers.additionalProjects.length;
|
|
1405
2092
|
const files = [
|
|
1406
|
-
`tools/kanban.cjs \u2014
|
|
1407
|
-
`tools/kanban.html \u2014
|
|
1408
|
-
`kanban.config.json \u2014
|
|
1409
|
-
`.claude/agents/ \u2014
|
|
1410
|
-
`.claude/agents/_project-context.md \u2014
|
|
1411
|
-
`.claude/orchestrator.md \u2014
|
|
1412
|
-
`.env.example \u2014
|
|
2093
|
+
`tools/kanban.cjs \u2014 ${t("index.fileKanbanServer")}`,
|
|
2094
|
+
`tools/kanban.html \u2014 ${t("index.fileKanbanUI")}`,
|
|
2095
|
+
`kanban.config.json \u2014 ${t("index.fileConfig", { count: projectCount })}`,
|
|
2096
|
+
`.claude/agents/ \u2014 ${t("index.fileAgents", { count: answers.agents.selectedAgents.length })}`,
|
|
2097
|
+
`.claude/agents/_project-context.md \u2014 ${t("index.fileContext")}`,
|
|
2098
|
+
`.claude/orchestrator.md \u2014 ${t("index.fileOrchestrator")}`,
|
|
2099
|
+
`.env.example \u2014 ${t("index.fileEnv")}`
|
|
1413
2100
|
];
|
|
1414
|
-
p9.note(files.join("\n"), "
|
|
1415
|
-
p9.outro(`${pc.green("node tools/kanban.cjs")}
|
|
2101
|
+
p9.note(files.join("\n"), t("index.filesHeader"));
|
|
2102
|
+
p9.outro(`${pc.green("node tools/kanban.cjs")} ${t("index.startCmd")}`);
|
|
1416
2103
|
}
|
|
1417
2104
|
main().catch((err) => {
|
|
1418
|
-
p9.cancel("
|
|
2105
|
+
p9.cancel(t("common.error"));
|
|
1419
2106
|
console.error(err);
|
|
1420
2107
|
process.exit(1);
|
|
1421
2108
|
});
|