@byh3071/vhk 1.8.1 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -43,13 +43,13 @@ import {
43
43
  stripBom,
44
44
  sync,
45
45
  t
46
- } from "./chunk-RXDOM4QT.js";
46
+ } from "./chunk-HCNU6K7D.js";
47
47
 
48
48
  // src/index.ts
49
49
  import { Command, Help } from "commander";
50
50
  import { pathToFileURL } from "url";
51
- import chalk34 from "chalk";
52
- import inquirer13 from "inquirer";
51
+ import chalk35 from "chalk";
52
+ import inquirer14 from "inquirer";
53
53
 
54
54
  // src/lib/nlp-router.ts
55
55
  function normalize(input) {
@@ -129,6 +129,12 @@ var RULES = [
129
129
  confidence: "high",
130
130
  test: (t2) => /적대\s*검증|자기\s*검증|거짓\s*완료|완료\s*심문|^review$|^검토$/.test(t2)
131
131
  },
132
+ {
133
+ command: "mission",
134
+ explanation: "\uBBF8\uC158 \uACC4\uC57D \u2014 \uC791\uC5C5 \uBC94\uC704\xB7\uAE08\uC9C0\uC120 \uC120\uC5B8/\uAC80\uC99D (vhk mission)",
135
+ confidence: "high",
136
+ test: (t2) => /미션\s*계약|작업\s*범위|범위\s*검증|^mission$|^미션$/.test(t2)
137
+ },
132
138
  {
133
139
  command: "init",
134
140
  explanation: "\uBB38\uC11C/\uD558\uB124\uC2A4 \uD30C\uC77C\uB9CC \uC0DD\uC131 (vhk init) \u2014 git/MCP/context\uB294 \uC81C\uC678",
@@ -177,11 +183,20 @@ var RULES = [
177
183
  confidence: "high",
178
184
  test: (t2) => /감사|취약점|audit|vulnerability|보안\s*감사|보안\s*취약|의존성\s*취약/.test(t2)
179
185
  },
186
+ // memory 마이그레이션은 패키지매니저 migrate 보다 **먼저** 평가 — "기억/메모리 마이그레이트" 가
187
+ // pnpm 전환(vhk migrate)으로 새지 않도록. 기억/메모리/memory 한정이라 bare "마이그레이트"는 안 가로챔.
188
+ {
189
+ command: "memory",
190
+ args: ["migrate"],
191
+ explanation: "memory.json v1 \u2192 v2 \uB9C8\uC774\uADF8\uB808\uC774\uC158 (vhk memory migrate)",
192
+ confidence: "high",
193
+ test: (t2) => /(기억|메모리|memory)\s*(을|를)?\s*(마이그레이|migrat)/.test(t2)
194
+ },
180
195
  {
181
196
  command: "migrate",
182
197
  explanation: "\uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800 \uC804\uD658 (vhk migrate)",
183
198
  confidence: "high",
184
- test: (t2) => /전환|마이그레이트|migrate|패키지\s*매니저|npm.*pnpm|pnpm.*npm|yarn.*전환|npm.*전환|pnpm.*전환/.test(t2)
199
+ test: (t2) => /전환|마이그레이(트|션)|migrate|패키지\s*매니저|npm.*pnpm|pnpm.*npm|yarn.*전환|npm.*전환|pnpm.*전환/.test(t2) && !/(기억|메모리|memory)\s*(을|를)?\s*(마이그레이|migrat)/.test(t2)
185
200
  },
186
201
  {
187
202
  command: "update",
@@ -205,7 +220,9 @@ var RULES = [
205
220
  command: "memory",
206
221
  explanation: "\uAE30\uC5B5 \uBAA9\uB85D \uC870\uD68C (vhk memory list)",
207
222
  confidence: "high",
208
- test: (t2) => /^기억$|기억\s*(목록|보|확인|뭐)|memory.*list|결정사항\s*(목록|확인|보여)/.test(t2) && !/(추가|add|삭제|remove|저장|기록해)/.test(t2)
223
+ // 보관(archive)/해결(resolve)/마이그레이션은 list 아니다 → **제외 토큰 한 곳**에서 오라우팅 차단.
224
+ // archive/resolve 는 <번호> 인자가 필요해 NL 미지원 → 매칭 안 되면 notMatched 가 정직(잘못된 list 실행 금지).
225
+ test: (t2) => /^기억$|기억\s*(목록|보|확인|뭐)|memory.*list|결정사항\s*(목록|확인|보여)/.test(t2) && !/(추가|add|삭제|remove|저장|기록해|보관|아카이브|archive|마이그레이|migrat|해결|복구)/.test(t2)
209
226
  },
210
227
  {
211
228
  command: "brief",
@@ -366,12 +383,13 @@ function extractNotionUrl(input) {
366
383
  var CONTAINER_SUBCOMMANDS = {
367
384
  goal: ["list", "next", "check", "init", "done", "sync"],
368
385
  ref: ["add", "list", "open"],
369
- memory: ["add", "list", "remove"],
386
+ memory: ["add", "list", "remove", "archive", "resolve", "unarchive", "migrate"],
370
387
  cloud: ["push", "pull"],
371
388
  secure: ["scan"],
372
389
  design: ["palette"],
373
390
  env: ["check"],
374
- mode: ["lite", "standard", "strict"]
391
+ mode: ["lite", "standard", "strict"],
392
+ mission: ["set", "check", "clear"]
375
393
  };
376
394
  var CONTAINER_ALIASES = {
377
395
  \uBAA9\uD45C: "goal",
@@ -381,7 +399,8 @@ var CONTAINER_ALIASES = {
381
399
  \uBCF4\uC548: "secure",
382
400
  \uB514\uC790\uC778: "design",
383
401
  \uD658\uACBD\uBCC0\uC218: "env",
384
- \uBAA8\uB4DC: "mode"
402
+ \uBAA8\uB4DC: "mode",
403
+ \uBBF8\uC158: "mission"
385
404
  };
386
405
 
387
406
  // src/lib/cli-args.ts
@@ -476,6 +495,8 @@ var KNOWN_COMMAND_TOKENS = /* @__PURE__ */ new Set([
476
495
  "\uC0AC\uC804\uC810\uAC80",
477
496
  "review",
478
497
  "\uAC80\uD1A0",
498
+ "mission",
499
+ "\uBBF8\uC158",
479
500
  "help"
480
501
  ]);
481
502
  function isOptionToken(token) {
@@ -513,8 +534,8 @@ function detectNaturalLanguageInput(argv) {
513
534
  }
514
535
 
515
536
  // src/lib/nlp-run.ts
516
- import chalk32 from "chalk";
517
- import inquirer12 from "inquirer";
537
+ import chalk33 from "chalk";
538
+ import inquirer13 from "inquirer";
518
539
 
519
540
  // src/commands/gate.ts
520
541
  import inquirer from "inquirer";
@@ -1695,32 +1716,6 @@ ${line}
1695
1716
  }
1696
1717
  return { count, hardStopTripped };
1697
1718
  }
1698
- function appendLearning(lesson, goalId) {
1699
- ensureStateDir();
1700
- const tag = goalId !== void 0 ? `goal-${goalId}` : "no-goal";
1701
- const line = `- [${isoDate()} ${tag}] ${lesson.trim()}`;
1702
- if (!existsSync(LEARNINGS_PATH)) {
1703
- writeFileSync(
1704
- LEARNINGS_PATH,
1705
- `# Learnings
1706
-
1707
- _Append-only. \uD55C \uC904 = \uD55C \uAD50\uD6C8._
1708
-
1709
- ${line}
1710
- `,
1711
- "utf-8"
1712
- );
1713
- } else {
1714
- appendFileSync(LEARNINGS_PATH, `${line}
1715
- `, "utf-8");
1716
- }
1717
- }
1718
- function getRecentLearnings(limit = 3) {
1719
- if (!existsSync(LEARNINGS_PATH)) return [];
1720
- const lines = readFileSync(LEARNINGS_PATH, "utf-8").split(/\r?\n/);
1721
- const entries = lines.filter((l) => l.startsWith("- ["));
1722
- return entries.slice(-limit);
1723
- }
1724
1719
  function getActiveBlockers(limit = 3) {
1725
1720
  if (!existsSync(BLOCKERS_PATH)) return [];
1726
1721
  const lines = readFileSync(BLOCKERS_PATH, "utf-8").split(/\r?\n/);
@@ -4434,15 +4429,432 @@ async function update() {
4434
4429
 
4435
4430
  // src/commands/context.ts
4436
4431
  import {
4437
- existsSync as existsSync11,
4438
- mkdirSync as mkdirSync7,
4439
- readFileSync as readFileSync4,
4432
+ existsSync as existsSync12,
4433
+ mkdirSync as mkdirSync8,
4434
+ readFileSync as readFileSync5,
4440
4435
  readdirSync as readdirSync2,
4441
4436
  statSync as statSync2,
4442
- writeFileSync as writeFileSync7
4437
+ writeFileSync as writeFileSync8
4443
4438
  } from "fs";
4439
+ import { join as join8 } from "path";
4440
+ import chalk24 from "chalk";
4441
+
4442
+ // src/commands/memory.ts
4443
+ import { existsSync as existsSync11, mkdirSync as mkdirSync7, writeFileSync as writeFileSync7, copyFileSync, readFileSync as readFileSync4, renameSync, rmSync as rmSync3 } from "fs";
4444
4444
  import { join as join7 } from "path";
4445
4445
  import chalk23 from "chalk";
4446
+ var MEMORY_PATH_REL = join7(".vhk", "memory.json");
4447
+ var MEMORY_SCHEMA_VERSION = 2;
4448
+ function emptyV2() {
4449
+ return { schemaVersion: MEMORY_SCHEMA_VERSION, decisions: [], failures: [], successes: [], patterns: [] };
4450
+ }
4451
+ function isV2(raw) {
4452
+ return !!raw && typeof raw === "object" && raw.schemaVersion === 2;
4453
+ }
4454
+ var BUCKET_PREFIX = { decision: "d", failure: "f", success: "s" };
4455
+ function arr(v) {
4456
+ return Array.isArray(v) ? v : [];
4457
+ }
4458
+ function normalizeV2(raw) {
4459
+ return {
4460
+ schemaVersion: MEMORY_SCHEMA_VERSION,
4461
+ decisions: arr(raw.decisions),
4462
+ failures: arr(raw.failures),
4463
+ successes: arr(raw.successes),
4464
+ patterns: arr(raw.patterns)
4465
+ };
4466
+ }
4467
+ function parseLearnings(rawLearnings) {
4468
+ const out = [];
4469
+ for (const line of rawLearnings.split(/\r?\n/)) {
4470
+ const m = line.match(/^-\s*\[(\d{4}-\d{2}-\d{2})\s+([^\]]*)\]\s*(.+)$/);
4471
+ if (m) out.push({ date: m[1], tag: m[2].trim(), lesson: m[3].trim() });
4472
+ }
4473
+ return out;
4474
+ }
4475
+ function migrateMemory(rawMemory, rawLearnings) {
4476
+ if (isV2(rawMemory)) return normalizeV2(rawMemory);
4477
+ const v2 = emptyV2();
4478
+ if (Array.isArray(rawMemory)) {
4479
+ rawMemory.forEach((m, i) => {
4480
+ const item = m;
4481
+ if (item && typeof item.content === "string") {
4482
+ v2.decisions.push({
4483
+ id: `d${i + 1}`,
4484
+ content: item.content,
4485
+ tags: arr(item.tags),
4486
+ createdAt: typeof item.addedAt === "string" ? item.addedAt : "",
4487
+ status: "active"
4488
+ });
4489
+ }
4490
+ });
4491
+ }
4492
+ if (rawLearnings) {
4493
+ parseLearnings(rawLearnings).forEach((l, i) => {
4494
+ v2.failures.push({
4495
+ id: `f${i + 1}`,
4496
+ content: "",
4497
+ tags: l.tag ? [l.tag] : [],
4498
+ createdAt: l.date,
4499
+ status: "active",
4500
+ lesson: l.lesson
4501
+ });
4502
+ });
4503
+ }
4504
+ return v2;
4505
+ }
4506
+ function readRaw(cwd) {
4507
+ const p = join7(cwd, MEMORY_PATH_REL);
4508
+ if (!existsSync11(p)) return { kind: "missing" };
4509
+ try {
4510
+ return { kind: "parsed", value: readJsonFile(p) };
4511
+ } catch {
4512
+ return { kind: "error" };
4513
+ }
4514
+ }
4515
+ function warnUnreadable(cwd) {
4516
+ const p = join7(cwd, MEMORY_PATH_REL);
4517
+ console.error(chalk23.red(`
4518
+ \u26A0\uFE0F ${MEMORY_PATH_REL} \uB97C \uC77D\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 (\uC190\uC0C1/\uBD80\uBD84 \uC4F0\uAE30 \uC758\uC2EC).`));
4519
+ console.error(chalk23.yellow(` \uB36E\uC5B4\uC4F0\uC9C0 \uC54A\uACE0 \uBE48 \uBA54\uBAA8\uB9AC\uB85C \uC9C4\uD589\uD569\uB2C8\uB2E4 \u2014 \uC6D0\uBCF8 \uBCF4\uC874\uB428.`));
4520
+ console.error(chalk23.dim(` \uD655\uC778/\uBCF5\uAD6C: ${p} (\uBC31\uC5C5: ${p}.bak / ${p}.v1.bak)`));
4521
+ }
4522
+ function warnUnrecognized(cwd) {
4523
+ const p = join7(cwd, MEMORY_PATH_REL);
4524
+ console.error(chalk23.red(`
4525
+ \u26A0\uFE0F ${MEMORY_PATH_REL} \uAC00 \uC778\uC2DD \uAC00\uB2A5\uD55C \uD615\uC2DD\uC774 \uC544\uB2D9\uB2C8\uB2E4 (v1 \uBC30\uC5F4/v2 \uAC1D\uCCB4 \uC544\uB2D8).`));
4526
+ console.error(chalk23.yellow(` \uBBF8\uB798 \uC2A4\uD0A4\uB9C8/\uC218\uB3D9 \uD3B8\uC9D1 \uC758\uC2EC \u2014 \uB36E\uC5B4\uC4F0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(\uC6D0\uBCF8 \uBCF4\uC874). \uD655\uC778 \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4.`));
4527
+ console.error(chalk23.dim(` \uD655\uC778: ${p}`));
4528
+ }
4529
+ function readLearningsRaw(cwd) {
4530
+ const p = join7(cwd, "docs", "state", "learnings.md");
4531
+ if (!existsSync11(p)) return void 0;
4532
+ try {
4533
+ return stripBom(readFileSync4(p, "utf-8"));
4534
+ } catch {
4535
+ return void 0;
4536
+ }
4537
+ }
4538
+ function readMemory(cwd = process.cwd()) {
4539
+ const raw = readRaw(cwd);
4540
+ if (raw.kind === "error") {
4541
+ warnUnreadable(cwd);
4542
+ return emptyV2();
4543
+ }
4544
+ if (raw.kind === "parsed") {
4545
+ if (isV2(raw.value)) return normalizeV2(raw.value);
4546
+ if (Array.isArray(raw.value)) {
4547
+ const v2 = migrateMemory(raw.value, readLearningsRaw(cwd));
4548
+ try {
4549
+ writeMemory(cwd, v2);
4550
+ } catch {
4551
+ console.error(chalk23.yellow(` (v2 \uC601\uAD6C\uD654 \uBCF4\uB958 \u2014 ${MEMORY_PATH_REL} \uC7A0\uAE08 \uC758\uC2EC. \uC774\uBC88\uC5D4 \uBA54\uBAA8\uB9AC\uC0C1\uC73C\uB85C\uB9CC \uC9C4\uD589)`));
4552
+ }
4553
+ return v2;
4554
+ }
4555
+ warnUnrecognized(cwd);
4556
+ return emptyV2();
4557
+ }
4558
+ return migrateMemory(null, readLearningsRaw(cwd));
4559
+ }
4560
+ function loadForMutation(cwd) {
4561
+ const raw = readRaw(cwd);
4562
+ if (raw.kind === "error") {
4563
+ warnUnreadable(cwd);
4564
+ return { ok: false };
4565
+ }
4566
+ if (raw.kind === "parsed") {
4567
+ if (isV2(raw.value)) return { ok: true, mem: normalizeV2(raw.value) };
4568
+ if (Array.isArray(raw.value)) return { ok: true, mem: migrateMemory(raw.value, readLearningsRaw(cwd)) };
4569
+ warnUnrecognized(cwd);
4570
+ return { ok: false };
4571
+ }
4572
+ return { ok: true, mem: migrateMemory(null, readLearningsRaw(cwd)) };
4573
+ }
4574
+ function isActive(e) {
4575
+ return e.status !== "archived" && e.status !== "resolved";
4576
+ }
4577
+ function writeMemory(cwd, mem) {
4578
+ const p = join7(cwd, MEMORY_PATH_REL);
4579
+ mkdirSync7(join7(cwd, ".vhk"), { recursive: true });
4580
+ if (existsSync11(p)) {
4581
+ const cur = readRaw(cwd);
4582
+ const curIsV2 = cur.kind === "parsed" && isV2(cur.value);
4583
+ if (cur.kind !== "error" && !curIsV2 && !existsSync11(p + ".v1.bak")) {
4584
+ try {
4585
+ copyFileSync(p, p + ".v1.bak");
4586
+ } catch {
4587
+ }
4588
+ }
4589
+ if (cur.kind !== "error") {
4590
+ try {
4591
+ copyFileSync(p, p + ".bak");
4592
+ } catch {
4593
+ }
4594
+ }
4595
+ }
4596
+ const tmpPath = p + ".tmp";
4597
+ writeFileSync7(tmpPath, JSON.stringify(mem, null, 2) + "\n", "utf-8");
4598
+ try {
4599
+ renameSync(tmpPath, p);
4600
+ } catch (err) {
4601
+ try {
4602
+ rmSync3(tmpPath, { force: true });
4603
+ } catch {
4604
+ }
4605
+ throw err;
4606
+ }
4607
+ }
4608
+ function nextId(bucket, mem) {
4609
+ const prefix = BUCKET_PREFIX[bucket];
4610
+ const list = bucket === "decision" ? mem.decisions : bucket === "failure" ? mem.failures : mem.successes;
4611
+ const idRe = new RegExp(`^${prefix}(\\d+)$`);
4612
+ let max = 0;
4613
+ for (const e of list) {
4614
+ const m = e.id.match(idRe);
4615
+ if (m) max = Math.max(max, Number(m[1]));
4616
+ }
4617
+ return `${prefix}${max + 1}`;
4618
+ }
4619
+ function orderedAll(mem) {
4620
+ return [
4621
+ ...mem.decisions.map((entry) => ({ bucket: "decision", entry })),
4622
+ ...mem.failures.map((entry) => ({ bucket: "failure", entry })),
4623
+ ...mem.successes.map((entry) => ({ bucket: "success", entry }))
4624
+ ];
4625
+ }
4626
+ var VALID_BUCKETS = ["decision", "failure", "success"];
4627
+ async function memoryAdd(content, opts = {}) {
4628
+ console.log(chalk23.bold("\n\u{1F9E0} " + t("memory.addTitle")));
4629
+ console.log(chalk23.gray("\u2500".repeat(40)));
4630
+ if (!content || !content.trim()) {
4631
+ console.log(chalk23.red("\u274C \uAE30\uC5B5\uD560 \uB0B4\uC6A9\uC744 \uC785\uB825\uD574\uC8FC\uC138\uC694."));
4632
+ console.log(chalk23.gray(' \uC608: vhk memory add "API\uB294 tRPC \uC0AC\uC6A9" --type decision'));
4633
+ process.exitCode = 1;
4634
+ return;
4635
+ }
4636
+ const typeRaw = opts.type ?? "decision";
4637
+ if (!VALID_BUCKETS.includes(typeRaw)) {
4638
+ console.log(chalk23.red(`\u274C --type \uC740 decision|failure|success \uC911 \uD558\uB098\uC5EC\uC57C \uD569\uB2C8\uB2E4 (\uBC1B\uC740 \uAC12: ${typeRaw}).`));
4639
+ process.exitCode = 1;
4640
+ return;
4641
+ }
4642
+ const type = typeRaw;
4643
+ if (type === "decision" && (opts.why || opts.lesson)) {
4644
+ console.log(chalk23.yellow("\u26A0\uFE0F --why/--lesson \uC740 --type failure|success \uC5D0\uC11C\uB9CC \uC800\uC7A5\uB429\uB2C8\uB2E4 \u2014 decision \uC5D0\uC11C\uB294 \uBB34\uC2DC\uB428."));
4645
+ }
4646
+ const cwd = process.cwd();
4647
+ const loaded = loadForMutation(cwd);
4648
+ if (!loaded.ok) {
4649
+ console.log(chalk23.red("\u274C memory.json \uC190\uC0C1 \uC758\uC2EC \u2014 \uC800\uC7A5 \uC911\uB2E8 (\uC6D0\uBCF8 \uBCF4\uC874). \uBC31\uC5C5 \uD655\uC778 \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694."));
4650
+ process.exitCode = 1;
4651
+ return;
4652
+ }
4653
+ const mem = loaded.mem;
4654
+ const base = {
4655
+ id: nextId(type, mem),
4656
+ content: content.trim(),
4657
+ tags: opts.tags && opts.tags.length > 0 ? opts.tags : [],
4658
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
4659
+ status: "active"
4660
+ };
4661
+ if (type === "failure") mem.failures.push({ ...base, why: opts.why, lesson: opts.lesson });
4662
+ else if (type === "success") mem.successes.push({ ...base, why: opts.why });
4663
+ else mem.decisions.push(base);
4664
+ writeMemory(cwd, mem);
4665
+ console.log(chalk23.green(`
4666
+ \u2705 \uAE30\uC5B5 \uC800\uC7A5\uB428 (${type} #${base.id})`));
4667
+ console.log(chalk23.cyan(` \u{1F4DD} ${base.content}`));
4668
+ printNextStep({ message: "\uAE30\uC5B5 \uC800\uC7A5 \uC644\uB8CC!", command: "vhk memory list", cursorHint: "\uAE30\uC5B5 \uBAA9\uB85D \uBCF4\uC5EC\uC918" });
4669
+ }
4670
+ var STATUS_ICON2 = { active: "\u{1F7E2}", resolved: "\u2705", archived: "\u{1F4E6}" };
4671
+ var BUCKET_LABEL = { decision: "\uACB0\uC815", failure: "\uC2E4\uD328", success: "\uC131\uACF5" };
4672
+ async function memoryList(opts = {}) {
4673
+ console.log(chalk23.bold("\n\u{1F9E0} " + t("memory.listTitle")));
4674
+ console.log(chalk23.gray("\u2500".repeat(40)));
4675
+ const mem = readMemory(process.cwd());
4676
+ const all = orderedAll(mem);
4677
+ const visible = all.map((x, i) => ({ ...x, n: i + 1 })).filter((x) => (opts.all || isActive(x.entry)) && (!opts.type || x.bucket === opts.type));
4678
+ if (visible.length === 0) {
4679
+ console.log(chalk23.yellow("\n\u{1F4ED} \uD45C\uC2DC\uD560 \uAE30\uC5B5\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."));
4680
+ console.log(chalk23.gray(' vhk memory add "\uB0B4\uC6A9" --type decision|failure|success'));
4681
+ return;
4682
+ }
4683
+ console.log(chalk23.cyan(`
4684
+ ${visible.length}\uAC1C${opts.all ? " (\uBCF4\uAD00 \uD3EC\uD568)" : " (\uD65C\uC131)"}:
4685
+ `));
4686
+ for (const x of visible) {
4687
+ const e = x.entry;
4688
+ const fail = e;
4689
+ console.log(` [${x.n}] ${STATUS_ICON2[e.status] ?? "\u{1F7E2}"} (${BUCKET_LABEL[x.bucket]}) ${e.content || (fail.lesson ? "\u{1F4A1} " + fail.lesson : "(\uB0B4\uC6A9 \uC5C6\uC74C)")}`);
4690
+ if (fail.lesson && e.content) console.log(chalk23.dim(` \u{1F4A1} \uAD50\uD6C8: ${fail.lesson}`));
4691
+ if (fail.why) console.log(chalk23.dim(` \u21B3 ${fail.why}`));
4692
+ if (e.tags.length > 0) console.log(chalk23.blue(` \u{1F3F7}\uFE0F ${e.tags.join(", ")}`));
4693
+ }
4694
+ }
4695
+ function resolveIndex(indexStr, len) {
4696
+ const idx = parseInt(indexStr, 10) - 1;
4697
+ if (Number.isNaN(idx) || idx < 0 || idx >= len) return null;
4698
+ return idx;
4699
+ }
4700
+ async function memoryRemove(indexStr) {
4701
+ const cwd = process.cwd();
4702
+ const loaded = loadForMutation(cwd);
4703
+ if (!loaded.ok) {
4704
+ console.log(chalk23.red("\u274C memory.json \uC190\uC0C1 \uC758\uC2EC \u2014 \uC0AD\uC81C \uC911\uB2E8 (\uC6D0\uBCF8 \uBCF4\uC874)."));
4705
+ process.exitCode = 1;
4706
+ return;
4707
+ }
4708
+ const mem = loaded.mem;
4709
+ const all = orderedAll(mem);
4710
+ const idx = resolveIndex(indexStr, all.length);
4711
+ if (idx === null) {
4712
+ console.log(chalk23.red(`\u274C \uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uBC88\uD638\uC785\uB2C8\uB2E4. (1~${all.length || 0})`));
4713
+ process.exitCode = 1;
4714
+ return;
4715
+ }
4716
+ const { bucket, entry } = all[idx];
4717
+ const list = bucket === "decision" ? mem.decisions : bucket === "failure" ? mem.failures : mem.successes;
4718
+ const pos = list.findIndex((e) => e === entry);
4719
+ if (pos >= 0) list.splice(pos, 1);
4720
+ writeMemory(cwd, mem);
4721
+ console.log(chalk23.green("\n\u2705 \uAE30\uC5B5 \uC0AD\uC81C\uB428:"));
4722
+ console.log(chalk23.gray(` ${entry.content || entry.lesson || entry.id}`));
4723
+ }
4724
+ function resolveEntryForMutation(indexStr) {
4725
+ const cwd = process.cwd();
4726
+ const loaded = loadForMutation(cwd);
4727
+ if (!loaded.ok) {
4728
+ console.log(chalk23.red("\u274C memory.json \uC190\uC0C1 \uC758\uC2EC \u2014 \uC791\uC5C5 \uC911\uB2E8 (\uC6D0\uBCF8 \uBCF4\uC874)."));
4729
+ process.exitCode = 1;
4730
+ return null;
4731
+ }
4732
+ const mem = loaded.mem;
4733
+ const all = orderedAll(mem);
4734
+ const idx = resolveIndex(indexStr, all.length);
4735
+ if (idx === null) {
4736
+ console.log(chalk23.red(`\u274C \uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uBC88\uD638\uC785\uB2C8\uB2E4. (1~${all.length || 0})`));
4737
+ process.exitCode = 1;
4738
+ return null;
4739
+ }
4740
+ return { cwd, mem, entry: all[idx].entry };
4741
+ }
4742
+ function entryLabel(entry) {
4743
+ return entry.content || entry.lesson || entry.id;
4744
+ }
4745
+ async function memoryArchive(indexStr) {
4746
+ const r = resolveEntryForMutation(indexStr);
4747
+ if (!r) return;
4748
+ r.entry.status = "archived";
4749
+ r.entry.archivedAt = (/* @__PURE__ */ new Date()).toISOString();
4750
+ delete r.entry.resolvedAt;
4751
+ writeMemory(r.cwd, r.mem);
4752
+ console.log(chalk23.green(`
4753
+ \u{1F4E6} \uBCF4\uAD00\uB428: ${entryLabel(r.entry)}`));
4754
+ console.log(chalk23.dim(" (\uD328\uD134 \uAC10\uC9C0\xB7\uC9C4\uD654\uC5D0\uC11C \uC81C\uC678\uB429\uB2C8\uB2E4 \u2014 \uC120\uC21C\uD658). \uB418\uB3CC\uB9AC\uAE30: vhk memory unarchive <\uBC88\uD638>"));
4755
+ }
4756
+ async function memoryResolve(indexStr) {
4757
+ const r = resolveEntryForMutation(indexStr);
4758
+ if (!r) return;
4759
+ r.entry.status = "resolved";
4760
+ r.entry.resolvedAt = (/* @__PURE__ */ new Date()).toISOString();
4761
+ delete r.entry.archivedAt;
4762
+ writeMemory(r.cwd, r.mem);
4763
+ console.log(chalk23.green(`
4764
+ \u2705 \uD574\uACB0\uB428: ${entryLabel(r.entry)}`));
4765
+ console.log(chalk23.dim(" (vhk memory list --all \uB85C \uD655\uC778. \uB418\uB3CC\uB9AC\uAE30: vhk memory unarchive <\uBC88\uD638>)"));
4766
+ }
4767
+ async function memoryUnarchive(indexStr) {
4768
+ const r = resolveEntryForMutation(indexStr);
4769
+ if (!r) return;
4770
+ if (isActive(r.entry)) {
4771
+ console.log(chalk23.dim(` \uC774\uBBF8 \uD65C\uC131 \uD56D\uBAA9\uC785\uB2C8\uB2E4 \u2014 \uBCC0\uACBD \uC5C6\uC74C: ${entryLabel(r.entry)}`));
4772
+ return;
4773
+ }
4774
+ r.entry.status = "active";
4775
+ delete r.entry.archivedAt;
4776
+ delete r.entry.resolvedAt;
4777
+ writeMemory(r.cwd, r.mem);
4778
+ console.log(chalk23.green(`
4779
+ \u{1F7E2} \uD65C\uC131\uC73C\uB85C \uBCF5\uAD6C\uB428: ${entryLabel(r.entry)}`));
4780
+ }
4781
+ async function memoryMigrate() {
4782
+ const cwd = process.cwd();
4783
+ const raw = readRaw(cwd);
4784
+ if (raw.kind === "error") {
4785
+ warnUnreadable(cwd);
4786
+ console.log(chalk23.red(" \u274C \uB9C8\uC774\uADF8\uB808\uC774\uC158 \uC911\uB2E8 (\uC190\uC0C1 \uC758\uC2EC). \uC6D0\uBCF8 \uD655\uC778 \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694."));
4787
+ process.exitCode = 1;
4788
+ return;
4789
+ }
4790
+ if (raw.kind === "parsed" && isV2(raw.value)) {
4791
+ console.log(chalk23.dim(" \uC774\uBBF8 memory schema v2 \uC785\uB2C8\uB2E4 \u2014 \uBCC0\uACBD \uC5C6\uC74C(\uBA71\uB4F1)."));
4792
+ return;
4793
+ }
4794
+ if (raw.kind === "parsed" && !Array.isArray(raw.value)) {
4795
+ warnUnrecognized(cwd);
4796
+ console.log(chalk23.red(" \u274C v1(\uD3C9\uBA74 \uBC30\uC5F4) \uD615\uC2DD\uC774 \uC544\uB2C8\uB77C \uB9C8\uC774\uADF8\uB808\uC774\uC158 \uB300\uC0C1\uC774 \uC544\uB2D9\uB2C8\uB2E4 \u2014 \uC911\uB2E8(\uC6D0\uBCF8 \uBCF4\uC874)."));
4797
+ process.exitCode = 1;
4798
+ return;
4799
+ }
4800
+ const learnings = readLearningsRaw(cwd);
4801
+ const hadFile = raw.kind === "parsed";
4802
+ if (raw.kind === "missing" && !learnings) {
4803
+ console.log(chalk23.yellow(" \u2139\uFE0F \uB9C8\uC774\uADF8\uB808\uC774\uC158\uD560 v1 memory.json / learnings.md \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uBCC0\uACBD \uC5C6\uC74C."));
4804
+ return;
4805
+ }
4806
+ const v2 = migrateMemory(raw.kind === "parsed" ? raw.value : null, learnings);
4807
+ writeMemory(cwd, v2);
4808
+ const backupNote = hadFile ? " (.v1.bak \uC6D0\uBCF8 \uC601\uAD6C \uBC31\uC5C5)" : " (\uC2E0\uADDC \uC0DD\uC131 \u2014 \uC6D0\uBCF8 \uC5C6\uC74C, \uBC31\uC5C5 \uC5C6\uC74C)";
4809
+ console.log(chalk23.green(`
4810
+ \u2705 memory.json \u2192 v2 \uB9C8\uC774\uADF8\uB808\uC774\uC158 \uC644\uB8CC${backupNote}`));
4811
+ console.log(
4812
+ chalk23.dim(
4813
+ ` decisions ${v2.decisions.length} \xB7 failures ${v2.failures.length} \xB7 successes ${v2.successes.length}` + (learnings ? " (learnings.md \uAD50\uD6C8 \uD761\uC218 \u2014 \uC774\uD6C4 vhk learn \uC740 memory \uC5D0 \uAE30\uB85D)" : "")
4814
+ )
4815
+ );
4816
+ }
4817
+ function activeMemoryLines(mem, limit = 5) {
4818
+ const lines = [];
4819
+ const fmt = (e) => {
4820
+ const f = e;
4821
+ const base = e.content || (f.lesson ? `\u{1F4A1} ${f.lesson}` : e.id);
4822
+ return e.content && f.lesson ? `${base} \u2014 \u{1F4A1} ${f.lesson}` : base;
4823
+ };
4824
+ const section = (label, list) => {
4825
+ const act = list.filter(isActive);
4826
+ if (act.length === 0) return;
4827
+ lines.push(`**${label}** (${act.length})`);
4828
+ for (const e of act.slice(-limit)) lines.push(`- ${fmt(e)}`);
4829
+ if (act.length > limit) lines.push(`- \u2026 \uC678 ${act.length - limit}\uAC1C`);
4830
+ lines.push("");
4831
+ };
4832
+ section("\uACB0\uC815 (decisions)", mem.decisions);
4833
+ section("\uC2E4\uD328\xB7\uAD50\uD6C8 (failures)", mem.failures);
4834
+ section("\uC131\uACF5 (successes)", mem.successes);
4835
+ const pats = mem.patterns.length;
4836
+ if (pats > 0) lines.push(`**\uD328\uD134 \uD6C4\uBCF4 (patterns)**: ${pats}\uAC1C \u2014 \`vhk pattern\``, "");
4837
+ return lines;
4838
+ }
4839
+ function recordLesson(cwd, lesson, goalId) {
4840
+ const loaded = loadForMutation(cwd);
4841
+ if (!loaded.ok) return null;
4842
+ const mem = loaded.mem;
4843
+ const tag = goalId !== void 0 ? `goal-${goalId}` : "no-goal";
4844
+ const entry = {
4845
+ id: nextId("failure", mem),
4846
+ content: "",
4847
+ tags: [tag],
4848
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
4849
+ status: "active",
4850
+ lesson: lesson.trim()
4851
+ };
4852
+ mem.failures.push(entry);
4853
+ writeMemory(cwd, mem);
4854
+ return entry;
4855
+ }
4856
+
4857
+ // src/commands/context.ts
4446
4858
  var CONTEXT_PATH = ".vhk/context.md";
4447
4859
  var IGNORE_DIRS = /* @__PURE__ */ new Set([
4448
4860
  "node_modules",
@@ -4467,7 +4879,7 @@ function buildTree(dir, prefix = "", maxDepth = 3, depth = 0) {
4467
4879
  filtered.forEach((entry, index) => {
4468
4880
  const isLast = index === filtered.length - 1;
4469
4881
  const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
4470
- const fullPath = join7(dir, entry);
4882
+ const fullPath = join8(dir, entry);
4471
4883
  const stat = statSync2(fullPath);
4472
4884
  const isDir = stat.isDirectory();
4473
4885
  lines.push(`${prefix}${connector}${entry}${isDir ? "/" : ""}`);
@@ -4499,8 +4911,8 @@ function extractTechStack() {
4499
4911
  else if (all.jest) stack["\uD14C\uC2A4\uD2B8"] = "jest";
4500
4912
  if (all.commander) stack["CLI"] = "commander";
4501
4913
  if (all.inquirer) stack["\uC778\uD130\uB799\uD2F0\uBE0C"] = "inquirer";
4502
- if (existsSync11("pnpm-lock.yaml")) stack["\uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800"] = "pnpm";
4503
- else if (existsSync11("yarn.lock")) stack["\uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800"] = "yarn";
4914
+ if (existsSync12("pnpm-lock.yaml")) stack["\uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800"] = "pnpm";
4915
+ else if (existsSync12("yarn.lock")) stack["\uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800"] = "yarn";
4504
4916
  else stack["\uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800"] = "npm";
4505
4917
  if (pkg.name) stack["\uD328\uD0A4\uC9C0 \uC774\uB984"] = pkg.name;
4506
4918
  if (pkg.version) stack["\uBC84\uC804"] = pkg.version;
@@ -4543,8 +4955,8 @@ function getVhkCommands() {
4543
4955
  }
4544
4956
  async function context(opts = {}) {
4545
4957
  const compact = opts.compact === true;
4546
- console.log(chalk23.bold("\n\u{1F9E0} " + t("context.title")));
4547
- console.log(chalk23.gray("\u2500".repeat(40)));
4958
+ console.log(chalk24.bold("\n\u{1F9E0} " + t("context.title")));
4959
+ console.log(chalk24.gray("\u2500".repeat(40)));
4548
4960
  const stack = extractTechStack();
4549
4961
  const tree = buildTree(".", "", compact ? 2 : 3).join("\n");
4550
4962
  const commands = getVhkCommands();
@@ -4579,27 +4991,14 @@ async function context(opts = {}) {
4579
4991
  }
4580
4992
  lines.push("");
4581
4993
  }
4582
- if (existsSync11(".vhk/memory.json")) {
4583
- try {
4584
- const memories = readJsonFile(
4585
- ".vhk/memory.json"
4586
- );
4587
- if (Array.isArray(memories) && memories.length > 0) {
4588
- const recentMemories = memories.slice(-5);
4589
- lines.push("## \uC800\uC7A5\uB41C \uACB0\uC815\uC0AC\uD56D");
4590
- lines.push("");
4591
- if (memories.length > recentMemories.length) {
4592
- lines.push(`_\uCD5C\uADFC ${recentMemories.length}\uAC1C\uB9CC \uD45C\uC2DC (\uC804\uCCB4 ${memories.length}\uAC1C)_`);
4593
- lines.push("");
4594
- }
4595
- for (const m of recentMemories) {
4596
- const date = new Date(m.addedAt).toLocaleDateString("ko-KR");
4597
- lines.push(`- ${m.content} _(${date})_`);
4598
- }
4599
- lines.push("");
4600
- }
4601
- } catch {
4994
+ try {
4995
+ const memLines = activeMemoryLines(readMemory(process.cwd()));
4996
+ if (memLines.length > 0) {
4997
+ lines.push("## \uC800\uC7A5\uB41C \uAE30\uC5B5 (memory v2)");
4998
+ lines.push("");
4999
+ lines.push(...memLines);
4602
5000
  }
5001
+ } catch {
4603
5002
  }
4604
5003
  const goals = listGoals("goals");
4605
5004
  const activeId = selectActiveId(goals);
@@ -4616,13 +5015,6 @@ async function context(opts = {}) {
4616
5015
  lines.push("");
4617
5016
  }
4618
5017
  }
4619
- const recent = getRecentLearnings(3);
4620
- if (recent.length > 0) {
4621
- lines.push("## Recent Learnings");
4622
- lines.push("");
4623
- for (const r of recent) lines.push(r);
4624
- lines.push("");
4625
- }
4626
5018
  const activeBlockers = getActiveBlockers(3);
4627
5019
  if (activeBlockers.length > 0) {
4628
5020
  lines.push("## Active Blockers");
@@ -4657,12 +5049,12 @@ async function context(opts = {}) {
4657
5049
  } catch {
4658
5050
  }
4659
5051
  lines.push("");
4660
- mkdirSync7(".vhk", { recursive: true });
4661
- writeFileSync7(CONTEXT_PATH, lines.join("\n"), "utf-8");
4662
- console.log(chalk23.green(`
5052
+ mkdirSync8(".vhk", { recursive: true });
5053
+ writeFileSync8(CONTEXT_PATH, lines.join("\n"), "utf-8");
5054
+ console.log(chalk24.green(`
4663
5055
  \u2705 ${CONTEXT_PATH} \uC0DD\uC131 \uC644\uB8CC!`));
4664
- console.log(chalk23.gray(` \uAE30\uC220 \uC2A4\uD0DD ${Object.keys(stack).length}\uAC1C \uAC10\uC9C0`));
4665
- console.log(chalk23.gray(" AI \uC5B4\uC2DC\uC2A4\uD134\uD2B8\uC5D0\uAC8C \uC774 \uD30C\uC77C\uC744 \uCC38\uC870\uD558\uAC8C \uD558\uC138\uC694."));
5056
+ console.log(chalk24.gray(` \uAE30\uC220 \uC2A4\uD0DD ${Object.keys(stack).length}\uAC1C \uAC10\uC9C0`));
5057
+ console.log(chalk24.gray(" AI \uC5B4\uC2DC\uC2A4\uD134\uD2B8\uC5D0\uAC8C \uC774 \uD30C\uC77C\uC744 \uCC38\uC870\uD558\uAC8C \uD558\uC138\uC694."));
4666
5058
  printNextStep({
4667
5059
  message: "\uCEE8\uD14D\uC2A4\uD2B8 \uD30C\uC77C \uC0DD\uC131 \uC644\uB8CC!",
4668
5060
  command: "vhk context-show",
@@ -4670,110 +5062,33 @@ async function context(opts = {}) {
4670
5062
  });
4671
5063
  }
4672
5064
  async function contextShow() {
4673
- console.log(chalk23.bold("\n\u{1F4C4} " + t("context.showTitle")));
4674
- console.log(chalk23.gray("\u2500".repeat(40)));
4675
- if (!existsSync11(CONTEXT_PATH)) {
4676
- console.log(chalk23.yellow("\n\u26A0\uFE0F \uCEE8\uD14D\uC2A4\uD2B8 \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."));
4677
- console.log(chalk23.gray(" vhk context\uB97C \uBA3C\uC800 \uC2E4\uD589\uD558\uC138\uC694."));
4678
- return;
4679
- }
4680
- const content = readFileSync4(CONTEXT_PATH, "utf-8");
4681
- console.log("\n" + content);
4682
- }
4683
-
4684
- // src/commands/memory.ts
4685
- import { existsSync as existsSync12, mkdirSync as mkdirSync8, writeFileSync as writeFileSync8 } from "fs";
4686
- import chalk24 from "chalk";
4687
- var MEMORY_PATH = ".vhk/memory.json";
4688
- function loadMemories() {
4689
- if (!existsSync12(MEMORY_PATH)) return [];
4690
- try {
4691
- const parsed = readJsonFile(MEMORY_PATH);
4692
- return Array.isArray(parsed) ? parsed : [];
4693
- } catch {
4694
- return [];
4695
- }
4696
- }
4697
- function saveMemories(memories) {
4698
- mkdirSync8(".vhk", { recursive: true });
4699
- writeFileSync8(MEMORY_PATH, JSON.stringify(memories, null, 2) + "\n", "utf-8");
4700
- }
4701
- async function memoryAdd(content, tags) {
4702
- console.log(chalk24.bold("\n\u{1F9E0} " + t("memory.addTitle")));
4703
- console.log(chalk24.gray("\u2500".repeat(40)));
4704
- if (!content) {
4705
- console.log(chalk24.red("\u274C \uAE30\uC5B5\uD560 \uB0B4\uC6A9\uC744 \uC785\uB825\uD574\uC8FC\uC138\uC694."));
4706
- console.log(chalk24.gray(' \uC608: vhk memory add "API\uB294 tRPC \uC0AC\uC6A9\uD558\uAE30\uB85C \uACB0\uC815"'));
4707
- process.exitCode = 1;
4708
- return;
4709
- }
4710
- const memories = loadMemories();
4711
- memories.push({
4712
- content,
4713
- addedAt: (/* @__PURE__ */ new Date()).toISOString(),
4714
- tags: tags && tags.length > 0 ? tags : []
4715
- });
4716
- saveMemories(memories);
4717
- console.log(chalk24.green(`
4718
- \u2705 \uAE30\uC5B5 \uC800\uC7A5\uB428 (#${memories.length})`));
4719
- console.log(chalk24.cyan(` \u{1F4DD} ${content}`));
4720
- printNextStep({
4721
- message: "\uAE30\uC5B5 \uC800\uC7A5 \uC644\uB8CC!",
4722
- command: "vhk memory list",
4723
- cursorHint: "\uAE30\uC5B5 \uBAA9\uB85D \uBCF4\uC5EC\uC918"
4724
- });
4725
- }
4726
- async function memoryList() {
4727
- console.log(chalk24.bold("\n\u{1F9E0} " + t("memory.listTitle")));
5065
+ console.log(chalk24.bold("\n\u{1F4C4} " + t("context.showTitle")));
4728
5066
  console.log(chalk24.gray("\u2500".repeat(40)));
4729
- const memories = loadMemories();
4730
- if (memories.length === 0) {
4731
- console.log(chalk24.yellow("\n\u{1F4ED} \uC800\uC7A5\uB41C \uAE30\uC5B5\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."));
4732
- console.log(chalk24.gray(' vhk memory add "\uB0B4\uC6A9"\uC73C\uB85C \uCD94\uAC00\uD558\uC138\uC694.'));
4733
- return;
4734
- }
4735
- console.log(chalk24.cyan(`
4736
- \uCD1D ${memories.length}\uAC1C\uC758 \uAE30\uC5B5:
4737
- `));
4738
- memories.forEach((m, index) => {
4739
- const date = new Date(m.addedAt).toLocaleDateString("ko-KR");
4740
- console.log(chalk24.white(` [${index + 1}] ${m.content}`));
4741
- if (m.tags && m.tags.length > 0) {
4742
- console.log(chalk24.blue(` \u{1F3F7}\uFE0F ${m.tags.join(", ")}`));
4743
- }
4744
- console.log(chalk24.gray(` \u{1F4C5} ${date}`));
4745
- console.log("");
4746
- });
4747
- }
4748
- async function memoryRemove(indexStr) {
4749
- const memories = loadMemories();
4750
- const idx = parseInt(indexStr, 10) - 1;
4751
- if (Number.isNaN(idx) || idx < 0 || idx >= memories.length) {
4752
- console.log(chalk24.red(`\u274C \uC720\uD6A8\uD558\uC9C0 \uC54A\uC740 \uBC88\uD638\uC785\uB2C8\uB2E4. (1~${memories.length || 0})`));
5067
+ if (!existsSync12(CONTEXT_PATH)) {
5068
+ console.log(chalk24.yellow("\n\u26A0\uFE0F \uCEE8\uD14D\uC2A4\uD2B8 \uD30C\uC77C\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."));
5069
+ console.log(chalk24.gray(" vhk context\uB97C \uBA3C\uC800 \uC2E4\uD589\uD558\uC138\uC694."));
4753
5070
  return;
4754
5071
  }
4755
- const removed = memories.splice(idx, 1)[0];
4756
- saveMemories(memories);
4757
- console.log(chalk24.green("\n\u2705 \uAE30\uC5B5 \uC0AD\uC81C\uB428:"));
4758
- console.log(chalk24.gray(` ${removed.content}`));
5072
+ const content = readFileSync5(CONTEXT_PATH, "utf-8");
5073
+ console.log("\n" + content);
4759
5074
  }
4760
5075
 
4761
5076
  // src/commands/brief.ts
4762
- import { existsSync as existsSync13, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9, readFileSync as readFileSync5 } from "fs";
5077
+ import { existsSync as existsSync13, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9, readFileSync as readFileSync6 } from "fs";
4763
5078
  import chalk25 from "chalk";
4764
5079
  var BRIEF_PATH = ".vhk/brief.md";
4765
5080
  function readProjectIdentity() {
4766
5081
  const out = {};
4767
5082
  try {
4768
5083
  if (existsSync13("RULES.md")) {
4769
- const r = readFileSync5("RULES.md", "utf-8");
5084
+ const r = readFileSync6("RULES.md", "utf-8");
4770
5085
  const m = r.split("\n")[0].match(/^#\s*(.+?)(?:\s*—.*)?$/);
4771
5086
  if (m) out.name = m[1].trim();
4772
5087
  const d = r.match(/한 줄 설명:\s*(.+)/);
4773
5088
  if (d) out.description = d[1].trim();
4774
5089
  }
4775
5090
  if (!out.name && existsSync13("CLAUDE.md")) {
4776
- const m = readFileSync5("CLAUDE.md", "utf-8").match(/#\s*기록 규칙\s*\((.+?)\)/);
5091
+ const m = readFileSync6("CLAUDE.md", "utf-8").match(/#\s*기록 규칙\s*\((.+?)\)/);
4777
5092
  if (m) out.name = m[1].trim();
4778
5093
  }
4779
5094
  } catch {
@@ -4823,22 +5138,14 @@ async function brief() {
4823
5138
  `- **\uBBF8\uCEE4\uBC0B \uBCC0\uACBD**: ${uncommitted ? `${uncommitted.split("\n").length}\uAC1C \uD30C\uC77C` : "\uC5C6\uC74C \u2705"}`
4824
5139
  );
4825
5140
  lines.push("");
4826
- if (existsSync13(".vhk/memory.json")) {
4827
- try {
4828
- const memories = readJsonFile(".vhk/memory.json");
4829
- if (Array.isArray(memories) && memories.length > 0) {
4830
- lines.push(`## \uC800\uC7A5\uB41C \uACB0\uC815\uC0AC\uD56D (${memories.length}\uAC1C)`);
4831
- lines.push("");
4832
- for (const m of memories.slice(-5)) {
4833
- lines.push(`- ${m.content}`);
4834
- }
4835
- if (memories.length > 5) {
4836
- lines.push(`- ... \uC678 ${memories.length - 5}\uAC1C`);
4837
- }
4838
- lines.push("");
4839
- }
4840
- } catch {
5141
+ try {
5142
+ const memLines = activeMemoryLines(readMemory(process.cwd()));
5143
+ if (memLines.length > 0) {
5144
+ lines.push("## \uC800\uC7A5\uB41C \uAE30\uC5B5 (memory v2)");
5145
+ lines.push("");
5146
+ lines.push(...memLines);
4841
5147
  }
5148
+ } catch {
4842
5149
  }
4843
5150
  if (existsSync13(".vhk/refs.json")) {
4844
5151
  try {
@@ -4885,7 +5192,7 @@ import chalk26 from "chalk";
4885
5192
  import inquirer11 from "inquirer";
4886
5193
  import { simpleGit as simpleGit2 } from "simple-git";
4887
5194
  import { existsSync as existsSync14 } from "fs";
4888
- import { join as join8 } from "path";
5195
+ import { join as join9 } from "path";
4889
5196
  var VHK_FOOTPRINT_FILES = [
4890
5197
  "CLAUDE.md",
4891
5198
  ".cursorrules",
@@ -4894,7 +5201,7 @@ var VHK_FOOTPRINT_FILES = [
4894
5201
  "docs/PRD.md"
4895
5202
  ];
4896
5203
  function detectExistingFootprint(cwd) {
4897
- return VHK_FOOTPRINT_FILES.filter((rel) => existsSync14(join8(cwd, rel)));
5204
+ return VHK_FOOTPRINT_FILES.filter((rel) => existsSync14(join9(cwd, rel)));
4898
5205
  }
4899
5206
  async function runGitInit(cwd) {
4900
5207
  try {
@@ -5300,7 +5607,7 @@ import chalk29 from "chalk";
5300
5607
 
5301
5608
  // src/lib/config.ts
5302
5609
  import { existsSync as existsSync15, mkdirSync as mkdirSync10, writeFileSync as writeFileSync10 } from "fs";
5303
- import { join as join9 } from "path";
5610
+ import { join as join10 } from "path";
5304
5611
 
5305
5612
  // src/lib/safety-mode.ts
5306
5613
  var SAFETY_MODES = ["lite", "standard", "strict"];
@@ -5316,10 +5623,10 @@ function isSafetyMode(value) {
5316
5623
 
5317
5624
  // src/lib/config.ts
5318
5625
  var CONFIG_DIR = ".vhk";
5319
- var CONFIG_PATH = join9(CONFIG_DIR, "config.json");
5626
+ var CONFIG_PATH = join10(CONFIG_DIR, "config.json");
5320
5627
  var DEFAULT_CONFIG = { safetyMode: DEFAULT_SAFETY_MODE };
5321
5628
  function readConfig(rootDir = process.cwd()) {
5322
- const full = join9(rootDir, CONFIG_PATH);
5629
+ const full = join10(rootDir, CONFIG_PATH);
5323
5630
  if (!existsSync15(full)) return { ...DEFAULT_CONFIG };
5324
5631
  try {
5325
5632
  const raw = readJsonFile(full);
@@ -5331,8 +5638,8 @@ function readConfig(rootDir = process.cwd()) {
5331
5638
  }
5332
5639
  }
5333
5640
  function writeConfig(config, rootDir = process.cwd()) {
5334
- mkdirSync10(join9(rootDir, CONFIG_DIR), { recursive: true });
5335
- writeFileSync10(join9(rootDir, CONFIG_PATH), JSON.stringify(config, null, 2) + "\n", "utf-8");
5641
+ mkdirSync10(join10(rootDir, CONFIG_DIR), { recursive: true });
5642
+ writeFileSync10(join10(rootDir, CONFIG_PATH), JSON.stringify(config, null, 2) + "\n", "utf-8");
5336
5643
  }
5337
5644
 
5338
5645
  // src/commands/mode.ts
@@ -5372,7 +5679,7 @@ async function mode(target) {
5372
5679
  // src/commands/verify.ts
5373
5680
  import { execFileSync as execFileSync4 } from "child_process";
5374
5681
  import { existsSync as existsSync16, mkdirSync as mkdirSync11, writeFileSync as writeFileSync11 } from "fs";
5375
- import { join as join10 } from "path";
5682
+ import { join as join11 } from "path";
5376
5683
  import chalk30 from "chalk";
5377
5684
 
5378
5685
  // src/commands/verify-report.ts
@@ -5481,13 +5788,13 @@ ${actions}
5481
5788
 
5482
5789
  // src/commands/verify.ts
5483
5790
  var REPORT_SCHEMA_VERSION = 1;
5484
- var REPORT_DIR_REL = join10(".vhk", "reports");
5485
- var REPORT_PATH_REL = join10(REPORT_DIR_REL, "latest.json");
5486
- var REPORT_HTML_PATH_REL = join10(REPORT_DIR_REL, "latest.html");
5791
+ var REPORT_DIR_REL = join11(".vhk", "reports");
5792
+ var REPORT_PATH_REL = join11(REPORT_DIR_REL, "latest.json");
5793
+ var REPORT_HTML_PATH_REL = join11(REPORT_DIR_REL, "latest.html");
5487
5794
  var SHIM = /* @__PURE__ */ new Set(["pnpm", "npm", "npx", "yarn"]);
5488
5795
  function detectPm(cwd) {
5489
- if (existsSync16(join10(cwd, "pnpm-lock.yaml"))) return "pnpm";
5490
- if (existsSync16(join10(cwd, "yarn.lock"))) return "yarn";
5796
+ if (existsSync16(join11(cwd, "pnpm-lock.yaml"))) return "pnpm";
5797
+ if (existsSync16(join11(cwd, "yarn.lock"))) return "yarn";
5491
5798
  return "npm";
5492
5799
  }
5493
5800
  function execGate(cmd, args, cwd) {
@@ -5530,7 +5837,7 @@ function runScriptGate(id, label, cwd, pm, argvFor) {
5530
5837
  };
5531
5838
  }
5532
5839
  function readPackageScripts(cwd) {
5533
- const pkgPath = join10(cwd, "package.json");
5840
+ const pkgPath = join11(cwd, "package.json");
5534
5841
  if (!existsSync16(pkgPath)) return {};
5535
5842
  try {
5536
5843
  const pkg = readJsonFile(pkgPath);
@@ -5546,7 +5853,7 @@ function runGates(cwd) {
5546
5853
  gates.push(
5547
5854
  runScriptGate("typecheck", "tsc --noEmit", cwd, pm, () => {
5548
5855
  if (scripts.typecheck) return ["run", "typecheck"];
5549
- if (existsSync16(join10(cwd, "tsconfig.json"))) return pm === "npm" ? ["exec", "--", "tsc", "--noEmit"] : ["exec", "tsc", "--noEmit"];
5856
+ if (existsSync16(join11(cwd, "tsconfig.json"))) return pm === "npm" ? ["exec", "--", "tsc", "--noEmit"] : ["exec", "tsc", "--noEmit"];
5550
5857
  return null;
5551
5858
  })
5552
5859
  );
@@ -5625,9 +5932,9 @@ function buildReport(gates, generatedAt, date) {
5625
5932
  function verifyEvidence(cwd = process.cwd()) {
5626
5933
  const gates = runGates(cwd);
5627
5934
  const report = buildReport(gates, (/* @__PURE__ */ new Date()).toISOString(), localDate());
5628
- const dir = join10(cwd, REPORT_DIR_REL);
5935
+ const dir = join11(cwd, REPORT_DIR_REL);
5629
5936
  mkdirSync11(dir, { recursive: true });
5630
- const path14 = join10(cwd, REPORT_PATH_REL);
5937
+ const path14 = join11(cwd, REPORT_PATH_REL);
5631
5938
  writeFileSync11(path14, JSON.stringify(report, null, 2) + "\n", "utf-8");
5632
5939
  try {
5633
5940
  ensureVhkIgnored(cwd, "reports/");
@@ -5641,7 +5948,7 @@ var STATUS_BADGE = {
5641
5948
  FAIL: chalk30.red.bold("FAIL")
5642
5949
  };
5643
5950
  async function renderVerifyReport(cwd, opts) {
5644
- const jsonPath = join10(cwd, REPORT_PATH_REL);
5951
+ const jsonPath = join11(cwd, REPORT_PATH_REL);
5645
5952
  let report;
5646
5953
  if (existsSync16(jsonPath)) {
5647
5954
  try {
@@ -5655,9 +5962,9 @@ async function renderVerifyReport(cwd, opts) {
5655
5962
  report = verifyEvidence(cwd).report;
5656
5963
  }
5657
5964
  const html = renderReportHtml(report);
5658
- const htmlPath = join10(cwd, REPORT_HTML_PATH_REL);
5965
+ const htmlPath = join11(cwd, REPORT_HTML_PATH_REL);
5659
5966
  try {
5660
- mkdirSync11(join10(cwd, REPORT_DIR_REL), { recursive: true });
5967
+ mkdirSync11(join11(cwd, REPORT_DIR_REL), { recursive: true });
5661
5968
  writeFileSync11(htmlPath, html, "utf-8");
5662
5969
  } catch (e) {
5663
5970
  console.error(
@@ -5741,7 +6048,7 @@ async function verify(opts = {}) {
5741
6048
 
5742
6049
  // src/commands/review.ts
5743
6050
  import { existsSync as existsSync17, writeFileSync as writeFileSync12 } from "fs";
5744
- import { join as join11 } from "path";
6051
+ import { join as join12 } from "path";
5745
6052
  import chalk31 from "chalk";
5746
6053
  var GOALS_DIR2 = "goals";
5747
6054
  var COVERAGE_MIN = 0.5;
@@ -5899,7 +6206,7 @@ async function review(opts = {}) {
5899
6206
  if (opts.id === void 0 && goalStatus === "NOT_STARTED") {
5900
6207
  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.`));
5901
6208
  }
5902
- const jsonPath = join11(cwd, REPORT_PATH_REL);
6209
+ const jsonPath = join12(cwd, REPORT_PATH_REL);
5903
6210
  if (!existsSync17(jsonPath)) {
5904
6211
  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).`));
5905
6212
  printNextStep({
@@ -6009,6 +6316,183 @@ ${result.disclaimer}`));
6009
6316
  }
6010
6317
  }
6011
6318
 
6319
+ // src/commands/mission.ts
6320
+ import { existsSync as existsSync18, mkdirSync as mkdirSync12, writeFileSync as writeFileSync13, rmSync as rmSync4 } from "fs";
6321
+ import { join as join13 } from "path";
6322
+ import chalk32 from "chalk";
6323
+ import inquirer12 from "inquirer";
6324
+ import { simpleGit as simpleGit3 } from "simple-git";
6325
+ var MISSION_PATH_REL = join13(".vhk", "mission.json");
6326
+ var MISSION_SCHEMA_VERSION = 1;
6327
+ 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).";
6328
+ function globToRegExp(glob) {
6329
+ let re = "";
6330
+ for (let i = 0; i < glob.length; i++) {
6331
+ const c = glob[i];
6332
+ if (c === "*") {
6333
+ if (glob[i + 1] === "*") {
6334
+ re += ".*";
6335
+ i++;
6336
+ if (glob[i + 1] === "/") i++;
6337
+ } else {
6338
+ re += "[^/]*";
6339
+ }
6340
+ } else if (c === "?") {
6341
+ re += "[^/]";
6342
+ } else if (".+^${}()|[]\\".includes(c)) {
6343
+ re += "\\" + c;
6344
+ } else {
6345
+ re += c;
6346
+ }
6347
+ }
6348
+ return new RegExp("^" + re + "$");
6349
+ }
6350
+ function matchesAny(file, globs) {
6351
+ const norm = file.replace(/\\/g, "/");
6352
+ for (const g of globs) {
6353
+ if (globToRegExp(g).test(norm)) return g;
6354
+ }
6355
+ return null;
6356
+ }
6357
+ function checkMission(changedFiles, mission) {
6358
+ const violations = [];
6359
+ const warnings = [];
6360
+ for (const file of changedFiles) {
6361
+ const forbiddenHit = matchesAny(file, mission.forbidden);
6362
+ if (forbiddenHit) {
6363
+ violations.push({ file, pattern: forbiddenHit });
6364
+ continue;
6365
+ }
6366
+ if (mission.scope.length > 0 && !matchesAny(file, mission.scope)) {
6367
+ warnings.push({ file });
6368
+ }
6369
+ }
6370
+ return { violations, warnings, disclaimer: MISSION_DISCLAIMER };
6371
+ }
6372
+ function readMission(cwd = process.cwd()) {
6373
+ const p = join13(cwd, MISSION_PATH_REL);
6374
+ if (!existsSync18(p)) return null;
6375
+ try {
6376
+ const m = readJsonFile(p);
6377
+ if (m && typeof m.objective === "string") return m;
6378
+ return null;
6379
+ } catch {
6380
+ return null;
6381
+ }
6382
+ }
6383
+ function writeMission(cwd, mission) {
6384
+ mkdirSync12(join13(cwd, ".vhk"), { recursive: true });
6385
+ writeFileSync13(join13(cwd, MISSION_PATH_REL), JSON.stringify(mission, null, 2) + "\n", "utf-8");
6386
+ }
6387
+ async function collectChangedFiles(cwd) {
6388
+ const status2 = await simpleGit3(cwd).status();
6389
+ const set = /* @__PURE__ */ new Set();
6390
+ for (const f of status2.files) if (f.path) set.add(f.path.replace(/\\/g, "/"));
6391
+ return [...set];
6392
+ }
6393
+ async function missionSet(opts = {}) {
6394
+ if (!ensureNotHardStopped("mission set")) return;
6395
+ const cwd = process.cwd();
6396
+ const existing = readMission(cwd);
6397
+ let objective = opts.objective ?? existing?.objective ?? "";
6398
+ if (!objective) {
6399
+ if (isInteractive(opts)) {
6400
+ const ans = await inquirer12.prompt([
6401
+ { type: "input", name: "obj", message: "\uBBF8\uC158 \uBAA9\uD45C(objective)\uB294?" }
6402
+ ]);
6403
+ objective = ans.obj.trim();
6404
+ }
6405
+ if (!objective) {
6406
+ console.error(chalk32.red(' \u274C objective \uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. --objective "..." \uB85C \uC9C0\uC815\uD558\uC138\uC694(\uBE44\uB300\uD654\uD615).'));
6407
+ process.exitCode = 1;
6408
+ return;
6409
+ }
6410
+ }
6411
+ const scope = opts.clearScope ? [] : opts.scope ?? existing?.scope ?? [];
6412
+ const forbidden = opts.clearForbidden ? [] : opts.forbidden ?? existing?.forbidden ?? [];
6413
+ const now = (/* @__PURE__ */ new Date()).toISOString();
6414
+ const mission = {
6415
+ schemaVersion: MISSION_SCHEMA_VERSION,
6416
+ objective,
6417
+ scope,
6418
+ forbidden,
6419
+ createdAt: existing?.createdAt ?? now,
6420
+ updatedAt: now
6421
+ };
6422
+ try {
6423
+ writeMission(cwd, mission);
6424
+ } catch (e) {
6425
+ console.error(chalk32.red(` \u274C mission.json \uAE30\uB85D \uC2E4\uD328: ${e instanceof Error ? e.message : String(e)}`));
6426
+ process.exitCode = 1;
6427
+ return;
6428
+ }
6429
+ console.log(chalk32.bold("\n\u{1F3AF} \uBBF8\uC158 \uACC4\uC57D \uC800\uC7A5"));
6430
+ console.log(chalk32.dim(` \u{1F4C4} ${MISSION_PATH_REL}`));
6431
+ console.log(` objective: ${mission.objective}`);
6432
+ console.log(` scope: ${mission.scope.length ? mission.scope.join(", ") : "(\uC81C\uD55C \uC5C6\uC74C)"}`);
6433
+ console.log(` forbidden: ${mission.forbidden.length ? mission.forbidden.join(", ") : "(\uC5C6\uC74C)"}`);
6434
+ printNextStep({ message: "\uBCC0\uACBD\uC774 \uACC4\uC57D \uC548\uC778\uC9C0 \uAC80\uC99D\uD558\uB824\uBA74:", command: "vhk mission check", cursorHint: "\uBBF8\uC158 \uAC80\uC99D\uD574\uC918" });
6435
+ }
6436
+ async function missionShow() {
6437
+ const cwd = process.cwd();
6438
+ const mission = readMission(cwd);
6439
+ if (!mission) {
6440
+ console.error(chalk32.yellow(" \u26A0\uFE0F \uBBF8\uC158 \uACC4\uC57D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 (.vhk/mission.json)."));
6441
+ printNextStep({ message: "\uBA3C\uC800 \uBBF8\uC158\uC744 \uC120\uC5B8\uD558\uC138\uC694:", command: 'vhk mission set --objective "..."', cursorHint: "\uBBF8\uC158 \uC815\uD574\uC918" });
6442
+ process.exitCode = 1;
6443
+ return;
6444
+ }
6445
+ console.log(chalk32.bold("\n\u{1F3AF} \uD604\uC7AC \uBBF8\uC158 \uACC4\uC57D"));
6446
+ console.log(` objective: ${mission.objective}`);
6447
+ console.log(` scope: ${mission.scope.length ? mission.scope.join(", ") : "(\uC81C\uD55C \uC5C6\uC74C)"}`);
6448
+ console.log(` forbidden: ${mission.forbidden.length ? mission.forbidden.join(", ") : "(\uC5C6\uC74C)"}`);
6449
+ console.log(chalk32.dim(` \uC0DD\uC131 ${mission.createdAt} \xB7 \uAC31\uC2E0 ${mission.updatedAt}`));
6450
+ }
6451
+ async function missionCheck() {
6452
+ const cwd = process.cwd();
6453
+ const mission = readMission(cwd);
6454
+ if (!mission) {
6455
+ 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."));
6456
+ process.exitCode = 1;
6457
+ return;
6458
+ }
6459
+ const changed = await collectChangedFiles(cwd);
6460
+ const result = checkMission(changed, mission);
6461
+ console.log(chalk32.bold("\n\u{1F3AF} \uBBF8\uC158 \uACC4\uC57D \uAC80\uC99D (mission check)"));
6462
+ console.log(chalk32.dim(` objective: ${mission.objective} \xB7 \uBCC0\uACBD \uD30C\uC77C ${changed.length}\uAC1C`));
6463
+ if (result.violations.length > 0) {
6464
+ console.log(chalk32.red.bold(`
6465
+ \u{1F6AB} forbidden \uC704\uBC18 ${result.violations.length}\uAC74`));
6466
+ for (const v of result.violations) console.log(chalk32.red(` \u2717 ${v.file} (\uAE08\uC9C0: ${v.pattern})`));
6467
+ }
6468
+ if (result.warnings.length > 0) {
6469
+ console.log(chalk32.yellow.bold(`
6470
+ \u26A0\uFE0F scope \uBC16 \uBCC0\uACBD ${result.warnings.length}\uAC74 (\uACBD\uACE0)`));
6471
+ for (const w of result.warnings) console.log(chalk32.yellow(` ? ${w.file}`));
6472
+ }
6473
+ if (result.violations.length === 0 && result.warnings.length === 0) {
6474
+ console.log(chalk32.green("\n \u2713 \uBCC0\uACBD\uC774 \uACC4\uC57D(scope/forbidden) \uC548\uC785\uB2C8\uB2E4."));
6475
+ }
6476
+ console.log(chalk32.yellow(`
6477
+ ${result.disclaimer}`));
6478
+ process.exitCode = result.violations.length > 0 ? 1 : 0;
6479
+ }
6480
+ async function missionClear() {
6481
+ const cwd = process.cwd();
6482
+ const p = join13(cwd, MISSION_PATH_REL);
6483
+ if (!existsSync18(p)) {
6484
+ console.log(chalk32.dim(" \uBBF8\uC158 \uACC4\uC57D\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uC9C0\uC6B8 \uAC83 \uC5C6\uC74C."));
6485
+ return;
6486
+ }
6487
+ try {
6488
+ rmSync4(p);
6489
+ console.log(chalk32.green(" \u2705 \uBBF8\uC158 \uACC4\uC57D \uC0AD\uC81C\uB428 (.vhk/mission.json)."));
6490
+ } catch (e) {
6491
+ console.error(chalk32.red(` \u274C \uC0AD\uC81C \uC2E4\uD328: ${e instanceof Error ? e.message : String(e)}`));
6492
+ process.exitCode = 1;
6493
+ }
6494
+ }
6495
+
6012
6496
  // src/lib/risk-policy.ts
6013
6497
  var HIGH_RISK_ACTIONS = [
6014
6498
  "undo",
@@ -6150,6 +6634,7 @@ async function dispatchNlpRoute(route, input) {
6150
6634
  case "context-show":
6151
6635
  return contextShow();
6152
6636
  case "memory":
6637
+ if (route.args?.[0] === "migrate") return memoryMigrate();
6153
6638
  return memoryList();
6154
6639
  case "brief":
6155
6640
  return brief();
@@ -6176,6 +6661,8 @@ async function dispatchNlpRoute(route, input) {
6176
6661
  return verify();
6177
6662
  case "review":
6178
6663
  return review();
6664
+ case "mission":
6665
+ return missionShow();
6179
6666
  }
6180
6667
  }
6181
6668
  var STATE_CHANGING_COMMANDS = /* @__PURE__ */ new Set([
@@ -6189,23 +6676,23 @@ function requiresConfirmation(route) {
6189
6676
  async function runNaturalLanguageRoute(input) {
6190
6677
  const route = routeNaturalLanguage(input);
6191
6678
  if (!route) {
6192
- console.log(chalk32.yellow(`
6679
+ console.log(chalk33.yellow(`
6193
6680
  \u2753 "${input}" \u2014 ${ko.nlp.notMatched}
6194
6681
  `));
6195
6682
  return;
6196
6683
  }
6197
6684
  console.log("");
6198
- console.log(chalk32.cyan(` \u{1F4AC} "${input}"`));
6199
- console.log(chalk32.cyan(` \u2192 ${route.explanation}`));
6685
+ console.log(chalk33.cyan(` \u{1F4AC} "${input}"`));
6686
+ console.log(chalk33.cyan(` \u2192 ${route.explanation}`));
6200
6687
  if (requiresConfirmation(route)) {
6201
- const { confirm } = await inquirer12.prompt([{
6688
+ const { confirm } = await inquirer13.prompt([{
6202
6689
  type: "confirm",
6203
6690
  name: "confirm",
6204
6691
  message: `${route.explanation} \u2014 ${ko.nlp.matched}`,
6205
6692
  default: true
6206
6693
  }]);
6207
6694
  if (!confirm) {
6208
- console.log(chalk32.dim(` ${ko.nlp.menuHint}`));
6695
+ console.log(chalk33.dim(` ${ko.nlp.menuHint}`));
6209
6696
  return;
6210
6697
  }
6211
6698
  }
@@ -6214,7 +6701,7 @@ async function runNaturalLanguageRoute(input) {
6214
6701
  if (riskAction) {
6215
6702
  await runGuarded(
6216
6703
  riskAction,
6217
- { channel: "nl", approved: false, log: (m) => console.log(chalk32.yellow(` ${m}`)) },
6704
+ { channel: "nl", approved: false, log: (m) => console.log(chalk33.yellow(` ${m}`)) },
6218
6705
  () => dispatchNlpRoute(route, input)
6219
6706
  );
6220
6707
  return;
@@ -6223,77 +6710,80 @@ async function runNaturalLanguageRoute(input) {
6223
6710
  }
6224
6711
 
6225
6712
  // src/commands/agent.ts
6226
- import chalk33 from "chalk";
6713
+ import chalk34 from "chalk";
6227
6714
  function activeGoalId() {
6228
6715
  const goals = listGoals("goals");
6229
6716
  const id = selectActiveId(goals);
6230
6717
  return id ?? void 0;
6231
6718
  }
6232
6719
  async function blocker(description) {
6233
- console.log(chalk33.bold(`
6720
+ console.log(chalk34.bold(`
6234
6721
  ${ko.agent.blockerTitle}
6235
6722
  `));
6236
6723
  if (!description || !description.trim()) {
6237
- console.log(chalk33.red(" \u274C \uBE14\uB85C\uCEE4 \uC124\uBA85\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694."));
6238
- console.log(chalk33.dim(' \uC608: vhk blocker "tsc \uC5D0\uB7EC \u2014 simple-git \uD0C0\uC785 \uD638\uD658"'));
6724
+ console.log(chalk34.red(" \u274C \uBE14\uB85C\uCEE4 \uC124\uBA85\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694."));
6725
+ console.log(chalk34.dim(' \uC608: vhk blocker "tsc \uC5D0\uB7EC \u2014 simple-git \uD0C0\uC785 \uD638\uD658"'));
6239
6726
  process.exitCode = 1;
6240
6727
  return;
6241
6728
  }
6242
6729
  const goalId = activeGoalId();
6243
6730
  const r = appendBlocker(description, goalId);
6244
- console.log(chalk33.green(` \u2705 blocker \uAE30\uB85D (\uD604\uC7AC \uD65C\uC131 ${r.count}\uAC74)`));
6731
+ console.log(chalk34.green(` \u2705 blocker \uAE30\uB85D (\uD604\uC7AC \uD65C\uC131 ${r.count}\uAC74)`));
6245
6732
  if (r.hardStopTripped) {
6246
- console.log(chalk33.red.bold(" \u{1F6D1} HARD_STOP \uC790\uB3D9 \uC0DD\uC131 \u2014 \uBAA8\uB4E0 \uC790\uB3D9\uD654 \uC911\uB2E8."));
6247
- console.log(chalk33.yellow(" \uC0AC\uB78C \uAC80\uD1A0 \uD6C4 `vhk resume --confirm` \uC73C\uB85C\uB9CC \uD574\uC81C."));
6733
+ console.log(chalk34.red.bold(" \u{1F6D1} HARD_STOP \uC790\uB3D9 \uC0DD\uC131 \u2014 \uBAA8\uB4E0 \uC790\uB3D9\uD654 \uC911\uB2E8."));
6734
+ console.log(chalk34.yellow(" \uC0AC\uB78C \uAC80\uD1A0 \uD6C4 `vhk resume --confirm` \uC73C\uB85C\uB9CC \uD574\uC81C."));
6248
6735
  process.exitCode = 2;
6249
6736
  }
6250
6737
  }
6251
6738
  async function learn(lesson) {
6252
- console.log(chalk33.bold(`
6739
+ console.log(chalk34.bold(`
6253
6740
  ${ko.agent.learnTitle}
6254
6741
  `));
6255
6742
  if (!lesson || !lesson.trim()) {
6256
- console.log(chalk33.red(" \u274C \uAD50\uD6C8 \uB0B4\uC6A9\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694."));
6257
- console.log(chalk33.dim(' \uC608: vhk learn "PowerShell \uC5D0\uC11C\uB294 ; \uC0AC\uC6A9 (&& \uBBF8\uC9C0\uC6D0)"'));
6743
+ console.log(chalk34.red(" \u274C \uAD50\uD6C8 \uB0B4\uC6A9\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694."));
6744
+ console.log(chalk34.dim(' \uC608: vhk learn "PowerShell \uC5D0\uC11C\uB294 ; \uC0AC\uC6A9 (&& \uBBF8\uC9C0\uC6D0)"'));
6258
6745
  process.exitCode = 1;
6259
6746
  return;
6260
6747
  }
6261
6748
  const goalId = activeGoalId();
6262
- appendLearning(lesson, goalId);
6263
- console.log(chalk33.green(" \u2705 learnings.md append."));
6264
- console.log(
6265
- chalk33.dim(" \uACB0\uC815\uC0AC\uD56D(decision)\uC740 `vhk memory add` \uB85C \uBCC4\uB3C4 \uAE30\uB85D \u2014 SoT \uBD84\uB9AC.")
6266
- );
6749
+ const entry = recordLesson(process.cwd(), lesson, goalId);
6750
+ if (!entry) {
6751
+ console.log(chalk34.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."));
6752
+ process.exitCode = 1;
6753
+ return;
6754
+ }
6755
+ console.log(chalk34.green(` \u2705 \uAD50\uD6C8 \uAE30\uB85D \u2192 memory failures.lesson (${entry.id})`));
6756
+ console.log(chalk34.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."));
6267
6757
  }
6268
6758
  async function resume(opts = {}) {
6269
- console.log(chalk33.bold(`
6759
+ console.log(chalk34.bold(`
6270
6760
  ${ko.agent.resumeTitle}
6271
6761
  `));
6272
6762
  if (!isHardStopActive()) {
6273
- console.log(chalk33.dim(" HARD_STOP \uD65C\uC131 \uC544\uB2D8 \u2014 \uD560 \uC77C \uC5C6\uC74C."));
6763
+ console.log(chalk34.dim(" HARD_STOP \uD65C\uC131 \uC544\uB2D8 \u2014 \uD560 \uC77C \uC5C6\uC74C."));
6274
6764
  return;
6275
6765
  }
6276
6766
  const reason = readHardStopReason();
6277
6767
  if (reason) {
6278
- console.log(chalk33.yellow(" \u{1F4CB} HARD_STOP \uC0AC\uC720:"));
6279
- console.log(chalk33.dim(` ${reason.split("\n").join("\n ")}`));
6768
+ console.log(chalk34.yellow(" \u{1F4CB} HARD_STOP \uC0AC\uC720:"));
6769
+ console.log(chalk34.dim(` ${reason.split("\n").join("\n ")}`));
6280
6770
  console.log("");
6281
6771
  }
6282
6772
  if (!opts.confirm) {
6283
6773
  console.log(
6284
- chalk33.red(
6774
+ chalk34.red(
6285
6775
  " \u274C --confirm \uD50C\uB798\uADF8 \uC5C6\uC774\uB294 \uD574\uC81C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 (\uC790\uB3D9 \uD638\uCD9C \uAE08\uC9C0)."
6286
6776
  )
6287
6777
  );
6288
- console.log(chalk33.yellow(" \uC0AC\uC720\uB97C \uD655\uC778\uD55C \uD6C4 \uB2E4\uC2DC: vhk resume --confirm"));
6778
+ console.log(chalk34.yellow(" \uC0AC\uC720\uB97C \uD655\uC778\uD55C \uD6C4 \uB2E4\uC2DC: vhk resume --confirm"));
6289
6779
  process.exitCode = 1;
6290
6780
  return;
6291
6781
  }
6292
6782
  const removed = clearHardStop();
6293
6783
  if (removed) {
6294
- console.log(chalk33.green(" \u2705 HARD_STOP \uD574\uC81C. \uC790\uB3D9\uD654 \uC7AC\uAC1C \uAC00\uB2A5."));
6784
+ console.log(chalk34.green(" \u2705 HARD_STOP \uD574\uC81C. \uC790\uB3D9\uD654 \uC7AC\uAC1C \uAC00\uB2A5."));
6295
6785
  } else {
6296
- console.log(chalk33.dim(" \uD30C\uC77C\uC774 \uC774\uBBF8 \uC5C6\uC74C \u2014 no-op."));
6786
+ console.log(chalk34.dim(" \uD30C\uC77C\uC774 \uC774\uBBF8 \uC5C6\uC74C \u2014 no-op."));
6297
6787
  }
6298
6788
  }
6299
6789
 
@@ -6306,7 +6796,7 @@ async function guardCli(action, approved, run) {
6306
6796
  channel: "cli",
6307
6797
  approved,
6308
6798
  confirm: async () => {
6309
- const { ok } = await inquirer13.prompt([{
6799
+ const { ok } = await inquirer14.prompt([{
6310
6800
  type: "confirm",
6311
6801
  name: "ok",
6312
6802
  message: `\u26A0\uFE0F \uC704\uD5D8 \uC791\uC5C5(${action})\uC744 \uC2E4\uD589\uD560\uAE4C\uC694?`,
@@ -6314,7 +6804,7 @@ async function guardCli(action, approved, run) {
6314
6804
  }]);
6315
6805
  return ok;
6316
6806
  },
6317
- log: (m) => console.log(chalk34.yellow(` ${m}`))
6807
+ log: (m) => console.log(chalk35.yellow(` ${m}`))
6318
6808
  },
6319
6809
  run
6320
6810
  );
@@ -6327,7 +6817,7 @@ async function guardCliDefer(action, approved, run) {
6327
6817
  approved,
6328
6818
  // TTY 면 통과(명령이 자체 확인), 비대화형은 confirm 불가 → 가드가 차단.
6329
6819
  confirm: async () => !!process.stdout.isTTY,
6330
- log: (m) => console.log(chalk34.yellow(` ${m}`))
6820
+ log: (m) => console.log(chalk35.yellow(` ${m}`))
6331
6821
  },
6332
6822
  run
6333
6823
  );
@@ -6367,6 +6857,7 @@ var KO_ALIASES = {
6367
6857
  brief: "\uBE0C\uB9AC\uD551",
6368
6858
  goal: "\uBAA9\uD45C",
6369
6859
  review: "\uAC80\uD1A0",
6860
+ mission: "\uBBF8\uC158",
6370
6861
  blocker: "\uBE14\uB85C\uCEE4",
6371
6862
  learn: "\uAD50\uD6C8",
6372
6863
  resume: "\uC7AC\uAC1C"
@@ -6494,22 +6985,48 @@ program.command("verify").alias("\uC0AC\uC804\uC810\uAC80").option("--json", "\u
6494
6985
  program.command("review").alias("\uAC80\uD1A0").option("--id <id>", "\uB300\uC0C1 goal id (\uC5C6\uC73C\uBA74 active goal)").description("\uC801\uB300\uC801 \uC790\uAE30\uAC80\uC99D \u2014 latest.json \u2194 goal \uC644\uB8CC\uC870\uAC74 \uAD50\uCC28\uAC80\uC99D (\uAC70\uC9D3\uC644\uB8CC \uC758\uC2EC \uD0D0\uC9C0, \uBCF4\uC7A5 \uC544\uB2D8)").action(async (opts) => {
6495
6986
  await review(opts);
6496
6987
  });
6988
+ var collectGlob = (v, prev = []) => prev.concat([v]);
6989
+ var missionCmd = program.command("mission").alias("\uBBF8\uC158").description("\uBBF8\uC158 \uACC4\uC57D \u2014 \uC791\uC5C5 \uBAA9\uD45C\xB7\uD5C8\uC6A9/\uAE08\uC9C0 \uBC94\uC704 \uC120\uC5B8\xB7\uAC80\uC99D (scope \uAC00\uB4DC, .vhk/mission.json)").action(async () => {
6990
+ await missionShow();
6991
+ });
6992
+ missionCmd.command("set").option("--objective <text>", "\uBBF8\uC158 \uBAA9\uD45C(objective)").option("--scope <glob>", "\uD5C8\uC6A9 \uACBD\uB85C glob (\uBC18\uBCF5 \uAC00\uB2A5, \uC81C\uACF5 \uC2DC \uAD50\uCCB4)", collectGlob).option("--forbidden <glob>", "\uAE08\uC9C0 \uACBD\uB85C glob (\uBC18\uBCF5 \uAC00\uB2A5, \uC81C\uACF5 \uC2DC \uAD50\uCCB4)", collectGlob).option("--clear-scope", "scope \uB97C \uBE44\uC6C0(\uBA85\uC2DC\uC801)").option("--clear-forbidden", "forbidden \uC744 \uBE44\uC6C0(\uBA85\uC2DC\uC801)").option("-y, --yes", "\uB300\uD654\uD615 \uD504\uB86C\uD504\uD2B8 \uC2A4\uD0B5 (\uBE44\uB300\uD654\uD615)").description("\uBBF8\uC158 \uACC4\uC57D \uC120\uC5B8/\uAC31\uC2E0 (\uC635\uC158 \uBBF8\uC9C0\uC815 \uC2DC \uAE30\uC874 scope/forbidden \uBCF4\uC874)").action(async (opts) => {
6993
+ await missionSet(opts);
6994
+ });
6995
+ missionCmd.command("check").description("\uBCC0\uACBD \uD30C\uC77C\uC774 \uACC4\uC57D(scope/forbidden) \uC548\uC778\uC9C0 \uAC80\uC99D \u2014 forbidden \uC704\uBC18 \uC2DC exit 1").action(async () => {
6996
+ await missionCheck();
6997
+ });
6998
+ missionCmd.command("clear").description("\uBBF8\uC158 \uACC4\uC57D \uC0AD\uC81C (.vhk/mission.json)").action(async () => {
6999
+ await missionClear();
7000
+ });
6497
7001
  program.command("context-show").alias("\uB9E5\uB77D\uBCF4\uAE30").description("\uD604\uC7AC \uCEE8\uD14D\uC2A4\uD2B8 \uD30C\uC77C \uB0B4\uC6A9 \uCD9C\uB825").action(async () => {
6498
7002
  await contextShow();
6499
7003
  });
6500
- var memoryCmd = program.command("memory").alias("\uAE30\uC5B5").description("\uACB0\uC815\uC0AC\uD56D \uAE30\uC5B5 \uAD00\uB9AC (add / list / remove)").action(async () => {
7004
+ var memoryCmd = program.command("memory").alias("\uAE30\uC5B5").description("\uAE30\uC5B5 \uAD00\uB9AC v2 (decisions/failures/successes 4\uBC84\uD0B7) \u2014 add/list/remove/archive/resolve/unarchive/migrate").action(async () => {
6501
7005
  await memoryList();
6502
7006
  });
6503
- memoryCmd.command("add <content>").option("--tags <tags>", "\uD0DC\uADF8 (\uC27C\uD45C \uAD6C\uBD84)").description("\uACB0\uC815\uC0AC\uD56D \uAE30\uC5B5 \uC800\uC7A5").action(async (content, opts) => {
7007
+ memoryCmd.command("add <content>").option("--type <type>", "\uBC84\uD0B7: decision|failure|success (\uAE30\uBCF8 decision)").option("--tags <tags>", "\uD0DC\uADF8 (\uC27C\uD45C \uAD6C\uBD84)").option("--why <why>", "\uC6D0\uC778 (failure/success)").option("--lesson <lesson>", "\uAD50\uD6C8 (failure)").description("\uAE30\uC5B5 \uC800\uC7A5 (--type \uC73C\uB85C \uACB0\uC815/\uC2E4\uD328/\uC131\uACF5 \uAD6C\uBD84)").action(async (content, opts) => {
6504
7008
  const tags = opts.tags ? opts.tags.split(",").map((s) => s.trim()) : void 0;
6505
- await memoryAdd(content, tags);
7009
+ await memoryAdd(content, { type: opts.type, tags, why: opts.why, lesson: opts.lesson });
6506
7010
  });
6507
- memoryCmd.command("list").alias("\uBAA9\uB85D").description("\uC800\uC7A5\uB41C \uAE30\uC5B5 \uBAA9\uB85D").action(async () => {
6508
- await memoryList();
7011
+ memoryCmd.command("list").alias("\uBAA9\uB85D").option("--type <type>", "\uBC84\uD0B7 \uD544\uD130: decision|failure|success").option("--all", "\uBCF4\uAD00(archived)\xB7\uD574\uACB0(resolved) \uD3EC\uD568").description("\uC800\uC7A5\uB41C \uAE30\uC5B5 \uBAA9\uB85D (\uAE30\uBCF8 \uD65C\uC131\uB9CC)").action(async (opts) => {
7012
+ const type = opts.type === "decision" || opts.type === "failure" || opts.type === "success" ? opts.type : void 0;
7013
+ await memoryList({ type, all: opts.all });
6509
7014
  });
6510
7015
  memoryCmd.command("remove <index>").alias("\uC0AD\uC81C").description("\uAE30\uC5B5 \uC0AD\uC81C (1\uBD80\uD130 \uC2DC\uC791\uD558\uB294 \uBC88\uD638)").action(async (index) => {
6511
7016
  await memoryRemove(index);
6512
7017
  });
7018
+ memoryCmd.command("archive <index>").alias("\uBCF4\uAD00").description("\uAE30\uC5B5 \uBCF4\uAD00 (\uD65C\uC131\u2192archived, \uD328\uD134/\uC9C4\uD654\uC5D0\uC11C \uC81C\uC678)").action(async (index) => {
7019
+ await memoryArchive(index);
7020
+ });
7021
+ memoryCmd.command("resolve <index>").alias("\uD574\uACB0").description("\uAE30\uC5B5 \uD574\uACB0 \uD45C\uC2DC (\uD65C\uC131\u2192resolved, \uD328\uD134/\uC9C4\uD654\uC5D0\uC11C \uC81C\uC678)").action(async (index) => {
7022
+ await memoryResolve(index);
7023
+ });
7024
+ memoryCmd.command("unarchive <index>").alias("\uBCF5\uAD6C").description("\uBCF4\uAD00/\uD574\uACB0 \uD56D\uBAA9\uC744 \uB2E4\uC2DC \uD65C\uC131\uC73C\uB85C \uBCF5\uAD6C (archive/resolve \uC5ED\uC804)").action(async (index) => {
7025
+ await memoryUnarchive(index);
7026
+ });
7027
+ memoryCmd.command("migrate").alias("\uB9C8\uC774\uADF8\uB808\uC774\uC158").description("memory.json v1 \u2192 v2 \uB9C8\uC774\uADF8\uB808\uC774\uC158 (\uAE30\uC874 v1 \uC788\uC73C\uBA74 .v1.bak \uC6D0\uBCF8 \uBC31\uC5C5, \uBA71\uB4F1)").action(async () => {
7028
+ await memoryMigrate();
7029
+ });
6513
7030
  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 () => {
6514
7031
  await brief();
6515
7032
  });
@@ -6537,7 +7054,7 @@ goalCmd.command("sync").alias("\uB3D9\uAE30\uD654").description("goals/*.md \uC2
6537
7054
  program.command("blocker <description>").alias("\uBE14\uB85C\uCEE4").description("\uBE14\uB85C\uCEE4 \uAE30\uB85D \u2192 docs/state/blockers.md append (3\uAC74 \uB204\uC801 \uC2DC HARD_STOP \uC790\uB3D9 \uC0DD\uC131)").action(async (description) => {
6538
7055
  await blocker(description);
6539
7056
  });
6540
- program.command("learn <lesson>").alias("\uAD50\uD6C8").description("\uAD50\uD6C8 \uAE30\uB85D \u2192 docs/state/learnings.md append (memory.json \uACFC \uBCC4\uB3C4 SoT)").action(async (lesson) => {
7057
+ program.command("learn <lesson>").alias("\uAD50\uD6C8").description("\uAD50\uD6C8 \uAE30\uB85D \u2192 memory v2 failures.lesson \uB2E8\uC77C SoT (v2.0 \uD1B5\uD569 \u2014 vhk memory list \uB85C \uD655\uC778)").action(async (lesson) => {
6541
7058
  await learn(lesson);
6542
7059
  });
6543
7060
  program.command("resume").alias("\uC7AC\uAC1C").option("--confirm", "\uC0AC\uB78C \uD655\uC778 \u2014 \uC790\uB3D9 \uD638\uCD9C \uAE08\uC9C0 (Forbidden \uC704\uBC18)").description(".vhk/HARD_STOP \uD574\uC81C (\uC0AC\uC6A9\uC790\uAC00 \uC0AC\uC720 \uD655\uC778 \uD6C4 --confirm \uD544\uC694)").action(async (opts) => {
@@ -6551,7 +7068,7 @@ program.on("command:*", async (operands) => {
6551
7068
  });
6552
7069
  program.action(async () => {
6553
7070
  console.log("\n\u{1F3AF} VHK \u2014 \uBC14\uC774\uBE0C\uCF54\uB529 \uD504\uB85C\uC81D\uD2B8 \uCF54\uCE58\n");
6554
- const { choice } = await inquirer13.prompt([{
7071
+ const { choice } = await inquirer14.prompt([{
6555
7072
  type: "list",
6556
7073
  name: "choice",
6557
7074
  message: "\uBB58 \uB3C4\uC640\uB4DC\uB9B4\uAE4C\uC694?",
@@ -6608,9 +7125,9 @@ if (isMainModule) {
6608
7125
  }
6609
7126
  } catch (err) {
6610
7127
  if (isPromptAbortError(err)) {
6611
- console.error(chalk34.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)"));
7128
+ console.error(chalk35.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)"));
6612
7129
  } else {
6613
- console.error(chalk34.red(`
7130
+ console.error(chalk35.red(`
6614
7131
  \u274C ${err instanceof Error ? err.message : String(err)}`));
6615
7132
  }
6616
7133
  process.exitCode = 1;