@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,393 @@
1
+ // adapters/mcp-ts/src/tools/vibe_pm/finalize_work.ts
2
+ // vibe_pm.finalize_work - Document updates + DEV_LOG + Git commit/push
3
+ import * as fs from "node:fs";
4
+ import * as path from "node:path";
5
+ import { simpleGit } from "simple-git";
6
+ import { memorySync } from "./memory_sync.js";
7
+ import { getAuthGate } from "../../auth/index.js";
8
+ import { advisoryReview } from "./advisory_review.js";
9
+ import { runDocStatusTriage } from "./doc_status_gate.js";
10
+ import { kickoffKceSyncBestEffort } from "./kce/on_finalize.js";
11
+ import { updateVersionFile } from "../../version-check.js";
12
+ import { CONTRACTS_VERSION, CONTRACTS_BUNDLE_SHA256 } from "../../generated/contracts_bundle_info.js";
13
+ /**
14
+ * vibe_pm.finalize_work - Complete work with documentation and Git
15
+ *
16
+ * Steps:
17
+ * 1. Calculate date (YYYY-MM-DD)
18
+ * 2. Create/append DEV_LOG file (docs/dev_logs/{date}.md)
19
+ * 3. Update CURRENT_SPEC.md sections (if spec_changes provided)
20
+ * 4. git add .
21
+ * 5. git commit with conventional commit format
22
+ * 6. git push (if remote origin exists)
23
+ * 7. Return result
24
+ */
25
+ export async function finalizeWork(input, basePath = process.cwd()) {
26
+ const updatedFiles = [];
27
+ let warning;
28
+ // Step 1: Calculate date
29
+ const today = new Date();
30
+ const dateStr = today.toISOString().split("T")[0]; // YYYY-MM-DD
31
+ const timestamp = today.toISOString();
32
+ // Step 1.5: Archive Logic (Clean Desk Policy)
33
+ let sessionSummary = input.task_summary;
34
+ if (input.completed_plan_path) {
35
+ try {
36
+ const planPath = path.resolve(basePath, input.completed_plan_path);
37
+ const planningDir = path.resolve(basePath, "docs", "planning");
38
+ // Validate: must be inside docs/planning and exist
39
+ if (fs.existsSync(planPath) && planPath.startsWith(planningDir)) {
40
+ const archiveDir = path.join(basePath, "docs", "archive");
41
+ if (!fs.existsSync(archiveDir))
42
+ fs.mkdirSync(archiveDir, { recursive: true });
43
+ const fileName = path.basename(planPath);
44
+ const datePrefix = dateStr.replace(/-/g, ""); // 20240520
45
+ const archiveName = `${datePrefix}_${fileName}`;
46
+ const archivePath = path.join(archiveDir, archiveName);
47
+ fs.renameSync(planPath, archivePath);
48
+ const relativeArchive = path.relative(basePath, archivePath);
49
+ updatedFiles.push(relativeArchive);
50
+ sessionSummary += `\n\n> **Archived Plan**: \`${relativeArchive}\``;
51
+ }
52
+ else {
53
+ warning = warning ? `${warning}; Invalid plan path` : "Invalid plan path (not in planning dir or missing)";
54
+ }
55
+ }
56
+ catch (e) {
57
+ warning = warning ? `${warning}; Archive error: ${e}` : `Archive error: ${e}`;
58
+ }
59
+ }
60
+ // Step 2: Create/append DEV_LOG
61
+ const devLogDir = path.join(basePath, "docs", "dev_logs");
62
+ const devLogPath = path.join(devLogDir, `${dateStr}.md`);
63
+ try {
64
+ // Ensure directory exists
65
+ if (!fs.existsSync(devLogDir)) {
66
+ fs.mkdirSync(devLogDir, { recursive: true });
67
+ }
68
+ const logEntry = formatDevLogEntry(sessionSummary, timestamp, input.git_commit);
69
+ if (fs.existsSync(devLogPath)) {
70
+ // Append to existing file
71
+ fs.appendFileSync(devLogPath, `\n${logEntry}`);
72
+ }
73
+ else {
74
+ // Create new file with header
75
+ const header = `# DEV LOG - ${dateStr}\n\n`;
76
+ fs.writeFileSync(devLogPath, header + logEntry);
77
+ }
78
+ updatedFiles.push(devLogPath);
79
+ }
80
+ catch (err) {
81
+ warning = `DEV_LOG 생성 실패: ${err instanceof Error ? err.message : String(err)}`;
82
+ }
83
+ // Step 3: Update CURRENT_SPEC.md (if spec_changes provided)
84
+ if (input.spec_changes && input.spec_changes.length > 0) {
85
+ const specPath = path.join(basePath, "docs", "CURRENT_SPEC.md");
86
+ try {
87
+ if (fs.existsSync(specPath)) {
88
+ let specContent = fs.readFileSync(specPath, "utf-8");
89
+ for (const change of input.spec_changes) {
90
+ specContent = applySpecChange(specContent, change.section, change.content, change.action ?? "REPLACE");
91
+ }
92
+ fs.writeFileSync(specPath, specContent);
93
+ updatedFiles.push(specPath);
94
+ }
95
+ else {
96
+ // Create new CURRENT_SPEC.md
97
+ let newContent = "# CURRENT_SPEC\n\n";
98
+ for (const change of input.spec_changes) {
99
+ newContent += `## ${change.section}\n\n${change.content}\n\n`;
100
+ }
101
+ fs.writeFileSync(specPath, newContent);
102
+ updatedFiles.push(specPath);
103
+ }
104
+ }
105
+ catch (err) {
106
+ const errMsg = `CURRENT_SPEC.md 갱신 실패: ${err instanceof Error ? err.message : String(err)}`;
107
+ warning = warning ? `${warning}; ${errMsg}` : errMsg;
108
+ }
109
+ }
110
+ // Step 3.5: Doc Status Triage (must run before git add/commit; idempotent best-effort)
111
+ try {
112
+ const touched = updatedFiles
113
+ .map((p) => {
114
+ const abs = path.isAbsolute(p) ? p : path.resolve(basePath, p);
115
+ return path.relative(basePath, abs).replace(/\\\\/g, "/");
116
+ })
117
+ .filter(Boolean);
118
+ const triage = runDocStatusTriage({ basePath, touched_paths: touched, now: today });
119
+ for (const p of [...triage.tagged, ...triage.archived, ...triage.tombstoned]) {
120
+ if (!updatedFiles.includes(p))
121
+ updatedFiles.push(p);
122
+ }
123
+ }
124
+ catch (err) {
125
+ warning = appendWarning(warning, `DOC_STATUS_TRIAGE_FAILED: ${err instanceof Error ? err.message : String(err)}`);
126
+ }
127
+ // Best-effort: keep Local Memory up-to-date after doc updates (do not block finalize_work)
128
+ if (shouldKickoffAutoMemorySync(basePath)) {
129
+ void kickoffAutoMemorySyncProOnly();
130
+ }
131
+ // Step 4-6: Git (add/commit/pull-rebase/push)
132
+ const commitMessage = formatCommitMessage(input.git_commit);
133
+ let commitHash = "no-commit";
134
+ let pushedToRemote = false;
135
+ let remoteUrl;
136
+ try {
137
+ const git = simpleGit({ baseDir: basePath });
138
+ const isRepo = await git.checkIsRepo();
139
+ if (isRepo) {
140
+ // Stage + commit (only when there are changes)
141
+ const status = await git.status();
142
+ const hasChanges = status.files.length > 0;
143
+ let commitCreated = false;
144
+ // Best-effort: pre-finalize triage (never blocks finalize_work)
145
+ if (hasChanges && shouldKickoffAutoAdvisoryTriage(basePath)) {
146
+ try {
147
+ void advisoryReview({
148
+ mode: "triage",
149
+ trigger: "pre_finalize",
150
+ budget: "low",
151
+ changed_paths: status.files.map((f) => f.path)
152
+ });
153
+ }
154
+ catch {
155
+ // ignore
156
+ }
157
+ }
158
+ if (hasChanges) {
159
+ await git.add(".");
160
+ try {
161
+ await git.commit(commitMessage);
162
+ commitHash = (await git.revparse(["HEAD"])).trim() || "unknown";
163
+ commitCreated = true;
164
+ }
165
+ catch (err) {
166
+ warning = appendWarning(warning, `Git commit 실패: ${err instanceof Error ? err.message : String(err)}`);
167
+ }
168
+ }
169
+ else {
170
+ commitHash = "no-changes";
171
+ warning = appendWarning(warning, "커밋할 변경사항 없음");
172
+ }
173
+ // Remote origin (optional)
174
+ try {
175
+ remoteUrl = (await git.raw(["remote", "get-url", "origin"])).trim();
176
+ }
177
+ catch {
178
+ remoteUrl = undefined;
179
+ }
180
+ const canPull = commitCreated || commitHash === "no-changes";
181
+ if (remoteUrl && canPull) {
182
+ // Default: current branch (fallback: main)
183
+ let branchName = "main";
184
+ try {
185
+ const branch = await git.branch();
186
+ if (branch.current)
187
+ branchName = branch.current;
188
+ }
189
+ catch {
190
+ // ignore
191
+ }
192
+ if (branchName !== "main") {
193
+ warning = appendWarning(warning, `NOT_ON_MAIN: current=${branchName}`);
194
+ }
195
+ // Smart sync: pull --rebase before push
196
+ try {
197
+ await git.pull("origin", branchName, { "--rebase": "true" });
198
+ }
199
+ catch (err) {
200
+ // Rebase conflict stop (no auto-resolve)
201
+ try {
202
+ await git.rebase(["--abort"]);
203
+ }
204
+ catch {
205
+ // ignore
206
+ }
207
+ return {
208
+ success: false,
209
+ updated_files: updatedFiles,
210
+ commit_hash: commitHash,
211
+ pushed_to_remote: false,
212
+ remote_url: remoteUrl,
213
+ warning: appendWarning(warning, "MERGE_CONFLICT: manual_resolution_required"),
214
+ next_action: {
215
+ tool: "vibe_pm.status",
216
+ reason: "작업 완료 상태를 확인하세요",
217
+ },
218
+ };
219
+ }
220
+ // Push only when we produced a new commit
221
+ if (commitCreated && commitHash !== "no-commit" && commitHash !== "no-changes") {
222
+ try {
223
+ await git.push("origin", branchName);
224
+ pushedToRemote = true;
225
+ }
226
+ catch (err) {
227
+ warning = appendWarning(warning, `Git push 실패: ${err instanceof Error ? err.message : String(err)}`);
228
+ }
229
+ }
230
+ }
231
+ }
232
+ }
233
+ catch (err) {
234
+ // Git not available / not a repo / unexpected error: keep docs work, but surface warning
235
+ warning = appendWarning(warning, `Git 처리 실패: ${err instanceof Error ? err.message : String(err)}`);
236
+ }
237
+ // Best-effort: KCE sync (do not block finalize_work)
238
+ if (shouldKickoffAutoMemorySync(basePath)) {
239
+ void kickoffKceSyncBestEffort();
240
+ }
241
+ // Best-effort: Update .vibe/version.json (finalize_work + release 정책)
242
+ try {
243
+ const pkgJsonPath = path.join(basePath, "package.json");
244
+ let appVersion = "0.0.0";
245
+ if (fs.existsSync(pkgJsonPath)) {
246
+ const pkgJson = JSON.parse(fs.readFileSync(pkgJsonPath, "utf-8"));
247
+ appVersion = pkgJson.version ?? "0.0.0";
248
+ }
249
+ updateVersionFile({
250
+ repoRoot: basePath,
251
+ version: appVersion,
252
+ channel: "stable",
253
+ contractsSemver: CONTRACTS_VERSION,
254
+ contractsSha256: `sha256:${CONTRACTS_BUNDLE_SHA256}`,
255
+ });
256
+ }
257
+ catch {
258
+ // Best-effort: do not block finalize_work
259
+ }
260
+ return {
261
+ success: commitHash !== "no-commit" || updatedFiles.length > 0,
262
+ updated_files: updatedFiles,
263
+ commit_hash: commitHash,
264
+ pushed_to_remote: pushedToRemote,
265
+ remote_url: remoteUrl,
266
+ warning,
267
+ next_action: {
268
+ tool: "vibe_pm.status",
269
+ reason: "작업 완료 상태를 확인하세요"
270
+ }
271
+ };
272
+ }
273
+ /**
274
+ * Format DEV_LOG entry
275
+ */
276
+ function formatDevLogEntry(summary, timestamp, commit) {
277
+ const time = timestamp.split("T")[1]?.slice(0, 5) ?? "";
278
+ const typeLabel = getCommitTypeLabel(commit.type);
279
+ const scope = commit.scope ? `(${commit.scope})` : "";
280
+ return `## ${time} - ${typeLabel}${scope}: ${commit.subject}
281
+
282
+ ${summary}
283
+
284
+ ---
285
+ `;
286
+ }
287
+ function shouldKickoffAutoMemorySync(basePath) {
288
+ // Skip for tests / library calls where basePath is injected
289
+ if (path.resolve(basePath) !== path.resolve(process.cwd()))
290
+ return false;
291
+ const raw = (process.env.VIBECODE_AUTOMEMORY ?? "").trim().toLowerCase();
292
+ if (raw && (raw === "0" || raw === "false" || raw === "no" || raw === "off"))
293
+ return false;
294
+ const nodeEnv = (process.env.NODE_ENV ?? "").trim().toLowerCase();
295
+ if (nodeEnv === "test")
296
+ return false;
297
+ const vitest = (process.env.VITEST ?? "").trim().toLowerCase();
298
+ if (vitest && vitest !== "0" && vitest !== "false" && vitest !== "no" && vitest !== "off")
299
+ return false;
300
+ return true;
301
+ }
302
+ async function kickoffAutoMemorySyncProOnly() {
303
+ try {
304
+ const gate = getAuthGate();
305
+ const allowed = await gate.check("local_memory_pro_tools");
306
+ if (!allowed.allowed)
307
+ return;
308
+ await memorySync({ docs_root: "docs", mode: "pre_finalize", force_full: false });
309
+ }
310
+ catch {
311
+ // ignore (best-effort)
312
+ }
313
+ }
314
+ function shouldKickoffAutoAdvisoryTriage(basePath) {
315
+ // Skip for tests / library calls where basePath is injected
316
+ if (path.resolve(basePath) !== path.resolve(process.cwd()))
317
+ return false;
318
+ const raw = (process.env.VIBECODE_AUTOADVISORY ?? "").trim().toLowerCase();
319
+ if (raw && (raw === "0" || raw === "false" || raw === "no" || raw === "off"))
320
+ return false;
321
+ const nodeEnv = (process.env.NODE_ENV ?? "").trim().toLowerCase();
322
+ if (nodeEnv === "test")
323
+ return false;
324
+ const vitest = (process.env.VITEST ?? "").trim().toLowerCase();
325
+ if (vitest && vitest !== "0" && vitest !== "false" && vitest !== "no" && vitest !== "off")
326
+ return false;
327
+ return true;
328
+ }
329
+ /**
330
+ * Get human-readable commit type label
331
+ */
332
+ function getCommitTypeLabel(type) {
333
+ const labels = {
334
+ feat: "새 기능",
335
+ fix: "버그 수정",
336
+ docs: "문서",
337
+ style: "스타일",
338
+ refactor: "리팩토링",
339
+ test: "테스트",
340
+ chore: "기타"
341
+ };
342
+ return labels[type] ?? type;
343
+ }
344
+ /**
345
+ * Format commit message in conventional commit style
346
+ */
347
+ function formatCommitMessage(commit) {
348
+ const scope = commit.scope ? `(${commit.scope})` : "";
349
+ let message = `${commit.type}${scope}: ${commit.subject}`;
350
+ if (commit.body) {
351
+ message += `\n\n${commit.body}`;
352
+ }
353
+ if (commit.footer) {
354
+ message += `\n\n${commit.footer}`;
355
+ }
356
+ return message;
357
+ }
358
+ /**
359
+ * Apply spec change to content
360
+ */
361
+ function applySpecChange(content, section, newContent, action) {
362
+ // Find section pattern: ## Section Name or # Section Name
363
+ const sectionPattern = new RegExp(`(^#{1,3}\\s*${escapeRegExp(section)}\\s*$)([\\s\\S]*?)(?=^#{1,3}\\s|$)`, "m");
364
+ const match = content.match(sectionPattern);
365
+ if (match) {
366
+ if (action === "REPLACE") {
367
+ return content.replace(sectionPattern, `$1\n\n${newContent}\n\n`);
368
+ }
369
+ else {
370
+ // APPEND
371
+ const existingContent = match[2].trim();
372
+ return content.replace(sectionPattern, `$1\n\n${existingContent}\n\n${newContent}\n\n`);
373
+ }
374
+ }
375
+ else {
376
+ // Section not found, append at end
377
+ return content + `\n\n## ${section}\n\n${newContent}\n`;
378
+ }
379
+ }
380
+ /**
381
+ * Escape string for shell argument
382
+ */
383
+ function appendWarning(existing, next) {
384
+ if (!existing)
385
+ return next;
386
+ return `${existing}; ${next}`;
387
+ }
388
+ /**
389
+ * Escape string for regex
390
+ */
391
+ function escapeRegExp(str) {
392
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
393
+ }
@@ -0,0 +1,33 @@
1
+ // adapters/mcp-ts/src/tools/vibe_pm/gate.ts
2
+ // vibe_pm.gate - System Design Gate check (direct)
3
+ import { GateInputSchema } from "../../generated/gate_input.js";
4
+ import { GateOutputSchema } from "../../generated/gate_output.js";
5
+ import { WorkOrderV1Schema } from "../../generated/work_order_v1.js";
6
+ import { checkGate } from "../../control_plane/gate.js";
7
+ // SSOT-generated (JSON Schema → Zod)
8
+ export const gateInputSchema = GateInputSchema;
9
+ export const gateOutputSchema = GateOutputSchema;
10
+ /**
11
+ * vibe_pm.gate
12
+ *
13
+ * Validates a WorkOrderV1 against System Design Gate.
14
+ * Returns GateOutput (GateResultV1-compatible shape).
15
+ */
16
+ export async function gate(input) {
17
+ const basePath = process.cwd();
18
+ // Fail-closed on tool input drift
19
+ const parsed = gateInputSchema.parse(input);
20
+ const workOrder = WorkOrderV1Schema.parse(parsed.work_order);
21
+ const opts = parsed.options;
22
+ const out = await checkGate(workOrder, {
23
+ repoRoot: basePath,
24
+ failFast: opts?.fail_fast,
25
+ semgrep: opts?.semgrep,
26
+ runtime: opts?.runtime
27
+ });
28
+ if (!out.result) {
29
+ throw new Error(out.error ?? "Gate returned no result");
30
+ }
31
+ // Fail-closed on output drift
32
+ return gateOutputSchema.parse(out.result);
33
+ }