@mandujs/cli 0.12.2 → 0.13.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 (51) hide show
  1. package/README.ko.md +234 -234
  2. package/README.md +354 -354
  3. package/package.json +2 -2
  4. package/src/commands/contract.ts +173 -173
  5. package/src/commands/dev.ts +8 -68
  6. package/src/commands/doctor.ts +27 -27
  7. package/src/commands/guard-arch.ts +303 -303
  8. package/src/commands/guard-check.ts +3 -3
  9. package/src/commands/monitor.ts +300 -300
  10. package/src/commands/openapi.ts +107 -107
  11. package/src/commands/registry.ts +367 -357
  12. package/src/commands/routes.ts +228 -228
  13. package/src/commands/start.ts +184 -0
  14. package/src/errors/codes.ts +35 -35
  15. package/src/errors/index.ts +2 -2
  16. package/src/errors/messages.ts +143 -143
  17. package/src/hooks/index.ts +17 -17
  18. package/src/hooks/preaction.ts +256 -256
  19. package/src/main.ts +37 -34
  20. package/src/terminal/banner.ts +166 -166
  21. package/src/terminal/help.ts +306 -306
  22. package/src/terminal/index.ts +71 -71
  23. package/src/terminal/output.ts +295 -295
  24. package/src/terminal/palette.ts +30 -30
  25. package/src/terminal/progress.ts +327 -327
  26. package/src/terminal/stream-writer.ts +214 -214
  27. package/src/terminal/table.ts +354 -354
  28. package/src/terminal/theme.ts +142 -142
  29. package/src/util/bun.ts +6 -6
  30. package/src/util/fs.ts +23 -23
  31. package/src/util/handlers.ts +96 -0
  32. package/src/util/manifest.ts +52 -52
  33. package/src/util/output.ts +22 -22
  34. package/src/util/port.ts +71 -71
  35. package/templates/default/AGENTS.md +96 -96
  36. package/templates/default/app/api/health/route.ts +13 -13
  37. package/templates/default/app/globals.css +49 -49
  38. package/templates/default/app/layout.tsx +27 -27
  39. package/templates/default/app/page.tsx +38 -38
  40. package/templates/default/package.json +1 -0
  41. package/templates/default/src/client/shared/lib/utils.ts +16 -16
  42. package/templates/default/src/client/shared/ui/button.tsx +57 -57
  43. package/templates/default/src/client/shared/ui/card.tsx +78 -78
  44. package/templates/default/src/client/shared/ui/index.ts +21 -21
  45. package/templates/default/src/client/shared/ui/input.tsx +24 -24
  46. package/templates/default/tests/example.test.ts +58 -58
  47. package/templates/default/tests/helpers.ts +52 -52
  48. package/templates/default/tests/setup.ts +9 -9
  49. package/templates/default/tsconfig.json +12 -14
  50. package/templates/default/apps/server/main.ts +0 -67
  51. package/templates/default/apps/web/entry.tsx +0 -35
@@ -1,303 +1,303 @@
1
- /**
2
- * mandu guard arch - Architecture Guard Command
3
- *
4
- * 실시간 아키텍처 감시 및 일회성 검사
5
- */
6
-
7
- import {
8
- createGuardWatcher,
9
- checkDirectory,
10
- printReport,
11
- formatReportForAgent,
12
- formatReportAsAgentJSON,
13
- getPreset,
14
- listPresets,
15
- createScanRecord,
16
- addScanRecord,
17
- loadStatistics,
18
- analyzeTrend,
19
- calculateLayerStatistics,
20
- generateGuardMarkdownReport,
21
- generateHTMLReport,
22
- validateAndReport,
23
- type GuardConfig,
24
- type GuardPreset,
25
- } from "@mandujs/core";
26
- import { writeFile } from "fs/promises";
27
- import { isDirectory, resolveFromCwd } from "../util/fs";
28
- import { resolveOutputFormat, type OutputFormat } from "../util/output";
29
- import path from "path";
30
-
31
- export interface GuardArchOptions {
32
- /** 프리셋 이름 */
33
- preset?: GuardPreset;
34
- /** 실시간 감시 모드 */
35
- watch?: boolean;
36
- /** CI 모드 (에러 시 exit 1) */
37
- ci?: boolean;
38
- /** 출력 형식: console, agent, json */
39
- format?: OutputFormat;
40
- /** 조용히 (요약만 출력) */
41
- quiet?: boolean;
42
- /** 소스 디렉토리 */
43
- srcDir?: string;
44
- /** 프리셋 목록 출력 */
45
- listPresets?: boolean;
46
- /** 리포트 파일 출력 */
47
- output?: string;
48
- /** 리포트 형식: json, markdown, html */
49
- reportFormat?: "json" | "markdown" | "html";
50
- /** 통계 저장 (트렌드 분석용) */
51
- saveStats?: boolean;
52
- /** 트렌드 분석 표시 */
53
- showTrend?: boolean;
54
- }
55
-
56
- function inferReportFormat(output?: string): "json" | "markdown" | "html" | undefined {
57
- if (!output) return undefined;
58
- const ext = path.extname(output).toLowerCase();
59
- if (ext === ".json") return "json";
60
- if (ext === ".html" || ext === ".htm") return "html";
61
- if (ext === ".md" || ext === ".markdown") return "markdown";
62
- return undefined;
63
- }
64
-
65
- export async function guardArch(options: GuardArchOptions = {}): Promise<boolean> {
66
- const rootDir = resolveFromCwd(".");
67
- const {
68
- watch = false,
69
- ci = process.env.CI === "true",
70
- format,
71
- quiet = false,
72
- listPresets: showPresets = false,
73
- output,
74
- reportFormat = inferReportFormat(options.output) ?? "markdown",
75
- saveStats = false,
76
- showTrend = false,
77
- } = options;
78
- const resolvedFormat = resolveOutputFormat(format);
79
- const enableFsRoutes = await isDirectory(path.resolve(rootDir, "app"));
80
-
81
- // 프리셋 목록 출력
82
- if (showPresets) {
83
- console.log("");
84
- console.log("🛡️ Mandu Guard - Available Presets");
85
- console.log("");
86
-
87
- const presets = listPresets();
88
- for (const p of presets) {
89
- const presetDef = getPreset(p.name);
90
- console.log(` ${p.name === "fsd" ? "✨ " : " "}${p.name}`);
91
- console.log(` ${p.description}`);
92
- console.log(` Layers: ${presetDef.hierarchy.join(" → ")}`);
93
- console.log("");
94
- }
95
-
96
- console.log("Usage: set guard.preset in mandu.config to choose a preset");
97
- return true;
98
- }
99
-
100
- const fileConfig = await validateAndReport(rootDir);
101
- if (!fileConfig) return false;
102
- const guardConfigFromFile = fileConfig.guard ?? {};
103
-
104
- const preset = options.preset ?? guardConfigFromFile.preset ?? "mandu";
105
- const srcDir = options.srcDir ?? guardConfigFromFile.srcDir ?? "src";
106
-
107
- if (resolvedFormat === "console") {
108
- console.log("");
109
- console.log("🛡️ Mandu Guard - Architecture Checker");
110
- console.log("");
111
- console.log(`📋 Preset: ${preset}`);
112
- console.log(`📂 Source: ${srcDir}/`);
113
- console.log(`🔧 Mode: ${watch ? "Watch" : "Check"}`);
114
- console.log("");
115
- }
116
-
117
- // Guard 설정
118
- const guardConfig: GuardConfig = {
119
- preset,
120
- srcDir,
121
- realtime: watch,
122
- realtimeOutput: resolvedFormat,
123
- exclude: guardConfigFromFile.exclude,
124
- fsRoutes: enableFsRoutes
125
- ? {
126
- noPageToPage: true,
127
- pageCanImport: [
128
- "client/pages",
129
- "client/widgets",
130
- "client/features",
131
- "client/entities",
132
- "client/shared",
133
- "shared/contracts",
134
- "shared/types",
135
- "shared/utils/client",
136
- ],
137
- layoutCanImport: [
138
- "client/app",
139
- "client/widgets",
140
- "client/shared",
141
- "shared/contracts",
142
- "shared/types",
143
- "shared/utils/client",
144
- ],
145
- routeCanImport: [
146
- "server/api",
147
- "server/application",
148
- "server/domain",
149
- "server/infra",
150
- "server/core",
151
- "shared/contracts",
152
- "shared/schema",
153
- "shared/types",
154
- "shared/utils/client",
155
- "shared/utils/server",
156
- "shared/env",
157
- ],
158
- }
159
- : undefined,
160
- };
161
-
162
- // 실시간 감시 모드
163
- if (watch) {
164
- if (resolvedFormat === "console") {
165
- console.log("👁️ Watching for architecture violations...");
166
- console.log(" Press Ctrl+C to stop\n");
167
- }
168
-
169
- const watcher = createGuardWatcher({
170
- config: guardConfig,
171
- rootDir,
172
- onViolation: (violation) => {
173
- // 실시간 위반 출력은 watcher 내부에서 처리됨
174
- },
175
- onFileAnalyzed: (analysis, violations) => {
176
- if (resolvedFormat === "console" && violations.length > 0 && !quiet) {
177
- const timestamp = new Date().toLocaleTimeString();
178
- console.log(`[${timestamp}] ${analysis.filePath}: ${violations.length} violation(s)`);
179
- }
180
- },
181
- });
182
-
183
- watcher.start();
184
-
185
- // Ctrl+C 핸들링
186
- process.on("SIGINT", () => {
187
- if (resolvedFormat === "console") {
188
- console.log("\n🛑 Guard stopped");
189
- }
190
- watcher.close();
191
- process.exit(0);
192
- });
193
-
194
- // 계속 실행
195
- return new Promise(() => {});
196
- }
197
-
198
- // 일회성 검사 모드
199
- if (resolvedFormat === "console" && !quiet) {
200
- console.log("🔍 Scanning for architecture violations...\n");
201
- }
202
-
203
- const report = await checkDirectory(guardConfig, rootDir);
204
- const presetDef = getPreset(preset);
205
-
206
- // 출력 형식에 따른 리포트 출력
207
- switch (resolvedFormat) {
208
- case "json":
209
- console.log(formatReportAsAgentJSON(report, preset));
210
- break;
211
-
212
- case "agent":
213
- console.log(formatReportForAgent(report, preset));
214
- break;
215
-
216
- case "console":
217
- default:
218
- if (quiet) {
219
- // 요약만 출력
220
- console.log(`Files analyzed: ${report.filesAnalyzed}`);
221
- console.log(`Violations: ${report.totalViolations}`);
222
- console.log(` Errors: ${report.bySeverity.error}`);
223
- console.log(` Warnings: ${report.bySeverity.warn}`);
224
- console.log(` Info: ${report.bySeverity.info}`);
225
- } else {
226
- printReport(report, presetDef.hierarchy);
227
- }
228
- break;
229
- }
230
-
231
- // 통계 저장
232
- if (saveStats) {
233
- const scanRecord = createScanRecord(report, preset);
234
- await addScanRecord(rootDir, scanRecord);
235
- console.log("📊 Statistics saved to .mandu/guard-stats.json");
236
- }
237
-
238
- // 트렌드 분석
239
- let trend = null;
240
- let layerStats = null;
241
-
242
- if (showTrend) {
243
- const store = await loadStatistics(rootDir);
244
- trend = analyzeTrend(store.records, 7);
245
- layerStats = calculateLayerStatistics(report.violations, presetDef.hierarchy);
246
-
247
- if (trend) {
248
- console.log("");
249
- console.log("📈 Trend Analysis (7 days):");
250
- const trendEmoji = trend.trend === "improving" ? "📉" : trend.trend === "degrading" ? "📈" : "➡️";
251
- console.log(` Status: ${trendEmoji} ${trend.trend.toUpperCase()}`);
252
- console.log(` Change: ${trend.violationDelta >= 0 ? "+" : ""}${trend.violationDelta} (${trend.violationChangePercent >= 0 ? "+" : ""}${trend.violationChangePercent}%)`);
253
-
254
- if (trend.recommendations.length > 0) {
255
- console.log(" 💡 Recommendations:");
256
- for (const rec of trend.recommendations) {
257
- console.log(` - ${rec}`);
258
- }
259
- }
260
- }
261
- }
262
-
263
- // 리포트 파일 출력
264
- if (output) {
265
- let reportContent: string;
266
-
267
- switch (reportFormat) {
268
- case "json":
269
- reportContent = formatReportAsAgentJSON(report, preset);
270
- break;
271
- case "html":
272
- reportContent = generateHTMLReport(report, trend, layerStats ?? undefined);
273
- break;
274
- case "markdown":
275
- default:
276
- reportContent = generateGuardMarkdownReport(report, trend, layerStats ?? undefined);
277
- break;
278
- }
279
-
280
- await writeFile(output, reportContent);
281
- console.log(`\n📄 Report saved to ${output}`);
282
- }
283
-
284
- // CI 모드에서 에러가 있으면 실패
285
- const hasErrors = report.bySeverity.error > 0;
286
- const hasWarnings = report.bySeverity.warn > 0;
287
-
288
- if (report.totalViolations === 0) {
289
- console.log("\n✅ Architecture check passed");
290
- return true;
291
- }
292
-
293
- if (hasErrors || (ci && hasWarnings)) {
294
- const reason = hasErrors
295
- ? `${report.bySeverity.error} error(s)`
296
- : `${report.bySeverity.warn} warning(s)`;
297
- console.log(`\n❌ Architecture check failed: ${reason}`);
298
- return false;
299
- }
300
-
301
- console.log(`\n⚠️ ${report.totalViolations} issue(s) found`);
302
- return true;
303
- }
1
+ /**
2
+ * mandu guard arch - Architecture Guard Command
3
+ *
4
+ * 실시간 아키텍처 감시 및 일회성 검사
5
+ */
6
+
7
+ import {
8
+ createGuardWatcher,
9
+ checkDirectory,
10
+ printReport,
11
+ formatReportForAgent,
12
+ formatReportAsAgentJSON,
13
+ getPreset,
14
+ listPresets,
15
+ createScanRecord,
16
+ addScanRecord,
17
+ loadStatistics,
18
+ analyzeTrend,
19
+ calculateLayerStatistics,
20
+ generateGuardMarkdownReport,
21
+ generateHTMLReport,
22
+ validateAndReport,
23
+ type GuardConfig,
24
+ type GuardPreset,
25
+ } from "@mandujs/core";
26
+ import { writeFile } from "fs/promises";
27
+ import { isDirectory, resolveFromCwd } from "../util/fs";
28
+ import { resolveOutputFormat, type OutputFormat } from "../util/output";
29
+ import path from "path";
30
+
31
+ export interface GuardArchOptions {
32
+ /** 프리셋 이름 */
33
+ preset?: GuardPreset;
34
+ /** 실시간 감시 모드 */
35
+ watch?: boolean;
36
+ /** CI 모드 (에러 시 exit 1) */
37
+ ci?: boolean;
38
+ /** 출력 형식: console, agent, json */
39
+ format?: OutputFormat;
40
+ /** 조용히 (요약만 출력) */
41
+ quiet?: boolean;
42
+ /** 소스 디렉토리 */
43
+ srcDir?: string;
44
+ /** 프리셋 목록 출력 */
45
+ listPresets?: boolean;
46
+ /** 리포트 파일 출력 */
47
+ output?: string;
48
+ /** 리포트 형식: json, markdown, html */
49
+ reportFormat?: "json" | "markdown" | "html";
50
+ /** 통계 저장 (트렌드 분석용) */
51
+ saveStats?: boolean;
52
+ /** 트렌드 분석 표시 */
53
+ showTrend?: boolean;
54
+ }
55
+
56
+ function inferReportFormat(output?: string): "json" | "markdown" | "html" | undefined {
57
+ if (!output) return undefined;
58
+ const ext = path.extname(output).toLowerCase();
59
+ if (ext === ".json") return "json";
60
+ if (ext === ".html" || ext === ".htm") return "html";
61
+ if (ext === ".md" || ext === ".markdown") return "markdown";
62
+ return undefined;
63
+ }
64
+
65
+ export async function guardArch(options: GuardArchOptions = {}): Promise<boolean> {
66
+ const rootDir = resolveFromCwd(".");
67
+ const {
68
+ watch = false,
69
+ ci = process.env.CI === "true",
70
+ format,
71
+ quiet = false,
72
+ listPresets: showPresets = false,
73
+ output,
74
+ reportFormat = inferReportFormat(options.output) ?? "markdown",
75
+ saveStats = false,
76
+ showTrend = false,
77
+ } = options;
78
+ const resolvedFormat = resolveOutputFormat(format);
79
+ const enableFsRoutes = await isDirectory(path.resolve(rootDir, "app"));
80
+
81
+ // 프리셋 목록 출력
82
+ if (showPresets) {
83
+ console.log("");
84
+ console.log("🛡️ Mandu Guard - Available Presets");
85
+ console.log("");
86
+
87
+ const presets = listPresets();
88
+ for (const p of presets) {
89
+ const presetDef = getPreset(p.name);
90
+ console.log(` ${p.name === "fsd" ? "✨ " : " "}${p.name}`);
91
+ console.log(` ${p.description}`);
92
+ console.log(` Layers: ${presetDef.hierarchy.join(" → ")}`);
93
+ console.log("");
94
+ }
95
+
96
+ console.log("Usage: set guard.preset in mandu.config to choose a preset");
97
+ return true;
98
+ }
99
+
100
+ const fileConfig = await validateAndReport(rootDir);
101
+ if (!fileConfig) return false;
102
+ const guardConfigFromFile = fileConfig.guard ?? {};
103
+
104
+ const preset = options.preset ?? guardConfigFromFile.preset ?? "mandu";
105
+ const srcDir = options.srcDir ?? guardConfigFromFile.srcDir ?? "src";
106
+
107
+ if (resolvedFormat === "console") {
108
+ console.log("");
109
+ console.log("🛡️ Mandu Guard - Architecture Checker");
110
+ console.log("");
111
+ console.log(`📋 Preset: ${preset}`);
112
+ console.log(`📂 Source: ${srcDir}/`);
113
+ console.log(`🔧 Mode: ${watch ? "Watch" : "Check"}`);
114
+ console.log("");
115
+ }
116
+
117
+ // Guard 설정
118
+ const guardConfig: GuardConfig = {
119
+ preset,
120
+ srcDir,
121
+ realtime: watch,
122
+ realtimeOutput: resolvedFormat,
123
+ exclude: guardConfigFromFile.exclude,
124
+ fsRoutes: enableFsRoutes
125
+ ? {
126
+ noPageToPage: true,
127
+ pageCanImport: [
128
+ "client/pages",
129
+ "client/widgets",
130
+ "client/features",
131
+ "client/entities",
132
+ "client/shared",
133
+ "shared/contracts",
134
+ "shared/types",
135
+ "shared/utils/client",
136
+ ],
137
+ layoutCanImport: [
138
+ "client/app",
139
+ "client/widgets",
140
+ "client/shared",
141
+ "shared/contracts",
142
+ "shared/types",
143
+ "shared/utils/client",
144
+ ],
145
+ routeCanImport: [
146
+ "server/api",
147
+ "server/application",
148
+ "server/domain",
149
+ "server/infra",
150
+ "server/core",
151
+ "shared/contracts",
152
+ "shared/schema",
153
+ "shared/types",
154
+ "shared/utils/client",
155
+ "shared/utils/server",
156
+ "shared/env",
157
+ ],
158
+ }
159
+ : undefined,
160
+ };
161
+
162
+ // 실시간 감시 모드
163
+ if (watch) {
164
+ if (resolvedFormat === "console") {
165
+ console.log("👁️ Watching for architecture violations...");
166
+ console.log(" Press Ctrl+C to stop\n");
167
+ }
168
+
169
+ const watcher = createGuardWatcher({
170
+ config: guardConfig,
171
+ rootDir,
172
+ onViolation: (violation) => {
173
+ // 실시간 위반 출력은 watcher 내부에서 처리됨
174
+ },
175
+ onFileAnalyzed: (analysis, violations) => {
176
+ if (resolvedFormat === "console" && violations.length > 0 && !quiet) {
177
+ const timestamp = new Date().toLocaleTimeString();
178
+ console.log(`[${timestamp}] ${analysis.filePath}: ${violations.length} violation(s)`);
179
+ }
180
+ },
181
+ });
182
+
183
+ watcher.start();
184
+
185
+ // Ctrl+C 핸들링
186
+ process.on("SIGINT", () => {
187
+ if (resolvedFormat === "console") {
188
+ console.log("\n🛑 Guard stopped");
189
+ }
190
+ watcher.close();
191
+ process.exit(0);
192
+ });
193
+
194
+ // 계속 실행
195
+ return new Promise(() => {});
196
+ }
197
+
198
+ // 일회성 검사 모드
199
+ if (resolvedFormat === "console" && !quiet) {
200
+ console.log("🔍 Scanning for architecture violations...\n");
201
+ }
202
+
203
+ const report = await checkDirectory(guardConfig, rootDir);
204
+ const presetDef = getPreset(preset);
205
+
206
+ // 출력 형식에 따른 리포트 출력
207
+ switch (resolvedFormat) {
208
+ case "json":
209
+ console.log(formatReportAsAgentJSON(report, preset));
210
+ break;
211
+
212
+ case "agent":
213
+ console.log(formatReportForAgent(report, preset));
214
+ break;
215
+
216
+ case "console":
217
+ default:
218
+ if (quiet) {
219
+ // 요약만 출력
220
+ console.log(`Files analyzed: ${report.filesAnalyzed}`);
221
+ console.log(`Violations: ${report.totalViolations}`);
222
+ console.log(` Errors: ${report.bySeverity.error}`);
223
+ console.log(` Warnings: ${report.bySeverity.warn}`);
224
+ console.log(` Info: ${report.bySeverity.info}`);
225
+ } else {
226
+ printReport(report, presetDef.hierarchy);
227
+ }
228
+ break;
229
+ }
230
+
231
+ // 통계 저장
232
+ if (saveStats) {
233
+ const scanRecord = createScanRecord(report, preset);
234
+ await addScanRecord(rootDir, scanRecord);
235
+ console.log("📊 Statistics saved to .mandu/guard-stats.json");
236
+ }
237
+
238
+ // 트렌드 분석
239
+ let trend = null;
240
+ let layerStats = null;
241
+
242
+ if (showTrend) {
243
+ const store = await loadStatistics(rootDir);
244
+ trend = analyzeTrend(store.records, 7);
245
+ layerStats = calculateLayerStatistics(report.violations, presetDef.hierarchy);
246
+
247
+ if (trend) {
248
+ console.log("");
249
+ console.log("📈 Trend Analysis (7 days):");
250
+ const trendEmoji = trend.trend === "improving" ? "📉" : trend.trend === "degrading" ? "📈" : "➡️";
251
+ console.log(` Status: ${trendEmoji} ${trend.trend.toUpperCase()}`);
252
+ console.log(` Change: ${trend.violationDelta >= 0 ? "+" : ""}${trend.violationDelta} (${trend.violationChangePercent >= 0 ? "+" : ""}${trend.violationChangePercent}%)`);
253
+
254
+ if (trend.recommendations.length > 0) {
255
+ console.log(" 💡 Recommendations:");
256
+ for (const rec of trend.recommendations) {
257
+ console.log(` - ${rec}`);
258
+ }
259
+ }
260
+ }
261
+ }
262
+
263
+ // 리포트 파일 출력
264
+ if (output) {
265
+ let reportContent: string;
266
+
267
+ switch (reportFormat) {
268
+ case "json":
269
+ reportContent = formatReportAsAgentJSON(report, preset);
270
+ break;
271
+ case "html":
272
+ reportContent = generateHTMLReport(report, trend, layerStats ?? undefined);
273
+ break;
274
+ case "markdown":
275
+ default:
276
+ reportContent = generateGuardMarkdownReport(report, trend, layerStats ?? undefined);
277
+ break;
278
+ }
279
+
280
+ await writeFile(output, reportContent);
281
+ console.log(`\n📄 Report saved to ${output}`);
282
+ }
283
+
284
+ // CI 모드에서 에러가 있으면 실패
285
+ const hasErrors = report.bySeverity.error > 0;
286
+ const hasWarnings = report.bySeverity.warn > 0;
287
+
288
+ if (report.totalViolations === 0) {
289
+ console.log("\n✅ Architecture check passed");
290
+ return true;
291
+ }
292
+
293
+ if (hasErrors || (ci && hasWarnings)) {
294
+ const reason = hasErrors
295
+ ? `${report.bySeverity.error} error(s)`
296
+ : `${report.bySeverity.warn} warning(s)`;
297
+ console.log(`\n❌ Architecture check failed: ${reason}`);
298
+ return false;
299
+ }
300
+
301
+ console.log(`\n⚠️ ${report.totalViolations} issue(s) found`);
302
+ return true;
303
+ }
@@ -13,13 +13,13 @@ export interface GuardCheckOptions {
13
13
  autoCorrect?: boolean;
14
14
  }
15
15
 
16
- export async function guardCheck(options: GuardCheckOptions = {}): Promise<boolean> {
17
- const { autoCorrect = true } = options;
16
+ export async function guardCheck(options: GuardCheckOptions = {}): Promise<boolean> {
17
+ const { autoCorrect = true } = options;
18
18
 
19
19
  const specPath = resolveFromCwd("spec/routes.manifest.json");
20
20
  const rootDir = getRootDir();
21
21
 
22
- console.log(`🥟 Mandu Guard (Legacy Spec)`);
22
+ console.log(`🥟 Mandu Guard (Legacy Spec)`);
23
23
  console.log(`📄 Spec 파일: ${specPath}`);
24
24
  console.log(`🔧 Auto-correct: ${autoCorrect ? "ON" : "OFF"}\n`);
25
25