@byh3071/vhk 1.4.0 โ 1.5.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/README.md +22 -7
- package/dist/{chunk-3DV7AEN4.js โ chunk-4KWZANQG.js} +6 -1
- package/dist/index.js +72 -24
- package/dist/mcp/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
id: vhk-readme
|
|
3
3
|
date: 2026-05-28
|
|
4
|
-
tags: [vhk, cli, readme, v1.
|
|
4
|
+
tags: [vhk, cli, readme, v1.5.0, ga]
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# ๐ง VHK โ Vibe Harness Kit
|
|
8
8
|
|
|
9
|
-
> ๐ **v1.
|
|
9
|
+
> ๐ **v1.5.0** โ **๊ท์น์ ํ ๋ฒ๋ก CursorยทClaudeยทWindsurfยทCopilotยทAntigravity์, ๋งฅ๋ฝ์ ํด๋ผ์ฐ๋๋ก.**
|
|
10
|
+
> ๋๊ตฌยท๊ธฐ๊ธฐ๋ฅผ ์ฎ๊ฒจ๋ `vhk` ๋ช
๋ น์ผ๋ก ๊ทธ๋๋ก ๋ถ๋ฌ์ต๋๋ค. (ํฌํฐ๋น๋ฆฌํฐ)
|
|
10
11
|
>
|
|
11
12
|
> AI ์ฝ๋ฉ ์์ด์ ํธ๋ฅผ ๋ถ๋ฆฌ๋ ์ฌ๋์ ์ํ **ํ๊ตญ์ด ํ์ฌ์ดํด CLI**.
|
|
12
13
|
>
|
|
@@ -14,6 +15,20 @@ tags: [vhk, cli, readme, v1.4.0, ga]
|
|
|
14
15
|
|
|
15
16
|
๋ช
๋ น์ด๋ฅผ ์ธ์ฐ์ง ์์๋ ๋ฉ๋๋ค. `vhk`๋ง ์น๋ฉด ๋ฉ๋ด๊ฐ ๋์ค๊ณ , ํ๊ตญ์ด๋ก ๋งํด๋ ์์๋ฃ์ต๋๋ค.
|
|
16
17
|
|
|
18
|
+
## ์ VHK? โ ํฌํฐ๋น๋ฆฌํฐ
|
|
19
|
+
|
|
20
|
+
AI ์ฝ๋ฉ ๋๊ตฌ๋ ์ ๋ง๋ค ๊ท์น ํ์ผ์ด ๋ค๋ฅด๊ณ (`.cursorrules`ยท`CLAUDE.md`ยท`.windsurfrules`ยท`.github/copilot-instructions.md`ยท`.agents/rules/`โฆ), ์ปดํจํฐ๋ฅผ ๋ฐ๊พธ๋ฉด ํ๋ก์ ํธ ๋งฅ๋ฝ์ ์ฒ์๋ถํฐ ๋ค์ ๋ชจ์๋๋ค. VHK๋ ์ด ๋์ ํ ๊ณณ์์ ๊ด๋ฆฌํฉ๋๋ค.
|
|
21
|
+
|
|
22
|
+
| ๋ฌธ์ | VHK ํด๊ฒฐ | ๋ช
๋ น |
|
|
23
|
+
|------|----------|------|
|
|
24
|
+
| ๋๊ตฌ๋ง๋ค ๊ท์น ํ์ผ์ด ๋ฐ๋ก ๋
ผ๋ค | `RULES.md` ํ ๋ฒ โ CursorยทClaudeยทWindsurfยทCopilotยทAntigravity ๊ท์น ๋์ ์์ฑ | `vhk sync` |
|
|
25
|
+
| ์ปดํจํฐยทํ๊ฒฝ ๋ฐ๋๋ฉด ๋งฅ๋ฝ ์ ์ค | `.vhk/` ๋งฅ๋ฝ์ GitHub gist๋ก ๋ฐฑ์
ยท๋ณต์ | `vhk cloud push` / `pull` |
|
|
26
|
+
| ์ ํ๋ก์ ํธ ์ธํ
๋ฐ๋ณต | ์ ํ๋ณ ๋ฌธ์ยท๊ท์นยท๋งฅ๋ฝ ๋ผ๋๋ฅผ ํ ๋ฒ์ | `vhk init` |
|
|
27
|
+
|
|
28
|
+
> ๊ท์นยท๋งฅ๋ฝ์ **์๋์ด ์๋๋ผ ๋ช
๋ น์ผ๋ก** ๋๊ธฐํ๋ฉ๋๋ค(ํ ์ค์ด๋ฉด ์ถฉ๋ถ). ๊ฐ์ธ ๋ฉ๋ชจ(`memory.json`)ยท์ฐธ๊ณ ๋งํฌ(`refs.json`)๋ ํ๋ผ์ด๋ฒ์ ์ํด ๊ธฐ๋ณธ ์ ์ธ, ์ PC์ ์ฝ๋ ์์ฒด๋ `git clone` ์ผ๋ก ๋ฐ์ต๋๋ค.
|
|
29
|
+
>
|
|
30
|
+
> โน๏ธ WindsurfยทCopilotยทAntigravity ์ถ๋ ฅ ๊ฒฝ๋กยทํฌ๋งท์ ๊ฐ ๋๊ตฌ์ **๊ณต์ ๋ฌธ์ ๊ธฐ์ค**์ผ๋ก ์์ฑํฉ๋๋ค(`.windsurfrules` ยท `.github/copilot-instructions.md` ยท `.agents/rules/`). Antigravity ๋ ํ์ผ๋น 12,000์ ์ ํ์ด ์์ด ์ด๊ณผ ์ ์์ ํ๊ฒ ์ ์ญํ๊ณ ์ ์ฒด๋ `RULES.md` ์ ๋จ์ต๋๋ค.
|
|
31
|
+
|
|
17
32
|
## 3๋ถ ์์ ์์ํ๊ธฐ (Getting Started)
|
|
18
33
|
|
|
19
34
|
### 1. ์ค์น
|
|
@@ -40,12 +55,12 @@ vhk start
|
|
|
40
55
|
vhk gate # ํต 5๋ฌธํญ โ GO / ๋ค๋ฌ๊ธฐ / ๋ค๋ฅธ ์์ด๋์ด
|
|
41
56
|
```
|
|
42
57
|
|
|
43
|
-
### 3.
|
|
58
|
+
### 3. ๊ทธ ์ธ ๊ธฐ๋ฅ ํ๋์ (v1.5)
|
|
44
59
|
|
|
45
60
|
| ๊ธฐ๋ฅ | ํ ์ค ์์ฝ | ์ง์
๋ช
๋ น |
|
|
46
61
|
|------|-----------|-----------|
|
|
47
62
|
| ๐ฏ **Goals ์ฒด๊ณ** | ๋จ๊ณ๋ณ ๋ฏธ์
+ ๊ฒ์ดํธ ์คํฌ๋ฆฝํธ๋ก AI๊ฐ ๋ชฉํ๋ฅผ ์ค์ค๋ก ์ถ์ | `vhk goal init` |
|
|
48
|
-
| โถ๏ธ **์์จ ๋ฃจํ** | `goal next โ ์์
โ goal check โ goal done`. FAIL 3
|
|
63
|
+
| โถ๏ธ **์์จ ๋ฃจํ** | `goal next โ ์์
โ goal check โ goal done`. FAIL ์ `vhk blocker` ์๋ ๊ธฐ๋ก โ ๋ธ๋ก์ปค 3๊ฑด ๋์ ์ HARD_STOP ์๋ | `vhk goal next` |
|
|
49
64
|
| ๐ง **HARD_STOP ์์ ์ฅ์น** | ๋ธ๋ก์ปค 3๊ฑด ๋์ โ `.vhk/HARD_STOP` ํธ๋ฆฝ์์ด์ด. `vhk resume --confirm` ๋ง ํด์ | `vhk blocker "<์ฆ์>"` |
|
|
50
65
|
| ๐ **MCP 24 tool** | CursorยทClaude Desktop ๋ฑ์์ vhk๋ฅผ ์ฑํ
์ผ๋ก ํธ์ถ | `vhk mcp-init` |
|
|
51
66
|
| ๐ **์ปจํ
์คํธ ์์ํ** | `.vhk/context.md` + `memory.json` + `brief.md` ๋ก ์ธ์
๊ฐ ๋งฅ๋ฝ ์ ์ง | `vhk context` |
|
|
@@ -115,7 +130,7 @@ vhk ๊ธฐํ ๋๋ฌ๊ณ ๋ฐ๋ก ์์
|
|
|
115
130
|
| `vhk gate` | `๊ฒ์ฆ`, `์์ด๋์ด` | ์์ด๋์ด ๊ฒ์ฆ (ํต 5๋ฌธํญ / ํ 13๋ฌธํญ / ์คํต) |
|
|
116
131
|
| `vhk init` | `์์`, `๋ง๋ค๊ธฐ` | ํ๋ก์ ํธ ์ด๊ธฐํ + ํ๋ค์ค ์์ฑ |
|
|
117
132
|
| `vhk recap` | `์ ๋ฆฌ`, `์ค๋` | Git ๋ณ๊ฒฝ โ `docs/log/` ์ธ์
๋ก๊ทธ |
|
|
118
|
-
| `vhk sync` | `๊ท์น`, `๋ง์ถ๊ธฐ` | RULES.md โ `.cursorrules` + CLAUDE.md + `.windsurfrules` |
|
|
133
|
+
| `vhk sync` | `๊ท์น`, `๋ง์ถ๊ธฐ` | RULES.md โ `.cursorrules` + CLAUDE.md + `.windsurfrules` + `.github/copilot-instructions.md` + `.agents/rules/vhk-rules.md` (5๊ฐ) |
|
|
119
134
|
| `vhk check` | `์ ๊ฒ`, `๋ฆฐํธ` | RULES.md ๊ท์น ์๋ฐ ๊ฒ์ฌ |
|
|
120
135
|
| `vhk secure` | `๋ณด์` | ์ํฌ๋ฆฟยทํค ์ ์ถ ์ค์บ (`scan` / `์ค์บ` ๋์ผ). **CRITICAL/HIGH ๋ฐ๊ฒฌ ์ exit code 1** (CI์ฉ) |
|
|
121
136
|
| `vhk ship` | `์ถํ` | ๋ฐฐํฌ ์ฒดํฌ๋ฆฌ์คํธ + ํ๊ณ + ๋น๋ ๋ก๊ทธ |
|
|
@@ -300,10 +315,10 @@ vhk ref open 1 # 1๋ฒ ๋ ํผ๋ฐ์ค๋ฅผ ๋ธ๋ผ์ฐ์ ๋ก ์ด๊ธฐ
|
|
|
300
315
|
|
|
301
316
|
| ๊ธฐ๋ฅ | ์ค๋ช
|
|
|
302
317
|
|------|------|
|
|
303
|
-
| **MCP ์๋ฒ** | `vhk mcp` โ stdio MCP ์๋ฒ ์ฒซ ๋์
(v0.6.0 ๋น์ 8๊ฐ ๋๊ตฌ โ save/undo/status/diff/ship/doctor/check/recap). ํ์ฌ v1.
|
|
318
|
+
| **MCP ์๋ฒ** | `vhk mcp` โ stdio MCP ์๋ฒ ์ฒซ ๋์
(v0.6.0 ๋น์ 8๊ฐ ๋๊ตฌ โ save/undo/status/diff/ship/doctor/check/recap). ํ์ฌ v1.5 ๊ธฐ์ค **24๊ฐ** ๋ก ํ์ฅ โ ์ "Cursor์ MCP๋ก ์ฐ๋ํ๊ธฐ" ์น์
์ฐธ์กฐ |
|
|
304
319
|
| **mcp-init** | `vhk mcp-init` โ Cursor `.cursor/mcp.json` ์๋ ์์ฑ. ์ฌ์์ ํ ๋ฒ์ผ๋ก ์ฐ๋ ์๋ฃ |
|
|
305
320
|
| **์์ฐ์ด ๋ผ์ฐํ
ํ์ฅ** | `vhk mcp์ค์ ` โ `vhk mcp-init` ๋ณ์นญ |
|
|
306
|
-
| **๋ณด์** | MCP save ๋๊ตฌ์ shell injection ์ฐจ๋จ โ ๋ชจ๋ git ํธ์ถ์ `
|
|
321
|
+
| **๋ณด์** | MCP save ๋๊ตฌ์ shell injection ์ฐจ๋จ โ ๋ชจ๋ git ํธ์ถ์ shell ๋ฏธ๊ฒฝ์ `safeExecFile` ์ฌ์ฉ |
|
|
307
322
|
|
|
308
323
|
## v0.5.3 ํ์ด๋ผ์ดํธ
|
|
309
324
|
|
|
@@ -755,6 +755,9 @@ var ko = {
|
|
|
755
755
|
cursorrulesDone: "\u2705 .cursorrules \uB9DE\uCDA4 \uC644\uB8CC",
|
|
756
756
|
claudeDone: "\u2705 CLAUDE.md \uB9DE\uCDA4 \uC644\uB8CC",
|
|
757
757
|
windsurfDone: "\u2705 .windsurfrules \uB9DE\uCDA4 \uC644\uB8CC",
|
|
758
|
+
copilotDone: "\u2705 .github/copilot-instructions.md \uB9DE\uCDA4 \uC644\uB8CC",
|
|
759
|
+
antigravityDone: "\u2705 .agents/rules/vhk-rules.md \uB9DE\uCDA4 \uC644\uB8CC",
|
|
760
|
+
antigravityTruncated: "Antigravity 12,000\uC790 \uC81C\uD55C\uC73C\uB85C \uC77C\uBD80 \uC808\uC0AD\uB428 \u2014 \uC804\uCCB4\uB294 RULES.md \uCC38\uC870",
|
|
758
761
|
done: "\u{1F504} \uB9DE\uCD94\uAE30 \uC644\uB8CC!"
|
|
759
762
|
},
|
|
760
763
|
cloud: {
|
|
@@ -882,7 +885,9 @@ var ko = {
|
|
|
882
885
|
nextTitle: "\u27A1\uFE0F \uB2E4\uC74C Goal",
|
|
883
886
|
initTitle: "\u{1F3D7}\uFE0F goals/ \uAD6C\uC870 \uC2A4\uCE90\uD3F4\uB529",
|
|
884
887
|
checkTitle: "\u2705 Goal \uAC8C\uC774\uD2B8 \uAC80\uC99D",
|
|
885
|
-
doneTitle: "\u{1F3C1} Goal \uC644\uB8CC \uCC98\uB9AC"
|
|
888
|
+
doneTitle: "\u{1F3C1} Goal \uC644\uB8CC \uCC98\uB9AC",
|
|
889
|
+
duplicateId: (ids) => `\u26A0 \uC911\uBCF5\uB41C goal id: ${ids} \u2014 \uAC19\uC740 id \uD30C\uC77C\uC774 \uC5EC\uB7EC \uAC1C\uBA74 \uCCAB \uB9E4\uCE58\uB9CC \uC0AC\uC6A9\uB429\uB2C8\uB2E4. id \uB97C \uC720\uC77C\uD558\uAC8C \uACE0\uCE58\uC138\uC694.`,
|
|
890
|
+
notFound: (id) => `goal id ${id} \uC5C6\uC74C \u2014 vhk goal list \uB85C \uD655\uC778\uD558\uC138\uC694.`
|
|
886
891
|
},
|
|
887
892
|
agent: {
|
|
888
893
|
blockerTitle: "\u{1F6D1} Blocker \uAE30\uB85D",
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
scanProjectForSecrets,
|
|
21
21
|
startMcpServer,
|
|
22
22
|
t
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-4KWZANQG.js";
|
|
24
24
|
|
|
25
25
|
// src/index.ts
|
|
26
26
|
import { Command, Help } from "commander";
|
|
@@ -1676,12 +1676,12 @@ function parseRulesMd(content) {
|
|
|
1676
1676
|
}
|
|
1677
1677
|
return sections;
|
|
1678
1678
|
}
|
|
1679
|
-
function
|
|
1679
|
+
function buildCodingDoc(headerTitle, sections, projectName) {
|
|
1680
1680
|
const codingSections = sections.filter(
|
|
1681
1681
|
(s) => CURSORRULES_KEYS.some((k) => s.title.includes(k))
|
|
1682
1682
|
);
|
|
1683
1683
|
const lines = [
|
|
1684
|
-
`# ${projectName} \u2014
|
|
1684
|
+
`# ${projectName} \u2014 ${headerTitle}`,
|
|
1685
1685
|
"",
|
|
1686
1686
|
"> \uCF54\uB529/\uB514\uC790\uC778 \uC804\uC6A9. \uAE30\uB85D/\uC6B4\uC601 \u2192 CLAUDE.md \uCC38\uC870.",
|
|
1687
1687
|
"> \u26A1 \uC774 \uD30C\uC77C\uC740 RULES.md\uC5D0\uC11C \uC790\uB3D9 \uC0DD\uC131\uB428 (vhk sync). \uC9C1\uC811 \uC218\uC815 \uAE08\uC9C0.",
|
|
@@ -1697,26 +1697,38 @@ function toCursorrules(sections, projectName) {
|
|
|
1697
1697
|
}
|
|
1698
1698
|
return lines.join("\n");
|
|
1699
1699
|
}
|
|
1700
|
+
function toCursorrules(sections, projectName) {
|
|
1701
|
+
return buildCodingDoc("Cursor Rules", sections, projectName);
|
|
1702
|
+
}
|
|
1700
1703
|
function toWindsurfrules(sections, projectName) {
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
}
|
|
1719
|
-
|
|
1704
|
+
return buildCodingDoc("Windsurf Rules", sections, projectName);
|
|
1705
|
+
}
|
|
1706
|
+
function toCopilotInstructions(sections, projectName) {
|
|
1707
|
+
return buildCodingDoc("GitHub Copilot Instructions", sections, projectName);
|
|
1708
|
+
}
|
|
1709
|
+
var ANTIGRAVITY_CHAR_LIMIT = 12e3;
|
|
1710
|
+
var ANTIGRAVITY_TRUNCATE_MARKER = "\n\n<!-- \u26A0\uFE0F Antigravity 12,000\uC790 \uC81C\uD55C\uC73C\uB85C \uC808\uC0AD\uB428 \u2014 \uC804\uCCB4 \uADDC\uCE59\uC740 RULES.md \uCC38\uC870 -->\n";
|
|
1711
|
+
function truncateForAntigravity(content, limit = ANTIGRAVITY_CHAR_LIMIT) {
|
|
1712
|
+
if (Buffer.byteLength(content, "utf8") <= limit) return content;
|
|
1713
|
+
const SAFETY = 200;
|
|
1714
|
+
const budget = limit - Buffer.byteLength(ANTIGRAVITY_TRUNCATE_MARKER, "utf8") - SAFETY;
|
|
1715
|
+
let lo = 0;
|
|
1716
|
+
let hi = content.length;
|
|
1717
|
+
while (lo < hi) {
|
|
1718
|
+
const mid = lo + hi + 1 >> 1;
|
|
1719
|
+
if (Buffer.byteLength(content.slice(0, mid), "utf8") <= budget) lo = mid;
|
|
1720
|
+
else hi = mid - 1;
|
|
1721
|
+
}
|
|
1722
|
+
const charCut = lo;
|
|
1723
|
+
let cut = content.lastIndexOf("\n## ", charCut);
|
|
1724
|
+
if (cut < charCut * 0.5) {
|
|
1725
|
+
const nl = content.lastIndexOf("\n", charCut);
|
|
1726
|
+
cut = nl > 0 ? nl : charCut;
|
|
1727
|
+
}
|
|
1728
|
+
return content.slice(0, cut).trimEnd() + ANTIGRAVITY_TRUNCATE_MARKER;
|
|
1729
|
+
}
|
|
1730
|
+
function toAntigravityRules(sections, projectName) {
|
|
1731
|
+
return truncateForAntigravity(buildCodingDoc("Antigravity Rules", sections, projectName));
|
|
1720
1732
|
}
|
|
1721
1733
|
function toClaudeMd(sections, existing) {
|
|
1722
1734
|
const recordSections = sections.filter(
|
|
@@ -1780,9 +1792,22 @@ ${ko.sync.title}
|
|
|
1780
1792
|
const windsurfPath = path6.join(cwd, ".windsurfrules");
|
|
1781
1793
|
fs5.writeFileSync(windsurfPath, toWindsurfrules(sections, projectName), "utf-8");
|
|
1782
1794
|
console.log(chalk5.green(` ${ko.sync.windsurfDone}`));
|
|
1795
|
+
const copilotPath = path6.join(cwd, ".github", "copilot-instructions.md");
|
|
1796
|
+
fs5.mkdirSync(path6.dirname(copilotPath), { recursive: true });
|
|
1797
|
+
fs5.writeFileSync(copilotPath, toCopilotInstructions(sections, projectName), "utf-8");
|
|
1798
|
+
console.log(chalk5.green(` ${ko.sync.copilotDone}`));
|
|
1799
|
+
const antigravityPath = path6.join(cwd, ".agents", "rules", "vhk-rules.md");
|
|
1800
|
+
fs5.mkdirSync(path6.dirname(antigravityPath), { recursive: true });
|
|
1801
|
+
const antigravityDoc = toAntigravityRules(sections, projectName);
|
|
1802
|
+
fs5.writeFileSync(antigravityPath, antigravityDoc, "utf-8");
|
|
1803
|
+
console.log(chalk5.green(` ${ko.sync.antigravityDone}`));
|
|
1804
|
+
if (antigravityDoc.includes("\uC808\uC0AD\uB428")) {
|
|
1805
|
+
console.log(chalk5.yellow(` \u26A0\uFE0F ${ko.sync.antigravityTruncated}`));
|
|
1806
|
+
}
|
|
1783
1807
|
console.log(chalk5.bold.green(`
|
|
1784
1808
|
${ko.sync.done}`));
|
|
1785
|
-
console.log(chalk5.dim(" RULES.md (\uC6D0\uBCF8) \u2192 .cursorrules + CLAUDE.md + .windsurfrules
|
|
1809
|
+
console.log(chalk5.dim(" RULES.md (\uC6D0\uBCF8) \u2192 .cursorrules + CLAUDE.md + .windsurfrules"));
|
|
1810
|
+
console.log(chalk5.dim(" + .github/copilot-instructions.md + .agents/rules/vhk-rules.md (\uC790\uB3D9 \uC0DD\uC131)"));
|
|
1786
1811
|
console.log(chalk5.dim(" \uADDC\uCE59 \uBCC0\uACBD\uC740 \uD56D\uC0C1 RULES.md\uC5D0\uC11C\uB9CC \uD558\uC138\uC694."));
|
|
1787
1812
|
printNextStep({
|
|
1788
1813
|
message: "\uADDC\uCE59 \uB3D9\uAE30\uD654 \uC644\uB8CC! \uC774\uC81C Cursor\uAC00 \uC0C8 \uADDC\uCE59\uC744 \uB530\uB985\uB2C8\uB2E4.",
|
|
@@ -2024,6 +2049,19 @@ function listGoals(goalsDir) {
|
|
|
2024
2049
|
parsed.sort((a, b) => a.frontmatter.id - b.frontmatter.id);
|
|
2025
2050
|
return parsed;
|
|
2026
2051
|
}
|
|
2052
|
+
function findDuplicateIds(goals) {
|
|
2053
|
+
const counts = /* @__PURE__ */ new Map();
|
|
2054
|
+
for (const g of goals) {
|
|
2055
|
+
const id = g.frontmatter.id;
|
|
2056
|
+
if (typeof id !== "number") continue;
|
|
2057
|
+
counts.set(id, (counts.get(id) ?? 0) + 1);
|
|
2058
|
+
}
|
|
2059
|
+
const dups = [];
|
|
2060
|
+
for (const [id, n] of counts) {
|
|
2061
|
+
if (n > 1) dups.push(id);
|
|
2062
|
+
}
|
|
2063
|
+
return dups.sort((a, b) => a - b);
|
|
2064
|
+
}
|
|
2027
2065
|
function updateFrontmatterStatus(content, newStatus, extraFields) {
|
|
2028
2066
|
const m = content.match(FRONTMATTER_RE);
|
|
2029
2067
|
if (!m) return content;
|
|
@@ -2108,6 +2146,11 @@ ${ko.goal.listTitle}
|
|
|
2108
2146
|
` [${id}] ${icon} ${status2.padEnd(11)} ${pri} ${ver} ${fm.title ?? "(untitled)"}`
|
|
2109
2147
|
);
|
|
2110
2148
|
}
|
|
2149
|
+
const dups = findDuplicateIds(goals);
|
|
2150
|
+
if (dups.length > 0) {
|
|
2151
|
+
console.log("");
|
|
2152
|
+
console.log(chalk6.yellow(` ${ko.goal.duplicateId(dups.join(", "))}`));
|
|
2153
|
+
}
|
|
2111
2154
|
}
|
|
2112
2155
|
async function goalNext() {
|
|
2113
2156
|
console.log(chalk6.bold(`
|
|
@@ -2221,6 +2264,11 @@ ${ko.goal.checkTitle}
|
|
|
2221
2264
|
process.exitCode = 1;
|
|
2222
2265
|
return;
|
|
2223
2266
|
}
|
|
2267
|
+
if (!goals.some((g) => g.frontmatter.id === id)) {
|
|
2268
|
+
console.log(chalk6.red(` \u274C ${ko.goal.notFound(id)}`));
|
|
2269
|
+
process.exitCode = 1;
|
|
2270
|
+
return;
|
|
2271
|
+
}
|
|
2224
2272
|
const scriptPath = findGateScript(id);
|
|
2225
2273
|
if (!scriptPath) {
|
|
2226
2274
|
console.log(
|
|
@@ -2258,7 +2306,7 @@ ${ko.goal.doneTitle}
|
|
|
2258
2306
|
}
|
|
2259
2307
|
const target = goals.find((g) => g.frontmatter.id === id);
|
|
2260
2308
|
if (!target) {
|
|
2261
|
-
console.log(chalk6.red(` \u274C
|
|
2309
|
+
console.log(chalk6.red(` \u274C ${ko.goal.notFound(id)}`));
|
|
2262
2310
|
process.exitCode = 1;
|
|
2263
2311
|
return;
|
|
2264
2312
|
}
|
package/dist/mcp/index.js
CHANGED