@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.
- package/LICENSE +21 -0
- package/README.md +269 -0
- package/build/auth/gate.js +225 -0
- package/build/auth/index.js +55 -0
- package/build/auth/public_key.js +27 -0
- package/build/auth/token_cache.js +122 -0
- package/build/auth/token_verifier.js +103 -0
- package/build/bootstrap/doctor.js +115 -0
- package/build/bootstrap/installer.js +673 -0
- package/build/bootstrap/lock.js +37 -0
- package/build/bootstrap/platform.js +26 -0
- package/build/bootstrap/registry.js +37 -0
- package/build/cache/index.js +147 -0
- package/build/cli.js +101 -0
- package/build/contracts.js +22 -0
- package/build/control_plane/gate.js +161 -0
- package/build/control_plane/index.js +6 -0
- package/build/dx/activity.js +139 -0
- package/build/engine.js +106 -0
- package/build/errors.js +171 -0
- package/build/generated/activate_input.js +2 -0
- package/build/generated/activate_output.js +57 -0
- package/build/generated/advisory_review_input.js +2 -0
- package/build/generated/advisory_review_output.js +35 -0
- package/build/generated/auth_token_file.js +2 -0
- package/build/generated/briefing_input.js +2 -0
- package/build/generated/briefing_output.js +2 -0
- package/build/generated/clinic_bridge_file.js +13 -0
- package/build/generated/contracts_bundle_info.js +5 -0
- package/build/generated/create_work_order_input.js +2 -0
- package/build/generated/create_work_order_output.js +2 -0
- package/build/generated/current_work_order_file.js +2 -0
- package/build/generated/doctor_input.js +2 -0
- package/build/generated/doctor_output.js +24 -0
- package/build/generated/execution_result.js +2 -0
- package/build/generated/execution_task.js +2 -0
- package/build/generated/export_output_input.js +2 -0
- package/build/generated/export_output_output.js +2 -0
- package/build/generated/finalize_work_input.js +2 -0
- package/build/generated/finalize_work_output.js +2 -0
- package/build/generated/gate_input.js +2 -0
- package/build/generated/gate_output.js +2 -0
- package/build/generated/gate_result_v1.js +2 -0
- package/build/generated/get_decision_input.js +2 -0
- package/build/generated/get_decision_output.js +13 -0
- package/build/generated/handoff_to_clinic.js +2 -0
- package/build/generated/index.js +75 -0
- package/build/generated/inspect_code_input.js +2 -0
- package/build/generated/inspect_code_output.js +13 -0
- package/build/generated/memory_retrieve_output.js +2 -0
- package/build/generated/memory_state_file.js +2 -0
- package/build/generated/memory_status_input.js +2 -0
- package/build/generated/memory_status_output.js +13 -0
- package/build/generated/memory_sync_input.js +2 -0
- package/build/generated/memory_sync_output.js +13 -0
- package/build/generated/plugin_result.js +2 -0
- package/build/generated/react_perf_check_patterns_input.js +2 -0
- package/build/generated/react_perf_check_patterns_output.js +2 -0
- package/build/generated/react_perf_generate_report_input.js +2 -0
- package/build/generated/react_perf_generate_report_output.js +2 -0
- package/build/generated/repair_plan_input.js +2 -0
- package/build/generated/repair_plan_output.js +2 -0
- package/build/generated/run_app_input.js +2 -0
- package/build/generated/run_app_output.js +2 -0
- package/build/generated/run_state_file.js +13 -0
- package/build/generated/scaffold_input.js +2 -0
- package/build/generated/scaffold_output.js +2 -0
- package/build/generated/search_oss_input.js +2 -0
- package/build/generated/search_oss_output.js +2 -0
- package/build/generated/selection_validation_result.js +2 -0
- package/build/generated/signal_agent_input.js +2 -0
- package/build/generated/spec_high_ask_queue_items_file.js +2 -0
- package/build/generated/spec_high_clinic_bridge_output.js +2 -0
- package/build/generated/spec_high_decision_draft_output.js +2 -0
- package/build/generated/spec_high_validate_output.js +2 -0
- package/build/generated/status_input.js +2 -0
- package/build/generated/status_output.js +2 -0
- package/build/generated/submit_decision_input.js +2 -0
- package/build/generated/submit_decision_output.js +2 -0
- package/build/generated/tool_error_output.js +2 -0
- package/build/generated/undo_last_task_input.js +2 -0
- package/build/generated/undo_last_task_output.js +2 -0
- package/build/generated/update_input.js +2 -0
- package/build/generated/update_output.js +2 -0
- package/build/generated/vibe_pm_inspection_result.js +2 -0
- package/build/generated/vibe_pm_report_markdown.js +2 -0
- package/build/generated/vibe_pm_verdict.js +2 -0
- package/build/generated/vibe_repo_config.js +2 -0
- package/build/generated/vibecoding_helper_answer_output.js +2 -0
- package/build/generated/vibecoding_helper_one_loop_selection_output.js +2 -0
- package/build/generated/vibecoding_helper_show_ask_queue_output.js +2 -0
- package/build/generated/work_order_v1.js +2 -0
- package/build/generated/zoekt_evidence_input.js +2 -0
- package/build/generated/zoekt_evidence_output.js +2 -0
- package/build/index.js +111 -0
- package/build/legacy_alias.js +65 -0
- package/build/local-mode/bash.js +61 -0
- package/build/local-mode/config.js +171 -0
- package/build/local-mode/git.js +33 -0
- package/build/local-mode/init.js +110 -0
- package/build/local-mode/paths.js +24 -0
- package/build/local-mode/templates.js +856 -0
- package/build/local-mode/work-order.js +41 -0
- package/build/resources/index.js +246 -0
- package/build/security/input-validator.js +119 -0
- package/build/security/path-policy.js +289 -0
- package/build/security/sandbox.js +228 -0
- package/build/tools/react_perf/check_patterns.js +172 -0
- package/build/tools/react_perf/generate_report.js +337 -0
- package/build/tools/react_perf/index.js +119 -0
- package/build/tools/react_perf/rules/advanced.js +325 -0
- package/build/tools/react_perf/rules/async.js +104 -0
- package/build/tools/react_perf/rules/bundle.js +101 -0
- package/build/tools/react_perf/rules/client.js +186 -0
- package/build/tools/react_perf/rules/index.js +74 -0
- package/build/tools/react_perf/rules/js.js +148 -0
- package/build/tools/react_perf/rules/rendering.js +166 -0
- package/build/tools/react_perf/rules/rerender.js +161 -0
- package/build/tools/react_perf/rules/server.js +141 -0
- package/build/tools/react_perf/types.js +127 -0
- package/build/tools/vibe_pm/activate.js +102 -0
- package/build/tools/vibe_pm/advisory_review.js +77 -0
- package/build/tools/vibe_pm/briefing.js +178 -0
- package/build/tools/vibe_pm/context.js +439 -0
- package/build/tools/vibe_pm/create_work_order.js +271 -0
- package/build/tools/vibe_pm/doc_status_gate.js +370 -0
- package/build/tools/vibe_pm/doctor.js +262 -0
- package/build/tools/vibe_pm/entity_gate/preflight.js +78 -0
- package/build/tools/vibe_pm/export_output.js +135 -0
- package/build/tools/vibe_pm/finalize_work.js +393 -0
- package/build/tools/vibe_pm/gate.js +33 -0
- package/build/tools/vibe_pm/get_decision.js +281 -0
- package/build/tools/vibe_pm/index.js +593 -0
- package/build/tools/vibe_pm/inspect_code.js +828 -0
- package/build/tools/vibe_pm/intent/generator.js +294 -0
- package/build/tools/vibe_pm/intent/index.js +5 -0
- package/build/tools/vibe_pm/intent/prompt_density.js +227 -0
- package/build/tools/vibe_pm/intent/types.js +70 -0
- package/build/tools/vibe_pm/intent/verifier.js +237 -0
- package/build/tools/vibe_pm/kce/doc_usage.js +51 -0
- package/build/tools/vibe_pm/kce/on_finalize.js +11 -0
- package/build/tools/vibe_pm/kce/preflight.js +232 -0
- package/build/tools/vibe_pm/local_memory.js +26 -0
- package/build/tools/vibe_pm/memory_status.js +82 -0
- package/build/tools/vibe_pm/memory_sync.js +134 -0
- package/build/tools/vibe_pm/modules/decision_snapshot.js +29 -0
- package/build/tools/vibe_pm/modules/ensure.js +100 -0
- package/build/tools/vibe_pm/modules/fingerprint.js +30 -0
- package/build/tools/vibe_pm/modules/fix_dependencies.js +394 -0
- package/build/tools/vibe_pm/modules/planning_v1.js +110 -0
- package/build/tools/vibe_pm/modules/repo_context.js +56 -0
- package/build/tools/vibe_pm/modules/research_v1.js +114 -0
- package/build/tools/vibe_pm/modules/skills_v1.js +100 -0
- package/build/tools/vibe_pm/pm_language.js +222 -0
- package/build/tools/vibe_pm/repair_plan.js +199 -0
- package/build/tools/vibe_pm/run_app.js +597 -0
- package/build/tools/vibe_pm/run_app_podman.js +64 -0
- package/build/tools/vibe_pm/scaffold.js +550 -0
- package/build/tools/vibe_pm/search_oss.js +124 -0
- package/build/tools/vibe_pm/status.js +153 -0
- package/build/tools/vibe_pm/submit_decision.js +87 -0
- package/build/tools/vibe_pm/system_design/issue_mapping.js +47 -0
- package/build/tools/vibe_pm/system_design/rulebook.js +112 -0
- package/build/tools/vibe_pm/system_design/semgrep.js +132 -0
- package/build/tools/vibe_pm/types.js +229 -0
- package/build/tools/vibe_pm/undo_last_task.js +163 -0
- package/build/tools/vibe_pm/update.js +146 -0
- package/build/tools/vibe_pm/zoekt_evidence.js +96 -0
- package/build/tools.js +269 -0
- package/build/version-check.js +239 -0
- package/build/vibe-cli.js +631 -0
- package/package.json +76 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
// adapters/mcp-ts/src/tools/vibe_pm/types.ts
|
|
2
|
+
// Type definitions for vibe_pm.* MCP tools
|
|
3
|
+
// Reference: docs/DEV_SPEC/MCP_TOOL_SCHEMA_SPEC.md
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
// ============================================================
|
|
6
|
+
// vibe_pm.briefing
|
|
7
|
+
// ============================================================
|
|
8
|
+
// Input schema is generated from JSON Schema SSOT.
|
|
9
|
+
export const briefingInputSchema = BriefingInputSchema;
|
|
10
|
+
// Output schema is generated from JSON Schema SSOT.
|
|
11
|
+
export const briefingOutputSchema = BriefingOutputSchema;
|
|
12
|
+
// ============================================================
|
|
13
|
+
// vibe_pm.get_decision
|
|
14
|
+
// ============================================================
|
|
15
|
+
// Input schema is generated from JSON Schema SSOT.
|
|
16
|
+
export const getDecisionInputSchema = GetDecisionInputSchema;
|
|
17
|
+
const choiceSchema = z.object({
|
|
18
|
+
key: z.enum(["A", "B", "C", "U"]).describe("선택 키"),
|
|
19
|
+
label: z.string().describe("선택지 레이블"),
|
|
20
|
+
description: z.string().optional().describe("선택지 설명")
|
|
21
|
+
});
|
|
22
|
+
const decisionRequestSchema = z.object({
|
|
23
|
+
decision_id: z.string().describe("결재 ID (내부용)"),
|
|
24
|
+
title: z.string().describe("비즈니스 언어 제목"),
|
|
25
|
+
context: z.string().describe("컨텍스트 설명 (기술 용어 없음)"),
|
|
26
|
+
choices: z.array(choiceSchema).describe("선택 가능한 옵션들")
|
|
27
|
+
});
|
|
28
|
+
// Output schema is generated from JSON Schema SSOT.
|
|
29
|
+
export const getDecisionOutputSchema = GetDecisionOutputSchema;
|
|
30
|
+
// ============================================================
|
|
31
|
+
// vibe_pm.memory_status
|
|
32
|
+
// ============================================================
|
|
33
|
+
// Input schema is generated from JSON Schema SSOT.
|
|
34
|
+
export const memoryStatusInputSchema = MemoryStatusInputSchema;
|
|
35
|
+
// Output schema is generated from JSON Schema SSOT.
|
|
36
|
+
export const memoryStatusOutputSchema = MemoryStatusOutputSchema;
|
|
37
|
+
// ============================================================
|
|
38
|
+
// vibe_pm.memory_sync
|
|
39
|
+
// ============================================================
|
|
40
|
+
// Input schema is generated from JSON Schema SSOT.
|
|
41
|
+
export const memorySyncInputSchema = MemorySyncInputSchema;
|
|
42
|
+
// Output schema is generated from JSON Schema SSOT.
|
|
43
|
+
export const memorySyncOutputSchema = MemorySyncOutputSchema;
|
|
44
|
+
// ============================================================
|
|
45
|
+
// vibe_pm.advisory_review
|
|
46
|
+
// ============================================================
|
|
47
|
+
// Input schema is generated from JSON Schema SSOT.
|
|
48
|
+
export const advisoryReviewInputSchema = AdvisoryReviewInputSchema;
|
|
49
|
+
// Output schema is generated from JSON Schema SSOT.
|
|
50
|
+
export const advisoryReviewOutputSchema = AdvisoryReviewOutputSchema;
|
|
51
|
+
// ============================================================
|
|
52
|
+
// vibe_pm.activate
|
|
53
|
+
// ============================================================
|
|
54
|
+
// Input schema is generated from JSON Schema SSOT.
|
|
55
|
+
export const activateInputSchema = ActivateInputSchema;
|
|
56
|
+
// Output schema is generated from JSON Schema SSOT.
|
|
57
|
+
export const activateOutputSchema = ActivateOutputSchema;
|
|
58
|
+
// ============================================================
|
|
59
|
+
// vibe_pm.submit_decision
|
|
60
|
+
// ============================================================
|
|
61
|
+
// Input schema is generated from JSON Schema SSOT.
|
|
62
|
+
export const submitDecisionInputSchema = SubmitDecisionInputSchema;
|
|
63
|
+
// Output schema is generated from JSON Schema SSOT.
|
|
64
|
+
export const submitDecisionOutputSchema = SubmitDecisionOutputSchema;
|
|
65
|
+
// ============================================================
|
|
66
|
+
// vibe_pm.create_work_order
|
|
67
|
+
// ============================================================
|
|
68
|
+
// Input schema is generated from JSON Schema SSOT.
|
|
69
|
+
export const createWorkOrderInputSchema = CreateWorkOrderInputSchema;
|
|
70
|
+
const workOrderSchema = z.object({
|
|
71
|
+
headline: z.string().describe("현재 작업 목표 (단일 항목)"),
|
|
72
|
+
scope: z.object({
|
|
73
|
+
include: z.array(z.string()).describe("포함 범위"),
|
|
74
|
+
exclude: z.array(z.string()).describe("제외 범위")
|
|
75
|
+
}).describe("작업 범위 정의"),
|
|
76
|
+
do_not_touch: z.array(z.string()).describe("건드리지 말아야 할 항목"),
|
|
77
|
+
verify_criteria: z.array(z.string()).describe("검증 기준"),
|
|
78
|
+
paste_to_agent: z.string().describe("AI 에이전트에 붙여넣을 텍스트")
|
|
79
|
+
});
|
|
80
|
+
// Output schema is generated from JSON Schema SSOT.
|
|
81
|
+
export const createWorkOrderOutputSchema = CreateWorkOrderOutputSchema;
|
|
82
|
+
// ============================================================
|
|
83
|
+
// vibe_pm.inspect_code
|
|
84
|
+
// ============================================================
|
|
85
|
+
// Input schema is generated from JSON Schema SSOT.
|
|
86
|
+
export const inspectCodeInputSchema = InspectCodeInputSchema;
|
|
87
|
+
// Output schema is generated from JSON Schema SSOT.
|
|
88
|
+
export const inspectCodeOutputSchema = InspectCodeOutputSchema;
|
|
89
|
+
/**
|
|
90
|
+
* P11: Validate inspect_code output against schema contract
|
|
91
|
+
* @throws ZodError if validation fails
|
|
92
|
+
*/
|
|
93
|
+
export function validateInspectCodeOutput(output) {
|
|
94
|
+
return inspectCodeOutputSchema.parse(output);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* P14: Select message template ID based on review result and issues
|
|
98
|
+
* Reference: docs/specs/PM_USER_MESSAGES_SSOT_v1.0.md
|
|
99
|
+
*
|
|
100
|
+
* Selection rules:
|
|
101
|
+
* - GO → GO-01 (기본) or GO-02 (다음 작업 연결 시)
|
|
102
|
+
* - FIX + VERIFY_FAIL → FIX-02
|
|
103
|
+
* - FIX (other) → FIX-01
|
|
104
|
+
* - BLOCK + RULE_VIOLATION|RISK_SPIKE → BLOCK-01
|
|
105
|
+
* - BLOCK + SCOPE_MISMATCH → BLOCK-02
|
|
106
|
+
*/
|
|
107
|
+
export function selectMessageTemplate(reviewResult, issues, hasNextWorkOrder = false) {
|
|
108
|
+
const issueTypes = new Set(issues.map(i => i.type));
|
|
109
|
+
switch (reviewResult) {
|
|
110
|
+
case "GO":
|
|
111
|
+
return hasNextWorkOrder ? "GO-02" : "GO-01";
|
|
112
|
+
case "FIX":
|
|
113
|
+
return issueTypes.has("VERIFY_FAIL") ? "FIX-02" : "FIX-01";
|
|
114
|
+
case "BLOCK":
|
|
115
|
+
if (issueTypes.has("RULE_VIOLATION") || issueTypes.has("RISK_SPIKE")) {
|
|
116
|
+
return "BLOCK-01";
|
|
117
|
+
}
|
|
118
|
+
return "BLOCK-02"; // SCOPE_MISMATCH or default
|
|
119
|
+
default:
|
|
120
|
+
return "GO-01";
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// ============================================================
|
|
124
|
+
// vibe_pm.status
|
|
125
|
+
// ============================================================
|
|
126
|
+
// Input schema is generated from JSON Schema SSOT.
|
|
127
|
+
export const statusInputSchema = StatusInputSchema;
|
|
128
|
+
// Output schema is generated from JSON Schema SSOT.
|
|
129
|
+
export const statusOutputSchema = StatusOutputSchema;
|
|
130
|
+
// ============================================================
|
|
131
|
+
// vibe_pm.repair_plan
|
|
132
|
+
// ============================================================
|
|
133
|
+
// Input schema is generated from JSON Schema SSOT.
|
|
134
|
+
export const repairPlanInputSchema = RepairPlanInputSchema;
|
|
135
|
+
// Output schema is generated from JSON Schema SSOT.
|
|
136
|
+
export const repairPlanOutputSchema = RepairPlanOutputSchema;
|
|
137
|
+
// ============================================================
|
|
138
|
+
// vibe_pm.scaffold (Vibe-SDS - Standard Directory Structure)
|
|
139
|
+
// ============================================================
|
|
140
|
+
// Input schema is generated from JSON Schema SSOT.
|
|
141
|
+
export const scaffoldInputSchema = ScaffoldInputSchema;
|
|
142
|
+
// Output schema is generated from JSON Schema SSOT.
|
|
143
|
+
export const scaffoldOutputSchema = ScaffoldOutputSchema;
|
|
144
|
+
// ============================================================
|
|
145
|
+
// vibe_pm.finalize_work
|
|
146
|
+
// ============================================================
|
|
147
|
+
// Imported from generated SSOT
|
|
148
|
+
import { BriefingInputSchema } from "../../generated/briefing_input.js";
|
|
149
|
+
import { CreateWorkOrderOutputSchema } from "../../generated/create_work_order_output.js";
|
|
150
|
+
import { BriefingOutputSchema } from "../../generated/briefing_output.js";
|
|
151
|
+
import { DoctorOutputSchema } from "../../generated/doctor_output.js";
|
|
152
|
+
import { FinalizeWorkInputSchema } from "../../generated/finalize_work_input.js";
|
|
153
|
+
import { FinalizeWorkOutputSchema } from "../../generated/finalize_work_output.js";
|
|
154
|
+
import { GetDecisionInputSchema } from "../../generated/get_decision_input.js";
|
|
155
|
+
import { GetDecisionOutputSchema } from "../../generated/get_decision_output.js";
|
|
156
|
+
import { CreateWorkOrderInputSchema } from "../../generated/create_work_order_input.js";
|
|
157
|
+
import { InspectCodeInputSchema } from "../../generated/inspect_code_input.js";
|
|
158
|
+
import { InspectCodeOutputSchema } from "../../generated/inspect_code_output.js";
|
|
159
|
+
import { RepairPlanInputSchema } from "../../generated/repair_plan_input.js";
|
|
160
|
+
import { RepairPlanOutputSchema } from "../../generated/repair_plan_output.js";
|
|
161
|
+
import { RunAppInputSchema } from "../../generated/run_app_input.js";
|
|
162
|
+
import { RunAppOutputSchema } from "../../generated/run_app_output.js";
|
|
163
|
+
import { ScaffoldInputSchema } from "../../generated/scaffold_input.js";
|
|
164
|
+
import { ScaffoldOutputSchema } from "../../generated/scaffold_output.js";
|
|
165
|
+
import { StatusInputSchema } from "../../generated/status_input.js";
|
|
166
|
+
import { StatusOutputSchema } from "../../generated/status_output.js";
|
|
167
|
+
import { SubmitDecisionInputSchema } from "../../generated/submit_decision_input.js";
|
|
168
|
+
import { SubmitDecisionOutputSchema } from "../../generated/submit_decision_output.js";
|
|
169
|
+
import { UndoLastTaskInputSchema } from "../../generated/undo_last_task_input.js";
|
|
170
|
+
import { UndoLastTaskOutputSchema } from "../../generated/undo_last_task_output.js";
|
|
171
|
+
import { UpdateOutputSchema } from "../../generated/update_output.js";
|
|
172
|
+
import { MemoryStatusInputSchema } from "../../generated/memory_status_input.js";
|
|
173
|
+
import { MemoryStatusOutputSchema } from "../../generated/memory_status_output.js";
|
|
174
|
+
import { MemorySyncInputSchema } from "../../generated/memory_sync_input.js";
|
|
175
|
+
import { MemorySyncOutputSchema } from "../../generated/memory_sync_output.js";
|
|
176
|
+
import { AdvisoryReviewInputSchema } from "../../generated/advisory_review_input.js";
|
|
177
|
+
import { AdvisoryReviewOutputSchema } from "../../generated/advisory_review_output.js";
|
|
178
|
+
import { ActivateInputSchema } from "../../generated/activate_input.js";
|
|
179
|
+
import { ActivateOutputSchema } from "../../generated/activate_output.js";
|
|
180
|
+
import { ExportOutputInputSchema } from "../../generated/export_output_input.js";
|
|
181
|
+
import { ExportOutputOutputSchema } from "../../generated/export_output_output.js";
|
|
182
|
+
import { SearchOssInputSchema } from "../../generated/search_oss_input.js";
|
|
183
|
+
import { SearchOssOutputSchema } from "../../generated/search_oss_output.js";
|
|
184
|
+
import { ZoektEvidenceInputSchema } from "../../generated/zoekt_evidence_input.js";
|
|
185
|
+
import { ZoektEvidenceOutputSchema } from "../../generated/zoekt_evidence_output.js";
|
|
186
|
+
export const finalizeWorkInputSchema = FinalizeWorkInputSchema;
|
|
187
|
+
// Output schema is generated from JSON Schema SSOT.
|
|
188
|
+
export const finalizeWorkOutputSchema = FinalizeWorkOutputSchema;
|
|
189
|
+
// ============================================================
|
|
190
|
+
// vibe_pm.undo_last_task
|
|
191
|
+
// ============================================================
|
|
192
|
+
// Input schema is generated from JSON Schema SSOT.
|
|
193
|
+
export const undoLastTaskInputSchema = UndoLastTaskInputSchema;
|
|
194
|
+
// Output schema is generated from JSON Schema SSOT.
|
|
195
|
+
export const undoLastTaskOutputSchema = UndoLastTaskOutputSchema;
|
|
196
|
+
// ============================================================
|
|
197
|
+
// vibe_pm.run_app
|
|
198
|
+
// ============================================================
|
|
199
|
+
// Input schema is generated from JSON Schema SSOT.
|
|
200
|
+
export const runAppInputSchema = RunAppInputSchema;
|
|
201
|
+
// Output schema is generated from JSON Schema SSOT.
|
|
202
|
+
export const runAppOutputSchema = RunAppOutputSchema;
|
|
203
|
+
// ============================================================
|
|
204
|
+
// vibe_pm.export_output
|
|
205
|
+
// ============================================================
|
|
206
|
+
// Input schema is generated from JSON Schema SSOT.
|
|
207
|
+
export const exportOutputInputSchema = ExportOutputInputSchema;
|
|
208
|
+
// Output schema is generated from JSON Schema SSOT.
|
|
209
|
+
export const exportOutputOutputSchema = ExportOutputOutputSchema;
|
|
210
|
+
// ============================================================
|
|
211
|
+
// vibe_pm.search_oss
|
|
212
|
+
// ============================================================
|
|
213
|
+
// Input schema is generated from JSON Schema SSOT.
|
|
214
|
+
export const searchOssInputSchema = SearchOssInputSchema;
|
|
215
|
+
// Output schema is generated from JSON Schema SSOT.
|
|
216
|
+
export const searchOssOutputSchema = SearchOssOutputSchema;
|
|
217
|
+
// ============================================================
|
|
218
|
+
// vibe_pm.zoekt_evidence
|
|
219
|
+
// ============================================================
|
|
220
|
+
// Input schema is generated from JSON Schema SSOT.
|
|
221
|
+
export const zoektEvidenceInputSchema = ZoektEvidenceInputSchema;
|
|
222
|
+
// Output schema is generated from JSON Schema SSOT.
|
|
223
|
+
export const zoektEvidenceOutputSchema = ZoektEvidenceOutputSchema;
|
|
224
|
+
// ============================================================
|
|
225
|
+
// vibe_pm.doctor / vibe_pm.update (Output SSOT only)
|
|
226
|
+
// ============================================================
|
|
227
|
+
export const doctorOutputSchema = DoctorOutputSchema;
|
|
228
|
+
export const updateOutputSchema = UpdateOutputSchema;
|
|
229
|
+
// All output schemas are exported in-place above
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// adapters/mcp-ts/src/tools/vibe_pm/undo_last_task.ts
|
|
2
|
+
// vibe_pm.undo_last_task - Time machine rollback via git revert
|
|
3
|
+
import * as fs from "node:fs";
|
|
4
|
+
import * as path from "node:path";
|
|
5
|
+
import { exec } from "node:child_process";
|
|
6
|
+
import { promisify } from "node:util";
|
|
7
|
+
const execAsync = promisify(exec);
|
|
8
|
+
/**
|
|
9
|
+
* vibe_pm.undo_last_task - Rollback recent commits via git revert
|
|
10
|
+
*
|
|
11
|
+
* Steps:
|
|
12
|
+
* 1. git log --oneline -n {steps} to get recent commits
|
|
13
|
+
* 2. For each commit, git revert --no-edit
|
|
14
|
+
* 3. Add [ROLLBACK] entry to DEV_LOG
|
|
15
|
+
* 4. Return result
|
|
16
|
+
*/
|
|
17
|
+
export async function undoLastTask(input) {
|
|
18
|
+
const basePath = process.cwd();
|
|
19
|
+
const steps = input.steps ?? 1;
|
|
20
|
+
const reason = input.reason ?? "사용자 요청으로 롤백";
|
|
21
|
+
// Step 1: Get recent commits
|
|
22
|
+
let commits;
|
|
23
|
+
try {
|
|
24
|
+
commits = await getRecentCommits(basePath, steps);
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
return {
|
|
28
|
+
success: false,
|
|
29
|
+
reverted_tasks: [],
|
|
30
|
+
current_commit: "unknown",
|
|
31
|
+
message: `Git 로그를 가져올 수 없습니다: ${err instanceof Error ? err.message : String(err)}`
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
if (commits.length === 0) {
|
|
35
|
+
return {
|
|
36
|
+
success: false,
|
|
37
|
+
reverted_tasks: [],
|
|
38
|
+
current_commit: await getCurrentCommit(basePath),
|
|
39
|
+
message: "되돌릴 커밋이 없습니다"
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
// Step 2: Revert each commit
|
|
43
|
+
const revertedTasks = [];
|
|
44
|
+
const revertErrors = [];
|
|
45
|
+
for (const commit of commits) {
|
|
46
|
+
try {
|
|
47
|
+
await execAsync(`git revert --no-edit ${commit.hash}`, { cwd: basePath });
|
|
48
|
+
revertedTasks.push({
|
|
49
|
+
commit_hash: commit.shortHash,
|
|
50
|
+
task_summary: commit.subject,
|
|
51
|
+
timestamp: commit.timestamp
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
56
|
+
revertErrors.push(`${commit.shortHash}: ${errMsg}`);
|
|
57
|
+
// If revert fails due to conflicts, abort and stop
|
|
58
|
+
if (errMsg.includes("conflict") || errMsg.includes("CONFLICT")) {
|
|
59
|
+
try {
|
|
60
|
+
await execAsync("git revert --abort", { cwd: basePath });
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Ignore abort errors
|
|
64
|
+
}
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Step 3: Add DEV_LOG entry
|
|
70
|
+
if (revertedTasks.length > 0) {
|
|
71
|
+
try {
|
|
72
|
+
await addRollbackLog(basePath, revertedTasks, reason);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// Logging is optional
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Step 4: Get current commit
|
|
79
|
+
const currentCommit = await getCurrentCommit(basePath);
|
|
80
|
+
// Determine result message
|
|
81
|
+
let message;
|
|
82
|
+
if (revertedTasks.length === steps) {
|
|
83
|
+
message = `${revertedTasks.length}개 작업을 성공적으로 롤백했습니다`;
|
|
84
|
+
}
|
|
85
|
+
else if (revertedTasks.length > 0) {
|
|
86
|
+
message = `${revertedTasks.length}/${steps}개 작업을 롤백했습니다. 일부 실패: ${revertErrors.join("; ")}`;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
message = `롤백 실패: ${revertErrors.join("; ")}`;
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
success: revertedTasks.length > 0,
|
|
93
|
+
reverted_tasks: revertedTasks,
|
|
94
|
+
current_commit: currentCommit,
|
|
95
|
+
message
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Get recent commits from git log
|
|
100
|
+
*/
|
|
101
|
+
async function getRecentCommits(basePath, count) {
|
|
102
|
+
const { stdout } = await execAsync(`git log --oneline -n ${count} --format="%H|%h|%s|%ci"`, { cwd: basePath });
|
|
103
|
+
const commits = [];
|
|
104
|
+
const lines = stdout.trim().split("\n").filter(Boolean);
|
|
105
|
+
for (const line of lines) {
|
|
106
|
+
const [hash, shortHash, subject, timestamp] = line.split("|");
|
|
107
|
+
if (hash && shortHash && subject) {
|
|
108
|
+
commits.push({
|
|
109
|
+
hash,
|
|
110
|
+
shortHash,
|
|
111
|
+
subject,
|
|
112
|
+
timestamp: timestamp ?? new Date().toISOString()
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return commits;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Get current HEAD commit hash
|
|
120
|
+
*/
|
|
121
|
+
async function getCurrentCommit(basePath) {
|
|
122
|
+
try {
|
|
123
|
+
const { stdout } = await execAsync("git rev-parse --short HEAD", { cwd: basePath });
|
|
124
|
+
return stdout.trim();
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return "unknown";
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Add rollback entry to DEV_LOG
|
|
132
|
+
*/
|
|
133
|
+
async function addRollbackLog(basePath, revertedTasks, reason) {
|
|
134
|
+
const today = new Date();
|
|
135
|
+
const dateStr = today.toISOString().split("T")[0];
|
|
136
|
+
const time = today.toISOString().split("T")[1]?.slice(0, 5) ?? "";
|
|
137
|
+
const devLogDir = path.join(basePath, "docs", "dev_logs");
|
|
138
|
+
const devLogPath = path.join(devLogDir, `${dateStr}.md`);
|
|
139
|
+
// Ensure directory exists
|
|
140
|
+
if (!fs.existsSync(devLogDir)) {
|
|
141
|
+
fs.mkdirSync(devLogDir, { recursive: true });
|
|
142
|
+
}
|
|
143
|
+
// Create rollback entry
|
|
144
|
+
const taskList = revertedTasks
|
|
145
|
+
.map((t) => `- \`${t.commit_hash}\`: ${t.task_summary}`)
|
|
146
|
+
.join("\n");
|
|
147
|
+
const entry = `## ${time} - [ROLLBACK] 작업 취소
|
|
148
|
+
|
|
149
|
+
**이유:** ${reason}
|
|
150
|
+
|
|
151
|
+
**취소된 작업:**
|
|
152
|
+
${taskList}
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
`;
|
|
156
|
+
if (fs.existsSync(devLogPath)) {
|
|
157
|
+
fs.appendFileSync(devLogPath, `\n${entry}`);
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
const header = `# DEV LOG - ${dateStr}\n\n`;
|
|
161
|
+
fs.writeFileSync(devLogPath, header + entry);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// adapters/mcp-ts/src/tools/vibe_pm/update.ts
|
|
2
|
+
// vibe_pm.update - Manual engine update
|
|
3
|
+
import { UpdateInputSchema } from "../../generated/update_input.js";
|
|
4
|
+
import { ensureEngines, checkUpdates, clearCache, getEngineHealth } from "../../bootstrap/installer.js";
|
|
5
|
+
import { ENGINE_SPECS } from "../../bootstrap/registry.js";
|
|
6
|
+
// ============================================================
|
|
7
|
+
// Input/Output Types
|
|
8
|
+
// ============================================================
|
|
9
|
+
export { UpdateInputSchema };
|
|
10
|
+
// ============================================================
|
|
11
|
+
// Update Implementation
|
|
12
|
+
// ============================================================
|
|
13
|
+
/**
|
|
14
|
+
* vibe_pm.update - Manual engine update
|
|
15
|
+
*
|
|
16
|
+
* PM-friendly description:
|
|
17
|
+
* 엔진 바이너리를 최신 버전으로 업데이트합니다.
|
|
18
|
+
*/
|
|
19
|
+
export async function update(input) {
|
|
20
|
+
const force = input.force ?? false;
|
|
21
|
+
const targetEngines = input.engines ?? Object.keys(ENGINE_SPECS);
|
|
22
|
+
const results = [];
|
|
23
|
+
try {
|
|
24
|
+
// Step 1: Check what needs updating
|
|
25
|
+
const updateStatus = await checkUpdates();
|
|
26
|
+
// Step 2: Filter engines to update
|
|
27
|
+
const enginesToUpdate = [];
|
|
28
|
+
for (const name of targetEngines) {
|
|
29
|
+
if (!(name in ENGINE_SPECS)) {
|
|
30
|
+
results.push({
|
|
31
|
+
name,
|
|
32
|
+
action: "failed",
|
|
33
|
+
from_version: null,
|
|
34
|
+
to_version: "unknown",
|
|
35
|
+
message: `알 수 없는 엔진: ${name}`
|
|
36
|
+
});
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const engineName = name;
|
|
40
|
+
const status = updateStatus[engineName];
|
|
41
|
+
if (force || status.needsUpdate) {
|
|
42
|
+
enginesToUpdate.push(engineName);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
results.push({
|
|
46
|
+
name: engineName,
|
|
47
|
+
action: "skipped",
|
|
48
|
+
from_version: status.current,
|
|
49
|
+
to_version: status.required,
|
|
50
|
+
message: "이미 최신 버전입니다"
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Step 3: Clear cache if force mode
|
|
55
|
+
if (force) {
|
|
56
|
+
for (const name of enginesToUpdate) {
|
|
57
|
+
await clearCache(name);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Step 4: Update engines
|
|
61
|
+
if (enginesToUpdate.length > 0) {
|
|
62
|
+
// Run ensureEngines which will update anything that needs updating
|
|
63
|
+
await ensureEngines();
|
|
64
|
+
// Check results
|
|
65
|
+
const newHealth = await getEngineHealth();
|
|
66
|
+
for (const name of enginesToUpdate) {
|
|
67
|
+
const health = newHealth.find((h) => h.name === name);
|
|
68
|
+
const oldStatus = updateStatus[name];
|
|
69
|
+
if (health?.status === "ok") {
|
|
70
|
+
results.push({
|
|
71
|
+
name,
|
|
72
|
+
action: "updated",
|
|
73
|
+
from_version: oldStatus.current,
|
|
74
|
+
to_version: health.version,
|
|
75
|
+
message: force ? "강제 재설치 완료" : "업데이트 완료"
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
results.push({
|
|
80
|
+
name,
|
|
81
|
+
action: "failed",
|
|
82
|
+
from_version: oldStatus.current,
|
|
83
|
+
to_version: oldStatus.required,
|
|
84
|
+
message: `업데이트 실패: ${health?.status ?? "unknown"}`
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Step 5: Generate summary
|
|
90
|
+
const updated = results.filter((r) => r.action === "updated").length;
|
|
91
|
+
const skipped = results.filter((r) => r.action === "skipped").length;
|
|
92
|
+
const failed = results.filter((r) => r.action === "failed").length;
|
|
93
|
+
let status;
|
|
94
|
+
let summary;
|
|
95
|
+
let nextAction;
|
|
96
|
+
if (failed > 0 && updated === 0) {
|
|
97
|
+
status = "ERROR";
|
|
98
|
+
summary = `업데이트 실패: ${failed}개 엔진`;
|
|
99
|
+
nextAction = {
|
|
100
|
+
type: "RETRY",
|
|
101
|
+
message: "force: true 옵션으로 다시 시도하거나, 네트워크 연결을 확인하세요."
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
else if (failed > 0) {
|
|
105
|
+
status = "PARTIAL";
|
|
106
|
+
summary = `부분 성공: ${updated}개 업데이트, ${failed}개 실패`;
|
|
107
|
+
nextAction = {
|
|
108
|
+
type: "RETRY",
|
|
109
|
+
message: "실패한 엔진은 force: true 옵션으로 다시 시도하세요."
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
else if (updated > 0) {
|
|
113
|
+
status = "OK";
|
|
114
|
+
summary = `${updated}개 엔진 업데이트 완료`;
|
|
115
|
+
nextAction = {
|
|
116
|
+
type: "NONE",
|
|
117
|
+
message: "모든 엔진이 최신 버전입니다."
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
status = "OK";
|
|
122
|
+
summary = "모든 엔진이 이미 최신 버전입니다";
|
|
123
|
+
nextAction = {
|
|
124
|
+
type: "NONE",
|
|
125
|
+
message: "업데이트할 항목이 없습니다."
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
status,
|
|
130
|
+
summary,
|
|
131
|
+
results,
|
|
132
|
+
next_action: nextAction
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
catch (e) {
|
|
136
|
+
return {
|
|
137
|
+
status: "ERROR",
|
|
138
|
+
summary: e instanceof Error ? e.message : "알 수 없는 오류",
|
|
139
|
+
results,
|
|
140
|
+
next_action: {
|
|
141
|
+
type: "CONTACT_SUPPORT",
|
|
142
|
+
message: "업데이트 중 오류가 발생했습니다. 네트워크 연결을 확인하고 다시 시도하세요."
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// adapters/mcp-ts/src/tools/vibe_pm/zoekt_evidence.ts
|
|
2
|
+
// vibe_pm.zoekt_evidence - Collect pattern evidence across local roots (zoekt/rg/python_scan)
|
|
3
|
+
import { McpError, ErrorCode } from "@modelcontextprotocol/sdk/types.js";
|
|
4
|
+
import { runEngine } from "../../engine.js";
|
|
5
|
+
import { safeJsonParse } from "../../cli.js";
|
|
6
|
+
import { validateToolInput } from "../../security/input-validator.js";
|
|
7
|
+
import { resolveProjectId, resolveRunId } from "./context.js";
|
|
8
|
+
function toCsv(values) {
|
|
9
|
+
return values
|
|
10
|
+
.map((v) => (typeof v === "string" ? v.trim() : ""))
|
|
11
|
+
.filter(Boolean)
|
|
12
|
+
.join(",");
|
|
13
|
+
}
|
|
14
|
+
function toInt(v) {
|
|
15
|
+
if (typeof v === "number" && Number.isFinite(v))
|
|
16
|
+
return Math.trunc(v);
|
|
17
|
+
if (typeof v === "string") {
|
|
18
|
+
const n = Number(v);
|
|
19
|
+
if (Number.isFinite(n))
|
|
20
|
+
return Math.trunc(n);
|
|
21
|
+
}
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
export async function zoektEvidence(input) {
|
|
25
|
+
const basePath = process.cwd();
|
|
26
|
+
validateToolInput({ project_id: input.project_id, run_id: input.run_id });
|
|
27
|
+
const resolvedRun = resolveRunId(input.run_id ?? input.project_id, basePath);
|
|
28
|
+
const run_id = resolvedRun.run_id;
|
|
29
|
+
const project_id = resolveProjectId(run_id, basePath);
|
|
30
|
+
const roots = Array.isArray(input.roots) ? input.roots.map((r) => String(r).trim()).filter(Boolean) : [];
|
|
31
|
+
const queries = Array.isArray(input.queries) ? input.queries.map((q) => String(q).trim()).filter(Boolean) : [];
|
|
32
|
+
if (roots.length === 0)
|
|
33
|
+
throw new McpError(ErrorCode.InvalidParams, "[VALIDATION] roots is required");
|
|
34
|
+
if (queries.length === 0)
|
|
35
|
+
throw new McpError(ErrorCode.InvalidParams, "[VALIDATION] queries is required");
|
|
36
|
+
const cmd = ["zoekt-evidence", run_id, "--roots", toCsv(roots), "--queries", toCsv(queries)];
|
|
37
|
+
const samplePaths = toInt(input?.sample_paths);
|
|
38
|
+
if (samplePaths !== undefined)
|
|
39
|
+
cmd.push("--sample-paths", String(samplePaths));
|
|
40
|
+
const maxFileBytes = toInt(input?.max_file_bytes);
|
|
41
|
+
if (maxFileBytes !== undefined)
|
|
42
|
+
cmd.push("--max-file-bytes", String(maxFileBytes));
|
|
43
|
+
const writeEvidence = input?.write_evidence !== false;
|
|
44
|
+
if (!writeEvidence)
|
|
45
|
+
cmd.push("--no-write-evidence");
|
|
46
|
+
const res = await runEngine("vibecoding-helper", cmd, { timeoutMs: 300_000 });
|
|
47
|
+
if (res.code !== 0) {
|
|
48
|
+
throw new Error(`zoekt-evidence failed: ${res.stderr || res.stdout || `exit_code=${res.code}`}`);
|
|
49
|
+
}
|
|
50
|
+
const parsed = safeJsonParse(res.stdout);
|
|
51
|
+
if (!parsed.ok) {
|
|
52
|
+
throw new Error(`zoekt-evidence invalid_json: ${parsed.error}`);
|
|
53
|
+
}
|
|
54
|
+
const doc = parsed.value;
|
|
55
|
+
const engineRaw = typeof doc?.engine === "string" ? doc.engine : "";
|
|
56
|
+
const engine = engineRaw === "zoekt" || engineRaw === "rg" || engineRaw === "python_scan" ? engineRaw : "python_scan";
|
|
57
|
+
const warnings = [];
|
|
58
|
+
if (Array.isArray(doc?.warnings)) {
|
|
59
|
+
for (const w of doc.warnings) {
|
|
60
|
+
if (typeof w === "string" && w.trim())
|
|
61
|
+
warnings.push(w.trim());
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const queriesOut = [];
|
|
65
|
+
const rawQueries = Array.isArray(doc?.queries) ? doc.queries : [];
|
|
66
|
+
for (const q of rawQueries) {
|
|
67
|
+
const obj = q;
|
|
68
|
+
const qq = typeof obj?.q === "string" ? obj.q.trim() : "";
|
|
69
|
+
if (!qq)
|
|
70
|
+
continue;
|
|
71
|
+
queriesOut.push({
|
|
72
|
+
q: qq,
|
|
73
|
+
repos_scanned: typeof obj?.repos_scanned === "number" ? obj.repos_scanned : 0,
|
|
74
|
+
match_count: typeof obj?.match_count === "number" ? obj.match_count : 0,
|
|
75
|
+
sample_paths: Array.isArray(obj?.sample_paths)
|
|
76
|
+
? obj.sample_paths.map((x) => String(x)).filter(Boolean)
|
|
77
|
+
: []
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
const evidencePath = typeof doc?.evidence_path === "string" && doc.evidence_path.trim() ? String(doc.evidence_path).trim() : undefined;
|
|
81
|
+
const out = {
|
|
82
|
+
success: true,
|
|
83
|
+
project_id,
|
|
84
|
+
run_id,
|
|
85
|
+
engine,
|
|
86
|
+
queries: queriesOut,
|
|
87
|
+
warnings,
|
|
88
|
+
next_action: {
|
|
89
|
+
tool: "vibe_pm.export_output",
|
|
90
|
+
reason: "Use this evidence to validate patterns/OSS choices, then export."
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
if (evidencePath)
|
|
94
|
+
out.evidence_path = evidencePath;
|
|
95
|
+
return out;
|
|
96
|
+
}
|