@byh3071/vhk 2.1.0 → 2.3.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/{chunk-ODNKCGUG.js → chunk-WQWPM364.js} +44 -0
- package/dist/index.js +441 -41
- package/dist/mcp/index.js +1 -1
- package/package.json +1 -1
|
@@ -918,6 +918,28 @@ var ko = {
|
|
|
918
918
|
detectTitle: "\uD328\uD134 \uAC10\uC9C0",
|
|
919
919
|
listTitle: "\uD328\uD134 \uBAA9\uB85D",
|
|
920
920
|
dismissTitle: "\uD328\uD134 dismiss"
|
|
921
|
+
},
|
|
922
|
+
evolve: {
|
|
923
|
+
suggestTitle: "\uC9C4\uD654 \uC81C\uC548 \uC0DD\uC131",
|
|
924
|
+
listTitle: "\uC9C4\uD654 \uD6C4\uBCF4 \uBAA9\uB85D",
|
|
925
|
+
applyTitle: "\uB8F0 \uBC18\uC601",
|
|
926
|
+
rejectTitle: "\uD6C4\uBCF4 \uAE30\uAC01",
|
|
927
|
+
undoTitle: "\uCD5C\uADFC \uBC18\uC601 \uB418\uB3CC\uB9AC\uAE30",
|
|
928
|
+
noRules: "RULES.md \uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. vhk init\uC73C\uB85C \uC0DD\uC131 \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694.",
|
|
929
|
+
noPatterns: "patterns[]\uAC00 \uBE44\uC5B4\uC788\uAC70\uB098 active avoid \uD328\uD134\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. vhk pattern detect \uB85C \uBA3C\uC800 \uAC10\uC9C0\uD558\uC138\uC694.",
|
|
930
|
+
noQueue: "\uD6C4\uBCF4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. vhk evolve suggest \uB85C \uBA3C\uC800 \uC0DD\uC131\uD558\uC138\uC694.",
|
|
931
|
+
notFound: (id) => `\uD6C4\uBCF4 '${id}' \uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. vhk evolve list \uB85C \uD655\uC778\uD558\uC138\uC694.`,
|
|
932
|
+
alreadyApplied: "\uC774\uBBF8 \uBC18\uC601\uB41C \uD6C4\uBCF4\uC785\uB2C8\uB2E4.",
|
|
933
|
+
dismissed: "\uC18C\uC2A4 \uD328\uD134\uC774 dismiss\uB428 \u2014 apply \uAC70\uBD80 (dismiss\uB41C \uD328\uD134 \uAE30\uBC18 \uB8F0\uC740 \uBC18\uC601 \uC548 \uB428)",
|
|
934
|
+
alreadyAppliedPattern: "\uC18C\uC2A4 \uD328\uD134\uC774 \uC774\uBBF8 \uBC18\uC601\uB428 \u2014 apply \uAC70\uBD80",
|
|
935
|
+
duplicateRule: (draft) => `\uC911\uBCF5 \uB8F0 \uAC10\uC9C0 \u2014 RULES.md\uC5D0 \uC774\uBBF8 \uC720\uC0AC\uD55C \uB8F0\uC774 \uC788\uC2B5\uB2C8\uB2E4:
|
|
936
|
+
${draft}`,
|
|
937
|
+
pendingApplyExists: "\uBBF8\uD574\uC18C apply\uAC00 \uC788\uC2B5\uB2C8\uB2E4. vhk evolve undo \uD6C4 \uC7AC\uC2DC\uB3C4\uD558\uAC70\uB098 \uADF8\uB300\uB85C \uC720\uC9C0\uD558\uC138\uC694.",
|
|
938
|
+
noAppliedToUndo: "undo\uD560 \uBC18\uC601 \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
939
|
+
noBackup: ".bak \uD30C\uC77C\uC774 \uC5C6\uC5B4 undo \uBD88\uAC00\uD569\uB2C8\uB2E4. RULES.md\uB97C \uC218\uB3D9 \uBCF5\uC6D0\uD558\uC138\uC694.",
|
|
940
|
+
allSuggested: "\uBAA8\uB4E0 \uD328\uD134\uC774 \uC774\uBBF8 \uC81C\uC548\uB410\uAC70\uB098 reject\uB410\uC2B5\uB2C8\uB2E4.",
|
|
941
|
+
newCandidates: (n) => `\uC2E0\uADDC \uD6C4\uBCF4: ${n}\uAC1C \uCD94\uAC00\uB428`,
|
|
942
|
+
suggestHint: "vhk evolve suggest \uB85C \uC0DD\uC131\uD558\uC138\uC694."
|
|
921
943
|
}
|
|
922
944
|
};
|
|
923
945
|
function lookup(path7) {
|
|
@@ -3031,6 +3053,28 @@ ${cliStatus}
|
|
|
3031
3053
|
return runVhkCli(args, "pattern list");
|
|
3032
3054
|
}
|
|
3033
3055
|
);
|
|
3056
|
+
server.registerTool(
|
|
3057
|
+
"evolve-suggest",
|
|
3058
|
+
{
|
|
3059
|
+
description: "active avoid \uD328\uD134 \u2192 \uB8F0 \uCD08\uC548 \uD6C4\uBCF4 \uC0DD\uC131\xB7\uD050 \uC801\uC7AC (Goal 20)",
|
|
3060
|
+
inputSchema: {}
|
|
3061
|
+
},
|
|
3062
|
+
async () => runVhkCli(["evolve", "suggest", "--json"], "evolve suggest")
|
|
3063
|
+
);
|
|
3064
|
+
server.registerTool(
|
|
3065
|
+
"evolve-list",
|
|
3066
|
+
{
|
|
3067
|
+
description: "\uC9C4\uD654 \uD6C4\uBCF4 \uBAA9\uB85D \uC870\uD68C (pending|rejected|applied \u2014 Goal 20)",
|
|
3068
|
+
inputSchema: {
|
|
3069
|
+
status: z.enum(["pending", "rejected", "applied"]).optional().describe("\uC0C1\uD0DC \uD544\uD130")
|
|
3070
|
+
}
|
|
3071
|
+
},
|
|
3072
|
+
async ({ status }) => {
|
|
3073
|
+
const args = ["evolve", "list", "--json"];
|
|
3074
|
+
if (status) args.push("--status", status);
|
|
3075
|
+
return runVhkCli(args, "evolve list");
|
|
3076
|
+
}
|
|
3077
|
+
);
|
|
3034
3078
|
return server;
|
|
3035
3079
|
}
|
|
3036
3080
|
async function startMcpServer() {
|
package/dist/index.js
CHANGED
|
@@ -43,14 +43,14 @@ import {
|
|
|
43
43
|
stripBom,
|
|
44
44
|
sync,
|
|
45
45
|
t
|
|
46
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-WQWPM364.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
|
|
53
|
-
import
|
|
52
|
+
import chalk37 from "chalk";
|
|
53
|
+
import inquirer15 from "inquirer";
|
|
54
54
|
|
|
55
55
|
// src/lib/nlp-router.ts
|
|
56
56
|
function normalize(input) {
|
|
@@ -59,6 +59,7 @@ function normalize(input) {
|
|
|
59
59
|
var NLP_KEYWORDS = {
|
|
60
60
|
save: ["\uC800\uC7A5", "\uC138\uC774\uBE0C", "\uCEE4\uBC0B", "\uC62C\uB824", "\uC62C\uB9AC\uAE30", "\uD478\uC2DC", "push", "commit"],
|
|
61
61
|
pattern: ["\uD328\uD134", "\uB418\uD480\uC774", "\uBC84\uB987", "pattern"],
|
|
62
|
+
evolve: ["\uC9C4\uD654", "\uB8F0\uD6C4\uBCF4", "\uC9C4\uD654\uD6C4\uBCF4"],
|
|
62
63
|
undo: ["\uB418\uB3CC\uB824", "\uB418\uB3CC\uB9AC\uAE30", "\uCDE8\uC18C", "\uC6D0\uB798\uB300\uB85C", "\uB864\uBC31", "\uB9AC\uC14B", "reset", "rollback"],
|
|
63
64
|
status: ["\uC0C1\uD0DC", "\uD604\uD669", "\uC5B4\uB5BB\uAC8C", "\uC5B4\uB54C", "\uC9C0\uAE08"],
|
|
64
65
|
diff: ["\uBCC0\uACBD", "\uBC14\uB010", "\uBB50\uBC14\uB01C", "\uBC14\uB00C\uC5C8", "\uCC28\uC774", "\uB2EC\uB77C\uC9C4", "\uC218\uC815\uB41C"]
|
|
@@ -328,6 +329,12 @@ var RULES = [
|
|
|
328
329
|
confidence: "high",
|
|
329
330
|
test: (t2) => matchesKeywords(t2, "pattern") || /^pattern$/.test(t2)
|
|
330
331
|
},
|
|
332
|
+
{
|
|
333
|
+
command: "evolve",
|
|
334
|
+
explanation: "\uC9C4\uD654 \uD6C4\uBCF4 \uBAA9\uB85D (vhk evolve list) \u2014 apply/undo\uB294 \uC9C1\uC811 \uC2E4\uD589",
|
|
335
|
+
confidence: "high",
|
|
336
|
+
test: (t2) => matchesKeywords(t2, "evolve") || /^evolve$/.test(t2)
|
|
337
|
+
},
|
|
331
338
|
// NLP 규칙은 한국어 표현만 매칭. 영문 `goal <sub>` 은 commander 가 직접 처리하도록
|
|
332
339
|
// 가로채기 금지 — vhk goal list / next / check / done 그대로 동작.
|
|
333
340
|
{
|
|
@@ -398,7 +405,8 @@ var CONTAINER_SUBCOMMANDS = {
|
|
|
398
405
|
env: ["check"],
|
|
399
406
|
mode: ["lite", "standard", "strict"],
|
|
400
407
|
mission: ["set", "check", "clear"],
|
|
401
|
-
pattern: ["detect", "list", "dismiss"]
|
|
408
|
+
pattern: ["detect", "list", "dismiss"],
|
|
409
|
+
evolve: ["suggest", "list", "apply", "reject", "undo"]
|
|
402
410
|
};
|
|
403
411
|
var CONTAINER_ALIASES = {
|
|
404
412
|
\uBAA9\uD45C: "goal",
|
|
@@ -410,7 +418,8 @@ var CONTAINER_ALIASES = {
|
|
|
410
418
|
\uD658\uACBD\uBCC0\uC218: "env",
|
|
411
419
|
\uBAA8\uB4DC: "mode",
|
|
412
420
|
\uBBF8\uC158: "mission",
|
|
413
|
-
\uD328\uD134: "pattern"
|
|
421
|
+
\uD328\uD134: "pattern",
|
|
422
|
+
\uC9C4\uD654: "evolve"
|
|
414
423
|
};
|
|
415
424
|
|
|
416
425
|
// src/lib/cli-args.ts
|
|
@@ -544,8 +553,8 @@ function detectNaturalLanguageInput(argv) {
|
|
|
544
553
|
}
|
|
545
554
|
|
|
546
555
|
// src/lib/nlp-run.ts
|
|
547
|
-
import
|
|
548
|
-
import
|
|
556
|
+
import chalk35 from "chalk";
|
|
557
|
+
import inquirer14 from "inquirer";
|
|
549
558
|
|
|
550
559
|
// src/commands/gate.ts
|
|
551
560
|
import inquirer from "inquirer";
|
|
@@ -6745,6 +6754,376 @@ async function patternDismiss(idStr) {
|
|
|
6745
6754
|
});
|
|
6746
6755
|
}
|
|
6747
6756
|
|
|
6757
|
+
// src/commands/evolve.ts
|
|
6758
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync13, writeFileSync as writeFileSync14, readFileSync as readFileSync7, copyFileSync as copyFileSync2, renameSync as renameSync2, rmSync as rmSync5 } from "fs";
|
|
6759
|
+
import { join as join14 } from "path";
|
|
6760
|
+
import chalk34 from "chalk";
|
|
6761
|
+
import inquirer13 from "inquirer";
|
|
6762
|
+
var QUEUE_PATH_REL = join14(".vhk", "evolve", "queue.json");
|
|
6763
|
+
function buildDraft(p) {
|
|
6764
|
+
const axisLabel = p.axis === "tag" ? `\uD0DC\uADF8 '${p.signal}'` : `\uD0A4\uC6CC\uB4DC '${p.signal}'`;
|
|
6765
|
+
const countDesc = `${p.count}\uAC74 \uBC18\uBCF5`;
|
|
6766
|
+
return `- ${axisLabel} \uAD00\uB828 \uC791\uC5C5 \uC2DC \uC0AC\uC804 \uC810\uAC80 \uD544\uC218 (\uADFC\uAC70: ${countDesc}, ${p.summary})`;
|
|
6767
|
+
}
|
|
6768
|
+
function buildDedupeKey(patternId, kind) {
|
|
6769
|
+
return `${patternId}:${kind}`;
|
|
6770
|
+
}
|
|
6771
|
+
function generateCandidates(patterns, existing) {
|
|
6772
|
+
const rejectedKeys = new Set(
|
|
6773
|
+
existing.filter((i) => i.status === "rejected").map((i) => i.dedupeKey)
|
|
6774
|
+
);
|
|
6775
|
+
const occupiedKeys = new Set(
|
|
6776
|
+
existing.filter((i) => i.status === "pending" || i.status === "applied").map((i) => i.dedupeKey)
|
|
6777
|
+
);
|
|
6778
|
+
const eligible = patterns.filter((p) => p.kind === "avoid" && p.status === "active").sort((a, b) => a.id.localeCompare(b.id));
|
|
6779
|
+
const result = [];
|
|
6780
|
+
for (const p of eligible) {
|
|
6781
|
+
const dedupeKey = buildDedupeKey(p.id, "rule");
|
|
6782
|
+
if (rejectedKeys.has(dedupeKey)) continue;
|
|
6783
|
+
if (occupiedKeys.has(dedupeKey)) continue;
|
|
6784
|
+
result.push({
|
|
6785
|
+
patternId: p.id,
|
|
6786
|
+
kind: "rule",
|
|
6787
|
+
status: "pending",
|
|
6788
|
+
draft: buildDraft(p),
|
|
6789
|
+
dedupeKey
|
|
6790
|
+
});
|
|
6791
|
+
}
|
|
6792
|
+
return result;
|
|
6793
|
+
}
|
|
6794
|
+
function isDuplicateRule(rulesContent, draft) {
|
|
6795
|
+
const normalize2 = (s) => s.trim().replace(/\s+/g, " ").toLowerCase();
|
|
6796
|
+
const normalizedDraft = normalize2(draft);
|
|
6797
|
+
for (const line of rulesContent.split(/\r?\n/)) {
|
|
6798
|
+
if (normalize2(line) === normalizedDraft) return true;
|
|
6799
|
+
}
|
|
6800
|
+
return false;
|
|
6801
|
+
}
|
|
6802
|
+
function stripBomStr(s) {
|
|
6803
|
+
return s.charCodeAt(0) === 65279 ? s.slice(1) : s;
|
|
6804
|
+
}
|
|
6805
|
+
function readQueue(cwd) {
|
|
6806
|
+
const p = join14(cwd, QUEUE_PATH_REL);
|
|
6807
|
+
if (!existsSync19(p)) return { version: 1, items: [] };
|
|
6808
|
+
try {
|
|
6809
|
+
const raw = stripBomStr(readFileSync7(p, "utf-8"));
|
|
6810
|
+
const parsed = JSON.parse(raw);
|
|
6811
|
+
if (!parsed || !Array.isArray(parsed.items)) return { version: 1, items: [] };
|
|
6812
|
+
return parsed;
|
|
6813
|
+
} catch {
|
|
6814
|
+
return { version: 1, items: [] };
|
|
6815
|
+
}
|
|
6816
|
+
}
|
|
6817
|
+
function writeQueue(cwd, queue) {
|
|
6818
|
+
const p = join14(cwd, QUEUE_PATH_REL);
|
|
6819
|
+
mkdirSync13(join14(cwd, ".vhk", "evolve"), { recursive: true });
|
|
6820
|
+
const tmpPath = p + ".tmp";
|
|
6821
|
+
writeFileSync14(tmpPath, JSON.stringify(queue, null, 2) + "\n", "utf-8");
|
|
6822
|
+
try {
|
|
6823
|
+
renameSync2(tmpPath, p);
|
|
6824
|
+
} catch (err) {
|
|
6825
|
+
try {
|
|
6826
|
+
rmSync5(tmpPath, { force: true });
|
|
6827
|
+
} catch {
|
|
6828
|
+
}
|
|
6829
|
+
throw err;
|
|
6830
|
+
}
|
|
6831
|
+
}
|
|
6832
|
+
function nextQueueId(queue) {
|
|
6833
|
+
const re = /^e(\d+)$/;
|
|
6834
|
+
let max = 0;
|
|
6835
|
+
for (const item of queue.items) {
|
|
6836
|
+
const m = item.id.match(re);
|
|
6837
|
+
if (m) max = Math.max(max, Number(m[1]));
|
|
6838
|
+
}
|
|
6839
|
+
return `e${max + 1}`;
|
|
6840
|
+
}
|
|
6841
|
+
function checkApplyRef(pattern, queueItems) {
|
|
6842
|
+
if (pattern === void 0 || pattern.status !== "archived") return "ok";
|
|
6843
|
+
const hasApplied = queueItems.some(
|
|
6844
|
+
(i) => i.patternId === pattern.id && i.status === "applied"
|
|
6845
|
+
);
|
|
6846
|
+
return hasApplied ? "already-applied" : "dismissed";
|
|
6847
|
+
}
|
|
6848
|
+
async function evolveSuggest(opts = {}) {
|
|
6849
|
+
const cwd = process.cwd();
|
|
6850
|
+
if (!existsSync19(join14(cwd, "RULES.md"))) {
|
|
6851
|
+
console.log(chalk34.yellow("\n\u26A0\uFE0F " + t("evolve.noRules")));
|
|
6852
|
+
process.exitCode = 1;
|
|
6853
|
+
return;
|
|
6854
|
+
}
|
|
6855
|
+
const mem = readMemory(cwd);
|
|
6856
|
+
const patterns = mem.patterns;
|
|
6857
|
+
const queue = readQueue(cwd);
|
|
6858
|
+
const newItems = generateCandidates(patterns, queue.items);
|
|
6859
|
+
if (newItems.length === 0 && !opts.json) {
|
|
6860
|
+
const activeAvoid = patterns.filter((p) => p.kind === "avoid" && p.status === "active");
|
|
6861
|
+
if (activeAvoid.length === 0) {
|
|
6862
|
+
console.log(chalk34.yellow("\n\u{1F4ED} " + t("evolve.noPatterns")));
|
|
6863
|
+
return;
|
|
6864
|
+
}
|
|
6865
|
+
console.log(chalk34.dim("\n " + t("evolve.allSuggested")));
|
|
6866
|
+
return;
|
|
6867
|
+
}
|
|
6868
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
6869
|
+
for (const c of newItems) {
|
|
6870
|
+
queue.items.push({ ...c, id: nextQueueId(queue), createdAt: now });
|
|
6871
|
+
}
|
|
6872
|
+
writeQueue(cwd, queue);
|
|
6873
|
+
if (opts.json) {
|
|
6874
|
+
const pending2 = queue.items.filter((i) => i.status === "pending");
|
|
6875
|
+
console.log(JSON.stringify(pending2, null, 2));
|
|
6876
|
+
return;
|
|
6877
|
+
}
|
|
6878
|
+
console.log(chalk34.bold("\n\u{1F504} " + t("evolve.suggestTitle")));
|
|
6879
|
+
console.log(chalk34.gray("\u2500".repeat(40)));
|
|
6880
|
+
console.log(chalk34.dim(" " + t("evolve.newCandidates", newItems.length)));
|
|
6881
|
+
const pending = queue.items.filter((i) => i.status === "pending");
|
|
6882
|
+
console.log(chalk34.cyan(`
|
|
6883
|
+
\uD6C4\uBCF4 ${pending.length}\uAC1C:
|
|
6884
|
+
`));
|
|
6885
|
+
for (const item of pending) {
|
|
6886
|
+
console.log(` [${item.id}] (${item.status}) \uD328\uD134 ${item.patternId} \u2192 rule`);
|
|
6887
|
+
console.log(chalk34.dim(` \uCD08\uC548: ${item.draft}`));
|
|
6888
|
+
}
|
|
6889
|
+
printNextStep({
|
|
6890
|
+
message: `\uC9C4\uD654 \uD6C4\uBCF4 ${pending.length}\uAC1C \uC0DD\uC131\uB428!`,
|
|
6891
|
+
command: "vhk evolve list",
|
|
6892
|
+
cursorHint: "\uC9C4\uD654 \uD6C4\uBCF4 \uBCF4\uC5EC\uC918",
|
|
6893
|
+
alternative: "vhk evolve apply <id> \uB85C \uBC18\uC601"
|
|
6894
|
+
});
|
|
6895
|
+
}
|
|
6896
|
+
async function evolveList(opts = {}) {
|
|
6897
|
+
const cwd = process.cwd();
|
|
6898
|
+
const queue = readQueue(cwd);
|
|
6899
|
+
const VALID = ["pending", "rejected", "applied"];
|
|
6900
|
+
let items = queue.items;
|
|
6901
|
+
if (opts.status && VALID.includes(opts.status)) {
|
|
6902
|
+
items = items.filter((i) => i.status === opts.status);
|
|
6903
|
+
}
|
|
6904
|
+
if (opts.json) {
|
|
6905
|
+
console.log(JSON.stringify(items, null, 2));
|
|
6906
|
+
return;
|
|
6907
|
+
}
|
|
6908
|
+
console.log(chalk34.bold("\n\u{1F504} " + t("evolve.listTitle")));
|
|
6909
|
+
console.log(chalk34.gray("\u2500".repeat(40)));
|
|
6910
|
+
if (items.length === 0) {
|
|
6911
|
+
console.log(chalk34.yellow("\n\u{1F4ED} " + t("evolve.noQueue")));
|
|
6912
|
+
console.log(chalk34.gray(" " + t("evolve.suggestHint")));
|
|
6913
|
+
return;
|
|
6914
|
+
}
|
|
6915
|
+
const STATUS_ICON3 = {
|
|
6916
|
+
pending: "\u23F3",
|
|
6917
|
+
rejected: "\u274C",
|
|
6918
|
+
applied: "\u2705"
|
|
6919
|
+
};
|
|
6920
|
+
console.log(chalk34.cyan(`
|
|
6921
|
+
${items.length}\uAC1C:
|
|
6922
|
+
`));
|
|
6923
|
+
for (const item of items) {
|
|
6924
|
+
console.log(` [${item.id}] ${STATUS_ICON3[item.status]} (${item.status}) \u2192 ${item.draft}`);
|
|
6925
|
+
if (item.appliedAt) console.log(chalk34.dim(` \uBC18\uC601: ${item.appliedAt}`));
|
|
6926
|
+
}
|
|
6927
|
+
}
|
|
6928
|
+
async function evolveApply(idStr) {
|
|
6929
|
+
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;
|
|
6930
|
+
const cwd = process.cwd();
|
|
6931
|
+
const rulesPath = join14(cwd, "RULES.md");
|
|
6932
|
+
if (!existsSync19(rulesPath)) {
|
|
6933
|
+
console.log(chalk34.red("\n\u274C " + t("evolve.noRules")));
|
|
6934
|
+
process.exitCode = 1;
|
|
6935
|
+
return;
|
|
6936
|
+
}
|
|
6937
|
+
const queue = readQueue(cwd);
|
|
6938
|
+
const item = queue.items.find((i) => i.id === idStr?.trim());
|
|
6939
|
+
if (!item) {
|
|
6940
|
+
console.log(chalk34.red("\n\u274C " + t("evolve.notFound", idStr ?? "")));
|
|
6941
|
+
process.exitCode = 1;
|
|
6942
|
+
return;
|
|
6943
|
+
}
|
|
6944
|
+
if (item.status === "applied") {
|
|
6945
|
+
console.log(chalk34.yellow("\n\u26A0\uFE0F " + t("evolve.alreadyApplied")));
|
|
6946
|
+
process.exitCode = 1;
|
|
6947
|
+
return;
|
|
6948
|
+
}
|
|
6949
|
+
const hasUnresolved = queue.items.some((i) => i.status === "applied");
|
|
6950
|
+
if (hasUnresolved) {
|
|
6951
|
+
console.log(chalk34.red("\n\u274C " + t("evolve.pendingApplyExists")));
|
|
6952
|
+
process.exitCode = 1;
|
|
6953
|
+
return;
|
|
6954
|
+
}
|
|
6955
|
+
const memLoaded = loadForMutation(cwd);
|
|
6956
|
+
if (!memLoaded.ok) {
|
|
6957
|
+
console.log(chalk34.red("\n\u274C memory.json \uC190\uC0C1 \uC758\uC2EC \u2014 apply \uC911\uB2E8 (\uC6D0\uBCF8 \uBCF4\uC874)."));
|
|
6958
|
+
process.exitCode = 1;
|
|
6959
|
+
return;
|
|
6960
|
+
}
|
|
6961
|
+
const srcPattern = memLoaded.mem.patterns.find((p) => p.id === item.patternId);
|
|
6962
|
+
const refResult = checkApplyRef(srcPattern, queue.items);
|
|
6963
|
+
if (refResult === "dismissed") {
|
|
6964
|
+
console.log(chalk34.red("\n\u274C " + t("evolve.dismissed")));
|
|
6965
|
+
process.exitCode = 1;
|
|
6966
|
+
return;
|
|
6967
|
+
}
|
|
6968
|
+
if (refResult === "already-applied") {
|
|
6969
|
+
console.log(chalk34.red("\n\u274C " + t("evolve.alreadyAppliedPattern")));
|
|
6970
|
+
process.exitCode = 1;
|
|
6971
|
+
return;
|
|
6972
|
+
}
|
|
6973
|
+
const rulesContent = readFileSync7(rulesPath, "utf-8");
|
|
6974
|
+
if (isDuplicateRule(rulesContent, item.draft)) {
|
|
6975
|
+
console.log(chalk34.yellow("\n\u26A0\uFE0F " + t("evolve.duplicateRule", item.draft)));
|
|
6976
|
+
return;
|
|
6977
|
+
}
|
|
6978
|
+
console.log(chalk34.bold("\n\u{1F504} " + t("evolve.applyTitle")));
|
|
6979
|
+
console.log(chalk34.gray("\u2500".repeat(40)));
|
|
6980
|
+
console.log(chalk34.cyan("\n\uCD94\uAC00\uB420 \uB8F0 \uCD08\uC548:"));
|
|
6981
|
+
console.log(chalk34.white(` ${item.draft}`));
|
|
6982
|
+
const { editedDraft } = await inquirer13.prompt([{
|
|
6983
|
+
type: "input",
|
|
6984
|
+
name: "editedDraft",
|
|
6985
|
+
message: "\uB8F0 \uBB38\uAD6C \uC218\uC815 (Enter = \uADF8\uB300\uB85C):",
|
|
6986
|
+
default: item.draft
|
|
6987
|
+
}]);
|
|
6988
|
+
const { confirmed } = await inquirer13.prompt([{
|
|
6989
|
+
type: "confirm",
|
|
6990
|
+
name: "confirmed",
|
|
6991
|
+
message: `RULES.md\uC5D0 \uC774 \uB8F0\uC744 \uCD94\uAC00\uD560\uAE4C\uC694?
|
|
6992
|
+
${editedDraft}`,
|
|
6993
|
+
default: false
|
|
6994
|
+
}]);
|
|
6995
|
+
if (!confirmed) {
|
|
6996
|
+
console.log(chalk34.dim(" \uCDE8\uC18C\uB428."));
|
|
6997
|
+
return;
|
|
6998
|
+
}
|
|
6999
|
+
const backupPath = rulesPath + ".bak";
|
|
7000
|
+
copyFileSync2(rulesPath, backupPath);
|
|
7001
|
+
const appendContent = "\n" + editedDraft + "\n";
|
|
7002
|
+
try {
|
|
7003
|
+
writeFileSync14(rulesPath, rulesContent + appendContent, "utf-8");
|
|
7004
|
+
await sync({ yes: true });
|
|
7005
|
+
} catch (err) {
|
|
7006
|
+
try {
|
|
7007
|
+
copyFileSync2(backupPath, rulesPath);
|
|
7008
|
+
} catch {
|
|
7009
|
+
}
|
|
7010
|
+
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."));
|
|
7011
|
+
console.error(chalk34.dim(` ${err instanceof Error ? err.message : String(err)}`));
|
|
7012
|
+
process.exitCode = 1;
|
|
7013
|
+
return;
|
|
7014
|
+
}
|
|
7015
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
7016
|
+
item.status = "applied";
|
|
7017
|
+
item.draft = editedDraft;
|
|
7018
|
+
item.appliedAt = now;
|
|
7019
|
+
item.rulesBackupPath = backupPath;
|
|
7020
|
+
writeQueue(cwd, queue);
|
|
7021
|
+
if (srcPattern) {
|
|
7022
|
+
const p = memLoaded.mem.patterns.find((x) => x.id === srcPattern.id);
|
|
7023
|
+
if (p) {
|
|
7024
|
+
p.status = "archived";
|
|
7025
|
+
writeMemory(cwd, memLoaded.mem);
|
|
7026
|
+
} else {
|
|
7027
|
+
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."));
|
|
7028
|
+
}
|
|
7029
|
+
}
|
|
7030
|
+
console.log(chalk34.green(`
|
|
7031
|
+
\u2705 \uB8F0 \uBC18\uC601 \uC644\uB8CC! [${item.id}]`));
|
|
7032
|
+
console.log(chalk34.dim(" RULES.md\uC5D0 \uCD94\uAC00 + vhk sync \uC7AC\uC0DD\uC131\uB428"));
|
|
7033
|
+
printNextStep({
|
|
7034
|
+
message: "\uB8F0 \uBC18\uC601 \uC644\uB8CC!",
|
|
7035
|
+
command: "vhk evolve list --status applied",
|
|
7036
|
+
cursorHint: "\uBC18\uC601\uB41C \uB8F0 \uBAA9\uB85D \uBCF4\uC5EC\uC918",
|
|
7037
|
+
alternative: "vhk evolve undo \u2014 \uB418\uB3CC\uB9AC\uAE30"
|
|
7038
|
+
});
|
|
7039
|
+
}
|
|
7040
|
+
async function evolveReject(idStr) {
|
|
7041
|
+
const cwd = process.cwd();
|
|
7042
|
+
const queue = readQueue(cwd);
|
|
7043
|
+
const item = queue.items.find((i) => i.id === idStr?.trim());
|
|
7044
|
+
if (!item) {
|
|
7045
|
+
console.log(chalk34.red("\n\u274C " + t("evolve.notFound", idStr ?? "")));
|
|
7046
|
+
process.exitCode = 1;
|
|
7047
|
+
return;
|
|
7048
|
+
}
|
|
7049
|
+
if (item.status === "rejected") {
|
|
7050
|
+
console.log(chalk34.dim(` \uC774\uBBF8 \uAE30\uAC01\uB41C \uD6C4\uBCF4\uC785\uB2C8\uB2E4 \u2014 \uBCC0\uACBD \uC5C6\uC74C: ${item.id}`));
|
|
7051
|
+
return;
|
|
7052
|
+
}
|
|
7053
|
+
if (item.status === "applied") {
|
|
7054
|
+
console.log(chalk34.red(`
|
|
7055
|
+
\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}`));
|
|
7056
|
+
process.exitCode = 1;
|
|
7057
|
+
return;
|
|
7058
|
+
}
|
|
7059
|
+
item.status = "rejected";
|
|
7060
|
+
writeQueue(cwd, queue);
|
|
7061
|
+
console.log(chalk34.green(`
|
|
7062
|
+
\u274C \uD6C4\uBCF4 \uAE30\uAC01\uB428: [${item.id}] ${item.draft}`));
|
|
7063
|
+
console.log(chalk34.dim(" (A1: \uB2E4\uC74C suggest\uC5D0\uC11C \uC7AC\uC81C\uC548 \uC548 \uB428)"));
|
|
7064
|
+
printNextStep({
|
|
7065
|
+
message: "\uAE30\uAC01 \uC644\uB8CC!",
|
|
7066
|
+
command: "vhk evolve list",
|
|
7067
|
+
cursorHint: "\uB0A8\uC740 \uD6C4\uBCF4 \uBCF4\uC5EC\uC918"
|
|
7068
|
+
});
|
|
7069
|
+
}
|
|
7070
|
+
async function evolveUndo() {
|
|
7071
|
+
if (!ensureInteractive("undo\uB294 TTY \uD655\uC778\uC774 \uD544\uC694\uD569\uB2C8\uB2E4. \uD130\uBBF8\uB110\uC5D0\uC11C \uC9C1\uC811 \uC2E4\uD589\uD558\uC138\uC694.")) return;
|
|
7072
|
+
const cwd = process.cwd();
|
|
7073
|
+
const queue = readQueue(cwd);
|
|
7074
|
+
const applied = queue.items.filter((i) => i.status === "applied");
|
|
7075
|
+
if (applied.length === 0) {
|
|
7076
|
+
console.log(chalk34.yellow("\n\u{1F4ED} " + t("evolve.noAppliedToUndo")));
|
|
7077
|
+
return;
|
|
7078
|
+
}
|
|
7079
|
+
const last = applied.sort(
|
|
7080
|
+
(a, b) => (b.appliedAt ?? "").localeCompare(a.appliedAt ?? "")
|
|
7081
|
+
)[0];
|
|
7082
|
+
if (!last.rulesBackupPath || !existsSync19(last.rulesBackupPath)) {
|
|
7083
|
+
console.log(chalk34.red("\n\u274C " + t("evolve.noBackup")));
|
|
7084
|
+
process.exitCode = 1;
|
|
7085
|
+
return;
|
|
7086
|
+
}
|
|
7087
|
+
console.log(chalk34.bold("\n\u{1F504} " + t("evolve.undoTitle")));
|
|
7088
|
+
console.log(chalk34.dim(` \uB418\uB3CC\uB9B4 \uD56D\uBAA9: [${last.id}] ${last.draft}`));
|
|
7089
|
+
const { confirmed } = await inquirer13.prompt([{
|
|
7090
|
+
type: "confirm",
|
|
7091
|
+
name: "confirmed",
|
|
7092
|
+
message: "RULES.md\uB97C .bak\uC73C\uB85C \uBCF5\uC6D0\uD558\uACE0 vhk sync\uB97C \uC7AC\uC2E4\uD589\uD560\uAE4C\uC694?",
|
|
7093
|
+
default: false
|
|
7094
|
+
}]);
|
|
7095
|
+
if (!confirmed) {
|
|
7096
|
+
console.log(chalk34.dim(" \uCDE8\uC18C\uB428."));
|
|
7097
|
+
return;
|
|
7098
|
+
}
|
|
7099
|
+
copyFileSync2(last.rulesBackupPath, join14(cwd, "RULES.md"));
|
|
7100
|
+
try {
|
|
7101
|
+
await sync({ yes: true });
|
|
7102
|
+
} catch (err) {
|
|
7103
|
+
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."));
|
|
7104
|
+
console.error(chalk34.dim(` ${err instanceof Error ? err.message : String(err)}`));
|
|
7105
|
+
console.error(chalk34.dim(" \uC218\uB3D9\uC73C\uB85C `vhk sync` \uC2E4\uD589\uD558\uC138\uC694."));
|
|
7106
|
+
}
|
|
7107
|
+
last.status = "pending";
|
|
7108
|
+
delete last.appliedAt;
|
|
7109
|
+
delete last.rulesBackupPath;
|
|
7110
|
+
writeQueue(cwd, queue);
|
|
7111
|
+
const memLoaded = loadForMutation(cwd);
|
|
7112
|
+
if (memLoaded.ok) {
|
|
7113
|
+
const p = memLoaded.mem.patterns.find((x) => x.id === last.patternId);
|
|
7114
|
+
if (p && p.status === "archived") {
|
|
7115
|
+
p.status = "active";
|
|
7116
|
+
writeMemory(cwd, memLoaded.mem);
|
|
7117
|
+
}
|
|
7118
|
+
}
|
|
7119
|
+
console.log(chalk34.green("\n\u2705 \uB418\uB3CC\uB9AC\uAE30 \uC644\uB8CC! RULES.md \uBCF5\uC6D0 + sync \uC7AC\uC2E4\uD589\uB428"));
|
|
7120
|
+
printNextStep({
|
|
7121
|
+
message: "\uB418\uB3CC\uB9AC\uAE30 \uC644\uB8CC!",
|
|
7122
|
+
command: "vhk evolve list",
|
|
7123
|
+
cursorHint: "\uD6C4\uBCF4 \uBAA9\uB85D \uBCF4\uC5EC\uC918"
|
|
7124
|
+
});
|
|
7125
|
+
}
|
|
7126
|
+
|
|
6748
7127
|
// src/lib/risk-policy.ts
|
|
6749
7128
|
var HIGH_RISK_ACTIONS = [
|
|
6750
7129
|
"undo",
|
|
@@ -6917,6 +7296,8 @@ async function dispatchNlpRoute(route, input) {
|
|
|
6917
7296
|
return missionShow();
|
|
6918
7297
|
case "pattern":
|
|
6919
7298
|
return patternList();
|
|
7299
|
+
case "evolve":
|
|
7300
|
+
return evolveList();
|
|
6920
7301
|
}
|
|
6921
7302
|
}
|
|
6922
7303
|
var STATE_CHANGING_COMMANDS = /* @__PURE__ */ new Set([
|
|
@@ -6930,23 +7311,23 @@ function requiresConfirmation(route) {
|
|
|
6930
7311
|
async function runNaturalLanguageRoute(input) {
|
|
6931
7312
|
const route = routeNaturalLanguage(input);
|
|
6932
7313
|
if (!route) {
|
|
6933
|
-
console.log(
|
|
7314
|
+
console.log(chalk35.yellow(`
|
|
6934
7315
|
\u2753 "${input}" \u2014 ${ko.nlp.notMatched}
|
|
6935
7316
|
`));
|
|
6936
7317
|
return;
|
|
6937
7318
|
}
|
|
6938
7319
|
console.log("");
|
|
6939
|
-
console.log(
|
|
6940
|
-
console.log(
|
|
7320
|
+
console.log(chalk35.cyan(` \u{1F4AC} "${input}"`));
|
|
7321
|
+
console.log(chalk35.cyan(` \u2192 ${route.explanation}`));
|
|
6941
7322
|
if (requiresConfirmation(route)) {
|
|
6942
|
-
const { confirm } = await
|
|
7323
|
+
const { confirm } = await inquirer14.prompt([{
|
|
6943
7324
|
type: "confirm",
|
|
6944
7325
|
name: "confirm",
|
|
6945
7326
|
message: `${route.explanation} \u2014 ${ko.nlp.matched}`,
|
|
6946
7327
|
default: true
|
|
6947
7328
|
}]);
|
|
6948
7329
|
if (!confirm) {
|
|
6949
|
-
console.log(
|
|
7330
|
+
console.log(chalk35.dim(` ${ko.nlp.menuHint}`));
|
|
6950
7331
|
return;
|
|
6951
7332
|
}
|
|
6952
7333
|
}
|
|
@@ -6955,7 +7336,7 @@ async function runNaturalLanguageRoute(input) {
|
|
|
6955
7336
|
if (riskAction) {
|
|
6956
7337
|
await runGuarded(
|
|
6957
7338
|
riskAction,
|
|
6958
|
-
{ channel: "nl", approved: false, log: (m) => console.log(
|
|
7339
|
+
{ channel: "nl", approved: false, log: (m) => console.log(chalk35.yellow(` ${m}`)) },
|
|
6959
7340
|
() => dispatchNlpRoute(route, input)
|
|
6960
7341
|
);
|
|
6961
7342
|
return;
|
|
@@ -6964,80 +7345,80 @@ async function runNaturalLanguageRoute(input) {
|
|
|
6964
7345
|
}
|
|
6965
7346
|
|
|
6966
7347
|
// src/commands/agent.ts
|
|
6967
|
-
import
|
|
7348
|
+
import chalk36 from "chalk";
|
|
6968
7349
|
function activeGoalId() {
|
|
6969
7350
|
const goals = listGoals("goals");
|
|
6970
7351
|
const id = selectActiveId(goals);
|
|
6971
7352
|
return id ?? void 0;
|
|
6972
7353
|
}
|
|
6973
7354
|
async function blocker(description) {
|
|
6974
|
-
console.log(
|
|
7355
|
+
console.log(chalk36.bold(`
|
|
6975
7356
|
${ko.agent.blockerTitle}
|
|
6976
7357
|
`));
|
|
6977
7358
|
if (!description || !description.trim()) {
|
|
6978
|
-
console.log(
|
|
6979
|
-
console.log(
|
|
7359
|
+
console.log(chalk36.red(" \u274C \uBE14\uB85C\uCEE4 \uC124\uBA85\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694."));
|
|
7360
|
+
console.log(chalk36.dim(' \uC608: vhk blocker "tsc \uC5D0\uB7EC \u2014 simple-git \uD0C0\uC785 \uD638\uD658"'));
|
|
6980
7361
|
process.exitCode = 1;
|
|
6981
7362
|
return;
|
|
6982
7363
|
}
|
|
6983
7364
|
const goalId = activeGoalId();
|
|
6984
7365
|
const r = appendBlocker(description, goalId);
|
|
6985
|
-
console.log(
|
|
7366
|
+
console.log(chalk36.green(` \u2705 blocker \uAE30\uB85D (\uD604\uC7AC \uD65C\uC131 ${r.count}\uAC74)`));
|
|
6986
7367
|
if (r.hardStopTripped) {
|
|
6987
|
-
console.log(
|
|
6988
|
-
console.log(
|
|
7368
|
+
console.log(chalk36.red.bold(" \u{1F6D1} HARD_STOP \uC790\uB3D9 \uC0DD\uC131 \u2014 \uBAA8\uB4E0 \uC790\uB3D9\uD654 \uC911\uB2E8."));
|
|
7369
|
+
console.log(chalk36.yellow(" \uC0AC\uB78C \uAC80\uD1A0 \uD6C4 `vhk resume --confirm` \uC73C\uB85C\uB9CC \uD574\uC81C."));
|
|
6989
7370
|
process.exitCode = 2;
|
|
6990
7371
|
}
|
|
6991
7372
|
}
|
|
6992
7373
|
async function learn(lesson) {
|
|
6993
|
-
console.log(
|
|
7374
|
+
console.log(chalk36.bold(`
|
|
6994
7375
|
${ko.agent.learnTitle}
|
|
6995
7376
|
`));
|
|
6996
7377
|
if (!lesson || !lesson.trim()) {
|
|
6997
|
-
console.log(
|
|
6998
|
-
console.log(
|
|
7378
|
+
console.log(chalk36.red(" \u274C \uAD50\uD6C8 \uB0B4\uC6A9\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694."));
|
|
7379
|
+
console.log(chalk36.dim(' \uC608: vhk learn "PowerShell \uC5D0\uC11C\uB294 ; \uC0AC\uC6A9 (&& \uBBF8\uC9C0\uC6D0)"'));
|
|
6999
7380
|
process.exitCode = 1;
|
|
7000
7381
|
return;
|
|
7001
7382
|
}
|
|
7002
7383
|
const goalId = activeGoalId();
|
|
7003
7384
|
const entry = recordLesson(process.cwd(), lesson, goalId);
|
|
7004
7385
|
if (!entry) {
|
|
7005
|
-
console.log(
|
|
7386
|
+
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."));
|
|
7006
7387
|
process.exitCode = 1;
|
|
7007
7388
|
return;
|
|
7008
7389
|
}
|
|
7009
|
-
console.log(
|
|
7010
|
-
console.log(
|
|
7390
|
+
console.log(chalk36.green(` \u2705 \uAD50\uD6C8 \uAE30\uB85D \u2192 memory failures.lesson (${entry.id})`));
|
|
7391
|
+
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."));
|
|
7011
7392
|
}
|
|
7012
7393
|
async function resume(opts = {}) {
|
|
7013
|
-
console.log(
|
|
7394
|
+
console.log(chalk36.bold(`
|
|
7014
7395
|
${ko.agent.resumeTitle}
|
|
7015
7396
|
`));
|
|
7016
7397
|
if (!isHardStopActive()) {
|
|
7017
|
-
console.log(
|
|
7398
|
+
console.log(chalk36.dim(" HARD_STOP \uD65C\uC131 \uC544\uB2D8 \u2014 \uD560 \uC77C \uC5C6\uC74C."));
|
|
7018
7399
|
return;
|
|
7019
7400
|
}
|
|
7020
7401
|
const reason = readHardStopReason();
|
|
7021
7402
|
if (reason) {
|
|
7022
|
-
console.log(
|
|
7023
|
-
console.log(
|
|
7403
|
+
console.log(chalk36.yellow(" \u{1F4CB} HARD_STOP \uC0AC\uC720:"));
|
|
7404
|
+
console.log(chalk36.dim(` ${reason.split("\n").join("\n ")}`));
|
|
7024
7405
|
console.log("");
|
|
7025
7406
|
}
|
|
7026
7407
|
if (!opts.confirm) {
|
|
7027
7408
|
console.log(
|
|
7028
|
-
|
|
7409
|
+
chalk36.red(
|
|
7029
7410
|
" \u274C --confirm \uD50C\uB798\uADF8 \uC5C6\uC774\uB294 \uD574\uC81C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 (\uC790\uB3D9 \uD638\uCD9C \uAE08\uC9C0)."
|
|
7030
7411
|
)
|
|
7031
7412
|
);
|
|
7032
|
-
console.log(
|
|
7413
|
+
console.log(chalk36.yellow(" \uC0AC\uC720\uB97C \uD655\uC778\uD55C \uD6C4 \uB2E4\uC2DC: vhk resume --confirm"));
|
|
7033
7414
|
process.exitCode = 1;
|
|
7034
7415
|
return;
|
|
7035
7416
|
}
|
|
7036
7417
|
const removed = clearHardStop();
|
|
7037
7418
|
if (removed) {
|
|
7038
|
-
console.log(
|
|
7419
|
+
console.log(chalk36.green(" \u2705 HARD_STOP \uD574\uC81C. \uC790\uB3D9\uD654 \uC7AC\uAC1C \uAC00\uB2A5."));
|
|
7039
7420
|
} else {
|
|
7040
|
-
console.log(
|
|
7421
|
+
console.log(chalk36.dim(" \uD30C\uC77C\uC774 \uC774\uBBF8 \uC5C6\uC74C \u2014 no-op."));
|
|
7041
7422
|
}
|
|
7042
7423
|
}
|
|
7043
7424
|
|
|
@@ -7050,7 +7431,7 @@ async function guardCli(action, approved, run) {
|
|
|
7050
7431
|
channel: "cli",
|
|
7051
7432
|
approved,
|
|
7052
7433
|
confirm: async () => {
|
|
7053
|
-
const { ok } = await
|
|
7434
|
+
const { ok } = await inquirer15.prompt([{
|
|
7054
7435
|
type: "confirm",
|
|
7055
7436
|
name: "ok",
|
|
7056
7437
|
message: `\u26A0\uFE0F \uC704\uD5D8 \uC791\uC5C5(${action})\uC744 \uC2E4\uD589\uD560\uAE4C\uC694?`,
|
|
@@ -7058,7 +7439,7 @@ async function guardCli(action, approved, run) {
|
|
|
7058
7439
|
}]);
|
|
7059
7440
|
return ok;
|
|
7060
7441
|
},
|
|
7061
|
-
log: (m) => console.log(
|
|
7442
|
+
log: (m) => console.log(chalk37.yellow(` ${m}`))
|
|
7062
7443
|
},
|
|
7063
7444
|
run
|
|
7064
7445
|
);
|
|
@@ -7071,7 +7452,7 @@ async function guardCliDefer(action, approved, run) {
|
|
|
7071
7452
|
approved,
|
|
7072
7453
|
// TTY 면 통과(명령이 자체 확인), 비대화형은 confirm 불가 → 가드가 차단.
|
|
7073
7454
|
confirm: async () => !!process.stdout.isTTY,
|
|
7074
|
-
log: (m) => console.log(
|
|
7455
|
+
log: (m) => console.log(chalk37.yellow(` ${m}`))
|
|
7075
7456
|
},
|
|
7076
7457
|
run
|
|
7077
7458
|
);
|
|
@@ -7115,7 +7496,8 @@ var KO_ALIASES = {
|
|
|
7115
7496
|
blocker: "\uBE14\uB85C\uCEE4",
|
|
7116
7497
|
learn: "\uAD50\uD6C8",
|
|
7117
7498
|
resume: "\uC7AC\uAC1C",
|
|
7118
|
-
pattern: "\uD328\uD134"
|
|
7499
|
+
pattern: "\uD328\uD134",
|
|
7500
|
+
evolve: "\uC9C4\uD654"
|
|
7119
7501
|
};
|
|
7120
7502
|
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());
|
|
7121
7503
|
program.configureHelp({
|
|
@@ -7327,6 +7709,24 @@ patternCmd.command("list").alias("\uBAA9\uB85D").option("--kind <kind>", "avoid|
|
|
|
7327
7709
|
patternCmd.command("dismiss <id>").alias("\uBCF4\uAD00").description("\uC624\uD0D0 \uD328\uD134 dismiss (\u2192archived, \uC7AC\uC81C\uC548 \uC548 \uB428)").action(async (id) => {
|
|
7328
7710
|
await patternDismiss(id);
|
|
7329
7711
|
});
|
|
7712
|
+
var evolveCmd = program.command("evolve").alias("\uC9C4\uD654").description("\uD328\uD134 \u2192 \uB8F0 \uD6C4\uBCF4 \uC81C\uC548\xB7\uBC18\uC601\xB7undo (Evolution Loop \uB3C4\uBBF8\uB178 4) \u2014 apply/undo\uB294 TTY \uD544\uC218").action(async () => {
|
|
7713
|
+
await evolveList();
|
|
7714
|
+
});
|
|
7715
|
+
evolveCmd.command("suggest").alias("\uC81C\uC548").option("--json", "JSON \uCD9C\uB825 (CI/MCP\uC6A9)").description("active avoid \uD328\uD134 \u2192 \uB8F0 \uCD08\uC548 \uD6C4\uBCF4 \uC0DD\uC131\xB7\uD050 \uC801\uC7AC").action(async (opts) => {
|
|
7716
|
+
await evolveSuggest(opts);
|
|
7717
|
+
});
|
|
7718
|
+
evolveCmd.command("list").alias("\uBAA9\uB85D").option("--status <status>", "pending|rejected|applied \uD544\uD130").option("--json", "JSON \uCD9C\uB825 (CI/MCP\uC6A9)").description("\uC9C4\uD654 \uD6C4\uBCF4 \uBAA9\uB85D").action(async (opts) => {
|
|
7719
|
+
await evolveList(opts);
|
|
7720
|
+
});
|
|
7721
|
+
evolveCmd.command("apply <id>").alias("\uBC18\uC601").description("\uD6C4\uBCF4 TTY \uD655\uC778 \u2192 RULES.md append \u2192 sync \uC7AC\uC0DD\uC131 (\uB300\uD654\uD615 \uD544\uC218)").action(async (id) => {
|
|
7722
|
+
await evolveApply(id);
|
|
7723
|
+
});
|
|
7724
|
+
evolveCmd.command("reject <id>").alias("\uAE30\uAC01").description("\uD6C4\uBCF4 \uAE30\uAC01 (\uC7AC\uC81C\uC548 \uC5B5\uC81C)").action(async (id) => {
|
|
7725
|
+
await evolveReject(id);
|
|
7726
|
+
});
|
|
7727
|
+
evolveCmd.command("undo").alias("\uB418\uB3CC\uB9AC\uAE30").description("\uCD5C\uADFC apply 1\uAC74 \uB418\uB3CC\uB9AC\uAE30(.bak \uBCF5\uC6D0 + sync \u2014 \uB300\uD654\uD615 \uD544\uC218)").action(async () => {
|
|
7728
|
+
await evolveUndo();
|
|
7729
|
+
});
|
|
7330
7730
|
program.on("command:*", async (operands) => {
|
|
7331
7731
|
const unknown = operands[0] ?? "";
|
|
7332
7732
|
const rest = operands.slice(1);
|
|
@@ -7335,7 +7735,7 @@ program.on("command:*", async (operands) => {
|
|
|
7335
7735
|
});
|
|
7336
7736
|
program.action(async () => {
|
|
7337
7737
|
console.log("\n\u{1F3AF} VHK \u2014 \uBC14\uC774\uBE0C\uCF54\uB529 \uD504\uB85C\uC81D\uD2B8 \uCF54\uCE58\n");
|
|
7338
|
-
const { choice } = await
|
|
7738
|
+
const { choice } = await inquirer15.prompt([{
|
|
7339
7739
|
type: "list",
|
|
7340
7740
|
name: "choice",
|
|
7341
7741
|
message: "\uBB58 \uB3C4\uC640\uB4DC\uB9B4\uAE4C\uC694?",
|
|
@@ -7399,9 +7799,9 @@ if (isMainModule) {
|
|
|
7399
7799
|
}
|
|
7400
7800
|
} catch (err) {
|
|
7401
7801
|
if (isPromptAbortError(err)) {
|
|
7402
|
-
console.error(
|
|
7802
|
+
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)"));
|
|
7403
7803
|
} else {
|
|
7404
|
-
console.error(
|
|
7804
|
+
console.error(chalk37.red(`
|
|
7405
7805
|
\u274C ${err instanceof Error ? err.message : String(err)}`));
|
|
7406
7806
|
}
|
|
7407
7807
|
process.exitCode = 1;
|
package/dist/mcp/index.js
CHANGED
package/package.json
CHANGED