@vibecodetown/mcp-server 2.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.
Files changed (172) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +269 -0
  3. package/build/auth/gate.js +225 -0
  4. package/build/auth/index.js +55 -0
  5. package/build/auth/public_key.js +27 -0
  6. package/build/auth/token_cache.js +122 -0
  7. package/build/auth/token_verifier.js +103 -0
  8. package/build/bootstrap/doctor.js +115 -0
  9. package/build/bootstrap/installer.js +673 -0
  10. package/build/bootstrap/lock.js +37 -0
  11. package/build/bootstrap/platform.js +26 -0
  12. package/build/bootstrap/registry.js +37 -0
  13. package/build/cache/index.js +147 -0
  14. package/build/cli.js +101 -0
  15. package/build/contracts.js +22 -0
  16. package/build/control_plane/gate.js +161 -0
  17. package/build/control_plane/index.js +6 -0
  18. package/build/dx/activity.js +139 -0
  19. package/build/engine.js +106 -0
  20. package/build/errors.js +171 -0
  21. package/build/generated/activate_input.js +2 -0
  22. package/build/generated/activate_output.js +57 -0
  23. package/build/generated/advisory_review_input.js +2 -0
  24. package/build/generated/advisory_review_output.js +35 -0
  25. package/build/generated/auth_token_file.js +2 -0
  26. package/build/generated/briefing_input.js +2 -0
  27. package/build/generated/briefing_output.js +2 -0
  28. package/build/generated/clinic_bridge_file.js +13 -0
  29. package/build/generated/contracts_bundle_info.js +5 -0
  30. package/build/generated/create_work_order_input.js +2 -0
  31. package/build/generated/create_work_order_output.js +2 -0
  32. package/build/generated/current_work_order_file.js +2 -0
  33. package/build/generated/doctor_input.js +2 -0
  34. package/build/generated/doctor_output.js +24 -0
  35. package/build/generated/execution_result.js +2 -0
  36. package/build/generated/execution_task.js +2 -0
  37. package/build/generated/export_output_input.js +2 -0
  38. package/build/generated/export_output_output.js +2 -0
  39. package/build/generated/finalize_work_input.js +2 -0
  40. package/build/generated/finalize_work_output.js +2 -0
  41. package/build/generated/gate_input.js +2 -0
  42. package/build/generated/gate_output.js +2 -0
  43. package/build/generated/gate_result_v1.js +2 -0
  44. package/build/generated/get_decision_input.js +2 -0
  45. package/build/generated/get_decision_output.js +13 -0
  46. package/build/generated/handoff_to_clinic.js +2 -0
  47. package/build/generated/index.js +75 -0
  48. package/build/generated/inspect_code_input.js +2 -0
  49. package/build/generated/inspect_code_output.js +13 -0
  50. package/build/generated/memory_retrieve_output.js +2 -0
  51. package/build/generated/memory_state_file.js +2 -0
  52. package/build/generated/memory_status_input.js +2 -0
  53. package/build/generated/memory_status_output.js +13 -0
  54. package/build/generated/memory_sync_input.js +2 -0
  55. package/build/generated/memory_sync_output.js +13 -0
  56. package/build/generated/plugin_result.js +2 -0
  57. package/build/generated/react_perf_check_patterns_input.js +2 -0
  58. package/build/generated/react_perf_check_patterns_output.js +2 -0
  59. package/build/generated/react_perf_generate_report_input.js +2 -0
  60. package/build/generated/react_perf_generate_report_output.js +2 -0
  61. package/build/generated/repair_plan_input.js +2 -0
  62. package/build/generated/repair_plan_output.js +2 -0
  63. package/build/generated/run_app_input.js +2 -0
  64. package/build/generated/run_app_output.js +2 -0
  65. package/build/generated/run_state_file.js +13 -0
  66. package/build/generated/scaffold_input.js +2 -0
  67. package/build/generated/scaffold_output.js +2 -0
  68. package/build/generated/search_oss_input.js +2 -0
  69. package/build/generated/search_oss_output.js +2 -0
  70. package/build/generated/selection_validation_result.js +2 -0
  71. package/build/generated/signal_agent_input.js +2 -0
  72. package/build/generated/spec_high_ask_queue_items_file.js +2 -0
  73. package/build/generated/spec_high_clinic_bridge_output.js +2 -0
  74. package/build/generated/spec_high_decision_draft_output.js +2 -0
  75. package/build/generated/spec_high_validate_output.js +2 -0
  76. package/build/generated/status_input.js +2 -0
  77. package/build/generated/status_output.js +2 -0
  78. package/build/generated/submit_decision_input.js +2 -0
  79. package/build/generated/submit_decision_output.js +2 -0
  80. package/build/generated/tool_error_output.js +2 -0
  81. package/build/generated/undo_last_task_input.js +2 -0
  82. package/build/generated/undo_last_task_output.js +2 -0
  83. package/build/generated/update_input.js +2 -0
  84. package/build/generated/update_output.js +2 -0
  85. package/build/generated/vibe_pm_inspection_result.js +2 -0
  86. package/build/generated/vibe_pm_report_markdown.js +2 -0
  87. package/build/generated/vibe_pm_verdict.js +2 -0
  88. package/build/generated/vibe_repo_config.js +2 -0
  89. package/build/generated/vibecoding_helper_answer_output.js +2 -0
  90. package/build/generated/vibecoding_helper_one_loop_selection_output.js +2 -0
  91. package/build/generated/vibecoding_helper_show_ask_queue_output.js +2 -0
  92. package/build/generated/work_order_v1.js +2 -0
  93. package/build/generated/zoekt_evidence_input.js +2 -0
  94. package/build/generated/zoekt_evidence_output.js +2 -0
  95. package/build/index.js +111 -0
  96. package/build/legacy_alias.js +65 -0
  97. package/build/local-mode/bash.js +61 -0
  98. package/build/local-mode/config.js +171 -0
  99. package/build/local-mode/git.js +33 -0
  100. package/build/local-mode/init.js +110 -0
  101. package/build/local-mode/paths.js +24 -0
  102. package/build/local-mode/templates.js +856 -0
  103. package/build/local-mode/work-order.js +41 -0
  104. package/build/resources/index.js +246 -0
  105. package/build/security/input-validator.js +119 -0
  106. package/build/security/path-policy.js +289 -0
  107. package/build/security/sandbox.js +228 -0
  108. package/build/tools/react_perf/check_patterns.js +172 -0
  109. package/build/tools/react_perf/generate_report.js +337 -0
  110. package/build/tools/react_perf/index.js +119 -0
  111. package/build/tools/react_perf/rules/advanced.js +325 -0
  112. package/build/tools/react_perf/rules/async.js +104 -0
  113. package/build/tools/react_perf/rules/bundle.js +101 -0
  114. package/build/tools/react_perf/rules/client.js +186 -0
  115. package/build/tools/react_perf/rules/index.js +74 -0
  116. package/build/tools/react_perf/rules/js.js +148 -0
  117. package/build/tools/react_perf/rules/rendering.js +166 -0
  118. package/build/tools/react_perf/rules/rerender.js +161 -0
  119. package/build/tools/react_perf/rules/server.js +141 -0
  120. package/build/tools/react_perf/types.js +127 -0
  121. package/build/tools/vibe_pm/activate.js +102 -0
  122. package/build/tools/vibe_pm/advisory_review.js +77 -0
  123. package/build/tools/vibe_pm/briefing.js +178 -0
  124. package/build/tools/vibe_pm/context.js +439 -0
  125. package/build/tools/vibe_pm/create_work_order.js +271 -0
  126. package/build/tools/vibe_pm/doc_status_gate.js +370 -0
  127. package/build/tools/vibe_pm/doctor.js +262 -0
  128. package/build/tools/vibe_pm/entity_gate/preflight.js +78 -0
  129. package/build/tools/vibe_pm/export_output.js +135 -0
  130. package/build/tools/vibe_pm/finalize_work.js +393 -0
  131. package/build/tools/vibe_pm/gate.js +33 -0
  132. package/build/tools/vibe_pm/get_decision.js +281 -0
  133. package/build/tools/vibe_pm/index.js +593 -0
  134. package/build/tools/vibe_pm/inspect_code.js +828 -0
  135. package/build/tools/vibe_pm/intent/generator.js +294 -0
  136. package/build/tools/vibe_pm/intent/index.js +5 -0
  137. package/build/tools/vibe_pm/intent/prompt_density.js +227 -0
  138. package/build/tools/vibe_pm/intent/types.js +70 -0
  139. package/build/tools/vibe_pm/intent/verifier.js +237 -0
  140. package/build/tools/vibe_pm/kce/doc_usage.js +51 -0
  141. package/build/tools/vibe_pm/kce/on_finalize.js +11 -0
  142. package/build/tools/vibe_pm/kce/preflight.js +232 -0
  143. package/build/tools/vibe_pm/local_memory.js +26 -0
  144. package/build/tools/vibe_pm/memory_status.js +82 -0
  145. package/build/tools/vibe_pm/memory_sync.js +134 -0
  146. package/build/tools/vibe_pm/modules/decision_snapshot.js +29 -0
  147. package/build/tools/vibe_pm/modules/ensure.js +100 -0
  148. package/build/tools/vibe_pm/modules/fingerprint.js +30 -0
  149. package/build/tools/vibe_pm/modules/fix_dependencies.js +394 -0
  150. package/build/tools/vibe_pm/modules/planning_v1.js +110 -0
  151. package/build/tools/vibe_pm/modules/repo_context.js +56 -0
  152. package/build/tools/vibe_pm/modules/research_v1.js +114 -0
  153. package/build/tools/vibe_pm/modules/skills_v1.js +100 -0
  154. package/build/tools/vibe_pm/pm_language.js +222 -0
  155. package/build/tools/vibe_pm/repair_plan.js +199 -0
  156. package/build/tools/vibe_pm/run_app.js +597 -0
  157. package/build/tools/vibe_pm/run_app_podman.js +64 -0
  158. package/build/tools/vibe_pm/scaffold.js +550 -0
  159. package/build/tools/vibe_pm/search_oss.js +124 -0
  160. package/build/tools/vibe_pm/status.js +153 -0
  161. package/build/tools/vibe_pm/submit_decision.js +87 -0
  162. package/build/tools/vibe_pm/system_design/issue_mapping.js +47 -0
  163. package/build/tools/vibe_pm/system_design/rulebook.js +112 -0
  164. package/build/tools/vibe_pm/system_design/semgrep.js +132 -0
  165. package/build/tools/vibe_pm/types.js +229 -0
  166. package/build/tools/vibe_pm/undo_last_task.js +163 -0
  167. package/build/tools/vibe_pm/update.js +146 -0
  168. package/build/tools/vibe_pm/zoekt_evidence.js +96 -0
  169. package/build/tools.js +269 -0
  170. package/build/version-check.js +239 -0
  171. package/build/vibe-cli.js +631 -0
  172. package/package.json +76 -0
@@ -0,0 +1,281 @@
1
+ // adapters/mcp-ts/src/tools/vibe_pm/get_decision.ts
2
+ // vibe_pm.get_decision - Fetch approval items
3
+ import * as fs from "node:fs";
4
+ import * as path from "node:path";
5
+ import { runEngineWithCache } from "../../engine.js";
6
+ import { safeJsonParse } from "../../cli.js";
7
+ import { getRunsDir, resolveRunId, resolveProjectId, resolveSpecHighRunDir } from "./context.js";
8
+ import { transformAskQueueText } from "./pm_language.js";
9
+ import { maybeGetLocalMemoryContextBlock } from "./local_memory.js";
10
+ import { validateToolInput } from "../../security/input-validator.js";
11
+ import { loadPromptDensity } from "./intent/prompt_density.js";
12
+ import { SpecHighAskQueueItemsFileSchema } from "../../generated/spec_high_ask_queue_items_file.js";
13
+ import { VibecodingHelperShowAskQueueOutputSchema } from "../../generated/vibecoding_helper_show_ask_queue_output.js";
14
+ /**
15
+ * vibe_pm.get_decision - Fetch approval items in PM language
16
+ *
17
+ * Internal mapping:
18
+ * → vibecoding-helper show-ask-queue <run_id>
19
+ * → PM language transform
20
+ */
21
+ export async function getDecision(input, basePath = process.cwd()) {
22
+ validateToolInput({ project_id: input.project_id });
23
+ // Resolve run_id
24
+ const { run_id, is_new } = resolveRunId(input.project_id, basePath);
25
+ const project_id = resolveProjectId(run_id, basePath);
26
+ // Prompt density mode (internal only; never expose to user)
27
+ const promptDensityMode = loadPromptDensity(getRunsDir(basePath), run_id)?.mode ?? "mode_0";
28
+ // If no existing run, return empty
29
+ if (is_new) {
30
+ return {
31
+ project_id,
32
+ decision_requests: [],
33
+ next_action: null
34
+ };
35
+ }
36
+ let items = [];
37
+ // Prefer reading Spec-High ask_queue_items.json directly (SSOT).
38
+ // This keeps get_decision deterministic and avoids parsing human text.
39
+ const fromSpecHigh = loadAskQueueItemsFromSpecHigh(run_id, basePath);
40
+ if (fromSpecHigh) {
41
+ items = fromSpecHigh;
42
+ }
43
+ else {
44
+ // Fallback: run show-ask-queue command (with caching)
45
+ const { code, stdout } = await runEngineWithCache("vibecoding-helper", ["show-ask-queue", run_id], { timeoutMs: 60_000 });
46
+ if (code === 0) {
47
+ // Parse response
48
+ const parsed = safeJsonParse(stdout);
49
+ if (parsed.ok) {
50
+ const validated = VibecodingHelperShowAskQueueOutputSchema.safeParse(parsed.value);
51
+ if (validated.success) {
52
+ items = validated.data.items ?? validated.data.ask_queue ?? [];
53
+ }
54
+ else {
55
+ items = [];
56
+ }
57
+ }
58
+ else {
59
+ // Try to parse as plain text format
60
+ items = parseTextAskQueue(stdout);
61
+ }
62
+ }
63
+ }
64
+ // Apply max_items limit
65
+ const maxItems = input.max_items ?? 2;
66
+ const limitedItems = items.slice(0, maxItems);
67
+ // Local Memory reference injection can be expensive and depends on installed engines.
68
+ // Only run it in the "real" MCP runtime path (default basePath = process.cwd()).
69
+ const shouldInjectLocalMemory = path.resolve(basePath) === path.resolve(process.cwd());
70
+ // Transform to PM language
71
+ const decisionRequests = await Promise.all(limitedItems.map(async (item, index) => {
72
+ const base = transformToDecisionRequest(item, index + 1, promptDensityMode);
73
+ if (!shouldInjectLocalMemory || promptDensityMode === "mode_2")
74
+ return base;
75
+ try {
76
+ const query = `${base.title}\n${base.context}`.trim();
77
+ const refs = await maybeGetLocalMemoryContextBlock({ query, maxItems: 3 });
78
+ if (refs) {
79
+ const sanitized = transformAskQueueText(refs);
80
+ const clipped = sanitized.length > 1200 ? `${sanitized.slice(0, 1200).trimEnd()}…` : sanitized;
81
+ return { ...base, context: `${base.context}\n\n[참고 문헌]\n${clipped}` };
82
+ }
83
+ }
84
+ catch {
85
+ // ignore
86
+ }
87
+ return base;
88
+ }));
89
+ // Determine next action
90
+ const hasDecisions = decisionRequests.length > 0;
91
+ return {
92
+ project_id,
93
+ decision_requests: decisionRequests,
94
+ next_action: hasDecisions
95
+ ? {
96
+ tool: "vibe_pm.submit_decision",
97
+ reason: `${decisionRequests.length}건의 결재가 필요합니다`
98
+ }
99
+ : null
100
+ };
101
+ }
102
+ function loadAskQueueItemsFromSpecHigh(runId, basePath) {
103
+ const resolved = resolveSpecHighRunDir(runId, basePath);
104
+ if (!resolved)
105
+ return null;
106
+ const filePath = path.join(resolved.run_dir, "ask_queue_items.json");
107
+ try {
108
+ if (!fs.existsSync(filePath))
109
+ return null;
110
+ const raw = fs.readFileSync(filePath, "utf-8");
111
+ const parsed = JSON.parse(raw);
112
+ const validated = SpecHighAskQueueItemsFileSchema.safeParse(parsed);
113
+ if (!validated.success)
114
+ return null;
115
+ const rawItems = validated.data.items ?? [];
116
+ if (rawItems.length === 0)
117
+ return [];
118
+ const out = [];
119
+ for (const it of rawItems) {
120
+ if (it.kind && it.kind !== "decision_ui")
121
+ continue;
122
+ const cardId = it.internal?.card_id?.trim();
123
+ const decisionId = (cardId && cardId.length > 0 ? cardId : it.id) ?? "";
124
+ const question = it.ui?.question ?? "결정이 필요합니다";
125
+ // Prefer Korean summary bullets if present; otherwise use why_this_question.
126
+ const bullets = it.ui?.summary_bullets?.filter(Boolean) ?? [];
127
+ const desc = bullets.length > 0
128
+ ? bullets[0]
129
+ : it.ui?.why_this_question ?? "";
130
+ const options = (it.ui?.options ?? []).map((o) => ({
131
+ key: o.key,
132
+ label: o.label,
133
+ description: o.next_action_hint,
134
+ }));
135
+ out.push({
136
+ id: decisionId,
137
+ question,
138
+ description: desc,
139
+ options,
140
+ });
141
+ }
142
+ return out;
143
+ }
144
+ catch {
145
+ return null;
146
+ }
147
+ }
148
+ /**
149
+ * Transform internal ask_queue item to user-facing DecisionRequest
150
+ */
151
+ function transformToDecisionRequest(item, index, mode) {
152
+ const decisionId = item.id ?? item.card_id ?? `D-${String(index).padStart(3, "0")}`;
153
+ // Get title - transform technical terms
154
+ const rawTitle = item.title ?? item.question ?? "결정이 필요합니다";
155
+ const title = transformAskQueueText(rawTitle);
156
+ // Get context - transform technical terms
157
+ const rawContext = item.context ?? item.description ?? "";
158
+ // Transform choices
159
+ const rawOptions = item.options ?? item.choices ?? [];
160
+ const choices = transformChoices(rawOptions);
161
+ // Ensure there's always an "Unknown" option
162
+ if (!choices.some((c) => c.key === "U")) {
163
+ choices.push({
164
+ key: "U",
165
+ label: "잘 모르겠어요",
166
+ description: "더 자세한 설명이 필요합니다"
167
+ });
168
+ }
169
+ const context = shapeDecisionContext({
170
+ mode,
171
+ rawContext: transformAskQueueText(rawContext),
172
+ recommendedKey: pickRecommendedKey(choices),
173
+ });
174
+ return {
175
+ decision_id: decisionId,
176
+ title,
177
+ context,
178
+ choices
179
+ };
180
+ }
181
+ function pickRecommendedKey(choices) {
182
+ // v1: deterministic, avoid overconfidence. Prefer A if present, else B/C.
183
+ const keys = choices.map((c) => c.key);
184
+ if (keys.includes("A"))
185
+ return "A";
186
+ if (keys.includes("B"))
187
+ return "B";
188
+ return "C";
189
+ }
190
+ function shapeDecisionContext(args) {
191
+ const baseReason = args.rawContext?.trim();
192
+ if (args.mode === "mode_2") {
193
+ return "이미 정리가 잘 되어 있습니다. 충돌 여부만 확인하겠습니다.";
194
+ }
195
+ if (args.mode === "mode_1") {
196
+ const lines = [];
197
+ lines.push(`입력하신 조건 기준으로는 ${args.recommendedKey}가 가장 안정적입니다.`);
198
+ if (baseReason)
199
+ lines.push(`이유: ${baseReason}`);
200
+ return lines.join("\n");
201
+ }
202
+ // mode_0 (Sparse): recommendation + reasons + micro SWOT + sovereignty + U help
203
+ const lines = [];
204
+ lines.push(`Vibe PM 추천: ${args.recommendedKey}`);
205
+ lines.push("이유:");
206
+ if (baseReason) {
207
+ lines.push(`- ${baseReason}`);
208
+ }
209
+ else {
210
+ lines.push("- v1에서는 속도와 사고 방지가 둘 다 필요합니다.");
211
+ lines.push("- 지금은 되돌리기 쉬운 균형이 안정적입니다.");
212
+ }
213
+ lines.push("");
214
+ lines.push("[S] 빠르게 만들고, 실패 비용이 낮습니다.");
215
+ lines.push("[W] 나중에 구조 변경이 필요할 수 있습니다.");
216
+ lines.push("[O] 지금 바로 사용자 반응을 확인할 수 있습니다.");
217
+ lines.push("[T] 핵심이 커지면 다시 설계가 필요합니다.");
218
+ lines.push("");
219
+ lines.push("이 추천은 참고용입니다. 선택은 언제든 바꿀 수 있고, 바꾸려면 다시 물어봅니다.");
220
+ lines.push("아직 확신이 없다면 ‘모르겠다’를 선택해도 됩니다. 질문을 더 쉽게 바꿔서 다시 묻습니다.");
221
+ return lines.join("\n");
222
+ }
223
+ /**
224
+ * Transform raw options to user-facing choices
225
+ */
226
+ function transformChoices(rawOptions) {
227
+ const validKeys = ["A", "B", "C", "U"];
228
+ return rawOptions.slice(0, 4).map((opt, index) => {
229
+ const key = validKeys[index] ?? "U";
230
+ const label = opt.label ? transformAskQueueText(opt.label) : `선택지 ${key}`;
231
+ const description = opt.description ? transformAskQueueText(opt.description) : undefined;
232
+ return {
233
+ key,
234
+ label,
235
+ description
236
+ };
237
+ });
238
+ }
239
+ /**
240
+ * Parse plain text ask_queue output (fallback)
241
+ */
242
+ function parseTextAskQueue(text) {
243
+ const items = [];
244
+ // Simple pattern matching for text-based ask queue
245
+ // Format: "Q1: question text\n A) option A\n B) option B"
246
+ const questionPattern = /Q(\d+):\s*(.+?)(?=Q\d+:|$)/gs;
247
+ let match;
248
+ while ((match = questionPattern.exec(text)) !== null) {
249
+ const questionNum = match[1];
250
+ const questionBlock = match[2].trim();
251
+ const lines = questionBlock.split("\n");
252
+ const questionText = lines[0].trim();
253
+ const options = [];
254
+ for (let i = 1; i < lines.length; i++) {
255
+ const optMatch = lines[i].match(/^\s*([A-D])\)\s*(.+)/);
256
+ if (optMatch) {
257
+ options.push({
258
+ key: optMatch[1],
259
+ label: optMatch[2].trim()
260
+ });
261
+ }
262
+ }
263
+ items.push({
264
+ id: `D-${String(questionNum).padStart(3, "0")}`,
265
+ question: questionText,
266
+ options
267
+ });
268
+ }
269
+ // If no structured format, create single item from whole text
270
+ if (items.length === 0 && text.trim()) {
271
+ items.push({
272
+ id: "D-001",
273
+ question: text.trim().split("\n")[0],
274
+ options: [
275
+ { key: "A", label: "예" },
276
+ { key: "B", label: "아니오" }
277
+ ]
278
+ });
279
+ }
280
+ return items;
281
+ }