@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,631 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// vibe-cli.ts - Thin CLI wrapper for non-technical users
|
|
3
|
+
// Usage: vibe <command> [options]
|
|
4
|
+
import * as fs from "node:fs";
|
|
5
|
+
import * as path from "node:path";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { healthCheck, validateCacheIntegrity, checkForUpdates } from "./bootstrap/doctor.js";
|
|
8
|
+
import { ensureEngines } from "./bootstrap/installer.js";
|
|
9
|
+
import { CONTRACTS_BUNDLE_SHA256, CONTRACTS_VERSION } from "./generated/contracts_bundle_info.js";
|
|
10
|
+
import { spawnBashScriptInRepoSync } from "./local-mode/bash.js";
|
|
11
|
+
import { getGitHooksPath, getGitRoot } from "./local-mode/git.js";
|
|
12
|
+
import { initLocalModeRepo } from "./local-mode/init.js";
|
|
13
|
+
import { setRepoConfigValue, validateRepoConfig } from "./local-mode/config.js";
|
|
14
|
+
import { getVibeRepoPaths } from "./local-mode/paths.js";
|
|
15
|
+
import { archiveCurrentWorkOrder, createWorkOrderTemplate, readCurrentWorkOrder, writeCurrentWorkOrder } from "./local-mode/work-order.js";
|
|
16
|
+
import { autoUpdateOnStart } from "./version-check.js";
|
|
17
|
+
// ============================================================
|
|
18
|
+
// Constants
|
|
19
|
+
// ============================================================
|
|
20
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
const VERSION = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "package.json"), "utf-8")).version;
|
|
22
|
+
// ANSI color codes (no dependencies)
|
|
23
|
+
const colors = {
|
|
24
|
+
reset: "\x1b[0m",
|
|
25
|
+
bold: "\x1b[1m",
|
|
26
|
+
dim: "\x1b[2m",
|
|
27
|
+
red: "\x1b[31m",
|
|
28
|
+
green: "\x1b[32m",
|
|
29
|
+
yellow: "\x1b[33m",
|
|
30
|
+
blue: "\x1b[34m",
|
|
31
|
+
magenta: "\x1b[35m",
|
|
32
|
+
cyan: "\x1b[36m",
|
|
33
|
+
};
|
|
34
|
+
const c = (color, text) => process.stdout.isTTY ? `${colors[color]}${text}${colors.reset}` : text;
|
|
35
|
+
// ============================================================
|
|
36
|
+
// CLI Commands
|
|
37
|
+
// ============================================================
|
|
38
|
+
async function cmdDoctor() {
|
|
39
|
+
console.log("");
|
|
40
|
+
console.log(c("cyan", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
|
41
|
+
console.log(c("cyan", " Vibe PM Doctor"));
|
|
42
|
+
console.log(c("cyan", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
|
43
|
+
console.log("");
|
|
44
|
+
// Check MCP server
|
|
45
|
+
console.log(` MCP Server: ${c("green", "✓")} @vibecode/mcp-server@${VERSION}`);
|
|
46
|
+
console.log(` Contracts: ${c("green", "✓")} v${CONTRACTS_VERSION} (${CONTRACTS_BUNDLE_SHA256.slice(0, 12)})`);
|
|
47
|
+
// Health check - gets list of EngineHealth objects
|
|
48
|
+
const health = await healthCheck();
|
|
49
|
+
// Show engine status
|
|
50
|
+
console.log("");
|
|
51
|
+
console.log(" Engines:");
|
|
52
|
+
for (const engine of health.engines) {
|
|
53
|
+
const statusIcon = engine.status === "ok"
|
|
54
|
+
? c("green", "✓")
|
|
55
|
+
: engine.status === "needs_update"
|
|
56
|
+
? c("yellow", "↑")
|
|
57
|
+
: c("red", "✗");
|
|
58
|
+
const versionStr = engine.currentVersion ?? "not installed";
|
|
59
|
+
console.log(` ${engine.name.padEnd(20)} ${statusIcon} ${versionStr}`);
|
|
60
|
+
}
|
|
61
|
+
// Check for updates
|
|
62
|
+
console.log("");
|
|
63
|
+
const updates = await checkForUpdates();
|
|
64
|
+
if (updates.hasUpdates) {
|
|
65
|
+
console.log(` Updates available: ${c("yellow", "Yes")}`);
|
|
66
|
+
for (const [name, info] of Object.entries(updates.updates)) {
|
|
67
|
+
console.log(` ${name}: ${info.current ?? "none"} → ${info.required}`);
|
|
68
|
+
}
|
|
69
|
+
console.log("");
|
|
70
|
+
console.log(` Run ${c("cyan", "vibe update")} to install updates.`);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
console.log(` Updates: ${c("green", "✓")} All engines up to date`);
|
|
74
|
+
}
|
|
75
|
+
// Check cache integrity
|
|
76
|
+
const cacheResult = await validateCacheIntegrity();
|
|
77
|
+
console.log(` Cache: ${cacheResult.valid ? c("green", "✓") : c("yellow", "⚠")} ${cacheResult.valid ? "valid" : "needs repair"}`);
|
|
78
|
+
// Check Agent Skills files
|
|
79
|
+
console.log("");
|
|
80
|
+
console.log(" Agent Skills:");
|
|
81
|
+
const skillFiles = [
|
|
82
|
+
{ name: "AGENTS.md", path: "AGENTS.md" },
|
|
83
|
+
{ name: ".cursorrules", path: ".cursorrules" },
|
|
84
|
+
{ name: "CLAUDE.md", path: "CLAUDE.md" },
|
|
85
|
+
];
|
|
86
|
+
for (const file of skillFiles) {
|
|
87
|
+
const fileExists = fs.existsSync(path.join(process.cwd(), file.path));
|
|
88
|
+
const status = fileExists ? c("green", "✓") : c("dim", "○");
|
|
89
|
+
console.log(` ${file.name.padEnd(15)} ${status}`);
|
|
90
|
+
}
|
|
91
|
+
// Summary
|
|
92
|
+
console.log("");
|
|
93
|
+
console.log(c("cyan", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
|
94
|
+
const allOk = health.status === "OK" && cacheResult.valid;
|
|
95
|
+
if (allOk) {
|
|
96
|
+
console.log("");
|
|
97
|
+
console.log(` ${c("green", "✓ 모든 것이 정상입니다!")}`);
|
|
98
|
+
console.log("");
|
|
99
|
+
console.log(' 에디터에서 "시작해줘"라고 말해보세요.');
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
console.log("");
|
|
103
|
+
console.log(` ${c("yellow", "⚠ 일부 문제가 있습니다.")}`);
|
|
104
|
+
console.log("");
|
|
105
|
+
console.log(` ${c("cyan", "vibe reset")}으로 초기화하거나`);
|
|
106
|
+
console.log(` ${c("cyan", "vibe update")}로 업데이트하세요.`);
|
|
107
|
+
}
|
|
108
|
+
console.log("");
|
|
109
|
+
}
|
|
110
|
+
function resolveRepoRoot() {
|
|
111
|
+
return getGitRoot(process.cwd()) ?? process.cwd();
|
|
112
|
+
}
|
|
113
|
+
function cmdInit() {
|
|
114
|
+
const repoRoot = resolveRepoRoot();
|
|
115
|
+
const args = process.argv.slice(2);
|
|
116
|
+
const forceFlag = args.includes("--force") || args.includes("-f");
|
|
117
|
+
const noHooks = args.includes("--no-hooks");
|
|
118
|
+
const installCi = args.includes("--ci") || args.includes("--install-ci");
|
|
119
|
+
const ciFailOnWarn = args.includes("--strict");
|
|
120
|
+
const result = initLocalModeRepo(repoRoot, { force: forceFlag, installHooks: !noHooks, installCi, ciFailOnWarn });
|
|
121
|
+
console.log("");
|
|
122
|
+
console.log(c("cyan", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
|
123
|
+
console.log(c("cyan", " Vibe PM Local Mode Init"));
|
|
124
|
+
console.log(c("cyan", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
|
125
|
+
console.log("");
|
|
126
|
+
console.log(` Repo: ${repoRoot}`);
|
|
127
|
+
if (result.created.length > 0) {
|
|
128
|
+
console.log("");
|
|
129
|
+
console.log(" Created:");
|
|
130
|
+
for (const p of result.created)
|
|
131
|
+
console.log(` ${c("green", "✓")} ${path.relative(repoRoot, p)}`);
|
|
132
|
+
}
|
|
133
|
+
if (result.updated.length > 0) {
|
|
134
|
+
console.log("");
|
|
135
|
+
console.log(" Updated:");
|
|
136
|
+
for (const p of result.updated)
|
|
137
|
+
console.log(` ${c("yellow", "↑")} ${path.relative(repoRoot, p)}`);
|
|
138
|
+
}
|
|
139
|
+
if (result.notes.length > 0) {
|
|
140
|
+
console.log("");
|
|
141
|
+
console.log(" Notes:");
|
|
142
|
+
for (const n of result.notes)
|
|
143
|
+
console.log(` - ${n}`);
|
|
144
|
+
}
|
|
145
|
+
console.log("");
|
|
146
|
+
console.log(` Next: ${c("cyan", "vibe status")}`);
|
|
147
|
+
console.log("");
|
|
148
|
+
}
|
|
149
|
+
function cmdStatus() {
|
|
150
|
+
const repoRoot = resolveRepoRoot();
|
|
151
|
+
const paths = getVibeRepoPaths(repoRoot);
|
|
152
|
+
if (!fs.existsSync(paths.configFile)) {
|
|
153
|
+
console.log(`Not a Vibe-managed repo in: ${repoRoot}`);
|
|
154
|
+
console.log(`Run: ${c("cyan", "vibe init")}`);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
const cfgResult = validateRepoConfig(paths.configFile);
|
|
158
|
+
const config = cfgResult.ok ? cfgResult.config : null;
|
|
159
|
+
const hooksPath = getGitHooksPath(repoRoot);
|
|
160
|
+
const workOrder = readCurrentWorkOrder(paths.currentWorkOrderFile);
|
|
161
|
+
console.log("");
|
|
162
|
+
console.log(c("cyan", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
|
163
|
+
console.log(c("cyan", " Vibe PM Status (Local Mode)"));
|
|
164
|
+
console.log(c("cyan", "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"));
|
|
165
|
+
console.log("");
|
|
166
|
+
console.log(` Repo: ${repoRoot}`);
|
|
167
|
+
console.log(` Config: ${fs.existsSync(paths.configFile) ? c("green", "✓") : c("red", "✗")} ${path.relative(repoRoot, paths.configFile)}`);
|
|
168
|
+
if (!cfgResult.ok) {
|
|
169
|
+
console.log(` Config Valid: ${c("red", "✗")} ${cfgResult.error}`);
|
|
170
|
+
}
|
|
171
|
+
else if (config) {
|
|
172
|
+
console.log(` Mode: ${config.mode ?? "local-first"}`);
|
|
173
|
+
console.log(` Enforcement: ${config.policy?.enforcement ?? "warn"}`);
|
|
174
|
+
}
|
|
175
|
+
console.log(` Hooks Path: ${hooksPath ? hooksPath : c("dim", "(not set)")}`);
|
|
176
|
+
console.log(` CI Workflow: ${fs.existsSync(paths.ciWorkflowFile) ? c("green", "✓") : c("dim", "○")} ${path.relative(repoRoot, paths.ciWorkflowFile)}`);
|
|
177
|
+
console.log(` Work Order: ${workOrder ? c("green", "✓") : c("dim", "○")} ${path.relative(repoRoot, paths.currentWorkOrderFile)}`);
|
|
178
|
+
if (workOrder) {
|
|
179
|
+
console.log(` ID: ${workOrder.run_id}`);
|
|
180
|
+
console.log(` Topic: ${workOrder.topic ?? ""}`);
|
|
181
|
+
console.log(` Created: ${workOrder.created_at}`);
|
|
182
|
+
}
|
|
183
|
+
console.log("");
|
|
184
|
+
}
|
|
185
|
+
function cmdTicket() {
|
|
186
|
+
const repoRoot = resolveRepoRoot();
|
|
187
|
+
const paths = getVibeRepoPaths(repoRoot);
|
|
188
|
+
if (!fs.existsSync(paths.configFile)) {
|
|
189
|
+
console.log(`Not a Vibe-managed repo in: ${repoRoot}`);
|
|
190
|
+
console.log(`Run: ${c("cyan", "vibe init")}`);
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
const cfg = validateRepoConfig(paths.configFile);
|
|
194
|
+
if (!cfg.ok) {
|
|
195
|
+
console.log(`[VIBE] Config invalid: ${cfg.error}`);
|
|
196
|
+
console.log(`Fix: vibe config validate`);
|
|
197
|
+
process.exit(1);
|
|
198
|
+
}
|
|
199
|
+
if (cfg.config.mode === "server-required") {
|
|
200
|
+
console.log(`[VIBE] Command disabled by policy (mode=server-required).`);
|
|
201
|
+
console.log(`Tip: switch mode to local-first in .vibe/config.json to use local ticket templates.`);
|
|
202
|
+
process.exit(1);
|
|
203
|
+
}
|
|
204
|
+
const args = process.argv.slice(2);
|
|
205
|
+
const forceFlag = args.includes("--force") || args.includes("-f");
|
|
206
|
+
const topic = args.filter((a) => !a.startsWith("-")).slice(1).join(" ").trim() || undefined;
|
|
207
|
+
const wo = createWorkOrderTemplate(topic);
|
|
208
|
+
writeCurrentWorkOrder(paths.currentWorkOrderFile, wo, { overwrite: forceFlag });
|
|
209
|
+
console.log(`[VIBE] Work order created (local)`);
|
|
210
|
+
console.log(` ID: ${wo.run_id}`);
|
|
211
|
+
console.log(` File: ${path.relative(repoRoot, paths.currentWorkOrderFile)}`);
|
|
212
|
+
}
|
|
213
|
+
function cmdCheck(update) {
|
|
214
|
+
const repoRoot = resolveRepoRoot();
|
|
215
|
+
const paths = getVibeRepoPaths(repoRoot);
|
|
216
|
+
const cfg = validateRepoConfig(paths.configFile);
|
|
217
|
+
if (!cfg.ok) {
|
|
218
|
+
console.log(`[VIBE] Config invalid: ${cfg.error}`);
|
|
219
|
+
console.log(`Fix: vibe config validate`);
|
|
220
|
+
process.exit(1);
|
|
221
|
+
}
|
|
222
|
+
if (cfg.config.mode === "server-required") {
|
|
223
|
+
console.log(`[VIBE] Command disabled by policy (mode=server-required).`);
|
|
224
|
+
console.log(`Tip: switch mode to local-first in .vibe/config.json to use local checks.`);
|
|
225
|
+
process.exit(1);
|
|
226
|
+
}
|
|
227
|
+
if (!fs.existsSync(paths.validateScript)) {
|
|
228
|
+
console.log(`Missing local guard: ${path.relative(repoRoot, paths.validateScript)}`);
|
|
229
|
+
console.log(`Run: ${c("cyan", "vibe init")}`);
|
|
230
|
+
process.exit(1);
|
|
231
|
+
}
|
|
232
|
+
const result = spawnBashScriptInRepoSync(repoRoot, paths.validateScript, [], { stdio: "inherit" });
|
|
233
|
+
if (!result) {
|
|
234
|
+
console.log("[VIBE] bash runtime not found.");
|
|
235
|
+
console.log("Install Git Bash (recommended) or WSL to run local guard scripts.");
|
|
236
|
+
process.exit(1);
|
|
237
|
+
}
|
|
238
|
+
// Local Mode signal alignment: update checks never block execution.
|
|
239
|
+
// This is a best-effort WARN reminder after the primary guard run.
|
|
240
|
+
if (update?.updateAvailable && !update.updated) {
|
|
241
|
+
const from = update.localVersion ?? "?";
|
|
242
|
+
const to = update.remoteVersion ?? "?";
|
|
243
|
+
console.log("");
|
|
244
|
+
console.log(`[VIBE] 새 버전이 있습니다: ${from} → ${to}`);
|
|
245
|
+
console.log("Tip: 다음 실행에서 업데이트를 허용하거나, 원격과 fast-forward로 동기화하세요.");
|
|
246
|
+
console.log("");
|
|
247
|
+
}
|
|
248
|
+
process.exit(result.status ?? 1);
|
|
249
|
+
}
|
|
250
|
+
function cmdDone() {
|
|
251
|
+
const repoRoot = resolveRepoRoot();
|
|
252
|
+
const paths = getVibeRepoPaths(repoRoot);
|
|
253
|
+
if (!fs.existsSync(paths.configFile)) {
|
|
254
|
+
console.log(`Not a Vibe-managed repo in: ${repoRoot}`);
|
|
255
|
+
console.log(`Run: ${c("cyan", "vibe init")}`);
|
|
256
|
+
process.exit(1);
|
|
257
|
+
}
|
|
258
|
+
const cfg = validateRepoConfig(paths.configFile);
|
|
259
|
+
if (!cfg.ok) {
|
|
260
|
+
console.log(`[VIBE] Config invalid: ${cfg.error}`);
|
|
261
|
+
console.log(`Fix: vibe config validate`);
|
|
262
|
+
process.exit(1);
|
|
263
|
+
}
|
|
264
|
+
if (cfg.config.mode === "server-required") {
|
|
265
|
+
console.log(`[VIBE] Command disabled by policy (mode=server-required).`);
|
|
266
|
+
console.log(`Tip: switch mode to local-first in .vibe/config.json to allow local finalization.`);
|
|
267
|
+
process.exit(1);
|
|
268
|
+
}
|
|
269
|
+
const archived = archiveCurrentWorkOrder(paths.currentWorkOrderFile, paths.archiveDir);
|
|
270
|
+
if (!archived) {
|
|
271
|
+
console.log("[VIBE] No active work order to finalize.");
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
console.log("[VIBE] Work finalized.");
|
|
275
|
+
console.log(` Archived: ${path.relative(repoRoot, archived.archivedPath)}`);
|
|
276
|
+
}
|
|
277
|
+
function cmdConfig() {
|
|
278
|
+
const repoRoot = resolveRepoRoot();
|
|
279
|
+
const paths = getVibeRepoPaths(repoRoot);
|
|
280
|
+
const args = process.argv.slice(2);
|
|
281
|
+
const sub = args[1]?.toLowerCase() ?? "help";
|
|
282
|
+
switch (sub) {
|
|
283
|
+
case "show": {
|
|
284
|
+
const raw = fs.existsSync(paths.configFile) ? fs.readFileSync(paths.configFile, "utf-8") : "{}\n";
|
|
285
|
+
process.stdout.write(raw);
|
|
286
|
+
break;
|
|
287
|
+
}
|
|
288
|
+
case "set": {
|
|
289
|
+
const key = args[2];
|
|
290
|
+
const value = args[3];
|
|
291
|
+
if (!key || value === undefined) {
|
|
292
|
+
console.log("Usage: vibe config set <key> <value>");
|
|
293
|
+
console.log("Supported keys:");
|
|
294
|
+
console.log(" mode (local-first|server-required)");
|
|
295
|
+
console.log(" policy.enforcement (warn|block)");
|
|
296
|
+
console.log(" policy.auto_update_on_start (off|prompt|silent)");
|
|
297
|
+
console.log(" hooks.pre_push.enabled (true|false)");
|
|
298
|
+
console.log(" hooks.pre_push.enforcement (warn|block)");
|
|
299
|
+
console.log(" hooks.pre_push.gitleaks_required (true|false)");
|
|
300
|
+
process.exit(1);
|
|
301
|
+
}
|
|
302
|
+
if (!fs.existsSync(paths.configFile)) {
|
|
303
|
+
console.log(`Missing config: ${path.relative(repoRoot, paths.configFile)}`);
|
|
304
|
+
console.log(`Run: ${c("cyan", "vibe init")}`);
|
|
305
|
+
process.exit(1);
|
|
306
|
+
}
|
|
307
|
+
const result = setRepoConfigValue(paths.configFile, key, value);
|
|
308
|
+
if (!result.ok) {
|
|
309
|
+
console.log(`✗ ${result.error}`);
|
|
310
|
+
process.exit(1);
|
|
311
|
+
}
|
|
312
|
+
console.log(`✓ ${key} set to ${value}`);
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
case "validate": {
|
|
316
|
+
const result = validateRepoConfig(paths.configFile);
|
|
317
|
+
if (result.ok) {
|
|
318
|
+
console.log("✓ Config is valid (schema validated)");
|
|
319
|
+
break;
|
|
320
|
+
}
|
|
321
|
+
console.log(`✗ Config invalid: ${result.error}`);
|
|
322
|
+
process.exit(1);
|
|
323
|
+
}
|
|
324
|
+
default: {
|
|
325
|
+
console.log("");
|
|
326
|
+
console.log("Usage: vibe config <command>");
|
|
327
|
+
console.log("");
|
|
328
|
+
console.log("Commands:");
|
|
329
|
+
console.log(` ${c("green", "show")} 설정 파일 출력`);
|
|
330
|
+
console.log(` ${c("green", "set")} 설정 변경 (예: set policy.enforcement block)`);
|
|
331
|
+
console.log(` ${c("green", "validate")} 설정 스키마 검증`);
|
|
332
|
+
console.log("");
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
async function cmdVersion() {
|
|
338
|
+
console.log(`@vibecode/mcp-server v${VERSION}`);
|
|
339
|
+
console.log(`contracts v${CONTRACTS_VERSION} (${CONTRACTS_BUNDLE_SHA256.slice(0, 12)})`);
|
|
340
|
+
// Also show engine versions if available
|
|
341
|
+
try {
|
|
342
|
+
const health = await healthCheck();
|
|
343
|
+
for (const engine of health.engines) {
|
|
344
|
+
if (engine.status === "ok" && engine.currentVersion) {
|
|
345
|
+
console.log(` ${engine.name}: ${engine.currentVersion}`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
catch {
|
|
350
|
+
// Ignore errors, just show MCP version
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
async function cmdReset() {
|
|
354
|
+
console.log("");
|
|
355
|
+
console.log(c("yellow", "Vibe PM Reset"));
|
|
356
|
+
console.log("");
|
|
357
|
+
const cwd = process.cwd();
|
|
358
|
+
const runsDir = path.join(cwd, "runs");
|
|
359
|
+
// Check if runs directory exists
|
|
360
|
+
if (!fs.existsSync(runsDir)) {
|
|
361
|
+
console.log(` runs/ 디렉토리가 없습니다. 초기화할 내용이 없습니다.`);
|
|
362
|
+
console.log("");
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
// Count runs
|
|
366
|
+
const runs = fs.readdirSync(runsDir).filter((f) => {
|
|
367
|
+
const stat = fs.statSync(path.join(runsDir, f));
|
|
368
|
+
return stat.isDirectory();
|
|
369
|
+
});
|
|
370
|
+
if (runs.length === 0) {
|
|
371
|
+
console.log(` runs/ 디렉토리가 비어있습니다.`);
|
|
372
|
+
console.log("");
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
console.log(` ${runs.length}개의 실행 기록을 발견했습니다.`);
|
|
376
|
+
console.log("");
|
|
377
|
+
// Interactive confirmation would need readline, but for simplicity
|
|
378
|
+
// we'll just show what would be deleted
|
|
379
|
+
console.log(` 삭제될 디렉토리:`);
|
|
380
|
+
for (const run of runs.slice(0, 5)) {
|
|
381
|
+
console.log(` - runs/${run}`);
|
|
382
|
+
}
|
|
383
|
+
if (runs.length > 5) {
|
|
384
|
+
console.log(` ... 외 ${runs.length - 5}개`);
|
|
385
|
+
}
|
|
386
|
+
console.log("");
|
|
387
|
+
// Check for --force flag
|
|
388
|
+
const forceFlag = process.argv.includes("--force") || process.argv.includes("-f");
|
|
389
|
+
if (!forceFlag) {
|
|
390
|
+
console.log(` ${c("yellow", "주의:")} 이 작업은 되돌릴 수 없습니다.`);
|
|
391
|
+
console.log(` 실제로 삭제하려면 ${c("cyan", "vibe reset --force")}를 사용하세요.`);
|
|
392
|
+
console.log("");
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
// Delete runs
|
|
396
|
+
console.log(` 삭제 중...`);
|
|
397
|
+
for (const run of runs) {
|
|
398
|
+
const runPath = path.join(runsDir, run);
|
|
399
|
+
fs.rmSync(runPath, { recursive: true, force: true });
|
|
400
|
+
console.log(` ${c("red", "✗")} runs/${run}`);
|
|
401
|
+
}
|
|
402
|
+
console.log("");
|
|
403
|
+
console.log(` ${c("green", "✓")} ${runs.length}개의 실행 기록이 삭제되었습니다.`);
|
|
404
|
+
console.log("");
|
|
405
|
+
}
|
|
406
|
+
async function cmdUpdate() {
|
|
407
|
+
console.log("");
|
|
408
|
+
console.log(c("cyan", "Vibe PM Update"));
|
|
409
|
+
console.log("");
|
|
410
|
+
console.log(" 엔진 업데이트 확인 중...");
|
|
411
|
+
try {
|
|
412
|
+
// Force reinstall all engines
|
|
413
|
+
const engines = await ensureEngines();
|
|
414
|
+
console.log("");
|
|
415
|
+
console.log(" 설치된 엔진:");
|
|
416
|
+
for (const [name, enginePath] of Object.entries(engines)) {
|
|
417
|
+
if (enginePath) {
|
|
418
|
+
console.log(` ${c("green", "✓")} ${name}`);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
console.log("");
|
|
422
|
+
console.log(` ${c("green", "✓")} 업데이트 완료!`);
|
|
423
|
+
}
|
|
424
|
+
catch (error) {
|
|
425
|
+
console.log("");
|
|
426
|
+
console.log(` ${c("red", "✗")} 업데이트 실패: ${error instanceof Error ? error.message : String(error)}`);
|
|
427
|
+
}
|
|
428
|
+
console.log("");
|
|
429
|
+
}
|
|
430
|
+
// P0-1: Subcommand-specific help messages
|
|
431
|
+
const SUBCOMMAND_HELP = {
|
|
432
|
+
init: `vibe init - 로컬 모드 초기화
|
|
433
|
+
|
|
434
|
+
Usage: vibe init [options]
|
|
435
|
+
|
|
436
|
+
Options:
|
|
437
|
+
-f, --force 기존 파일 덮어쓰기
|
|
438
|
+
--no-hooks git hooks 설치 스킵
|
|
439
|
+
--ci GitHub Actions 워크플로우 설치
|
|
440
|
+
--strict CI에서 경고도 실패 처리
|
|
441
|
+
|
|
442
|
+
Examples:
|
|
443
|
+
$ vibe init # 기본 초기화
|
|
444
|
+
$ vibe init --force # 기존 파일 덮어쓰기
|
|
445
|
+
$ vibe init --ci # CI 워크플로우 포함
|
|
446
|
+
`,
|
|
447
|
+
status: `vibe status - 로컬 상태 확인
|
|
448
|
+
|
|
449
|
+
Usage: vibe status
|
|
450
|
+
|
|
451
|
+
현재 레포지토리의 Vibe PM 상태를 표시합니다.
|
|
452
|
+
`,
|
|
453
|
+
ticket: `vibe ticket - 작업 티켓 생성
|
|
454
|
+
|
|
455
|
+
Usage: vibe ticket [topic] [options]
|
|
456
|
+
|
|
457
|
+
Options:
|
|
458
|
+
-f, --force 기존 티켓 덮어쓰기
|
|
459
|
+
|
|
460
|
+
Examples:
|
|
461
|
+
$ vibe ticket "Fix auth" # 주제 지정
|
|
462
|
+
$ vibe ticket --force # 기존 티켓 덮어쓰기
|
|
463
|
+
`,
|
|
464
|
+
check: `vibe check - 로컬 가드 검증 실행
|
|
465
|
+
|
|
466
|
+
Usage: vibe check
|
|
467
|
+
|
|
468
|
+
푸시 전 로컬 검증을 실행합니다.
|
|
469
|
+
gitleaks 등의 보안 검사를 포함합니다.
|
|
470
|
+
`,
|
|
471
|
+
done: `vibe done - 작업 티켓 종료
|
|
472
|
+
|
|
473
|
+
Usage: vibe done
|
|
474
|
+
|
|
475
|
+
현재 작업 티켓을 아카이브합니다.
|
|
476
|
+
`,
|
|
477
|
+
config: `vibe config - 설정 관리
|
|
478
|
+
|
|
479
|
+
Usage: vibe config <command>
|
|
480
|
+
|
|
481
|
+
Commands:
|
|
482
|
+
show 설정 파일 출력
|
|
483
|
+
set 설정 변경 (예: set policy.enforcement block)
|
|
484
|
+
validate 설정 스키마 검증
|
|
485
|
+
`,
|
|
486
|
+
doctor: `vibe doctor - 설치 상태 확인
|
|
487
|
+
|
|
488
|
+
Usage: vibe doctor
|
|
489
|
+
|
|
490
|
+
설치된 엔진, 캐시 상태, 에이전트 스킬 파일을 점검합니다.
|
|
491
|
+
`,
|
|
492
|
+
update: `vibe update - 엔진 바이너리 업데이트
|
|
493
|
+
|
|
494
|
+
Usage: vibe update
|
|
495
|
+
|
|
496
|
+
최신 엔진 바이너리를 다운로드/설치합니다.
|
|
497
|
+
`,
|
|
498
|
+
reset: `vibe reset - 프로젝트 초기화
|
|
499
|
+
|
|
500
|
+
Usage: vibe reset [options]
|
|
501
|
+
|
|
502
|
+
Options:
|
|
503
|
+
-f, --force 실제로 삭제 실행
|
|
504
|
+
|
|
505
|
+
runs/ 디렉토리의 실행 기록을 삭제합니다.
|
|
506
|
+
`,
|
|
507
|
+
};
|
|
508
|
+
// P0-1: Helper functions for --help priority handling
|
|
509
|
+
function hasHelpFlag(args) {
|
|
510
|
+
return args.includes("--help") || args.includes("-h");
|
|
511
|
+
}
|
|
512
|
+
function getCommandArgs(args) {
|
|
513
|
+
return args.slice(1);
|
|
514
|
+
}
|
|
515
|
+
function cmdHelp(subcommand) {
|
|
516
|
+
// P0-1: Show subcommand-specific help if available
|
|
517
|
+
if (subcommand && SUBCOMMAND_HELP[subcommand]) {
|
|
518
|
+
console.log(SUBCOMMAND_HELP[subcommand]);
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
console.log("");
|
|
522
|
+
console.log(c("cyan", "Vibe PM") + " - AI Project Manager for Non-Technical Founders");
|
|
523
|
+
console.log("");
|
|
524
|
+
console.log("Usage: vibe <command> [options]");
|
|
525
|
+
console.log("");
|
|
526
|
+
console.log("Commands:");
|
|
527
|
+
console.log(` ${c("green", "init")} 로컬 모드 초기화 (.vibe/ + 훅)`);
|
|
528
|
+
console.log(` ${c("green", "status")} 로컬 상태 확인`);
|
|
529
|
+
console.log(` ${c("green", "ticket")} 작업 티켓(Work Order) 생성`);
|
|
530
|
+
console.log(` ${c("green", "check")} 로컬 가드 검증 실행`);
|
|
531
|
+
console.log(` ${c("green", "done")} 작업 티켓 종료/아카이브`);
|
|
532
|
+
console.log(` ${c("green", "config")} 설정 관리 (show/validate)`);
|
|
533
|
+
console.log(` ${c("green", "doctor")} 설치 상태 확인 및 진단`);
|
|
534
|
+
console.log(` ${c("green", "version")} 버전 정보 출력`);
|
|
535
|
+
console.log(` ${c("green", "reset")} 프로젝트 초기화 (runs/ 정리)`);
|
|
536
|
+
console.log(` ${c("green", "update")} 엔진 바이너리 업데이트`);
|
|
537
|
+
console.log(` ${c("green", "help")} 이 도움말 표시`);
|
|
538
|
+
console.log("");
|
|
539
|
+
console.log("Options:");
|
|
540
|
+
console.log(` ${c("dim", "-f, --force")} 강제 실행 (reset 명령에서 사용)`);
|
|
541
|
+
console.log(` ${c("dim", "--no-update")} 자동 업데이트 체크 스킵`);
|
|
542
|
+
console.log(` ${c("dim", "-h, --help")} 명령어별 도움말 표시`);
|
|
543
|
+
console.log("");
|
|
544
|
+
console.log("Examples:");
|
|
545
|
+
console.log(` ${c("dim", "$")} vibe init # 로컬 모드 초기화`);
|
|
546
|
+
console.log(` ${c("dim", "$")} vibe init --help # init 명령어 도움말`);
|
|
547
|
+
console.log(` ${c("dim", "$")} vibe ticket \"Fix auth\" # 작업 티켓 생성`);
|
|
548
|
+
console.log(` ${c("dim", "$")} vibe check # 푸시 전 로컬 검증`);
|
|
549
|
+
console.log(` ${c("dim", "$")} vibe doctor # 설치 상태 확인`);
|
|
550
|
+
console.log(` ${c("dim", "$")} vibe reset --force # 프로젝트 초기화`);
|
|
551
|
+
console.log("");
|
|
552
|
+
console.log("More info:");
|
|
553
|
+
console.log(` Documentation: ${c("blue", "https://vibecode.town/docs")}`);
|
|
554
|
+
console.log(` Support: ${c("blue", "mayor@vibecode.town")}`);
|
|
555
|
+
console.log("");
|
|
556
|
+
}
|
|
557
|
+
// ============================================================
|
|
558
|
+
// Main Entry Point
|
|
559
|
+
// ============================================================
|
|
560
|
+
async function main() {
|
|
561
|
+
const args = process.argv.slice(2);
|
|
562
|
+
const command = args[0]?.toLowerCase() ?? "help";
|
|
563
|
+
const commandArgs = getCommandArgs(args);
|
|
564
|
+
const noUpdate = args.includes("--no-update");
|
|
565
|
+
// P0-1: --help는 실행보다 우선 처리
|
|
566
|
+
if (hasHelpFlag(commandArgs) && command !== "help" && command !== "-h" && command !== "--help") {
|
|
567
|
+
cmdHelp(command);
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
570
|
+
// 자동 업데이트 체크 (CLI 진입 훅)
|
|
571
|
+
// 정책: 모든 실패는 GO (절대 실행을 막지 않음)
|
|
572
|
+
const update = await autoUpdateOnStart({
|
|
573
|
+
cwd: process.cwd(),
|
|
574
|
+
noUpdate,
|
|
575
|
+
silent: command === "version" || command === "-v" || command === "--version",
|
|
576
|
+
});
|
|
577
|
+
try {
|
|
578
|
+
switch (command) {
|
|
579
|
+
case "init":
|
|
580
|
+
cmdInit();
|
|
581
|
+
break;
|
|
582
|
+
case "status":
|
|
583
|
+
cmdStatus();
|
|
584
|
+
break;
|
|
585
|
+
case "ticket":
|
|
586
|
+
case "create_work_order":
|
|
587
|
+
cmdTicket();
|
|
588
|
+
break;
|
|
589
|
+
case "check":
|
|
590
|
+
case "inspect_code":
|
|
591
|
+
cmdCheck(update);
|
|
592
|
+
break;
|
|
593
|
+
case "done":
|
|
594
|
+
case "finalize_work":
|
|
595
|
+
cmdDone();
|
|
596
|
+
break;
|
|
597
|
+
case "config":
|
|
598
|
+
cmdConfig();
|
|
599
|
+
break;
|
|
600
|
+
case "doctor":
|
|
601
|
+
await cmdDoctor();
|
|
602
|
+
break;
|
|
603
|
+
case "version":
|
|
604
|
+
case "-v":
|
|
605
|
+
case "--version":
|
|
606
|
+
await cmdVersion();
|
|
607
|
+
break;
|
|
608
|
+
case "reset":
|
|
609
|
+
await cmdReset();
|
|
610
|
+
break;
|
|
611
|
+
case "update":
|
|
612
|
+
await cmdUpdate();
|
|
613
|
+
break;
|
|
614
|
+
case "help":
|
|
615
|
+
case "-h":
|
|
616
|
+
case "--help":
|
|
617
|
+
default:
|
|
618
|
+
cmdHelp();
|
|
619
|
+
break;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
catch (error) {
|
|
623
|
+
console.error("");
|
|
624
|
+
console.error(c("red", "Error:"), error instanceof Error ? error.message : String(error));
|
|
625
|
+
console.error("");
|
|
626
|
+
console.error(`문제가 계속되면 ${c("cyan", "vibe doctor")}를 실행해 보세요.`);
|
|
627
|
+
console.error("");
|
|
628
|
+
process.exit(1);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
main();
|