@byh3071/vhk 0.6.0 → 0.7.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/index.js CHANGED
@@ -2,8 +2,15 @@
2
2
  import {
3
3
  __commonJS,
4
4
  __toESM,
5
- startMcpServer
6
- } from "./chunk-IU37BEQA.js";
5
+ env,
6
+ envCheck,
7
+ ko,
8
+ printNextStep,
9
+ safeExecFile,
10
+ safeExecFileStream,
11
+ startMcpServer,
12
+ t
13
+ } from "./chunk-3HHU7V77.js";
7
14
 
8
15
  // node_modules/.pnpm/ignore@7.0.5/node_modules/ignore/index.js
9
16
  var require_ignore = __commonJS({
@@ -465,7 +472,7 @@ var require_ignore = __commonJS({
465
472
 
466
473
  // src/index.ts
467
474
  import { Command, Help } from "commander";
468
- import inquirer8 from "inquirer";
475
+ import inquirer10 from "inquirer";
469
476
 
470
477
  // src/lib/nlp-router.ts
471
478
  function normalize(input) {
@@ -571,9 +578,33 @@ var RULES = [
571
578
  },
572
579
  {
573
580
  command: "ship",
574
- explanation: "\uBC30\uD3EC \uCCB4\uD06C + \uD68C\uACE0 (vhk ship)",
581
+ explanation: "\uBC30\uD3EC \uCCB4\uD06C\uB9AC\uC2A4\uD2B8 + \uD68C\uACE0 (vhk \uCD9C\uD558)",
582
+ confidence: "high",
583
+ test: (t2) => /^출하$|^ship$|빌드\s*전|(배포|출하)\s*(체크|준비|점검)/.test(t2)
584
+ },
585
+ {
586
+ command: "deploy",
587
+ explanation: "\uD504\uB85C\uB355\uC158 \uBC30\uD3EC (vhk deploy)",
588
+ confidence: "high",
589
+ test: (t2) => /^배포$|배포\s*해|배포하|배포해줘|^deploy$|디플로이|vercel|netlify|cloudflare|wrangler|프로덕션|올려줘/.test(t2) && !/체크|준비|점검|출하|회고|빌드\s*전/.test(t2)
590
+ },
591
+ {
592
+ command: "env-check",
593
+ explanation: "\uD658\uACBD\uBCC0\uC218 \uB204\uB77D \uAC80\uC0AC (vhk env-check)",
594
+ confidence: "high",
595
+ test: (t2) => /환경변수\s*(점검|확인|누락)|env\s*(체크|확인|check)|키\s*(확인|누락)/.test(t2)
596
+ },
597
+ {
598
+ command: "env",
599
+ explanation: "\uD658\uACBD\uBCC0\uC218 \uAD00\uB9AC (vhk env)",
600
+ confidence: "high",
601
+ test: (t2) => /환경변수|\.env|env\s*example|env\s*동기화|시크릿\s*정리|키\s*설정/.test(t2) && !/점검|확인|누락|체크|check/.test(t2)
602
+ },
603
+ {
604
+ command: "publish",
605
+ explanation: "npm \uBC30\uD3EC (vhk publish)",
575
606
  confidence: "high",
576
- test: (t2) => /배포|출시|릴리스|ship|빌드\s*전/.test(t2)
607
+ test: (t2) => /^출시$|출시\s*해|^publish$|퍼블리시|npm\s*(배포|출시)|버전\s*올|^릴리즈$|^release$/.test(t2) && !/체크|준비|회고/.test(t2)
577
608
  }
578
609
  ];
579
610
  function routeNaturalLanguage(input) {
@@ -618,8 +649,6 @@ var KNOWN_COMMAND_TOKENS = /* @__PURE__ */ new Set([
618
649
  "scan",
619
650
  "\uC2A4\uCE94",
620
651
  "ship",
621
- "\uBC30\uD3EC",
622
- "\uB9B4\uB9AC\uC988",
623
652
  "doctor",
624
653
  "\uD658\uACBD",
625
654
  "\uC9C4\uB2E8",
@@ -636,6 +665,15 @@ var KNOWN_COMMAND_TOKENS = /* @__PURE__ */ new Set([
636
665
  "mcp",
637
666
  "mcp-init",
638
667
  "mcp\uC124\uC815",
668
+ "deploy",
669
+ "\uBC30\uD3EC",
670
+ "env",
671
+ "\uD658\uACBD\uBCC0\uC218",
672
+ "env-check",
673
+ "\uD658\uACBD\uBCC0\uC218\uC810\uAC80",
674
+ "publish",
675
+ "\uCD9C\uC2DC",
676
+ "\uCD9C\uD558",
639
677
  "help"
640
678
  ]);
641
679
  function isOptionToken(token) {
@@ -659,306 +697,12 @@ function detectNaturalLanguageInput(argv) {
659
697
  }
660
698
 
661
699
  // src/lib/nlp-run.ts
662
- import chalk17 from "chalk";
663
- import inquirer7 from "inquirer";
664
-
665
- // src/i18n/ko.ts
666
- var ko = {
667
- status: {
668
- title: "\uD504\uB85C\uC81D\uD2B8 \uC0C1\uD0DC",
669
- notGitRepo: "Git \uC800\uC7A5\uC18C\uAC00 \uC544\uB2C8\uC5D0\uC694. \uBA3C\uC800 git init\uC744 \uC2E4\uD589\uD558\uC138\uC694.",
670
- branch: "\uBE0C\uB79C\uCE58:",
671
- changes: "\uBCC0\uACBD:",
672
- recentCommits: "\uCD5C\uADFC \uCEE4\uBC0B (3):",
673
- noCommits: "\uCEE4\uBC0B \uC5C6\uC74C",
674
- remote: "\uC6D0\uACA9:",
675
- noUpstream: "upstream \uC5C6\uC74C",
676
- inSync: "\uB3D9\uAE30\uD654\uB428",
677
- ahead: (n) => `\u2191${n} ahead`,
678
- behind: (n) => `\u2193${n} behind`,
679
- package: "package.json:",
680
- noPackage: "package.json \uC5C6\uC74C",
681
- detached: "(detached HEAD)",
682
- unknownBranch: "(\uC54C \uC218 \uC5C6\uC74C)"
683
- },
684
- save: {
685
- title: "\uC800\uC7A5\uD558\uAE30",
686
- notGitRepo: "git \uC800\uC7A5\uC18C\uAC00 \uC544\uB2D9\uB2C8\uB2E4. \uBA3C\uC800 git init\uC744 \uC2E4\uD589\uD558\uC138\uC694.",
687
- noChanges: "\uC800\uC7A5\uD560 \uBCC0\uACBD\uC0AC\uD56D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
688
- filesHeader: (n) => `\uBCC0\uACBD\uB41C \uD30C\uC77C (${n}\uAC1C):`,
689
- commitMessage: "\uCEE4\uBC0B \uBA54\uC2DC\uC9C0 (Enter\uB85C \uAE30\uBCF8\uAC12 \uC0AC\uC6A9):",
690
- saving: "\uC800\uC7A5 \uC911...",
691
- pushing: "\uC6D0\uACA9 \uC800\uC7A5\uC18C\uC5D0 \uC62C\uB9AC\uB294 \uC911...",
692
- successWithPush: "\uC800\uC7A5 + \uC6D0\uACA9 \uC5C5\uB85C\uB4DC \uC644\uB8CC!",
693
- successLocal: "\uB85C\uCEEC \uC800\uC7A5 \uC644\uB8CC!",
694
- noRemote: "\uC6D0\uACA9 \uC800\uC7A5\uC18C\uAC00 \uC124\uC815\uB418\uC9C0 \uC54A\uC544 push\uB97C \uAC74\uB108\uB6F0\uC5C8\uC2B5\uB2C8\uB2E4.",
695
- failed: "\uC800\uC7A5 \uC2E4\uD328",
696
- stagedAfterFail: "\uCEE4\uBC0B\uC740 \uC2E4\uD328\uD588\uC9C0\uB9CC \uD30C\uC77C\uC740 \uC2A4\uD14C\uC774\uC9D5\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4. \uD655\uC778: git status / \uCDE8\uC18C: git reset HEAD",
697
- securityWarnHeader: "\uC800\uC7A5 \uC804 \uBCF4\uC548 \uD655\uC778:",
698
- secretsFound: (n) => `\uCF54\uB4DC\uC5D0\uC11C CRITICAL/HIGH \uC2DC\uD06C\uB9BF \uD328\uD134 ${n}\uAC74 \uAC10\uC9C0`,
699
- secretsConfirm: "\uADF8\uB798\uB3C4 \uCEE4\uBC0B\xB7push\uB97C \uC9C4\uD589\uD560\uAE4C\uC694?",
700
- cancelled: "\uC800\uC7A5\uC744 \uCDE8\uC18C\uD588\uC2B5\uB2C8\uB2E4.",
701
- pushFailed: "push \uC2E4\uD328 (\uB85C\uCEEC \uCEE4\uBC0B\uC740 \uC644\uB8CC\uB428)",
702
- commitOkPushFailed: "\uB85C\uCEEC \uCEE4\uBC0B\uC740 \uB410\uC9C0\uB9CC \uC6D0\uACA9 push\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. git push\uB97C \uC9C1\uC811 \uD655\uC778\uD558\uC138\uC694.",
703
- done: (n) => `${n}\uAC1C \uD30C\uC77C \uC800\uC7A5 \uC644\uB8CC!`,
704
- doneLocalOnly: (n) => `${n}\uAC1C \uD30C\uC77C \uB85C\uCEEC \uC800\uC7A5\uB428 (push\uB294 \uC2E4\uD328)`
705
- },
706
- undo: {
707
- title: "\uB418\uB3CC\uB9AC\uAE30",
708
- notGitRepo: "git \uC800\uC7A5\uC18C\uAC00 \uC544\uB2D9\uB2C8\uB2E4.",
709
- noCommits: "\uB418\uB3CC\uB9B4 \uCEE4\uBC0B\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
710
- recentHeader: "\u{1F4CB} \uCD5C\uADFC \uCEE4\uBC0B:",
711
- howMany: "\uBA87 \uAC1C\uC758 \uCEE4\uBC0B\uC744 \uB418\uB3CC\uB9B4\uAE4C\uC694?",
712
- alreadyPushed: "\uC774 \uCEE4\uBC0B\uC740 \uC774\uBBF8 \uC6D0\uACA9\uC5D0 \uC62C\uB77C\uAC14\uC2B5\uB2C8\uB2E4. \uB418\uB3CC\uB9AC\uBA74 \uCDA9\uB3CC\uC774 \uC0DD\uAE38 \uC218 \uC788\uC5B4\uC694.",
713
- noUpstreamWarning: "upstream \uBE0C\uB79C\uCE58\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. \uC774\uBBF8 push\uD55C \uCEE4\uBC0B\uC77C \uC218 \uC788\uC5B4\uC694. \uB418\uB3CC\uB9B0 \uB4A4 force push\uAC00 \uD544\uC694\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
714
- confirmMessage: "\uCD5C\uADFC \uCEE4\uBC0B\uC744 \uB418\uB3CC\uB9AC\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
715
- confirmRisky: (n) => `\u26A0\uFE0F \uC704\uD5D8: \uCD5C\uADFC ${n}\uAC1C \uCEE4\uBC0B\uC744 soft reset\uD569\uB2C8\uB2E4. \uC6D0\uACA9\uACFC \uC5B4\uAE0B\uB0A0 \uC218 \uC788\uC2B5\uB2C8\uB2E4. \uACC4\uC18D\uD560\uAE4C\uC694?`,
716
- cancelled: "\uCDE8\uC18C\uB428",
717
- success: "\uB418\uB3CC\uB9AC\uAE30 \uC644\uB8CC! \uBCC0\uACBD\uC0AC\uD56D\uC740 \uADF8\uB300\uB85C \uB0A8\uC544\uC788\uC2B5\uB2C8\uB2E4.",
718
- stagedHint: "\uBCC0\uACBD\uC0AC\uD56D\uC740 \uC2A4\uD14C\uC774\uC9D5 \uC601\uC5ED\uC5D0 \uB0A8\uC544 \uC788\uC5B4\uC694.",
719
- rootCommit: "\uCCAB \uCEE4\uBC0B\uB9CC \uC788\uC5B4\uC11C \uB354 \uB418\uB3CC\uB9B4 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
720
- forcePushHint: "\uC6D0\uACA9\uACFC \uB9DE\uCD94\uB824\uBA74: git push --force-with-lease (\uD63C\uC790 \uC791\uC5C5\uD55C \uBE0C\uB79C\uCE58\uC5D0\uC11C\uB9CC, \uD300\uACFC \uD569\uC758 \uD6C4)",
721
- failed: "\uB418\uB3CC\uB9AC\uAE30 \uC2E4\uD328"
722
- },
723
- diff: {
724
- title: "\uBCC0\uACBD\uC0AC\uD56D \uD655\uC778",
725
- notGitRepo: "git \uC800\uC7A5\uC18C\uAC00 \uC544\uB2D9\uB2C8\uB2E4.",
726
- noChanges: "\uBCC0\uACBD\uC0AC\uD56D \uC5C6\uC74C! \uAE68\uB057\uD569\uB2C8\uB2E4.",
727
- stagedHeader: "\u{1F4E6} \uCEE4\uBC0B \uB300\uAE30 (staged):",
728
- unstagedHeader: "\u270F\uFE0F \uC218\uC815\uB428 (unstaged):",
729
- untrackedHeader: (n) => `\u2795 \uC0C8 \uD30C\uC77C (${n}\uAC1C):`,
730
- summaryHeader: "\u{1F4CA} \uCD1D \uBCC0\uACBD \uC694\uC57D (\uC791\uC5C5 \uD2B8\uB9AC vs HEAD)",
731
- filesLine: (n) => `\uD30C\uC77C: ${n}\uAC1C`
732
- },
733
- start: {
734
- title: "\u{1F527} VHK \u2014 \uBB34\uC5C7\uC744 \uB3C4\uC640\uB4DC\uB9B4\uAE4C\uC694?",
735
- subtitle: "\uBC88\uD638\uB9CC \uACE0\uB974\uBA74 \uB429\uB2C8\uB2E4. \uBA85\uB839\uC5B4\uB97C \uC678\uC6B8 \uD544\uC694 \uC5C6\uC5B4\uC694.",
736
- menuPrompt: "\uC5B4\uB5A4 \uC791\uC5C5\uC744 \uD560\uAE4C\uC694?",
737
- choiceGate: "1) \uC0C8 \uC544\uC774\uB514\uC5B4 \uAC80\uC99D\uD558\uAE30",
738
- choiceInit: "2) \uD504\uB85C\uC81D\uD2B8 \uC2DC\uC791\uD558\uAE30 \u2014 \uD3F4\uB354\xB7\uD30C\uC77C \uB9CC\uB4E4\uAE30",
739
- choiceInitSkipGate: "3) \uAE30\uD68D\uC740 \uB05D\uB0AC\uC5B4\uC694 \u2014 \uBC14\uB85C \uD504\uB85C\uC81D\uD2B8 \uB9CC\uB4E4\uAE30",
740
- choiceRecap: "4) \uC624\uB298 \uD55C \uC77C \uC815\uB9AC\uD558\uAE30",
741
- choiceSync: "5) \uADDC\uCE59 \uD30C\uC77C \uB9DE\uCD94\uAE30",
742
- choiceCheck: "6) \uD504\uB85C\uC81D\uD2B8 \uADDC\uCE59 \uC810\uAC80\uD558\uAE30",
743
- choiceSecure: "7) \uBE44\uBC00\uBC88\uD638\xB7\uD0A4 \uC720\uCD9C \uAC80\uC0AC\uD558\uAE30",
744
- choiceExit: "\uB098\uAC00\uAE30",
745
- goodbye: "\uB2E4\uC74C\uC5D0 \uB610 \uBD88\uB7EC\uC8FC\uC138\uC694."
746
- },
747
- gate: {
748
- title: "\u{1F4A1} \uC544\uC774\uB514\uC5B4 \uAC80\uC99D",
749
- welcome: "\uC0C8 \uC544\uC774\uB514\uC5B4\uB97C \uAC80\uC99D\uD569\uB2C8\uB2E4. \uC9C8\uBB38\uC5D0 \uB2F5\uD574\uC8FC\uC138\uC694.",
750
- modePrompt: "\uC5B4\uB5BB\uAC8C \uAC80\uC99D\uD560\uAE4C\uC694?",
751
- modeQuickLabel: "\u26A1 \uC9E7\uAC8C (\uD575\uC2EC 5\uBB38\uD56D) \u2014 \uB9C9 \uB5A0\uC62C\uB790\uC744 \uB54C",
752
- modeFullLabel: "\u{1F50D} \uC790\uC138\uD788 (13\uBB38\uD56D) \u2014 \uAE30\uD68D\uC774 \uC5B4\uB290 \uC815\uB3C4 \uC7A1\uD614\uC744 \uB54C",
753
- modeSkipLabel: "\u23ED\uFE0F \uAC74\uB108\uB6F0\uAE30 \u2014 \uB178\uC158\xB7\uBB38\uC11C\uC5D0 \uC774\uBBF8 \uAE30\uD68D\uD574 \uB460",
754
- skipSourcePrompt: "\u{1F4C4} \uAE30\uD68D \uBB38\uC11C \uC704\uCE58 (\uB178\uC158 \uC8FC\uC18C, \uD30C\uC77C \uACBD\uB85C \uB4F1):",
755
- skipGo: "\u2705 \uC2DC\uC791\uD574\uB3C4 \uB3FC\uC694! \uC774\uC81C \uD504\uB85C\uC81D\uD2B8\uB97C \uB9CC\uB4E4\uC5B4 \uBCF4\uC138\uC694 (vhk init)",
756
- skipSourceLabel: (source) => `\uAE30\uD68D \uBB38\uC11C: ${source}`,
757
- quickHeader: "\u26A1 \uC9E7\uC740 \uAC80\uC99D",
758
- fullHeader: "\u{1F50D} \uC790\uC138\uD55C \uAC80\uC99D",
759
- modeCountSuffix: (total) => `\u2014 ${total}\uBB38\uD56D`,
760
- idea: "\u{1F4A1} \uC5B4\uB5A4 \uAC78 \uB9CC\uB4E4 \uAC74\uAC00\uC694? (\uD55C \uC904)",
761
- ideaHint: '\uC608: "\uD300 \uD560 \uC77C\uC744 3\uCD08\uC5D0 \uCD94\uAC00\uD558\uB294 \uC571"',
762
- painPoint: "\u{1F624} \uC774 \uBB38\uC81C, \uB204\uAC00 \uC5BC\uB9C8\uB098 \uC544\uD30C\uD574\uC694?",
763
- painPointHint: '\uC608: "\uB9E4\uC77C \uC5D1\uC140\uC5D0 \uBCF5\uBD99\uD558\uB290\uB77C 30\uBD84\uC529 \uB0A0\uB9BC"',
764
- edge: "\u{1F4AA} \uB098\uB9CC\uC758 \uAC15\uC810\uC740? (\uBE44\uC2B7\uD55C \uAC8C \uC788\uB294\uB370 \uC65C \uC774\uAC78?)",
765
- edgeHint: '\uC608: "\uD55C\uAD6D\uC5B4\uB85C \uB41C \uAC00\uC774\uB4DC + \uBC14\uB85C \uC4F0\uB294 \uD15C\uD50C\uB9BF"',
766
- checklistStart: "\u2500\u2500\u2500 \uC774\uC5B4\uC11C \uC9C8\uBB38\uD569\uB2C8\uB2E4 \u2500\u2500\u2500",
767
- hintPrefix: " \u{1F4A1}",
768
- verdictPrompt: (_failIf) => " \u2192 \uC9C0\uAE08 \uC0C1\uD0DC\uB294?",
769
- statusPassChoice: "\u2705 \uAD1C\uCC2E\uC544\uC694",
770
- statusHoldChoice: "\u{1F7E1} \uC544\uC9C1 \uBAA8\uB974\uACA0\uC5B4\uC694 (\uB098\uC911\uC5D0 \uCC44\uC6CC\uB3C4 \uB429\uB2C8\uB2E4)",
771
- statusFailChoice: "\u{1F504} \uBC94\uC704\uB97C \uC904\uC5EC\uBCFC\uAC8C\uC694",
772
- statusPassLine: " \u2705 \uAD1C\uCC2E\uC544\uC694",
773
- statusHoldLine: " \u{1F7E1} \uBCF4\uB958 \u2014 \uAC1C\uBC1C\uD558\uBA74\uC11C \uCC44\uC6CC\uB3C4 \uB429\uB2C8\uB2E4",
774
- statusFailLine: " \u{1F504} \uBC94\uC704 \uC870\uC815\uC774 \uD544\uC694\uD574 \uBCF4\uC5EC\uC694",
775
- verdictTitle: "\u2550\u2550\u2550 \uACB0\uACFC \u2550\u2550\u2550",
776
- ideaLabel: "\uB9CC\uB4E4 \uAC83:",
777
- painPointLabel: "\uC544\uD508 \uC810:",
778
- edgeLabel: "\uB098\uB9CC\uC758 \uAC15\uC810:",
779
- countLine: (failCount, holdCount, total) => `\uBC94\uC704 \uC870\uC815 ${failCount}\uAC1C \xB7 \uBCF4\uB958 ${holdCount}\uAC1C / ${total}\uBB38\uD56D`,
780
- go: "\u2705 \uC2DC\uC791\uD574\uB3C4 \uB3FC\uC694! \uB2E4\uC74C \uB2E8\uACC4(\uD504\uB85C\uC81D\uD2B8 \uB9CC\uB4E4\uAE30)\uB85C \uB118\uC5B4\uAC00\uC138\uC694.",
781
- refine: "\u{1F504} \uC870\uAE08 \uB354 \uB2E4\uB4EC\uC73C\uBA74 \uC88B\uACA0\uC5B4\uC694. \uC704 \uD56D\uBAA9\uC744 \uBCF4\uC644\uD574 \uBCF4\uC138\uC694.",
782
- drop: "\u{1F4A1} \uB2E4\uB978 \uC544\uC774\uB514\uC5B4\uB97C \uAC80\uD1A0\uD574 \uBCF4\uB294 \uAC74 \uC5B4\uB5A8\uAE4C\uC694?",
783
- nextCommand: "\uB2E4\uC74C: vhk init (\uD504\uB85C\uC81D\uD2B8 \uC2DC\uC791\uD558\uAE30)",
784
- holdRemainHint: "\u{1F4A1} \uBCF4\uB958\uD55C \uD56D\uBAA9\uC740 \uAC1C\uBC1C\uD558\uBA74\uC11C \uCC44\uC6CC\uB3C4 \uAD1C\uCC2E\uC544\uC694.",
785
- failMessage: "\uC544\uC9C1 \uBAA8\uB974\uACA0\uC5B4\uC694 \u2192 \uAD1C\uCC2E\uC544\uC694, \uAC1C\uBC1C\uD558\uBA74\uC11C \uCC44\uC6CC\uB3C4 \uB429\uB2C8\uB2E4."
786
- },
787
- init: {
788
- title: "\u{1F6E0}\uFE0F \uD504\uB85C\uC81D\uD2B8 \uC2DC\uC791\uD558\uAE30",
789
- skipGate: "\u23ED\uFE0F 1\uB2E8\uACC4(\uC544\uC774\uB514\uC5B4 \uAC80\uC99D) \uAC74\uB108\uB6F0\uAE30 \u2014 \uAE30\uD68D\xB7\uC124\uACC4\uAC00 \uC774\uBBF8 \uC788\uC5B4\uC694",
790
- projectName: "\u{1F4E6} \uD504\uB85C\uC81D\uD2B8 \uC774\uB984\uC740?",
791
- projectNameHint: '\uC608: "\uD300 \uD560 \uC77C \uC571"',
792
- description: "\u{1F4DD} \uD55C \uC904\uB85C \uC124\uBA85\uD558\uBA74?",
793
- descriptionHint: '\uC608: "3\uCD08 \uB9CC\uC5D0 \uD560 \uC77C \uCD94\uAC00"',
794
- projectType: "\u{1F3D7}\uFE0F \uC5B4\uB5A4 \uC885\uB958\uC778\uAC00\uC694?",
795
- confirmStack: "\uC774 \uAE30\uC220 \uBB36\uC74C\uC73C\uB85C \uC9C4\uD589\uD560\uAE4C\uC694?",
796
- canceled: "\uCDE8\uC18C\uD588\uC5B4\uC694. \uAE30\uC220 \uBB36\uC74C\uC744 \uBC14\uAFB8\uB824\uBA74 \uB2E4\uC2DC vhk init\uC744 \uC2E4\uD589\uD558\uC138\uC694.",
797
- recommendedStack: "\uCD94\uCC9C \uAE30\uC220 \uBB36\uC74C:",
798
- filesGenerating: "\u{1F4C2} \uD544\uC694\uD55C \uD30C\uC77C \uB9CC\uB4DC\uB294 \uC911...",
799
- overwrite: (filePath) => ` \u26A0\uFE0F ${filePath} \uD30C\uC77C\uC774 \uC788\uC5B4\uC694. \uB36E\uC5B4\uC4F8\uAE4C\uC694?`,
800
- skipped: (filePath) => `${filePath} \u2014 \uAC74\uB108\uB700`,
801
- done: "\u{1F389} \uD504\uB85C\uC81D\uD2B8 \uBF08\uB300\uAC00 \uC900\uBE44\uB410\uC5B4\uC694!",
802
- nextSteps: "\uB2E4\uC74C\uC5D0 \uD560 \uC77C:",
803
- fillHint: "CLAUDE.md \xB7 .cursorrules\uC5D0\uC11C \u{1F449} \uC5EC\uAE30\uB97C \uCC44\uC6CC\uC8FC\uC138\uC694 \uD45C\uC2DC\uB97C \uCC3E\uC544 \uCC44\uC6B0\uC138\uC694",
804
- prdHint: "docs/PRD.md\uC5D0 1\uCC28 \uBC84\uC804\uC5D0 \uB123\uC744 \uAE30\uB2A5\xB7\uBE7C\uB294 \uAE30\uB2A5\uC744 \uC801\uC5B4 \uBCF4\uC138\uC694",
805
- notionFetching: "\u{1F4E1} \uB178\uC158 \uAE30\uD68D \uD398\uC774\uC9C0 \uBD88\uB7EC\uC624\uB294 \uC911...",
806
- notionDone: (name) => `\uB178\uC158\uC5D0\uC11C \uAC00\uC838\uC624\uAE30 \uC644\uB8CC: ${name}`,
807
- notionReviewHint: "docs/PRD.md\uB97C \uC77D\uACE0 \u{1F449} \uC5EC\uAE30\uB97C \uCC44\uC6CC\uC8FC\uC138\uC694 \uD56D\uBAA9\uC744 \uCC44\uC6B0\uC138\uC694",
808
- gitHintLabel: "\uD130\uBBF8\uB110\uC5D0 \uBCF5\uC0AC\uD560 \uBA85\uB839 (\uC544\uB798 \uBC15\uC2A4 \uBCF5\uBD99):",
809
- gitHintCommand: 'git init && git add . && git commit -m "feat: \uD504\uB85C\uC81D\uD2B8 \uC2DC\uC791"',
810
- startDev: "\uC774\uC81C \uAC1C\uBC1C\uD574 \uBCF4\uC138\uC694! \u{1F680}",
811
- commandsMdDone: "\u{1F4CB} COMMANDS.md \uC0DD\uC131",
812
- scriptsDone: "\u{1F4E6} package.json scripts \uCD94\uAC00"
813
- },
814
- recap: {
815
- title: "\u{1F4DD} \uC624\uB298 \uD55C \uC77C \uC815\uB9AC",
816
- analyzing: "\u{1F4CA} \uC624\uB298 \uBC14\uB010 \uD30C\uC77C\xB7\uCEE4\uBC0B\uC744 \uC0B4\uD3B4\uBCF4\uB294 \uC911...",
817
- noRepo: "\u274C Git \uC800\uC7A5\uC18C\uAC00 \uC544\uB2C8\uC5D0\uC694. \uBA3C\uC800 git init\uC744 \uC2E4\uD589\uD558\uC138\uC694.",
818
- noChanges: "\u26A0\uFE0F \uC624\uB298 \uBC14\uB010 \uB0B4\uC6A9\uC774 \uC5C6\uC5B4\uC694.",
819
- summary: "\u{1F4DD} \uC774\uBC88\uC5D0 \uBB58 \uD588\uB098\uC694? (1~3\uC904)",
820
- summaryHint: '\uC608: "\uB85C\uADF8\uC778 \uD654\uBA74 \uB9CC\uB4E4\uACE0 \uBC84\uD2BC \uC0C9 \uACE0\uCE68"',
821
- decisions: "\u{1F9ED} \uC815\uD55C \uACB0\uC815\uC774 \uC788\uB098\uC694? (\uC5C6\uC73C\uBA74 Enter)",
822
- nextTodo: "\u23ED\uFE0F \uB2E4\uC74C\uC5D0 \uD560 \uC77C\uC740?",
823
- blockers: "\u{1F6A7} \uB9C9\uD78C \uAC8C \uC788\uB098\uC694? (\uC5C6\uC73C\uBA74 Enter)",
824
- done: "\u2705 \uC624\uB298 \uAE30\uB85D\uC744 \uC800\uC7A5\uD588\uC5B4\uC694!",
825
- updateClaude: 'CLAUDE.md "\uC9C0\uAE08 \uC0C1\uD0DC"\uB3C4 \uAC19\uC774 \uACE0\uCE60\uAE4C\uC694?',
826
- adrDetected: "\u{1F4D0} \uC4F0\uB294 \uAE30\uC220\xB7\uC124\uC815\uC774 \uBC14\uB010 \uAC83 \uAC19\uC544\uC694!",
827
- createAdr: "\uC65C \uADF8\uB807\uAC8C \uD588\uB294\uC9C0 \uAE30\uB85D \uBB38\uC11C\uB97C \uB9CC\uB4E4\uAE4C\uC694?",
828
- troubleDetected: "\u{1F527} \uBC84\uADF8\xB7\uC624\uB958\uB97C \uACE0\uCE5C \uCEE4\uBC0B\uC774 \uBCF4\uC5EC\uC694!",
829
- createTroubleshoot: "\uC5B4\uB5BB\uAC8C \uACE0\uCCE4\uB294\uC9C0 \uBA54\uBAA8\uB97C \uB0A8\uAE38\uAE4C\uC694?"
830
- },
831
- check: {
832
- title: "\u{1F50D} \uD504\uB85C\uC81D\uD2B8 \uADDC\uCE59 \uC810\uAC80",
833
- noRules: "\u26A0\uFE0F RULES.md \uD30C\uC77C\uC774 \uC5C6\uC5B4\uC694.",
834
- noAutoRules: "\u26A0\uFE0F \uC790\uB3D9\uC73C\uB85C \uAC80\uC0AC\uD560 \uADDC\uCE59\uC774 \uC5C6\uC5B4\uC694.",
835
- allPassed: "\u{1F389} \uADDC\uCE59\uC744 \uBAA8\uB450 \uC9C0\uCF30\uC5B4\uC694!",
836
- summary: "\u{1F4CA} \uC810\uAC80 \uACB0\uACFC:"
837
- },
838
- doctor: {
839
- title: "\u{1FA7A} \uAC1C\uBC1C \uD658\uACBD \uC810\uAC80",
840
- allOk: "\u{1F389} \uAC1C\uBC1C \uD658\uACBD \uC900\uBE44 \uC644\uB8CC!",
841
- missing: "\u26A0\uFE0F \uC77C\uBD80 \uB3C4\uAD6C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
842
- missingHint: "\uC704 \uC548\uB0B4\uB97C \uB530\uB77C \uC124\uCE58\uD558\uC138\uC694.",
843
- projectFiles: "\u{1F4C1} \uD504\uB85C\uC81D\uD2B8 \uD30C\uC77C \uD655\uC778:",
844
- envNotIgnored: "\u26A0\uFE0F .env\uAC00 .gitignore\uC5D0 \uC5C6\uC74C! \uCD94\uAC00\uD558\uC138\uC694",
845
- nextOkMessage: "\uD658\uACBD \uC810\uAC80 \uD1B5\uACFC! \uC774\uC81C \uD504\uB85C\uC81D\uD2B8\uB97C \uC2DC\uC791\uD558\uC138\uC694.",
846
- nextRetryMessage: "\uC704 \uB3C4\uAD6C\uB97C \uC124\uCE58\uD55C \uD6C4 \uB2E4\uC2DC \uC810\uAC80\uD558\uC138\uC694.",
847
- updateAvailable: (latest) => `\u{1F195} v${latest} \uC0AC\uC6A9 \uAC00\uB2A5 \u2014 npm i -g @byh3071/vhk`,
848
- updateCurrent: "\uCD5C\uC2E0 \uBC84\uC804\uC744 \uC4F0\uACE0 \uC788\uC5B4\uC694"
849
- },
850
- nlp: {
851
- matched: "\uC774\uAC8C \uB9DE\uB098\uC694?",
852
- notMatched: "\uBB34\uC2A8 \uB73B\uC778\uC9C0 \uBAA8\uB974\uACA0\uC5B4\uC694. vhk\uB97C \uC785\uB825\uD558\uBA74 \uBA54\uB274\uC5D0\uC11C \uC120\uD0DD\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4.",
853
- menuHint: "vhk\uB97C \uC785\uB825\uD558\uBA74 \uBA54\uB274\uC5D0\uC11C \uC120\uD0DD\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4."
854
- },
855
- secure: {
856
- title: "\u{1F512} \uBE44\uBC00\uBC88\uD638\xB7\uD0A4 \uC720\uCD9C \uAC80\uC0AC",
857
- noGitignore: "\u26A0\uFE0F .gitignore \uD30C\uC77C\uC774 \uC5C6\uC5B4\uC694!",
858
- noEnvInGitignore: "\u26A0\uFE0F .gitignore\uC5D0 .env\uAC00 \uC5C6\uC5B4\uC694!",
859
- scanning: "\u{1F50D} \uD30C\uC77C\uC744 \uC0B4\uD3B4\uBCF4\uB294 \uC911...",
860
- clean: "\u{1F389} \uBE44\uBC00\uBC88\uD638\xB7\uD0A4\uAC00 \uCF54\uB4DC\uC5D0 \uBCF4\uC774\uC9C0 \uC54A\uC544\uC694!",
861
- summary: "\u{1F4CA} \uAC80\uC0AC \uC694\uC57D:"
862
- },
863
- sync: {
864
- title: "\u{1F504} \uADDC\uCE59 \uD30C\uC77C \uB9DE\uCD94\uAE30",
865
- noRules: "\u26A0\uFE0F RULES.md \uD30C\uC77C\uC774 \uC5C6\uC5B4\uC694.",
866
- cursorrulesDone: "\u2705 .cursorrules \uB9DE\uCDA4 \uC644\uB8CC",
867
- claudeDone: "\u2705 CLAUDE.md \uB9DE\uCDA4 \uC644\uB8CC",
868
- done: "\u{1F504} \uB9DE\uCD94\uAE30 \uC644\uB8CC!"
869
- },
870
- ship: {
871
- title: "\u{1F680} \uBC30\uD3EC \uCCB4\uD06C\uB9AC\uC2A4\uD2B8",
872
- checklist: "\u{1F4CB} \uBC30\uD3EC \uC804 \uCCB4\uD06C\uB9AC\uC2A4\uD2B8",
873
- retro: "\u{1F50D} \uBC30\uD3EC \uD68C\uACE0",
874
- buildLogCreated: "\u2705 \uBE4C\uB4DC \uB85C\uADF8 \uC0DD\uC131 \uC644\uB8CC",
875
- buildLogDone: (rel) => `\u2705 \uBE4C\uB4DC \uB85C\uADF8 \uC0DD\uC131 \uC644\uB8CC: ${rel}`,
876
- questionWell: "\uC798\uB41C \uC810\uC740?",
877
- questionWrong: "\uC5B4\uB824\uC6E0\uB358 \uC810\uC740?",
878
- questionLearned: "\uBC30\uC6B4 \uC810\uC740?",
879
- questionNext: "\uB2E4\uC74C \uBC84\uC804\uC5D0\uC11C \uD560 \uAC83\uC740?",
880
- checkboxPrompt: "\uC644\uB8CC\uD55C \uD56D\uBAA9\uC744 \uC120\uD0DD\uD558\uC138\uC694:",
881
- incompleteHeader: "\u26A0\uFE0F \uC544\uC9C1 \uC644\uB8CC\uD558\uC9C0 \uC54A\uC740 \uD56D\uBAA9:",
882
- proceedConfirm: "\uADF8\uB798\uB3C4 \uACC4\uC18D \uC9C4\uD589\uD560\uAE4C\uC694?",
883
- allPassed: "\u2705 \uBAA8\uB4E0 \uCCB4\uD06C\uB9AC\uC2A4\uD2B8 \uD1B5\uACFC!",
884
- retryMessage: "\uCCB4\uD06C\uB9AC\uC2A4\uD2B8\uB97C \uB9C8\uCE5C \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD574 \uBCF4\uC138\uC694.",
885
- retryCursorHint: "\uBE4C\uB4DC\uD558\uACE0 \uD14C\uC2A4\uD2B8 \uB3CC\uB824\uC918",
886
- versionPrompt: "\uBC30\uD3EC \uBC84\uC804\uC740?",
887
- versionHint: "\uC608: 0.4.0",
888
- emptySection: "(\uBBF8\uC791\uC131)",
889
- emptyNext: "(\uBBF8\uC815)",
890
- deployMessage: "\uBE4C\uB4DC \uB85C\uADF8\uB97C \uC800\uC7A5\uD588\uC5B4\uC694! \uC774\uC81C \uC2E4\uC81C \uBC30\uD3EC\uB97C \uC9C4\uD589\uD558\uC138\uC694.",
891
- deployCursorHint: "\uBC30\uD3EC\uD574\uC918",
892
- checkBuild: "\uBE4C\uB4DC\uAC00 \uC131\uACF5\uD588\uB098\uC694?",
893
- hintBuild: "pnpm build",
894
- checkTest: "\uBAA8\uB4E0 \uD14C\uC2A4\uD2B8\uAC00 \uD1B5\uACFC\uD588\uB098\uC694?",
895
- hintTest: "pnpm test --run",
896
- checkVersion: "package.json \uBC84\uC804\uC744 \uC62C\uB838\uB098\uC694?",
897
- hintVersion: "version \uD544\uB4DC \uD655\uC778",
898
- checkChangelog: "\uBCC0\uACBD \uB0B4\uC6A9\uC744 \uAE30\uB85D\uD588\uB098\uC694?",
899
- hintChangelog: "README \uB610\uB294 CHANGELOG",
900
- checkSecurity: "\uBCF4\uC548 \uC2A4\uCE94\uC744 \uB3CC\uB838\uB098\uC694?",
901
- hintSecurity: "vhk \uBCF4\uC548 scan",
902
- checkCommit: "\uBAA8\uB4E0 \uBCC0\uACBD\uC774 \uCEE4\uBC0B\uB418\uC5C8\uB098\uC694?",
903
- hintCommit: "git status \uD655\uC778",
904
- changelogUpdated: (version) => `CHANGELOG.md \uAC31\uC2E0\uB428 \u2014 [Unreleased] \u2192 [${version}] \uC139\uC158\uC73C\uB85C \uC774\uB3D9`,
905
- changelogNoUnreleased: "CHANGELOG.md\uC5D0 [Unreleased] \uC139\uC158\uC774 \uC5C6\uC5B4 \uC790\uB3D9 \uAC31\uC2E0\uC744 \uC2A4\uD0B5\uD588\uC5B4\uC694",
906
- changelogMissing: "CHANGELOG.md\uAC00 \uC5C6\uC5B4\uC694. \uB9CC\uB4E4\uBA74 ship\uC774 \uC790\uB3D9\uC73C\uB85C [Unreleased] \u2192 \uBC84\uC804 \uC139\uC158\uC73C\uB85C \uC62E\uACA8\uC90D\uB2C8\uB2E4."
907
- },
908
- mcp: {
909
- initTitle: "Cursor MCP \uC5F0\uB3D9 \uC124\uC815",
910
- serverStarted: "VHK MCP \uC11C\uBC84 \uC2DC\uC791\uB428"
911
- }
912
- };
913
- function lookup(path15) {
914
- const parts = path15.split(".");
915
- let cur = ko;
916
- for (const part of parts) {
917
- if (cur === null || typeof cur !== "object") return void 0;
918
- cur = cur[part];
919
- }
920
- return cur;
921
- }
922
- function t(key, ...args) {
923
- const value = lookup(key);
924
- if (typeof value === "function") {
925
- return value(...args);
926
- }
927
- if (typeof value === "string") return value;
928
- return key;
929
- }
700
+ import chalk18 from "chalk";
701
+ import inquirer9 from "inquirer";
930
702
 
931
703
  // src/commands/gate.ts
932
704
  import inquirer from "inquirer";
933
- import chalk2 from "chalk";
934
-
935
- // src/lib/next-step.ts
936
705
  import chalk from "chalk";
937
- function printNextStep(step) {
938
- console.log("");
939
- console.log(chalk.cyan.bold("\u2501\u2501\u2501 \uB2E4\uC74C\uC5D0 \uC774\uAC83\uB9CC \uD558\uC138\uC694 \u2501\u2501\u2501"));
940
- console.log("");
941
- console.log(` ${step.message}`);
942
- if (step.command) {
943
- console.log("");
944
- console.log(chalk.white.bgGray(" \uD130\uBBF8\uB110\uC5D0 \uBCF5\uBD99 "));
945
- console.log(chalk.green(` ${step.command}`));
946
- }
947
- if (step.cursorHint) {
948
- console.log("");
949
- console.log(chalk.white.bgBlue(" Cursor\uC5D0\uAC8C \uB9D0\uD558\uAE30 "));
950
- console.log(chalk.blue(` "${step.cursorHint}"`));
951
- }
952
- if (step.alternative) {
953
- console.log("");
954
- console.log(chalk.dim(` \uB610\uB294: ${step.alternative}`));
955
- }
956
- console.log("");
957
- console.log(chalk.cyan.bold("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
958
- console.log("");
959
- }
960
-
961
- // src/commands/gate.ts
962
706
  var GATE_QUESTIONS = [
963
707
  { id: 1, stage: "\uBB38\uC81C \uC815\uC758", question: "\uC774 \uC544\uC774\uB514\uC5B4\uAC00 \uD574\uACB0\uD558\uB294 \uBB38\uC81C\uB97C \uD55C \uBB38\uC7A5\uC73C\uB85C \uB9D0\uD574\uBCF4\uC138\uC694.", failIf: "\uD55C \uBB38\uC7A5 \uBD88\uAC00 \u2192 \uBBF8\uC131\uC219", quick: true },
964
708
  { id: 2, stage: "\uD575\uC2EC \uAE30\uB2A5", question: "\uB531 1\uAC1C \uAE30\uB2A5\uB9CC \uACE0\uB974\uBA74?", failIf: "2\uAC1C \uC774\uC0C1 \u2192 \uBC94\uC704 \uCD08\uACFC", quick: true },
@@ -980,7 +724,7 @@ function judgeGate(failCount, holdCount) {
980
724
  return "DROP";
981
725
  }
982
726
  async function gate() {
983
- console.log(chalk2.bold(`
727
+ console.log(chalk.bold(`
984
728
  ${ko.gate.title}
985
729
  `));
986
730
  const { mode } = await inquirer.prompt([{
@@ -999,33 +743,33 @@ ${ko.gate.title}
999
743
  name: "source",
1000
744
  message: ko.gate.skipSourcePrompt
1001
745
  }]);
1002
- console.log(chalk2.green.bold(`
746
+ console.log(chalk.green.bold(`
1003
747
  ${ko.gate.skipGo}`));
1004
- console.log(chalk2.dim(ko.gate.skipSourceLabel(source)));
748
+ console.log(chalk.dim(ko.gate.skipSourceLabel(source)));
1005
749
  return;
1006
750
  }
1007
751
  const questions = mode === "quick" ? GATE_QUESTIONS.filter((q) => q.quick) : GATE_QUESTIONS;
1008
752
  const total = questions.length;
1009
753
  const header = mode === "quick" ? ko.gate.quickHeader : ko.gate.fullHeader;
1010
- console.log(chalk2.dim(`
754
+ console.log(chalk.dim(`
1011
755
  ${header} ${ko.gate.modeCountSuffix(total)}
1012
756
  `));
1013
- console.log(chalk2.dim(`
757
+ console.log(chalk.dim(`
1014
758
  ${ko.gate.welcome}
1015
759
  `));
1016
- console.log(chalk2.dim(` ${ko.gate.ideaHint}`));
760
+ console.log(chalk.dim(` ${ko.gate.ideaHint}`));
1017
761
  const { idea } = await inquirer.prompt([
1018
762
  { type: "input", name: "idea", message: ko.gate.idea }
1019
763
  ]);
1020
- console.log(chalk2.dim(` ${ko.gate.painPointHint}`));
764
+ console.log(chalk.dim(` ${ko.gate.painPointHint}`));
1021
765
  const { painPoint } = await inquirer.prompt([
1022
766
  { type: "input", name: "painPoint", message: ko.gate.painPoint }
1023
767
  ]);
1024
- console.log(chalk2.dim(` ${ko.gate.edgeHint}`));
768
+ console.log(chalk.dim(` ${ko.gate.edgeHint}`));
1025
769
  const { edge } = await inquirer.prompt([
1026
770
  { type: "input", name: "edge", message: ko.gate.edge }
1027
771
  ]);
1028
- console.log(chalk2.dim(`
772
+ console.log(chalk.dim(`
1029
773
  ${ko.gate.checklistStart}
1030
774
  `));
1031
775
  let failCount = 0;
@@ -1033,7 +777,7 @@ ${ko.gate.checklistStart}
1033
777
  const results = [];
1034
778
  for (let i = 0; i < questions.length; i++) {
1035
779
  const q = questions[i];
1036
- if (q.hint) console.log(chalk2.dim(`${ko.gate.hintPrefix} ${q.hint}`));
780
+ if (q.hint) console.log(chalk.dim(`${ko.gate.hintPrefix} ${q.hint}`));
1037
781
  const { answer } = await inquirer.prompt([{
1038
782
  type: "input",
1039
783
  name: "answer",
@@ -1052,22 +796,22 @@ ${ko.gate.checklistStart}
1052
796
  if (status2 === "fail") failCount++;
1053
797
  if (status2 === "hold") holdCount++;
1054
798
  results.push({ id: q.id, stage: q.stage, status: status2, answer });
1055
- const icon = status2 === "pass" ? chalk2.green(ko.gate.statusPassLine) : status2 === "hold" ? chalk2.yellow(ko.gate.statusHoldLine) : chalk2.red(ko.gate.statusFailLine);
799
+ const icon = status2 === "pass" ? chalk.green(ko.gate.statusPassLine) : status2 === "hold" ? chalk.yellow(ko.gate.statusHoldLine) : chalk.red(ko.gate.statusFailLine);
1056
800
  console.log(icon);
1057
801
  }
1058
- console.log(chalk2.bold(`
802
+ console.log(chalk.bold(`
1059
803
  ${ko.gate.verdictTitle}
1060
804
  `));
1061
- console.log(`${ko.gate.ideaLabel} ${chalk2.cyan(idea)}`);
805
+ console.log(`${ko.gate.ideaLabel} ${chalk.cyan(idea)}`);
1062
806
  console.log(`${ko.gate.painPointLabel} ${painPoint}`);
1063
807
  console.log(`${ko.gate.edgeLabel} ${edge}`);
1064
808
  console.log(`${ko.gate.countLine(failCount, holdCount, total)}
1065
809
  `);
1066
810
  const verdict = judgeGate(failCount, holdCount);
1067
811
  if (verdict === "GO") {
1068
- console.log(chalk2.green.bold(ko.gate.go));
812
+ console.log(chalk.green.bold(ko.gate.go));
1069
813
  if (holdCount > 0) {
1070
- console.log(chalk2.yellow(ko.gate.holdRemainHint));
814
+ console.log(chalk.yellow(ko.gate.holdRemainHint));
1071
815
  }
1072
816
  printNextStep({
1073
817
  message: "\uC544\uC774\uB514\uC5B4 \uD1B5\uACFC! \uC774\uC81C \uD504\uB85C\uC81D\uD2B8\uB97C \uB9CC\uB4E4\uC5B4\uBCF4\uC138\uC694.",
@@ -1075,20 +819,20 @@ ${ko.gate.verdictTitle}
1075
819
  cursorHint: "\uD504\uB85C\uC81D\uD2B8 \uB9CC\uB4E4\uC5B4\uC918"
1076
820
  });
1077
821
  } else if (verdict === "REFINE") {
1078
- console.log(chalk2.yellow.bold(ko.gate.refine));
822
+ console.log(chalk.yellow.bold(ko.gate.refine));
1079
823
  printNextStep({
1080
824
  message: "\uC870\uAE08 \uB354 \uB2E4\uB4EC\uC740 \uD6C4 \uB2E4\uC2DC \uAC80\uC99D\uD574\uBCF4\uC138\uC694.",
1081
825
  command: "vhk \uAC80\uC99D",
1082
826
  cursorHint: "\uC544\uC774\uB514\uC5B4 \uB2E4\uC2DC \uAC80\uC99D\uD574\uC918"
1083
827
  });
1084
828
  } else {
1085
- console.log(chalk2.red.bold(ko.gate.drop));
829
+ console.log(chalk.red.bold(ko.gate.drop));
1086
830
  }
1087
831
  }
1088
832
 
1089
833
  // src/commands/init.ts
1090
834
  import inquirer2 from "inquirer";
1091
- import chalk5 from "chalk";
835
+ import chalk4 from "chalk";
1092
836
  import fs3 from "fs";
1093
837
  import path3 from "path";
1094
838
 
@@ -1304,7 +1048,7 @@ function COMMANDS_MD_TEMPLATE() {
1304
1048
  var import_ignore = __toESM(require_ignore(), 1);
1305
1049
  import fs from "fs";
1306
1050
  import path from "path";
1307
- import chalk3 from "chalk";
1051
+ import chalk2 from "chalk";
1308
1052
  function loadGitignore(rootDir) {
1309
1053
  const ig = (0, import_ignore.default)();
1310
1054
  const gitignorePath = path.join(rootDir, ".gitignore");
@@ -1377,7 +1121,7 @@ function printSecurityWarnings(rootDir = process.cwd()) {
1377
1121
  const result = checkProjectSecurity(rootDir);
1378
1122
  if (result.ok) return true;
1379
1123
  for (const w of result.warnings) {
1380
- console.log(chalk3.yellow(` \u26A0\uFE0F ${w}`));
1124
+ console.log(chalk2.yellow(` \u26A0\uFE0F ${w}`));
1381
1125
  }
1382
1126
  return false;
1383
1127
  }
@@ -1387,13 +1131,13 @@ function filterTrackedPaths(paths, rootDir = process.cwd()) {
1387
1131
  }
1388
1132
 
1389
1133
  // src/utils/logger.ts
1390
- import chalk4 from "chalk";
1134
+ import chalk3 from "chalk";
1391
1135
  var log = {
1392
- success: (msg) => console.log(chalk4.green(`\u2705 ${msg}`)),
1393
- error: (msg) => console.log(chalk4.red(`\u274C ${msg}`)),
1394
- warn: (msg) => console.log(chalk4.yellow(`\u26A0\uFE0F ${msg}`)),
1395
- info: (msg) => console.log(chalk4.blue(`\u2139\uFE0F ${msg}`)),
1396
- step: (msg) => console.log(chalk4.bold(`
1136
+ success: (msg) => console.log(chalk3.green(`\u2705 ${msg}`)),
1137
+ error: (msg) => console.log(chalk3.red(`\u274C ${msg}`)),
1138
+ warn: (msg) => console.log(chalk3.yellow(`\u26A0\uFE0F ${msg}`)),
1139
+ info: (msg) => console.log(chalk3.blue(`\u2139\uFE0F ${msg}`)),
1140
+ step: (msg) => console.log(chalk3.bold(`
1397
1141
  \u25B8 ${msg}`))
1398
1142
  };
1399
1143
 
@@ -1598,11 +1342,11 @@ async function collectAnswers(options, defaults = {}) {
1598
1342
  async function init(options = {}) {
1599
1343
  const skipGate = Boolean(options.skipGate || options.fromNotion);
1600
1344
  if (skipGate) {
1601
- console.log(chalk5.dim(`
1345
+ console.log(chalk4.dim(`
1602
1346
  ${ko.init.skipGate}
1603
1347
  `));
1604
1348
  }
1605
- console.log(chalk5.bold(`
1349
+ console.log(chalk4.bold(`
1606
1350
  ${ko.init.title}
1607
1351
  `));
1608
1352
  printSecurityWarnings();
@@ -1627,7 +1371,7 @@ ${ko.init.title}
1627
1371
  process.exit(1);
1628
1372
  }
1629
1373
  const stack = STACK_PRESETS[answers.type];
1630
- console.log(chalk5.dim(`
1374
+ console.log(chalk4.dim(`
1631
1375
  ${ko.init.recommendedStack} ${stack.join(" + ")}
1632
1376
  `));
1633
1377
  if (!options.yes) {
@@ -1663,21 +1407,21 @@ ${ko.init.recommendedStack} ${stack.join(" + ")}
1663
1407
  log.success(filePath);
1664
1408
  }
1665
1409
  await writeInitExtras(cwd);
1666
- console.log(chalk5.bold.green(`
1410
+ console.log(chalk4.bold.green(`
1667
1411
  ${ko.init.done}`));
1668
- console.log(chalk5.dim(`
1412
+ console.log(chalk4.dim(`
1669
1413
  ${ko.init.nextSteps}`));
1670
1414
  if (options.fromNotion) {
1671
1415
  console.log(` 1. ${ko.init.notionReviewHint}`);
1672
1416
  console.log(` 2. ${ko.init.gitHintLabel}`);
1673
- console.log(` ${chalk5.cyan(ko.init.gitHintCommand)}`);
1417
+ console.log(` ${chalk4.cyan(ko.init.gitHintCommand)}`);
1674
1418
  console.log(` 3. ${ko.init.startDev}
1675
1419
  `);
1676
1420
  } else {
1677
1421
  console.log(` 1. ${ko.init.fillHint}`);
1678
1422
  console.log(` 2. ${ko.init.prdHint}`);
1679
1423
  console.log(` 3. ${ko.init.gitHintLabel}`);
1680
- console.log(` ${chalk5.cyan(ko.init.gitHintCommand)}`);
1424
+ console.log(` ${chalk4.cyan(ko.init.gitHintCommand)}`);
1681
1425
  console.log(` 4. ${ko.init.startDev}
1682
1426
  `);
1683
1427
  }
@@ -1758,7 +1502,7 @@ async function writeInitExtras(projectDir) {
1758
1502
 
1759
1503
  // src/commands/recap.ts
1760
1504
  import inquirer3 from "inquirer";
1761
- import chalk6 from "chalk";
1505
+ import chalk5 from "chalk";
1762
1506
  import fs5 from "fs";
1763
1507
  import path6 from "path";
1764
1508
 
@@ -1917,40 +1661,40 @@ function createAdrFile(cwd, title, context, decision, consequences) {
1917
1661
 
1918
1662
  // src/commands/recap.ts
1919
1663
  async function recap(options = {}) {
1920
- console.log(chalk6.bold(`
1664
+ console.log(chalk5.bold(`
1921
1665
  ${ko.recap.title}
1922
1666
  `));
1923
1667
  if (!await isGitRepo()) {
1924
- console.log(chalk6.red(ko.recap.noRepo));
1668
+ console.log(chalk5.red(ko.recap.noRepo));
1925
1669
  return;
1926
1670
  }
1927
1671
  printSecurityWarnings();
1928
- console.log(chalk6.dim(`${ko.recap.analyzing}
1672
+ console.log(chalk5.dim(`${ko.recap.analyzing}
1929
1673
  `));
1930
1674
  const since = options.since || (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1931
1675
  const diff2 = await getSessionDiff(since);
1932
1676
  const commits = await getRecentCommits(10, since);
1933
1677
  if (diff2.filesChanged === 0 && commits.length === 0) {
1934
- console.log(chalk6.yellow(ko.recap.noChanges));
1678
+ console.log(chalk5.yellow(ko.recap.noChanges));
1935
1679
  return;
1936
1680
  }
1937
- console.log(chalk6.bold("\u{1F4CA} \uBCC0\uACBD \uC694\uC57D:"));
1938
- console.log(` \uD30C\uC77C: ${chalk6.cyan(String(diff2.filesChanged))}\uAC1C \uBCC0\uACBD`);
1939
- console.log(` \uCD94\uAC00: ${chalk6.green("+" + diff2.insertions)} / \uC0AD\uC81C: ${chalk6.red("-" + diff2.deletions)}`);
1681
+ console.log(chalk5.bold("\u{1F4CA} \uBCC0\uACBD \uC694\uC57D:"));
1682
+ console.log(` \uD30C\uC77C: ${chalk5.cyan(String(diff2.filesChanged))}\uAC1C \uBCC0\uACBD`);
1683
+ console.log(` \uCD94\uAC00: ${chalk5.green("+" + diff2.insertions)} / \uC0AD\uC81C: ${chalk5.red("-" + diff2.deletions)}`);
1940
1684
  if (diff2.files.length > 0) {
1941
- console.log(chalk6.dim("\n \uBCC0\uACBD \uD30C\uC77C:"));
1685
+ console.log(chalk5.dim("\n \uBCC0\uACBD \uD30C\uC77C:"));
1942
1686
  diff2.files.slice(0, 15).forEach((f) => {
1943
- const icon = f.status === "new" ? chalk6.green("\u{1F195}") : f.status === "deleted" ? chalk6.red("\u{1F5D1}\uFE0F") : chalk6.yellow("\u270F\uFE0F");
1687
+ const icon = f.status === "new" ? chalk5.green("\u{1F195}") : f.status === "deleted" ? chalk5.red("\u{1F5D1}\uFE0F") : chalk5.yellow("\u270F\uFE0F");
1944
1688
  console.log(` ${icon} ${f.file}`);
1945
1689
  });
1946
1690
  if (diff2.files.length > 15) {
1947
- console.log(chalk6.dim(` ... \uC678 ${diff2.files.length - 15}\uAC1C`));
1691
+ console.log(chalk5.dim(` ... \uC678 ${diff2.files.length - 15}\uAC1C`));
1948
1692
  }
1949
1693
  }
1950
1694
  if (commits.length > 0) {
1951
- console.log(chalk6.dim("\n \uCD5C\uADFC \uCEE4\uBC0B:"));
1695
+ console.log(chalk5.dim("\n \uCD5C\uADFC \uCEE4\uBC0B:"));
1952
1696
  commits.slice(0, 5).forEach((c) => {
1953
- console.log(chalk6.dim(` \u2022 ${c.message}`));
1697
+ console.log(chalk5.dim(` \u2022 ${c.message}`));
1954
1698
  });
1955
1699
  }
1956
1700
  console.log("");
@@ -2018,11 +1762,11 @@ ${ko.recap.title}
2018
1762
  fs5.writeFileSync(filePath, content, "utf-8");
2019
1763
  const adrCandidates = detectAdrCandidates(diff2);
2020
1764
  if (adrCandidates.length > 0) {
2021
- console.log(chalk6.cyan.bold(`
1765
+ console.log(chalk5.cyan.bold(`
2022
1766
  ${ko.recap.adrDetected} (${adrCandidates.length}\uAC74)`));
2023
1767
  for (const candidate of adrCandidates) {
2024
- console.log(chalk6.cyan(` \u2022 ${candidate.title}: ${candidate.context}`));
2025
- candidate.files.forEach((f) => console.log(chalk6.dim(` ${f}`)));
1768
+ console.log(chalk5.cyan(` \u2022 ${candidate.title}: ${candidate.context}`));
1769
+ candidate.files.forEach((f) => console.log(chalk5.dim(` ${f}`)));
2026
1770
  }
2027
1771
  const { createAdr } = await inquirer3.prompt([{
2028
1772
  type: "confirm",
@@ -2052,17 +1796,17 @@ ${ko.recap.adrDetected} (${adrCandidates.length}\uAC74)`));
2052
1796
  adrAnswers.decision,
2053
1797
  adrAnswers.consequences
2054
1798
  );
2055
- console.log(chalk6.green(` \u2705 ADR \uC0DD\uC131: ${path6.relative(process.cwd(), adrPath)}`));
1799
+ console.log(chalk5.green(` \u2705 ADR \uC0DD\uC131: ${path6.relative(process.cwd(), adrPath)}`));
2056
1800
  }
2057
1801
  }
2058
1802
  }
2059
1803
  const troubleshootingKeywords = /fix|bug|error|crash|hotfix|patch|revert|트러블|에러|버그|수정|핫픽스/i;
2060
1804
  const troubleCommits = commits.filter((c) => troubleshootingKeywords.test(c.message));
2061
1805
  if (troubleCommits.length > 0) {
2062
- console.log(chalk6.yellow.bold(`
1806
+ console.log(chalk5.yellow.bold(`
2063
1807
  ${ko.recap.troubleDetected} (${troubleCommits.length}\uAC74)`));
2064
1808
  troubleCommits.forEach((c) => {
2065
- console.log(chalk6.dim(` \u2022 ${c.message}`));
1809
+ console.log(chalk5.dim(` \u2022 ${c.message}`));
2066
1810
  });
2067
1811
  const { createTroubleshoot } = await inquirer3.prompt([{
2068
1812
  type: "confirm",
@@ -2113,12 +1857,12 @@ ${ko.recap.troubleDetected} (${troubleCommits.length}\uAC74)`));
2113
1857
  `*Generated by \`vhk recap\` at ${(/* @__PURE__ */ new Date()).toISOString()}*`
2114
1858
  ].join("\n");
2115
1859
  fs5.writeFileSync(tsFilePath, tsContent, "utf-8");
2116
- console.log(chalk6.green(` \u2705 \uD2B8\uB7EC\uBE14\uC288\uD305 \uBB38\uC11C \uC0DD\uC131: ${path6.relative(process.cwd(), tsFilePath)}`));
1860
+ console.log(chalk5.green(` \u2705 \uD2B8\uB7EC\uBE14\uC288\uD305 \uBB38\uC11C \uC0DD\uC131: ${path6.relative(process.cwd(), tsFilePath)}`));
2117
1861
  }
2118
1862
  }
2119
- console.log(chalk6.green.bold(`
1863
+ console.log(chalk5.green.bold(`
2120
1864
  ${ko.recap.done}`));
2121
- console.log(chalk6.dim(` \u{1F4C4} ${path6.relative(process.cwd(), filePath)}`));
1865
+ console.log(chalk5.dim(` \u{1F4C4} ${path6.relative(process.cwd(), filePath)}`));
2122
1866
  const claudeMdPath = path6.join(process.cwd(), "CLAUDE.md");
2123
1867
  if (fs5.existsSync(claudeMdPath)) {
2124
1868
  const { updateClaude } = await inquirer3.prompt([{
@@ -2138,7 +1882,7 @@ ${ko.recap.done}`));
2138
1882
  `- **\uB2E4\uC74C \uC561\uC158:** ${answers.nextTodo}`
2139
1883
  );
2140
1884
  fs5.writeFileSync(claudeMdPath, claudeContent, "utf-8");
2141
- console.log(chalk6.green(" \u2705 CLAUDE.md \uC5C5\uB370\uC774\uD2B8 \uC644\uB8CC"));
1885
+ console.log(chalk5.green(" \u2705 CLAUDE.md \uC5C5\uB370\uC774\uD2B8 \uC644\uB8CC"));
2142
1886
  }
2143
1887
  }
2144
1888
  const gitSaveCmd = process.platform === "win32" ? 'git add .; git commit -m "recap: \uC138\uC158 \uAE30\uB85D"' : 'git add . && git commit -m "recap: \uC138\uC158 \uAE30\uB85D"';
@@ -2150,7 +1894,7 @@ ${ko.recap.done}`));
2150
1894
  }
2151
1895
 
2152
1896
  // src/commands/sync.ts
2153
- import chalk7 from "chalk";
1897
+ import chalk6 from "chalk";
2154
1898
  import fs6 from "fs";
2155
1899
  import path7 from "path";
2156
1900
  var CURSORRULES_KEYS = ["\uCF54\uB529 \uADDC\uCE59", "\uAE30\uC220 \uC2A4\uD0DD", "\uC544\uD0A4\uD14D\uCC98", "\uB514\uC790\uC778", "Anti-patterns", "\uCEE4\uBC0B"];
@@ -2220,32 +1964,32 @@ function toClaudeMd(sections, existing) {
2220
1964
  return lines.join("\n");
2221
1965
  }
2222
1966
  async function sync() {
2223
- console.log(chalk7.bold(`
1967
+ console.log(chalk6.bold(`
2224
1968
  ${ko.sync.title}
2225
1969
  `));
2226
1970
  const cwd = process.cwd();
2227
1971
  const rulesPath = path7.join(cwd, "RULES.md");
2228
1972
  if (!fs6.existsSync(rulesPath)) {
2229
- console.log(chalk7.yellow(ko.sync.noRules));
2230
- console.log(chalk7.dim(" RULES.md\uB294 \uD504\uB85C\uC81D\uD2B8 \uADDC\uCE59\uC758 Single Source of Truth\uC785\uB2C8\uB2E4."));
2231
- console.log(chalk7.dim(" \uC0DD\uC131\uD558\uB824\uBA74: vhk init \uC2E4\uD589 \uD6C4 RULES.md\uB97C \uC791\uC131\uD558\uC138\uC694."));
1973
+ console.log(chalk6.yellow(ko.sync.noRules));
1974
+ console.log(chalk6.dim(" RULES.md\uB294 \uD504\uB85C\uC81D\uD2B8 \uADDC\uCE59\uC758 Single Source of Truth\uC785\uB2C8\uB2E4."));
1975
+ console.log(chalk6.dim(" \uC0DD\uC131\uD558\uB824\uBA74: vhk init \uC2E4\uD589 \uD6C4 RULES.md\uB97C \uC791\uC131\uD558\uC138\uC694."));
2232
1976
  console.log("");
2233
- console.log(chalk7.dim(" RULES.md \uAE30\uBCF8 \uAD6C\uC870:"));
2234
- console.log(chalk7.dim(" ## \uD504\uB85C\uC81D\uD2B8 \uC815\uCCB4\uC131"));
2235
- console.log(chalk7.dim(" ## \uAE30\uC220 \uC2A4\uD0DD"));
2236
- console.log(chalk7.dim(" ## \uCF54\uB529 \uADDC\uCE59"));
2237
- console.log(chalk7.dim(" ## \uAE30\uB85D \uADDC\uCE59"));
2238
- console.log(chalk7.dim(" ## \uCEE4\uBC0B \uCEE8\uBCA4\uC158"));
1977
+ console.log(chalk6.dim(" RULES.md \uAE30\uBCF8 \uAD6C\uC870:"));
1978
+ console.log(chalk6.dim(" ## \uD504\uB85C\uC81D\uD2B8 \uC815\uCCB4\uC131"));
1979
+ console.log(chalk6.dim(" ## \uAE30\uC220 \uC2A4\uD0DD"));
1980
+ console.log(chalk6.dim(" ## \uCF54\uB529 \uADDC\uCE59"));
1981
+ console.log(chalk6.dim(" ## \uAE30\uB85D \uADDC\uCE59"));
1982
+ console.log(chalk6.dim(" ## \uCEE4\uBC0B \uCEE8\uBCA4\uC158"));
2239
1983
  return;
2240
1984
  }
2241
1985
  const rulesContent = fs6.readFileSync(rulesPath, "utf-8");
2242
1986
  const sections = parseRulesMd(rulesContent);
2243
- console.log(chalk7.dim(` \u{1F4C4} RULES.md \uD30C\uC2F1 \uC644\uB8CC \u2014 ${sections.length}\uAC1C \uC139\uC158`));
1987
+ console.log(chalk6.dim(` \u{1F4C4} RULES.md \uD30C\uC2F1 \uC644\uB8CC \u2014 ${sections.length}\uAC1C \uC139\uC158`));
2244
1988
  const firstLine = rulesContent.split("\n")[0];
2245
1989
  const projectName = firstLine.replace(/^#\s*/, "").replace(/\s*—.*/, "").trim() || "Project";
2246
1990
  const cursorrulesPath = path7.join(cwd, ".cursorrules");
2247
1991
  fs6.writeFileSync(cursorrulesPath, toCursorrules(sections, projectName), "utf-8");
2248
- console.log(chalk7.green(` ${ko.sync.cursorrulesDone}`));
1992
+ console.log(chalk6.green(` ${ko.sync.cursorrulesDone}`));
2249
1993
  const claudePath = path7.join(cwd, "CLAUDE.md");
2250
1994
  const existingClaude = fs6.existsSync(claudePath) ? fs6.readFileSync(claudePath, "utf-8") : `# \uAE30\uB85D \uADDC\uCE59 (${projectName})
2251
1995
 
@@ -2255,11 +1999,11 @@ ${ko.sync.title}
2255
1999
  - **\uB2E4\uC74C \uC561\uC158:** __FILL__
2256
2000
  - **\uB9C8\uC9C0\uB9C9 \uC5C5\uB370\uC774\uD2B8:** ${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}`;
2257
2001
  fs6.writeFileSync(claudePath, toClaudeMd(sections, existingClaude), "utf-8");
2258
- console.log(chalk7.green(` ${ko.sync.claudeDone}`));
2259
- console.log(chalk7.bold.green(`
2002
+ console.log(chalk6.green(` ${ko.sync.claudeDone}`));
2003
+ console.log(chalk6.bold.green(`
2260
2004
  ${ko.sync.done}`));
2261
- console.log(chalk7.dim(" RULES.md (\uC6D0\uBCF8) \u2192 .cursorrules + CLAUDE.md (\uC790\uB3D9 \uC0DD\uC131)"));
2262
- console.log(chalk7.dim(" \uADDC\uCE59 \uBCC0\uACBD\uC740 \uD56D\uC0C1 RULES.md\uC5D0\uC11C\uB9CC \uD558\uC138\uC694."));
2005
+ console.log(chalk6.dim(" RULES.md (\uC6D0\uBCF8) \u2192 .cursorrules + CLAUDE.md (\uC790\uB3D9 \uC0DD\uC131)"));
2006
+ console.log(chalk6.dim(" \uADDC\uCE59 \uBCC0\uACBD\uC740 \uD56D\uC0C1 RULES.md\uC5D0\uC11C\uB9CC \uD558\uC138\uC694."));
2263
2007
  printNextStep({
2264
2008
  message: "\uADDC\uCE59 \uB3D9\uAE30\uD654 \uC644\uB8CC! \uC774\uC81C Cursor\uAC00 \uC0C8 \uADDC\uCE59\uC744 \uB530\uB985\uB2C8\uB2E4.",
2265
2009
  command: "vhk \uC810\uAC80",
@@ -2268,7 +2012,7 @@ ${ko.sync.done}`));
2268
2012
  }
2269
2013
 
2270
2014
  // src/commands/check.ts
2271
- import chalk8 from "chalk";
2015
+ import chalk7 from "chalk";
2272
2016
  import path9 from "path";
2273
2017
  import fs8 from "fs";
2274
2018
 
@@ -2427,22 +2171,22 @@ function escapeRegex(str) {
2427
2171
 
2428
2172
  // src/commands/check.ts
2429
2173
  async function check() {
2430
- console.log(chalk8.bold(`
2174
+ console.log(chalk7.bold(`
2431
2175
  ${ko.check.title}
2432
2176
  `));
2433
2177
  const cwd = process.cwd();
2434
2178
  const rulesPath = path9.join(cwd, "RULES.md");
2435
2179
  if (!fs8.existsSync(rulesPath)) {
2436
- console.log(chalk8.yellow(ko.check.noRules));
2437
- console.log(chalk8.dim(" vhk init\uC73C\uB85C \uC2DC\uC791\uD558\uAC70\uB098 RULES.md\uB97C \uB9CC\uB4E4\uC5B4 \uBCF4\uC138\uC694."));
2180
+ console.log(chalk7.yellow(ko.check.noRules));
2181
+ console.log(chalk7.dim(" vhk init\uC73C\uB85C \uC2DC\uC791\uD558\uAC70\uB098 RULES.md\uB97C \uB9CC\uB4E4\uC5B4 \uBCF4\uC138\uC694."));
2438
2182
  return;
2439
2183
  }
2440
2184
  const rules = parseRules(rulesPath);
2441
- console.log(chalk8.dim(` \u{1F4CF} ${rules.length}\uAC1C \uAC80\uC99D \uAC00\uB2A5\uD55C \uADDC\uCE59 \uAC10\uC9C0
2185
+ console.log(chalk7.dim(` \u{1F4CF} ${rules.length}\uAC1C \uAC80\uC99D \uAC00\uB2A5\uD55C \uADDC\uCE59 \uAC10\uC9C0
2442
2186
  `));
2443
2187
  if (rules.length === 0) {
2444
- console.log(chalk8.yellow(ko.check.noAutoRules));
2445
- console.log(chalk8.dim(" RULES.md\uC5D0 \uD30C\uC77C \uC774\uB984\xB7\uD3F4\uB354 \uADDC\uCE59\uC744 \uC801\uC73C\uBA74 \uC790\uB3D9\uC73C\uB85C \uC810\uAC80\uD574\uC694."));
2188
+ console.log(chalk7.yellow(ko.check.noAutoRules));
2189
+ console.log(chalk7.dim(" RULES.md\uC5D0 \uD30C\uC77C \uC774\uB984\xB7\uD3F4\uB354 \uADDC\uCE59\uC744 \uC801\uC73C\uBA74 \uC790\uB3D9\uC73C\uB85C \uC810\uAC80\uD574\uC694."));
2446
2190
  return;
2447
2191
  }
2448
2192
  const allViolations = [];
@@ -2450,13 +2194,13 @@ ${ko.check.title}
2450
2194
  for (const rule of rules) {
2451
2195
  const violations = rule.check(cwd);
2452
2196
  if (violations.length === 0) {
2453
- console.log(chalk8.green(` \u2705 ${rule.id}`) + chalk8.dim(` \u2014 ${rule.description.slice(0, 60)}`));
2197
+ console.log(chalk7.green(` \u2705 ${rule.id}`) + chalk7.dim(` \u2014 ${rule.description.slice(0, 60)}`));
2454
2198
  passCount++;
2455
2199
  } else {
2456
- console.log(chalk8.red(` \u274C ${rule.id}`) + chalk8.dim(` \u2014 ${violations.length}\uAC74 \uC704\uBC18`));
2200
+ console.log(chalk7.red(` \u274C ${rule.id}`) + chalk7.dim(` \u2014 ${violations.length}\uAC74 \uC704\uBC18`));
2457
2201
  violations.forEach((v) => {
2458
- const loc = v.file ? chalk8.dim(` (${v.file}${v.line ? ":" + v.line : ""})`) : "";
2459
- const icon = v.severity === "error" ? chalk8.red("\u2716") : v.severity === "warning" ? chalk8.yellow("\u26A0") : chalk8.blue("\u2139");
2202
+ const loc = v.file ? chalk7.dim(` (${v.file}${v.line ? ":" + v.line : ""})`) : "";
2203
+ const icon = v.severity === "error" ? chalk7.red("\u2716") : v.severity === "warning" ? chalk7.yellow("\u26A0") : chalk7.blue("\u2139");
2460
2204
  console.log(` ${icon} ${v.message}${loc}`);
2461
2205
  });
2462
2206
  allViolations.push(...violations);
@@ -2466,17 +2210,17 @@ ${ko.check.title}
2466
2210
  const errors = allViolations.filter((v) => v.severity === "error").length;
2467
2211
  const warnings = allViolations.filter((v) => v.severity === "warning").length;
2468
2212
  if (allViolations.length === 0) {
2469
- console.log(chalk8.green.bold(`${ko.check.allPassed} (${passCount}/${rules.length})`));
2213
+ console.log(chalk7.green.bold(`${ko.check.allPassed} (${passCount}/${rules.length})`));
2470
2214
  printNextStep({
2471
2215
  message: "\uBAA8\uB4E0 \uADDC\uCE59 \uD1B5\uACFC! \uBCF4\uC548 \uC2A4\uCE94\uB3C4 \uD574\uBCFC\uAE4C\uC694?",
2472
2216
  command: "vhk \uBCF4\uC548 scan",
2473
2217
  cursorHint: "\uBCF4\uC548 \uC2A4\uCE94 \uB3CC\uB824\uC918"
2474
2218
  });
2475
2219
  } else {
2476
- console.log(chalk8.bold(ko.check.summary));
2477
- console.log(` \uADDC\uCE59: ${chalk8.cyan(String(rules.length))}\uAC1C | \uD1B5\uACFC: ${chalk8.green(String(passCount))}\uAC1C | \uC704\uBC18: ${chalk8.red(String(allViolations.length))}\uAC74`);
2478
- if (errors > 0) console.log(` ${chalk8.red(`\u2716 ${errors}\uAC1C \uC5D0\uB7EC`)}`);
2479
- if (warnings > 0) console.log(` ${chalk8.yellow(`\u26A0 ${warnings}\uAC1C \uACBD\uACE0`)}`);
2220
+ console.log(chalk7.bold(ko.check.summary));
2221
+ console.log(` \uADDC\uCE59: ${chalk7.cyan(String(rules.length))}\uAC1C | \uD1B5\uACFC: ${chalk7.green(String(passCount))}\uAC1C | \uC704\uBC18: ${chalk7.red(String(allViolations.length))}\uAC74`);
2222
+ if (errors > 0) console.log(` ${chalk7.red(`\u2716 ${errors}\uAC1C \uC5D0\uB7EC`)}`);
2223
+ if (warnings > 0) console.log(` ${chalk7.yellow(`\u26A0 ${warnings}\uAC1C \uACBD\uACE0`)}`);
2480
2224
  printNextStep({
2481
2225
  message: "\uC704\uBC18 \uD56D\uBAA9\uC744 \uC218\uC815\uD55C \uD6C4 \uB2E4\uC2DC \uC810\uAC80\uD558\uC138\uC694.",
2482
2226
  command: "vhk \uC810\uAC80",
@@ -2489,7 +2233,7 @@ ${ko.check.title}
2489
2233
  }
2490
2234
 
2491
2235
  // src/commands/secure.ts
2492
- import chalk9 from "chalk";
2236
+ import chalk8 from "chalk";
2493
2237
  import fs11 from "fs";
2494
2238
  import path11 from "path";
2495
2239
 
@@ -2690,32 +2434,32 @@ function filterSevereFindings(findings) {
2690
2434
 
2691
2435
  // src/commands/secure.ts
2692
2436
  async function secure() {
2693
- console.log(chalk9.bold(`
2437
+ console.log(chalk8.bold(`
2694
2438
  ${ko.secure.title}
2695
2439
  `));
2696
2440
  const cwd = process.cwd();
2697
2441
  const gitignorePath = path11.join(cwd, ".gitignore");
2698
2442
  const hasGitignore = fs11.existsSync(gitignorePath);
2699
2443
  if (!hasGitignore) {
2700
- console.log(chalk9.yellow(` ${ko.secure.noGitignore}`));
2701
- console.log(chalk9.dim(" .env \uD30C\uC77C\uC774 \uCEE4\uBC0B\uB420 \uC218 \uC788\uC2B5\uB2C8\uB2E4.\n"));
2444
+ console.log(chalk8.yellow(` ${ko.secure.noGitignore}`));
2445
+ console.log(chalk8.dim(" .env \uD30C\uC77C\uC774 \uCEE4\uBC0B\uB420 \uC218 \uC788\uC2B5\uB2C8\uB2E4.\n"));
2702
2446
  } else {
2703
2447
  const gitignoreContent = fs11.readFileSync(gitignorePath, "utf-8");
2704
2448
  if (!gitignoreContent.includes(".env")) {
2705
- console.log(chalk9.yellow(` ${ko.secure.noEnvInGitignore}`));
2706
- console.log(chalk9.dim(" \uCD94\uAC00\uB97C \uAD8C\uC7A5\uD569\uB2C8\uB2E4.\n"));
2449
+ console.log(chalk8.yellow(` ${ko.secure.noEnvInGitignore}`));
2450
+ console.log(chalk8.dim(" \uCD94\uAC00\uB97C \uAD8C\uC7A5\uD569\uB2C8\uB2E4.\n"));
2707
2451
  }
2708
2452
  }
2709
- console.log(chalk9.dim(` ${ko.secure.scanning}
2453
+ console.log(chalk8.dim(` ${ko.secure.scanning}
2710
2454
  `));
2711
2455
  const { findings, scannedFiles, truncated } = scanProjectForSecrets(cwd);
2712
- console.log(chalk9.dim(` \u{1F4C2} ${scannedFiles}\uAC1C \uD30C\uC77C \uC2A4\uCE94 \uC644\uB8CC (lock\xB7node_modules\xB7>${MAX_SCAN_FILE_BYTES / 1024}KB \uC81C\uC678)`));
2456
+ console.log(chalk8.dim(` \u{1F4C2} ${scannedFiles}\uAC1C \uD30C\uC77C \uC2A4\uCE94 \uC644\uB8CC (lock\xB7node_modules\xB7>${MAX_SCAN_FILE_BYTES / 1024}KB \uC81C\uC678)`));
2713
2457
  if (truncated) {
2714
- console.log(chalk9.yellow(` \u26A0\uFE0F \uACB0\uACFC ${MAX_SECRET_FINDINGS}\uAC74\uC5D0\uC11C \uCD9C\uB825\uC744 \uC81C\uD55C\uD588\uC2B5\uB2C8\uB2E4. lock \uD30C\uC77C \uB4F1\uC740 \uC790\uB3D9 \uC81C\uC678\uB429\uB2C8\uB2E4.`));
2458
+ console.log(chalk8.yellow(` \u26A0\uFE0F \uACB0\uACFC ${MAX_SECRET_FINDINGS}\uAC74\uC5D0\uC11C \uCD9C\uB825\uC744 \uC81C\uD55C\uD588\uC2B5\uB2C8\uB2E4. lock \uD30C\uC77C \uB4F1\uC740 \uC790\uB3D9 \uC81C\uC678\uB429\uB2C8\uB2E4.`));
2715
2459
  }
2716
2460
  console.log("");
2717
2461
  if (findings.length === 0) {
2718
- console.log(chalk9.green.bold(` ${ko.secure.clean}`));
2462
+ console.log(chalk8.green.bold(` ${ko.secure.clean}`));
2719
2463
  printNextStep({
2720
2464
  message: "\uBCF4\uC548 \uC774\uC0C1 \uC5C6\uC74C! \uAE68\uB057\uD569\uB2C8\uB2E4.",
2721
2465
  command: "vhk \uC815\uB9AC",
@@ -2727,43 +2471,43 @@ ${ko.secure.title}
2727
2471
  const high = findings.filter((f) => f.severity === "high");
2728
2472
  const medium = findings.filter((f) => f.severity === "medium");
2729
2473
  if (critical.length > 0) {
2730
- console.log(chalk9.red.bold(` \u{1F6A8} CRITICAL \u2014 ${critical.length}\uAC74`));
2474
+ console.log(chalk8.red.bold(` \u{1F6A8} CRITICAL \u2014 ${critical.length}\uAC74`));
2731
2475
  critical.forEach((f) => {
2732
- console.log(chalk9.red(` \u2716 ${f.patternName}`));
2733
- console.log(chalk9.dim(` ${f.file}:${f.line} \u2192 ${f.match}`));
2476
+ console.log(chalk8.red(` \u2716 ${f.patternName}`));
2477
+ console.log(chalk8.dim(` ${f.file}:${f.line} \u2192 ${f.match}`));
2734
2478
  });
2735
2479
  console.log("");
2736
2480
  }
2737
2481
  if (high.length > 0) {
2738
- console.log(chalk9.yellow.bold(` \u26A0\uFE0F HIGH \u2014 ${high.length}\uAC74`));
2482
+ console.log(chalk8.yellow.bold(` \u26A0\uFE0F HIGH \u2014 ${high.length}\uAC74`));
2739
2483
  high.forEach((f) => {
2740
- console.log(chalk9.yellow(` \u26A0 ${f.patternName}`));
2741
- console.log(chalk9.dim(` ${f.file}:${f.line} \u2192 ${f.match}`));
2484
+ console.log(chalk8.yellow(` \u26A0 ${f.patternName}`));
2485
+ console.log(chalk8.dim(` ${f.file}:${f.line} \u2192 ${f.match}`));
2742
2486
  });
2743
2487
  console.log("");
2744
2488
  }
2745
2489
  if (medium.length > 0) {
2746
- console.log(chalk9.blue.bold(` \u2139 MEDIUM \u2014 ${medium.length}\uAC74`));
2490
+ console.log(chalk8.blue.bold(` \u2139 MEDIUM \u2014 ${medium.length}\uAC74`));
2747
2491
  medium.forEach((f) => {
2748
- console.log(chalk9.blue(` \u2139 ${f.patternName}`));
2749
- console.log(chalk9.dim(` ${f.file}:${f.line} \u2192 ${f.match}`));
2492
+ console.log(chalk8.blue(` \u2139 ${f.patternName}`));
2493
+ console.log(chalk8.dim(` ${f.file}:${f.line} \u2192 ${f.match}`));
2750
2494
  });
2751
2495
  console.log("");
2752
2496
  }
2753
- console.log(chalk9.bold(` ${ko.secure.summary}`));
2754
- console.log(` \uCD1D ${chalk9.red(String(findings.length))}\uAC74 \uAC10\uC9C0 | CRITICAL: ${critical.length} | HIGH: ${high.length} | MEDIUM: ${medium.length}`);
2497
+ console.log(chalk8.bold(` ${ko.secure.summary}`));
2498
+ console.log(` \uCD1D ${chalk8.red(String(findings.length))}\uAC74 \uAC10\uC9C0 | CRITICAL: ${critical.length} | HIGH: ${high.length} | MEDIUM: ${medium.length}`);
2755
2499
  console.log("");
2756
- console.log(chalk9.dim(" \u{1F4A1} \uC870\uCE58 \uBC29\uBC95:"));
2757
- console.log(chalk9.dim(" 1. \uD574\uB2F9 \uD30C\uC77C\uC5D0\uC11C \uC2DC\uD06C\uB9BF\uC744 \uC81C\uAC70\uD558\uACE0 \uD658\uACBD\uBCC0\uC218\uB85C \uC774\uB3D9"));
2758
- console.log(chalk9.dim(" 2. git history\uC5D0\uC11C\uB3C4 \uC81C\uAC70: git filter-branch \uB610\uB294 BFG Repo-Cleaner"));
2759
- console.log(chalk9.dim(" 3. \uC720\uCD9C\uB41C \uD0A4\uB294 \uC989\uC2DC \uD3D0\uAE30\uD558\uACE0 \uC7AC\uBC1C\uAE09\n"));
2500
+ console.log(chalk8.dim(" \u{1F4A1} \uC870\uCE58 \uBC29\uBC95:"));
2501
+ console.log(chalk8.dim(" 1. \uD574\uB2F9 \uD30C\uC77C\uC5D0\uC11C \uC2DC\uD06C\uB9BF\uC744 \uC81C\uAC70\uD558\uACE0 \uD658\uACBD\uBCC0\uC218\uB85C \uC774\uB3D9"));
2502
+ console.log(chalk8.dim(" 2. git history\uC5D0\uC11C\uB3C4 \uC81C\uAC70: git filter-branch \uB610\uB294 BFG Repo-Cleaner"));
2503
+ console.log(chalk8.dim(" 3. \uC720\uCD9C\uB41C \uD0A4\uB294 \uC989\uC2DC \uD3D0\uAE30\uD558\uACE0 \uC7AC\uBC1C\uAE09\n"));
2760
2504
  if (critical.length > 0 || high.length > 0) {
2761
2505
  process.exitCode = 1;
2762
2506
  }
2763
2507
  }
2764
2508
 
2765
2509
  // src/commands/doctor.ts
2766
- import chalk10 from "chalk";
2510
+ import chalk9 from "chalk";
2767
2511
  import { execSync } from "child_process";
2768
2512
  import fs12 from "fs";
2769
2513
  import path12 from "path";
@@ -2816,7 +2560,7 @@ function compareSemver(a, b) {
2816
2560
  return a3 - b3;
2817
2561
  }
2818
2562
  async function doctor() {
2819
- console.log(chalk10.bold(`
2563
+ console.log(chalk9.bold(`
2820
2564
  ${ko.doctor.title}
2821
2565
  `));
2822
2566
  const checks = [
@@ -2828,30 +2572,30 @@ ${ko.doctor.title}
2828
2572
  let allOk = true;
2829
2573
  for (const check2 of checks) {
2830
2574
  if (check2.ok) {
2831
- console.log(chalk10.green(` \u2705 ${check2.name}`) + chalk10.dim(` \u2014 ${check2.version}`));
2575
+ console.log(chalk9.green(` \u2705 ${check2.name}`) + chalk9.dim(` \u2014 ${check2.version}`));
2832
2576
  } else {
2833
- console.log(chalk10.red(` \u274C ${check2.name} \uC5C6\uC74C`));
2834
- console.log(chalk10.dim(` \u2192 ${check2.hint}`));
2577
+ console.log(chalk9.red(` \u274C ${check2.name} \uC5C6\uC74C`));
2578
+ console.log(chalk9.dim(` \u2192 ${check2.hint}`));
2835
2579
  allOk = false;
2836
2580
  }
2837
2581
  }
2838
2582
  console.log("");
2839
2583
  const vhkVersion = getVhkVersion();
2840
2584
  if (vhkVersion) {
2841
- console.log(chalk10.green(" \u2705 VHK") + chalk10.dim(` \u2014 v${vhkVersion}`));
2585
+ console.log(chalk9.green(" \u2705 VHK") + chalk9.dim(` \u2014 v${vhkVersion}`));
2842
2586
  } else {
2843
- console.log(chalk10.green(" \u2705 VHK") + chalk10.dim(" \u2014 \uC124\uCE58\uB428"));
2587
+ console.log(chalk9.green(" \u2705 VHK") + chalk9.dim(" \u2014 \uC124\uCE58\uB428"));
2844
2588
  }
2845
2589
  if (vhkVersion) {
2846
2590
  const latest = fetchLatestNpmVersion("@byh3071/vhk");
2847
2591
  if (latest && compareSemver(latest, vhkVersion) > 0) {
2848
- console.log(chalk10.yellow(` ${ko.doctor.updateAvailable(latest)}`));
2592
+ console.log(chalk9.yellow(` ${ko.doctor.updateAvailable(latest)}`));
2849
2593
  } else if (latest) {
2850
- console.log(chalk10.dim(` ${ko.doctor.updateCurrent}`));
2594
+ console.log(chalk9.dim(` ${ko.doctor.updateCurrent}`));
2851
2595
  }
2852
2596
  }
2853
2597
  console.log("");
2854
- console.log(chalk10.bold(` ${ko.doctor.projectFiles}`));
2598
+ console.log(chalk9.bold(` ${ko.doctor.projectFiles}`));
2855
2599
  const cwd = process.cwd();
2856
2600
  const projectFiles = [
2857
2601
  { name: "RULES.md", hint: "vhk init\uC73C\uB85C \uC0DD\uC131 \uAC00\uB2A5" },
@@ -2863,30 +2607,30 @@ ${ko.doctor.title}
2863
2607
  for (const file of projectFiles) {
2864
2608
  const exists = fs12.existsSync(path12.join(cwd, file.name));
2865
2609
  if (exists) {
2866
- console.log(chalk10.green(` \u2705 ${file.name}`));
2610
+ console.log(chalk9.green(` \u2705 ${file.name}`));
2867
2611
  if (file.name === ".env") {
2868
2612
  const gitignorePath = path12.join(cwd, ".gitignore");
2869
2613
  if (fs12.existsSync(gitignorePath)) {
2870
2614
  const gitignore = fs12.readFileSync(gitignorePath, "utf-8");
2871
2615
  if (!gitignore.includes(".env")) {
2872
- console.log(chalk10.yellow(` ${ko.doctor.envNotIgnored}`));
2616
+ console.log(chalk9.yellow(` ${ko.doctor.envNotIgnored}`));
2873
2617
  }
2874
2618
  }
2875
2619
  }
2876
2620
  } else {
2877
- console.log(chalk10.dim(` \u2B1A ${file.name}`) + chalk10.dim(` \u2014 ${file.hint}`));
2621
+ console.log(chalk9.dim(` \u2B1A ${file.name}`) + chalk9.dim(` \u2014 ${file.hint}`));
2878
2622
  }
2879
2623
  }
2880
2624
  console.log("");
2881
2625
  if (allOk) {
2882
- console.log(chalk10.green.bold(` ${ko.doctor.allOk}`));
2626
+ console.log(chalk9.green.bold(` ${ko.doctor.allOk}`));
2883
2627
  printNextStep({
2884
2628
  message: ko.doctor.nextOkMessage,
2885
2629
  command: "vhk \uC2DC\uC791",
2886
2630
  cursorHint: "\uD504\uB85C\uC81D\uD2B8 \uB9CC\uB4E4\uC5B4\uC918"
2887
2631
  });
2888
2632
  } else {
2889
- console.log(chalk10.yellow.bold(` ${ko.doctor.missing} ${ko.doctor.missingHint}`));
2633
+ console.log(chalk9.yellow.bold(` ${ko.doctor.missing} ${ko.doctor.missingHint}`));
2890
2634
  printNextStep({
2891
2635
  message: ko.doctor.nextRetryMessage,
2892
2636
  command: "vhk doctor",
@@ -2897,7 +2641,7 @@ ${ko.doctor.title}
2897
2641
  }
2898
2642
 
2899
2643
  // src/commands/ship.ts
2900
- import chalk11 from "chalk";
2644
+ import chalk10 from "chalk";
2901
2645
  import inquirer4 from "inquirer";
2902
2646
  import fs13 from "fs";
2903
2647
  import path13 from "path";
@@ -2936,29 +2680,29 @@ function updateChangelogUnreleased(cwd, version, date) {
2936
2680
  return { status: "updated", version };
2937
2681
  }
2938
2682
  async function ship() {
2939
- console.log(chalk11.bold(`
2683
+ console.log(chalk10.bold(`
2940
2684
  ${ko.ship.title}
2941
2685
  `));
2942
2686
  const cwd = process.cwd();
2943
- console.log(chalk11.cyan.bold(` ${ko.ship.checklist}
2687
+ console.log(chalk10.cyan.bold(` ${ko.ship.checklist}
2944
2688
  `));
2945
2689
  const { passed } = await inquirer4.prompt([{
2946
2690
  type: "checkbox",
2947
2691
  name: "passed",
2948
2692
  message: ko.ship.checkboxPrompt,
2949
2693
  choices: CHECKLIST.map((c) => ({
2950
- name: `${ko.ship[c.questionKey]} ${chalk11.dim(`(${ko.ship[c.hintKey]})`)}`,
2694
+ name: `${ko.ship[c.questionKey]} ${chalk10.dim(`(${ko.ship[c.hintKey]})`)}`,
2951
2695
  value: c.id
2952
2696
  }))
2953
2697
  }]);
2954
2698
  const allPassed = passed.length === CHECKLIST.length;
2955
2699
  const skipped = CHECKLIST.filter((c) => !passed.includes(c.id));
2956
2700
  if (!allPassed) {
2957
- console.log(chalk11.yellow(`
2701
+ console.log(chalk10.yellow(`
2958
2702
  ${ko.ship.incompleteHeader}`));
2959
2703
  skipped.forEach((s) => {
2960
- console.log(chalk11.yellow(` \u2022 ${ko.ship[s.questionKey]}`));
2961
- console.log(chalk11.dim(` \u2192 ${ko.ship[s.hintKey]}`));
2704
+ console.log(chalk10.yellow(` \u2022 ${ko.ship[s.questionKey]}`));
2705
+ console.log(chalk10.dim(` \u2192 ${ko.ship[s.hintKey]}`));
2962
2706
  });
2963
2707
  const { proceed } = await inquirer4.prompt([{
2964
2708
  type: "confirm",
@@ -2975,13 +2719,13 @@ ${ko.ship.title}
2975
2719
  return;
2976
2720
  }
2977
2721
  } else {
2978
- console.log(chalk11.green(`
2722
+ console.log(chalk10.green(`
2979
2723
  ${ko.ship.allPassed}
2980
2724
  `));
2981
2725
  }
2982
- console.log(chalk11.cyan.bold(` ${ko.ship.retro}
2726
+ console.log(chalk10.cyan.bold(` ${ko.ship.retro}
2983
2727
  `));
2984
- console.log(chalk11.dim(` ${ko.ship.versionHint}`));
2728
+ console.log(chalk10.dim(` ${ko.ship.versionHint}`));
2985
2729
  const retro = await inquirer4.prompt([
2986
2730
  { type: "input", name: "version", message: ko.ship.versionPrompt },
2987
2731
  { type: "input", name: "whatWentWell", message: ko.ship.questionWell },
@@ -3024,7 +2768,7 @@ ${ko.ship.title}
3024
2768
  `*Generated by \`vhk ship\` at ${(/* @__PURE__ */ new Date()).toISOString()}*`
3025
2769
  ].join("\n");
3026
2770
  fs13.writeFileSync(filePath, content, "utf-8");
3027
- console.log(chalk11.green(`
2771
+ console.log(chalk10.green(`
3028
2772
  ${ko.ship.buildLogDone(path13.relative(cwd, filePath))}`));
3029
2773
  const changelogResult = updateChangelogUnreleased(cwd, versionSlug, today);
3030
2774
  if (changelogResult.status === "updated") {
@@ -3044,7 +2788,7 @@ ${ko.ship.title}
3044
2788
 
3045
2789
  // src/commands/save.ts
3046
2790
  import { execFileSync as execFileSync2 } from "child_process";
3047
- import chalk12 from "chalk";
2791
+ import chalk11 from "chalk";
3048
2792
  import ora from "ora";
3049
2793
  import inquirer5 from "inquirer";
3050
2794
 
@@ -3115,29 +2859,29 @@ function statusIcon(code) {
3115
2859
  return "\u{1F4C4}";
3116
2860
  }
3117
2861
  async function save() {
3118
- console.log(chalk12.bold(`
2862
+ console.log(chalk11.bold(`
3119
2863
  \u{1F4BE} ${t("save.title")}`));
3120
- console.log(chalk12.gray("\u2500".repeat(40)));
2864
+ console.log(chalk11.gray("\u2500".repeat(40)));
3121
2865
  let gitRoot;
3122
2866
  try {
3123
2867
  execFileSync2("git", ["rev-parse", "--is-inside-work-tree"], { stdio: "pipe" });
3124
2868
  gitRoot = getGitRoot();
3125
2869
  } catch {
3126
- console.log(chalk12.red(`\u274C ${t("save.notGitRepo")}`));
2870
+ console.log(chalk11.red(`\u274C ${t("save.notGitRepo")}`));
3127
2871
  return;
3128
2872
  }
3129
- console.log(chalk12.cyan(`
2873
+ console.log(chalk11.cyan(`
3130
2874
  \u{1F512} ${t("save.securityWarnHeader")}`));
3131
2875
  printSecurityWarnings(gitRoot);
3132
2876
  const severe = filterSevereFindings(scanProjectForSecrets(gitRoot).findings);
3133
2877
  if (severe.length > 0) {
3134
- console.log(chalk12.red(`
2878
+ console.log(chalk11.red(`
3135
2879
  \u26A0\uFE0F ${t("save.secretsFound", severe.length)}`));
3136
2880
  severe.slice(0, 5).forEach((f) => {
3137
- console.log(chalk12.dim(` ${f.file}:${f.line} \u2014 ${f.patternName}`));
2881
+ console.log(chalk11.dim(` ${f.file}:${f.line} \u2014 ${f.patternName}`));
3138
2882
  });
3139
2883
  if (severe.length > 5) {
3140
- console.log(chalk12.dim(` ... \uC678 ${severe.length - 5}\uAC74 (vhk \uBCF4\uC548 scan)`));
2884
+ console.log(chalk11.dim(` ... \uC678 ${severe.length - 5}\uAC74 (vhk \uBCF4\uC548 scan)`));
3141
2885
  }
3142
2886
  const { proceed } = await inquirer5.prompt([{
3143
2887
  type: "confirm",
@@ -3146,16 +2890,16 @@ async function save() {
3146
2890
  default: false
3147
2891
  }]);
3148
2892
  if (!proceed) {
3149
- console.log(chalk12.gray(t("save.cancelled")));
2893
+ console.log(chalk11.gray(t("save.cancelled")));
3150
2894
  return;
3151
2895
  }
3152
2896
  }
3153
2897
  const lines = parsePorcelainLines(gitOut(["status", "--porcelain"], gitRoot));
3154
2898
  if (lines.length === 0) {
3155
- console.log(chalk12.yellow(`\u{1F4ED} ${t("save.noChanges")}`));
2899
+ console.log(chalk11.yellow(`\u{1F4ED} ${t("save.noChanges")}`));
3156
2900
  return;
3157
2901
  }
3158
- console.log(chalk12.cyan(`
2902
+ console.log(chalk11.cyan(`
3159
2903
  \u{1F4CB} ${t("save.filesHeader", lines.length)}`));
3160
2904
  lines.forEach((line) => {
3161
2905
  const code = line.substring(0, 2);
@@ -3177,34 +2921,34 @@ async function save() {
3177
2921
  spinner.text = t("save.pushing");
3178
2922
  if (!hasGitRemote(gitRoot)) {
3179
2923
  spinner.succeed(t("save.successLocal"));
3180
- console.log(chalk12.yellow(` \u{1F4A1} ${t("save.noRemote")}`));
2924
+ console.log(chalk11.yellow(` \u{1F4A1} ${t("save.noRemote")}`));
3181
2925
  } else {
3182
2926
  try {
3183
2927
  gitRun(["push"], gitRoot);
3184
2928
  spinner.succeed(t("save.successWithPush"));
3185
2929
  } catch (pushErr) {
3186
2930
  spinner.fail(t("save.pushFailed"));
3187
- console.log(chalk12.red(getExecErrorMessage(pushErr)));
3188
- console.log(chalk12.yellow(`
2931
+ console.log(chalk11.red(getExecErrorMessage(pushErr)));
2932
+ console.log(chalk11.yellow(`
3189
2933
  \u{1F4A1} ${t("save.commitOkPushFailed")}`));
3190
2934
  process.exitCode = 1;
3191
2935
  }
3192
2936
  }
3193
2937
  if (process.exitCode !== 1) {
3194
- console.log(chalk12.green(`
2938
+ console.log(chalk11.green(`
3195
2939
  \u2705 ${t("save.done", lines.length)}`));
3196
2940
  } else {
3197
- console.log(chalk12.green(`
2941
+ console.log(chalk11.green(`
3198
2942
  \u2705 ${t("save.doneLocalOnly", lines.length)}`));
3199
2943
  }
3200
2944
  } catch (err) {
3201
2945
  spinner.fail(t("save.failed"));
3202
- console.log(chalk12.red(getExecErrorMessage(err)));
2946
+ console.log(chalk11.red(getExecErrorMessage(err)));
3203
2947
  if (didAdd) {
3204
2948
  try {
3205
2949
  const staged = gitOut(["diff", "--cached", "--stat"], gitRoot).trim();
3206
2950
  if (staged) {
3207
- console.log(chalk12.yellow(`
2951
+ console.log(chalk11.yellow(`
3208
2952
  \u{1F4A1} ${t("save.stagedAfterFail")}`));
3209
2953
  }
3210
2954
  } catch {
@@ -3216,7 +2960,7 @@ async function save() {
3216
2960
 
3217
2961
  // src/commands/undo.ts
3218
2962
  import { execFileSync as execFileSync3 } from "child_process";
3219
- import chalk13 from "chalk";
2963
+ import chalk12 from "chalk";
3220
2964
  import inquirer6 from "inquirer";
3221
2965
  function parseRecentCommits(logOutput) {
3222
2966
  return logOutput.split("\n").map((l) => l.trim()).filter(Boolean);
@@ -3240,30 +2984,30 @@ function isUndoRisky(undoCount, unpushedCount, hasRemote) {
3240
2984
  return false;
3241
2985
  }
3242
2986
  async function undo() {
3243
- console.log(chalk13.bold(`
2987
+ console.log(chalk12.bold(`
3244
2988
  \u23EA ${t("undo.title")}`));
3245
- console.log(chalk13.gray("\u2500".repeat(40)));
2989
+ console.log(chalk12.gray("\u2500".repeat(40)));
3246
2990
  let gitRoot;
3247
2991
  try {
3248
2992
  execFileSync3("git", ["rev-parse", "--is-inside-work-tree"], { stdio: "pipe" });
3249
2993
  gitRoot = getGitRoot();
3250
2994
  } catch {
3251
- console.log(chalk13.red(`\u274C ${t("undo.notGitRepo")}`));
2995
+ console.log(chalk12.red(`\u274C ${t("undo.notGitRepo")}`));
3252
2996
  return;
3253
2997
  }
3254
2998
  let logOutput;
3255
2999
  try {
3256
3000
  logOutput = gitOut(["log", "--oneline", "-5"], gitRoot).trim();
3257
3001
  } catch {
3258
- console.log(chalk13.yellow(`\u{1F4ED} ${t("undo.noCommits")}`));
3002
+ console.log(chalk12.yellow(`\u{1F4ED} ${t("undo.noCommits")}`));
3259
3003
  return;
3260
3004
  }
3261
3005
  const commits = parseRecentCommits(logOutput);
3262
3006
  if (commits.length === 0) {
3263
- console.log(chalk13.yellow(`\u{1F4ED} ${t("undo.noCommits")}`));
3007
+ console.log(chalk12.yellow(`\u{1F4ED} ${t("undo.noCommits")}`));
3264
3008
  return;
3265
3009
  }
3266
- console.log(chalk13.cyan(`
3010
+ console.log(chalk12.cyan(`
3267
3011
  ${t("undo.recentHeader")}`));
3268
3012
  commits.forEach((c, i) => {
3269
3013
  console.log(` ${i === 0 ? "\u{1F449}" : " "} ${c}`);
@@ -3280,7 +3024,7 @@ ${t("undo.recentHeader")}`));
3280
3024
  const undoCount = Math.min(Math.max(1, count || 1), maxUndo);
3281
3025
  const headCount = countLocalCommits(gitRoot);
3282
3026
  if (undoCount >= headCount) {
3283
- console.log(chalk13.yellow(`
3027
+ console.log(chalk12.yellow(`
3284
3028
  \u{1F4ED} ${t("undo.rootCommit")}`));
3285
3029
  return;
3286
3030
  }
@@ -3289,10 +3033,10 @@ ${t("undo.recentHeader")}`));
3289
3033
  const risky = isUndoRisky(undoCount, unpushed, remote);
3290
3034
  if (risky) {
3291
3035
  if (unpushed < 0) {
3292
- console.log(chalk13.red(`
3036
+ console.log(chalk12.red(`
3293
3037
  \u26A0\uFE0F ${t("undo.noUpstreamWarning")}`));
3294
3038
  } else {
3295
- console.log(chalk13.red(`
3039
+ console.log(chalk12.red(`
3296
3040
  \u26A0\uFE0F ${t("undo.alreadyPushed")}`));
3297
3041
  }
3298
3042
  }
@@ -3303,22 +3047,22 @@ ${t("undo.recentHeader")}`));
3303
3047
  default: false
3304
3048
  }]);
3305
3049
  if (!confirm) {
3306
- console.log(chalk13.gray(t("undo.cancelled")));
3050
+ console.log(chalk12.gray(t("undo.cancelled")));
3307
3051
  return;
3308
3052
  }
3309
3053
  try {
3310
3054
  gitRun(["reset", "--soft", `HEAD~${undoCount}`], gitRoot);
3311
- console.log(chalk13.green(`
3055
+ console.log(chalk12.green(`
3312
3056
  \u2705 ${t("undo.success")}`));
3313
- console.log(chalk13.gray(` \u{1F4A1} ${t("undo.stagedHint")}`));
3057
+ console.log(chalk12.gray(` \u{1F4A1} ${t("undo.stagedHint")}`));
3314
3058
  if (risky) {
3315
- console.log(chalk13.yellow(`
3059
+ console.log(chalk12.yellow(`
3316
3060
  \u{1F4A1} ${t("undo.forcePushHint")}`));
3317
3061
  }
3318
3062
  } catch (err) {
3319
- console.log(chalk13.red(`\u274C ${t("undo.failed")}`));
3063
+ console.log(chalk12.red(`\u274C ${t("undo.failed")}`));
3320
3064
  const msg = err instanceof Error ? err.message : String(err);
3321
- console.log(chalk13.red(msg));
3065
+ console.log(chalk12.red(msg));
3322
3066
  process.exitCode = 1;
3323
3067
  }
3324
3068
  }
@@ -3327,7 +3071,7 @@ ${t("undo.recentHeader")}`));
3327
3071
  import { execFileSync as execFileSync4 } from "child_process";
3328
3072
  import fs15 from "fs";
3329
3073
  import path14 from "path";
3330
- import chalk14 from "chalk";
3074
+ import chalk13 from "chalk";
3331
3075
 
3332
3076
  // src/lib/read-json.ts
3333
3077
  import fs14 from "fs";
@@ -3399,15 +3143,15 @@ function getSyncCounts(gitRoot) {
3399
3143
  }
3400
3144
  }
3401
3145
  async function status() {
3402
- console.log(chalk14.bold(`
3146
+ console.log(chalk13.bold(`
3403
3147
  \u{1F4CA} ${t("status.title")}`));
3404
- console.log(chalk14.gray("\u2500".repeat(40)));
3148
+ console.log(chalk13.gray("\u2500".repeat(40)));
3405
3149
  let gitRoot;
3406
3150
  try {
3407
3151
  execFileSync4("git", ["rev-parse", "--is-inside-work-tree"], { stdio: "pipe" });
3408
3152
  gitRoot = getGitRoot();
3409
3153
  } catch {
3410
- console.log(chalk14.red(`\u274C ${t("status.notGitRepo")}`));
3154
+ console.log(chalk13.red(`\u274C ${t("status.notGitRepo")}`));
3411
3155
  return;
3412
3156
  }
3413
3157
  let branch;
@@ -3426,36 +3170,36 @@ async function status() {
3426
3170
  commits = [];
3427
3171
  }
3428
3172
  const pkg = readProjectPackage();
3429
- console.log(chalk14.cyan(`
3430
- \u{1F33F} ${t("status.branch")}`) + chalk14.white(` ${branch}`));
3173
+ console.log(chalk13.cyan(`
3174
+ \u{1F33F} ${t("status.branch")}`) + chalk13.white(` ${branch}`));
3431
3175
  console.log(
3432
- chalk14.cyan(`\u{1F4C1} ${t("status.changes")}`) + chalk14.white(
3176
+ chalk13.cyan(`\u{1F4C1} ${t("status.changes")}`) + chalk13.white(
3433
3177
  ` staged ${counts.staged} \xB7 unstaged ${counts.unstaged} \xB7 untracked ${counts.untracked}`
3434
3178
  )
3435
3179
  );
3436
- console.log(chalk14.cyan(`
3180
+ console.log(chalk13.cyan(`
3437
3181
  \u{1F4CB} ${t("status.recentCommits")}`));
3438
3182
  if (commits.length === 0) {
3439
- console.log(chalk14.dim(` ${t("status.noCommits")}`));
3183
+ console.log(chalk13.dim(` ${t("status.noCommits")}`));
3440
3184
  } else {
3441
- commits.forEach((c) => console.log(` ${chalk14.dim("\u2022")} ${c}`));
3185
+ commits.forEach((c) => console.log(` ${chalk13.dim("\u2022")} ${c}`));
3442
3186
  }
3443
3187
  console.log(
3444
- chalk14.cyan(`
3445
- \u{1F504} ${t("status.remote")}`) + chalk14.white(` ${formatSyncLabel(sync2)}`)
3188
+ chalk13.cyan(`
3189
+ \u{1F504} ${t("status.remote")}`) + chalk13.white(` ${formatSyncLabel(sync2)}`)
3446
3190
  );
3447
- console.log(chalk14.gray("\n" + "\u2500".repeat(40)));
3191
+ console.log(chalk13.gray("\n" + "\u2500".repeat(40)));
3448
3192
  if (pkg) {
3449
- console.log(chalk14.cyan(`\u{1F4E6} ${t("status.package")}`) + chalk14.white(` ${pkg.name} v${pkg.version}`));
3193
+ console.log(chalk13.cyan(`\u{1F4E6} ${t("status.package")}`) + chalk13.white(` ${pkg.name} v${pkg.version}`));
3450
3194
  } else {
3451
- console.log(chalk14.dim(`\u{1F4E6} ${t("status.noPackage")}`));
3195
+ console.log(chalk13.dim(`\u{1F4E6} ${t("status.noPackage")}`));
3452
3196
  }
3453
3197
  console.log("");
3454
3198
  }
3455
3199
 
3456
3200
  // src/commands/diff.ts
3457
3201
  import { execFileSync as execFileSync5, execSync as execSync2 } from "child_process";
3458
- import chalk15 from "chalk";
3202
+ import chalk14 from "chalk";
3459
3203
  function gitOut2(args) {
3460
3204
  try {
3461
3205
  return execFileSync5("git", args, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
@@ -3495,53 +3239,53 @@ function summarizeNumstat(numstat) {
3495
3239
  return { fileCount, totalAdd, totalDel };
3496
3240
  }
3497
3241
  function printFile(f) {
3498
- const adds = f.additions > 0 ? chalk15.green(`+${f.additions}`) : "";
3499
- const dels = f.deletions > 0 ? chalk15.red(`-${f.deletions}`) : "";
3242
+ const adds = f.additions > 0 ? chalk14.green(`+${f.additions}`) : "";
3243
+ const dels = f.deletions > 0 ? chalk14.red(`-${f.deletions}`) : "";
3500
3244
  const change = [adds, dels].filter(Boolean).join(" ");
3501
3245
  console.log(` ${f.name} ${change}`);
3502
3246
  }
3503
3247
  async function diff() {
3504
- console.log(chalk15.bold(`
3248
+ console.log(chalk14.bold(`
3505
3249
  \u{1F50D} ${t("diff.title")}`));
3506
- console.log(chalk15.gray("\u2500".repeat(40)));
3250
+ console.log(chalk14.gray("\u2500".repeat(40)));
3507
3251
  try {
3508
3252
  execSync2("git rev-parse --is-inside-work-tree", { stdio: "pipe" });
3509
3253
  } catch {
3510
- console.log(chalk15.red(`\u274C ${t("diff.notGitRepo")}`));
3254
+ console.log(chalk14.red(`\u274C ${t("diff.notGitRepo")}`));
3511
3255
  return;
3512
3256
  }
3513
3257
  const unstaged = gitOut2(["diff", "--stat"]);
3514
3258
  const staged = gitOut2(["diff", "--cached", "--stat"]);
3515
3259
  const untracked = gitOut2(["ls-files", "--others", "--exclude-standard"]);
3516
3260
  if (!unstaged && !staged && !untracked) {
3517
- console.log(chalk15.green(`
3261
+ console.log(chalk14.green(`
3518
3262
  \u2705 ${t("diff.noChanges")}`));
3519
3263
  return;
3520
3264
  }
3521
3265
  if (staged) {
3522
- console.log(chalk15.cyan(`
3266
+ console.log(chalk14.cyan(`
3523
3267
  ${t("diff.stagedHeader")}`));
3524
3268
  parseDiffStat(staged).forEach((f) => printFile(f));
3525
3269
  }
3526
3270
  if (unstaged) {
3527
- console.log(chalk15.cyan(`
3271
+ console.log(chalk14.cyan(`
3528
3272
  ${t("diff.unstagedHeader")}`));
3529
3273
  parseDiffStat(unstaged).forEach((f) => printFile(f));
3530
3274
  }
3531
3275
  if (untracked) {
3532
3276
  const files = untracked.split("\n").filter(Boolean);
3533
- console.log(chalk15.cyan(`
3277
+ console.log(chalk14.cyan(`
3534
3278
  ${t("diff.untrackedHeader", files.length)}`));
3535
- files.forEach((f) => console.log(` ${chalk15.green("+")} ${f}`));
3279
+ files.forEach((f) => console.log(` ${chalk14.green("+")} ${f}`));
3536
3280
  }
3537
3281
  const numstat = gitOut2(["diff", "--numstat", "HEAD"]);
3538
3282
  if (numstat) {
3539
3283
  const { fileCount, totalAdd, totalDel } = summarizeNumstat(numstat);
3540
- console.log(chalk15.cyan(`
3284
+ console.log(chalk14.cyan(`
3541
3285
  ${t("diff.summaryHeader")}`));
3542
3286
  console.log(` ${t("diff.filesLine", fileCount)}`);
3543
- console.log(` \uCD94\uAC00: ${chalk15.green(`+${totalAdd}`)}\uC904`);
3544
- console.log(` \uC0AD\uC81C: ${chalk15.red(`-${totalDel}`)}\uC904`);
3287
+ console.log(` \uCD94\uAC00: ${chalk14.green(`+${totalAdd}`)}\uC904`);
3288
+ console.log(` \uC0AD\uC81C: ${chalk14.red(`-${totalDel}`)}\uC904`);
3545
3289
  }
3546
3290
  console.log("");
3547
3291
  }
@@ -3550,8 +3294,18 @@ ${t("diff.summaryHeader")}`));
3550
3294
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
3551
3295
  import { join } from "path";
3552
3296
  import { fileURLToPath as fileURLToPath2 } from "url";
3553
- import chalk16 from "chalk";
3297
+ import chalk15 from "chalk";
3554
3298
  function resolveVhkMcpPath() {
3299
+ try {
3300
+ const pkgPath = join(process.cwd(), "package.json");
3301
+ if (existsSync(pkgPath)) {
3302
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
3303
+ if (pkg.name === "@byh3071/vhk") {
3304
+ return join(process.cwd(), "dist", "mcp", "index.js");
3305
+ }
3306
+ }
3307
+ } catch {
3308
+ }
3555
3309
  try {
3556
3310
  const url = import.meta.resolve?.("@byh3071/vhk/dist/mcp/index.js");
3557
3311
  if (typeof url === "string") return fileURLToPath2(url);
@@ -3560,8 +3314,8 @@ function resolveVhkMcpPath() {
3560
3314
  return join(process.cwd(), "node_modules", "@byh3071", "vhk", "dist", "mcp", "index.js");
3561
3315
  }
3562
3316
  async function mcpInit() {
3563
- console.log(chalk16.bold("\n\u{1F50C} " + t("mcp.initTitle")));
3564
- console.log(chalk16.gray("\u2500".repeat(40)));
3317
+ console.log(chalk15.bold("\n\u{1F50C} " + t("mcp.initTitle")));
3318
+ console.log(chalk15.gray("\u2500".repeat(40)));
3565
3319
  const cursorDir = join(process.cwd(), ".cursor");
3566
3320
  if (!existsSync(cursorDir)) {
3567
3321
  mkdirSync(cursorDir, { recursive: true });
@@ -3579,20 +3333,242 @@ async function mcpInit() {
3579
3333
  mcpServers: { ...parsed.mcpServers ?? {}, vhk: vhkEntry }
3580
3334
  };
3581
3335
  } catch {
3582
- console.log(chalk16.yellow("\u26A0\uFE0F \uAE30\uC874 .cursor/mcp.json \uD30C\uC2F1 \uC2E4\uD328 \u2014 \uC0C8 \uD30C\uC77C\uB85C \uB36E\uC5B4\uC501\uB2C8\uB2E4."));
3336
+ console.log(chalk15.yellow("\u26A0\uFE0F \uAE30\uC874 .cursor/mcp.json \uD30C\uC2F1 \uC2E4\uD328 \u2014 \uC0C8 \uD30C\uC77C\uB85C \uB36E\uC5B4\uC501\uB2C8\uB2E4."));
3583
3337
  config = { mcpServers: { vhk: vhkEntry } };
3584
3338
  }
3585
3339
  } else {
3586
3340
  config = { mcpServers: { vhk: vhkEntry } };
3587
3341
  }
3588
3342
  writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
3589
- console.log(chalk16.green("\n\u2705 Cursor MCP \uC124\uC815 \uC644\uB8CC!"));
3590
- console.log(chalk16.cyan("\u{1F4C1} \uC0DD\uC131\uB41C \uD30C\uC77C:"));
3343
+ console.log(chalk15.green("\n\u2705 Cursor MCP \uC124\uC815 \uC644\uB8CC!"));
3344
+ console.log(chalk15.cyan("\u{1F4C1} \uC0DD\uC131\uB41C \uD30C\uC77C:"));
3591
3345
  console.log(` ${configPath}`);
3592
- console.log(chalk16.cyan("\n\u{1F504} \uB2E4\uC74C \uB2E8\uACC4:"));
3346
+ console.log(chalk15.cyan("\n\u{1F504} \uB2E4\uC74C \uB2E8\uACC4:"));
3593
3347
  console.log(" 1. Cursor\uB97C \uC7AC\uC2DC\uC791\uD558\uC138\uC694");
3594
3348
  console.log(" 2. Cursor \uCC44\uD305\uC5D0\uC11C vhk \uB3C4\uAD6C\uB97C \uC0AC\uC6A9\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4");
3595
- console.log(chalk16.gray('\n\u{1F4A1} \uC608: "\uD504\uB85C\uC81D\uD2B8 \uC0C1\uD0DC \uC54C\uB824\uC918" \u2192 Cursor\uAC00 vhk status \uD638\uCD9C'));
3349
+ console.log(chalk15.gray('\n\u{1F4A1} \uC608: "\uD504\uB85C\uC81D\uD2B8 \uC0C1\uD0DC \uC54C\uB824\uC918" \u2192 Cursor\uAC00 vhk status \uD638\uCD9C'));
3350
+ }
3351
+
3352
+ // src/commands/deploy.ts
3353
+ import { existsSync as existsSync2 } from "fs";
3354
+ import chalk16 from "chalk";
3355
+ import inquirer7 from "inquirer";
3356
+ var PLATFORMS = {
3357
+ vercel: {
3358
+ name: "Vercel",
3359
+ detectFiles: ["vercel.json", ".vercel"],
3360
+ command: "vercel",
3361
+ commandArgs: ["--prod"],
3362
+ checkArgs: ["--version"],
3363
+ installHint: "npm i -g vercel"
3364
+ },
3365
+ netlify: {
3366
+ name: "Netlify",
3367
+ detectFiles: ["netlify.toml", ".netlify"],
3368
+ command: "netlify",
3369
+ commandArgs: ["deploy", "--prod"],
3370
+ checkArgs: ["--version"],
3371
+ installHint: "npm i -g netlify-cli"
3372
+ },
3373
+ cloudflare: {
3374
+ name: "Cloudflare Workers",
3375
+ detectFiles: ["wrangler.toml"],
3376
+ command: "wrangler",
3377
+ commandArgs: ["deploy"],
3378
+ checkArgs: ["--version"],
3379
+ installHint: "npm i -g wrangler"
3380
+ }
3381
+ };
3382
+ function detectPlatform() {
3383
+ for (const [key, config] of Object.entries(PLATFORMS)) {
3384
+ for (const file of config.detectFiles) {
3385
+ if (existsSync2(file)) return key;
3386
+ }
3387
+ }
3388
+ return null;
3389
+ }
3390
+ function isCLIAvailable(cmd, checkArgs) {
3391
+ return safeExecFile(cmd, checkArgs).ok;
3392
+ }
3393
+ async function deploy() {
3394
+ console.log(chalk16.bold("\n\u{1F680} " + t("deploy.title")));
3395
+ console.log(chalk16.gray("\u2500".repeat(40)));
3396
+ let platform = detectPlatform();
3397
+ if (platform) {
3398
+ console.log(chalk16.cyan(`
3399
+ \u{1F50D} \uAC10\uC9C0\uB41C \uD50C\uB7AB\uD3FC: ${PLATFORMS[platform].name}`));
3400
+ } else {
3401
+ const { selected } = await inquirer7.prompt([
3402
+ {
3403
+ type: "list",
3404
+ name: "selected",
3405
+ message: t("deploy.selectPlatform"),
3406
+ choices: [
3407
+ { name: "\u25B2 Vercel", value: "vercel" },
3408
+ { name: "\u25C6 Netlify", value: "netlify" },
3409
+ { name: "\u2601 Cloudflare Workers", value: "cloudflare" }
3410
+ ]
3411
+ }
3412
+ ]);
3413
+ platform = selected;
3414
+ }
3415
+ const config = PLATFORMS[platform];
3416
+ if (!isCLIAvailable(config.command, config.checkArgs)) {
3417
+ console.log(chalk16.red(`
3418
+ \u274C ${config.name} CLI\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.`));
3419
+ console.log(chalk16.yellow(` \u2192 ${config.installHint}`));
3420
+ return;
3421
+ }
3422
+ const { confirm } = await inquirer7.prompt([
3423
+ {
3424
+ type: "confirm",
3425
+ name: "confirm",
3426
+ message: `${config.name}\uC5D0 \uD504\uB85C\uB355\uC158 \uBC30\uD3EC\uD560\uAE4C\uC694?`,
3427
+ default: true
3428
+ }
3429
+ ]);
3430
+ if (!confirm) {
3431
+ console.log(chalk16.gray("\uCDE8\uC18C\uB428"));
3432
+ return;
3433
+ }
3434
+ console.log(chalk16.cyan(`
3435
+ ${t("deploy.deploying")}
3436
+ `));
3437
+ const result = safeExecFileStream(config.command, config.commandArgs);
3438
+ if (result.ok) {
3439
+ console.log(chalk16.green(`
3440
+ \u2705 ${t("deploy.success")}`));
3441
+ printNextStep({
3442
+ message: "\uBC30\uD3EC \uC644\uB8CC! \uC0AC\uC774\uD2B8\uB97C \uD655\uC778\uD558\uC138\uC694.",
3443
+ command: "vhk status",
3444
+ cursorHint: "\uC0C1\uD0DC \uD655\uC778\uD574\uC918"
3445
+ });
3446
+ } else {
3447
+ console.log(chalk16.red(`
3448
+ \u274C ${t("deploy.failed")}`));
3449
+ console.log(chalk16.red(result.err));
3450
+ }
3451
+ }
3452
+
3453
+ // src/commands/publish.ts
3454
+ import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
3455
+ import chalk17 from "chalk";
3456
+ import inquirer8 from "inquirer";
3457
+ import ora2 from "ora";
3458
+ function bumpVersion(current, type) {
3459
+ const [major, minor, patch] = current.split(".").map((n) => parseInt(n, 10) || 0);
3460
+ switch (type) {
3461
+ case "major":
3462
+ return `${major + 1}.0.0`;
3463
+ case "minor":
3464
+ return `${major}.${minor + 1}.0`;
3465
+ case "patch":
3466
+ return `${major}.${minor}.${patch + 1}`;
3467
+ }
3468
+ }
3469
+ async function publish() {
3470
+ console.log(chalk17.bold("\n\u{1F4E6} " + t("publish.title")));
3471
+ console.log(chalk17.gray("\u2500".repeat(40)));
3472
+ if (!existsSync3("package.json")) {
3473
+ console.log(chalk17.red("\u274C package.json\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."));
3474
+ return;
3475
+ }
3476
+ let pkg;
3477
+ try {
3478
+ pkg = JSON.parse(readFileSync2("package.json", "utf-8"));
3479
+ } catch {
3480
+ console.log(chalk17.red("\u274C package.json \uD30C\uC2F1 \uC2E4\uD328"));
3481
+ return;
3482
+ }
3483
+ const currentVersion = pkg.version || "0.0.0";
3484
+ console.log(chalk17.cyan(`
3485
+ \u{1F4CC} \uD604\uC7AC \uBC84\uC804: v${currentVersion}`));
3486
+ const { bumpType } = await inquirer8.prompt([
3487
+ {
3488
+ type: "list",
3489
+ name: "bumpType",
3490
+ message: t("publish.selectBump"),
3491
+ choices: [
3492
+ { name: `\u{1F527} patch (${bumpVersion(currentVersion, "patch")}) \u2014 \uBC84\uADF8 \uC218\uC815`, value: "patch" },
3493
+ { name: `\u2728 minor (${bumpVersion(currentVersion, "minor")}) \u2014 \uC0C8 \uAE30\uB2A5`, value: "minor" },
3494
+ { name: `\u{1F4A5} major (${bumpVersion(currentVersion, "major")}) \u2014 \uD638\uD658\uC131 \uBCC0\uACBD`, value: "major" }
3495
+ ]
3496
+ }
3497
+ ]);
3498
+ const newVersion = bumpVersion(currentVersion, bumpType);
3499
+ console.log(chalk17.cyan(`
3500
+ \u{1F195} \uC0C8 \uBC84\uC804: v${newVersion}`));
3501
+ pkg.version = newVersion;
3502
+ writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
3503
+ console.log(chalk17.green("\u2705 package.json \uBC84\uC804 \uC5C5\uB370\uC774\uD2B8"));
3504
+ const buildSpinner = ora2(t("publish.building")).start();
3505
+ const buildResult = safeExecFile("pnpm", ["build"]);
3506
+ if (!buildResult.ok) {
3507
+ buildSpinner.fail(t("publish.buildFailed"));
3508
+ console.log(chalk17.red(buildResult.err.slice(0, 500)));
3509
+ pkg.version = currentVersion;
3510
+ writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
3511
+ return;
3512
+ }
3513
+ buildSpinner.succeed(t("publish.buildSuccess"));
3514
+ const testSpinner = ora2(t("publish.testing")).start();
3515
+ const testResult = safeExecFile("pnpm", ["test", "--run"]);
3516
+ if (!testResult.ok) {
3517
+ testSpinner.fail(t("publish.testFailed"));
3518
+ console.log(chalk17.red(testResult.err.slice(0, 500)));
3519
+ pkg.version = currentVersion;
3520
+ writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
3521
+ return;
3522
+ }
3523
+ testSpinner.succeed(t("publish.testSuccess"));
3524
+ const { confirm } = await inquirer8.prompt([
3525
+ {
3526
+ type: "confirm",
3527
+ name: "confirm",
3528
+ message: `v${newVersion}\uC744 npm\uC5D0 \uBC30\uD3EC\uD560\uAE4C\uC694?`,
3529
+ default: true
3530
+ }
3531
+ ]);
3532
+ if (!confirm) {
3533
+ pkg.version = currentVersion;
3534
+ writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
3535
+ console.log(chalk17.gray("\uCDE8\uC18C\uB428. \uBC84\uC804\uC774 \uC6D0\uB798\uB300\uB85C \uBCF5\uAD6C\uB429\uB2C8\uB2E4."));
3536
+ return;
3537
+ }
3538
+ const pubSpinner = ora2(t("publish.publishing")).start();
3539
+ const pubResult = safeExecFile("npm", ["publish", "--access", "public"]);
3540
+ if (!pubResult.ok) {
3541
+ pubSpinner.fail(t("publish.publishFailed"));
3542
+ console.log(chalk17.red(pubResult.err.slice(0, 500)));
3543
+ pkg.version = currentVersion;
3544
+ writeFileSync2("package.json", JSON.stringify(pkg, null, 2) + "\n", "utf-8");
3545
+ console.log(chalk17.gray(`\u{1F4E6} package.json \uBC84\uC804\uC744 v${currentVersion}\uB85C \uBCF5\uAD6C\uD588\uC2B5\uB2C8\uB2E4.`));
3546
+ return;
3547
+ }
3548
+ pubSpinner.succeed(t("publish.publishSuccess"));
3549
+ const addResult = safeExecFile("git", ["add", "package.json"]);
3550
+ if (addResult.ok) {
3551
+ safeExecFile("git", ["commit", "-m", `chore: release v${newVersion}`]);
3552
+ const tagResult = safeExecFile("git", ["tag", `v${newVersion}`]);
3553
+ if (tagResult.ok) {
3554
+ const pushResult = safeExecFile("git", ["push"]);
3555
+ const pushTagsResult = safeExecFile("git", ["push", "--tags"]);
3556
+ if (pushResult.ok && pushTagsResult.ok) {
3557
+ console.log(chalk17.green(`
3558
+ \u{1F3F7}\uFE0F git tag v${newVersion} \uC0DD\uC131 + push \uC644\uB8CC`));
3559
+ } else {
3560
+ console.log(chalk17.yellow(`
3561
+ \u{1F3F7}\uFE0F git tag v${newVersion} \uC0DD\uC131\uB428 (push\uB294 \uC218\uB3D9\uC73C\uB85C)`));
3562
+ }
3563
+ }
3564
+ }
3565
+ console.log(chalk17.green.bold(`
3566
+ \u{1F389} v${newVersion} \uBC30\uD3EC \uC644\uB8CC!`));
3567
+ printNextStep({
3568
+ message: "npm \uBC30\uD3EC \uC644\uB8CC!",
3569
+ command: "vhk status",
3570
+ cursorHint: "\uC0C1\uD0DC \uD655\uC778\uD574\uC918"
3571
+ });
3596
3572
  }
3597
3573
 
3598
3574
  // src/lib/nlp-run.ts
@@ -3627,28 +3603,36 @@ async function dispatchNlpRoute(route, input) {
3627
3603
  return diff();
3628
3604
  case "mcp-init":
3629
3605
  return mcpInit();
3606
+ case "deploy":
3607
+ return deploy();
3608
+ case "env":
3609
+ return env();
3610
+ case "env-check":
3611
+ return envCheck();
3612
+ case "publish":
3613
+ return publish();
3630
3614
  }
3631
3615
  }
3632
3616
  async function runNaturalLanguageRoute(input) {
3633
3617
  const route = routeNaturalLanguage(input);
3634
3618
  if (!route) {
3635
- console.log(chalk17.yellow(`
3619
+ console.log(chalk18.yellow(`
3636
3620
  \u2753 "${input}" \u2014 ${ko.nlp.notMatched}
3637
3621
  `));
3638
3622
  return;
3639
3623
  }
3640
3624
  console.log("");
3641
- console.log(chalk17.cyan(` \u{1F4AC} "${input}"`));
3642
- console.log(chalk17.cyan(` \u2192 ${route.explanation}`));
3625
+ console.log(chalk18.cyan(` \u{1F4AC} "${input}"`));
3626
+ console.log(chalk18.cyan(` \u2192 ${route.explanation}`));
3643
3627
  if (route.confidence === "low") {
3644
- const { confirm } = await inquirer7.prompt([{
3628
+ const { confirm } = await inquirer9.prompt([{
3645
3629
  type: "confirm",
3646
3630
  name: "confirm",
3647
3631
  message: `${route.explanation} \u2014 ${ko.nlp.matched}`,
3648
3632
  default: true
3649
3633
  }]);
3650
3634
  if (!confirm) {
3651
- console.log(chalk17.dim(` ${ko.nlp.menuHint}`));
3635
+ console.log(chalk18.dim(` ${ko.nlp.menuHint}`));
3652
3636
  return;
3653
3637
  }
3654
3638
  }
@@ -3666,14 +3650,18 @@ var KO_ALIASES = {
3666
3650
  sync: "\uADDC\uCE59",
3667
3651
  check: "\uC810\uAC80",
3668
3652
  secure: "\uBCF4\uC548",
3669
- ship: "\uBC30\uD3EC",
3653
+ ship: "\uCD9C\uD558",
3670
3654
  doctor: "\uD658\uACBD",
3671
3655
  save: "\uC800\uC7A5",
3672
3656
  undo: "\uB418\uB3CC\uB9AC\uAE30",
3673
3657
  status: "\uC0C1\uD0DC",
3674
- diff: "\uBCC0\uACBD"
3658
+ diff: "\uBCC0\uACBD",
3659
+ deploy: "\uBC30\uD3EC",
3660
+ env: "\uD658\uACBD\uBCC0\uC218",
3661
+ "env-check": "\uD658\uACBD\uBCC0\uC218\uC810\uAC80",
3662
+ publish: "\uCD9C\uC2DC"
3675
3663
  };
3676
- program.name("vhk").description("VHK \u2014 \uBC14\uC774\uBE0C\uCF54\uB529 \uD504\uB85C\uC81D\uD2B8 \uCF54\uCE58 (\uD55C\uAD6D\uC5B4\uB85C \uC548\uB0B4\uD569\uB2C8\uB2E4)").version("0.6.0");
3664
+ program.name("vhk").description("VHK \u2014 \uBC14\uC774\uBE0C\uCF54\uB529 \uD504\uB85C\uC81D\uD2B8 \uCF54\uCE58 (\uD55C\uAD6D\uC5B4\uB85C \uC548\uB0B4\uD569\uB2C8\uB2E4)").version("0.7.1");
3677
3665
  program.configureHelp({
3678
3666
  formatHelp(cmd, helper) {
3679
3667
  if (cmd.parent) {
@@ -3704,7 +3692,7 @@ program.command("sync").alias("\uB9DE\uCD94\uAE30").alias("\uADDC\uCE59").descri
3704
3692
  program.command("check").alias("\uC810\uAC80").alias("\uB9B0\uD2B8").description("RULES.md \uADDC\uCE59 \uC810\uAC80 \u2014 \uCF54\uB4DC \uC704\uBC18 \uAC80\uC0AC").action(check);
3705
3693
  var secureCmd = program.command("secure").alias("\uBCF4\uC548").description("\uBCF4\uC548 \uB3C4\uAD6C \uBAA8\uC74C \u2014 scan: \uC2DC\uD06C\uB9BF\xB7\uD0A4 \uC720\uCD9C \uAC80\uC0AC").action(secure);
3706
3694
  secureCmd.command("scan").alias("\uC2A4\uCE94").description("\uC2DC\uD06C\uB9BF/\uD0A4 \uC720\uCD9C \uC2A4\uCE94").action(secure);
3707
- program.command("ship").alias("\uBC30\uD3EC").alias("\uB9B4\uB9AC\uC988").description("\uBC30\uD3EC \uCCB4\uD06C\uB9AC\uC2A4\uD2B8 + \uD68C\uACE0 + \uBE4C\uB4DC \uB85C\uADF8 \uC0DD\uC131").action(ship);
3695
+ program.command("ship").alias("\uCD9C\uD558").description("\uBC30\uD3EC \uCCB4\uD06C\uB9AC\uC2A4\uD2B8 + \uD68C\uACE0 + \uBE4C\uB4DC \uB85C\uADF8 \uC0DD\uC131").action(ship);
3708
3696
  program.command("doctor").alias("\uD658\uACBD").alias("\uC9C4\uB2E8").description("\uAC1C\uBC1C \uD658\uACBD \uC810\uAC80 \u2014 Node/Git/npm \uC0C1\uD0DC \uD655\uC778").action(doctor);
3709
3697
  program.command("save").alias("\uC800\uC7A5").description("\uBCC0\uACBD\uC0AC\uD56D \uC800\uC7A5 (git add \u2192 commit \u2192 push)").action(async () => {
3710
3698
  await save();
@@ -3722,6 +3710,18 @@ program.command("mcp").description("MCP \uC11C\uBC84 \uC2DC\uC791 (Cursor \uB4F1
3722
3710
  program.command("mcp-init").alias("mcp\uC124\uC815").description("Cursor MCP \uC5F0\uB3D9 \uC124\uC815 \uC790\uB3D9 \uC0DD\uC131 (.cursor/mcp.json)").action(async () => {
3723
3711
  await mcpInit();
3724
3712
  });
3713
+ program.command("deploy").alias("\uBC30\uD3EC").description("\uD504\uB85C\uB355\uC158 \uBC30\uD3EC (Vercel/Netlify/Cloudflare \uC790\uB3D9 \uAC10\uC9C0)").action(async () => {
3714
+ await deploy();
3715
+ });
3716
+ program.command("env").alias("\uD658\uACBD\uBCC0\uC218").description(".env \u2192 .env.example \uB3D9\uAE30\uD654 + .gitignore \uC790\uB3D9 \uCD94\uAC00").action(async () => {
3717
+ await env();
3718
+ });
3719
+ program.command("env-check").alias("\uD658\uACBD\uBCC0\uC218\uC810\uAC80").description("\uD544\uC218 \uD658\uACBD\uBCC0\uC218 \uB204\uB77D \uAC80\uC0AC").action(async () => {
3720
+ await envCheck();
3721
+ });
3722
+ program.command("publish").alias("\uCD9C\uC2DC").description("npm \uBC30\uD3EC (\uBC84\uC804 \uBC94\uD504 \u2192 \uBE4C\uB4DC \u2192 \uD14C\uC2A4\uD2B8 \u2192 publish)").action(async () => {
3723
+ await publish();
3724
+ });
3725
3725
  program.on("command:*", async (operands) => {
3726
3726
  const unknown = operands[0] ?? "";
3727
3727
  const rest = operands.slice(1);
@@ -3730,7 +3730,7 @@ program.on("command:*", async (operands) => {
3730
3730
  });
3731
3731
  program.action(async () => {
3732
3732
  console.log("\n\u{1F3AF} VHK \u2014 \uBC14\uC774\uBE0C\uCF54\uB529 \uD504\uB85C\uC81D\uD2B8 \uCF54\uCE58\n");
3733
- const { choice } = await inquirer8.prompt([{
3733
+ const { choice } = await inquirer10.prompt([{
3734
3734
  type: "list",
3735
3735
  name: "choice",
3736
3736
  message: "\uBB58 \uB3C4\uC640\uB4DC\uB9B4\uAE4C\uC694?",