@byh3071/vhk 2.3.2 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -43,13 +43,13 @@ import {
43
43
  stripBom,
44
44
  sync,
45
45
  t
46
- } from "./chunk-OHGVVAKT.js";
46
+ } from "./chunk-MN6LSPN6.js";
47
47
 
48
48
  // src/index.ts
49
49
  import { Command, Help } from "commander";
50
50
  import { fileURLToPath as fileURLToPath4 } from "url";
51
51
  import fs13 from "fs";
52
- import chalk37 from "chalk";
52
+ import chalk38 from "chalk";
53
53
  import inquirer15 from "inquirer";
54
54
 
55
55
  // src/lib/nlp-router.ts
@@ -62,7 +62,8 @@ var NLP_KEYWORDS = {
62
62
  evolve: ["\uC9C4\uD654", "\uB8F0\uD6C4\uBCF4", "\uC9C4\uD654\uD6C4\uBCF4"],
63
63
  undo: ["\uB418\uB3CC\uB824", "\uB418\uB3CC\uB9AC\uAE30", "\uCDE8\uC18C", "\uC6D0\uB798\uB300\uB85C", "\uB864\uBC31", "\uB9AC\uC14B", "reset", "rollback"],
64
64
  status: ["\uC0C1\uD0DC", "\uD604\uD669", "\uC5B4\uB5BB\uAC8C", "\uC5B4\uB54C", "\uC9C0\uAE08"],
65
- diff: ["\uBCC0\uACBD", "\uBC14\uB010", "\uBB50\uBC14\uB01C", "\uBC14\uB00C\uC5C8", "\uCC28\uC774", "\uB2EC\uB77C\uC9C4", "\uC218\uC815\uB41C"]
65
+ diff: ["\uBCC0\uACBD", "\uBC14\uB010", "\uBB50\uBC14\uB01C", "\uBC14\uB00C\uC5C8", "\uCC28\uC774", "\uB2EC\uB77C\uC9C4", "\uC218\uC815\uB41C"],
66
+ work: ["\uC774\uC5B4\uC11C", "\uC774\uC5B4\uD558\uAE30", "work"]
66
67
  };
67
68
  function matchesKeywords(text, command) {
68
69
  const keywords = NLP_KEYWORDS[command];
@@ -372,6 +373,20 @@ var RULES = [
372
373
  confidence: "high",
373
374
  args: ["sync"],
374
375
  test: (t2) => /(게이트|목표).*(스크립트|동기화)|체크\s*스크립트\s*(생성|만들)/.test(t2)
376
+ },
377
+ // work — handoff(인수인계)를 먼저 평가(더 구체적), 그다음 작업 시작/이어하기.
378
+ {
379
+ command: "work",
380
+ explanation: "\uC791\uC5C5 \uC911\uB2E8 \uC815\uB9AC \uD504\uB86C\uD504\uD2B8 (vhk work handoff)",
381
+ confidence: "high",
382
+ args: ["handoff"],
383
+ test: (t2) => /인수인계|핸드오프|handoff|작업\s*(넘기|넘겨|전달|마무리)|중단\s*정리/.test(t2)
384
+ },
385
+ {
386
+ command: "work",
387
+ explanation: "\uC791\uC5C5 \uC2DC\uC791/\uC774\uC5B4\uD558\uAE30 \uD504\uB86C\uD504\uD2B8 (vhk work)",
388
+ confidence: "high",
389
+ test: (t2) => matchesKeywords(t2, "work") || /작업\s*(시작|이어|이어서|계속)|이어서\s*(작업|하자|할래)|^work$/.test(t2)
375
390
  }
376
391
  ];
377
392
  function routeNaturalLanguage(input) {
@@ -406,7 +421,8 @@ var CONTAINER_SUBCOMMANDS = {
406
421
  mode: ["lite", "standard", "strict"],
407
422
  mission: ["set", "check", "clear"],
408
423
  pattern: ["detect", "list", "dismiss"],
409
- evolve: ["suggest", "list", "apply", "reject", "undo"]
424
+ evolve: ["suggest", "list", "apply", "reject", "undo"],
425
+ work: ["handoff"]
410
426
  };
411
427
  var CONTAINER_ALIASES = {
412
428
  \uBAA9\uD45C: "goal",
@@ -419,8 +435,55 @@ var CONTAINER_ALIASES = {
419
435
  \uBAA8\uB4DC: "mode",
420
436
  \uBBF8\uC158: "mission",
421
437
  \uD328\uD134: "pattern",
422
- \uC9C4\uD654: "evolve"
438
+ \uC9C4\uD654: "evolve",
439
+ \uC791\uC5C5: "work"
423
440
  };
441
+ var TOP_LEVEL_COMMANDS = [
442
+ { name: "gate", desc: "\uC544\uC774\uB514\uC5B4 \uAC80\uC99D" },
443
+ { name: "start", desc: "\uC0C8 \uD504\uB85C\uC81D\uD2B8 \uC2DC\uC791 \uB9C8\uBC95\uC0AC" },
444
+ { name: "init", desc: "\uD558\uB124\uC2A4 \uD30C\uC77C \uC0DD\uC131" },
445
+ { name: "recap", desc: "\uC624\uB298 \uD55C \uC77C \uC815\uB9AC + ADR \uBD84\uB9AC" },
446
+ { name: "sync", desc: "RULES.md \u2192 \uADDC\uCE59 \uD30C\uC77C \uB3D9\uAE30\uD654" },
447
+ { name: "check", desc: "RULES.md \uADDC\uCE59 \uC810\uAC80" },
448
+ { name: "secure", desc: "\uBCF4\uC548 \uC2A4\uCE94 (\uC2DC\uD06C\uB9BF \uC720\uCD9C \uAC80\uC0AC)" },
449
+ { name: "cloud", desc: ".vhk \uD074\uB77C\uC6B0\uB4DC \uBC31\uC5C5\xB7\uBCF5\uC6D0 (push/pull)" },
450
+ { name: "ship", desc: "\uBC30\uD3EC \uCCB4\uD06C\uB9AC\uC2A4\uD2B8 + \uD68C\uACE0" },
451
+ { name: "doctor", desc: "\uAC1C\uBC1C \uD658\uACBD \uC810\uAC80 (+ --strict \uB4DC\uB9AC\uD504\uD2B8 \uAC8C\uC774\uD2B8)" },
452
+ { name: "save", desc: "git \uC800\uC7A5 (add \u2192 commit \u2192 push)" },
453
+ { name: "undo", desc: "\uCD5C\uADFC \uCEE4\uBC0B \uB418\uB3CC\uB9AC\uAE30" },
454
+ { name: "restore", desc: "sync \uBC31\uC5C5 \uBCF5\uC6D0" },
455
+ { name: "status", desc: "\uD504\uB85C\uC81D\uD2B8 \uC0C1\uD0DC \uB300\uC2DC\uBCF4\uB4DC" },
456
+ { name: "diff", desc: "Git \uBCC0\uACBD\uC0AC\uD56D \uD55C\uAD6D\uC5B4 \uC694\uC57D" },
457
+ { name: "mcp", desc: "MCP \uC11C\uBC84 \uC2DC\uC791 (stdio)" },
458
+ { name: "mcp-init", desc: "Cursor\xB7Claude Desktop MCP \uC124\uC815 \uC0DD\uC131" },
459
+ { name: "deploy", desc: "\uD504\uB85C\uB355\uC158 \uBC30\uD3EC (\uC790\uB3D9 \uAC10\uC9C0)" },
460
+ { name: "env", desc: ".env \u2192 .env.example \uB3D9\uAE30\uD654" },
461
+ { name: "env-check", desc: "\uD544\uC218 \uD658\uACBD\uBCC0\uC218 \uB204\uB77D \uAC80\uC0AC" },
462
+ { name: "publish", desc: "npm \uBC30\uD3EC (\uBC84\uC804 \uBC94\uD504 \u2192 \uBE4C\uB4DC \u2192 \uD14C\uC2A4\uD2B8)" },
463
+ { name: "design", desc: "\uB514\uC790\uC778 \uD1A0\uD070 \uC0DD\uC131" },
464
+ { name: "design-palette", desc: "\uCEEC\uB7EC \uD314\uB808\uD2B8 \uD504\uB9AC\uC14B \uC120\uD0DD" },
465
+ { name: "theme", desc: "\uB2E4\uD06C/\uB77C\uC774\uD2B8 \uBAA8\uB4DC CSS \uC0DD\uC131" },
466
+ { name: "ref", desc: "\uB808\uD37C\uB7F0\uC2A4 URL \uAD00\uB9AC (add/list/open)" },
467
+ { name: "harness", desc: "\uD1B5\uD569 \uD488\uC9C8 \uC810\uAC80 (lint+type+test+build)" },
468
+ { name: "audit", desc: "\uBCF4\uC548 \uCDE8\uC57D\uC810 \uAC10\uC0AC (npm audit)" },
469
+ { name: "migrate", desc: "\uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800 \uC804\uD658 (npm/yarn/pnpm)" },
470
+ { name: "update", desc: "VHK CLI \uC140\uD504 \uC5C5\uB370\uC774\uD2B8" },
471
+ { name: "context", desc: "\uD504\uB85C\uC81D\uD2B8 \uB9E5\uB77D \uD30C\uC77C \uC0DD\uC131 (.vhk/context.md)" },
472
+ { name: "mode", desc: "Safety Mode \uC870\uD68C/\uBCC0\uACBD (lite|standard|strict)" },
473
+ { name: "verify", desc: "\uAC80\uC99D \uAC8C\uC774\uD2B8 \uC2E4\uD589 + \uC99D\uAC70 \uAE30\uB85D" },
474
+ { name: "review", desc: "\uC801\uB300\uC801 \uC790\uAE30\uAC80\uC99D (\uAC70\uC9D3\uC644\uB8CC \uC758\uC2EC \uD0D0\uC9C0)" },
475
+ { name: "mission", desc: "\uBBF8\uC158 \uACC4\uC57D \u2014 \uC791\uC5C5 \uBAA9\uD45C\xB7\uD5C8\uC6A9/\uAE08\uC9C0 \uBC94\uC704 \uC120\uC5B8\xB7\uAC80\uC99D" },
476
+ { name: "context-show", desc: "\uCEE8\uD14D\uC2A4\uD2B8 \uD30C\uC77C \uB0B4\uC6A9 \uCD9C\uB825" },
477
+ { name: "memory", desc: "\uAE30\uC5B5 \uAD00\uB9AC v2 (decisions/failures/successes)" },
478
+ { name: "brief", desc: "\uD504\uB85C\uC81D\uD2B8 \uC694\uC57D \uBCF4\uACE0\uC11C \uC0DD\uC131" },
479
+ { name: "work", desc: "AI \uC791\uC5C5 \uC2DC\uC791/\uC774\uC5B4\uD558\uAE30 (+ handoff)" },
480
+ { name: "goal", desc: "Goal \uB2E8\uACC4\uBCC4 \uBBF8\uC158 \uAD00\uB9AC" },
481
+ { name: "blocker", desc: "\uBE14\uB85C\uCEE4 \uAE30\uB85D (3\uAC74 \uB204\uC801 \uC2DC HARD_STOP)" },
482
+ { name: "learn", desc: "\uAD50\uD6C8 \uAE30\uB85D \u2192 memory v2 \uB2E8\uC77C SoT" },
483
+ { name: "resume", desc: ".vhk/HARD_STOP \uD574\uC81C (--confirm \uD544\uC694)" },
484
+ { name: "pattern", desc: "\uBC18\uBCF5 \uD328\uD134 \uAC10\uC9C0\xB7\uBAA9\uB85D (avoid/reinforce)" },
485
+ { name: "evolve", desc: "\uD328\uD134 \u2192 \uB8F0 \uD6C4\uBCF4 \uC81C\uC548\xB7\uBC18\uC601\xB7undo" }
486
+ ];
424
487
 
425
488
  // src/lib/cli-args.ts
426
489
  var KNOWN_COMMAND_TOKENS = /* @__PURE__ */ new Set([
@@ -520,6 +583,8 @@ var KNOWN_COMMAND_TOKENS = /* @__PURE__ */ new Set([
520
583
  "\uD328\uD134",
521
584
  "evolve",
522
585
  "\uC9C4\uD654",
586
+ "work",
587
+ "\uC791\uC5C5",
523
588
  "help"
524
589
  ]);
525
590
  function isOptionToken(token) {
@@ -557,7 +622,7 @@ function detectNaturalLanguageInput(argv) {
557
622
  }
558
623
 
559
624
  // src/lib/nlp-run.ts
560
- import chalk35 from "chalk";
625
+ import chalk36 from "chalk";
561
626
  import inquirer14 from "inquirer";
562
627
 
563
628
  // src/commands/gate.ts
@@ -2957,7 +3022,7 @@ function compareSemver(a, b) {
2957
3022
  if (a2 !== b2) return a2 - b2;
2958
3023
  return a3 - b3;
2959
3024
  }
2960
- async function doctor() {
3025
+ async function doctor(opts = {}) {
2961
3026
  console.log(chalk9.bold(`
2962
3027
  ${ko.doctor.title}
2963
3028
  `));
@@ -3016,14 +3081,15 @@ ${ko.doctor.title}
3016
3081
  }
3017
3082
  }
3018
3083
  } else if (file.name === ".env" && fs8.existsSync(path9.join(cwd, ".env.local"))) {
3019
- console.log(chalk9.green(" \u2705 .env.local") + chalk9.dim(" \u2014 \uB85C\uCEEC env \uC0AC\uC6A9 \uC911 (.env \uC5C6\uC5B4\uB3C4 \uC815\uC0C1)"));
3084
+ console.log(chalk9.green(" \u2705 .env.local") + chalk9.dim(" \u2014 \uB85C\uCEF4 env \uC0AC\uC6A9 \uC911 (.env \uC5C6\uC5B4\uB3C4 \uC815\uC0C1)"));
3020
3085
  } else {
3021
- console.log(chalk9.dim(` \u2B1A ${file.name}`) + chalk9.dim(` \u2014 ${file.hint}`));
3086
+ console.log(chalk9.dim(` \u26AB ${file.name}`) + chalk9.dim(` \u2014 ${file.hint}`));
3022
3087
  }
3023
3088
  }
3024
3089
  console.log("");
3025
3090
  console.log(chalk9.bold(` ${ko.doctor.driftTitle}`));
3026
3091
  const ruleDrift = checkRuleDrift(cwd);
3092
+ let ruleDrifted = false;
3027
3093
  if (!ruleDrift.checked) {
3028
3094
  console.log(chalk9.dim(` ${ko.doctor.driftNoRules}`));
3029
3095
  } else {
@@ -3032,6 +3098,7 @@ ${ko.doctor.title}
3032
3098
  console.log(chalk9.green(` ${ko.doctor.driftRuleClean}`));
3033
3099
  } else {
3034
3100
  console.log(chalk9.yellow(` ${ko.doctor.driftRuleWarn(drifted.map((d) => d.path).join(", "))}`));
3101
+ ruleDrifted = true;
3035
3102
  }
3036
3103
  }
3037
3104
  const ctxDrift = checkContextDrift(cwd);
@@ -3055,6 +3122,11 @@ ${ko.doctor.title}
3055
3122
  });
3056
3123
  process.exitCode = 1;
3057
3124
  }
3125
+ if (opts.strict && ruleDrifted) {
3126
+ console.log("");
3127
+ console.log(chalk9.red.bold(" \u274C --strict: \uADDC\uCE59 \uB4DC\uB9AC\uD504\uD2B8 \uBC1C\uACAC \u2192 \uC2E4\uD328 \uCC98\uB9AC (vhk sync \uB85C \uB3D9\uAE30\uD654 \uD6C4 \uB2E4\uC2DC \uC2E4\uD589)"));
3128
+ process.exitCode = 1;
3129
+ }
3058
3130
  }
3059
3131
 
3060
3132
  // src/commands/ship.ts
@@ -4947,37 +5019,7 @@ function extractTechStack() {
4947
5019
  return stack;
4948
5020
  }
4949
5021
  function getVhkCommands() {
4950
- return [
4951
- "gate \u2014 \uC544\uC774\uB514\uC5B4 \uAC80\uC99D",
4952
- "init \u2014 \uD504\uB85C\uC81D\uD2B8 \uCD08\uAE30\uD654",
4953
- "recap \u2014 \uC138\uC158 \uC694\uC57D \uC800\uC7A5",
4954
- "sync \u2014 \uADDC\uCE59 \uD30C\uC77C \uB3D9\uAE30\uD654",
4955
- "check \u2014 \uADDC\uCE59 \uC810\uAC80",
4956
- "secure \u2014 \uBCF4\uC548 \uC2A4\uCE94",
4957
- "ship \u2014 \uBC30\uD3EC \uCCB4\uD06C + \uD68C\uACE0",
4958
- "doctor \u2014 \uD658\uACBD \uC9C4\uB2E8",
4959
- "save \u2014 git \uC800\uC7A5 (add+commit+push)",
4960
- "undo \u2014 \uCD5C\uADFC \uCEE4\uBC0B \uB418\uB3CC\uB9AC\uAE30",
4961
- "status \u2014 git \uC0C1\uD0DC \uD655\uC778",
4962
- "diff \u2014 git \uBCC0\uACBD \uC0AC\uD56D \uC694\uC57D",
4963
- "deploy \u2014 \uD504\uB85C\uB355\uC158 \uBC30\uD3EC",
4964
- "env \u2014 \uD658\uACBD\uBCC0\uC218 \uAD00\uB9AC",
4965
- "publish \u2014 npm \uBC30\uD3EC \uC790\uB3D9\uD654",
4966
- "design \u2014 \uB514\uC790\uC778 \uD1A0\uD070 \uC0DD\uC131",
4967
- "design-palette \u2014 \uCEEC\uB7EC \uD314\uB808\uD2B8 \uC120\uD0DD",
4968
- "theme \u2014 \uB2E4\uD06C/\uB77C\uC774\uD2B8 \uBAA8\uB4DC",
4969
- "ref add|list|open \u2014 \uB808\uD37C\uB7F0\uC2A4 URL \uAD00\uB9AC",
4970
- "harness \u2014 \uD1B5\uD569 \uD488\uC9C8 \uC810\uAC80",
4971
- "audit \u2014 \uBCF4\uC548 \uCDE8\uC57D\uC810 \uAC10\uC0AC",
4972
- "migrate \u2014 \uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800 \uC804\uD658",
4973
- "update \u2014 VHK CLI \uC140\uD504 \uC5C5\uB370\uC774\uD2B8",
4974
- "context \u2014 \uD504\uB85C\uC81D\uD2B8 \uB9E5\uB77D \uC0DD\uC131",
4975
- "context-show \u2014 \uB9E5\uB77D \uD30C\uC77C \uBCF4\uAE30",
4976
- "memory add|list|remove \u2014 \uACB0\uC815\uC0AC\uD56D \uAE30\uC5B5",
4977
- "brief \u2014 \uD504\uB85C\uC81D\uD2B8 \uC694\uC57D \uBCF4\uACE0\uC11C",
4978
- "mcp \u2014 MCP \uC11C\uBC84 \uC2DC\uC791",
4979
- "mcp-init \u2014 Cursor MCP \uC124\uC815"
4980
- ];
5022
+ return TOP_LEVEL_COMMANDS.map((c) => `${c.name} \u2014 ${c.desc}`);
4981
5023
  }
4982
5024
  async function context(opts = {}) {
4983
5025
  const compact = opts.compact === true;
@@ -4992,6 +5034,16 @@ async function context(opts = {}) {
4992
5034
  lines.push("> \uC774 \uD30C\uC77C\uC740 `vhk context`\uB85C \uC790\uB3D9 \uC0DD\uC131\uB418\uC5C8\uC2B5\uB2C8\uB2E4.");
4993
5035
  lines.push("> AI \uC5B4\uC2DC\uC2A4\uD134\uD2B8\uC5D0\uAC8C \uD504\uB85C\uC81D\uD2B8 \uB9E5\uB77D\uC744 \uC81C\uACF5\uD569\uB2C8\uB2E4.");
4994
5036
  lines.push("");
5037
+ lines.push("## \uC6D0\uBCF8 \uC9C0\uB3C4 (Source of Truth)");
5038
+ lines.push("");
5039
+ lines.push('> \uBB34\uC5C7\uC744 \uACE0\uCE60 \uB540 "\uC6D0\uBCF8" \uD55C \uACF3\uB9CC \uACE0\uCE58\uC138\uC694. \uB098\uBA38\uC9C0\uB294 \uD30C\uC0DD\uBCF8\uC774\uB77C \uC790\uB3D9 \uC0DD\uC131\uB429\uB2C8\uB2E4.');
5040
+ lines.push("");
5041
+ lines.push("- **\uADDC\uCE59(\uC6D0\uBCF8)**: `RULES.md` \u2014 \uADDC\uCE59\uC740 \uC5EC\uAE30 \uD55C \uACF3\uC5D0\uC11C\uB9CC \uC218\uC815");
5042
+ lines.push("- **\uC791\uC5C5 \uC0C1\uD0DC**: `docs/state/next-task.md`, `docs/state/blockers.md`");
5043
+ lines.push("- **\uBC84\uC804\xB7\uB9B4\uB9AC\uC2A4**: `package.json`, `CHANGELOG.md`");
5044
+ lines.push("- **\uBA85\uB839 \uBAA9\uB85D**: `COMMANDS.md` (+ `vhk help`)");
5045
+ lines.push("- **\uD30C\uC0DD\uBCF8(\uC9C1\uC811 \uC218\uC815 \uAE08\uC9C0)**: `.cursorrules`\xB7`.windsurfrules`\xB7`.github/copilot-instructions.md`\xB7`AGENTS.md`\xB7`GEMINI.md` \uB4F1 7\uC885 + `CLAUDE.md` \uADDC\uCE59 \uC601\uC5ED \u2192 `vhk sync` \uB85C \uC0DD\uC131");
5046
+ lines.push("");
4995
5047
  lines.push("## \uAE30\uC220 \uC2A4\uD0DD");
4996
5048
  lines.push("");
4997
5049
  for (const [key, value] of Object.entries(stack)) {
@@ -5051,9 +5103,10 @@ async function context(opts = {}) {
5051
5103
  if (compact) {
5052
5104
  lines.push("## \uCC38\uC870 \uBB38\uC11C (\uD544\uC694\uC2DC \uC5F4\uB78C)");
5053
5105
  lines.push("");
5106
+ lines.push("- \uADDC\uCE59 \uC6D0\uBCF8(SoT): `RULES.md` \u2014 \uADDC\uCE59\uC740 \uC5EC\uAE30\uC11C\uB9CC \uC218\uC815");
5054
5107
  lines.push("- \uC791\uB3D9 \uADDC\uC57D(\uC694\uC57D): `docs/context/agent-compact.md`");
5055
5108
  lines.push("- \uADDC\uC57D \uC0C1\uC138: `AGENTS.md`");
5056
- lines.push("- \uAE30\uB85D \uADDC\uCE59: `CLAUDE.md`");
5109
+ lines.push("- \uC6B4\uC601 \uC548\uB0B4\xB7\uAE30\uB85D: `CLAUDE.md`");
5057
5110
  lines.push("- \uBA85\uB839 \uC0C1\uC138: `COMMANDS.md`");
5058
5111
  lines.push("- \uAD6C\uC870 \uC0C1\uC138: `docs/ARCHITECTURE.md`");
5059
5112
  lines.push("- \uD604\uC7AC \uC0C1\uD0DC: `docs/state/next-task.md`");
@@ -5213,12 +5266,227 @@ async function brief() {
5213
5266
  });
5214
5267
  }
5215
5268
 
5216
- // src/commands/start.ts
5269
+ // src/commands/work.ts
5270
+ import { existsSync as existsSync14, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10, readFileSync as readFileSync7 } from "fs";
5271
+ import { join as join9 } from "path";
5217
5272
  import chalk26 from "chalk";
5273
+
5274
+ // src/lib/clipboard.ts
5275
+ import { spawnSync } from "child_process";
5276
+ function copyToClipboard(text) {
5277
+ try {
5278
+ if (process.platform === "win32") return copyWin32(text);
5279
+ if (process.platform === "darwin") return runWithInput("pbcopy", [], text);
5280
+ return runWithInput("wl-copy", [], text) || runWithInput("xclip", ["-selection", "clipboard"], text) || runWithInput("xsel", ["--clipboard", "--input"], text);
5281
+ } catch {
5282
+ return false;
5283
+ }
5284
+ }
5285
+ function copyWin32(text) {
5286
+ const b64 = Buffer.from(text, "utf8").toString("base64");
5287
+ const psScript = "$b=[Console]::In.ReadToEnd();$t=[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($b));Set-Clipboard -Value $t";
5288
+ const r = spawnSync(
5289
+ "powershell",
5290
+ ["-NoProfile", "-NonInteractive", "-Command", psScript],
5291
+ { input: b64, encoding: "utf8", windowsHide: true }
5292
+ );
5293
+ return r.status === 0 && !r.error;
5294
+ }
5295
+ function runWithInput(cmd, args, input) {
5296
+ const r = spawnSync(cmd, args, { input, encoding: "utf8" });
5297
+ return r.status === 0 && !r.error;
5298
+ }
5299
+
5300
+ // src/commands/work.ts
5301
+ var VHK_DIR2 = ".vhk";
5302
+ function gitShort() {
5303
+ const r = safeExecFile("git", ["status", "--short"]);
5304
+ return r.ok ? r.out.trim() : "";
5305
+ }
5306
+ function ensureVhkProject() {
5307
+ if (existsSync14("CLAUDE.md") || existsSync14(VHK_DIR2) || existsSync14("goals")) return true;
5308
+ console.log(chalk26.yellow(" \u26A0\uFE0F \uC5EC\uAE30\uB294 VHK \uD504\uB85C\uC81D\uD2B8 \uD3F4\uB354\uAC00 \uC544\uB2CC \uAC83 \uAC19\uC544\uC694."));
5309
+ console.log(chalk26.dim(" VHK \uD504\uB85C\uC81D\uD2B8 \uD3F4\uB354\uC5D0\uC11C \uC2E4\uD589\uD558\uAC70\uB098, vhk start \uB85C \uC0C8\uB85C \uC2DC\uC791\uD558\uC138\uC694."));
5310
+ return false;
5311
+ }
5312
+ function passHardStop() {
5313
+ if (!isHardStopActive()) {
5314
+ console.log(chalk26.green(" \u2705 HARD_STOP \uC5C6\uC74C"));
5315
+ return true;
5316
+ }
5317
+ console.log(chalk26.red.bold("\n\u{1F6D1} HARD STOP \uD65C\uC131 (.vhk/HARD_STOP) \u2014 \uC790\uB3D9\uD654\uB97C \uC911\uB2E8\uD569\uB2C8\uB2E4."));
5318
+ const reason = readHardStopReason();
5319
+ if (reason) console.log(chalk26.red(` \uC0AC\uC720: ${reason.replace(/\s*\n\s*/g, " ")}`));
5320
+ console.log(chalk26.yellow(" \uD574\uC81C\uB294 \uC0AC\uB78C\uC774 \uC9C1\uC811: vhk resume --confirm"));
5321
+ return false;
5322
+ }
5323
+ function activeGoalLine() {
5324
+ const goals = listGoals("goals");
5325
+ if (goals.length === 0) return "\uC815\uC758\uB41C goal \uC5C6\uC74C";
5326
+ const id = selectActiveId(goals);
5327
+ if (id === null) return "\uBAA8\uB4E0 goal \uC644\uB8CC\uB428";
5328
+ const g = goals.find((x) => x.frontmatter.id === id);
5329
+ if (!g) return "\uC815\uC758\uB41C goal \uC5C6\uC74C";
5330
+ return `Goal ${id} \u2014 ${g.frontmatter.title ?? "(untitled)"}`;
5331
+ }
5332
+ function printGit(git3) {
5333
+ if (!git3) {
5334
+ console.log(chalk26.dim(" (\uBCC0\uACBD\uB41C \uD30C\uC77C \uC5C6\uC74C \u2014 \uAE68\uB057\uD55C \uC0C1\uD0DC)"));
5335
+ return;
5336
+ }
5337
+ for (const line of git3.split(/\r?\n/)) console.log(` ${line}`);
5338
+ }
5339
+ function buildStartPrompt(git3, goalLine) {
5340
+ const gitBlock = git3 || "(\uBCC0\uACBD \uC5C6\uC74C)";
5341
+ return [
5342
+ "\uB2F9\uC2E0\uC740 VHK \uD504\uB85C\uC81D\uD2B8\uC758 \uC791\uC5C5 \uD30C\uD2B8\uB108\uC785\uB2C8\uB2E4. \uB098\uB294 \uBE44\uAC1C\uBC1C\uC790\uC785\uB2C8\uB2E4.",
5343
+ "",
5344
+ "[\uADDC\uCE59 \uC6B0\uC120\uC21C\uC704]",
5345
+ "1. CLAUDE.md \uB97C 1\uC21C\uC704 \uADDC\uCE59\uC73C\uB85C \uC77D\uACE0 \uADF8\uB300\uB85C \uB530\uB974\uC138\uC694. (\uCDA9\uB3CC \uC2DC CLAUDE.md \uC6B0\uC120)",
5346
+ "2. AGENTS.md \uB294 Codex/\uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8\uC6A9 \uCC38\uACE0 \uADDC\uCE59\uC785\uB2C8\uB2E4. \uB2F9\uC2E0\uC740 \uCC38\uACE0\uB9CC \uD558\uC138\uC694.",
5347
+ "3. docs/state/next-task.md \uC640 .vhk/context.md \uB97C \uC77D\uACE0 \uADF8 \uAE30\uC900\uC73C\uB85C \uC774\uC5B4\uC11C \uC791\uC5C5\uD558\uC138\uC694.",
5348
+ "",
5349
+ "[\uC791\uC5C5 \uC804 Source of Truth \uCCB4\uD06C]",
5350
+ "1. \uC0C8 \uD0C0\uC785\xB7\uADDC\uCE59\xB7\uC0C1\uC218\xB7\uBA85\uB839\uC5B4\xB7\uD504\uB86C\uD504\uD2B8\uB97C \uB9CC\uB4E4\uAE30 \uC804\uC5D0 \uAE30\uC874 \uC815\uC758\uAC00 \uC788\uB294\uC9C0 \uBA3C\uC800 \uCC3E\uC544\uBCF4\uACE0, \uC788\uC73C\uBA74 \uC7AC\uC0AC\uC6A9(import)\uD558\uC138\uC694.",
5351
+ "2. \uADDC\uCE59\uC740 RULES.md \uD55C \uACF3\uC5D0\uC11C\uB9CC \uACE0\uCE58\uC138\uC694. CLAUDE.md\xB7AGENTS.md\xB7.cursorrules \uB4F1\uC740 vhk sync \uB85C \uB9CC\uB4DC\uB294 \uD30C\uC0DD\uBCF8\uC774\uB77C \uC9C1\uC811 \uC218\uC815 \uAE08\uC9C0.",
5352
+ "3. \uC6D0\uBCF8 \uAD6C\uBD84 \u2014 \uADDC\uCE59=RULES.md / \uC791\uC5C5 \uC0C1\uD0DC=docs/state/next-task.md / \uBC84\uC804\xB7\uB9B4\uB9AC\uC2A4=package.json\xB7CHANGELOG.md.",
5353
+ "4. DTO\xB7\uACC4\uCE35 \uBD84\uB9AC\uCC98\uB7FC \uC77C\uBD80\uB7EC \uD0C0\uC785\uC744 \uB098\uB20C \uB550 \uC774\uC720\uB97C \uD55C \uC904 \uC124\uBA85\uD558\uC138\uC694. (\uC758\uBBF8\uAC00 \uAC19\uC740 \uAC78 \uC0C8\uB85C \uB610 \uC815\uC758\uD558\uB294 \uAC83\uB9CC \uAE08\uC9C0)",
5354
+ "",
5355
+ "[\uC9C0\uAE08 \uC0C1\uD0DC \u2014 \uC790\uB3D9 \uC218\uC9D1\uB428]",
5356
+ "- \uBCC0\uACBD\uB41C \uD30C\uC77C (git status --short):",
5357
+ gitBlock,
5358
+ "- \uD604\uC7AC \uBAA9\uD45C (active goal):",
5359
+ goalLine,
5360
+ "",
5361
+ "[\uD574\uC8FC\uC138\uC694]",
5362
+ "1. \uBA3C\uC800 \uD604\uC7AC \uC0C1\uD0DC\uB97C \uBE44\uAC1C\uBC1C\uC790\uAC00 \uC54C\uC544\uB4E3\uAC8C \uC27D\uAC8C \uC694\uC57D\uD574 \uC8FC\uC138\uC694.",
5363
+ "2. \uADF8\uB2E4\uC74C \uD560 \uC77C\uC744 3\uB2E8\uACC4 \uC774\uD558\uB85C \uB9D0\uD558\uACE0 \uC9C4\uD589\uD558\uC138\uC694.",
5364
+ "3. \uD14C\uC2A4\uD2B8\uAC00 \uD1B5\uACFC\uD558\uAE30 \uC804\uC5D0\uB294 \uC644\uB8CC(done) \uCC98\uB9AC\uD558\uC9C0 \uB9C8\uC138\uC694.",
5365
+ "4. \uC790\uB3D9 \uCEE4\uBC0B\uC774\uB098 vhk goal done \uC740 \uB0B4\uAC00 \uC2B9\uC778\uD558\uAE30 \uC804\uC5D0\uB294 \uD558\uC9C0 \uB9C8\uC138\uC694.",
5366
+ "\uBAA8\uB4E0 \uC751\uB2F5\uC740 \uD55C\uAD6D\uC5B4\uB85C."
5367
+ ].join("\n");
5368
+ }
5369
+ function buildHandoffPrompt(git3) {
5370
+ const gitBlock = git3 || "(\uBCC0\uACBD \uC5C6\uC74C)";
5371
+ return [
5372
+ "\uB2F9\uC2E0\uC740 VHK \uD504\uB85C\uC81D\uD2B8\uC758 \uC791\uC5C5 \uD30C\uD2B8\uB108\uC785\uB2C8\uB2E4. \uC624\uB298\uC740 \uC5EC\uAE30\uC11C \uC791\uC5C5\uC744 \uC911\uB2E8\uD558\uACE0 \uCEF4\uD4E8\uD130\uB97C \uAEBC\uC57C \uD569\uB2C8\uB2E4.",
5373
+ "\uB2E4\uC74C \uC138\uC158\uC774 \uC774\uC5B4\uBC1B\uC744 \uC218 \uC788\uAC8C \uC815\uB9AC\uD574 \uC8FC\uC138\uC694.",
5374
+ "",
5375
+ "[\uAC00\uC7A5 \uBA3C\uC800] CLAUDE.md \uB97C 1\uC21C\uC704 \uADDC\uCE59\uC73C\uB85C \uC77D\uC73C\uC138\uC694. AGENTS.md \uB294 Codex/\uBCF4\uC870\uC6A9 \uCC38\uACE0\uB9CC.",
5376
+ "",
5377
+ "[\uC9C0\uAE08 \uC0C1\uD0DC \u2014 \uC790\uB3D9 \uC218\uC9D1\uB428]",
5378
+ "- \uBCC0\uACBD\uB41C \uD30C\uC77C (git status --short):",
5379
+ gitBlock,
5380
+ "",
5381
+ "[\uD574\uC8FC\uC138\uC694 \u2014 \uC815\uB9AC\uB9CC, \uC0C8 \uAC1C\uBC1C \uC2DC\uC791 \uAE08\uC9C0]",
5382
+ "1. \uD604\uC7AC \uBCC0\uACBD\uC0AC\uD56D\uC744 \uD655\uC778\uD558\uACE0, \uC644\uB8CC\uB41C \uC77C / \uBBF8\uC644\uB8CC\uB41C \uC77C\uB85C \uB098\uB220 \uD55C\uAD6D\uC5B4\uB85C \uC815\uB9AC\uD574 \uC8FC\uC138\uC694.",
5383
+ "2. \uD14C\uC2A4\uD2B8\uB97C \uC2E4\uD589\uD588\uB294\uC9C0/\uC548 \uD588\uB294\uC9C0, \uACB0\uACFC\uAC00 \uC5B4\uB560\uB294\uC9C0 \uBA85\uD655\uD788 \uAE30\uB85D\uD574 \uC8FC\uC138\uC694. (\uC548 \uB3CC\uB838\uC73C\uBA74 '\uBBF8\uC2E4\uD589')",
5384
+ "3. docs/state/next-task.md \uB97C \uC9C0\uAE08 \uC0C1\uD0DC\uC5D0 \uB9DE\uAC8C \uC5C5\uB370\uC774\uD2B8\uD574 \uC8FC\uC138\uC694. (\uB2E4\uC74C \uC0AC\uB78C\uC774 \uC774\uC5B4\uBC1B\uC744 \uC9C0\uC810 \uBA85\uD655\uD788)",
5385
+ "4. \uC9C0\uAE08 \uCEE4\uBC0B \uAC00\uB2A5\uD55C \uC0C1\uD0DC\uC778\uC9C0 \uD310\uB2E8\uD574 \uC8FC\uC138\uC694. (\uC774\uC720 \uC124\uBA85)",
5386
+ "5. \uC644\uB8CC(done) \uCC98\uB9AC\uD558\uBA74 \uC548 \uB418\uB294 \uC0C1\uD0DC\uB77C\uBA74 \uC815\uB9AC \uB9E8 \uC704\uC5D0 \uAD75\uAC8C \uD45C\uC2DC\uD574 \uC8FC\uC138\uC694.",
5387
+ "",
5388
+ "[\uAE08\uC9C0] \uC9C1\uC811 git commit / git stash / git reset / vhk goal done \uC2E4\uD589 \uAE08\uC9C0. \uD30C\uC77C \uB418\uB3CC\uB9AC\uAE30\xB7\uC0AD\uC81C \uAE08\uC9C0.",
5389
+ "\uBAA8\uB4E0 \uC751\uB2F5\uC740 \uD55C\uAD6D\uC5B4\uB85C."
5390
+ ].join("\n");
5391
+ }
5392
+ function emitPrompt(prompt, fileName, label) {
5393
+ let savedPath = "";
5394
+ try {
5395
+ mkdirSync10(VHK_DIR2, { recursive: true });
5396
+ savedPath = join9(VHK_DIR2, fileName);
5397
+ writeFileSync10(savedPath, prompt, "utf-8");
5398
+ } catch {
5399
+ savedPath = "";
5400
+ }
5401
+ const copied = copyToClipboard(prompt);
5402
+ if (copied) {
5403
+ console.log(chalk26.green(`
5404
+ \u{1F4CB} Claude\uC5D0\uAC8C \uC904 '${label}'\uC744 \uD074\uB9BD\uBCF4\uB4DC\uC5D0 \uBCF5\uC0AC\uD588\uC2B5\uB2C8\uB2E4! \u2705`));
5405
+ if (savedPath) console.log(chalk26.dim(` (\uC0AC\uBCF8 \uC800\uC7A5: ${savedPath})`));
5406
+ } else {
5407
+ console.log(chalk26.yellow(`
5408
+ \u26A0\uFE0F \uD074\uB9BD\uBCF4\uB4DC \uBCF5\uC0AC\uC5D0 \uC2E4\uD328\uD588\uC5B4\uC694 \u2014 \uC544\uB798 \uD504\uB86C\uD504\uD2B8\uB97C \uC9C1\uC811 \uBCF5\uC0AC\uD558\uC138\uC694:`));
5409
+ if (savedPath) console.log(chalk26.dim(` (\uD30C\uC77C\uB85C\uB3C4 \uC800\uC7A5\uB428: ${savedPath} \u2014 \uC5F4\uC5B4\uC11C \uBCF5\uC0AC \uAC00\uB2A5)`));
5410
+ console.log(chalk26.gray("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
5411
+ console.log(prompt);
5412
+ console.log(chalk26.gray("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
5413
+ }
5414
+ }
5415
+ async function refreshContextQuietly() {
5416
+ const origLog = console.log;
5417
+ console.log = () => {
5418
+ };
5419
+ try {
5420
+ await context({ compact: true });
5421
+ return true;
5422
+ } catch {
5423
+ return false;
5424
+ } finally {
5425
+ console.log = origLog;
5426
+ }
5427
+ }
5428
+ async function work() {
5429
+ console.log(chalk26.bold(`
5430
+ ${ko.work.workTitle}`));
5431
+ console.log(chalk26.gray("\u2500".repeat(40)));
5432
+ if (!ensureVhkProject()) return;
5433
+ if (!passHardStop()) return;
5434
+ const git3 = gitShort();
5435
+ console.log("");
5436
+ console.log(chalk26.cyan("\u{1F4CB} \uBCC0\uACBD\uB41C \uD30C\uC77C"));
5437
+ printGit(git3);
5438
+ console.log("");
5439
+ console.log(chalk26.cyan("\u{1F4D6} \uADDC\uCE59"));
5440
+ console.log(" \xB7 CLAUDE.md \uAC00 1\uC21C\uC704 \uADDC\uCE59\uC785\uB2C8\uB2E4.");
5441
+ console.log(chalk26.dim(" \xB7 AGENTS.md \uB294 Codex/\uBCF4\uC870 \uC5D0\uC774\uC804\uD2B8\uC6A9 \uCC38\uACE0 \uADDC\uCE59\uC785\uB2C8\uB2E4."));
5442
+ const goalLine = activeGoalLine();
5443
+ console.log("");
5444
+ console.log(chalk26.cyan(`\u{1F3AF} \uD604\uC7AC \uBAA9\uD45C: ${goalLine}`));
5445
+ const refreshed = await refreshContextQuietly();
5446
+ console.log(chalk26.dim(refreshed ? "\u2699\uFE0F .vhk/context.md \uAC31\uC2E0\uB428" : "\u2699\uFE0F .vhk/context.md \uAC31\uC2E0 \uC0DD\uB7B5(\uAC74\uB108\uB700)"));
5447
+ const nextTaskPath = join9("docs", "state", "next-task.md");
5448
+ if (existsSync14(nextTaskPath)) {
5449
+ try {
5450
+ const lines = readFileSync7(nextTaskPath, "utf-8").split(/\r?\n/).slice(0, 12);
5451
+ console.log("");
5452
+ console.log(chalk26.cyan("\u{1F4DD} \uB2E4\uC74C \uD560 \uC77C (next-task.md)"));
5453
+ for (const l of lines) console.log(chalk26.dim(` ${l}`));
5454
+ } catch {
5455
+ }
5456
+ }
5457
+ const prompt = buildStartPrompt(git3, goalLine);
5458
+ emitPrompt(prompt, "work-prompt.md", "\uC2DC\uC791 \uD504\uB86C\uD504\uD2B8");
5459
+ printNextStep({
5460
+ message: "\uD130\uBBF8\uB110\uC5D0\uC11C claude \uB97C \uC2E4\uD589\uD55C \uB4A4, Ctrl+V \uB85C \uBD99\uC5EC\uB123\uACE0 Enter \uD558\uC138\uC694.",
5461
+ command: "claude"
5462
+ });
5463
+ }
5464
+ async function workHandoff() {
5465
+ console.log(chalk26.bold(`
5466
+ ${ko.work.handoffTitle}`));
5467
+ console.log(chalk26.gray("\u2500".repeat(40)));
5468
+ if (!ensureVhkProject()) return;
5469
+ if (!passHardStop()) return;
5470
+ const git3 = gitShort();
5471
+ console.log("");
5472
+ console.log(chalk26.cyan("\u{1F4CB} \uBC14\uB010 \uD30C\uC77C"));
5473
+ printGit(git3);
5474
+ const prompt = buildHandoffPrompt(git3);
5475
+ emitPrompt(prompt, "handoff-prompt.md", "\uC911\uB2E8 \uC815\uB9AC \uD504\uB86C\uD504\uD2B8");
5476
+ console.log("");
5477
+ console.log(chalk26.dim("\u{1F4A1} \uC774 \uBA85\uB839\uC740 \uCEE4\uBC0B\xB7\uC0AD\uC81C\uB97C \uC808\uB300 \uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC815\uB9AC\xB7\uD310\uB2E8\uC740 Claude \uAC00 \uD569\uB2C8\uB2E4."));
5478
+ printNextStep({
5479
+ message: "\uD130\uBBF8\uB110\uC5D0\uC11C claude \uB97C \uC2E4\uD589\uD55C \uB4A4, Ctrl+V \uB85C \uBD99\uC5EC\uB123\uACE0 Enter \uD558\uC138\uC694.",
5480
+ command: "claude"
5481
+ });
5482
+ }
5483
+
5484
+ // src/commands/start.ts
5485
+ import chalk27 from "chalk";
5218
5486
  import inquirer11 from "inquirer";
5219
5487
  import { simpleGit as simpleGit2 } from "simple-git";
5220
- import { existsSync as existsSync14 } from "fs";
5221
- import { join as join9 } from "path";
5488
+ import { existsSync as existsSync15 } from "fs";
5489
+ import { join as join10 } from "path";
5222
5490
  var VHK_FOOTPRINT_FILES = [
5223
5491
  "CLAUDE.md",
5224
5492
  ".cursorrules",
@@ -5227,7 +5495,7 @@ var VHK_FOOTPRINT_FILES = [
5227
5495
  "docs/PRD.md"
5228
5496
  ];
5229
5497
  function detectExistingFootprint(cwd) {
5230
- return VHK_FOOTPRINT_FILES.filter((rel) => existsSync14(join9(cwd, rel)));
5498
+ return VHK_FOOTPRINT_FILES.filter((rel) => existsSync15(join10(cwd, rel)));
5231
5499
  }
5232
5500
  async function runGitInit(cwd) {
5233
5501
  try {
@@ -5256,21 +5524,21 @@ async function runStep(label, fn) {
5256
5524
  }
5257
5525
  }
5258
5526
  async function start(options = {}) {
5259
- console.log(chalk26.bold(`
5527
+ console.log(chalk27.bold(`
5260
5528
  ${ko.start.title}
5261
5529
  `));
5262
- console.log(chalk26.dim(ko.start.intro));
5263
- console.log(chalk26.dim(` ${ko.start.step1}`));
5264
- console.log(chalk26.dim(` ${ko.start.step2}`));
5265
- console.log(chalk26.dim(` ${ko.start.step3}`));
5266
- console.log(chalk26.dim(` ${ko.start.step4}`));
5530
+ console.log(chalk27.dim(ko.start.intro));
5531
+ console.log(chalk27.dim(` ${ko.start.step1}`));
5532
+ console.log(chalk27.dim(` ${ko.start.step2}`));
5533
+ console.log(chalk27.dim(` ${ko.start.step3}`));
5534
+ console.log(chalk27.dim(` ${ko.start.step4}`));
5267
5535
  console.log();
5268
5536
  const cwd = process.cwd();
5269
5537
  const footprint = detectExistingFootprint(cwd);
5270
5538
  if (footprint.length > 0 && !options.yes) {
5271
- console.log(chalk26.yellow("\u26A0\uFE0F \uC774\uBBF8 VHK \uC124\uCE58 \uD754\uC801\uC774 \uAC10\uC9C0\uB410\uC5B4\uC694:"));
5272
- for (const f of footprint) console.log(chalk26.dim(` - ${f}`));
5273
- console.log(chalk26.dim(" \uACC4\uC18D \uC9C4\uD589\uD558\uBA74 \uC77C\uBD80 \uD30C\uC77C(`.cursor/mcp.json`, `.vhk/context.md`)\uC740 \uAC31\uC2E0\xB7\uB36E\uC5B4\uC4F0\uAE30\uB429\uB2C8\uB2E4."));
5539
+ console.log(chalk27.yellow("\u26A0\uFE0F \uC774\uBBF8 VHK \uC124\uCE58 \uD754\uC801\uC774 \uAC10\uC9C0\uB410\uC5B4\uC694:"));
5540
+ for (const f of footprint) console.log(chalk27.dim(` - ${f}`));
5541
+ console.log(chalk27.dim(" \uACC4\uC18D \uC9C4\uD589\uD558\uBA74 \uC77C\uBD80 \uD30C\uC77C(`.cursor/mcp.json`, `.vhk/context.md`)\uC740 \uAC31\uC2E0\xB7\uB36E\uC5B4\uC4F0\uAE30\uB429\uB2C8\uB2E4."));
5274
5542
  const { proceedExisting } = await inquirer11.prompt([{
5275
5543
  type: "confirm",
5276
5544
  name: "proceedExisting",
@@ -5308,7 +5576,7 @@ ${ko.start.title}
5308
5576
  await runStep("[3/4] vhk mcp-init", () => mcpInit());
5309
5577
  log.step(ko.start.step4Header);
5310
5578
  await runStep("[4/4] vhk context", () => context());
5311
- console.log(chalk26.bold.green(`
5579
+ console.log(chalk27.bold.green(`
5312
5580
  ${ko.start.allDone}
5313
5581
  `));
5314
5582
  printNextStep({
@@ -5321,7 +5589,7 @@ ${ko.start.allDone}
5321
5589
  import fs12 from "fs";
5322
5590
  import os from "os";
5323
5591
  import path13 from "path";
5324
- import chalk27 from "chalk";
5592
+ import chalk28 from "chalk";
5325
5593
 
5326
5594
  // src/lib/vhk-cloud.ts
5327
5595
  var import_ignore = __toESM(require_ignore(), 1);
@@ -5339,7 +5607,7 @@ var DEFAULT_CLOUD_EXCLUDES = [
5339
5607
  ".gitignore"
5340
5608
  // .vhk/ 내부 gitignore
5341
5609
  ];
5342
- var VHK_DIR2 = ".vhk";
5610
+ var VHK_DIR3 = ".vhk";
5343
5611
  var CLOUD_CONFIG_FILE = "cloud.json";
5344
5612
  function loadVhkignore(rootDir) {
5345
5613
  const ig = (0, import_ignore.default)();
@@ -5351,7 +5619,7 @@ function loadVhkignore(rootDir) {
5351
5619
  return ig;
5352
5620
  }
5353
5621
  function collectVhkFiles(rootDir, ig = loadVhkignore(rootDir)) {
5354
- const vhkDir = path12.join(rootDir, VHK_DIR2);
5622
+ const vhkDir = path12.join(rootDir, VHK_DIR3);
5355
5623
  let entries;
5356
5624
  try {
5357
5625
  entries = fs11.readdirSync(vhkDir, { withFileTypes: true });
@@ -5370,7 +5638,7 @@ function partitionGistFiles(gistFiles, ig) {
5370
5638
  return { keep, excluded };
5371
5639
  }
5372
5640
  function readCloudConfig(rootDir) {
5373
- const p = path12.join(rootDir, VHK_DIR2, CLOUD_CONFIG_FILE);
5641
+ const p = path12.join(rootDir, VHK_DIR3, CLOUD_CONFIG_FILE);
5374
5642
  if (!fs11.existsSync(p)) return null;
5375
5643
  try {
5376
5644
  const parsed = readJsonFile(p);
@@ -5383,7 +5651,7 @@ function readCloudConfig(rootDir) {
5383
5651
  }
5384
5652
  }
5385
5653
  function writeCloudConfig(rootDir, config) {
5386
- const vhkDir = path12.join(rootDir, VHK_DIR2);
5654
+ const vhkDir = path12.join(rootDir, VHK_DIR3);
5387
5655
  fs11.mkdirSync(vhkDir, { recursive: true });
5388
5656
  const p = path12.join(vhkDir, CLOUD_CONFIG_FILE);
5389
5657
  fs11.writeFileSync(p, JSON.stringify(config, null, 2) + "\n", "utf-8");
@@ -5413,14 +5681,14 @@ ${CLOUD_CONFIG_FILE}
5413
5681
  function ensureGhReady() {
5414
5682
  const ver = safeExecFile("gh", ["--version"]);
5415
5683
  if (!ver.ok) {
5416
- console.log(chalk27.red(` ${ko.cloud.noGh}`));
5417
- console.log(chalk27.dim(" \uC124\uCE58: https://cli.github.com/ (\uC124\uCE58 \uD6C4 `gh auth login`)"));
5684
+ console.log(chalk28.red(` ${ko.cloud.noGh}`));
5685
+ console.log(chalk28.dim(" \uC124\uCE58: https://cli.github.com/ (\uC124\uCE58 \uD6C4 `gh auth login`)"));
5418
5686
  return false;
5419
5687
  }
5420
5688
  const auth = safeExecFile("gh", ["auth", "status"]);
5421
5689
  if (!auth.ok) {
5422
- console.log(chalk27.red(` ${ko.cloud.noAuth}`));
5423
- console.log(chalk27.dim(" \uC2E4\uD589: gh auth login (gist \uAD8C\uD55C \uD544\uC694)"));
5690
+ console.log(chalk28.red(` ${ko.cloud.noAuth}`));
5691
+ console.log(chalk28.dim(" \uC2E4\uD589: gh auth login (gist \uAD8C\uD55C \uD544\uC694)"));
5424
5692
  return false;
5425
5693
  }
5426
5694
  return true;
@@ -5433,26 +5701,26 @@ function parseGistId(output) {
5433
5701
  return null;
5434
5702
  }
5435
5703
  async function cloudPush() {
5436
- console.log(chalk27.bold(`
5704
+ console.log(chalk28.bold(`
5437
5705
  ${ko.cloud.pushTitle}
5438
5706
  `));
5439
5707
  const cwd = process.cwd();
5440
- if (!fs12.existsSync(path13.join(cwd, VHK_DIR2))) {
5441
- console.log(chalk27.yellow(` ${ko.cloud.noVhkDir}`));
5708
+ if (!fs12.existsSync(path13.join(cwd, VHK_DIR3))) {
5709
+ console.log(chalk28.yellow(` ${ko.cloud.noVhkDir}`));
5442
5710
  return;
5443
5711
  }
5444
5712
  const ig = loadVhkignore(cwd);
5445
5713
  const files = collectVhkFiles(cwd, ig);
5446
5714
  if (files.length === 0) {
5447
- console.log(chalk27.yellow(` ${ko.cloud.nothingToSync}`));
5715
+ console.log(chalk28.yellow(` ${ko.cloud.nothingToSync}`));
5448
5716
  return;
5449
5717
  }
5450
5718
  if (!ensureGhReady()) {
5451
5719
  process.exitCode = 1;
5452
5720
  return;
5453
5721
  }
5454
- const filePaths = files.map((f) => path13.join(cwd, VHK_DIR2, f));
5455
- console.log(chalk27.dim(` \u{1F4E6} \uBC31\uC5C5 \uB300\uC0C1 ${files.length}\uAC1C: ${files.join(", ")}
5722
+ const filePaths = files.map((f) => path13.join(cwd, VHK_DIR3, f));
5723
+ console.log(chalk28.dim(` \u{1F4E6} \uBC31\uC5C5 \uB300\uC0C1 ${files.length}\uAC1C: ${files.join(", ")}
5456
5724
  `));
5457
5725
  const existing = readCloudConfig(cwd);
5458
5726
  const desc = `vhk .vhk backup \u2014 ${path13.basename(cwd)}`;
@@ -5464,8 +5732,8 @@ ${ko.cloud.pushTitle}
5464
5732
  const args = gistFiles.includes(name) ? ["gist", "edit", existing.gistId, "-f", name, src] : ["gist", "edit", existing.gistId, "-a", src];
5465
5733
  const res2 = safeExecFile("gh", args);
5466
5734
  if (!res2.ok) {
5467
- console.log(chalk27.red(` ${ko.cloud.pushFail}: ${name}`));
5468
- console.log(chalk27.dim(` ${res2.err}`));
5735
+ console.log(chalk28.red(` ${ko.cloud.pushFail}: ${name}`));
5736
+ console.log(chalk28.dim(` ${res2.err}`));
5469
5737
  process.exitCode = 1;
5470
5738
  return;
5471
5739
  }
@@ -5480,15 +5748,15 @@ ${ko.cloud.pushTitle}
5480
5748
  if (!purgeFailed.includes(name)) purgeFailed.push(name);
5481
5749
  }
5482
5750
  }
5483
- console.log(chalk27.green.bold(` ${ko.cloud.pushDone}`));
5484
- console.log(chalk27.dim(` gist: ${existing.gistId} (\uAC31\uC2E0)`));
5751
+ console.log(chalk28.green.bold(` ${ko.cloud.pushDone}`));
5752
+ console.log(chalk28.dim(` gist: ${existing.gistId} (\uAC31\uC2E0)`));
5485
5753
  if (excluded.length > 0) {
5486
5754
  const purged = excluded.filter((n) => !purgeFailed.includes(n));
5487
5755
  if (purged.length > 0) {
5488
- console.log(chalk27.dim(` \u{1F512} \uC81C\uC678 \uB300\uC0C1 ${purged.length}\uAC1C gist \uC5D0\uC11C \uC81C\uAC70: ${purged.join(", ")}`));
5756
+ console.log(chalk28.dim(` \u{1F512} \uC81C\uC678 \uB300\uC0C1 ${purged.length}\uAC1C gist \uC5D0\uC11C \uC81C\uAC70: ${purged.join(", ")}`));
5489
5757
  }
5490
5758
  if (purgeFailed.length > 0) {
5491
- console.log(chalk27.yellow(` \u26A0\uFE0F \uC81C\uC678 \uB300\uC0C1 \uC81C\uAC70 \uC2E4\uD328: ${purgeFailed.join(", ")} (\uC218\uB3D9 \uC81C\uAC70 \uAD8C\uC7A5 \u2014 pull \uC2DC\uC5D4 \uBCF5\uC6D0 \uC548 \uB428)`));
5759
+ console.log(chalk28.yellow(` \u26A0\uFE0F \uC81C\uC678 \uB300\uC0C1 \uC81C\uAC70 \uC2E4\uD328: ${purgeFailed.join(", ")} (\uC218\uB3D9 \uC81C\uAC70 \uAD8C\uC7A5 \u2014 pull \uC2DC\uC5D4 \uBCF5\uC6D0 \uC548 \uB428)`));
5492
5760
  }
5493
5761
  }
5494
5762
  printPushNext();
@@ -5496,32 +5764,32 @@ ${ko.cloud.pushTitle}
5496
5764
  }
5497
5765
  const res = safeExecFile("gh", ["gist", "create", "--desc", desc, ...filePaths]);
5498
5766
  if (!res.ok) {
5499
- console.log(chalk27.red(` ${ko.cloud.pushFail}`));
5500
- console.log(chalk27.dim(` ${res.err || res.out}`));
5767
+ console.log(chalk28.red(` ${ko.cloud.pushFail}`));
5768
+ console.log(chalk28.dim(` ${res.err || res.out}`));
5501
5769
  process.exitCode = 1;
5502
5770
  return;
5503
5771
  }
5504
5772
  const gistId = parseGistId(res.out);
5505
5773
  if (!gistId) {
5506
- console.log(chalk27.red(` ${ko.cloud.pushFail} \u2014 gist id \uD30C\uC2F1 \uC2E4\uD328`));
5507
- console.log(chalk27.dim(` \uCD9C\uB825: ${res.out}`));
5774
+ console.log(chalk28.red(` ${ko.cloud.pushFail} \u2014 gist id \uD30C\uC2F1 \uC2E4\uD328`));
5775
+ console.log(chalk28.dim(` \uCD9C\uB825: ${res.out}`));
5508
5776
  process.exitCode = 1;
5509
5777
  return;
5510
5778
  }
5511
5779
  writeCloudConfig(cwd, { gistId });
5512
- console.log(chalk27.green.bold(` ${ko.cloud.pushDone}`));
5513
- console.log(chalk27.dim(` gist: ${gistId} (\uC2E0\uADDC, secret) \u2192 .vhk/cloud.json \uC800\uC7A5`));
5780
+ console.log(chalk28.green.bold(` ${ko.cloud.pushDone}`));
5781
+ console.log(chalk28.dim(` gist: ${gistId} (\uC2E0\uADDC, secret) \u2192 .vhk/cloud.json \uC800\uC7A5`));
5514
5782
  printPushNext();
5515
5783
  }
5516
5784
  async function cloudPull(gistIdArg) {
5517
- console.log(chalk27.bold(`
5785
+ console.log(chalk28.bold(`
5518
5786
  ${ko.cloud.pullTitle}
5519
5787
  `));
5520
5788
  const cwd = process.cwd();
5521
5789
  const gistId = gistIdArg || readCloudConfig(cwd)?.gistId;
5522
5790
  if (!gistId) {
5523
- console.log(chalk27.yellow(` ${ko.cloud.noGistId}`));
5524
- console.log(chalk27.dim(" \uC0AC\uC6A9\uBC95: vhk cloud pull <gistId> (\uB610\uB294 cloud.json \uC774 \uC788\uB294 \uACF3\uC5D0\uC11C \uC2E4\uD589)"));
5791
+ console.log(chalk28.yellow(` ${ko.cloud.noGistId}`));
5792
+ console.log(chalk28.dim(" \uC0AC\uC6A9\uBC95: vhk cloud pull <gistId> (\uB610\uB294 cloud.json \uC774 \uC788\uB294 \uACF3\uC5D0\uC11C \uC2E4\uD589)"));
5525
5793
  return;
5526
5794
  }
5527
5795
  if (!ensureGhReady()) {
@@ -5530,34 +5798,34 @@ ${ko.cloud.pullTitle}
5530
5798
  }
5531
5799
  const allNames = listGistFiles(gistId);
5532
5800
  if (allNames.length === 0) {
5533
- console.log(chalk27.red(` ${ko.cloud.pullFail} \u2014 gist \uBE44\uC5C8\uAC70\uB098 \uC811\uADFC \uBD88\uAC00: ${gistId}`));
5801
+ console.log(chalk28.red(` ${ko.cloud.pullFail} \u2014 gist \uBE44\uC5C8\uAC70\uB098 \uC811\uADFC \uBD88\uAC00: ${gistId}`));
5534
5802
  process.exitCode = 1;
5535
5803
  return;
5536
5804
  }
5537
5805
  const { keep: names, excluded: skipped } = partitionGistFiles(allNames, loadVhkignore(cwd));
5538
5806
  if (skipped.length > 0) {
5539
- console.log(chalk27.dim(` \u{1F512} \uC81C\uC678 \uB300\uC0C1 ${skipped.length}\uAC1C \uBCF5\uC6D0 \uC2A4\uD0B5: ${skipped.join(", ")}`));
5807
+ console.log(chalk28.dim(` \u{1F512} \uC81C\uC678 \uB300\uC0C1 ${skipped.length}\uAC1C \uBCF5\uC6D0 \uC2A4\uD0B5: ${skipped.join(", ")}`));
5540
5808
  }
5541
5809
  if (names.length === 0) {
5542
- console.log(chalk27.yellow(` \uBCF5\uC6D0 \uB300\uC0C1\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 (gist \uD30C\uC77C\uC774 \uBAA8\uB450 \uC81C\uC678 \uADDC\uCE59\uC5D0 \uD574\uB2F9).`));
5810
+ console.log(chalk28.yellow(` \uBCF5\uC6D0 \uB300\uC0C1\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 (gist \uD30C\uC77C\uC774 \uBAA8\uB450 \uC81C\uC678 \uADDC\uCE59\uC5D0 \uD574\uB2F9).`));
5543
5811
  return;
5544
5812
  }
5545
- const vhkDir = path13.join(cwd, VHK_DIR2);
5813
+ const vhkDir = path13.join(cwd, VHK_DIR3);
5546
5814
  fs12.mkdirSync(vhkDir, { recursive: true });
5547
5815
  let restored = 0;
5548
5816
  for (const name of names) {
5549
5817
  const res = safeExecFile("gh", ["gist", "view", gistId, "-f", name, "--raw"]);
5550
5818
  if (!res.ok) {
5551
- console.log(chalk27.red(` ${ko.cloud.pullFail}: ${name}`));
5552
- console.log(chalk27.dim(` ${res.err}`));
5819
+ console.log(chalk28.red(` ${ko.cloud.pullFail}: ${name}`));
5820
+ console.log(chalk28.dim(` ${res.err}`));
5553
5821
  continue;
5554
5822
  }
5555
5823
  fs12.writeFileSync(path13.join(vhkDir, name), ensureTrailingNewline(res.out), "utf-8");
5556
5824
  restored++;
5557
5825
  }
5558
5826
  writeCloudConfig(cwd, { gistId });
5559
- console.log(chalk27.green.bold(` ${ko.cloud.pullDone}`));
5560
- console.log(chalk27.dim(` ${restored}\uAC1C \uD30C\uC77C \uBCF5\uC6D0 (gist: ${gistId})`));
5827
+ console.log(chalk28.green.bold(` ${ko.cloud.pullDone}`));
5828
+ console.log(chalk28.dim(` ${restored}\uAC1C \uD30C\uC77C \uBCF5\uC6D0 (gist: ${gistId})`));
5561
5829
  printNextStep({
5562
5830
  message: "\uD074\uB77C\uC6B0\uB4DC\uC5D0\uC11C .vhk/ \uBCF5\uC6D0 \uC644\uB8CC!",
5563
5831
  command: "vhk \uB9E5\uB77D",
@@ -5605,7 +5873,7 @@ function printPushNext() {
5605
5873
  }
5606
5874
 
5607
5875
  // src/commands/help.ts
5608
- import chalk28 from "chalk";
5876
+ import chalk29 from "chalk";
5609
5877
  var QUICK_ACTIONS = [
5610
5878
  { say: "\uC0C1\uD0DC \uC54C\uB824\uC918", does: "vhk status" },
5611
5879
  { say: "\uBB50 \uBC14\uB00C\uC5C8\uC5B4?", does: "vhk diff" },
@@ -5619,21 +5887,21 @@ var QUICK_ACTIONS = [
5619
5887
  { say: "\uC804\uCCB4 \uBA85\uB839\uC5B4 \uBCF4\uAE30", does: "vhk --help" }
5620
5888
  ];
5621
5889
  function quickActions() {
5622
- console.log(chalk28.bold("\n\u{1F9ED} VHK \u2014 \uC774\uB807\uAC8C \uB9D0\uD558\uBA74 \uB429\uB2C8\uB2E4 (quick actions)"));
5623
- console.log(chalk28.gray("\u2500".repeat(40)));
5890
+ console.log(chalk29.bold("\n\u{1F9ED} VHK \u2014 \uC774\uB807\uAC8C \uB9D0\uD558\uBA74 \uB429\uB2C8\uB2E4 (quick actions)"));
5891
+ console.log(chalk29.gray("\u2500".repeat(40)));
5624
5892
  for (const a of QUICK_ACTIONS) {
5625
- console.log(` "${chalk28.cyan(a.say)}" \u2192 ${chalk28.dim(a.does)}`);
5893
+ console.log(` "${chalk29.cyan(a.say)}" \u2192 ${chalk29.dim(a.does)}`);
5626
5894
  }
5627
- console.log(chalk28.gray("\n \uC804\uCCB4 \uBA85\uB839\uC740 `vhk --help` \uB610\uB294 COMMANDS.md \uB97C \uBCF4\uC138\uC694."));
5895
+ console.log(chalk29.gray("\n \uC804\uCCB4 \uBA85\uB839\uC740 `vhk --help` \uB610\uB294 COMMANDS.md \uB97C \uBCF4\uC138\uC694."));
5628
5896
  console.log("");
5629
5897
  }
5630
5898
 
5631
5899
  // src/commands/mode.ts
5632
- import chalk29 from "chalk";
5900
+ import chalk30 from "chalk";
5633
5901
 
5634
5902
  // src/lib/config.ts
5635
- import { existsSync as existsSync15, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
5636
- import { join as join10 } from "path";
5903
+ import { existsSync as existsSync16, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "fs";
5904
+ import { join as join11 } from "path";
5637
5905
 
5638
5906
  // src/lib/safety-mode.ts
5639
5907
  var SAFETY_MODES = ["lite", "standard", "strict"];
@@ -5649,11 +5917,11 @@ function isSafetyMode(value) {
5649
5917
 
5650
5918
  // src/lib/config.ts
5651
5919
  var CONFIG_DIR = ".vhk";
5652
- var CONFIG_PATH = join10(CONFIG_DIR, "config.json");
5920
+ var CONFIG_PATH = join11(CONFIG_DIR, "config.json");
5653
5921
  var DEFAULT_CONFIG = { safetyMode: DEFAULT_SAFETY_MODE };
5654
5922
  function readConfig(rootDir = process.cwd()) {
5655
- const full = join10(rootDir, CONFIG_PATH);
5656
- if (!existsSync15(full)) return { ...DEFAULT_CONFIG };
5923
+ const full = join11(rootDir, CONFIG_PATH);
5924
+ if (!existsSync16(full)) return { ...DEFAULT_CONFIG };
5657
5925
  try {
5658
5926
  const raw = readJsonFile(full);
5659
5927
  return {
@@ -5664,23 +5932,23 @@ function readConfig(rootDir = process.cwd()) {
5664
5932
  }
5665
5933
  }
5666
5934
  function writeConfig(config, rootDir = process.cwd()) {
5667
- mkdirSync10(join10(rootDir, CONFIG_DIR), { recursive: true });
5668
- writeFileSync10(join10(rootDir, CONFIG_PATH), JSON.stringify(config, null, 2) + "\n", "utf-8");
5935
+ mkdirSync11(join11(rootDir, CONFIG_DIR), { recursive: true });
5936
+ writeFileSync11(join11(rootDir, CONFIG_PATH), JSON.stringify(config, null, 2) + "\n", "utf-8");
5669
5937
  }
5670
5938
 
5671
5939
  // src/commands/mode.ts
5672
5940
  async function mode(target) {
5673
- console.log(chalk29.bold("\n\u{1F6E1}\uFE0F Safety Mode"));
5674
- console.log(chalk29.gray("\u2500".repeat(40)));
5941
+ console.log(chalk30.bold("\n\u{1F6E1}\uFE0F Safety Mode"));
5942
+ console.log(chalk30.gray("\u2500".repeat(40)));
5675
5943
  const current = readConfig().safetyMode;
5676
5944
  if (!target) {
5677
- console.log(chalk29.cyan(`
5678
- \uD604\uC7AC \uBAA8\uB4DC: ${chalk29.bold(current)}`));
5679
- console.log(chalk29.dim(` ${SAFETY_MODE_DESC[current]}`));
5945
+ console.log(chalk30.cyan(`
5946
+ \uD604\uC7AC \uBAA8\uB4DC: ${chalk30.bold(current)}`));
5947
+ console.log(chalk30.dim(` ${SAFETY_MODE_DESC[current]}`));
5680
5948
  console.log("");
5681
5949
  for (const m of SAFETY_MODES) {
5682
5950
  const mark = m === current ? "\u25CF" : "\u25CB";
5683
- console.log(` ${mark} ${m.padEnd(9)} ${chalk29.dim(SAFETY_MODE_DESC[m])}`);
5951
+ console.log(` ${mark} ${m.padEnd(9)} ${chalk30.dim(SAFETY_MODE_DESC[m])}`);
5684
5952
  }
5685
5953
  printNextStep({
5686
5954
  message: "\uBAA8\uB4DC\uB97C \uBC14\uAFB8\uB824\uBA74:",
@@ -5690,23 +5958,23 @@ async function mode(target) {
5690
5958
  return;
5691
5959
  }
5692
5960
  if (!isSafetyMode(target)) {
5693
- console.log(chalk29.red(`
5961
+ console.log(chalk30.red(`
5694
5962
  \u274C \uC54C \uC218 \uC5C6\uB294 \uBAA8\uB4DC: ${target}`));
5695
- console.log(chalk29.dim(` \uAC00\uB2A5: ${SAFETY_MODES.join(" | ")}`));
5963
+ console.log(chalk30.dim(` \uAC00\uB2A5: ${SAFETY_MODES.join(" | ")}`));
5696
5964
  process.exitCode = 1;
5697
5965
  return;
5698
5966
  }
5699
5967
  writeConfig({ ...readConfig(), safetyMode: target });
5700
- console.log(chalk29.green(`
5701
- \u2705 Safety Mode \u2192 ${chalk29.bold(target)}`));
5702
- console.log(chalk29.dim(` ${SAFETY_MODE_DESC[target]}`));
5968
+ console.log(chalk30.green(`
5969
+ \u2705 Safety Mode \u2192 ${chalk30.bold(target)}`));
5970
+ console.log(chalk30.dim(` ${SAFETY_MODE_DESC[target]}`));
5703
5971
  }
5704
5972
 
5705
5973
  // src/commands/verify.ts
5706
5974
  import { execFileSync as execFileSync4 } from "child_process";
5707
- import { existsSync as existsSync16, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "fs";
5708
- import { join as join11 } from "path";
5709
- import chalk30 from "chalk";
5975
+ import { existsSync as existsSync17, mkdirSync as mkdirSync12, writeFileSync as writeFileSync12 } from "fs";
5976
+ import { join as join12 } from "path";
5977
+ import chalk31 from "chalk";
5710
5978
 
5711
5979
  // src/commands/verify-report.ts
5712
5980
  function escapeHtml(text) {
@@ -5814,13 +6082,13 @@ ${actions}
5814
6082
 
5815
6083
  // src/commands/verify.ts
5816
6084
  var REPORT_SCHEMA_VERSION = 1;
5817
- var REPORT_DIR_REL = join11(".vhk", "reports");
5818
- var REPORT_PATH_REL = join11(REPORT_DIR_REL, "latest.json");
5819
- var REPORT_HTML_PATH_REL = join11(REPORT_DIR_REL, "latest.html");
6085
+ var REPORT_DIR_REL = join12(".vhk", "reports");
6086
+ var REPORT_PATH_REL = join12(REPORT_DIR_REL, "latest.json");
6087
+ var REPORT_HTML_PATH_REL = join12(REPORT_DIR_REL, "latest.html");
5820
6088
  var SHIM = /* @__PURE__ */ new Set(["pnpm", "npm", "npx", "yarn"]);
5821
6089
  function detectPm(cwd) {
5822
- if (existsSync16(join11(cwd, "pnpm-lock.yaml"))) return "pnpm";
5823
- if (existsSync16(join11(cwd, "yarn.lock"))) return "yarn";
6090
+ if (existsSync17(join12(cwd, "pnpm-lock.yaml"))) return "pnpm";
6091
+ if (existsSync17(join12(cwd, "yarn.lock"))) return "yarn";
5824
6092
  return "npm";
5825
6093
  }
5826
6094
  function execGate(cmd, args, cwd) {
@@ -5863,8 +6131,8 @@ function runScriptGate(id, label, cwd, pm, argvFor) {
5863
6131
  };
5864
6132
  }
5865
6133
  function readPackageScripts(cwd) {
5866
- const pkgPath = join11(cwd, "package.json");
5867
- if (!existsSync16(pkgPath)) return {};
6134
+ const pkgPath = join12(cwd, "package.json");
6135
+ if (!existsSync17(pkgPath)) return {};
5868
6136
  try {
5869
6137
  const pkg = readJsonFile(pkgPath);
5870
6138
  return pkg.scripts ?? {};
@@ -5879,7 +6147,7 @@ function runGates(cwd) {
5879
6147
  gates.push(
5880
6148
  runScriptGate("typecheck", "tsc --noEmit", cwd, pm, () => {
5881
6149
  if (scripts.typecheck) return ["run", "typecheck"];
5882
- if (existsSync16(join11(cwd, "tsconfig.json"))) return pm === "npm" ? ["exec", "--", "tsc", "--noEmit"] : ["exec", "tsc", "--noEmit"];
6150
+ if (existsSync17(join12(cwd, "tsconfig.json"))) return pm === "npm" ? ["exec", "--", "tsc", "--noEmit"] : ["exec", "tsc", "--noEmit"];
5883
6151
  return null;
5884
6152
  })
5885
6153
  );
@@ -5958,10 +6226,10 @@ function buildReport(gates, generatedAt, date) {
5958
6226
  function verifyEvidence(cwd = process.cwd()) {
5959
6227
  const gates = runGates(cwd);
5960
6228
  const report = buildReport(gates, (/* @__PURE__ */ new Date()).toISOString(), localDate());
5961
- const dir = join11(cwd, REPORT_DIR_REL);
5962
- mkdirSync11(dir, { recursive: true });
5963
- const path14 = join11(cwd, REPORT_PATH_REL);
5964
- writeFileSync11(path14, JSON.stringify(report, null, 2) + "\n", "utf-8");
6229
+ const dir = join12(cwd, REPORT_DIR_REL);
6230
+ mkdirSync12(dir, { recursive: true });
6231
+ const path14 = join12(cwd, REPORT_PATH_REL);
6232
+ writeFileSync12(path14, JSON.stringify(report, null, 2) + "\n", "utf-8");
5965
6233
  try {
5966
6234
  ensureVhkIgnored(cwd, "reports/");
5967
6235
  } catch {
@@ -5969,44 +6237,44 @@ function verifyEvidence(cwd = process.cwd()) {
5969
6237
  return { report, path: REPORT_PATH_REL };
5970
6238
  }
5971
6239
  var STATUS_BADGE = {
5972
- PASS: chalk30.green.bold("PASS"),
5973
- WARN: chalk30.yellow.bold("WARN"),
5974
- FAIL: chalk30.red.bold("FAIL")
6240
+ PASS: chalk31.green.bold("PASS"),
6241
+ WARN: chalk31.yellow.bold("WARN"),
6242
+ FAIL: chalk31.red.bold("FAIL")
5975
6243
  };
5976
6244
  async function renderVerifyReport(cwd, opts) {
5977
- const jsonPath = join11(cwd, REPORT_PATH_REL);
6245
+ const jsonPath = join12(cwd, REPORT_PATH_REL);
5978
6246
  let report;
5979
- if (existsSync16(jsonPath)) {
6247
+ if (existsSync17(jsonPath)) {
5980
6248
  try {
5981
6249
  report = readJsonFile(jsonPath);
5982
6250
  } catch {
5983
- console.log(chalk30.yellow(" \u26A0\uFE0F \uAE30\uC874 latest.json \uC190\uC0C1 \u2014 verify \uC7AC\uC2E4\uD589\uC73C\uB85C \uC99D\uAC70\uB97C \uB2E4\uC2DC \uB9CC\uB4ED\uB2C8\uB2E4."));
6251
+ console.log(chalk31.yellow(" \u26A0\uFE0F \uAE30\uC874 latest.json \uC190\uC0C1 \u2014 verify \uC7AC\uC2E4\uD589\uC73C\uB85C \uC99D\uAC70\uB97C \uB2E4\uC2DC \uB9CC\uB4ED\uB2C8\uB2E4."));
5984
6252
  report = verifyEvidence(cwd).report;
5985
6253
  }
5986
6254
  } else {
5987
- console.log(chalk30.dim(" latest.json \uC5C6\uC74C \u2014 verify 1\uD68C \uC120\uC2E4\uD589\uC73C\uB85C \uC99D\uAC70\uB97C \uB9CC\uB4ED\uB2C8\uB2E4."));
6255
+ console.log(chalk31.dim(" latest.json \uC5C6\uC74C \u2014 verify 1\uD68C \uC120\uC2E4\uD589\uC73C\uB85C \uC99D\uAC70\uB97C \uB9CC\uB4ED\uB2C8\uB2E4."));
5988
6256
  report = verifyEvidence(cwd).report;
5989
6257
  }
5990
6258
  const html = renderReportHtml(report);
5991
- const htmlPath = join11(cwd, REPORT_HTML_PATH_REL);
6259
+ const htmlPath = join12(cwd, REPORT_HTML_PATH_REL);
5992
6260
  try {
5993
- mkdirSync11(join11(cwd, REPORT_DIR_REL), { recursive: true });
5994
- writeFileSync11(htmlPath, html, "utf-8");
6261
+ mkdirSync12(join12(cwd, REPORT_DIR_REL), { recursive: true });
6262
+ writeFileSync12(htmlPath, html, "utf-8");
5995
6263
  } catch (e) {
5996
6264
  console.error(
5997
- chalk30.red(` \u274C \uB9AC\uD3EC\uD2B8 HTML \uC744 \uC4F8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 (${REPORT_HTML_PATH_REL}): ${e instanceof Error ? e.message : String(e)}`)
6265
+ chalk31.red(` \u274C \uB9AC\uD3EC\uD2B8 HTML \uC744 \uC4F8 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 (${REPORT_HTML_PATH_REL}): ${e instanceof Error ? e.message : String(e)}`)
5998
6266
  );
5999
- console.error(chalk30.dim(" \uD574\uB2F9 \uACBD\uB85C\uC758 \uC4F0\uAE30 \uAD8C\uD55C\uC744 \uD655\uC778\uD558\uC138\uC694."));
6267
+ console.error(chalk31.dim(" \uD574\uB2F9 \uACBD\uB85C\uC758 \uC4F0\uAE30 \uAD8C\uD55C\uC744 \uD655\uC778\uD558\uC138\uC694."));
6000
6268
  process.exitCode = 1;
6001
6269
  return;
6002
6270
  }
6003
- console.log(chalk30.bold("\n\u{1F50E} \uAC80\uC99D \uB9AC\uD3EC\uD2B8 (verify --report)"));
6271
+ console.log(chalk31.bold("\n\u{1F50E} \uAC80\uC99D \uB9AC\uD3EC\uD2B8 (verify --report)"));
6004
6272
  console.log(` \uACB0\uACFC: ${STATUS_BADGE[report.status]}`);
6005
- console.log(chalk30.dim(` \u{1F4C4} HTML: ${REPORT_HTML_PATH_REL}`));
6273
+ console.log(chalk31.dim(` \u{1F4C4} HTML: ${REPORT_HTML_PATH_REL}`));
6006
6274
  process.exitCode = report.status === "FAIL" ? 1 : 0;
6007
6275
  if (opts.open) {
6008
6276
  if (isInteractive()) openReportInBrowser(htmlPath);
6009
- else console.log(chalk30.dim(" (\uBE44\uB300\uD654\uD615/CI/MCP \u2014 --open \uC790\uB3D9 \uC2A4\uD0B5)"));
6277
+ else console.log(chalk31.dim(" (\uBE44\uB300\uD654\uD615/CI/MCP \u2014 --open \uC790\uB3D9 \uC2A4\uD0B5)"));
6010
6278
  return;
6011
6279
  }
6012
6280
  printNextStep({
@@ -6024,8 +6292,8 @@ function openReportInBrowser(filePath) {
6024
6292
  } else {
6025
6293
  result = safeExecFile("xdg-open", [filePath]);
6026
6294
  }
6027
- if (result.ok) console.log(chalk30.green(" \u2705 \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4."));
6028
- else console.log(chalk30.yellow(" \u26A0\uFE0F \uBE0C\uB77C\uC6B0\uC800\uB97C \uC5F4 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC704 \uD30C\uC77C\uC744 \uC9C1\uC811 \uC5EC\uC138\uC694."));
6295
+ if (result.ok) console.log(chalk31.green(" \u2705 \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4."));
6296
+ else console.log(chalk31.yellow(" \u26A0\uFE0F \uBE0C\uB77C\uC6B0\uC800\uB97C \uC5F4 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC704 \uD30C\uC77C\uC744 \uC9C1\uC811 \uC5EC\uC138\uC694."));
6029
6297
  }
6030
6298
  async function verify(opts = {}) {
6031
6299
  if (!ensureNotHardStopped("verify")) return;
@@ -6040,21 +6308,21 @@ async function verify(opts = {}) {
6040
6308
  process.exitCode = report.status === "FAIL" ? 1 : 0;
6041
6309
  return;
6042
6310
  }
6043
- console.log(chalk30.bold("\n\u{1F50E} \uAC80\uC99D \uBB36\uC74C (verify)"));
6044
- console.log(chalk30.gray("\u2500".repeat(40)));
6311
+ console.log(chalk31.bold("\n\u{1F50E} \uAC80\uC99D \uBB36\uC74C (verify)"));
6312
+ console.log(chalk31.gray("\u2500".repeat(40)));
6045
6313
  const mode2 = readConfig().safetyMode;
6046
- console.log(chalk30.dim(` \uD604\uC7AC Safety Mode: ${mode2} \u2014 ${SAFETY_MODE_DESC[mode2]}`));
6047
- const icon = (s2) => s2 === "pass" ? chalk30.green("\u2713") : s2 === "fail" ? chalk30.red("\u2717") : chalk30.yellow("\u2298");
6314
+ console.log(chalk31.dim(` \uD604\uC7AC Safety Mode: ${mode2} \u2014 ${SAFETY_MODE_DESC[mode2]}`));
6315
+ const icon = (s2) => s2 === "pass" ? chalk31.green("\u2713") : s2 === "fail" ? chalk31.red("\u2717") : chalk31.yellow("\u2298");
6048
6316
  for (const g of report.gates) {
6049
- const tail = g.detail ? chalk30.dim(` \u2014 ${g.detail}`) : "";
6317
+ const tail = g.detail ? chalk31.dim(` \u2014 ${g.detail}`) : "";
6050
6318
  console.log(` ${icon(g.status)} ${g.label}${tail}`);
6051
6319
  }
6052
6320
  const s = report.summary;
6053
6321
  console.log(
6054
6322
  `
6055
- \uACB0\uACFC: ${STATUS_BADGE[report.status]} ` + chalk30.dim(`(pass ${s.pass} / fail ${s.fail} / skip ${s.skip}, \uCD1D ${s.total})`)
6323
+ \uACB0\uACFC: ${STATUS_BADGE[report.status]} ` + chalk31.dim(`(pass ${s.pass} / fail ${s.fail} / skip ${s.skip}, \uCD1D ${s.total})`)
6056
6324
  );
6057
- console.log(chalk30.dim(` \u{1F4C4} \uC99D\uAC70: ${path14}`));
6325
+ console.log(chalk31.dim(` \u{1F4C4} \uC99D\uAC70: ${path14}`));
6058
6326
  process.exitCode = report.status === "FAIL" ? 1 : 0;
6059
6327
  if (report.status === "FAIL") {
6060
6328
  printNextStep({
@@ -6073,9 +6341,9 @@ async function verify(opts = {}) {
6073
6341
  }
6074
6342
 
6075
6343
  // src/commands/review.ts
6076
- import { existsSync as existsSync17, writeFileSync as writeFileSync12 } from "fs";
6077
- import { join as join12 } from "path";
6078
- import chalk31 from "chalk";
6344
+ import { existsSync as existsSync18, writeFileSync as writeFileSync13 } from "fs";
6345
+ import { join as join13 } from "path";
6346
+ import chalk32 from "chalk";
6079
6347
  var GOALS_DIR2 = "goals";
6080
6348
  var COVERAGE_MIN = 0.5;
6081
6349
  var STALE_AGE_MS = 6 * 60 * 60 * 1e3;
@@ -6207,22 +6475,22 @@ function resolveGoal(optId, goals) {
6207
6475
  return goals.find((g) => g.frontmatter.id === id) ?? null;
6208
6476
  }
6209
6477
  var CONFIDENCE_LABEL = {
6210
- low: chalk31.red.bold("\uB0AE\uC74C (\uAC70\uC9D3\uC644\uB8CC \uC758\uC2EC \uB610\uB294 \uC644\uB8CC \uC8FC\uC7A5 \uC5C6\uC74C)"),
6211
- medium: chalk31.yellow.bold("\uC911\uAC04 (\uCEE4\uBC84\uB9AC\uC9C0/\uC2E0\uC120\uB3C4 \uBD80\uC871 \u2014 \uC99D\uAC70 \uC5C6\uC74C \u2260 \uD1B5\uACFC)"),
6212
- high: chalk31.green.bold("\uB192\uC74C (\uC758\uC2EC 0 + \uCEE4\uBC84\uB9AC\uC9C0\xB7\uC2E0\uC120\uB3C4 \uCDA9\uBD84 \u2014 \uB2E8 \uBCF4\uC7A5 \uC544\uB2D8)")
6478
+ low: chalk32.red.bold("\uB0AE\uC74C (\uAC70\uC9D3\uC644\uB8CC \uC758\uC2EC \uB610\uB294 \uC644\uB8CC \uC8FC\uC7A5 \uC5C6\uC74C)"),
6479
+ medium: chalk32.yellow.bold("\uC911\uAC04 (\uCEE4\uBC84\uB9AC\uC9C0/\uC2E0\uC120\uB3C4 \uBD80\uC871 \u2014 \uC99D\uAC70 \uC5C6\uC74C \u2260 \uD1B5\uACFC)"),
6480
+ high: chalk32.green.bold("\uB192\uC74C (\uC758\uC2EC 0 + \uCEE4\uBC84\uB9AC\uC9C0\xB7\uC2E0\uC120\uB3C4 \uCDA9\uBD84 \u2014 \uB2E8 \uBCF4\uC7A5 \uC544\uB2D8)")
6213
6481
  };
6214
6482
  async function review(opts = {}) {
6215
6483
  if (!ensureNotHardStopped("review")) return;
6216
6484
  const cwd = process.cwd();
6217
6485
  const goals = listGoals(GOALS_DIR2);
6218
6486
  if (goals.length === 0) {
6219
- console.error(chalk31.yellow(" \u26A0\uFE0F goals/ \uC5D0 goal \uC774 \uC5C6\uC2B5\uB2C8\uB2E4. vhk goal init \uC73C\uB85C \uC2DC\uC791\uD558\uC138\uC694."));
6487
+ console.error(chalk32.yellow(" \u26A0\uFE0F goals/ \uC5D0 goal \uC774 \uC5C6\uC2B5\uB2C8\uB2E4. vhk goal init \uC73C\uB85C \uC2DC\uC791\uD558\uC138\uC694."));
6220
6488
  process.exitCode = 1;
6221
6489
  return;
6222
6490
  }
6223
6491
  const goal = resolveGoal(opts.id, goals);
6224
6492
  if (!goal || typeof goal.frontmatter.id !== "number") {
6225
- console.error(chalk31.red(` \u274C \uB300\uC0C1 goal \uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4${opts.id ? ` (--id ${opts.id})` : " (active goal \uC5C6\uC74C)"}.`));
6493
+ console.error(chalk32.red(` \u274C \uB300\uC0C1 goal \uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4${opts.id ? ` (--id ${opts.id})` : " (active goal \uC5C6\uC74C)"}.`));
6226
6494
  process.exitCode = 1;
6227
6495
  return;
6228
6496
  }
@@ -6230,11 +6498,11 @@ async function review(opts = {}) {
6230
6498
  const goalStatus = goal.frontmatter.status ?? "NOT_STARTED";
6231
6499
  const checks = parseCompletionChecks(goal.body);
6232
6500
  if (opts.id === void 0 && goalStatus === "NOT_STARTED") {
6233
- console.error(chalk31.yellow(` \u26A0\uFE0F active goal ${goalId} \uAC00 NOT_STARTED \u2014 \uC644\uB8CC \uC8FC\uC7A5\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uAC80\uC99D \uB300\uC0C1\uC740 --id \uB85C \uC9C0\uC815\uD558\uC138\uC694.`));
6501
+ console.error(chalk32.yellow(` \u26A0\uFE0F active goal ${goalId} \uAC00 NOT_STARTED \u2014 \uC644\uB8CC \uC8FC\uC7A5\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uAC80\uC99D \uB300\uC0C1\uC740 --id \uB85C \uC9C0\uC815\uD558\uC138\uC694.`));
6234
6502
  }
6235
- const jsonPath = join12(cwd, REPORT_PATH_REL);
6236
- if (!existsSync17(jsonPath)) {
6237
- console.error(chalk31.yellow(` \u26A0\uFE0F \uC99D\uAC70 \uBD80\uC7AC \u2014 ${REPORT_PATH_REL} \uC5C6\uC74C. review \uB97C \uC911\uB2E8\uD569\uB2C8\uB2E4(\uC0C8 \uC99D\uAC70 \uC548 \uB9CC\uB4E6).`));
6503
+ const jsonPath = join13(cwd, REPORT_PATH_REL);
6504
+ if (!existsSync18(jsonPath)) {
6505
+ console.error(chalk32.yellow(` \u26A0\uFE0F \uC99D\uAC70 \uBD80\uC7AC \u2014 ${REPORT_PATH_REL} \uC5C6\uC74C. review \uB97C \uC911\uB2E8\uD569\uB2C8\uB2E4(\uC0C8 \uC99D\uAC70 \uC548 \uB9CC\uB4E6).`));
6238
6506
  printNextStep({
6239
6507
  message: "\uC99D\uAC70(latest.json)\uAC00 \uC788\uC5B4\uC57C review \uAC00 \uAD50\uCC28\uAC80\uC99D\uD569\uB2C8\uB2E4:",
6240
6508
  command: "vhk verify",
@@ -6247,7 +6515,7 @@ async function review(opts = {}) {
6247
6515
  try {
6248
6516
  report = readJsonFile(jsonPath);
6249
6517
  } catch {
6250
- console.error(chalk31.red(` \u274C ${REPORT_PATH_REL} \uB97C \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(\uC190\uC0C1). vhk verify \uB85C \uC7AC\uC0DD\uC131\uD558\uC138\uC694.`));
6518
+ console.error(chalk32.red(` \u274C ${REPORT_PATH_REL} \uB97C \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(\uC190\uC0C1). vhk verify \uB85C \uC7AC\uC0DD\uC131\uD558\uC138\uC694.`));
6251
6519
  process.exitCode = 1;
6252
6520
  return;
6253
6521
  }
@@ -6259,44 +6527,44 @@ async function review(opts = {}) {
6259
6527
  goalStatus,
6260
6528
  reportStatus: report.status
6261
6529
  };
6262
- console.log(chalk31.bold(`
6530
+ console.log(chalk32.bold(`
6263
6531
  \u{1F52C} \uC801\uB300\uC801 \uC790\uAE30\uAC80\uC99D (review) \u2014 Goal ${goalId}`));
6264
- console.log(chalk31.gray("\u2500".repeat(44)));
6532
+ console.log(chalk32.gray("\u2500".repeat(44)));
6265
6533
  console.log(
6266
- chalk31.dim(
6534
+ chalk32.dim(
6267
6535
  ` goal status: ${goalStatus} \xB7 verify: ${report.status} \xB7 \uCCB4\uD06C\uB41C \uC644\uB8CC\uC870\uAC74 ${result.checkedCount}\uAC1C (\uB9E4\uD551 ${result.mappedCount} / \uBBF8\uAC80\uC99D ${result.unmappedCount}, coverage ${result.coverage * 100 | 0}%)`
6268
6536
  )
6269
6537
  );
6270
- console.log(chalk31.dim(` \uC99D\uAC70 \uC2E0\uC120\uB3C4: ${result.freshness.note}`));
6538
+ console.log(chalk32.dim(` \uC99D\uAC70 \uC2E0\uC120\uB3C4: ${result.freshness.note}`));
6271
6539
  if (result.checkedCount === 0) {
6272
- console.log(chalk31.yellow("\n \u26AA \uC644\uB8CC \uC8FC\uC7A5 \uC5C6\uC74C(\uCCB4\uD06C\uB41C \uC644\uB8CC\uC870\uAC74 0\uAC1C) \u2014 \uC2EC\uBB38\uD560 \uB300\uC0C1\uC774 \uC5C6\uC2B5\uB2C8\uB2E4(vacuous)."));
6540
+ console.log(chalk32.yellow("\n \u26AA \uC644\uB8CC \uC8FC\uC7A5 \uC5C6\uC74C(\uCCB4\uD06C\uB41C \uC644\uB8CC\uC870\uAC74 0\uAC1C) \u2014 \uC2EC\uBB38\uD560 \uB300\uC0C1\uC774 \uC5C6\uC2B5\uB2C8\uB2E4(vacuous)."));
6273
6541
  }
6274
6542
  if (result.suspicions.length > 0) {
6275
- console.log(chalk31.red.bold(`
6543
+ console.log(chalk32.red.bold(`
6276
6544
  \u{1F6A9} \uAC70\uC9D3\uC644\uB8CC \uC758\uC2EC ${result.suspicions.length}\uAC74`));
6277
- for (const s of result.suspicions) console.log(chalk31.red(` \u2717 ${s.check}
6545
+ for (const s of result.suspicions) console.log(chalk32.red(` \u2717 ${s.check}
6278
6546
  \u21B3 ${s.reason}`));
6279
6547
  }
6280
6548
  if (result.gaps.length > 0) {
6281
- console.log(chalk31.yellow.bold(`
6549
+ console.log(chalk32.yellow.bold(`
6282
6550
  \u26A0\uFE0F \uBBF8\uAC80\uC99D(unmapped) ${result.gaps.length}\uAC74 \u2014 \uAC8C\uC774\uD2B8\uB85C \uC790\uB3D9 \uD655\uC778 \uBD88\uAC00`));
6283
- for (const g of result.gaps) console.log(chalk31.yellow(` ? ${g.check}`));
6551
+ for (const g of result.gaps) console.log(chalk32.yellow(` ? ${g.check}`));
6284
6552
  }
6285
6553
  if (result.checkedCount > 0 && result.suspicions.length === 0 && result.gaps.length === 0) {
6286
- console.log(chalk31.green("\n \u2713 \uCCB4\uD06C\uB41C \uC644\uB8CC\uC870\uAC74\uC774 \uBAA8\uB450 \uAC8C\uC774\uD2B8 \uC99D\uAC70\uB85C \uB4B7\uBC1B\uCE68\uB428."));
6554
+ console.log(chalk32.green("\n \u2713 \uCCB4\uD06C\uB41C \uC644\uB8CC\uC870\uAC74\uC774 \uBAA8\uB450 \uAC8C\uC774\uD2B8 \uC99D\uAC70\uB85C \uB4B7\uBC1B\uCE68\uB428."));
6287
6555
  }
6288
6556
  console.log(`
6289
6557
  \uC2E0\uB8B0\uB3C4: ${CONFIDENCE_LABEL[result.confidence]}`);
6290
- console.log(chalk31.yellow(`
6558
+ console.log(chalk32.yellow(`
6291
6559
  ${result.disclaimer}`));
6292
6560
  let mergeOk = false;
6293
6561
  try {
6294
6562
  const merged = { ...report, review: result };
6295
- writeFileSync12(jsonPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
6563
+ writeFileSync13(jsonPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
6296
6564
  mergeOk = true;
6297
- console.log(chalk31.dim(` \u{1F4C4} \uD310\uC815 \uBCD1\uD569: ${REPORT_PATH_REL} (review \uC139\uC158)`));
6565
+ console.log(chalk32.dim(` \u{1F4C4} \uD310\uC815 \uBCD1\uD569: ${REPORT_PATH_REL} (review \uC139\uC158)`));
6298
6566
  } catch (e) {
6299
- console.error(chalk31.red(` \u274C review \uD310\uC815 \uAE30\uB85D \uC2E4\uD328: ${e instanceof Error ? e.message : String(e)}`));
6567
+ console.error(chalk32.red(` \u274C review \uD310\uC815 \uAE30\uB85D \uC2E4\uD328: ${e instanceof Error ? e.message : String(e)}`));
6300
6568
  }
6301
6569
  if (!mergeOk) {
6302
6570
  process.exitCode = 1;
@@ -6317,8 +6585,8 @@ ${result.disclaimer}`));
6317
6585
  cursorHint: "\uC644\uB8CC\uC870\uAC74 \uCC44\uC6CC\uC918"
6318
6586
  });
6319
6587
  } else if (result.suspicions.length > 0) {
6320
- console.log(chalk31.dim("\n AI \uC7AC\uC9C8\uBB38 \uD504\uB86C\uD504\uD2B8:"));
6321
- console.log(chalk31.cyan(result.reprompt.split("\n").map((l) => ` ${l}`).join("\n")));
6588
+ console.log(chalk32.dim("\n AI \uC7AC\uC9C8\uBB38 \uD504\uB86C\uD504\uD2B8:"));
6589
+ console.log(chalk32.cyan(result.reprompt.split("\n").map((l) => ` ${l}`).join("\n")));
6322
6590
  printNextStep({
6323
6591
  message: "\uAC70\uC9D3\uC644\uB8CC \uC758\uC2EC\uC73C\uB85C \uC2E4\uD328(exit 1) \u2014 \uC99D\uAC70 \uBCF4\uAC15 \uD6C4 \uB2E4\uC2DC \uAC80\uC99D\uD558\uC138\uC694:",
6324
6592
  command: "vhk verify",
@@ -6332,8 +6600,8 @@ ${result.disclaimer}`));
6332
6600
  cursorHint: "goal \uC644\uB8CC \uCC98\uB9AC\uD574\uC918"
6333
6601
  });
6334
6602
  } else {
6335
- console.log(chalk31.dim("\n AI \uC7AC\uC9C8\uBB38 \uD504\uB86C\uD504\uD2B8:"));
6336
- console.log(chalk31.cyan(result.reprompt.split("\n").map((l) => ` ${l}`).join("\n")));
6603
+ console.log(chalk32.dim("\n AI \uC7AC\uC9C8\uBB38 \uD504\uB86C\uD504\uD2B8:"));
6604
+ console.log(chalk32.cyan(result.reprompt.split("\n").map((l) => ` ${l}`).join("\n")));
6337
6605
  printNextStep({
6338
6606
  message: `\uC99D\uAC70 \uBD88\uCDA9\uBD84(\uC2E0\uB8B0\uB3C4 ${result.confidence}) \u2014 goal done \uAE08\uC9C0. \uCEE4\uBC84\uB9AC\uC9C0/\uC2E0\uC120\uB3C4 \uBCF4\uAC15 \uD6C4 \uC7AC\uAC80\uC99D:`,
6339
6607
  command: "vhk verify",
@@ -6343,12 +6611,12 @@ ${result.disclaimer}`));
6343
6611
  }
6344
6612
 
6345
6613
  // src/commands/mission.ts
6346
- import { existsSync as existsSync18, mkdirSync as mkdirSync12, writeFileSync as writeFileSync13, rmSync as rmSync4 } from "fs";
6347
- import { join as join13 } from "path";
6348
- import chalk32 from "chalk";
6614
+ import { existsSync as existsSync19, mkdirSync as mkdirSync13, writeFileSync as writeFileSync14, rmSync as rmSync4 } from "fs";
6615
+ import { join as join14 } from "path";
6616
+ import chalk33 from "chalk";
6349
6617
  import inquirer12 from "inquirer";
6350
6618
  import { simpleGit as simpleGit3 } from "simple-git";
6351
- var MISSION_PATH_REL = join13(".vhk", "mission.json");
6619
+ var MISSION_PATH_REL = join14(".vhk", "mission.json");
6352
6620
  var MISSION_SCHEMA_VERSION = 1;
6353
6621
  var MISSION_DISCLAIMER = "\u26A0\uFE0F mission check \uB294 \uACBD\uB85C glob \uAE30\uC900\uC785\uB2C8\uB2E4 \u2014 objective \uC758\uBBF8 \uBD80\uD569\uC740 \uAC80\uC99D\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(\uC2E0\uB8B0\uB3C4 \uC2E0\uD638, \uBCF4\uC7A5 \uC544\uB2D8).";
6354
6622
  function globToRegExp(glob) {
@@ -6396,8 +6664,8 @@ function checkMission(changedFiles, mission) {
6396
6664
  return { violations, warnings, disclaimer: MISSION_DISCLAIMER };
6397
6665
  }
6398
6666
  function readMission(cwd = process.cwd()) {
6399
- const p = join13(cwd, MISSION_PATH_REL);
6400
- if (!existsSync18(p)) return null;
6667
+ const p = join14(cwd, MISSION_PATH_REL);
6668
+ if (!existsSync19(p)) return null;
6401
6669
  try {
6402
6670
  const m = readJsonFile(p);
6403
6671
  if (m && typeof m.objective === "string") return m;
@@ -6407,8 +6675,8 @@ function readMission(cwd = process.cwd()) {
6407
6675
  }
6408
6676
  }
6409
6677
  function writeMission(cwd, mission) {
6410
- mkdirSync12(join13(cwd, ".vhk"), { recursive: true });
6411
- writeFileSync13(join13(cwd, MISSION_PATH_REL), JSON.stringify(mission, null, 2) + "\n", "utf-8");
6678
+ mkdirSync13(join14(cwd, ".vhk"), { recursive: true });
6679
+ writeFileSync14(join14(cwd, MISSION_PATH_REL), JSON.stringify(mission, null, 2) + "\n", "utf-8");
6412
6680
  }
6413
6681
  async function collectChangedFiles(cwd) {
6414
6682
  const status2 = await simpleGit3(cwd).status();
@@ -6429,7 +6697,7 @@ async function missionSet(opts = {}) {
6429
6697
  objective = ans.obj.trim();
6430
6698
  }
6431
6699
  if (!objective) {
6432
- console.error(chalk32.red(' \u274C objective \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. --objective "..." \uB85C \uC9C0\uC815\uD558\uC138\uC694(\uBE44\uB300\uD654\uD615).'));
6700
+ console.error(chalk33.red(' \u274C objective \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. --objective "..." \uB85C \uC9C0\uC815\uD558\uC138\uC694(\uBE44\uB300\uD654\uD615).'));
6433
6701
  process.exitCode = 1;
6434
6702
  return;
6435
6703
  }
@@ -6448,12 +6716,12 @@ async function missionSet(opts = {}) {
6448
6716
  try {
6449
6717
  writeMission(cwd, mission);
6450
6718
  } catch (e) {
6451
- console.error(chalk32.red(` \u274C mission.json \uAE30\uB85D \uC2E4\uD328: ${e instanceof Error ? e.message : String(e)}`));
6719
+ console.error(chalk33.red(` \u274C mission.json \uAE30\uB85D \uC2E4\uD328: ${e instanceof Error ? e.message : String(e)}`));
6452
6720
  process.exitCode = 1;
6453
6721
  return;
6454
6722
  }
6455
- console.log(chalk32.bold("\n\u{1F3AF} \uBBF8\uC158 \uACC4\uC57D \uC800\uC7A5"));
6456
- console.log(chalk32.dim(` \u{1F4C4} ${MISSION_PATH_REL}`));
6723
+ console.log(chalk33.bold("\n\u{1F3AF} \uBBF8\uC158 \uACC4\uC57D \uC800\uC7A5"));
6724
+ console.log(chalk33.dim(` \u{1F4C4} ${MISSION_PATH_REL}`));
6457
6725
  console.log(` objective: ${mission.objective}`);
6458
6726
  console.log(` scope: ${mission.scope.length ? mission.scope.join(", ") : "(\uC81C\uD55C \uC5C6\uC74C)"}`);
6459
6727
  console.log(` forbidden: ${mission.forbidden.length ? mission.forbidden.join(", ") : "(\uC5C6\uC74C)"}`);
@@ -6463,64 +6731,64 @@ async function missionShow() {
6463
6731
  const cwd = process.cwd();
6464
6732
  const mission = readMission(cwd);
6465
6733
  if (!mission) {
6466
- console.error(chalk32.yellow(" \u26A0\uFE0F \uBBF8\uC158 \uACC4\uC57D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 (.vhk/mission.json)."));
6734
+ console.error(chalk33.yellow(" \u26A0\uFE0F \uBBF8\uC158 \uACC4\uC57D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 (.vhk/mission.json)."));
6467
6735
  printNextStep({ message: "\uBA3C\uC800 \uBBF8\uC158\uC744 \uC120\uC5B8\uD558\uC138\uC694:", command: 'vhk mission set --objective "..."', cursorHint: "\uBBF8\uC158 \uC815\uD574\uC918" });
6468
6736
  process.exitCode = 1;
6469
6737
  return;
6470
6738
  }
6471
- console.log(chalk32.bold("\n\u{1F3AF} \uD604\uC7AC \uBBF8\uC158 \uACC4\uC57D"));
6739
+ console.log(chalk33.bold("\n\u{1F3AF} \uD604\uC7AC \uBBF8\uC158 \uACC4\uC57D"));
6472
6740
  console.log(` objective: ${mission.objective}`);
6473
6741
  console.log(` scope: ${mission.scope.length ? mission.scope.join(", ") : "(\uC81C\uD55C \uC5C6\uC74C)"}`);
6474
6742
  console.log(` forbidden: ${mission.forbidden.length ? mission.forbidden.join(", ") : "(\uC5C6\uC74C)"}`);
6475
- console.log(chalk32.dim(` \uC0DD\uC131 ${mission.createdAt} \xB7 \uAC31\uC2E0 ${mission.updatedAt}`));
6743
+ console.log(chalk33.dim(` \uC0DD\uC131 ${mission.createdAt} \xB7 \uAC31\uC2E0 ${mission.updatedAt}`));
6476
6744
  }
6477
6745
  async function missionCheck() {
6478
6746
  const cwd = process.cwd();
6479
6747
  const mission = readMission(cwd);
6480
6748
  if (!mission) {
6481
- console.error(chalk32.yellow(" \u26A0\uFE0F \uBBF8\uC158 \uACC4\uC57D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uBA3C\uC800 vhk mission set \uC73C\uB85C \uC120\uC5B8\uD558\uC138\uC694."));
6749
+ console.error(chalk33.yellow(" \u26A0\uFE0F \uBBF8\uC158 \uACC4\uC57D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uBA3C\uC800 vhk mission set \uC73C\uB85C \uC120\uC5B8\uD558\uC138\uC694."));
6482
6750
  process.exitCode = 1;
6483
6751
  return;
6484
6752
  }
6485
6753
  const changed = await collectChangedFiles(cwd);
6486
6754
  const result = checkMission(changed, mission);
6487
- console.log(chalk32.bold("\n\u{1F3AF} \uBBF8\uC158 \uACC4\uC57D \uAC80\uC99D (mission check)"));
6488
- console.log(chalk32.dim(` objective: ${mission.objective} \xB7 \uBCC0\uACBD \uD30C\uC77C ${changed.length}\uAC1C`));
6755
+ console.log(chalk33.bold("\n\u{1F3AF} \uBBF8\uC158 \uACC4\uC57D \uAC80\uC99D (mission check)"));
6756
+ console.log(chalk33.dim(` objective: ${mission.objective} \xB7 \uBCC0\uACBD \uD30C\uC77C ${changed.length}\uAC1C`));
6489
6757
  if (result.violations.length > 0) {
6490
- console.log(chalk32.red.bold(`
6758
+ console.log(chalk33.red.bold(`
6491
6759
  \u{1F6AB} forbidden \uC704\uBC18 ${result.violations.length}\uAC74`));
6492
- for (const v of result.violations) console.log(chalk32.red(` \u2717 ${v.file} (\uAE08\uC9C0: ${v.pattern})`));
6760
+ for (const v of result.violations) console.log(chalk33.red(` \u2717 ${v.file} (\uAE08\uC9C0: ${v.pattern})`));
6493
6761
  }
6494
6762
  if (result.warnings.length > 0) {
6495
- console.log(chalk32.yellow.bold(`
6763
+ console.log(chalk33.yellow.bold(`
6496
6764
  \u26A0\uFE0F scope \uBC16 \uBCC0\uACBD ${result.warnings.length}\uAC74 (\uACBD\uACE0)`));
6497
- for (const w of result.warnings) console.log(chalk32.yellow(` ? ${w.file}`));
6765
+ for (const w of result.warnings) console.log(chalk33.yellow(` ? ${w.file}`));
6498
6766
  }
6499
6767
  if (result.violations.length === 0 && result.warnings.length === 0) {
6500
- console.log(chalk32.green("\n \u2713 \uBCC0\uACBD\uC774 \uACC4\uC57D(scope/forbidden) \uC548\uC785\uB2C8\uB2E4."));
6768
+ console.log(chalk33.green("\n \u2713 \uBCC0\uACBD\uC774 \uACC4\uC57D(scope/forbidden) \uC548\uC785\uB2C8\uB2E4."));
6501
6769
  }
6502
- console.log(chalk32.yellow(`
6770
+ console.log(chalk33.yellow(`
6503
6771
  ${result.disclaimer}`));
6504
6772
  process.exitCode = result.violations.length > 0 ? 1 : 0;
6505
6773
  }
6506
6774
  async function missionClear() {
6507
6775
  const cwd = process.cwd();
6508
- const p = join13(cwd, MISSION_PATH_REL);
6509
- if (!existsSync18(p)) {
6510
- console.log(chalk32.dim(" \uBBF8\uC158 \uACC4\uC57D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uC9C0\uC6B8 \uAC83 \uC5C6\uC74C."));
6776
+ const p = join14(cwd, MISSION_PATH_REL);
6777
+ if (!existsSync19(p)) {
6778
+ console.log(chalk33.dim(" \uBBF8\uC158 \uACC4\uC57D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uC9C0\uC6B8 \uAC83 \uC5C6\uC74C."));
6511
6779
  return;
6512
6780
  }
6513
6781
  try {
6514
6782
  rmSync4(p);
6515
- console.log(chalk32.green(" \u2705 \uBBF8\uC158 \uACC4\uC57D \uC0AD\uC81C\uB428 (.vhk/mission.json)."));
6783
+ console.log(chalk33.green(" \u2705 \uBBF8\uC158 \uACC4\uC57D \uC0AD\uC81C\uB428 (.vhk/mission.json)."));
6516
6784
  } catch (e) {
6517
- console.error(chalk32.red(` \u274C \uC0AD\uC81C \uC2E4\uD328: ${e instanceof Error ? e.message : String(e)}`));
6785
+ console.error(chalk33.red(` \u274C \uC0AD\uC81C \uC2E4\uD328: ${e instanceof Error ? e.message : String(e)}`));
6518
6786
  process.exitCode = 1;
6519
6787
  }
6520
6788
  }
6521
6789
 
6522
6790
  // src/commands/pattern.ts
6523
- import chalk33 from "chalk";
6791
+ import chalk34 from "chalk";
6524
6792
  var MIN_TAG_FREQ = 3;
6525
6793
  var STOPWORDS = /* @__PURE__ */ new Set(["the", "a", "an", "is", "are", "and", "or", "in", "on", "at", "to", "for", "of", "with", "it", "was", "be"]);
6526
6794
  function tokenize(text) {
@@ -6638,14 +6906,14 @@ function reconcilePatterns(patterns, candidates, now) {
6638
6906
  async function patternDetect(opts = {}) {
6639
6907
  const minFreq = opts.min !== void 0 ? parseInt(opts.min, 10) : MIN_TAG_FREQ;
6640
6908
  if (!Number.isFinite(minFreq) || minFreq < 1) {
6641
- console.log(chalk33.red("\u274C --min \uC740 1 \uC774\uC0C1\uC758 \uC815\uC218\uC5EC\uC57C \uD569\uB2C8\uB2E4."));
6909
+ console.log(chalk34.red("\u274C --min \uC740 1 \uC774\uC0C1\uC758 \uC815\uC218\uC5EC\uC57C \uD569\uB2C8\uB2E4."));
6642
6910
  process.exitCode = 1;
6643
6911
  return;
6644
6912
  }
6645
6913
  const cwd = process.cwd();
6646
6914
  const loaded = loadForMutation(cwd);
6647
6915
  if (!loaded.ok) {
6648
- console.log(chalk33.red("\u274C memory.json \uC190\uC0C1 \uC758\uC2EC \u2014 \uAC10\uC9C0 \uC911\uB2E8 (\uC6D0\uBCF8 \uBCF4\uC874). \uBC31\uC5C5 \uD655\uC778 \uD6C4 \uC7AC\uC2DC\uB3C4\uD558\uC138\uC694."));
6916
+ console.log(chalk34.red("\u274C memory.json \uC190\uC0C1 \uC758\uC2EC \u2014 \uAC10\uC9C0 \uC911\uB2E8 (\uC6D0\uBCF8 \uBCF4\uC874). \uBC31\uC5C5 \uD655\uC778 \uD6C4 \uC7AC\uC2DC\uB3C4\uD558\uC138\uC694."));
6649
6917
  process.exitCode = 1;
6650
6918
  return;
6651
6919
  }
@@ -6661,26 +6929,26 @@ async function patternDetect(opts = {}) {
6661
6929
  console.log(JSON.stringify(active2, null, 2));
6662
6930
  return;
6663
6931
  }
6664
- console.log(chalk33.bold("\n\u{1F50D} " + t("pattern.detectTitle")));
6665
- console.log(chalk33.gray("\u2500".repeat(40)));
6666
- console.log(chalk33.dim(` \uC784\uACC4: ${minFreq}\uD68C \uC774\uC0C1 \xB7 active failures+successes \uC785\uB825`));
6667
- console.log(chalk33.dim(` \uD6C4\uBCF4: ${candidates.length}\uAC1C \uAC10\uC9C0 (\uCD94\uAC00 ${added} / \uAC31\uC2E0 ${updated})`));
6932
+ console.log(chalk34.bold("\n\u{1F50D} " + t("pattern.detectTitle")));
6933
+ console.log(chalk34.gray("\u2500".repeat(40)));
6934
+ console.log(chalk34.dim(` \uC784\uACC4: ${minFreq}\uD68C \uC774\uC0C1 \xB7 active failures+successes \uC785\uB825`));
6935
+ console.log(chalk34.dim(` \uD6C4\uBCF4: ${candidates.length}\uAC1C \uAC10\uC9C0 (\uCD94\uAC00 ${added} / \uAC31\uC2E0 ${updated})`));
6668
6936
  const active = mem.patterns.filter((p) => p.status !== "archived");
6669
6937
  if (active.length === 0) {
6670
- console.log(chalk33.yellow("\n\u{1F4ED} \uC784\uACC4 \uC774\uC0C1 \uBC18\uBCF5 \uD328\uD134\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."));
6671
- console.log(chalk33.gray(` failures/successes \uAC00 ${minFreq}\uAC1C \uC774\uC0C1 \uC313\uC774\uBA74 \uAC10\uC9C0\uB429\uB2C8\uB2E4.`));
6672
- console.log(chalk33.gray(" --min N \uC73C\uB85C \uC784\uACC4\uB97C \uB0AE\uCD9C \uC218 \uC788\uC2B5\uB2C8\uB2E4."));
6938
+ console.log(chalk34.yellow("\n\u{1F4ED} \uC784\uACC4 \uC774\uC0C1 \uBC18\uBCF5 \uD328\uD134\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."));
6939
+ console.log(chalk34.gray(` failures/successes \uAC00 ${minFreq}\uAC1C \uC774\uC0C1 \uC313\uC774\uBA74 \uAC10\uC9C0\uB429\uB2C8\uB2E4.`));
6940
+ console.log(chalk34.gray(" --min N \uC73C\uB85C \uC784\uACC4\uB97C \uB0AE\uCD9C \uC218 \uC788\uC2B5\uB2C8\uB2E4."));
6673
6941
  return;
6674
6942
  }
6675
- console.log(chalk33.cyan(`
6943
+ console.log(chalk34.cyan(`
6676
6944
  \uD328\uD134 \uD6C4\uBCF4 ${active.length}\uAC1C:
6677
6945
  `));
6678
6946
  for (const p of active.slice(0, 20)) {
6679
6947
  const icon = p.kind === "avoid" ? "\u26A0\uFE0F " : "\u2705";
6680
6948
  console.log(` [${p.id}] ${icon} (${p.kind}/${p.axis}) "${p.signal}" \u2014 ${p.count}\uAC74`);
6681
6949
  const preview = p.sources.slice(0, 5).join(", ") + (p.sources.length > 5 ? ` \uC678 ${p.sources.length - 5}\uAC74` : "");
6682
- console.log(chalk33.dim(` \uADFC\uAC70: ${preview}`));
6683
- console.log(chalk33.dim(` ${p.summary}`));
6950
+ console.log(chalk34.dim(` \uADFC\uAC70: ${preview}`));
6951
+ console.log(chalk34.dim(` ${p.summary}`));
6684
6952
  }
6685
6953
  printNextStep({
6686
6954
  message: `\uD328\uD134 \uAC10\uC9C0 \uC644\uB8CC! ${active.length}\uAC1C \uD6C4\uBCF4.`,
@@ -6690,8 +6958,8 @@ async function patternDetect(opts = {}) {
6690
6958
  });
6691
6959
  }
6692
6960
  async function patternList(opts = {}) {
6693
- console.log(chalk33.bold("\n\u{1F50D} " + t("pattern.listTitle")));
6694
- console.log(chalk33.gray("\u2500".repeat(40)));
6961
+ console.log(chalk34.bold("\n\u{1F50D} " + t("pattern.listTitle")));
6962
+ console.log(chalk34.gray("\u2500".repeat(40)));
6695
6963
  const mem = readMemory(process.cwd());
6696
6964
  let patterns = mem.patterns;
6697
6965
  if (!opts.all) patterns = patterns.filter((p) => p.status !== "archived");
@@ -6703,51 +6971,51 @@ async function patternList(opts = {}) {
6703
6971
  return;
6704
6972
  }
6705
6973
  if (patterns.length === 0) {
6706
- console.log(chalk33.yellow("\n\u{1F4ED} \uD45C\uC2DC\uD560 \uD328\uD134\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."));
6707
- console.log(chalk33.gray(" vhk pattern detect \uB85C \uAC10\uC9C0 \uBA3C\uC800 \uC2E4\uD589\uD558\uC138\uC694."));
6974
+ console.log(chalk34.yellow("\n\u{1F4ED} \uD45C\uC2DC\uD560 \uD328\uD134\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."));
6975
+ console.log(chalk34.gray(" vhk pattern detect \uB85C \uAC10\uC9C0 \uBA3C\uC800 \uC2E4\uD589\uD558\uC138\uC694."));
6708
6976
  return;
6709
6977
  }
6710
- console.log(chalk33.cyan(`
6978
+ console.log(chalk34.cyan(`
6711
6979
  ${patterns.length}\uAC1C${opts.all ? " (\uBCF4\uAD00 \uD3EC\uD568)" : " (\uD65C\uC131)"}:
6712
6980
  `));
6713
6981
  for (const p of patterns) {
6714
6982
  const icon = p.kind === "avoid" ? "\u26A0\uFE0F " : "\u2705";
6715
6983
  const archived = p.status === "archived" ? "\u{1F4E6} " : "";
6716
6984
  console.log(` [${p.id}] ${archived}${icon} (${p.kind}/${p.axis}) "${p.signal}" \u2014 ${p.count}\uAC74`);
6717
- if (p.summary) console.log(chalk33.dim(` ${p.summary}`));
6718
- if (p.tags?.length) console.log(chalk33.blue(` \u{1F3F7}\uFE0F ${p.tags.join(", ")}`));
6985
+ if (p.summary) console.log(chalk34.dim(` ${p.summary}`));
6986
+ if (p.tags?.length) console.log(chalk34.blue(` \u{1F3F7}\uFE0F ${p.tags.join(", ")}`));
6719
6987
  }
6720
6988
  }
6721
6989
  async function patternDismiss(idStr) {
6722
6990
  if (!idStr?.trim()) {
6723
- console.log(chalk33.red("\u274C \uD328\uD134 id \uB97C \uC785\uB825\uD574\uC8FC\uC138\uC694. \uC608: vhk pattern dismiss p1"));
6991
+ console.log(chalk34.red("\u274C \uD328\uD134 id \uB97C \uC785\uB825\uD574\uC8FC\uC138\uC694. \uC608: vhk pattern dismiss p1"));
6724
6992
  process.exitCode = 1;
6725
6993
  return;
6726
6994
  }
6727
6995
  const cwd = process.cwd();
6728
6996
  const loaded = loadForMutation(cwd);
6729
6997
  if (!loaded.ok) {
6730
- console.log(chalk33.red("\u274C memory.json \uC190\uC0C1 \uC758\uC2EC \u2014 dismiss \uC911\uB2E8 (\uC6D0\uBCF8 \uBCF4\uC874)."));
6998
+ console.log(chalk34.red("\u274C memory.json \uC190\uC0C1 \uC758\uC2EC \u2014 dismiss \uC911\uB2E8 (\uC6D0\uBCF8 \uBCF4\uC874)."));
6731
6999
  process.exitCode = 1;
6732
7000
  return;
6733
7001
  }
6734
7002
  const mem = loaded.mem;
6735
7003
  const pattern = mem.patterns.find((p) => p.id === idStr.trim());
6736
7004
  if (!pattern) {
6737
- console.log(chalk33.red(`\u274C \uD328\uD134 '${idStr}' \uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`));
6738
- console.log(chalk33.gray(" vhk pattern list --all \uB85C \uBAA9\uB85D \uD655\uC778."));
7005
+ console.log(chalk34.red(`\u274C \uD328\uD134 '${idStr}' \uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`));
7006
+ console.log(chalk34.gray(" vhk pattern list --all \uB85C \uBAA9\uB85D \uD655\uC778."));
6739
7007
  process.exitCode = 1;
6740
7008
  return;
6741
7009
  }
6742
7010
  if (pattern.status === "archived") {
6743
- console.log(chalk33.dim(` \uC774\uBBF8 \uBCF4\uAD00\uB41C \uD328\uD134\uC785\uB2C8\uB2E4 \u2014 \uBCC0\uACBD \uC5C6\uC74C: ${pattern.id}`));
7011
+ console.log(chalk34.dim(` \uC774\uBBF8 \uBCF4\uAD00\uB41C \uD328\uD134\uC785\uB2C8\uB2E4 \u2014 \uBCC0\uACBD \uC5C6\uC74C: ${pattern.id}`));
6744
7012
  return;
6745
7013
  }
6746
7014
  pattern.status = "archived";
6747
7015
  writeMemory(cwd, mem);
6748
- console.log(chalk33.green(`
7016
+ console.log(chalk34.green(`
6749
7017
  \u{1F4E6} \uD328\uD134 dismiss(\uBCF4\uAD00)\uB428: [${pattern.id}] ${pattern.summary ?? pattern.signal}`));
6750
- console.log(chalk33.dim(" \uC624\uD0D0\uC73C\uB85C \uD310\uB2E8. detect \uC7AC\uC2E4\uD589 \uC2DC \uC7AC\uC81C\uC548 \uC548 \uB428."));
7018
+ console.log(chalk34.dim(" \uC624\uD0D0\uC73C\uB85C \uD310\uB2E8. detect \uC7AC\uC2E4\uD589 \uC2DC \uC7AC\uC81C\uC548 \uC548 \uB428."));
6751
7019
  printNextStep({
6752
7020
  message: "\uD328\uD134 dismiss \uC644\uB8CC!",
6753
7021
  command: "vhk pattern list",
@@ -6756,11 +7024,11 @@ async function patternDismiss(idStr) {
6756
7024
  }
6757
7025
 
6758
7026
  // src/commands/evolve.ts
6759
- import { existsSync as existsSync19, mkdirSync as mkdirSync13, writeFileSync as writeFileSync14, readFileSync as readFileSync7, copyFileSync as copyFileSync2, renameSync as renameSync2, rmSync as rmSync5 } from "fs";
6760
- import { join as join14 } from "path";
6761
- import chalk34 from "chalk";
7027
+ import { existsSync as existsSync20, mkdirSync as mkdirSync14, writeFileSync as writeFileSync15, readFileSync as readFileSync8, copyFileSync as copyFileSync2, renameSync as renameSync2, rmSync as rmSync5 } from "fs";
7028
+ import { join as join15 } from "path";
7029
+ import chalk35 from "chalk";
6762
7030
  import inquirer13 from "inquirer";
6763
- var QUEUE_PATH_REL = join14(".vhk", "evolve", "queue.json");
7031
+ var QUEUE_PATH_REL = join15(".vhk", "evolve", "queue.json");
6764
7032
  function buildDraft(p) {
6765
7033
  const axisLabel = p.axis === "tag" ? `\uD0DC\uADF8 '${p.signal}'` : `\uD0A4\uC6CC\uB4DC '${p.signal}'`;
6766
7034
  const countDesc = `${p.count}\uAC74 \uBC18\uBCF5`;
@@ -6804,10 +7072,10 @@ function stripBomStr(s) {
6804
7072
  return s.charCodeAt(0) === 65279 ? s.slice(1) : s;
6805
7073
  }
6806
7074
  function readQueue(cwd) {
6807
- const p = join14(cwd, QUEUE_PATH_REL);
6808
- if (!existsSync19(p)) return { version: 1, items: [] };
7075
+ const p = join15(cwd, QUEUE_PATH_REL);
7076
+ if (!existsSync20(p)) return { version: 1, items: [] };
6809
7077
  try {
6810
- const raw = stripBomStr(readFileSync7(p, "utf-8"));
7078
+ const raw = stripBomStr(readFileSync8(p, "utf-8"));
6811
7079
  const parsed = JSON.parse(raw);
6812
7080
  if (!parsed || !Array.isArray(parsed.items)) return { version: 1, items: [] };
6813
7081
  return parsed;
@@ -6816,10 +7084,10 @@ function readQueue(cwd) {
6816
7084
  }
6817
7085
  }
6818
7086
  function writeQueue(cwd, queue) {
6819
- const p = join14(cwd, QUEUE_PATH_REL);
6820
- mkdirSync13(join14(cwd, ".vhk", "evolve"), { recursive: true });
7087
+ const p = join15(cwd, QUEUE_PATH_REL);
7088
+ mkdirSync14(join15(cwd, ".vhk", "evolve"), { recursive: true });
6821
7089
  const tmpPath = p + ".tmp";
6822
- writeFileSync14(tmpPath, JSON.stringify(queue, null, 2) + "\n", "utf-8");
7090
+ writeFileSync15(tmpPath, JSON.stringify(queue, null, 2) + "\n", "utf-8");
6823
7091
  try {
6824
7092
  renameSync2(tmpPath, p);
6825
7093
  } catch (err) {
@@ -6848,8 +7116,8 @@ function checkApplyRef(pattern, queueItems) {
6848
7116
  }
6849
7117
  async function evolveSuggest(opts = {}) {
6850
7118
  const cwd = process.cwd();
6851
- if (!existsSync19(join14(cwd, "RULES.md"))) {
6852
- console.log(chalk34.yellow("\n\u26A0\uFE0F " + t("evolve.noRules")));
7119
+ if (!existsSync20(join15(cwd, "RULES.md"))) {
7120
+ console.log(chalk35.yellow("\n\u26A0\uFE0F " + t("evolve.noRules")));
6853
7121
  process.exitCode = 1;
6854
7122
  return;
6855
7123
  }
@@ -6860,10 +7128,10 @@ async function evolveSuggest(opts = {}) {
6860
7128
  if (newItems.length === 0 && !opts.json) {
6861
7129
  const activeAvoid = patterns.filter((p) => p.kind === "avoid" && p.status === "active");
6862
7130
  if (activeAvoid.length === 0) {
6863
- console.log(chalk34.yellow("\n\u{1F4ED} " + t("evolve.noPatterns")));
7131
+ console.log(chalk35.yellow("\n\u{1F4ED} " + t("evolve.noPatterns")));
6864
7132
  return;
6865
7133
  }
6866
- console.log(chalk34.dim("\n " + t("evolve.allSuggested")));
7134
+ console.log(chalk35.dim("\n " + t("evolve.allSuggested")));
6867
7135
  return;
6868
7136
  }
6869
7137
  const now = (/* @__PURE__ */ new Date()).toISOString();
@@ -6876,16 +7144,16 @@ async function evolveSuggest(opts = {}) {
6876
7144
  console.log(JSON.stringify(pending2, null, 2));
6877
7145
  return;
6878
7146
  }
6879
- console.log(chalk34.bold("\n\u{1F504} " + t("evolve.suggestTitle")));
6880
- console.log(chalk34.gray("\u2500".repeat(40)));
6881
- console.log(chalk34.dim(" " + t("evolve.newCandidates", newItems.length)));
7147
+ console.log(chalk35.bold("\n\u{1F504} " + t("evolve.suggestTitle")));
7148
+ console.log(chalk35.gray("\u2500".repeat(40)));
7149
+ console.log(chalk35.dim(" " + t("evolve.newCandidates", newItems.length)));
6882
7150
  const pending = queue.items.filter((i) => i.status === "pending");
6883
- console.log(chalk34.cyan(`
7151
+ console.log(chalk35.cyan(`
6884
7152
  \uD6C4\uBCF4 ${pending.length}\uAC1C:
6885
7153
  `));
6886
7154
  for (const item of pending) {
6887
7155
  console.log(` [${item.id}] (${item.status}) \uD328\uD134 ${item.patternId} \u2192 rule`);
6888
- console.log(chalk34.dim(` \uCD08\uC548: ${item.draft}`));
7156
+ console.log(chalk35.dim(` \uCD08\uC548: ${item.draft}`));
6889
7157
  }
6890
7158
  printNextStep({
6891
7159
  message: `\uC9C4\uD654 \uD6C4\uBCF4 ${pending.length}\uAC1C \uC0DD\uC131\uB428!`,
@@ -6906,11 +7174,11 @@ async function evolveList(opts = {}) {
6906
7174
  console.log(JSON.stringify(items, null, 2));
6907
7175
  return;
6908
7176
  }
6909
- console.log(chalk34.bold("\n\u{1F504} " + t("evolve.listTitle")));
6910
- console.log(chalk34.gray("\u2500".repeat(40)));
7177
+ console.log(chalk35.bold("\n\u{1F504} " + t("evolve.listTitle")));
7178
+ console.log(chalk35.gray("\u2500".repeat(40)));
6911
7179
  if (items.length === 0) {
6912
- console.log(chalk34.yellow("\n\u{1F4ED} " + t("evolve.noQueue")));
6913
- console.log(chalk34.gray(" " + t("evolve.suggestHint")));
7180
+ console.log(chalk35.yellow("\n\u{1F4ED} " + t("evolve.noQueue")));
7181
+ console.log(chalk35.gray(" " + t("evolve.suggestHint")));
6914
7182
  return;
6915
7183
  }
6916
7184
  const STATUS_ICON3 = {
@@ -6918,68 +7186,68 @@ async function evolveList(opts = {}) {
6918
7186
  rejected: "\u274C",
6919
7187
  applied: "\u2705"
6920
7188
  };
6921
- console.log(chalk34.cyan(`
7189
+ console.log(chalk35.cyan(`
6922
7190
  ${items.length}\uAC1C:
6923
7191
  `));
6924
7192
  for (const item of items) {
6925
7193
  console.log(` [${item.id}] ${STATUS_ICON3[item.status]} (${item.status}) \u2192 ${item.draft}`);
6926
- if (item.appliedAt) console.log(chalk34.dim(` \uBC18\uC601: ${item.appliedAt}`));
7194
+ if (item.appliedAt) console.log(chalk35.dim(` \uBC18\uC601: ${item.appliedAt}`));
6927
7195
  }
6928
7196
  }
6929
7197
  async function evolveApply(idStr) {
6930
7198
  if (!ensureInteractive("apply\uB294 TTY \uD655\uC778\uC774 \uD544\uC694\uD569\uB2C8\uB2E4. \uD130\uBBF8\uB110\uC5D0\uC11C \uC9C1\uC811 \uC2E4\uD589\uD558\uC138\uC694.")) return;
6931
7199
  const cwd = process.cwd();
6932
- const rulesPath = join14(cwd, "RULES.md");
6933
- if (!existsSync19(rulesPath)) {
6934
- console.log(chalk34.red("\n\u274C " + t("evolve.noRules")));
7200
+ const rulesPath = join15(cwd, "RULES.md");
7201
+ if (!existsSync20(rulesPath)) {
7202
+ console.log(chalk35.red("\n\u274C " + t("evolve.noRules")));
6935
7203
  process.exitCode = 1;
6936
7204
  return;
6937
7205
  }
6938
7206
  const queue = readQueue(cwd);
6939
7207
  const item = queue.items.find((i) => i.id === idStr?.trim());
6940
7208
  if (!item) {
6941
- console.log(chalk34.red("\n\u274C " + t("evolve.notFound", idStr ?? "")));
7209
+ console.log(chalk35.red("\n\u274C " + t("evolve.notFound", idStr ?? "")));
6942
7210
  process.exitCode = 1;
6943
7211
  return;
6944
7212
  }
6945
7213
  if (item.status === "applied") {
6946
- console.log(chalk34.yellow("\n\u26A0\uFE0F " + t("evolve.alreadyApplied")));
7214
+ console.log(chalk35.yellow("\n\u26A0\uFE0F " + t("evolve.alreadyApplied")));
6947
7215
  process.exitCode = 1;
6948
7216
  return;
6949
7217
  }
6950
7218
  const hasUnresolved = queue.items.some((i) => i.status === "applied");
6951
7219
  if (hasUnresolved) {
6952
- console.log(chalk34.red("\n\u274C " + t("evolve.pendingApplyExists")));
7220
+ console.log(chalk35.red("\n\u274C " + t("evolve.pendingApplyExists")));
6953
7221
  process.exitCode = 1;
6954
7222
  return;
6955
7223
  }
6956
7224
  const memLoaded = loadForMutation(cwd);
6957
7225
  if (!memLoaded.ok) {
6958
- console.log(chalk34.red("\n\u274C memory.json \uC190\uC0C1 \uC758\uC2EC \u2014 apply \uC911\uB2E8 (\uC6D0\uBCF8 \uBCF4\uC874)."));
7226
+ console.log(chalk35.red("\n\u274C memory.json \uC190\uC0C1 \uC758\uC2EC \u2014 apply \uC911\uB2E8 (\uC6D0\uBCF8 \uBCF4\uC874)."));
6959
7227
  process.exitCode = 1;
6960
7228
  return;
6961
7229
  }
6962
7230
  const srcPattern = memLoaded.mem.patterns.find((p) => p.id === item.patternId);
6963
7231
  const refResult = checkApplyRef(srcPattern, queue.items);
6964
7232
  if (refResult === "dismissed") {
6965
- console.log(chalk34.red("\n\u274C " + t("evolve.dismissed")));
7233
+ console.log(chalk35.red("\n\u274C " + t("evolve.dismissed")));
6966
7234
  process.exitCode = 1;
6967
7235
  return;
6968
7236
  }
6969
7237
  if (refResult === "already-applied") {
6970
- console.log(chalk34.red("\n\u274C " + t("evolve.alreadyAppliedPattern")));
7238
+ console.log(chalk35.red("\n\u274C " + t("evolve.alreadyAppliedPattern")));
6971
7239
  process.exitCode = 1;
6972
7240
  return;
6973
7241
  }
6974
- const rulesContent = readFileSync7(rulesPath, "utf-8");
7242
+ const rulesContent = readFileSync8(rulesPath, "utf-8");
6975
7243
  if (isDuplicateRule(rulesContent, item.draft)) {
6976
- console.log(chalk34.yellow("\n\u26A0\uFE0F " + t("evolve.duplicateRule", item.draft)));
7244
+ console.log(chalk35.yellow("\n\u26A0\uFE0F " + t("evolve.duplicateRule", item.draft)));
6977
7245
  return;
6978
7246
  }
6979
- console.log(chalk34.bold("\n\u{1F504} " + t("evolve.applyTitle")));
6980
- console.log(chalk34.gray("\u2500".repeat(40)));
6981
- console.log(chalk34.cyan("\n\uCD94\uAC00\uB420 \uB8F0 \uCD08\uC548:"));
6982
- console.log(chalk34.white(` ${item.draft}`));
7247
+ console.log(chalk35.bold("\n\u{1F504} " + t("evolve.applyTitle")));
7248
+ console.log(chalk35.gray("\u2500".repeat(40)));
7249
+ console.log(chalk35.cyan("\n\uCD94\uAC00\uB420 \uB8F0 \uCD08\uC548:"));
7250
+ console.log(chalk35.white(` ${item.draft}`));
6983
7251
  const { editedDraft } = await inquirer13.prompt([{
6984
7252
  type: "input",
6985
7253
  name: "editedDraft",
@@ -6994,22 +7262,22 @@ async function evolveApply(idStr) {
6994
7262
  default: false
6995
7263
  }]);
6996
7264
  if (!confirmed) {
6997
- console.log(chalk34.dim(" \uCDE8\uC18C\uB428."));
7265
+ console.log(chalk35.dim(" \uCDE8\uC18C\uB428."));
6998
7266
  return;
6999
7267
  }
7000
7268
  const backupPath = rulesPath + ".bak";
7001
7269
  copyFileSync2(rulesPath, backupPath);
7002
7270
  const appendContent = "\n" + editedDraft + "\n";
7003
7271
  try {
7004
- writeFileSync14(rulesPath, rulesContent + appendContent, "utf-8");
7272
+ writeFileSync15(rulesPath, rulesContent + appendContent, "utf-8");
7005
7273
  await sync({ yes: true });
7006
7274
  } catch (err) {
7007
7275
  try {
7008
7276
  copyFileSync2(backupPath, rulesPath);
7009
7277
  } catch {
7010
7278
  }
7011
- console.error(chalk34.red("\n\u274C RULES.md \uBC18\uC601 \uC911 \uC624\uB958 \u2014 \uC6D0\uBCF8 \uBCF5\uC6D0\uB428. \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694."));
7012
- console.error(chalk34.dim(` ${err instanceof Error ? err.message : String(err)}`));
7279
+ console.error(chalk35.red("\n\u274C RULES.md \uBC18\uC601 \uC911 \uC624\uB958 \u2014 \uC6D0\uBCF8 \uBCF5\uC6D0\uB428. \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694."));
7280
+ console.error(chalk35.dim(` ${err instanceof Error ? err.message : String(err)}`));
7013
7281
  process.exitCode = 1;
7014
7282
  return;
7015
7283
  }
@@ -7025,12 +7293,12 @@ async function evolveApply(idStr) {
7025
7293
  p.status = "archived";
7026
7294
  writeMemory(cwd, memLoaded.mem);
7027
7295
  } else {
7028
- console.error(chalk34.yellow(" \u26A0\uFE0F \uC18C\uC2A4 \uD328\uD134 archived \uCC98\uB9AC \uC2E4\uD328 (memory.json \uC190\uC0C1 \uC758\uC2EC). \uB8F0\uC740 \uBC18\uC601\uB410\uC2B5\uB2C8\uB2E4."));
7296
+ console.error(chalk35.yellow(" \u26A0\uFE0F \uC18C\uC2A4 \uD328\uD134 archived \uCC98\uB9AC \uC2E4\uD328 (memory.json \uC190\uC0C1 \uC758\uC2EC). \uB8F0\uC740 \uBC18\uC601\uB410\uC2B5\uB2C8\uB2E4."));
7029
7297
  }
7030
7298
  }
7031
- console.log(chalk34.green(`
7299
+ console.log(chalk35.green(`
7032
7300
  \u2705 \uB8F0 \uBC18\uC601 \uC644\uB8CC! [${item.id}]`));
7033
- console.log(chalk34.dim(" RULES.md\uC5D0 \uCD94\uAC00 + vhk sync \uC7AC\uC0DD\uC131\uB428"));
7301
+ console.log(chalk35.dim(" RULES.md\uC5D0 \uCD94\uAC00 + vhk sync \uC7AC\uC0DD\uC131\uB428"));
7034
7302
  printNextStep({
7035
7303
  message: "\uB8F0 \uBC18\uC601 \uC644\uB8CC!",
7036
7304
  command: "vhk evolve list --status applied",
@@ -7043,25 +7311,25 @@ async function evolveReject(idStr) {
7043
7311
  const queue = readQueue(cwd);
7044
7312
  const item = queue.items.find((i) => i.id === idStr?.trim());
7045
7313
  if (!item) {
7046
- console.log(chalk34.red("\n\u274C " + t("evolve.notFound", idStr ?? "")));
7314
+ console.log(chalk35.red("\n\u274C " + t("evolve.notFound", idStr ?? "")));
7047
7315
  process.exitCode = 1;
7048
7316
  return;
7049
7317
  }
7050
7318
  if (item.status === "rejected") {
7051
- console.log(chalk34.dim(` \uC774\uBBF8 \uAE30\uAC01\uB41C \uD6C4\uBCF4\uC785\uB2C8\uB2E4 \u2014 \uBCC0\uACBD \uC5C6\uC74C: ${item.id}`));
7319
+ console.log(chalk35.dim(` \uC774\uBBF8 \uAE30\uAC01\uB41C \uD6C4\uBCF4\uC785\uB2C8\uB2E4 \u2014 \uBCC0\uACBD \uC5C6\uC74C: ${item.id}`));
7052
7320
  return;
7053
7321
  }
7054
7322
  if (item.status === "applied") {
7055
- console.log(chalk34.red(`
7323
+ console.log(chalk35.red(`
7056
7324
  \u274C \uC774\uBBF8 \uBC18\uC601\uB41C \uD56D\uBAA9\uC740 \uAE30\uAC01\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 vhk evolve undo \uB85C \uB418\uB3CC\uB9AC\uC138\uC694: ${item.id}`));
7057
7325
  process.exitCode = 1;
7058
7326
  return;
7059
7327
  }
7060
7328
  item.status = "rejected";
7061
7329
  writeQueue(cwd, queue);
7062
- console.log(chalk34.green(`
7330
+ console.log(chalk35.green(`
7063
7331
  \u274C \uD6C4\uBCF4 \uAE30\uAC01\uB428: [${item.id}] ${item.draft}`));
7064
- console.log(chalk34.dim(" (A1: \uB2E4\uC74C suggest\uC5D0\uC11C \uC7AC\uC81C\uC548 \uC548 \uB428)"));
7332
+ console.log(chalk35.dim(" (A1: \uB2E4\uC74C suggest\uC5D0\uC11C \uC7AC\uC81C\uC548 \uC548 \uB428)"));
7065
7333
  printNextStep({
7066
7334
  message: "\uAE30\uAC01 \uC644\uB8CC!",
7067
7335
  command: "vhk evolve list",
@@ -7074,19 +7342,19 @@ async function evolveUndo() {
7074
7342
  const queue = readQueue(cwd);
7075
7343
  const applied = queue.items.filter((i) => i.status === "applied");
7076
7344
  if (applied.length === 0) {
7077
- console.log(chalk34.yellow("\n\u{1F4ED} " + t("evolve.noAppliedToUndo")));
7345
+ console.log(chalk35.yellow("\n\u{1F4ED} " + t("evolve.noAppliedToUndo")));
7078
7346
  return;
7079
7347
  }
7080
7348
  const last = applied.sort(
7081
7349
  (a, b) => (b.appliedAt ?? "").localeCompare(a.appliedAt ?? "")
7082
7350
  )[0];
7083
- if (!last.rulesBackupPath || !existsSync19(last.rulesBackupPath)) {
7084
- console.log(chalk34.red("\n\u274C " + t("evolve.noBackup")));
7351
+ if (!last.rulesBackupPath || !existsSync20(last.rulesBackupPath)) {
7352
+ console.log(chalk35.red("\n\u274C " + t("evolve.noBackup")));
7085
7353
  process.exitCode = 1;
7086
7354
  return;
7087
7355
  }
7088
- console.log(chalk34.bold("\n\u{1F504} " + t("evolve.undoTitle")));
7089
- console.log(chalk34.dim(` \uB418\uB3CC\uB9B4 \uD56D\uBAA9: [${last.id}] ${last.draft}`));
7356
+ console.log(chalk35.bold("\n\u{1F504} " + t("evolve.undoTitle")));
7357
+ console.log(chalk35.dim(` \uB418\uB3CC\uB9B4 \uD56D\uBAA9: [${last.id}] ${last.draft}`));
7090
7358
  const { confirmed } = await inquirer13.prompt([{
7091
7359
  type: "confirm",
7092
7360
  name: "confirmed",
@@ -7094,16 +7362,16 @@ async function evolveUndo() {
7094
7362
  default: false
7095
7363
  }]);
7096
7364
  if (!confirmed) {
7097
- console.log(chalk34.dim(" \uCDE8\uC18C\uB428."));
7365
+ console.log(chalk35.dim(" \uCDE8\uC18C\uB428."));
7098
7366
  return;
7099
7367
  }
7100
- copyFileSync2(last.rulesBackupPath, join14(cwd, "RULES.md"));
7368
+ copyFileSync2(last.rulesBackupPath, join15(cwd, "RULES.md"));
7101
7369
  try {
7102
7370
  await sync({ yes: true });
7103
7371
  } catch (err) {
7104
- console.error(chalk34.red("\n\u274C sync \uC7AC\uC2E4\uD589 \uC911 \uC624\uB958. RULES.md\uB294 \uBCF5\uC6D0\uB410\uC73C\uB098 .cursorrules \uB4F1 \uC7AC\uC0DD\uC131 \uC2E4\uD328."));
7105
- console.error(chalk34.dim(` ${err instanceof Error ? err.message : String(err)}`));
7106
- console.error(chalk34.dim(" \uC218\uB3D9\uC73C\uB85C `vhk sync` \uC2E4\uD589\uD558\uC138\uC694."));
7372
+ console.error(chalk35.red("\n\u274C sync \uC7AC\uC2E4\uD589 \uC911 \uC624\uB958. RULES.md\uB294 \uBCF5\uC6D0\uB410\uC73C\uB098 .cursorrules \uB4F1 \uC7AC\uC0DD\uC131 \uC2E4\uD328."));
7373
+ console.error(chalk35.dim(` ${err instanceof Error ? err.message : String(err)}`));
7374
+ console.error(chalk35.dim(" \uC218\uB3D9\uC73C\uB85C `vhk sync` \uC2E4\uD589\uD558\uC138\uC694."));
7107
7375
  }
7108
7376
  last.status = "pending";
7109
7377
  delete last.appliedAt;
@@ -7117,7 +7385,7 @@ async function evolveUndo() {
7117
7385
  writeMemory(cwd, memLoaded.mem);
7118
7386
  }
7119
7387
  }
7120
- console.log(chalk34.green("\n\u2705 \uB418\uB3CC\uB9AC\uAE30 \uC644\uB8CC! RULES.md \uBCF5\uC6D0 + sync \uC7AC\uC2E4\uD589\uB428"));
7388
+ console.log(chalk35.green("\n\u2705 \uB418\uB3CC\uB9AC\uAE30 \uC644\uB8CC! RULES.md \uBCF5\uC6D0 + sync \uC7AC\uC2E4\uD589\uB428"));
7121
7389
  printNextStep({
7122
7390
  message: "\uB418\uB3CC\uB9AC\uAE30 \uC644\uB8CC!",
7123
7391
  command: "vhk evolve list",
@@ -7299,6 +7567,10 @@ async function dispatchNlpRoute(route, input) {
7299
7567
  return patternList();
7300
7568
  case "evolve":
7301
7569
  return evolveList();
7570
+ case "work": {
7571
+ if (route.args?.[0] === "handoff") return workHandoff();
7572
+ return work();
7573
+ }
7302
7574
  }
7303
7575
  }
7304
7576
  var STATE_CHANGING_COMMANDS = /* @__PURE__ */ new Set([
@@ -7312,14 +7584,14 @@ function requiresConfirmation(route) {
7312
7584
  async function runNaturalLanguageRoute(input) {
7313
7585
  const route = routeNaturalLanguage(input);
7314
7586
  if (!route) {
7315
- console.log(chalk35.yellow(`
7587
+ console.log(chalk36.yellow(`
7316
7588
  \u2753 "${input}" \u2014 ${ko.nlp.notMatched}
7317
7589
  `));
7318
7590
  return;
7319
7591
  }
7320
7592
  console.log("");
7321
- console.log(chalk35.cyan(` \u{1F4AC} "${input}"`));
7322
- console.log(chalk35.cyan(` \u2192 ${route.explanation}`));
7593
+ console.log(chalk36.cyan(` \u{1F4AC} "${input}"`));
7594
+ console.log(chalk36.cyan(` \u2192 ${route.explanation}`));
7323
7595
  if (requiresConfirmation(route)) {
7324
7596
  const { confirm } = await inquirer14.prompt([{
7325
7597
  type: "confirm",
@@ -7328,7 +7600,7 @@ async function runNaturalLanguageRoute(input) {
7328
7600
  default: true
7329
7601
  }]);
7330
7602
  if (!confirm) {
7331
- console.log(chalk35.dim(` ${ko.nlp.menuHint}`));
7603
+ console.log(chalk36.dim(` ${ko.nlp.menuHint}`));
7332
7604
  return;
7333
7605
  }
7334
7606
  }
@@ -7337,7 +7609,7 @@ async function runNaturalLanguageRoute(input) {
7337
7609
  if (riskAction) {
7338
7610
  await runGuarded(
7339
7611
  riskAction,
7340
- { channel: "nl", approved: false, log: (m) => console.log(chalk35.yellow(` ${m}`)) },
7612
+ { channel: "nl", approved: false, log: (m) => console.log(chalk36.yellow(` ${m}`)) },
7341
7613
  () => dispatchNlpRoute(route, input)
7342
7614
  );
7343
7615
  return;
@@ -7346,80 +7618,80 @@ async function runNaturalLanguageRoute(input) {
7346
7618
  }
7347
7619
 
7348
7620
  // src/commands/agent.ts
7349
- import chalk36 from "chalk";
7621
+ import chalk37 from "chalk";
7350
7622
  function activeGoalId() {
7351
7623
  const goals = listGoals("goals");
7352
7624
  const id = selectActiveId(goals);
7353
7625
  return id ?? void 0;
7354
7626
  }
7355
7627
  async function blocker(description) {
7356
- console.log(chalk36.bold(`
7628
+ console.log(chalk37.bold(`
7357
7629
  ${ko.agent.blockerTitle}
7358
7630
  `));
7359
7631
  if (!description || !description.trim()) {
7360
- console.log(chalk36.red(" \u274C \uBE14\uB85C\uCEE4 \uC124\uBA85\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694."));
7361
- console.log(chalk36.dim(' \uC608: vhk blocker "tsc \uC5D0\uB7EC \u2014 simple-git \uD0C0\uC785 \uD638\uD658"'));
7632
+ console.log(chalk37.red(" \u274C \uBE14\uB85C\uCEE4 \uC124\uBA85\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694."));
7633
+ console.log(chalk37.dim(' \uC608: vhk blocker "tsc \uC5D0\uB7EC \u2014 simple-git \uD0C0\uC785 \uD638\uD658"'));
7362
7634
  process.exitCode = 1;
7363
7635
  return;
7364
7636
  }
7365
7637
  const goalId = activeGoalId();
7366
7638
  const r = appendBlocker(description, goalId);
7367
- console.log(chalk36.green(` \u2705 blocker \uAE30\uB85D (\uD604\uC7AC \uD65C\uC131 ${r.count}\uAC74)`));
7639
+ console.log(chalk37.green(` \u2705 blocker \uAE30\uB85D (\uD604\uC7AC \uD65C\uC131 ${r.count}\uAC74)`));
7368
7640
  if (r.hardStopTripped) {
7369
- console.log(chalk36.red.bold(" \u{1F6D1} HARD_STOP \uC790\uB3D9 \uC0DD\uC131 \u2014 \uBAA8\uB4E0 \uC790\uB3D9\uD654 \uC911\uB2E8."));
7370
- console.log(chalk36.yellow(" \uC0AC\uB78C \uAC80\uD1A0 \uD6C4 `vhk resume --confirm` \uC73C\uB85C\uB9CC \uD574\uC81C."));
7641
+ console.log(chalk37.red.bold(" \u{1F6D1} HARD_STOP \uC790\uB3D9 \uC0DD\uC131 \u2014 \uBAA8\uB4E0 \uC790\uB3D9\uD654 \uC911\uB2E8."));
7642
+ console.log(chalk37.yellow(" \uC0AC\uB78C \uAC80\uD1A0 \uD6C4 `vhk resume --confirm` \uC73C\uB85C\uB9CC \uD574\uC81C."));
7371
7643
  process.exitCode = 2;
7372
7644
  }
7373
7645
  }
7374
7646
  async function learn(lesson) {
7375
- console.log(chalk36.bold(`
7647
+ console.log(chalk37.bold(`
7376
7648
  ${ko.agent.learnTitle}
7377
7649
  `));
7378
7650
  if (!lesson || !lesson.trim()) {
7379
- console.log(chalk36.red(" \u274C \uAD50\uD6C8 \uB0B4\uC6A9\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694."));
7380
- console.log(chalk36.dim(' \uC608: vhk learn "PowerShell \uC5D0\uC11C\uB294 ; \uC0AC\uC6A9 (&& \uBBF8\uC9C0\uC6D0)"'));
7651
+ console.log(chalk37.red(" \u274C \uAD50\uD6C8 \uB0B4\uC6A9\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694."));
7652
+ console.log(chalk37.dim(' \uC608: vhk learn "PowerShell \uC5D0\uC11C\uB294 ; \uC0AC\uC6A9 (&& \uBBF8\uC9C0\uC6D0)"'));
7381
7653
  process.exitCode = 1;
7382
7654
  return;
7383
7655
  }
7384
7656
  const goalId = activeGoalId();
7385
7657
  const entry = recordLesson(process.cwd(), lesson, goalId);
7386
7658
  if (!entry) {
7387
- console.log(chalk36.red(" \u274C memory.json \uC190\uC0C1 \uC758\uC2EC \u2014 \uAD50\uD6C8 \uAE30\uB85D \uC911\uB2E8. \uC6D0\uBCF8/\uBC31\uC5C5 \uD655\uC778 \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694."));
7659
+ console.log(chalk37.red(" \u274C memory.json \uC190\uC0C1 \uC758\uC2EC \u2014 \uAD50\uD6C8 \uAE30\uB85D \uC911\uB2E8. \uC6D0\uBCF8/\uBC31\uC5C5 \uD655\uC778 \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694."));
7388
7660
  process.exitCode = 1;
7389
7661
  return;
7390
7662
  }
7391
- console.log(chalk36.green(` \u2705 \uAD50\uD6C8 \uAE30\uB85D \u2192 memory failures.lesson (${entry.id})`));
7392
- console.log(chalk36.dim(" \uAD50\uD6C8\xB7\uACB0\uC815\xB7\uC2E4\uD328\xB7\uC131\uACF5 \uBAA8\uB450 vhk memory (\uB2E8\uC77C SoT). vhk memory list \uB85C \uD655\uC778."));
7663
+ console.log(chalk37.green(` \u2705 \uAD50\uD6C8 \uAE30\uB85D \u2192 memory failures.lesson (${entry.id})`));
7664
+ console.log(chalk37.dim(" \uAD50\uD6C8\xB7\uACB0\uC815\xB7\uC2E4\uD328\xB7\uC131\uACF5 \uBAA8\uB450 vhk memory (\uB2E8\uC77C SoT). vhk memory list \uB85C \uD655\uC778."));
7393
7665
  }
7394
7666
  async function resume(opts = {}) {
7395
- console.log(chalk36.bold(`
7667
+ console.log(chalk37.bold(`
7396
7668
  ${ko.agent.resumeTitle}
7397
7669
  `));
7398
7670
  if (!isHardStopActive()) {
7399
- console.log(chalk36.dim(" HARD_STOP \uD65C\uC131 \uC544\uB2D8 \u2014 \uD560 \uC77C \uC5C6\uC74C."));
7671
+ console.log(chalk37.dim(" HARD_STOP \uD65C\uC131 \uC544\uB2D8 \u2014 \uD560 \uC77C \uC5C6\uC74C."));
7400
7672
  return;
7401
7673
  }
7402
7674
  const reason = readHardStopReason();
7403
7675
  if (reason) {
7404
- console.log(chalk36.yellow(" \u{1F4CB} HARD_STOP \uC0AC\uC720:"));
7405
- console.log(chalk36.dim(` ${reason.split("\n").join("\n ")}`));
7676
+ console.log(chalk37.yellow(" \u{1F4CB} HARD_STOP \uC0AC\uC720:"));
7677
+ console.log(chalk37.dim(` ${reason.split("\n").join("\n ")}`));
7406
7678
  console.log("");
7407
7679
  }
7408
7680
  if (!opts.confirm) {
7409
7681
  console.log(
7410
- chalk36.red(
7682
+ chalk37.red(
7411
7683
  " \u274C --confirm \uD50C\uB798\uADF8 \uC5C6\uC774\uB294 \uD574\uC81C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 (\uC790\uB3D9 \uD638\uCD9C \uAE08\uC9C0)."
7412
7684
  )
7413
7685
  );
7414
- console.log(chalk36.yellow(" \uC0AC\uC720\uB97C \uD655\uC778\uD55C \uD6C4 \uB2E4\uC2DC: vhk resume --confirm"));
7686
+ console.log(chalk37.yellow(" \uC0AC\uC720\uB97C \uD655\uC778\uD55C \uD6C4 \uB2E4\uC2DC: vhk resume --confirm"));
7415
7687
  process.exitCode = 1;
7416
7688
  return;
7417
7689
  }
7418
7690
  const removed = clearHardStop();
7419
7691
  if (removed) {
7420
- console.log(chalk36.green(" \u2705 HARD_STOP \uD574\uC81C. \uC790\uB3D9\uD654 \uC7AC\uAC1C \uAC00\uB2A5."));
7692
+ console.log(chalk37.green(" \u2705 HARD_STOP \uD574\uC81C. \uC790\uB3D9\uD654 \uC7AC\uAC1C \uAC00\uB2A5."));
7421
7693
  } else {
7422
- console.log(chalk36.dim(" \uD30C\uC77C\uC774 \uC774\uBBF8 \uC5C6\uC74C \u2014 no-op."));
7694
+ console.log(chalk37.dim(" \uD30C\uC77C\uC774 \uC774\uBBF8 \uC5C6\uC74C \u2014 no-op."));
7423
7695
  }
7424
7696
  }
7425
7697
 
@@ -7440,7 +7712,7 @@ async function guardCli(action, approved, run) {
7440
7712
  }]);
7441
7713
  return ok;
7442
7714
  },
7443
- log: (m) => console.log(chalk37.yellow(` ${m}`))
7715
+ log: (m) => console.log(chalk38.yellow(` ${m}`))
7444
7716
  },
7445
7717
  run
7446
7718
  );
@@ -7453,7 +7725,7 @@ async function guardCliDefer(action, approved, run) {
7453
7725
  approved,
7454
7726
  // TTY 면 통과(명령이 자체 확인), 비대화형은 confirm 불가 → 가드가 차단.
7455
7727
  confirm: async () => !!process.stdout.isTTY,
7456
- log: (m) => console.log(chalk37.yellow(` ${m}`))
7728
+ log: (m) => console.log(chalk38.yellow(` ${m}`))
7457
7729
  },
7458
7730
  run
7459
7731
  );
@@ -7498,7 +7770,8 @@ var KO_ALIASES = {
7498
7770
  learn: "\uAD50\uD6C8",
7499
7771
  resume: "\uC7AC\uAC1C",
7500
7772
  pattern: "\uD328\uD134",
7501
- evolve: "\uC9C4\uD654"
7773
+ evolve: "\uC9C4\uD654",
7774
+ work: "\uC791\uC5C5"
7502
7775
  };
7503
7776
  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(getVhkVersion());
7504
7777
  program.configureHelp({
@@ -7546,7 +7819,9 @@ cloudCmd.command("pull").alias("\uB0B4\uB9AC\uAE30").argument("[gistId]", "\uBCF
7546
7819
  await guardCli("cloud-pull", opts?.yes === true, () => cloudPull(gistId));
7547
7820
  });
7548
7821
  program.command("ship").alias("\uCD9C\uD558").description("\uBC30\uD3EC \uCCB4\uD06C\uB9AC\uC2A4\uD2B8 + \uD68C\uACE0 + \uBE4C\uB4DC \uB85C\uADF8 \uC0DD\uC131").action(ship);
7549
- 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);
7822
+ program.command("doctor").alias("\uD658\uACBD").alias("\uC9C4\uB2E8").option("--strict", "\uADDC\uCE59 \uB4DC\uB9AC\uD504\uD2B8 \uBC1C\uACAC \uC2DC \uC2E4\uD328 \uCC98\uB9AC (exit 1, CI \uAC8C\uC774\uD2B8\uC6A9)").description("\uAC1C\uBC1C \uD658\uACBD \uC810\uAC80 \u2014 Node/Git/npm \uC0C1\uD0DC \uD655\uC778").action(async (opts) => {
7823
+ await doctor(opts);
7824
+ });
7550
7825
  program.command("save").alias("\uC800\uC7A5").option("--yes", "\uD655\uC778 \uC5C6\uC774 \uC2E4\uD589 (strict \uBAA8\uB4DC \uAC00\uB4DC \uBA85\uC2DC \uC2B9\uC778)").description("\uBCC0\uACBD\uC0AC\uD56D \uC800\uC7A5 (git add \u2192 commit \u2192 push)").action(async (opts) => {
7551
7826
  await guardCli("save", opts?.yes === true, () => save());
7552
7827
  });
@@ -7668,6 +7943,12 @@ memoryCmd.command("migrate").alias("\uB9C8\uC774\uADF8\uB808\uC774\uC158").descr
7668
7943
  program.command("brief").alias("\uBE0C\uB9AC\uD551").description("\uD504\uB85C\uC81D\uD2B8 \uC0C1\uD0DC \uC694\uC57D \uBCF4\uACE0\uC11C \uC0DD\uC131 (.vhk/brief.md)").action(async () => {
7669
7944
  await brief();
7670
7945
  });
7946
+ var workCmd = program.command("work").alias("\uC791\uC5C5").description("AI \uC791\uC5C5 \uC2DC\uC791/\uC774\uC5B4\uD558\uAE30 \u2014 \uC2DC\uC791 \uD504\uB86C\uD504\uD2B8 \uC0DD\uC131 \uD6C4 \uD074\uB9BD\uBCF4\uB4DC \uBCF5\uC0AC").action(async () => {
7947
+ await work();
7948
+ });
7949
+ workCmd.command("handoff").alias("\uC778\uC218\uC778\uACC4").description("\uC791\uC5C5 \uC911\uB2E8 \uC815\uB9AC \u2014 \uC778\uC218\uC778\uACC4 \uD504\uB86C\uD504\uD2B8 \uC0DD\uC131 \uD6C4 \uD074\uB9BD\uBCF4\uB4DC \uBCF5\uC0AC").action(async () => {
7950
+ await workHandoff();
7951
+ });
7671
7952
  var goalCmd = program.command("goal").alias("\uBAA9\uD45C").description("Goal \uB2E8\uACC4\uBCC4 \uBBF8\uC158 \uAD00\uB9AC (init / list / next / check / done / sync)").action(async () => {
7672
7953
  await goalList();
7673
7954
  });
@@ -7800,9 +8081,9 @@ if (isMainModule) {
7800
8081
  }
7801
8082
  } catch (err) {
7802
8083
  if (isPromptAbortError(err)) {
7803
- console.error(chalk37.yellow("\n \u26A0\uFE0F \uB300\uD654\uD615 \uC785\uB825\uC774 \uCDE8\uC18C/\uC885\uB8CC\uB410\uC2B5\uB2C8\uB2E4. (\uBE44\uB300\uD654\uD615 \uD658\uACBD\uC5D0\uC11C\uB294 \uD574\uB2F9 \uBA85\uB839\uC744 \uC4F8 \uC218 \uC5C6\uC5B4\uC694)"));
8084
+ console.error(chalk38.yellow("\n \u26A0\uFE0F \uB300\uD654\uD615 \uC785\uB825\uC774 \uCDE8\uC18C/\uC885\uB8CC\uB410\uC2B5\uB2C8\uB2E4. (\uBE44\uB300\uD654\uD615 \uD658\uACBD\uC5D0\uC11C\uB294 \uD574\uB2F9 \uBA85\uB839\uC744 \uC4F8 \uC218 \uC5C6\uC5B4\uC694)"));
7804
8085
  } else {
7805
- console.error(chalk37.red(`
8086
+ console.error(chalk38.red(`
7806
8087
  \u274C ${err instanceof Error ? err.message : String(err)}`));
7807
8088
  }
7808
8089
  process.exitCode = 1;