@byh3071/vhk 1.6.3 → 1.6.5
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-53RJHPP6.js → chunk-EJTVXWUZ.js} +1 -0
- package/dist/index.js +100 -75
- package/dist/mcp/index.js +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -35,9 +35,10 @@ import {
|
|
|
35
35
|
safeExecFile,
|
|
36
36
|
scanProjectForSecrets,
|
|
37
37
|
startMcpServer,
|
|
38
|
+
stripBom,
|
|
38
39
|
sync,
|
|
39
40
|
t
|
|
40
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-EJTVXWUZ.js";
|
|
41
42
|
|
|
42
43
|
// src/index.ts
|
|
43
44
|
import { Command, Help } from "commander";
|
|
@@ -504,7 +505,32 @@ import inquirer12 from "inquirer";
|
|
|
504
505
|
|
|
505
506
|
// src/commands/gate.ts
|
|
506
507
|
import inquirer from "inquirer";
|
|
508
|
+
import chalk2 from "chalk";
|
|
509
|
+
|
|
510
|
+
// src/lib/interactive.ts
|
|
507
511
|
import chalk from "chalk";
|
|
512
|
+
function isInteractive(opts) {
|
|
513
|
+
if (opts?.yes) return false;
|
|
514
|
+
if (process.env.VHK_FORCE_INTERACTIVE === "1") return true;
|
|
515
|
+
return !!process.stdin.isTTY;
|
|
516
|
+
}
|
|
517
|
+
async function promptOrDefault(ask, fallback, opts) {
|
|
518
|
+
if (!isInteractive(opts)) return fallback;
|
|
519
|
+
return await ask();
|
|
520
|
+
}
|
|
521
|
+
function ensureInteractive(hint = "") {
|
|
522
|
+
if (isInteractive()) return true;
|
|
523
|
+
console.error(chalk.yellow(" \u26A0\uFE0F \uC774 \uBA85\uB839\uC740 \uB300\uD654\uD615 \uC785\uB825\uC774 \uD544\uC694\uD569\uB2C8\uB2E4 \u2014 \uBE44-TTY/\uD30C\uC774\uD504 \uD658\uACBD\uC5D0\uC11C\uB294 \uC2E4\uD589\uD560 \uC218 \uC5C6\uC5B4\uC694."));
|
|
524
|
+
if (hint) console.error(chalk.dim(` ${hint}`));
|
|
525
|
+
process.exitCode = 1;
|
|
526
|
+
return false;
|
|
527
|
+
}
|
|
528
|
+
function isPromptAbortError(err) {
|
|
529
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
530
|
+
return /ERR_USE_AFTER_CLOSE|force closed|ExitPromptError|readline was closed|User force closed/i.test(msg);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// src/commands/gate.ts
|
|
508
534
|
var GATE_QUESTIONS = [
|
|
509
535
|
{ id: 1, stage: "\uBB38\uC81C \uC815\uC758", question: "\uC774 \uC544\uC774\uB514\uC5B4\uAC00 \uD574\uACB0\uD558\uB294 \uBB38\uC81C\uB97C \uD55C \uBB38\uC7A5\uC73C\uB85C \uB9D0\uD574\uBCF4\uC138\uC694.", failIf: "\uD55C \uBB38\uC7A5 \uBD88\uAC00 \u2192 \uBBF8\uC131\uC219", quick: true },
|
|
510
536
|
{ id: 2, stage: "\uD575\uC2EC \uAE30\uB2A5", question: "\uB531 1\uAC1C \uAE30\uB2A5\uB9CC \uACE0\uB974\uBA74?", failIf: "2\uAC1C \uC774\uC0C1 \u2192 \uBC94\uC704 \uCD08\uACFC", quick: true },
|
|
@@ -526,7 +552,8 @@ function judgeGate(failCount, holdCount) {
|
|
|
526
552
|
return "DROP";
|
|
527
553
|
}
|
|
528
554
|
async function gate() {
|
|
529
|
-
|
|
555
|
+
if (!ensureInteractive("\uC544\uC774\uB514\uC5B4 \uAC80\uC99D\uC740 \uB300\uD654\uD615 \uC9C8\uBB38\uC774 \uD544\uC694\uD569\uB2C8\uB2E4. \uD130\uBBF8\uB110(PowerShell \uB4F1)\uC5D0\uC11C \uC9C1\uC811 \uC2E4\uD589\uD558\uC138\uC694. Git Bash \uBA74 VHK_FORCE_INTERACTIVE=1.")) return;
|
|
556
|
+
console.log(chalk2.bold(`
|
|
530
557
|
${ko.gate.title}
|
|
531
558
|
`));
|
|
532
559
|
const { mode: mode2 } = await inquirer.prompt([{
|
|
@@ -545,33 +572,33 @@ ${ko.gate.title}
|
|
|
545
572
|
name: "source",
|
|
546
573
|
message: ko.gate.skipSourcePrompt
|
|
547
574
|
}]);
|
|
548
|
-
console.log(
|
|
575
|
+
console.log(chalk2.green.bold(`
|
|
549
576
|
${ko.gate.skipGo}`));
|
|
550
|
-
console.log(
|
|
577
|
+
console.log(chalk2.dim(ko.gate.skipSourceLabel(source)));
|
|
551
578
|
return;
|
|
552
579
|
}
|
|
553
580
|
const questions = mode2 === "quick" ? GATE_QUESTIONS.filter((q) => q.quick) : GATE_QUESTIONS;
|
|
554
581
|
const total = questions.length;
|
|
555
582
|
const header = mode2 === "quick" ? ko.gate.quickHeader : ko.gate.fullHeader;
|
|
556
|
-
console.log(
|
|
583
|
+
console.log(chalk2.dim(`
|
|
557
584
|
${header} ${ko.gate.modeCountSuffix(total)}
|
|
558
585
|
`));
|
|
559
|
-
console.log(
|
|
586
|
+
console.log(chalk2.dim(`
|
|
560
587
|
${ko.gate.welcome}
|
|
561
588
|
`));
|
|
562
|
-
console.log(
|
|
589
|
+
console.log(chalk2.dim(` ${ko.gate.ideaHint}`));
|
|
563
590
|
const { idea } = await inquirer.prompt([
|
|
564
591
|
{ type: "input", name: "idea", message: ko.gate.idea }
|
|
565
592
|
]);
|
|
566
|
-
console.log(
|
|
593
|
+
console.log(chalk2.dim(` ${ko.gate.painPointHint}`));
|
|
567
594
|
const { painPoint } = await inquirer.prompt([
|
|
568
595
|
{ type: "input", name: "painPoint", message: ko.gate.painPoint }
|
|
569
596
|
]);
|
|
570
|
-
console.log(
|
|
597
|
+
console.log(chalk2.dim(` ${ko.gate.edgeHint}`));
|
|
571
598
|
const { edge } = await inquirer.prompt([
|
|
572
599
|
{ type: "input", name: "edge", message: ko.gate.edge }
|
|
573
600
|
]);
|
|
574
|
-
console.log(
|
|
601
|
+
console.log(chalk2.dim(`
|
|
575
602
|
${ko.gate.checklistStart}
|
|
576
603
|
`));
|
|
577
604
|
let failCount = 0;
|
|
@@ -579,7 +606,7 @@ ${ko.gate.checklistStart}
|
|
|
579
606
|
const results = [];
|
|
580
607
|
for (let i = 0; i < questions.length; i++) {
|
|
581
608
|
const q = questions[i];
|
|
582
|
-
if (q.hint) console.log(
|
|
609
|
+
if (q.hint) console.log(chalk2.dim(`${ko.gate.hintPrefix} ${q.hint}`));
|
|
583
610
|
const { answer } = await inquirer.prompt([{
|
|
584
611
|
type: "input",
|
|
585
612
|
name: "answer",
|
|
@@ -598,22 +625,22 @@ ${ko.gate.checklistStart}
|
|
|
598
625
|
if (status2 === "fail") failCount++;
|
|
599
626
|
if (status2 === "hold") holdCount++;
|
|
600
627
|
results.push({ id: q.id, stage: q.stage, status: status2, answer });
|
|
601
|
-
const icon = status2 === "pass" ?
|
|
628
|
+
const icon = status2 === "pass" ? chalk2.green(ko.gate.statusPassLine) : status2 === "hold" ? chalk2.yellow(ko.gate.statusHoldLine) : chalk2.red(ko.gate.statusFailLine);
|
|
602
629
|
console.log(icon);
|
|
603
630
|
}
|
|
604
|
-
console.log(
|
|
631
|
+
console.log(chalk2.bold(`
|
|
605
632
|
${ko.gate.verdictTitle}
|
|
606
633
|
`));
|
|
607
|
-
console.log(`${ko.gate.ideaLabel} ${
|
|
634
|
+
console.log(`${ko.gate.ideaLabel} ${chalk2.cyan(idea)}`);
|
|
608
635
|
console.log(`${ko.gate.painPointLabel} ${painPoint}`);
|
|
609
636
|
console.log(`${ko.gate.edgeLabel} ${edge}`);
|
|
610
637
|
console.log(`${ko.gate.countLine(failCount, holdCount, total)}
|
|
611
638
|
`);
|
|
612
639
|
const verdict = judgeGate(failCount, holdCount);
|
|
613
640
|
if (verdict === "GO") {
|
|
614
|
-
console.log(
|
|
641
|
+
console.log(chalk2.green.bold(ko.gate.go));
|
|
615
642
|
if (holdCount > 0) {
|
|
616
|
-
console.log(
|
|
643
|
+
console.log(chalk2.yellow(ko.gate.holdRemainHint));
|
|
617
644
|
}
|
|
618
645
|
printNextStep({
|
|
619
646
|
message: "\uC544\uC774\uB514\uC5B4 \uD1B5\uACFC! \uC774\uC81C \uD504\uB85C\uC81D\uD2B8\uB97C \uB9CC\uB4E4\uC5B4\uBCF4\uC138\uC694.",
|
|
@@ -621,20 +648,20 @@ ${ko.gate.verdictTitle}
|
|
|
621
648
|
cursorHint: "\uD504\uB85C\uC81D\uD2B8 \uB9CC\uB4E4\uC5B4\uC918"
|
|
622
649
|
});
|
|
623
650
|
} else if (verdict === "REFINE") {
|
|
624
|
-
console.log(
|
|
651
|
+
console.log(chalk2.yellow.bold(ko.gate.refine));
|
|
625
652
|
printNextStep({
|
|
626
653
|
message: "\uC870\uAE08 \uB354 \uB2E4\uB4EC\uC740 \uD6C4 \uB2E4\uC2DC \uAC80\uC99D\uD574\uBCF4\uC138\uC694.",
|
|
627
654
|
command: "vhk \uAC80\uC99D",
|
|
628
655
|
cursorHint: "\uC544\uC774\uB514\uC5B4 \uB2E4\uC2DC \uAC80\uC99D\uD574\uC918"
|
|
629
656
|
});
|
|
630
657
|
} else {
|
|
631
|
-
console.log(
|
|
658
|
+
console.log(chalk2.red.bold(ko.gate.drop));
|
|
632
659
|
}
|
|
633
660
|
}
|
|
634
661
|
|
|
635
662
|
// src/commands/init.ts
|
|
636
663
|
import inquirer2 from "inquirer";
|
|
637
|
-
import
|
|
664
|
+
import chalk4 from "chalk";
|
|
638
665
|
import fs2 from "fs";
|
|
639
666
|
import path2 from "path";
|
|
640
667
|
|
|
@@ -956,13 +983,13 @@ function VHK_CONTEXT_SEED(name, type, stack) {
|
|
|
956
983
|
}
|
|
957
984
|
|
|
958
985
|
// src/utils/logger.ts
|
|
959
|
-
import
|
|
986
|
+
import chalk3 from "chalk";
|
|
960
987
|
var log = {
|
|
961
|
-
success: (msg) => console.log(
|
|
962
|
-
error: (msg) => console.log(
|
|
963
|
-
warn: (msg) => console.log(
|
|
964
|
-
info: (msg) => console.log(
|
|
965
|
-
step: (msg) => console.log(
|
|
988
|
+
success: (msg) => console.log(chalk3.green(`\u2705 ${msg}`)),
|
|
989
|
+
error: (msg) => console.log(chalk3.red(`\u274C ${msg}`)),
|
|
990
|
+
warn: (msg) => console.log(chalk3.yellow(`\u26A0\uFE0F ${msg}`)),
|
|
991
|
+
info: (msg) => console.log(chalk3.blue(`\u2139\uFE0F ${msg}`)),
|
|
992
|
+
step: (msg) => console.log(chalk3.bold(`
|
|
966
993
|
\u25B8 ${msg}`))
|
|
967
994
|
};
|
|
968
995
|
|
|
@@ -1180,12 +1207,9 @@ function resolveType(type) {
|
|
|
1180
1207
|
}
|
|
1181
1208
|
return type;
|
|
1182
1209
|
}
|
|
1183
|
-
function isNonInteractive(options) {
|
|
1184
|
-
return Boolean(options.yes) || !process.stdin.isTTY || !process.stdout.isTTY;
|
|
1185
|
-
}
|
|
1186
1210
|
var DEFAULT_TYPE = PROJECT_TYPES[0].value;
|
|
1187
1211
|
async function collectAnswers(options, defaults = {}) {
|
|
1188
|
-
const noninteractive =
|
|
1212
|
+
const noninteractive = !isInteractive(options);
|
|
1189
1213
|
const prompts = [];
|
|
1190
1214
|
if (!noninteractive) {
|
|
1191
1215
|
if (!options.name && !defaults.name) {
|
|
@@ -1208,11 +1232,11 @@ async function collectAnswers(options, defaults = {}) {
|
|
|
1208
1232
|
async function init(options = {}) {
|
|
1209
1233
|
const skipGate = Boolean(options.skipGate || options.fromNotion);
|
|
1210
1234
|
if (skipGate) {
|
|
1211
|
-
console.log(
|
|
1235
|
+
console.log(chalk4.dim(`
|
|
1212
1236
|
${ko.init.skipGate}
|
|
1213
1237
|
`));
|
|
1214
1238
|
}
|
|
1215
|
-
console.log(
|
|
1239
|
+
console.log(chalk4.bold(`
|
|
1216
1240
|
${ko.init.title}
|
|
1217
1241
|
`));
|
|
1218
1242
|
printSecurityWarnings();
|
|
@@ -1238,11 +1262,11 @@ ${ko.init.title}
|
|
|
1238
1262
|
}
|
|
1239
1263
|
const detected = detectProjectStack(process.cwd());
|
|
1240
1264
|
const stack = detected ?? STACK_PRESETS[answers.type];
|
|
1241
|
-
if (detected) console.log(
|
|
1242
|
-
console.log(
|
|
1265
|
+
if (detected) console.log(chalk4.dim(" \u{1F50E} package.json \uC758\uC874\uC131\uC5D0\uC11C \uC2E4\uC81C \uC2A4\uD0DD \uAC10\uC9C0"));
|
|
1266
|
+
console.log(chalk4.dim(`
|
|
1243
1267
|
${ko.init.recommendedStack} ${stack.join(" + ")}
|
|
1244
1268
|
`));
|
|
1245
|
-
if (
|
|
1269
|
+
if (isInteractive(options)) {
|
|
1246
1270
|
const { confirmStack } = await inquirer2.prompt([{
|
|
1247
1271
|
type: "confirm",
|
|
1248
1272
|
name: "confirmStack",
|
|
@@ -1256,7 +1280,7 @@ ${ko.init.recommendedStack} ${stack.join(" + ")}
|
|
|
1256
1280
|
}
|
|
1257
1281
|
const cwd = process.cwd();
|
|
1258
1282
|
let adoptedRules = null;
|
|
1259
|
-
if (
|
|
1283
|
+
if (isInteractive(options) && !options.fromNotion) {
|
|
1260
1284
|
const existingRules = detectExistingRuleFiles(cwd);
|
|
1261
1285
|
if (existingRules.length > 0) {
|
|
1262
1286
|
const { adopt } = await inquirer2.prompt([{
|
|
@@ -1270,7 +1294,7 @@ ${ko.init.recommendedStack} ${stack.join(" + ")}
|
|
|
1270
1294
|
}]);
|
|
1271
1295
|
if (adopt) {
|
|
1272
1296
|
adoptedRules = buildAdoptedRules(existingRules, answers.name);
|
|
1273
|
-
console.log(
|
|
1297
|
+
console.log(chalk4.dim(` ${ko.init.adoptPreview(existingRules.length)}`));
|
|
1274
1298
|
}
|
|
1275
1299
|
}
|
|
1276
1300
|
}
|
|
@@ -1280,7 +1304,7 @@ ${ko.init.recommendedStack} ${stack.join(" + ")}
|
|
|
1280
1304
|
for (const [filePath, content] of Object.entries(files)) {
|
|
1281
1305
|
const fullPath = path2.join(cwd, filePath);
|
|
1282
1306
|
if (fileExists(fullPath)) {
|
|
1283
|
-
const overwrite =
|
|
1307
|
+
const overwrite = !isInteractive(options) ? false : (await inquirer2.prompt([{
|
|
1284
1308
|
type: "confirm",
|
|
1285
1309
|
name: "overwrite",
|
|
1286
1310
|
message: ko.init.overwrite(filePath),
|
|
@@ -1294,22 +1318,22 @@ ${ko.init.recommendedStack} ${stack.join(" + ")}
|
|
|
1294
1318
|
writeFile(fullPath, content);
|
|
1295
1319
|
log.success(filePath);
|
|
1296
1320
|
}
|
|
1297
|
-
await writeInitExtras(cwd,
|
|
1298
|
-
console.log(
|
|
1321
|
+
await writeInitExtras(cwd, !isInteractive(options));
|
|
1322
|
+
console.log(chalk4.bold.green(`
|
|
1299
1323
|
${ko.init.done}`));
|
|
1300
|
-
console.log(
|
|
1324
|
+
console.log(chalk4.dim(`
|
|
1301
1325
|
${ko.init.nextSteps}`));
|
|
1302
1326
|
if (options.fromNotion) {
|
|
1303
1327
|
console.log(` 1. ${ko.init.notionReviewHint}`);
|
|
1304
1328
|
console.log(` 2. ${ko.init.gitHintLabel}`);
|
|
1305
|
-
console.log(` ${
|
|
1329
|
+
console.log(` ${chalk4.cyan(ko.init.gitHintCommand)}`);
|
|
1306
1330
|
console.log(` 3. ${ko.init.startDev}
|
|
1307
1331
|
`);
|
|
1308
1332
|
} else {
|
|
1309
1333
|
console.log(` 1. ${ko.init.fillHint}`);
|
|
1310
1334
|
console.log(` 2. ${ko.init.prdHint}`);
|
|
1311
1335
|
console.log(` 3. ${ko.init.gitHintLabel}`);
|
|
1312
|
-
console.log(` ${
|
|
1336
|
+
console.log(` ${chalk4.cyan(ko.init.gitHintCommand)}`);
|
|
1313
1337
|
console.log(` 4. ${ko.init.startDev}
|
|
1314
1338
|
`);
|
|
1315
1339
|
}
|
|
@@ -1626,20 +1650,6 @@ function createAdrFile(cwd, title, context2, decision, consequences) {
|
|
|
1626
1650
|
return filePath;
|
|
1627
1651
|
}
|
|
1628
1652
|
|
|
1629
|
-
// src/lib/interactive.ts
|
|
1630
|
-
import chalk4 from "chalk";
|
|
1631
|
-
function ensureInteractive(hint = "") {
|
|
1632
|
-
if (process.stdin.isTTY) return true;
|
|
1633
|
-
console.error(chalk4.yellow(" \u26A0\uFE0F \uC774 \uBA85\uB839\uC740 \uB300\uD654\uD615 \uC785\uB825\uC774 \uD544\uC694\uD569\uB2C8\uB2E4 \u2014 \uBE44-TTY/\uD30C\uC774\uD504 \uD658\uACBD\uC5D0\uC11C\uB294 \uC2E4\uD589\uD560 \uC218 \uC5C6\uC5B4\uC694."));
|
|
1634
|
-
if (hint) console.error(chalk4.dim(` ${hint}`));
|
|
1635
|
-
process.exitCode = 1;
|
|
1636
|
-
return false;
|
|
1637
|
-
}
|
|
1638
|
-
function isPromptAbortError(err) {
|
|
1639
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1640
|
-
return /ERR_USE_AFTER_CLOSE|force closed|ExitPromptError|readline was closed|User force closed/i.test(msg);
|
|
1641
|
-
}
|
|
1642
|
-
|
|
1643
1653
|
// src/lib/hard-stop-guard.ts
|
|
1644
1654
|
import chalk5 from "chalk";
|
|
1645
1655
|
|
|
@@ -2178,8 +2188,9 @@ import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync,
|
|
|
2178
2188
|
import { join as join3 } from "path";
|
|
2179
2189
|
var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
|
|
2180
2190
|
function parseFrontmatter(content) {
|
|
2181
|
-
const
|
|
2182
|
-
|
|
2191
|
+
const normalized = stripBom(content);
|
|
2192
|
+
const m = normalized.match(FRONTMATTER_RE);
|
|
2193
|
+
if (!m) return { frontmatter: {}, body: normalized };
|
|
2183
2194
|
const fm = parseSimpleYaml(m[1]);
|
|
2184
2195
|
const body = (m[2] ?? "").replace(/^\r?\n+/, "");
|
|
2185
2196
|
return { frontmatter: fm, body };
|
|
@@ -3236,12 +3247,16 @@ async function save() {
|
|
|
3236
3247
|
if (severe.length > 5) {
|
|
3237
3248
|
console.log(chalk12.dim(` ... \uC678 ${severe.length - 5}\uAC74 (vhk \uBCF4\uC548 scan)`));
|
|
3238
3249
|
}
|
|
3239
|
-
const
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3250
|
+
const proceed = await promptOrDefault(
|
|
3251
|
+
async () => (await inquirer5.prompt([{
|
|
3252
|
+
type: "confirm",
|
|
3253
|
+
name: "proceed",
|
|
3254
|
+
message: t("save.secretsConfirm"),
|
|
3255
|
+
default: false
|
|
3256
|
+
}])).proceed,
|
|
3257
|
+
false
|
|
3258
|
+
// 비대화형 = 시크릿 커밋 안 함 (안전)
|
|
3259
|
+
);
|
|
3245
3260
|
if (!proceed) {
|
|
3246
3261
|
console.log(chalk12.gray(t("save.cancelled")));
|
|
3247
3262
|
return;
|
|
@@ -3259,12 +3274,15 @@ async function save() {
|
|
|
3259
3274
|
const name = line.substring(3);
|
|
3260
3275
|
console.log(` ${statusIcon(code)} ${name}`);
|
|
3261
3276
|
});
|
|
3262
|
-
const
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3277
|
+
const message = await promptOrDefault(
|
|
3278
|
+
async () => (await inquirer5.prompt([{
|
|
3279
|
+
type: "input",
|
|
3280
|
+
name: "message",
|
|
3281
|
+
message: t("save.commitMessage"),
|
|
3282
|
+
default: formatDefaultCommitMessage()
|
|
3283
|
+
}])).message,
|
|
3284
|
+
"chore: vhk save"
|
|
3285
|
+
);
|
|
3268
3286
|
const spinner = ora(t("save.saving")).start();
|
|
3269
3287
|
let didAdd = false;
|
|
3270
3288
|
try {
|
|
@@ -5393,7 +5411,8 @@ var HIGH_RISK_ACTIONS = [
|
|
|
5393
5411
|
"cloud-pull",
|
|
5394
5412
|
"resume",
|
|
5395
5413
|
"env-write",
|
|
5396
|
-
"delete"
|
|
5414
|
+
"delete",
|
|
5415
|
+
"restore"
|
|
5397
5416
|
];
|
|
5398
5417
|
var STRICT_EXTRA_ACTIONS = /* @__PURE__ */ new Set(["save", "sync"]);
|
|
5399
5418
|
var NL_GUARDED_ACTIONS = {
|
|
@@ -5404,7 +5423,8 @@ var NL_GUARDED_ACTIONS = {
|
|
|
5404
5423
|
"cloud-pull": "cloud-pull",
|
|
5405
5424
|
env: "env-write",
|
|
5406
5425
|
save: "save",
|
|
5407
|
-
sync: "sync"
|
|
5426
|
+
sync: "sync",
|
|
5427
|
+
restore: "restore"
|
|
5408
5428
|
};
|
|
5409
5429
|
function isHighRisk(action) {
|
|
5410
5430
|
return HIGH_RISK_ACTIONS.includes(action);
|
|
@@ -5426,6 +5446,11 @@ async function runGuarded(action, deps, run) {
|
|
|
5426
5446
|
return { outcome: { ran: true, guard, reason: "low-risk" }, result: await run() };
|
|
5427
5447
|
}
|
|
5428
5448
|
if (guard === "warn") {
|
|
5449
|
+
const canConfirm = deps.isTTY ?? !!process.stdin.isTTY;
|
|
5450
|
+
if (!deps.approved && !canConfirm) {
|
|
5451
|
+
log2(`\u26A0\uFE0F \uC704\uD5D8 \uC791\uC5C5(${action}) \u2014 lite \uC9C0\uB9CC \uBE44\uB300\uD654\uD615+\uBBF8\uC2B9\uC778 \u2192 \uC911\uB2E8. (--yes \uB85C \uC2B9\uC778)`);
|
|
5452
|
+
return { outcome: { ran: false, guard, reason: "lite-noninteractive-block" } };
|
|
5453
|
+
}
|
|
5429
5454
|
log2(`\u26A0\uFE0F \uC704\uD5D8 \uC791\uC5C5(${action}) \u2014 lite \uBAA8\uB4DC: \uACBD\uACE0\uB9CC \uD558\uACE0 \uC9C4\uD589\uD569\uB2C8\uB2E4.`);
|
|
5430
5455
|
return { outcome: { ran: true, guard, reason: "lite-warn" }, result: await run() };
|
|
5431
5456
|
}
|
|
@@ -5433,7 +5458,7 @@ async function runGuarded(action, deps, run) {
|
|
|
5433
5458
|
if (deps.approved === true) {
|
|
5434
5459
|
return { outcome: { ran: true, guard, reason: "approved" }, result: await run() };
|
|
5435
5460
|
}
|
|
5436
|
-
const tty = deps.isTTY ?? !!process.
|
|
5461
|
+
const tty = deps.isTTY ?? !!process.stdin.isTTY;
|
|
5437
5462
|
if (tty && deps.confirm) {
|
|
5438
5463
|
const ok = await deps.confirm();
|
|
5439
5464
|
if (ok) return { outcome: { ran: true, guard, reason: "confirmed" }, result: await run() };
|
|
@@ -5789,8 +5814,8 @@ program.command("save").alias("\uC800\uC7A5").option("--yes", "\uD655\uC778 \uC5
|
|
|
5789
5814
|
program.command("undo").alias("\uB418\uB3CC\uB9AC\uAE30").option("--yes", "\uD655\uC778 \uC5C6\uC774 \uC2E4\uD589 (\uC704\uD5D8 \uC791\uC5C5 \uBA85\uC2DC \uC2B9\uC778)").description("\uCD5C\uADFC \uCEE4\uBC0B \uB418\uB3CC\uB9AC\uAE30").action(async (opts) => {
|
|
5790
5815
|
await guardCliDefer("undo", opts?.yes === true, () => undo());
|
|
5791
5816
|
});
|
|
5792
|
-
program.command("restore").alias("\uBCF5\uC6D0").argument("[id]", "\uBCF5\uC6D0\uD560 \uBC31\uC5C5 id (\uC0DD\uB7B5 \uC2DC \uBAA9\uB85D\uC5D0\uC11C \uC120\uD0DD)").description("sync \uBC31\uC5C5 \uBCF5\uC6D0 (.vhk/backups/ \u2014 \uC5B8\uCEE4\uBC0B \uB36E\uC5B4\uC4F0\uAE30 \uBCF5\uAD6C)").action(async (id) => {
|
|
5793
|
-
await restore(id);
|
|
5817
|
+
program.command("restore").alias("\uBCF5\uC6D0").argument("[id]", "\uBCF5\uC6D0\uD560 \uBC31\uC5C5 id (\uC0DD\uB7B5 \uC2DC \uBAA9\uB85D\uC5D0\uC11C \uC120\uD0DD)").option("--yes", "\uD655\uC778 \uC5C6\uC774 \uC2E4\uD589 (\uC704\uD5D8 \uC791\uC5C5 \uBA85\uC2DC \uC2B9\uC778)").description("sync \uBC31\uC5C5 \uBCF5\uC6D0 (.vhk/backups/ \u2014 \uC5B8\uCEE4\uBC0B \uB36E\uC5B4\uC4F0\uAE30 \uBCF5\uAD6C)").action(async (id, opts) => {
|
|
5818
|
+
await guardCli("restore", opts?.yes === true, () => restore(id));
|
|
5794
5819
|
});
|
|
5795
5820
|
program.command("status").alias("\uC0C1\uD0DC").description("\uD504\uB85C\uC81D\uD2B8 \uC0C1\uD0DC \uB300\uC2DC\uBCF4\uB4DC").action(async () => {
|
|
5796
5821
|
await status();
|
package/dist/mcp/index.js
CHANGED
package/package.json
CHANGED