pai-zero 0.11.0 → 0.11.1

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/dist/bin/pai.js CHANGED
@@ -53,6 +53,124 @@ var init_logger = __esm({
53
53
  }
54
54
  });
55
55
 
56
+ // src/core/config.ts
57
+ import path from "path";
58
+ import { createRequire } from "module";
59
+ import fs from "fs-extra";
60
+ function normalizeMode(value) {
61
+ if (value === "prototype" || value === "poc" || value === "production") return value;
62
+ if (value === "mockup") return "prototype";
63
+ return "prototype";
64
+ }
65
+ async function loadConfig(cwd) {
66
+ const configPath = path.join(cwd, CONFIG_DIR, CONFIG_FILE);
67
+ if (!await fs.pathExists(configPath)) return null;
68
+ const raw = await fs.readJson(configPath);
69
+ return {
70
+ ...raw,
71
+ mode: normalizeMode(raw.mode)
72
+ };
73
+ }
74
+ async function saveConfig(cwd, config) {
75
+ const configDir = path.join(cwd, CONFIG_DIR);
76
+ await fs.ensureDir(configDir);
77
+ await fs.writeJson(path.join(configDir, CONFIG_FILE), config, { spaces: 2 });
78
+ }
79
+ function createDefaultConfig(projectName, mode) {
80
+ return {
81
+ version: pkg.version,
82
+ mode: normalizeMode(mode),
83
+ projectName,
84
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
85
+ plugins: []
86
+ };
87
+ }
88
+ var require2, pkg, CONFIG_DIR, CONFIG_FILE;
89
+ var init_config = __esm({
90
+ "src/core/config.ts"() {
91
+ "use strict";
92
+ require2 = createRequire(import.meta.url);
93
+ pkg = require2("../../package.json");
94
+ CONFIG_DIR = ".pai";
95
+ CONFIG_FILE = "config.json";
96
+ }
97
+ });
98
+
99
+ // src/cli/commands/welcome.cmd.ts
100
+ var welcome_cmd_exports = {};
101
+ __export(welcome_cmd_exports, {
102
+ welcomeCommand: () => welcomeCommand
103
+ });
104
+ import { createRequire as createRequire2 } from "module";
105
+ import fs2 from "fs";
106
+ import path2 from "path";
107
+ async function welcomeCommand(cwd) {
108
+ const paiConfig = await loadConfig(cwd);
109
+ const inPaiProject = paiConfig !== null;
110
+ const hasGit = fs2.existsSync(path2.join(cwd, ".git"));
111
+ const hasPackageJson = fs2.existsSync(path2.join(cwd, "package.json"));
112
+ console.log("");
113
+ console.log(colors.accent(" \u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E"));
114
+ console.log(colors.accent(` \u2502 \u{1F527} PAI Zero v${pkg2.version.padEnd(22)}\u2502`));
115
+ console.log(colors.accent(" \u2502 Plugin AI for ProjectZero \u2502"));
116
+ console.log(colors.accent(" \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F"));
117
+ console.log("");
118
+ if (inPaiProject) {
119
+ console.log(colors.dim(" \uD604\uC7AC PAI \uD504\uB85C\uC81D\uD2B8\uAC00 \uAC10\uC9C0\uB418\uC5C8\uC2B5\uB2C8\uB2E4"));
120
+ console.log(colors.dim(` \u2500 \uBAA8\uB4DC: ${paiConfig.mode}`));
121
+ console.log(colors.dim(` \u2500 \uD50C\uB7EC\uADF8\uC778: ${paiConfig.plugins.length}\uAC1C \uC124\uCE58\uB428`));
122
+ console.log("");
123
+ console.log(colors.accent(" \uBC14\uB85C \uC4F8 \uC218 \uC788\uB294 \uBA85\uB839\uC5B4"));
124
+ console.log(colors.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
125
+ console.log(` ${colors.success("\u25CF")} ${"pai status".padEnd(18)} ${colors.dim("\uC124\uCE58\uB41C \uD50C\uB7EC\uADF8\uC778 \uD655\uC778")}`);
126
+ console.log(` ${colors.success("\u25CF")} ${"pai grade".padEnd(18)} ${colors.dim("AI \uAC1C\uBC1C \uC900\uBE44\uB3C4 \uD3C9\uAC00 (6\uCE74\uD14C\uACE0\uB9AC)")}`);
127
+ console.log(` ${colors.success("\u25CF")} ${"pai add".padEnd(18)} ${colors.dim("\uD50C\uB7EC\uADF8\uC778 \uCD94\uAC00 \xB7 \uBAA8\uB4DC \uC2B9\uACA9 (prototype\u2192poc\u2192production)")}`);
128
+ console.log(` ${colors.success("\u25CF")} ${"pai design".padEnd(18)} ${colors.dim("PRD/OMC \uC124\uACC4 \uAD00\uB9AC")}`);
129
+ console.log(` ${colors.success("\u25CF")} ${"pai test".padEnd(18)} ${colors.dim("\uD14C\uC2A4\uD2B8 + \uD558\uB124\uC2A4 \uAC80\uC99D")}`);
130
+ console.log(` ${colors.success("\u25CF")} ${"pai check".padEnd(18)} ${colors.dim("\uD658\uACBD \uC810\uAC80")}`);
131
+ console.log("");
132
+ console.log(colors.dim(" \uC804\uCCB4 \uBAA9\uB85D: ") + colors.accent("pai help"));
133
+ } else if (hasGit || hasPackageJson) {
134
+ console.log(colors.dim(" \uAE30\uC874 \uD504\uB85C\uC81D\uD2B8\uAC00 \uAC10\uC9C0\uB418\uC5C8\uC2B5\uB2C8\uB2E4 (PAI \uBBF8\uC124\uCE58)"));
135
+ console.log("");
136
+ console.log(colors.accent(" \uC2DC\uC791\uD558\uAE30"));
137
+ console.log(colors.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
138
+ console.log(` ${colors.success("\u25B8")} ${"pai init".padEnd(18)} ${colors.dim("\uC774 \uD504\uB85C\uC81D\uD2B8\uC5D0 PAI \uC801\uC6A9 (\uC790\uB3D9 \uC9C4\uB2E8 \uD3EC\uD568)")}`);
139
+ console.log(` ${colors.success("\u25B8")} ${"pai check".padEnd(18)}${colors.dim("\uD658\uACBD\uBD80\uD130 \uC810\uAC80")}`);
140
+ console.log("");
141
+ console.log(colors.dim(" \uC804\uCCB4 \uBAA9\uB85D: ") + colors.accent("pai help"));
142
+ } else {
143
+ console.log(colors.accent(" \uCC98\uC74C\uC774\uC2E0\uAC00\uC694?"));
144
+ console.log(colors.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
145
+ console.log(` ${colors.success("\u25B8")} ${"pai init <\uD504\uB85C\uC81D\uD2B8\uBA85>".padEnd(24)}${colors.dim("\uC0C8 \uD504\uB85C\uC81D\uD2B8 \uC2DC\uC791")}`);
146
+ console.log("");
147
+ console.log(colors.accent(" \uC774\uBBF8 PAI \uD504\uB85C\uC81D\uD2B8\uC5D0 \uC788\uB2E4\uBA74?"));
148
+ console.log(colors.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
149
+ console.log(` ${colors.success("\u25CF")} ${"pai status".padEnd(18)} ${colors.dim("\uC124\uCE58\uB41C \uD50C\uB7EC\uADF8\uC778 \uD655\uC778")}`);
150
+ console.log(` ${colors.success("\u25CF")} ${"pai grade".padEnd(18)} ${colors.dim("AI \uAC1C\uBC1C \uC900\uBE44\uB3C4 \uD3C9\uAC00")}`);
151
+ console.log(` ${colors.success("\u25CF")} ${"pai add".padEnd(18)} ${colors.dim("\uD50C\uB7EC\uADF8\uC778 \uCD94\uAC00 (\uBAA8\uB4DC \uC2B9\uACA9)")}`);
152
+ console.log("");
153
+ console.log(colors.accent(" \uBB38\uC81C\uAC00 \uC788\uB098\uC694?"));
154
+ console.log(colors.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
155
+ console.log(` ${colors.success("\u25CF")} ${"pai check".padEnd(18)} ${colors.dim("Node / Git / Claude Code / OMC \uC810\uAC80")}`);
156
+ console.log("");
157
+ console.log(colors.dim(" \uC804\uCCB4 \uBA85\uB839\uC5B4: ") + colors.accent("pai help"));
158
+ }
159
+ console.log("");
160
+ console.log(colors.dim(" \uBB38\uC11C: https://github.com/SoInKyu/pai"));
161
+ console.log("");
162
+ }
163
+ var require3, pkg2;
164
+ var init_welcome_cmd = __esm({
165
+ "src/cli/commands/welcome.cmd.ts"() {
166
+ "use strict";
167
+ init_logger();
168
+ init_config();
169
+ require3 = createRequire2(import.meta.url);
170
+ pkg2 = require3("../../package.json");
171
+ }
172
+ });
173
+
56
174
  // src/ui/banner.ts
57
175
  function printBanner() {
58
176
  const c2 = colors;
@@ -158,7 +276,7 @@ __export(analyzer_exports, {
158
276
  });
159
277
  import { readdir, access } from "fs/promises";
160
278
  import { join } from "path";
161
- import fs from "fs-extra";
279
+ import fs3 from "fs-extra";
162
280
  async function analyzeProject(targetPath) {
163
281
  try {
164
282
  await access(targetPath);
@@ -180,16 +298,16 @@ async function detectStack(cwd) {
180
298
  packageManager: null,
181
299
  hasTypeScript: false
182
300
  };
183
- if (await fs.pathExists(join(cwd, "package.json"))) {
301
+ if (await fs3.pathExists(join(cwd, "package.json"))) {
184
302
  info2.languages.push("JavaScript");
185
303
  info2.packageManager = "npm";
186
304
  try {
187
- const pkg4 = await fs.readJson(join(cwd, "package.json"));
305
+ const pkg5 = await fs3.readJson(join(cwd, "package.json"));
188
306
  const allDeps = {
189
- ...pkg4.dependencies ?? {},
190
- ...pkg4.devDependencies ?? {}
307
+ ...pkg5.dependencies ?? {},
308
+ ...pkg5.devDependencies ?? {}
191
309
  };
192
- if (allDeps["typescript"] || await fs.pathExists(join(cwd, "tsconfig.json"))) {
310
+ if (allDeps["typescript"] || await fs3.pathExists(join(cwd, "tsconfig.json"))) {
193
311
  info2.hasTypeScript = true;
194
312
  info2.languages.push("TypeScript");
195
313
  }
@@ -211,16 +329,16 @@ async function detectStack(cwd) {
211
329
  }
212
330
  } catch {
213
331
  }
214
- if (await fs.pathExists(join(cwd, "pnpm-lock.yaml"))) info2.packageManager = "pnpm";
215
- else if (await fs.pathExists(join(cwd, "yarn.lock"))) info2.packageManager = "yarn";
216
- else if (await fs.pathExists(join(cwd, "bun.lockb"))) info2.packageManager = "bun";
332
+ if (await fs3.pathExists(join(cwd, "pnpm-lock.yaml"))) info2.packageManager = "pnpm";
333
+ else if (await fs3.pathExists(join(cwd, "yarn.lock"))) info2.packageManager = "yarn";
334
+ else if (await fs3.pathExists(join(cwd, "bun.lockb"))) info2.packageManager = "bun";
217
335
  }
218
- if (await fs.pathExists(join(cwd, "pyproject.toml")) || await fs.pathExists(join(cwd, "requirements.txt"))) {
336
+ if (await fs3.pathExists(join(cwd, "pyproject.toml")) || await fs3.pathExists(join(cwd, "requirements.txt"))) {
219
337
  info2.languages.push("Python");
220
338
  }
221
- if (await fs.pathExists(join(cwd, "go.mod"))) info2.languages.push("Go");
222
- if (await fs.pathExists(join(cwd, "Cargo.toml"))) info2.languages.push("Rust");
223
- if (await fs.pathExists(join(cwd, "pom.xml")) || await fs.pathExists(join(cwd, "build.gradle"))) {
339
+ if (await fs3.pathExists(join(cwd, "go.mod"))) info2.languages.push("Go");
340
+ if (await fs3.pathExists(join(cwd, "Cargo.toml"))) info2.languages.push("Rust");
341
+ if (await fs3.pathExists(join(cwd, "pom.xml")) || await fs3.pathExists(join(cwd, "build.gradle"))) {
224
342
  info2.languages.push("Java");
225
343
  }
226
344
  return info2;
@@ -238,18 +356,18 @@ async function scanStructure(cwd) {
238
356
  }
239
357
  async function checkExistingConfig(cwd) {
240
358
  const [hasClaudeMd, hasClaudeDir, hasPaiDir, hasOpenSpec, hasOmc] = await Promise.all([
241
- fs.pathExists(join(cwd, "CLAUDE.md")),
242
- fs.pathExists(join(cwd, ".claude")),
243
- fs.pathExists(join(cwd, ".pai")),
244
- fs.pathExists(join(cwd, "docs", "openspec.md")).then(
245
- (r) => r ? r : fs.pathExists(join(cwd, "openspec.md"))
359
+ fs3.pathExists(join(cwd, "CLAUDE.md")),
360
+ fs3.pathExists(join(cwd, ".claude")),
361
+ fs3.pathExists(join(cwd, ".pai")),
362
+ fs3.pathExists(join(cwd, "docs", "openspec.md")).then(
363
+ (r) => r ? r : fs3.pathExists(join(cwd, "openspec.md"))
246
364
  ),
247
- fs.pathExists(join(cwd, ".pai", "omc.md"))
365
+ fs3.pathExists(join(cwd, ".pai", "omc.md"))
248
366
  ]);
249
367
  let claudeSettings = null;
250
368
  try {
251
- if (await fs.pathExists(join(cwd, ".claude", "settings.json"))) {
252
- claudeSettings = await fs.readJson(join(cwd, ".claude", "settings.json"));
369
+ if (await fs3.pathExists(join(cwd, ".claude", "settings.json"))) {
370
+ claudeSettings = await fs3.readJson(join(cwd, ".claude", "settings.json"));
253
371
  }
254
372
  } catch {
255
373
  }
@@ -275,7 +393,7 @@ async function listDirNames(dirPath) {
275
393
  }
276
394
  }
277
395
  async function getGitInfo(cwd) {
278
- const isGitRepo = await fs.pathExists(join(cwd, ".git"));
396
+ const isGitRepo = await fs3.pathExists(join(cwd, ".git"));
279
397
  if (!isGitRepo) {
280
398
  return { isGitRepo: false, remoteUrl: null, repoName: null, currentBranch: null };
281
399
  }
@@ -323,11 +441,14 @@ async function aiInterview(analysis, _cwd, projectName) {
323
441
  options: {
324
442
  maxTurns: 10,
325
443
  systemPrompt: `You are PAI, an AI assistant that helps set up vibe coding environments.
326
- Analyze the repository and ask the user targeted questions about project purpose (mockup/production), authentication, and domain.
444
+ Analyze the repository and ask the user targeted questions about project level (prototype/poc/production), authentication, and domain.
445
+ - prototype: quick idea validation, UI mockup, concept demo
446
+ - poc: PoC web development, working demo with basic features
447
+ - production: operational service with tests, QA, deployment, monitoring
327
448
  Output your final recommendation as a JSON code block with this schema:
328
449
  \`\`\`json
329
450
  {
330
- "mode": "mockup" | "production",
451
+ "mode": "prototype" | "poc" | "production",
331
452
  "projectName": string,
332
453
  "authMethods": string[],
333
454
  "setupDomains": { "claudeEnv": true, "processDocs": boolean, "cicd": boolean },
@@ -367,7 +488,7 @@ function parseAiResult(result, analysis, projectName) {
367
488
  try {
368
489
  const parsed = JSON.parse(jsonMatch[1]);
369
490
  return {
370
- mode: parsed.mode ?? "mockup",
491
+ mode: normalizeMode(parsed.mode),
371
492
  projectName,
372
493
  authMethods: parsed.authMethods ?? [],
373
494
  extraTools: parsed.extraTools ?? [],
@@ -393,24 +514,39 @@ function parseAiResult(result, analysis, projectName) {
393
514
  async function interactiveInterview(analysis, _cwd, projectName) {
394
515
  const { default: inquirer } = await import("inquirer");
395
516
  const chalk8 = (await import("chalk")).default;
396
- step(1, 3, "\uC2DC\uC791 \uBC29\uC2DD\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694");
397
- hint("\uD504\uB85C\uC81D\uD2B8\uC5D0 \uC5B4\uB5A4 \uB3C4\uAD6C\uB4E4\uC744 \uC124\uCE58\uD560\uC9C0 \uACB0\uC815\uD569\uB2C8\uB2E4.");
517
+ step(1, 3, "\uD504\uB85C\uC81D\uD2B8 \uC218\uC900\uC744 \uC120\uD0DD\uD574\uC8FC\uC138\uC694");
518
+ hint("\uC120\uD0DD\uC5D0 \uB530\uB77C \uC124\uCE58\uB418\uB294 \uD50C\uB7EC\uADF8\uC778 \uC138\uD2B8\uAC00 \uB2EC\uB77C\uC9D1\uB2C8\uB2E4.");
398
519
  console.log("");
399
520
  const { mode } = await inquirer.prompt([{
400
521
  type: "list",
401
522
  name: "mode",
402
- message: "\uC5B4\uB5A4 \uD504\uB85C\uC81D\uD2B8\uB97C \uB9CC\uB4DC\uC2DC\uB098\uC694?",
523
+ message: "\uC5B4\uB5A4 \uC218\uC900\uC758 \uD504\uB85C\uC81D\uD2B8\uC778\uAC00\uC694?",
403
524
  choices: [
404
525
  {
405
- name: `\uC544\uC774\uB514\uC5B4 \uC815\uB9AC ${colors.dim("\u2500 \uAE30\uD68D\uC11C/PRD \uBB38\uC11C\uB97C AI\uC640 \uD568\uAED8 \uC791\uC131")}`,
406
- value: "mockup"
526
+ name: `\u{1F9EA} prototype ${colors.dim("\u2500 \uBE60\uB978 \uAC80\uC99D (\uC544\uC774\uB514\uC5B4\xB7UI \uBAA9\uC5C5\xB7\uCEE8\uC149 \uC2DC\uC5F0)")}`,
527
+ value: "prototype"
407
528
  },
408
529
  {
409
- name: `\uC6F9 \uC11C\uBE44\uC2A4 \uAC1C\uBC1C ${colors.dim("\u2500 \uD654\uBA74 + \uC11C\uBC84 + DB + \uBC30\uD3EC\uAE4C\uC9C0 \uD55C\uBC88\uC5D0")}`,
530
+ name: `\u{1F52C} poc ${colors.dim("\u2500 PoC \uC6F9\uAC1C\uBC1C (\uB3D9\uC791 \uB370\uBAA8\xB7\uAE30\uBCF8 \uAE30\uB2A5 \uAD6C\uD604)")}`,
531
+ value: "poc"
532
+ },
533
+ {
534
+ name: `\u{1F3ED} production ${colors.dim("\u2500 \uC6B4\uC601 \uC11C\uBE44\uC2A4 (\uD14C\uC2A4\uD2B8\xB7QA\xB7\uBC30\uD3EC\xB7\uBAA8\uB2C8\uD130\uB9C1)")}`,
410
535
  value: "production"
411
536
  }
412
537
  ]
413
538
  }]);
539
+ console.log("");
540
+ console.log(colors.dim(" \uC774 \uC218\uC900\uC5D0 \uC124\uCE58\uB420 \uD56D\uBAA9"));
541
+ console.log(colors.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
542
+ const matrix = {
543
+ prototype: ["GitHub \uAD6C\uC870", "OpenSpec (PRD)", "roboco (\uC9C4\uB2E8)"],
544
+ poc: ["GitHub \uAD6C\uC870", "OpenSpec (PRD)", "roboco (\uC9C4\uB2E8)", "OMC (\uAC1D\uCCB4\uBAA8\uB378)", "Vercel \uBC30\uD3EC (\uC120\uD0DD)"],
545
+ production: ["GitHub \uAD6C\uC870", "OpenSpec (PRD)", "roboco (\uC9C4\uB2E8)", "OMC (\uAC1D\uCCB4\uBAA8\uB378)", "gstack (\uD14C\uC2A4\uD2B8)", "Harness (\uAC80\uC99D)", "Vercel \uBC30\uD3EC (\uC120\uD0DD)", "Supabase DB (\uC120\uD0DD)"]
546
+ };
547
+ for (const item of matrix[mode] ?? []) {
548
+ console.log(` ${colors.success("\u2713")} ${item}`);
549
+ }
414
550
  step(2, 3, "\uB85C\uADF8\uC778 \uAE30\uB2A5");
415
551
  hint("\uB098\uC911\uC5D0 \uCD94\uAC00\uD560 \uC218\uB3C4 \uC788\uC2B5\uB2C8\uB2E4.");
416
552
  console.log("");
@@ -469,7 +605,10 @@ async function interactiveInterview(analysis, _cwd, projectName) {
469
605
  }
470
606
  }
471
607
  let extraTools = [];
472
- if (mode === "production") {
608
+ if (mode === "poc" || mode === "production") {
609
+ extraTools.push("omc");
610
+ }
611
+ if (mode === "poc" || mode === "production") {
473
612
  console.log("");
474
613
  const { hosting } = await inquirer.prompt([{
475
614
  type: "list",
@@ -477,10 +616,14 @@ async function interactiveInterview(analysis, _cwd, projectName) {
477
616
  message: "\uBC30\uD3EC \uD658\uACBD:",
478
617
  choices: [
479
618
  { name: `Vercel ${colors.dim("\u2500 \uC790\uB3D9 \uBC30\uD3EC (Preview + Production)")}`, value: "vercel" },
480
- { name: `\uB2E4\uB978 \uC11C\uBE44\uC2A4 \uC0AC\uC6A9 ${colors.dim("\u2500 AWS, GCP, Netlify \uB4F1")}`, value: "other" },
481
- { name: `\uC628\uD504\uB808\uBBF8\uC2A4 ${colors.dim("\u2500 \uC9C1\uC811 \uC11C\uBC84 \uAD6C\uC131")}`, value: "onprem" }
619
+ { name: `\uB2E4\uB978 \uC11C\uBE44\uC2A4 \uC0AC\uC6A9 ${colors.dim("\u2500 AWS, GCP, Netlify \uB4F1)")}`, value: "other" },
620
+ { name: `\uB098\uC911\uC5D0 \uC815\uD558\uAE30 ${colors.dim("\u2500 \uBC30\uD3EC \uC124\uC815 \uC5C6\uC774 \uC2DC\uC791")}`, value: "skip" }
482
621
  ]
483
622
  }]);
623
+ if (hosting === "vercel") extraTools.push("vercel");
624
+ }
625
+ if (mode === "production") {
626
+ console.log("");
484
627
  const { database } = await inquirer.prompt([{
485
628
  type: "list",
486
629
  name: "database",
@@ -488,10 +631,9 @@ async function interactiveInterview(analysis, _cwd, projectName) {
488
631
  choices: [
489
632
  { name: `Supabase ${colors.dim("\u2500 PostgreSQL + Auth + Storage")}`, value: "supabase" },
490
633
  { name: `\uB2E4\uB978 \uC11C\uBE44\uC2A4 \uC0AC\uC6A9 ${colors.dim("\u2500 PlanetScale, Neon, Firebase \uB4F1")}`, value: "other" },
491
- { name: `\uC628\uD504\uB808\uBBF8\uC2A4 ${colors.dim("\u2500 \uC9C1\uC811 DB \uAD6C\uC131")}`, value: "onprem" }
634
+ { name: `\uB098\uC911\uC5D0 \uC815\uD558\uAE30 ${colors.dim("\u2500 DB \uC124\uC815 \uC5C6\uC774 \uC2DC\uC791")}`, value: "skip" }
492
635
  ]
493
636
  }]);
494
- if (hosting === "vercel") extraTools.push("vercel");
495
637
  if (database === "supabase") extraTools.push("supabase");
496
638
  extraTools.push("gstack", "harness");
497
639
  }
@@ -603,6 +745,7 @@ var init_interviewer = __esm({
603
745
  "use strict";
604
746
  init_ui();
605
747
  init_logger();
748
+ init_config();
606
749
  }
607
750
  });
608
751
 
@@ -612,7 +755,7 @@ __export(generator_exports, {
612
755
  generateFiles: () => generateFiles
613
756
  });
614
757
  import { join as join2 } from "path";
615
- import fs2 from "fs-extra";
758
+ import fs4 from "fs-extra";
616
759
  async function generateFiles(cwd, analysis, interview) {
617
760
  const files = [];
618
761
  files.push(generateClaudeMd(cwd, analysis, interview));
@@ -625,11 +768,11 @@ async function generateFiles(cwd, analysis, interview) {
625
768
  }
626
769
  const created = [];
627
770
  for (const file of files) {
628
- if (await fs2.pathExists(file.path) && !file.overwrite) {
771
+ if (await fs4.pathExists(file.path) && !file.overwrite) {
629
772
  continue;
630
773
  }
631
- await fs2.ensureDir(join2(file.path, ".."));
632
- await fs2.writeFile(file.path, file.content, "utf8");
774
+ await fs4.ensureDir(join2(file.path, ".."));
775
+ await fs4.writeFile(file.path, file.content, "utf8");
633
776
  created.push(file.path);
634
777
  }
635
778
  return created;
@@ -876,8 +1019,8 @@ __export(platform_exports, {
876
1019
  writeEnvFile: () => writeEnvFile
877
1020
  });
878
1021
  import os from "os";
879
- import fs3 from "fs";
880
- import path from "path";
1022
+ import fs5 from "fs";
1023
+ import path3 from "path";
881
1024
  import { execFileSync } from "child_process";
882
1025
  function diagnoseWindowsEnv() {
883
1026
  const issues = [];
@@ -905,7 +1048,7 @@ function diagnoseWindowsEnv() {
905
1048
  }
906
1049
  function writeEnvFile(filePath, entries) {
907
1050
  const content = Object.entries(entries).map(([k, v]) => `${k}=${v}`).join("\n");
908
- fs3.writeFileSync(filePath, content + "\n", { encoding: "utf8" });
1051
+ fs5.writeFileSync(filePath, content + "\n", { encoding: "utf8" });
909
1052
  }
910
1053
  function getPlatformInfo() {
911
1054
  return {
@@ -920,13 +1063,13 @@ function getPlatformInfo() {
920
1063
  function getShellRcPath() {
921
1064
  const home = os.homedir();
922
1065
  if (isWindows) {
923
- const ps7 = path.join(home, "Documents", "PowerShell", "Microsoft.PowerShell_profile.ps1");
924
- const ps5 = path.join(home, "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1");
925
- if (fs3.existsSync(path.dirname(ps7))) return ps7;
1066
+ const ps7 = path3.join(home, "Documents", "PowerShell", "Microsoft.PowerShell_profile.ps1");
1067
+ const ps5 = path3.join(home, "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1");
1068
+ if (fs5.existsSync(path3.dirname(ps7))) return ps7;
926
1069
  return ps5;
927
1070
  }
928
1071
  const shell = process.env["SHELL"] || "";
929
- return shell.includes("zsh") ? path.join(home, ".zshrc") : path.join(home, ".bashrc");
1072
+ return shell.includes("zsh") ? path3.join(home, ".zshrc") : path3.join(home, ".bashrc");
930
1073
  }
931
1074
  function spawnSubshell(cwd) {
932
1075
  try {
@@ -969,14 +1112,14 @@ __export(mcp_exports, {
969
1112
  provisionMcp: () => provisionMcp
970
1113
  });
971
1114
  import { join as join3 } from "path";
972
- import fs4 from "fs-extra";
1115
+ import fs6 from "fs-extra";
973
1116
  async function provisionMcp(ctx) {
974
1117
  const mcp = ctx.mcp;
975
1118
  if (!mcp?.enabled) return;
976
1119
  const mcpDir = join3(ctx.cwd, "mcp-server");
977
- await fs4.ensureDir(mcpDir);
978
- await fs4.ensureDir(join3(mcpDir, "src"));
979
- await fs4.ensureDir(join3(mcpDir, "tests"));
1120
+ await fs6.ensureDir(mcpDir);
1121
+ await fs6.ensureDir(join3(mcpDir, "src"));
1122
+ await fs6.ensureDir(join3(mcpDir, "tests"));
980
1123
  const isPublicDeps = mcp.type === "tools-public";
981
1124
  const pkgJson = {
982
1125
  name: mcp.name,
@@ -1002,8 +1145,8 @@ async function provisionMcp(ctx) {
1002
1145
  }
1003
1146
  };
1004
1147
  const pkgPath = join3(mcpDir, "package.json");
1005
- if (!await fs4.pathExists(pkgPath)) {
1006
- await fs4.writeJson(pkgPath, pkgJson, { spaces: 2 });
1148
+ if (!await fs6.pathExists(pkgPath)) {
1149
+ await fs6.writeJson(pkgPath, pkgJson, { spaces: 2 });
1007
1150
  }
1008
1151
  const tsconfig = {
1009
1152
  compilerOptions: {
@@ -1022,103 +1165,103 @@ async function provisionMcp(ctx) {
1022
1165
  exclude: ["node_modules", "dist", "tests"]
1023
1166
  };
1024
1167
  const tsPath = join3(mcpDir, "tsconfig.json");
1025
- if (!await fs4.pathExists(tsPath)) {
1026
- await fs4.writeJson(tsPath, tsconfig, { spaces: 2 });
1168
+ if (!await fs6.pathExists(tsPath)) {
1169
+ await fs6.writeJson(tsPath, tsconfig, { spaces: 2 });
1027
1170
  }
1028
1171
  const indexPath = join3(mcpDir, "src", "index.ts");
1029
- if (!await fs4.pathExists(indexPath)) {
1030
- await fs4.writeFile(indexPath, buildIndexTs(mcp), "utf8");
1172
+ if (!await fs6.pathExists(indexPath)) {
1173
+ await fs6.writeFile(indexPath, buildIndexTs(mcp), "utf8");
1031
1174
  }
1032
1175
  const isTools = mcp.type === "tools" || mcp.type === "tools-public" || mcp.type === "all";
1033
1176
  const isPublic = mcp.type === "tools-public";
1034
1177
  if (isTools) {
1035
1178
  const toolsPath = join3(mcpDir, "src", "tools.ts");
1036
- if (!await fs4.pathExists(toolsPath)) {
1037
- await fs4.writeFile(toolsPath, isPublic ? TOOLS_PUBLIC_TEMPLATE : TOOLS_TEMPLATE, "utf8");
1179
+ if (!await fs6.pathExists(toolsPath)) {
1180
+ await fs6.writeFile(toolsPath, isPublic ? TOOLS_PUBLIC_TEMPLATE : TOOLS_TEMPLATE, "utf8");
1038
1181
  }
1039
1182
  }
1040
1183
  if (isPublic) {
1041
1184
  const authPath = join3(mcpDir, "src", "auth.ts");
1042
- if (!await fs4.pathExists(authPath)) {
1043
- await fs4.writeFile(authPath, AUTH_MIDDLEWARE_TEMPLATE, "utf8");
1185
+ if (!await fs6.pathExists(authPath)) {
1186
+ await fs6.writeFile(authPath, AUTH_MIDDLEWARE_TEMPLATE, "utf8");
1044
1187
  }
1045
1188
  const rateLimitPath = join3(mcpDir, "src", "rate-limit.ts");
1046
- if (!await fs4.pathExists(rateLimitPath)) {
1047
- await fs4.writeFile(rateLimitPath, RATE_LIMIT_TEMPLATE, "utf8");
1189
+ if (!await fs6.pathExists(rateLimitPath)) {
1190
+ await fs6.writeFile(rateLimitPath, RATE_LIMIT_TEMPLATE, "utf8");
1048
1191
  }
1049
1192
  const migDir = join3(ctx.cwd, "supabase", "migrations");
1050
- await fs4.ensureDir(migDir);
1193
+ await fs6.ensureDir(migDir);
1051
1194
  const migPath = join3(migDir, "20260101_mcp_keys_and_usage.sql");
1052
- if (!await fs4.pathExists(migPath)) {
1053
- await fs4.writeFile(migPath, SUPABASE_MIGRATION, "utf8");
1195
+ if (!await fs6.pathExists(migPath)) {
1196
+ await fs6.writeFile(migPath, SUPABASE_MIGRATION, "utf8");
1054
1197
  }
1055
1198
  const dashDir = join3(ctx.cwd, "src", "app", "dashboard");
1056
- await fs4.ensureDir(join3(dashDir, "keys"));
1057
- await fs4.ensureDir(join3(dashDir, "usage"));
1199
+ await fs6.ensureDir(join3(dashDir, "keys"));
1200
+ await fs6.ensureDir(join3(dashDir, "usage"));
1058
1201
  const dashLayoutPath = join3(dashDir, "layout.tsx");
1059
- if (!await fs4.pathExists(dashLayoutPath)) {
1060
- await fs4.writeFile(dashLayoutPath, DASHBOARD_LAYOUT, "utf8");
1202
+ if (!await fs6.pathExists(dashLayoutPath)) {
1203
+ await fs6.writeFile(dashLayoutPath, DASHBOARD_LAYOUT, "utf8");
1061
1204
  }
1062
1205
  const dashPagePath = join3(dashDir, "page.tsx");
1063
- if (!await fs4.pathExists(dashPagePath)) {
1064
- await fs4.writeFile(dashPagePath, DASHBOARD_PAGE, "utf8");
1206
+ if (!await fs6.pathExists(dashPagePath)) {
1207
+ await fs6.writeFile(dashPagePath, DASHBOARD_PAGE, "utf8");
1065
1208
  }
1066
1209
  const keysPagePath = join3(dashDir, "keys", "page.tsx");
1067
- if (!await fs4.pathExists(keysPagePath)) {
1068
- await fs4.writeFile(keysPagePath, KEYS_PAGE, "utf8");
1210
+ if (!await fs6.pathExists(keysPagePath)) {
1211
+ await fs6.writeFile(keysPagePath, KEYS_PAGE, "utf8");
1069
1212
  }
1070
1213
  const usagePagePath = join3(dashDir, "usage", "page.tsx");
1071
- if (!await fs4.pathExists(usagePagePath)) {
1072
- await fs4.writeFile(usagePagePath, USAGE_PAGE, "utf8");
1214
+ if (!await fs6.pathExists(usagePagePath)) {
1215
+ await fs6.writeFile(usagePagePath, USAGE_PAGE, "utf8");
1073
1216
  }
1074
1217
  const apiKeysDir = join3(ctx.cwd, "src", "app", "api", "keys");
1075
- await fs4.ensureDir(apiKeysDir);
1218
+ await fs6.ensureDir(apiKeysDir);
1076
1219
  const keysRoutePath = join3(apiKeysDir, "route.ts");
1077
- if (!await fs4.pathExists(keysRoutePath)) {
1078
- await fs4.writeFile(keysRoutePath, KEYS_API_ROUTE, "utf8");
1220
+ if (!await fs6.pathExists(keysRoutePath)) {
1221
+ await fs6.writeFile(keysRoutePath, KEYS_API_ROUTE, "utf8");
1079
1222
  }
1080
1223
  }
1081
1224
  if (mcp.type === "resources" || mcp.type === "all") {
1082
1225
  const resPath = join3(mcpDir, "src", "resources.ts");
1083
- if (!await fs4.pathExists(resPath)) {
1084
- await fs4.writeFile(resPath, RESOURCES_TEMPLATE, "utf8");
1226
+ if (!await fs6.pathExists(resPath)) {
1227
+ await fs6.writeFile(resPath, RESOURCES_TEMPLATE, "utf8");
1085
1228
  }
1086
1229
  }
1087
1230
  if (mcp.type === "prompts" || mcp.type === "all") {
1088
1231
  const promptsPath = join3(mcpDir, "src", "prompts.ts");
1089
- if (!await fs4.pathExists(promptsPath)) {
1090
- await fs4.writeFile(promptsPath, PROMPTS_TEMPLATE, "utf8");
1232
+ if (!await fs6.pathExists(promptsPath)) {
1233
+ await fs6.writeFile(promptsPath, PROMPTS_TEMPLATE, "utf8");
1091
1234
  }
1092
1235
  }
1093
1236
  const testPath = join3(mcpDir, "tests", "server.test.ts");
1094
- if (!await fs4.pathExists(testPath)) {
1095
- await fs4.writeFile(testPath, TEST_TEMPLATE, "utf8");
1237
+ if (!await fs6.pathExists(testPath)) {
1238
+ await fs6.writeFile(testPath, TEST_TEMPLATE, "utf8");
1096
1239
  }
1097
1240
  const readmePath = join3(mcpDir, "README.md");
1098
- if (!await fs4.pathExists(readmePath)) {
1099
- await fs4.writeFile(readmePath, buildReadme(mcp), "utf8");
1241
+ if (!await fs6.pathExists(readmePath)) {
1242
+ await fs6.writeFile(readmePath, buildReadme(mcp), "utf8");
1100
1243
  }
1101
1244
  const openspecPath = join3(ctx.cwd, "docs", "openspec.md");
1102
- if (await fs4.pathExists(openspecPath)) {
1103
- const existing = await fs4.readFile(openspecPath, "utf8");
1245
+ if (await fs6.pathExists(openspecPath)) {
1246
+ const existing = await fs6.readFile(openspecPath, "utf8");
1104
1247
  if (!existing.includes("## MCP \uC11C\uBC84")) {
1105
1248
  const section2 = buildOpenSpecMcpSection(mcp);
1106
- await fs4.appendFile(openspecPath, `
1249
+ await fs6.appendFile(openspecPath, `
1107
1250
 
1108
1251
  ${section2}
1109
1252
  `);
1110
1253
  }
1111
1254
  }
1112
1255
  const mcpJsonPath = join3(ctx.cwd, ".mcp.json");
1113
- const mcpJson = await fs4.pathExists(mcpJsonPath) ? await fs4.readJson(mcpJsonPath) : { mcpServers: {} };
1256
+ const mcpJson = await fs6.pathExists(mcpJsonPath) ? await fs6.readJson(mcpJsonPath) : { mcpServers: {} };
1114
1257
  mcpJson.mcpServers[mcp.name] = {
1115
1258
  command: "node",
1116
1259
  args: ["./mcp-server/dist/index.js"]
1117
1260
  };
1118
- await fs4.writeJson(mcpJsonPath, mcpJson, { spaces: 2 });
1261
+ await fs6.writeJson(mcpJsonPath, mcpJson, { spaces: 2 });
1119
1262
  const gitignorePath = join3(mcpDir, ".gitignore");
1120
- if (!await fs4.pathExists(gitignorePath)) {
1121
- await fs4.writeFile(gitignorePath, "node_modules/\ndist/\n*.log\n", "utf8");
1263
+ if (!await fs6.pathExists(gitignorePath)) {
1264
+ await fs6.writeFile(gitignorePath, "node_modules/\ndist/\n*.log\n", "utf8");
1122
1265
  }
1123
1266
  }
1124
1267
  function buildIndexTs(mcp) {
@@ -1805,11 +1948,11 @@ __export(registry_exports, {
1805
1948
  runProvisioners: () => runProvisioners
1806
1949
  });
1807
1950
  import { join as join4 } from "path";
1808
- import fs5 from "fs-extra";
1951
+ import fs7 from "fs-extra";
1809
1952
  async function provisionGitHub(ctx) {
1810
1953
  const gitDir = join4(ctx.cwd, ".git");
1811
- if (!await fs5.pathExists(gitDir)) {
1812
- await fs5.ensureDir(join4(ctx.cwd, ".github", "workflows"));
1954
+ if (!await fs7.pathExists(gitDir)) {
1955
+ await fs7.ensureDir(join4(ctx.cwd, ".github", "workflows"));
1813
1956
  try {
1814
1957
  const { execa } = await import("execa");
1815
1958
  await execa("git", ["init"], { cwd: ctx.cwd });
@@ -1818,11 +1961,11 @@ async function provisionGitHub(ctx) {
1818
1961
  }
1819
1962
  }
1820
1963
  const dirs = ["src", "docs", "tests", "public", ".pai"];
1821
- await Promise.all(dirs.map((d) => fs5.ensureDir(join4(ctx.cwd, d))));
1964
+ await Promise.all(dirs.map((d) => fs7.ensureDir(join4(ctx.cwd, d))));
1822
1965
  const handoffPath = join4(ctx.cwd, "handoff.md");
1823
- if (!await fs5.pathExists(handoffPath)) {
1966
+ if (!await fs7.pathExists(handoffPath)) {
1824
1967
  const now = (/* @__PURE__ */ new Date()).toLocaleString("ko-KR");
1825
- await fs5.writeFile(handoffPath, [
1968
+ await fs7.writeFile(handoffPath, [
1826
1969
  `# Handoff \u2014 ${ctx.projectName}`,
1827
1970
  "",
1828
1971
  `> \uB9C8\uC9C0\uB9C9 \uC5C5\uB370\uC774\uD2B8: ${now}`,
@@ -1852,8 +1995,8 @@ async function provisionGitHub(ctx) {
1852
1995
  ].join("\n") + "\n");
1853
1996
  }
1854
1997
  const contribPath = join4(ctx.cwd, "CONTRIBUTING.md");
1855
- if (!await fs5.pathExists(contribPath)) {
1856
- await fs5.writeFile(contribPath, [
1998
+ if (!await fs7.pathExists(contribPath)) {
1999
+ await fs7.writeFile(contribPath, [
1857
2000
  `# Contributing to ${ctx.projectName}`,
1858
2001
  "",
1859
2002
  "\uC774 \uD504\uB85C\uC81D\uD2B8\uC5D0 \uAE30\uC5EC\uD574 \uC8FC\uC154\uC11C \uAC10\uC0AC\uD569\uB2C8\uB2E4.",
@@ -1898,10 +2041,10 @@ async function provisionGitHub(ctx) {
1898
2041
  ].join("\n") + "\n");
1899
2042
  }
1900
2043
  const contribSkillDir = join4(ctx.cwd, ".claude", "skills");
1901
- await fs5.ensureDir(contribSkillDir);
2044
+ await fs7.ensureDir(contribSkillDir);
1902
2045
  const contribSkillPath = join4(contribSkillDir, "contributing.md");
1903
- if (!await fs5.pathExists(contribSkillPath)) {
1904
- await fs5.writeFile(contribSkillPath, [
2046
+ if (!await fs7.pathExists(contribSkillPath)) {
2047
+ await fs7.writeFile(contribSkillPath, [
1905
2048
  "---",
1906
2049
  "name: contributing",
1907
2050
  'description: "\uAE30\uC5EC\uC790 \uAC00\uC774\uB4DC \u2014 \uBE0C\uB79C\uCE58 \uADDC\uCE59, \uCEE4\uBC0B \uBA54\uC2DC\uC9C0, PR \uD504\uB85C\uC138\uC2A4 \uC790\uB3D9 \uC801\uC6A9"',
@@ -1927,8 +2070,8 @@ async function provisionGitHub(ctx) {
1927
2070
  ].join("\n") + "\n");
1928
2071
  }
1929
2072
  const gitignorePath = join4(ctx.cwd, ".gitignore");
1930
- if (!await fs5.pathExists(gitignorePath)) {
1931
- await fs5.writeFile(gitignorePath, [
2073
+ if (!await fs7.pathExists(gitignorePath)) {
2074
+ await fs7.writeFile(gitignorePath, [
1932
2075
  "# Dependencies",
1933
2076
  "node_modules/",
1934
2077
  "",
@@ -1974,8 +2117,8 @@ async function provisionGitHub(ctx) {
1974
2117
  }
1975
2118
  async function provisionVercel(ctx) {
1976
2119
  const vercelJson = join4(ctx.cwd, "vercel.json");
1977
- if (!await fs5.pathExists(vercelJson)) {
1978
- await fs5.writeJson(vercelJson, {
2120
+ if (!await fs7.pathExists(vercelJson)) {
2121
+ await fs7.writeJson(vercelJson, {
1979
2122
  version: 2,
1980
2123
  name: ctx.projectName,
1981
2124
  builds: [{ src: "src/**", use: "@vercel/static" }]
@@ -1984,19 +2127,19 @@ async function provisionVercel(ctx) {
1984
2127
  }
1985
2128
  async function provisionSupabase(ctx) {
1986
2129
  const supabaseDir = join4(ctx.cwd, "supabase");
1987
- await fs5.ensureDir(supabaseDir);
2130
+ await fs7.ensureDir(supabaseDir);
1988
2131
  const configToml = join4(supabaseDir, "config.toml");
1989
- if (!await fs5.pathExists(configToml)) {
1990
- await fs5.writeFile(configToml, '[api]\nschemas = ["public"]\n[auth]\nsite_url = "http://localhost:3000"\n');
2132
+ if (!await fs7.pathExists(configToml)) {
2133
+ await fs7.writeFile(configToml, '[api]\nschemas = ["public"]\n[auth]\nsite_url = "http://localhost:3000"\n');
1991
2134
  }
1992
2135
  ctx.envEntries["NEXT_PUBLIC_SUPABASE_URL"] = "YOUR_SUPABASE_URL";
1993
2136
  ctx.envEntries["NEXT_PUBLIC_SUPABASE_ANON_KEY"] = "YOUR_SUPABASE_ANON_KEY";
1994
2137
  }
1995
2138
  async function provisionOpenSpec(ctx) {
1996
- await fs5.ensureDir(join4(ctx.cwd, "docs"));
2139
+ await fs7.ensureDir(join4(ctx.cwd, "docs"));
1997
2140
  const openspecPath = join4(ctx.cwd, "docs", "openspec.md");
1998
- if (!await fs5.pathExists(openspecPath)) {
1999
- await fs5.writeFile(openspecPath, [
2141
+ if (!await fs7.pathExists(openspecPath)) {
2142
+ await fs7.writeFile(openspecPath, [
2000
2143
  `# OpenSpec \u2014 ${ctx.projectName}`,
2001
2144
  "",
2002
2145
  "## 1. \uBAA9\uC801 (Purpose)",
@@ -2023,10 +2166,10 @@ async function provisionOpenSpec(ctx) {
2023
2166
  }
2024
2167
  }
2025
2168
  async function provisionOMC(ctx) {
2026
- await fs5.ensureDir(join4(ctx.cwd, ".pai"));
2169
+ await fs7.ensureDir(join4(ctx.cwd, ".pai"));
2027
2170
  const omcPath = join4(ctx.cwd, ".pai", "omc.md");
2028
- if (!await fs5.pathExists(omcPath)) {
2029
- await fs5.writeFile(omcPath, [
2171
+ if (!await fs7.pathExists(omcPath)) {
2172
+ await fs7.writeFile(omcPath, [
2030
2173
  `# OMC \u2014 Object Model Context (${ctx.projectName})`,
2031
2174
  "",
2032
2175
  "> AI\uAC00 \uC774 \uD504\uB85C\uC81D\uD2B8\uC758 \uB3C4\uBA54\uC778\uC744 \uC774\uD574\uD558\uAE30 \uC704\uD55C \uD575\uC2EC \uAC1D\uCCB4 \uBAA8\uB378",
@@ -2046,8 +2189,8 @@ async function provisionOMC(ctx) {
2046
2189
  }
2047
2190
  }
2048
2191
  async function provisionGstack(ctx) {
2049
- await fs5.ensureDir(join4(ctx.cwd, ".pai"));
2050
- await fs5.writeJson(join4(ctx.cwd, ".pai", "gstack.json"), {
2192
+ await fs7.ensureDir(join4(ctx.cwd, ".pai"));
2193
+ await fs7.writeJson(join4(ctx.cwd, ".pai", "gstack.json"), {
2051
2194
  version: "1.0",
2052
2195
  testRunner: "jest",
2053
2196
  coverageThreshold: { global: { lines: 80 } },
@@ -2055,10 +2198,10 @@ async function provisionGstack(ctx) {
2055
2198
  }, { spaces: 2 });
2056
2199
  }
2057
2200
  async function provisionRoboco(ctx) {
2058
- await fs5.ensureDir(join4(ctx.cwd, ".pai"));
2201
+ await fs7.ensureDir(join4(ctx.cwd, ".pai"));
2059
2202
  const robocoPath = join4(ctx.cwd, ".pai", "roboco.json");
2060
- if (await fs5.pathExists(robocoPath)) return;
2061
- await fs5.writeJson(robocoPath, {
2203
+ if (await fs7.pathExists(robocoPath)) return;
2204
+ await fs7.writeJson(robocoPath, {
2062
2205
  version: "1.0",
2063
2206
  checks: ["github", "vercel", "supabase", "openspec", "omc"],
2064
2207
  reportOutput: "AI_READINESS_REPORT.md",
@@ -2066,8 +2209,8 @@ async function provisionRoboco(ctx) {
2066
2209
  }, { spaces: 2 });
2067
2210
  }
2068
2211
  async function provisionHarness(ctx) {
2069
- await fs5.ensureDir(join4(ctx.cwd, ".pai"));
2070
- await fs5.writeJson(join4(ctx.cwd, ".pai", "harness.json"), {
2212
+ await fs7.ensureDir(join4(ctx.cwd, ".pai"));
2213
+ await fs7.writeJson(join4(ctx.cwd, ".pai", "harness.json"), {
2071
2214
  version: "1.0",
2072
2215
  specFile: "docs/openspec.md",
2073
2216
  checkOn: ["pre-commit", "ci"],
@@ -2125,20 +2268,20 @@ __export(claude_commands_exports, {
2125
2268
  upgradeClaudeCommands: () => upgradeClaudeCommands
2126
2269
  });
2127
2270
  import { join as join5 } from "path";
2128
- import fs6 from "fs-extra";
2271
+ import fs8 from "fs-extra";
2129
2272
  async function writeCommandFiles(cmdDir, entries, options) {
2130
- await fs6.ensureDir(cmdDir);
2273
+ await fs8.ensureDir(cmdDir);
2131
2274
  const written = [];
2132
2275
  const skipped = [];
2133
2276
  const errors = [];
2134
2277
  for (const [filename, content] of Object.entries(entries)) {
2135
2278
  const filePath = join5(cmdDir, filename);
2136
2279
  try {
2137
- if (options.skipIfExists && await fs6.pathExists(filePath)) {
2280
+ if (options.skipIfExists && await fs8.pathExists(filePath)) {
2138
2281
  skipped.push(filename);
2139
2282
  continue;
2140
2283
  }
2141
- await fs6.writeFile(filePath, content);
2284
+ await fs8.writeFile(filePath, content);
2142
2285
  written.push(filename);
2143
2286
  } catch (err) {
2144
2287
  const msg = err instanceof Error ? err.message : String(err);
@@ -2149,10 +2292,10 @@ async function writeCommandFiles(cmdDir, entries, options) {
2149
2292
  }
2150
2293
  async function provisionClaudeCommands(cwd) {
2151
2294
  const skillDir = join5(cwd, ".claude", "skills", "pai");
2152
- await fs6.ensureDir(skillDir);
2295
+ await fs8.ensureDir(skillDir);
2153
2296
  const skillPath = join5(skillDir, "SKILL.md");
2154
- if (!await fs6.pathExists(skillPath)) {
2155
- await fs6.writeFile(skillPath, SKILL_CONTENT);
2297
+ if (!await fs8.pathExists(skillPath)) {
2298
+ await fs8.writeFile(skillPath, SKILL_CONTENT);
2156
2299
  }
2157
2300
  const cmdDir = join5(cwd, ".claude", "commands", "pai");
2158
2301
  await writeCommandFiles(cmdDir, COMMANDS, { skipIfExists: true });
@@ -2164,9 +2307,9 @@ async function upgradeClaudeCommands(cwd) {
2164
2307
  commandErrors: []
2165
2308
  };
2166
2309
  const skillDir = join5(cwd, ".claude", "skills", "pai");
2167
- await fs6.ensureDir(skillDir);
2310
+ await fs8.ensureDir(skillDir);
2168
2311
  try {
2169
- await fs6.writeFile(join5(skillDir, "SKILL.md"), SKILL_CONTENT);
2312
+ await fs8.writeFile(join5(skillDir, "SKILL.md"), SKILL_CONTENT);
2170
2313
  result.skillUpdated = true;
2171
2314
  } catch (err) {
2172
2315
  const msg = err instanceof Error ? err.message : String(err);
@@ -2986,42 +3129,6 @@ description: "\uD50C\uB7EC\uADF8\uC778 \uCD94\uAC00 \uC124\uCE58 \u2014 Mockup\u
2986
3129
  }
2987
3130
  });
2988
3131
 
2989
- // src/core/config.ts
2990
- import path2 from "path";
2991
- import { createRequire } from "module";
2992
- import fs7 from "fs-extra";
2993
- async function loadConfig(cwd) {
2994
- const configPath = path2.join(cwd, CONFIG_DIR, CONFIG_FILE);
2995
- if (await fs7.pathExists(configPath)) {
2996
- return fs7.readJson(configPath);
2997
- }
2998
- return null;
2999
- }
3000
- async function saveConfig(cwd, config) {
3001
- const configDir = path2.join(cwd, CONFIG_DIR);
3002
- await fs7.ensureDir(configDir);
3003
- await fs7.writeJson(path2.join(configDir, CONFIG_FILE), config, { spaces: 2 });
3004
- }
3005
- function createDefaultConfig(projectName, mode) {
3006
- return {
3007
- version: pkg.version,
3008
- mode,
3009
- projectName,
3010
- installedAt: (/* @__PURE__ */ new Date()).toISOString(),
3011
- plugins: []
3012
- };
3013
- }
3014
- var require2, pkg, CONFIG_DIR, CONFIG_FILE;
3015
- var init_config = __esm({
3016
- "src/core/config.ts"() {
3017
- "use strict";
3018
- require2 = createRequire(import.meta.url);
3019
- pkg = require2("../../package.json");
3020
- CONFIG_DIR = ".pai";
3021
- CONFIG_FILE = "config.json";
3022
- }
3023
- });
3024
-
3025
3132
  // src/stages/environment/doctor.ts
3026
3133
  var doctor_exports = {};
3027
3134
  __export(doctor_exports, {
@@ -3029,7 +3136,7 @@ __export(doctor_exports, {
3029
3136
  });
3030
3137
  import { join as join6 } from "path";
3031
3138
  import { homedir } from "os";
3032
- import fs8 from "fs-extra";
3139
+ import fs9 from "fs-extra";
3033
3140
  async function runDoctor() {
3034
3141
  section("PAI Doctor \u2014 \uD658\uACBD \uC9C4\uB2E8");
3035
3142
  const checks = [];
@@ -3049,7 +3156,7 @@ async function runDoctor() {
3049
3156
  fix: claudeCheck.ok ? void 0 : "npm install -g @anthropic-ai/claude-code"
3050
3157
  });
3051
3158
  const globalConfigPath = join6(homedir(), ".pai", "config.json");
3052
- const hasGlobalConfig = await fs8.pathExists(globalConfigPath);
3159
+ const hasGlobalConfig = await fs9.pathExists(globalConfigPath);
3053
3160
  checks.push({
3054
3161
  label: "\uAE00\uB85C\uBC8C \uC124\uC815",
3055
3162
  ok: true,
@@ -3162,8 +3269,8 @@ var init_environment = __esm({
3162
3269
  return files;
3163
3270
  });
3164
3271
  artifacts.push(...generated);
3165
- const basePlugins = ["github", "openspec", "omc", "roboco"];
3166
- const pluginKeys = [...basePlugins, ...interview.extraTools];
3272
+ const basePlugins = ["github", "openspec", "roboco"];
3273
+ const pluginKeys = [.../* @__PURE__ */ new Set([...basePlugins, ...interview.extraTools])];
3167
3274
  const provCtx = {
3168
3275
  cwd: input.cwd,
3169
3276
  projectName: interview.projectName,
@@ -3257,11 +3364,14 @@ var detector_exports = {};
3257
3364
  __export(detector_exports, {
3258
3365
  PLUGIN_META: () => PLUGIN_META,
3259
3366
  PLUGIN_SIGNATURES: () => PLUGIN_SIGNATURES,
3367
+ getBasePluginsForMode: () => getBasePluginsForMode,
3260
3368
  getPluginsForMode: () => getPluginsForMode,
3369
+ nextMode: () => nextMode,
3370
+ pluginsAddedByPromotion: () => pluginsAddedByPromotion,
3261
3371
  scanProjectState: () => scanProjectState
3262
3372
  });
3263
- import path3 from "path";
3264
- import fs9 from "fs-extra";
3373
+ import path4 from "path";
3374
+ import fs10 from "fs-extra";
3265
3375
  async function scanProjectState(cwd) {
3266
3376
  const result = {
3267
3377
  isNewProject: true,
@@ -3271,19 +3381,19 @@ async function scanProjectState(cwd) {
3271
3381
  missingPlugins: [],
3272
3382
  details: {}
3273
3383
  };
3274
- const paiConfigPath = path3.join(cwd, ".pai", "config.json");
3275
- if (await fs9.pathExists(paiConfigPath)) {
3384
+ const paiConfigPath = path4.join(cwd, ".pai", "config.json");
3385
+ if (await fs10.pathExists(paiConfigPath)) {
3276
3386
  result.hasPaiConfig = true;
3277
3387
  try {
3278
- const config = await fs9.readJson(paiConfigPath);
3279
- result.projectMode = config.mode ?? null;
3388
+ const config = await fs10.readJson(paiConfigPath);
3389
+ result.projectMode = config.mode != null ? normalizeMode(config.mode) : null;
3280
3390
  } catch {
3281
3391
  }
3282
3392
  }
3283
3393
  for (const [key, signatures] of Object.entries(PLUGIN_SIGNATURES)) {
3284
3394
  const installed = await Promise.any(
3285
3395
  signatures.map(async (sig) => {
3286
- if (await fs9.pathExists(path3.join(cwd, sig))) return true;
3396
+ if (await fs10.pathExists(path4.join(cwd, sig))) return true;
3287
3397
  throw new Error("not found");
3288
3398
  })
3289
3399
  ).catch(() => false);
@@ -3294,17 +3404,30 @@ async function scanProjectState(cwd) {
3294
3404
  result.missingPlugins.push(key);
3295
3405
  }
3296
3406
  }
3297
- const hasAnyContent = result.installedPlugins.length > 0 || await fs9.pathExists(path3.join(cwd, "package.json")) || await fs9.pathExists(path3.join(cwd, "src")) || await fs9.pathExists(path3.join(cwd, "README.md"));
3407
+ const hasAnyContent = result.installedPlugins.length > 0 || await fs10.pathExists(path4.join(cwd, "package.json")) || await fs10.pathExists(path4.join(cwd, "src")) || await fs10.pathExists(path4.join(cwd, "README.md"));
3298
3408
  result.isNewProject = !hasAnyContent;
3299
3409
  return result;
3300
3410
  }
3301
3411
  function getPluginsForMode(mode) {
3302
3412
  return Object.entries(PLUGIN_META).filter(([, meta]) => meta.modes.includes(mode)).map(([key, meta]) => ({ key, ...meta }));
3303
3413
  }
3414
+ function getBasePluginsForMode(mode) {
3415
+ return Object.entries(PLUGIN_META).filter(([, meta]) => meta.modes.includes(mode) && meta.required).map(([key]) => key);
3416
+ }
3417
+ function nextMode(current) {
3418
+ if (current === "prototype") return "poc";
3419
+ if (current === "poc") return "production";
3420
+ return null;
3421
+ }
3422
+ function pluginsAddedByPromotion(from, to) {
3423
+ const fromSet = new Set(getPluginsForMode(from).map((p) => p.key));
3424
+ return getPluginsForMode(to).map((p) => p.key).filter((k) => !fromSet.has(k));
3425
+ }
3304
3426
  var PLUGIN_SIGNATURES, PLUGIN_META;
3305
3427
  var init_detector = __esm({
3306
3428
  "src/core/detector.ts"() {
3307
3429
  "use strict";
3430
+ init_config();
3308
3431
  PLUGIN_SIGNATURES = {
3309
3432
  github: [".git", ".github"],
3310
3433
  vercel: [".vercel", "vercel.json"],
@@ -3319,32 +3442,32 @@ var init_detector = __esm({
3319
3442
  github: {
3320
3443
  label: "GitHub \uB808\uD3EC & \uD3F4\uB354 \uAD6C\uC870",
3321
3444
  description: "\uB808\uD3EC \uCD08\uAE30\uD654, .gitignore, \uAE30\uBCF8 \uBE0C\uB79C\uCE58 \uC124\uC815",
3322
- modes: ["mockup", "production"],
3445
+ modes: ["prototype", "poc", "production"],
3323
3446
  required: true
3324
3447
  },
3325
- vercel: {
3326
- label: "Vercel \uBC30\uD3EC \uC5F0\uB3D9",
3327
- description: "\uC790\uB3D9 \uBC30\uD3EC \uD30C\uC774\uD504\uB77C\uC778 \uBC0F Preview URL \uC124\uC815",
3328
- modes: ["mockup", "production"],
3329
- required: false
3330
- },
3331
- supabase: {
3332
- label: "Supabase (DB & Auth)",
3333
- description: "\uB370\uC774\uD130\uBCA0\uC774\uC2A4, \uC778\uC99D, API \uD0A4 \uC790\uB3D9 \uC5F0\uB3D9",
3334
- modes: ["production"],
3335
- required: false
3336
- },
3337
3448
  openspec: {
3338
3449
  label: "OpenSpec (PRD \uC124\uACC4)",
3339
3450
  description: "AI \uAE30\uBC18 PRD \uC0DD\uC131 \uBC0F \uC2A4\uD399 \uBB38\uC11C\uD654",
3340
- modes: ["mockup", "production"],
3451
+ modes: ["prototype", "poc", "production"],
3341
3452
  required: true
3342
3453
  },
3454
+ roboco: {
3455
+ label: "roboco (AI \uC9C4\uB2E8)",
3456
+ description: "\uC124\uCE58 \uC0C1\uD0DC \uD3C9\uAC00 \uBC0F AI \uC900\uBE44\uB3C4 \uB9AC\uD3EC\uD2B8 \uC0DD\uC131",
3457
+ modes: ["prototype", "poc", "production"],
3458
+ required: false
3459
+ },
3343
3460
  omc: {
3344
3461
  label: "OMC (Object Model Context)",
3345
3462
  description: "\uAC1D\uCCB4 \uBAA8\uB378 \uCEE8\uD14D\uC2A4\uD2B8 \u2014 AI\uAC00 \uB3C4\uBA54\uC778\uC744 \uC774\uD574\uD558\uB294 \uAD6C\uC870",
3346
- modes: ["mockup", "production"],
3347
- required: true
3463
+ modes: ["poc", "production"],
3464
+ required: false
3465
+ },
3466
+ vercel: {
3467
+ label: "Vercel \uBC30\uD3EC \uC5F0\uB3D9",
3468
+ description: "\uC790\uB3D9 \uBC30\uD3EC \uD30C\uC774\uD504\uB77C\uC778 \uBC0F Preview URL \uC124\uC815",
3469
+ modes: ["poc", "production"],
3470
+ required: false
3348
3471
  },
3349
3472
  gstack: {
3350
3473
  label: "gstack (QA / \uD488\uC9C8\uAD00\uB9AC)",
@@ -3352,17 +3475,17 @@ var init_detector = __esm({
3352
3475
  modes: ["production"],
3353
3476
  required: false
3354
3477
  },
3355
- roboco: {
3356
- label: "roboco (AI \uC9C4\uB2E8)",
3357
- description: "\uC124\uCE58 \uC0C1\uD0DC \uD3C9\uAC00 \uBC0F AI \uC900\uBE44\uB3C4 \uB9AC\uD3EC\uD2B8 \uC0DD\uC131",
3358
- modes: ["mockup", "production"],
3359
- required: false
3360
- },
3361
3478
  harness: {
3362
3479
  label: "Harness Engineering (\uAC80\uC99D \uC790\uB3D9\uD654)",
3363
3480
  description: "\uC124\uACC4(OpenSpec)\uC640 \uAD6C\uD604 \uC77C\uCE58 \uC5EC\uBD80 \uC790\uB3D9 \uCCB4\uD06C",
3364
3481
  modes: ["production"],
3365
3482
  required: false
3483
+ },
3484
+ supabase: {
3485
+ label: "Supabase (DB & Auth)",
3486
+ description: "\uB370\uC774\uD130\uBCA0\uC774\uC2A4, \uC778\uC99D, API \uD0A4 \uC790\uB3D9 \uC5F0\uB3D9",
3487
+ modes: ["production"],
3488
+ required: false
3366
3489
  }
3367
3490
  };
3368
3491
  }
@@ -3425,7 +3548,7 @@ __export(analyzer_exports2, {
3425
3548
  analyzeRepository: () => analyzeRepository
3426
3549
  });
3427
3550
  import { join as join7 } from "path";
3428
- import fs10 from "fs-extra";
3551
+ import fs11 from "fs-extra";
3429
3552
  async function analyzeRepository(repoPath) {
3430
3553
  try {
3431
3554
  return await aiAnalysis(repoPath);
@@ -3486,14 +3609,14 @@ async function checkTestCoverage(repoPath) {
3486
3609
  ".nycrc"
3487
3610
  ];
3488
3611
  for (const f of testConfigs) {
3489
- const found = await fs10.pathExists(join7(repoPath, f));
3612
+ const found = await fs11.pathExists(join7(repoPath, f));
3490
3613
  findings.push({ item: f, found, details: found ? "\uC874\uC7AC" : "\uC5C6\uC74C" });
3491
3614
  if (found) score += 20;
3492
3615
  }
3493
3616
  const testDirs = ["tests", "test", "__tests__", "spec"];
3494
3617
  let hasTestDir = false;
3495
3618
  for (const d of testDirs) {
3496
- if (await fs10.pathExists(join7(repoPath, d))) {
3619
+ if (await fs11.pathExists(join7(repoPath, d))) {
3497
3620
  findings.push({ item: d, found: true, details: "\uD14C\uC2A4\uD2B8 \uB514\uB809\uD1A0\uB9AC \uC874\uC7AC" });
3498
3621
  hasTestDir = true;
3499
3622
  score += 30;
@@ -3516,8 +3639,8 @@ async function checkCiCd(repoPath) {
3516
3639
  { path: "Jenkinsfile", label: "Jenkins" },
3517
3640
  { path: ".circleci", label: "CircleCI" }
3518
3641
  ];
3519
- for (const { path: path5, label } of ciConfigs) {
3520
- const found = await fs10.pathExists(join7(repoPath, path5));
3642
+ for (const { path: path6, label } of ciConfigs) {
3643
+ const found = await fs11.pathExists(join7(repoPath, path6));
3521
3644
  findings.push({ item: label, found, details: found ? "\uC874\uC7AC" : "\uC5C6\uC74C" });
3522
3645
  if (found) score += 40;
3523
3646
  }
@@ -3535,8 +3658,8 @@ async function checkHooks(repoPath) {
3535
3658
  { path: "commitlint.config.js", label: "commitlint" },
3536
3659
  { path: ".claude/settings.json", label: "Claude Code settings" }
3537
3660
  ];
3538
- for (const { path: path5, label } of hookConfigs) {
3539
- const found = await fs10.pathExists(join7(repoPath, path5));
3661
+ for (const { path: path6, label } of hookConfigs) {
3662
+ const found = await fs11.pathExists(join7(repoPath, path6));
3540
3663
  findings.push({ item: label, found, details: found ? "\uC874\uC7AC" : "\uC5C6\uC74C" });
3541
3664
  if (found) score += 20;
3542
3665
  }
@@ -3553,8 +3676,8 @@ async function checkRepoStructure(repoPath) {
3553
3676
  { path: ".env.example", label: "\uD658\uACBD\uBCC0\uC218 \uC608\uC2DC" },
3554
3677
  { path: ".gitignore", label: ".gitignore" }
3555
3678
  ];
3556
- for (const { path: path5, label } of structureChecks) {
3557
- const found = await fs10.pathExists(join7(repoPath, path5));
3679
+ for (const { path: path6, label } of structureChecks) {
3680
+ const found = await fs11.pathExists(join7(repoPath, path6));
3558
3681
  findings.push({ item: label, found, details: found ? "\uC874\uC7AC" : "\uC5C6\uC74C" });
3559
3682
  if (found) score += 25;
3560
3683
  }
@@ -3570,8 +3693,8 @@ async function checkDocumentation(repoPath) {
3570
3693
  { path: "docs", label: "docs/ \uB514\uB809\uD1A0\uB9AC", points: 25 },
3571
3694
  { path: "docs/openspec.md", label: "OpenSpec PRD", points: 25 }
3572
3695
  ];
3573
- for (const { path: path5, label, points } of docChecks) {
3574
- const found = await fs10.pathExists(join7(repoPath, path5));
3696
+ for (const { path: path6, label, points } of docChecks) {
3697
+ const found = await fs11.pathExists(join7(repoPath, path6));
3575
3698
  findings.push({ item: label, found, details: found ? "\uC874\uC7AC" : "\uC5C6\uC74C" });
3576
3699
  if (found) score += points;
3577
3700
  }
@@ -3589,8 +3712,8 @@ async function checkHarnessEngineering(repoPath) {
3589
3712
  { path: ".claude/commands", label: ".claude/commands/", points: 10 },
3590
3713
  { path: ".pai/config.json", label: "PAI config", points: 10 }
3591
3714
  ];
3592
- for (const { path: path5, label, points } of harnessChecks) {
3593
- const found = await fs10.pathExists(join7(repoPath, path5));
3715
+ for (const { path: path6, label, points } of harnessChecks) {
3716
+ const found = await fs11.pathExists(join7(repoPath, path6));
3594
3717
  findings.push({ item: label, found, details: found ? "\uC874\uC7AC" : "\uC5C6\uC74C" });
3595
3718
  if (found) score += points;
3596
3719
  }
@@ -3975,54 +4098,54 @@ __export(shell_cd_exports, {
3975
4098
  });
3976
4099
  import { join as join8 } from "path";
3977
4100
  import { homedir as homedir2 } from "os";
3978
- import fs11 from "fs-extra";
4101
+ import fs12 from "fs-extra";
3979
4102
  async function requestCdAfter(targetDir) {
3980
- await fs11.ensureDir(PAI_DIR);
3981
- await fs11.writeFile(CD_FILE, targetDir);
4103
+ await fs12.ensureDir(PAI_DIR);
4104
+ await fs12.writeFile(CD_FILE, targetDir);
3982
4105
  }
3983
4106
  async function installShellHelper() {
3984
- await fs11.ensureDir(PAI_DIR);
4107
+ await fs12.ensureDir(PAI_DIR);
3985
4108
  if (isWindows) {
3986
4109
  return installPowerShellHelper();
3987
4110
  }
3988
4111
  return installBashHelper();
3989
4112
  }
3990
4113
  async function installBashHelper() {
3991
- await fs11.writeFile(HELPER_FILE_SH, BASH_HELPER);
4114
+ await fs12.writeFile(HELPER_FILE_SH, BASH_HELPER);
3992
4115
  const rcFile = getShellRcPath();
3993
4116
  const sourceLine = 'source "$HOME/.pai/shell-helper.sh"';
3994
- if (await fs11.pathExists(rcFile)) {
3995
- const content = await fs11.readFile(rcFile, "utf8");
4117
+ if (await fs12.pathExists(rcFile)) {
4118
+ const content = await fs12.readFile(rcFile, "utf8");
3996
4119
  if (content.includes("shell-helper.sh")) {
3997
4120
  return true;
3998
4121
  }
3999
- await fs11.appendFile(rcFile, `
4122
+ await fs12.appendFile(rcFile, `
4000
4123
  # PAI \u2014 \uC790\uB3D9 \uB514\uB809\uD1A0\uB9AC \uC774\uB3D9
4001
4124
  ${sourceLine}
4002
4125
  `);
4003
4126
  return false;
4004
4127
  }
4005
- await fs11.writeFile(rcFile, `${sourceLine}
4128
+ await fs12.writeFile(rcFile, `${sourceLine}
4006
4129
  `);
4007
4130
  return false;
4008
4131
  }
4009
4132
  async function installPowerShellHelper() {
4010
- await fs11.writeFile(HELPER_FILE_PS1, POWERSHELL_HELPER);
4133
+ await fs12.writeFile(HELPER_FILE_PS1, POWERSHELL_HELPER);
4011
4134
  const rcFile = getShellRcPath();
4012
4135
  const sourceLine = '. "$env:USERPROFILE\\.pai\\shell-helper.ps1"';
4013
- await fs11.ensureDir(join8(rcFile, ".."));
4014
- if (await fs11.pathExists(rcFile)) {
4015
- const content = await fs11.readFile(rcFile, "utf8");
4136
+ await fs12.ensureDir(join8(rcFile, ".."));
4137
+ if (await fs12.pathExists(rcFile)) {
4138
+ const content = await fs12.readFile(rcFile, "utf8");
4016
4139
  if (content.includes("shell-helper.ps1")) {
4017
4140
  return true;
4018
4141
  }
4019
- await fs11.appendFile(rcFile, `
4142
+ await fs12.appendFile(rcFile, `
4020
4143
  # PAI \u2014 \uC790\uB3D9 \uB514\uB809\uD1A0\uB9AC \uC774\uB3D9
4021
4144
  ${sourceLine}
4022
4145
  `);
4023
4146
  return false;
4024
4147
  }
4025
- await fs11.writeFile(rcFile, `${sourceLine}
4148
+ await fs12.writeFile(rcFile, `${sourceLine}
4026
4149
  `);
4027
4150
  return false;
4028
4151
  }
@@ -4085,10 +4208,10 @@ __export(claude_settings_exports, {
4085
4208
  mergeOmcIntoSettings: () => mergeOmcIntoSettings
4086
4209
  });
4087
4210
  import os2 from "os";
4088
- import path4 from "path";
4089
- import fs12 from "fs-extra";
4211
+ import path5 from "path";
4212
+ import fs13 from "fs-extra";
4090
4213
  function getClaudeSettingsPath(homeDir = os2.homedir()) {
4091
- return path4.join(homeDir, ".claude", "settings.json");
4214
+ return path5.join(homeDir, ".claude", "settings.json");
4092
4215
  }
4093
4216
  function parseJsonWithBom(raw) {
4094
4217
  const stripped = raw.charCodeAt(0) === 65279 ? raw.slice(1) : raw;
@@ -4103,13 +4226,13 @@ async function enableOmcPlugin(options = {}) {
4103
4226
  const pluginId = options.pluginId ?? DEFAULT_PLUGIN_ID;
4104
4227
  const wantBackup = options.backup ?? true;
4105
4228
  const settingsPath = getClaudeSettingsPath();
4106
- await fs12.ensureDir(path4.dirname(settingsPath));
4107
- if (!await fs12.pathExists(settingsPath)) {
4229
+ await fs13.ensureDir(path5.dirname(settingsPath));
4230
+ if (!await fs13.pathExists(settingsPath)) {
4108
4231
  const skeleton = buildSkeleton(marketplaceId, marketplaceUrl, pluginId);
4109
- await fs12.writeFile(settingsPath, JSON.stringify(skeleton, null, 2) + "\n", "utf8");
4232
+ await fs13.writeFile(settingsPath, JSON.stringify(skeleton, null, 2) + "\n", "utf8");
4110
4233
  return { action: "created", settingsPath };
4111
4234
  }
4112
- const raw = await fs12.readFile(settingsPath, "utf8");
4235
+ const raw = await fs13.readFile(settingsPath, "utf8");
4113
4236
  let parsed;
4114
4237
  try {
4115
4238
  const value = parseJsonWithBom(raw);
@@ -4119,7 +4242,7 @@ async function enableOmcPlugin(options = {}) {
4119
4242
  parsed = value;
4120
4243
  } catch (err) {
4121
4244
  const backupPath2 = `${settingsPath}.backup-${timestampSuffix()}`;
4122
- await fs12.copy(settingsPath, backupPath2);
4245
+ await fs13.copy(settingsPath, backupPath2);
4123
4246
  throw new ClaudeSettingsError(
4124
4247
  `settings.json \uD30C\uC2F1 \uC2E4\uD328: ${err.message}. \uBC31\uC5C5: ${backupPath2}`,
4125
4248
  backupPath2
@@ -4131,10 +4254,10 @@ async function enableOmcPlugin(options = {}) {
4131
4254
  let backupPath;
4132
4255
  if (wantBackup) {
4133
4256
  backupPath = `${settingsPath}.backup-${timestampSuffix()}`;
4134
- await fs12.copy(settingsPath, backupPath);
4257
+ await fs13.copy(settingsPath, backupPath);
4135
4258
  }
4136
4259
  const merged = mergeOmcIntoSettings(parsed, marketplaceId, marketplaceUrl, pluginId);
4137
- await fs12.writeFile(settingsPath, JSON.stringify(merged, null, 2) + "\n", "utf8");
4260
+ await fs13.writeFile(settingsPath, JSON.stringify(merged, null, 2) + "\n", "utf8");
4138
4261
  return { action: "added", settingsPath, backupPath };
4139
4262
  }
4140
4263
  function buildSkeleton(marketplaceId, marketplaceUrl, pluginId) {
@@ -4276,7 +4399,7 @@ __export(evaluate_cmd_exports, {
4276
4399
  evaluateCommand: () => evaluateCommand
4277
4400
  });
4278
4401
  import { join as join10, basename } from "path";
4279
- import fs13 from "fs-extra";
4402
+ import fs14 from "fs-extra";
4280
4403
  async function evaluateCommand(cwd, options) {
4281
4404
  const useCache = options.cache !== false;
4282
4405
  let llmOutput = useCache ? getCachedResult(cwd) : null;
@@ -4298,15 +4421,15 @@ async function evaluateCommand(cwd, options) {
4298
4421
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4299
4422
  const reportDir = join10(cwd, "docs", "p-reports");
4300
4423
  const reportPath = join10(reportDir, `${today}.md`);
4301
- await fs13.ensureDir(reportDir);
4424
+ await fs14.ensureDir(reportDir);
4302
4425
  const detailedReport = buildDetailedReport(result, projectName);
4303
- await fs13.writeFile(reportPath, detailedReport, "utf8");
4426
+ await fs14.writeFile(reportPath, detailedReport, "utf8");
4304
4427
  console.log("");
4305
4428
  success(`\uB9AC\uD3EC\uD2B8 \uC800\uC7A5: docs/p-reports/${today}.md`);
4306
4429
  console.log("");
4307
4430
  console.log(detailedReport);
4308
4431
  if (options.output) {
4309
- await fs13.writeFile(options.output, detailedReport, "utf8");
4432
+ await fs14.writeFile(options.output, detailedReport, "utf8");
4310
4433
  success(`\uCD94\uAC00 \uC800\uC7A5: ${options.output}`);
4311
4434
  }
4312
4435
  if (options.failUnder && result.totalScore < options.failUnder) {
@@ -4336,52 +4459,91 @@ __export(env_cmd_exports, {
4336
4459
  async function envSetupCommand(cwd) {
4337
4460
  const { default: inquirer } = await import("inquirer");
4338
4461
  const { basename: basename5 } = await import("path");
4339
- section("\uD658\uACBD \uC124\uC815");
4462
+ section("\uD50C\uB7EC\uADF8\uC778 \uCD94\uAC00 \xB7 \uBAA8\uB4DC \uC2B9\uACA9");
4340
4463
  const state = await scanProjectState(cwd);
4341
- const allPlugins = Object.entries(PLUGIN_META).map(([key, meta]) => ({
4342
- key,
4343
- label: meta.label,
4344
- installed: state.details[key]?.installed ?? false,
4345
- required: meta.required
4346
- }));
4347
- const missing = allPlugins.filter((p) => !p.installed);
4348
- if (missing.length === 0) {
4349
- success("\uBAA8\uB4E0 \uD50C\uB7EC\uADF8\uC778\uC774 \uC774\uBBF8 \uC124\uCE58\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4!");
4350
- return;
4464
+ const existingConfig = await loadConfig(cwd);
4465
+ const currentMode = state.projectMode ?? existingConfig?.mode ?? "prototype";
4466
+ const upgradeTarget = nextMode(currentMode);
4467
+ let promotedMode = null;
4468
+ const autoPluginsFromPromotion = [];
4469
+ if (upgradeTarget) {
4470
+ const addedPlugins = pluginsAddedByPromotion(currentMode, upgradeTarget);
4471
+ const notYetInstalled = addedPlugins.filter((k) => !(state.details[k]?.installed ?? false));
4472
+ console.log("");
4473
+ console.log(colors.dim(` \uD604\uC7AC \uBAA8\uB4DC: ${colors.accent(currentMode)}`));
4474
+ console.log(colors.dim(` \uB2E4\uC74C \uB2E8\uACC4: ${colors.accent(upgradeTarget)}`));
4475
+ if (notYetInstalled.length > 0) {
4476
+ console.log(colors.dim(` \uC2B9\uACA9 \uC2DC \uCD94\uAC00\uB418\uB294 \uD50C\uB7EC\uADF8\uC778: ${notYetInstalled.join(", ")}`));
4477
+ }
4478
+ console.log("");
4479
+ const { promote } = await inquirer.prompt([{
4480
+ type: "confirm",
4481
+ name: "promote",
4482
+ message: `${upgradeTarget} \uC218\uC900\uC73C\uB85C \uC2B9\uACA9\uD558\uC2DC\uACA0\uC5B4\uC694?`,
4483
+ default: false
4484
+ }]);
4485
+ if (promote) {
4486
+ promotedMode = upgradeTarget;
4487
+ autoPluginsFromPromotion.push(...notYetInstalled);
4488
+ }
4489
+ } else {
4490
+ info(`\uC774\uBBF8 \uCD5C\uC0C1\uC704 \uBAA8\uB4DC(${currentMode})\uC785\uB2C8\uB2E4.`);
4351
4491
  }
4352
- const { selectedKeys } = await inquirer.prompt([{
4353
- type: "checkbox",
4354
- name: "selectedKeys",
4355
- message: "\uC124\uCE58\uD560 \uD50C\uB7EC\uADF8\uC778\uC744 \uC120\uD0DD\uD558\uC138\uC694:",
4356
- choices: missing.map((p) => ({
4357
- name: `${p.label} ${p.required ? "[\uD544\uC218]" : "[\uC120\uD0DD]"}`,
4358
- value: p.key,
4359
- checked: p.required
4360
- }))
4361
- }]);
4362
- if (selectedKeys.length === 0) {
4492
+ const targetMode = promotedMode ?? currentMode;
4493
+ const availableForMode = getPluginsForMode(targetMode).map((p) => p.key);
4494
+ const remaining = availableForMode.filter(
4495
+ (k) => !(state.details[k]?.installed ?? false) && !autoPluginsFromPromotion.includes(k)
4496
+ );
4497
+ let selectedKeys = [];
4498
+ if (remaining.length > 0) {
4499
+ console.log("");
4500
+ const choices = remaining.map((k) => {
4501
+ const meta = PLUGIN_META[k];
4502
+ const tag = meta?.required ? "[\uD544\uC218]" : "[\uC120\uD0DD]";
4503
+ return {
4504
+ name: `${meta?.label ?? k} ${colors.dim(tag)}`,
4505
+ value: k,
4506
+ checked: meta?.required ?? false
4507
+ };
4508
+ });
4509
+ const answer = await inquirer.prompt([{
4510
+ type: "checkbox",
4511
+ name: "selectedKeys",
4512
+ message: autoPluginsFromPromotion.length > 0 ? "\uCD94\uAC00\uB85C \uC124\uCE58\uD560 \uD50C\uB7EC\uADF8\uC778 (\uC120\uD0DD):" : "\uC124\uCE58\uD560 \uD50C\uB7EC\uADF8\uC778\uC744 \uC120\uD0DD\uD558\uC138\uC694:",
4513
+ choices
4514
+ }]);
4515
+ selectedKeys = answer.selectedKeys;
4516
+ }
4517
+ const allToInstall = [.../* @__PURE__ */ new Set([...autoPluginsFromPromotion, ...selectedKeys])];
4518
+ if (allToInstall.length === 0) {
4363
4519
  info("\uC120\uD0DD\uB41C \uD50C\uB7EC\uADF8\uC778\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
4520
+ if (promotedMode) {
4521
+ const config2 = existingConfig ?? createDefaultConfig(basename5(cwd), promotedMode);
4522
+ config2.mode = promotedMode;
4523
+ await saveConfig(cwd, config2);
4524
+ success(`\uBAA8\uB4DC: ${currentMode} \u2192 ${promotedMode}`);
4525
+ }
4364
4526
  return;
4365
4527
  }
4366
- const { projectName } = await inquirer.prompt([{
4367
- type: "input",
4368
- name: "projectName",
4369
- message: "\uD504\uB85C\uC81D\uD2B8\uBA85:",
4370
- default: basename5(cwd)
4371
- }]);
4528
+ const projectName = existingConfig?.projectName ?? basename5(cwd);
4372
4529
  const ctx = {
4373
4530
  cwd,
4374
4531
  projectName,
4375
- mode: state.projectMode ?? "production",
4532
+ mode: targetMode,
4376
4533
  envEntries: {}
4377
4534
  };
4378
4535
  section("\uD50C\uB7EC\uADF8\uC778 \uC124\uCE58 \uC911...");
4379
- await runProvisioners(selectedKeys, ctx);
4380
- const config = await loadConfig(cwd) ?? createDefaultConfig(projectName, ctx.mode);
4381
- config.plugins = [.../* @__PURE__ */ new Set([...config.plugins, ...selectedKeys])];
4536
+ await runProvisioners(allToInstall, ctx);
4537
+ const config = existingConfig ?? createDefaultConfig(projectName, targetMode);
4538
+ config.mode = targetMode;
4539
+ config.plugins = [.../* @__PURE__ */ new Set([...config.plugins, ...allToInstall])];
4382
4540
  await saveConfig(cwd, config);
4383
- success("\uC124\uCE58 \uC644\uB8CC!");
4384
- info("docs/openspec.md\uB97C \uC5F4\uC5B4 PRD \uC791\uC131\uC744 \uC2DC\uC791\uD558\uC138\uC694!");
4541
+ success("\uC124\uCE58 \uC644\uB8CC");
4542
+ if (promotedMode) {
4543
+ success(`\uBAA8\uB4DC: ${currentMode} \u2192 ${promotedMode}`);
4544
+ }
4545
+ console.log("");
4546
+ hint("\uB2E4\uC74C \uB2E8\uACC4: /pai status \uB610\uB294 /pai grade");
4385
4547
  }
4386
4548
  async function envDoctorCommand() {
4387
4549
  await runDoctor();
@@ -4415,6 +4577,10 @@ async function envStatusCommand(cwd) {
4415
4577
  if (state.projectMode) {
4416
4578
  console.log("");
4417
4579
  info(`\uBAA8\uB4DC: ${state.projectMode}`);
4580
+ const next = nextMode(state.projectMode);
4581
+ if (next) {
4582
+ hint(`\uC2B9\uACA9 \uACBD\uB85C: ${state.projectMode} \u2192 ${next} (pai add \uC5D0\uC11C \uC2B9\uACA9 \uAC00\uB2A5)`);
4583
+ }
4418
4584
  }
4419
4585
  }
4420
4586
  var init_env_cmd = __esm({
@@ -4426,6 +4592,7 @@ var init_env_cmd = __esm({
4426
4592
  init_registry();
4427
4593
  init_doctor();
4428
4594
  init_analyzer();
4595
+ init_logger();
4429
4596
  }
4430
4597
  });
4431
4598
 
@@ -4435,7 +4602,7 @@ __export(init_cmd_exports, {
4435
4602
  initCommand: () => initCommand
4436
4603
  });
4437
4604
  import { join as join11, basename as basename2 } from "path";
4438
- import fs14 from "fs-extra";
4605
+ import fs15 from "fs-extra";
4439
4606
  async function initCommand(cwd, nameArg) {
4440
4607
  printBanner();
4441
4608
  const { isWindows: isWindows2, diagnoseWindowsEnv: diagnoseWindowsEnv2 } = await Promise.resolve().then(() => (init_platform(), platform_exports));
@@ -4494,10 +4661,10 @@ async function initCommand(cwd, nameArg) {
4494
4661
  printReport2(evalResult);
4495
4662
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4496
4663
  const reportDir = join11(cwd, "docs", "p-reports");
4497
- await fs14.ensureDir(reportDir);
4664
+ await fs15.ensureDir(reportDir);
4498
4665
  const legacyName = basename2(cwd);
4499
4666
  const detailedReport = buildDetailedReport3(evalResult, legacyName);
4500
- await fs14.writeFile(join11(reportDir, `${today}.md`), detailedReport, "utf8");
4667
+ await fs15.writeFile(join11(reportDir, `${today}.md`), detailedReport, "utf8");
4501
4668
  console.log("");
4502
4669
  success(`\uB9AC\uD3EC\uD2B8 \uC800\uC7A5: docs/p-reports/${today}.md`);
4503
4670
  } catch {
@@ -4543,7 +4710,7 @@ async function initCommand(cwd, nameArg) {
4543
4710
  projectName = answer.name.trim();
4544
4711
  }
4545
4712
  const projectDir = join11(cwd, projectName);
4546
- if (await fs14.pathExists(projectDir)) {
4713
+ if (await fs15.pathExists(projectDir)) {
4547
4714
  const existingConfig = await loadConfig(projectDir);
4548
4715
  if (existingConfig) {
4549
4716
  console.log("");
@@ -4565,7 +4732,7 @@ async function initCommand(cwd, nameArg) {
4565
4732
  return;
4566
4733
  }
4567
4734
  } else {
4568
- await fs14.ensureDir(projectDir);
4735
+ await fs15.ensureDir(projectDir);
4569
4736
  success(`${projectName}/ \uD3F4\uB354 \uC0DD\uC131`);
4570
4737
  }
4571
4738
  await setupInDirectory(projectDir, projectName);
@@ -4579,7 +4746,7 @@ async function setupInDirectory(projectDir, projectName) {
4579
4746
  console.log("");
4580
4747
  }
4581
4748
  step(2, 3, "\uD504\uB85C\uC81D\uD2B8 \uC124\uC815");
4582
- const config = createDefaultConfig(projectName, "mockup");
4749
+ const config = createDefaultConfig(projectName, "prototype");
4583
4750
  const input = {
4584
4751
  cwd: projectDir,
4585
4752
  config,
@@ -4646,7 +4813,7 @@ async function showCompletion(projectName, projectDir, extraTools, isCurrentDir)
4646
4813
  { label: "\uC2AC\uB798\uC2DC \uCEE4\uB9E8\uB4DC", path: ".claude/skills/pai/SKILL.md" }
4647
4814
  ];
4648
4815
  for (const check of checks) {
4649
- const exists = await fs14.pathExists(join11(projectDir, check.path));
4816
+ const exists = await fs15.pathExists(join11(projectDir, check.path));
4650
4817
  console.log(` ${exists ? colors.success("\u2713") : colors.err("\u2717")} ${check.label.padEnd(16)} ${colors.dim(check.path)}`);
4651
4818
  }
4652
4819
  console.log("");
@@ -4672,9 +4839,9 @@ async function showCompletion(projectName, projectDir, extraTools, isCurrentDir)
4672
4839
  await sleep2(500);
4673
4840
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4674
4841
  const reportDir = join11(projectDir, "docs", "p-reports");
4675
- await fs14.ensureDir(reportDir);
4842
+ await fs15.ensureDir(reportDir);
4676
4843
  const detailedReport = buildDetailedReport3(evalResult, projectName);
4677
- await fs14.writeFile(join11(reportDir, `${today}.md`), detailedReport, "utf8");
4844
+ await fs15.writeFile(join11(reportDir, `${today}.md`), detailedReport, "utf8");
4678
4845
  await sleep2(500);
4679
4846
  console.log("");
4680
4847
  success(`\uB9AC\uD3EC\uD2B8 \uC800\uC7A5: docs/p-reports/${today}.md`);
@@ -4702,7 +4869,7 @@ async function showCompletion(projectName, projectDir, extraTools, isCurrentDir)
4702
4869
  const shellRc = getShellRcPath2();
4703
4870
  let hasYoloAliasSet = false;
4704
4871
  try {
4705
- const rcContent = await fs14.readFile(shellRc, "utf8");
4872
+ const rcContent = await fs15.readFile(shellRc, "utf8");
4706
4873
  hasYoloAliasSet = checkYolo(rcContent);
4707
4874
  } catch {
4708
4875
  }
@@ -4723,10 +4890,10 @@ async function showCompletion(projectName, projectDir, extraTools, isCurrentDir)
4723
4890
  const { getYoloAliasLine: getYoloAliasLine2 } = await Promise.resolve().then(() => (init_platform(), platform_exports));
4724
4891
  const aliasLine = getYoloAliasLine2();
4725
4892
  try {
4726
- const rcContent = await fs14.readFile(shellRc, "utf8").catch(() => "");
4893
+ const rcContent = await fs15.readFile(shellRc, "utf8").catch(() => "");
4727
4894
  if (!rcContent.includes("claude-yolo")) {
4728
- await fs14.ensureDir(join11(shellRc, ".."));
4729
- await fs14.appendFile(shellRc, `
4895
+ await fs15.ensureDir(join11(shellRc, ".."));
4896
+ await fs15.appendFile(shellRc, `
4730
4897
  # PAI \u2014 claude-YOLO mode
4731
4898
  ${aliasLine}
4732
4899
  `);
@@ -4830,16 +4997,30 @@ async function handleExistingProject(cwd, state) {
4830
4997
  console.log(colors.dim(` \xB7 ${p.label} ${chalk8.gray("\uBBF8\uC124\uCE58")}`));
4831
4998
  }
4832
4999
  }
5000
+ const currentConfig = await loadConfig(cwd);
5001
+ if (currentConfig) {
5002
+ console.log("");
5003
+ console.log(colors.dim(` \uD604\uC7AC \uBAA8\uB4DC: ${colors.accent(currentConfig.mode)}`));
5004
+ }
4833
5005
  console.log("");
4834
5006
  const { action } = await inquirer.prompt([{
4835
5007
  type: "list",
4836
5008
  name: "action",
4837
- message: "\uC5B4\uB5BB\uAC8C \uC9C4\uD589\uD560\uAE4C\uC694?",
5009
+ message: "\uC5B4\uB5A4 \uC791\uC5C5\uC744 \uD560\uAE4C\uC694?",
4838
5010
  choices: [
4839
- { name: "\uD488\uC9C8 \uD3C9\uAC00", value: "evaluate" },
4840
- { name: "\uD50C\uB7EC\uADF8\uC778 \uCD94\uAC00", value: "install" },
4841
- { name: "\uD658\uACBD \uC9C4\uB2E8", value: "doctor" },
4842
- { name: chalk8.gray("\uC885\uB8CC"), value: "exit" }
5011
+ {
5012
+ name: `\u{1F4CA} AI \uAC1C\uBC1C \uC900\uBE44\uB3C4 \uD3C9\uAC00 ${colors.dim("(pai grade \u2014 6\uCE74\uD14C\uACE0\uB9AC \uC810\uC218)")}`,
5013
+ value: "evaluate"
5014
+ },
5015
+ {
5016
+ name: `\u2795 \uD50C\uB7EC\uADF8\uC778 \uCD94\uAC00\xB7\uBAA8\uB4DC \uC2B9\uACA9 ${colors.dim("(pai add \u2014 prototype \u2192 poc \u2192 production)")}`,
5017
+ value: "install"
5018
+ },
5019
+ {
5020
+ name: `\u{1FA7A} \uD658\uACBD \uC810\uAC80 ${colors.dim("(pai check \u2014 Node/Git/Claude/OMC)")}`,
5021
+ value: "doctor"
5022
+ },
5023
+ { name: chalk8.gray("\u{1F6AA} \uC885\uB8CC"), value: "exit" }
4843
5024
  ]
4844
5025
  }]);
4845
5026
  switch (action) {
@@ -4900,7 +5081,7 @@ async function installOrchestratorOnly(projectDir, projectName) {
4900
5081
  if (selectedPlugins.includes("gstack")) extraTools.push("gstack");
4901
5082
  if (selectedPlugins.includes("harness")) extraTools.push("harness");
4902
5083
  const autoInterview = {
4903
- mode: "mockup",
5084
+ mode: "prototype",
4904
5085
  projectName,
4905
5086
  authMethods: [],
4906
5087
  extraTools,
@@ -4925,8 +5106,8 @@ async function installOrchestratorOnly(projectDir, projectName) {
4925
5106
  const provCtx = {
4926
5107
  cwd: projectDir,
4927
5108
  projectName,
4928
- mode: "mockup",
4929
- envEntries: { PAI_PROJECT_NAME: projectName, PAI_MODE: "mockup" }
5109
+ mode: "prototype",
5110
+ envEntries: { PAI_PROJECT_NAME: projectName, PAI_MODE: "prototype" }
4930
5111
  };
4931
5112
  console.log("");
4932
5113
  await withSpinner2("\uD50C\uB7EC\uADF8\uC778 \uC124\uCE58 \uC911...", async () => {
@@ -4940,7 +5121,7 @@ async function installOrchestratorOnly(projectDir, projectName) {
4940
5121
  });
4941
5122
  console.log("");
4942
5123
  await withSpinner2("\uC124\uC815 \uC800\uC7A5 \uC911...", async () => {
4943
- const config = createDefaultConfig(projectName, "mockup");
5124
+ const config = createDefaultConfig(projectName, "prototype");
4944
5125
  config.plugins = allPluginKeys;
4945
5126
  await saveConfig(projectDir, config);
4946
5127
  await sleep2(300);
@@ -4957,8 +5138,8 @@ async function installOrchestratorOnly(projectDir, projectName) {
4957
5138
  printReport2(evalResult);
4958
5139
  const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
4959
5140
  const reportDir = join11(projectDir, "docs", "p-reports");
4960
- await fs14.ensureDir(reportDir);
4961
- await fs14.writeFile(join11(reportDir, `${today}.md`), buildDetailedReport3(evalResult, projectName), "utf8");
5141
+ await fs15.ensureDir(reportDir);
5142
+ await fs15.writeFile(join11(reportDir, `${today}.md`), buildDetailedReport3(evalResult, projectName), "utf8");
4962
5143
  console.log("");
4963
5144
  hint(`\uC0C1\uC138 \uB9AC\uD3EC\uD2B8: docs/p-reports/${today}.md`);
4964
5145
  } catch {
@@ -5008,7 +5189,7 @@ async function detectLegacyProject(cwd) {
5008
5189
  ".gitignore"
5009
5190
  ];
5010
5191
  for (const signal of signals) {
5011
- if (await fs14.pathExists(join11(cwd, signal))) return true;
5192
+ if (await fs15.pathExists(join11(cwd, signal))) return true;
5012
5193
  }
5013
5194
  return false;
5014
5195
  }
@@ -5100,16 +5281,16 @@ var init_help_cmd = __esm({
5100
5281
 
5101
5282
  // src/stages/design/openspec.ts
5102
5283
  import { join as join12 } from "path";
5103
- import fs15 from "fs-extra";
5284
+ import fs16 from "fs-extra";
5104
5285
  async function initOpenSpec(cwd, projectName) {
5105
5286
  const docsDir = join12(cwd, "docs");
5106
- await fs15.ensureDir(docsDir);
5287
+ await fs16.ensureDir(docsDir);
5107
5288
  const openspecPath = join12(docsDir, "openspec.md");
5108
- if (await fs15.pathExists(openspecPath)) {
5289
+ if (await fs16.pathExists(openspecPath)) {
5109
5290
  info("docs/openspec.md \uC774\uBBF8 \uC874\uC7AC \u2014 \uAC74\uB108\uB700");
5110
5291
  return;
5111
5292
  }
5112
- await fs15.writeFile(openspecPath, [
5293
+ await fs16.writeFile(openspecPath, [
5113
5294
  `# OpenSpec \u2014 ${projectName}`,
5114
5295
  "",
5115
5296
  "## 1. \uBAA9\uC801 (Purpose)",
@@ -5143,7 +5324,7 @@ async function validateOpenSpec(cwd) {
5143
5324
  ];
5144
5325
  let specPath = null;
5145
5326
  for (const p of candidates) {
5146
- if (await fs15.pathExists(p)) {
5327
+ if (await fs16.pathExists(p)) {
5147
5328
  specPath = p;
5148
5329
  break;
5149
5330
  }
@@ -5157,7 +5338,7 @@ async function validateOpenSpec(cwd) {
5157
5338
  warnings: ["openspec.md \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. `pai design init` \uC744 \uC2E4\uD589\uD558\uC138\uC694."]
5158
5339
  };
5159
5340
  }
5160
- const content = await fs15.readFile(specPath, "utf8");
5341
+ const content = await fs16.readFile(specPath, "utf8");
5161
5342
  const missing = [];
5162
5343
  let filled = 0;
5163
5344
  for (const section2 of REQUIRED_SECTIONS) {
@@ -5206,16 +5387,16 @@ var init_openspec = __esm({
5206
5387
 
5207
5388
  // src/stages/design/omc.ts
5208
5389
  import { join as join13 } from "path";
5209
- import fs16 from "fs-extra";
5390
+ import fs17 from "fs-extra";
5210
5391
  async function initOMC(cwd, projectName) {
5211
5392
  const paiDir = join13(cwd, ".pai");
5212
- await fs16.ensureDir(paiDir);
5393
+ await fs17.ensureDir(paiDir);
5213
5394
  const omcPath = join13(paiDir, "omc.md");
5214
- if (await fs16.pathExists(omcPath)) {
5395
+ if (await fs17.pathExists(omcPath)) {
5215
5396
  info(".pai/omc.md \uC774\uBBF8 \uC874\uC7AC \u2014 \uAC74\uB108\uB700");
5216
5397
  return;
5217
5398
  }
5218
- await fs16.writeFile(omcPath, [
5399
+ await fs17.writeFile(omcPath, [
5219
5400
  `# OMC \u2014 Object Model Context (${projectName})`,
5220
5401
  "",
5221
5402
  "> AI\uAC00 \uC774 \uD504\uB85C\uC81D\uD2B8\uC758 \uB3C4\uBA54\uC778\uC744 \uC774\uD574\uD558\uAE30 \uC704\uD55C \uD575\uC2EC \uAC1D\uCCB4 \uBAA8\uB378",
@@ -5298,14 +5479,14 @@ var init_design_cmd = __esm({
5298
5479
 
5299
5480
  // src/stages/validation/runner.ts
5300
5481
  import { join as join14 } from "path";
5301
- import fs17 from "fs-extra";
5482
+ import fs18 from "fs-extra";
5302
5483
  async function runTests(cwd) {
5303
5484
  const start = Date.now();
5304
5485
  const gstackPath = join14(cwd, ".pai", "gstack.json");
5305
5486
  let runner = "npm test";
5306
- if (await fs17.pathExists(gstackPath)) {
5487
+ if (await fs18.pathExists(gstackPath)) {
5307
5488
  try {
5308
- const config = await fs17.readJson(gstackPath);
5489
+ const config = await fs18.readJson(gstackPath);
5309
5490
  if (config.testRunner === "vitest") runner = "npx vitest run";
5310
5491
  else if (config.testRunner === "jest") runner = "npx jest";
5311
5492
  else if (config.testRunner === "mocha") runner = "npx mocha";
@@ -5313,10 +5494,10 @@ async function runTests(cwd) {
5313
5494
  }
5314
5495
  }
5315
5496
  const pkgPath = join14(cwd, "package.json");
5316
- if (await fs17.pathExists(pkgPath)) {
5497
+ if (await fs18.pathExists(pkgPath)) {
5317
5498
  try {
5318
- const pkg4 = await fs17.readJson(pkgPath);
5319
- if (!pkg4.scripts?.test || pkg4.scripts.test.includes("no test specified")) {
5499
+ const pkg5 = await fs18.readJson(pkgPath);
5500
+ if (!pkg5.scripts?.test || pkg5.scripts.test.includes("no test specified")) {
5320
5501
  return {
5321
5502
  runner,
5322
5503
  passed: false,
@@ -5358,15 +5539,15 @@ var init_runner = __esm({
5358
5539
 
5359
5540
  // src/stages/validation/harness.ts
5360
5541
  import { join as join15 } from "path";
5361
- import fs18 from "fs-extra";
5542
+ import fs19 from "fs-extra";
5362
5543
  async function runHarnessCheck(cwd) {
5363
5544
  const harnessPath = join15(cwd, ".pai", "harness.json");
5364
- if (!await fs18.pathExists(harnessPath)) {
5545
+ if (!await fs19.pathExists(harnessPath)) {
5365
5546
  return { enabled: false, specFile: null, rules: [], checks: [] };
5366
5547
  }
5367
5548
  let config;
5368
5549
  try {
5369
- config = await fs18.readJson(harnessPath);
5550
+ config = await fs19.readJson(harnessPath);
5370
5551
  } catch {
5371
5552
  return { enabled: false, specFile: null, rules: [], checks: [] };
5372
5553
  }
@@ -5374,8 +5555,8 @@ async function runHarnessCheck(cwd) {
5374
5555
  const rules = config.rules ?? [];
5375
5556
  const checks = [];
5376
5557
  if (rules.includes("spec-implementation-match")) {
5377
- const specExists = await fs18.pathExists(join15(cwd, specFile));
5378
- const srcExists = await fs18.pathExists(join15(cwd, "src"));
5558
+ const specExists = await fs19.pathExists(join15(cwd, specFile));
5559
+ const srcExists = await fs19.pathExists(join15(cwd, "src"));
5379
5560
  checks.push({
5380
5561
  rule: "spec-implementation-match",
5381
5562
  passed: specExists && srcExists,
@@ -5383,8 +5564,8 @@ async function runHarnessCheck(cwd) {
5383
5564
  });
5384
5565
  }
5385
5566
  if (rules.includes("api-contract-test")) {
5386
- const testDir = await fs18.pathExists(join15(cwd, "tests"));
5387
- const testDir2 = await fs18.pathExists(join15(cwd, "test"));
5567
+ const testDir = await fs19.pathExists(join15(cwd, "tests"));
5568
+ const testDir2 = await fs19.pathExists(join15(cwd, "test"));
5388
5569
  checks.push({
5389
5570
  rule: "api-contract-test",
5390
5571
  passed: testDir || testDir2,
@@ -5499,13 +5680,13 @@ var init_context = __esm({
5499
5680
 
5500
5681
  // src/stages/design/index.ts
5501
5682
  import { join as join16 } from "path";
5502
- import fs19 from "fs-extra";
5683
+ import fs20 from "fs-extra";
5503
5684
  async function autoInstallHarness(cwd) {
5504
5685
  const harnessPath = join16(cwd, ".pai", "harness.json");
5505
- if (await fs19.pathExists(harnessPath)) return;
5686
+ if (await fs20.pathExists(harnessPath)) return;
5506
5687
  await withSpinner("Harness Engineering \uC790\uB3D9 \uC124\uC815 \uC911...", async () => {
5507
- await fs19.ensureDir(join16(cwd, ".pai"));
5508
- await fs19.writeJson(harnessPath, {
5688
+ await fs20.ensureDir(join16(cwd, ".pai"));
5689
+ await fs20.writeJson(harnessPath, {
5509
5690
  version: "1.0",
5510
5691
  specFile: "docs/openspec.md",
5511
5692
  checkOn: ["pre-commit", "ci"],
@@ -5862,7 +6043,7 @@ __export(remove_cmd_exports, {
5862
6043
  removeCommand: () => removeCommand
5863
6044
  });
5864
6045
  import { basename as basename4, dirname } from "path";
5865
- import fs20 from "fs-extra";
6046
+ import fs21 from "fs-extra";
5866
6047
  async function removeCommand(cwd, options) {
5867
6048
  section("\uD504\uB85C\uC81D\uD2B8 \uC0AD\uC81C");
5868
6049
  const config = await loadConfig(cwd);
@@ -5880,7 +6061,7 @@ async function removeCommand(cwd, options) {
5880
6061
  console.log(colors.err(` ${folderName}/ \uD3F4\uB354 \uC804\uCCB4\uAC00 \uC0AD\uC81C\uB429\uB2C8\uB2E4.`));
5881
6062
  hint("\uC774 \uC791\uC5C5\uC740 \uB418\uB3CC\uB9B4 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
5882
6063
  console.log("");
5883
- const items = await fs20.readdir(cwd);
6064
+ const items = await fs21.readdir(cwd);
5884
6065
  const fileCount = items.filter((i) => !i.startsWith(".")).length;
5885
6066
  const hiddenCount = items.filter((i) => i.startsWith(".")).length;
5886
6067
  info(`\uD30C\uC77C/\uD3F4\uB354 ${fileCount}\uAC1C, \uC228\uAE40 \uD56D\uBAA9 ${hiddenCount}\uAC1C`);
@@ -5899,7 +6080,7 @@ async function removeCommand(cwd, options) {
5899
6080
  }
5900
6081
  process.chdir(parentDir);
5901
6082
  try {
5902
- await fs20.remove(cwd);
6083
+ await fs21.remove(cwd);
5903
6084
  console.log("");
5904
6085
  success(`${folderName}/ \uD504\uB85C\uC81D\uD2B8\uAC00 \uC0AD\uC81C\uB418\uC5C8\uC2B5\uB2C8\uB2E4.`);
5905
6086
  try {
@@ -5955,9 +6136,9 @@ var init_errors = __esm({
5955
6136
  recoverable;
5956
6137
  };
5957
6138
  ConfigNotFoundError = class extends PaiError {
5958
- constructor(path5) {
6139
+ constructor(path6) {
5959
6140
  super(
5960
- `.pai/config.json not found at ${path5}. Run 'pai init' first.`,
6141
+ `.pai/config.json not found at ${path6}. Run 'pai init' first.`,
5961
6142
  "CONFIG_NOT_FOUND",
5962
6143
  true
5963
6144
  );
@@ -5972,7 +6153,7 @@ var upgrade_cmd_exports = {};
5972
6153
  __export(upgrade_cmd_exports, {
5973
6154
  upgradeCommand: () => upgradeCommand
5974
6155
  });
5975
- import { createRequire as createRequire2 } from "module";
6156
+ import { createRequire as createRequire3 } from "module";
5976
6157
  import chalk5 from "chalk";
5977
6158
  function compareSemver(a, b) {
5978
6159
  const pa = a.split(".").map(Number);
@@ -5991,7 +6172,7 @@ async function upgradeCommand(cwd, options) {
5991
6172
  if (!config) {
5992
6173
  throw new ConfigNotFoundError(cwd);
5993
6174
  }
5994
- const currentVersion = pkg2.version;
6175
+ const currentVersion = pkg3.version;
5995
6176
  const configVersion = config.version;
5996
6177
  console.log("");
5997
6178
  console.log(` \uD604\uC7AC \uBC84\uC804: ${chalk5.gray(`v${configVersion}`)}`);
@@ -6033,7 +6214,7 @@ async function upgradeCommand(cwd, options) {
6033
6214
  success(`v${configVersion} \u2192 v${currentVersion} \uC5C5\uADF8\uB808\uC774\uB4DC \uC644\uB8CC!`);
6034
6215
  console.log("");
6035
6216
  }
6036
- var require3, pkg2;
6217
+ var require4, pkg3;
6037
6218
  var init_upgrade_cmd = __esm({
6038
6219
  "src/cli/commands/upgrade.cmd.ts"() {
6039
6220
  "use strict";
@@ -6042,8 +6223,8 @@ var init_upgrade_cmd = __esm({
6042
6223
  init_claude_commands();
6043
6224
  init_errors();
6044
6225
  init_progress();
6045
- require3 = createRequire2(import.meta.url);
6046
- pkg2 = require3("../../package.json");
6226
+ require4 = createRequire3(import.meta.url);
6227
+ pkg3 = require4("../../package.json");
6047
6228
  }
6048
6229
  });
6049
6230
 
@@ -6053,7 +6234,7 @@ __export(savetoken_cmd_exports, {
6053
6234
  savetokenCommand: () => savetokenCommand
6054
6235
  });
6055
6236
  import { join as join17, relative } from "path";
6056
- import fs21 from "fs-extra";
6237
+ import fs22 from "fs-extra";
6057
6238
  import chalk6 from "chalk";
6058
6239
  async function savetokenCommand(cwd) {
6059
6240
  const { createSpinner: createSpinner2 } = await Promise.resolve().then(() => (init_progress(), progress_exports));
@@ -6123,10 +6304,10 @@ async function savetokenCommand(cwd) {
6123
6304
  console.log(` ${chalk6.red("\u25CF")} \uB192\uC74C \uCF54\uB4DC \uC0DD\uC131, \uBCF5\uC7A1\uD55C \uCD94\uB860, \uCC3D\uC758\uC801 \uC0DD\uC131`);
6124
6305
  console.log(` \u2192 ${colors.dim("AI \uD544\uC218 \u2014 \uD504\uB86C\uD504\uD2B8 \uCD5C\uC801\uD654\uB85C \uD1A0\uD070 \uC808\uAC10")}`);
6125
6306
  const reportDir = join17(cwd, ".pai");
6126
- await fs21.ensureDir(reportDir);
6307
+ await fs22.ensureDir(reportDir);
6127
6308
  const report = buildReport(callSites, cwd);
6128
6309
  const reportPath = join17(reportDir, "savetoken-report.md");
6129
- await fs21.writeFile(reportPath, report, "utf8");
6310
+ await fs22.writeFile(reportPath, report, "utf8");
6130
6311
  console.log("");
6131
6312
  success("\uC2A4\uCE94 \uB9AC\uD3EC\uD2B8 \uC800\uC7A5: .pai/savetoken-report.md");
6132
6313
  console.log("");
@@ -6284,7 +6465,7 @@ __export(wakeup_cmd_exports, {
6284
6465
  });
6285
6466
  import { join as join18 } from "path";
6286
6467
  import { homedir as homedir3, platform as osPlatform } from "os";
6287
- import fs22 from "fs-extra";
6468
+ import fs23 from "fs-extra";
6288
6469
  import chalk7 from "chalk";
6289
6470
  async function wakeupCommand(timeOrAction, schedule = "\uD3C9\uC77C") {
6290
6471
  if (timeOrAction === "off") {
@@ -6331,9 +6512,9 @@ async function wakeupCommand(timeOrAction, schedule = "\uD3C9\uC77C") {
6331
6512
  projectDir,
6332
6513
  launchMode
6333
6514
  };
6334
- await fs22.ensureDir(PAI_DIR2);
6335
- await fs22.writeJson(CONFIG_FILE2, config, { spaces: 2 });
6336
- await fs22.writeJson(MESSAGES_FILE, MESSAGES);
6515
+ await fs23.ensureDir(PAI_DIR2);
6516
+ await fs23.writeJson(CONFIG_FILE2, config, { spaces: 2 });
6517
+ await fs23.writeJson(MESSAGES_FILE, MESSAGES);
6337
6518
  await createWakeupScript(config);
6338
6519
  if (osPlatform() === "darwin") {
6339
6520
  await setupMacOS(config);
@@ -6364,7 +6545,7 @@ async function setupMacOS(config) {
6364
6545
  const { execa } = await import("execa");
6365
6546
  const [hour, minute] = config.time.split(":").map(Number);
6366
6547
  const plistDir = join18(homedir3(), "Library", "LaunchAgents");
6367
- await fs22.ensureDir(plistDir);
6548
+ await fs23.ensureDir(plistDir);
6368
6549
  const weekdays = scheduleToWeekdays(config.schedule);
6369
6550
  let calendarEntries;
6370
6551
  if (weekdays.length === 7) {
@@ -6400,7 +6581,7 @@ ${calendarEntries}
6400
6581
  <string>${PAI_DIR2}/wakeup.log</string>
6401
6582
  </dict>
6402
6583
  </plist>`;
6403
- await fs22.writeFile(PLIST_PATH, plist);
6584
+ await fs23.writeFile(PLIST_PATH, plist);
6404
6585
  await execa("launchctl", ["unload", PLIST_PATH]).catch(() => {
6405
6586
  });
6406
6587
  await execa("launchctl", ["load", PLIST_PATH]);
@@ -6423,7 +6604,7 @@ async function setupWindows(config) {
6423
6604
  const { execa } = await import("execa");
6424
6605
  const [hour, minute] = config.time.split(":").map(Number);
6425
6606
  const psScriptDir = join18(homedir3(), ".pai");
6426
- await fs22.ensureDir(psScriptDir);
6607
+ await fs23.ensureDir(psScriptDir);
6427
6608
  const psScriptPath = join18(psScriptDir, "wakeup.ps1");
6428
6609
  const claudeCmd = config.launchMode === "yolo" ? "claude --dangerously-skip-permissions" : "claude";
6429
6610
  const psScript = `# PAI Wakeup \u2014 Claude Code \uC138\uC158 \uC790\uB3D9 \uC2DC\uC791
@@ -6453,7 +6634,7 @@ $notifier.Show([Windows.UI.Notifications.ToastNotification]::new($xml))
6453
6634
  # Open PowerShell with Claude Code
6454
6635
  Start-Process powershell -ArgumentList "-NoExit", "-Command", "Get-Content '$todayFile'; Write-Host ''; Set-Location '${config.projectDir}'; ${claudeCmd}"
6455
6636
  `;
6456
- await fs22.writeFile(psScriptPath, psScript, "utf8");
6637
+ await fs23.writeFile(psScriptPath, psScript, "utf8");
6457
6638
  const daysMap = {
6458
6639
  "\uD3C9\uC77C": "MON,TUE,WED,THU,FRI",
6459
6640
  "\uB9E4\uC77C": "MON,TUE,WED,THU,FRI,SAT,SUN",
@@ -6501,7 +6682,7 @@ async function disableWakeup() {
6501
6682
  if (osPlatform() === "darwin") {
6502
6683
  await execa("launchctl", ["unload", PLIST_PATH]).catch(() => {
6503
6684
  });
6504
- await fs22.remove(PLIST_PATH).catch(() => {
6685
+ await fs23.remove(PLIST_PATH).catch(() => {
6505
6686
  });
6506
6687
  success("launchd \uC2A4\uCF00\uC904 \uC81C\uAC70");
6507
6688
  console.log("");
@@ -6522,14 +6703,14 @@ async function disableWakeup() {
6522
6703
  } else {
6523
6704
  await removeCronEntry();
6524
6705
  }
6525
- await fs22.remove(CONFIG_FILE2).catch(() => {
6706
+ await fs23.remove(CONFIG_FILE2).catch(() => {
6526
6707
  });
6527
6708
  console.log("");
6528
6709
  success("\u2600\uFE0F \uC6E8\uC774\uD06C\uC5C5 \uD574\uC81C \uC644\uB8CC");
6529
6710
  }
6530
6711
  async function showStatus() {
6531
- if (await fs22.pathExists(CONFIG_FILE2)) {
6532
- const config = await fs22.readJson(CONFIG_FILE2);
6712
+ if (await fs23.pathExists(CONFIG_FILE2)) {
6713
+ const config = await fs23.readJson(CONFIG_FILE2);
6533
6714
  console.log("");
6534
6715
  success("\u2600\uFE0F \uC6E8\uC774\uD06C\uC5C5 \uD65C\uC131\uD654");
6535
6716
  console.log(` \uC2DC\uAC04 ${chalk7.white(config.time)}`);
@@ -6537,7 +6718,7 @@ async function showStatus() {
6537
6718
  console.log(` \uD504\uB85C\uC81D\uD2B8 ${chalk7.white(config.projectDir)}`);
6538
6719
  console.log(` \uBAA8\uB4DC ${chalk7.white(config.launchMode === "yolo" ? "claude-YOLO mode" : "\uC77C\uBC18 \uBAA8\uB4DC")}`);
6539
6720
  if (osPlatform() === "darwin") {
6540
- const plistExists = await fs22.pathExists(PLIST_PATH);
6721
+ const plistExists = await fs23.pathExists(PLIST_PATH);
6541
6722
  console.log(` launchd ${plistExists ? chalk7.green("\uD65C\uC131") : chalk7.red("\uBE44\uD65C\uC131")}`);
6542
6723
  }
6543
6724
  console.log("");
@@ -6690,7 +6871,7 @@ fi
6690
6871
 
6691
6872
  echo "[$(date)] PAI Wakeup completed" >> "$LOG_FILE"
6692
6873
  `;
6693
- await fs22.writeFile(SCRIPT_FILE, script, { mode: 493 });
6874
+ await fs23.writeFile(SCRIPT_FILE, script, { mode: 493 });
6694
6875
  }
6695
6876
  var PAI_DIR2, CONFIG_FILE2, MESSAGES_FILE, SCRIPT_FILE, PLIST_NAME, PLIST_PATH, CRON_MARKER, MESSAGES;
6696
6877
  var init_wakeup_cmd = __esm({
@@ -6764,7 +6945,7 @@ Good programmers write code that humans can understand."
6764
6945
 
6765
6946
  // src/cli/index.ts
6766
6947
  import { Command } from "commander";
6767
- import { createRequire as createRequire3 } from "module";
6948
+ import { createRequire as createRequire4 } from "module";
6768
6949
 
6769
6950
  // src/cli/deprecation.ts
6770
6951
  var warned = /* @__PURE__ */ new Set();
@@ -6778,11 +6959,14 @@ function warnDeprecated(oldCmd, newCmd) {
6778
6959
  }
6779
6960
 
6780
6961
  // src/cli/index.ts
6781
- var require4 = createRequire3(import.meta.url);
6782
- var pkg3 = require4("../../package.json");
6962
+ var require5 = createRequire4(import.meta.url);
6963
+ var pkg4 = require5("../../package.json");
6783
6964
  function createProgram() {
6784
6965
  const program2 = new Command();
6785
- program2.name("pai").description("PAI Zero (Plugin AI for ProjectZero) \u2014 AI \uAC1C\uBC1C \uBE4C\uB4DC \uC624\uCF00\uC2A4\uD2B8\uB808\uC774\uD130").version(pkg3.version, "-v, --version");
6966
+ program2.name("pai").description("PAI Zero (Plugin AI for ProjectZero) \u2014 AI \uAC1C\uBC1C \uBE4C\uB4DC \uC624\uCF00\uC2A4\uD2B8\uB808\uC774\uD130").version(pkg4.version, "-v, --version").action(async () => {
6967
+ const { welcomeCommand: welcomeCommand2 } = await Promise.resolve().then(() => (init_welcome_cmd(), welcome_cmd_exports));
6968
+ await welcomeCommand2(process.cwd());
6969
+ });
6786
6970
  program2.command("init [project-name]").description("\uD504\uB85C\uC81D\uD2B8 \uCD08\uAE30\uD654 (\uC0C8 \uD504\uB85C\uC81D\uD2B8 / \uAE30\uC874 \uD504\uB85C\uC81D\uD2B8 \uC790\uB3D9 \uAC10\uC9C0)").action(async (projectName) => {
6787
6971
  const { initCommand: initCommand2 } = await Promise.resolve().then(() => (init_init_cmd(), init_cmd_exports));
6788
6972
  await initCommand2(process.cwd(), projectName);