@gethmy/mcp 2.3.0 → 2.3.2

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.
Files changed (38) hide show
  1. package/dist/cli.js +80 -23
  2. package/dist/index.js +80 -23
  3. package/dist/lib/active-learning.js +939 -787
  4. package/dist/lib/api-client.js +2527 -638
  5. package/dist/lib/auto-session.js +177 -196
  6. package/dist/lib/cli.js +34954 -128
  7. package/dist/lib/config.js +235 -201
  8. package/dist/lib/consolidation.js +374 -289
  9. package/dist/lib/context-assembly.js +1265 -838
  10. package/dist/lib/graph-expansion.js +139 -155
  11. package/dist/lib/http.js +1917 -130
  12. package/dist/lib/index.js +29525 -5
  13. package/dist/lib/lifecycle-maintenance.js +663 -79
  14. package/dist/lib/memory-cleanup.js +1316 -381
  15. package/dist/lib/onboard.js +2588 -32
  16. package/dist/lib/prompt-builder.js +438 -445
  17. package/dist/lib/remote.js +31733 -143
  18. package/dist/lib/server.js +29389 -3216
  19. package/dist/lib/skills.js +315 -132
  20. package/dist/lib/tui/agents.js +128 -107
  21. package/dist/lib/tui/docs.js +1590 -687
  22. package/dist/lib/tui/setup.js +5698 -804
  23. package/dist/lib/tui/theme.js +183 -86
  24. package/dist/lib/tui/writer.js +1149 -176
  25. package/package.json +2 -2
  26. package/src/api-client.ts +37 -1
  27. package/src/memory-cleanup.ts +92 -52
  28. package/src/server.ts +16 -1
  29. package/dist/lib/__tests__/active-learning.test.js +0 -386
  30. package/dist/lib/__tests__/agent-performance-profiles.test.js +0 -325
  31. package/dist/lib/__tests__/auto-session.test.js +0 -661
  32. package/dist/lib/__tests__/context-assembly.test.js +0 -362
  33. package/dist/lib/__tests__/graph-expansion.test.js +0 -150
  34. package/dist/lib/__tests__/integration-memory-crud.test.js +0 -797
  35. package/dist/lib/__tests__/integration-memory-system.test.js +0 -281
  36. package/dist/lib/__tests__/lifecycle-maintenance.test.js +0 -207
  37. package/dist/lib/__tests__/pattern-detection.test.js +0 -295
  38. package/dist/lib/__tests__/prompt-builder.test.js +0 -418
@@ -1,744 +1,1647 @@
1
+ import { createRequire } from "node:module";
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __toESM = (mod, isNodeMode, target) => {
8
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
9
+ const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
10
+ for (let key of __getOwnPropNames(mod))
11
+ if (!__hasOwnProp.call(to, key))
12
+ __defProp(to, key, {
13
+ get: () => mod[key],
14
+ enumerable: true
15
+ });
16
+ return to;
17
+ };
18
+ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
19
+ var __export = (target, all) => {
20
+ for (var name in all)
21
+ __defProp(target, name, {
22
+ get: all[name],
23
+ enumerable: true,
24
+ configurable: true,
25
+ set: (newValue) => all[name] = () => newValue
26
+ });
27
+ };
28
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
29
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
30
+
31
+ // ../../node_modules/picocolors/picocolors.js
32
+ var require_picocolors = __commonJS((exports, module) => {
33
+ var p = process || {};
34
+ var argv = p.argv || [];
35
+ var env = p.env || {};
36
+ var isColorSupported = !(!!env.NO_COLOR || argv.includes("--no-color")) && (!!env.FORCE_COLOR || argv.includes("--color") || p.platform === "win32" || (p.stdout || {}).isTTY && env.TERM !== "dumb" || !!env.CI);
37
+ var formatter = (open, close, replace = open) => (input) => {
38
+ let string = "" + input, index = string.indexOf(close, open.length);
39
+ return ~index ? open + replaceClose(string, close, replace, index) + close : open + string + close;
40
+ };
41
+ var replaceClose = (string, close, replace, index) => {
42
+ let result = "", cursor = 0;
43
+ do {
44
+ result += string.substring(cursor, index) + replace;
45
+ cursor = index + close.length;
46
+ index = string.indexOf(close, cursor);
47
+ } while (~index);
48
+ return result + string.substring(cursor);
49
+ };
50
+ var createColors = (enabled = isColorSupported) => {
51
+ let f = enabled ? formatter : () => String;
52
+ return {
53
+ isColorSupported: enabled,
54
+ reset: f("\x1B[0m", "\x1B[0m"),
55
+ bold: f("\x1B[1m", "\x1B[22m", "\x1B[22m\x1B[1m"),
56
+ dim: f("\x1B[2m", "\x1B[22m", "\x1B[22m\x1B[2m"),
57
+ italic: f("\x1B[3m", "\x1B[23m"),
58
+ underline: f("\x1B[4m", "\x1B[24m"),
59
+ inverse: f("\x1B[7m", "\x1B[27m"),
60
+ hidden: f("\x1B[8m", "\x1B[28m"),
61
+ strikethrough: f("\x1B[9m", "\x1B[29m"),
62
+ black: f("\x1B[30m", "\x1B[39m"),
63
+ red: f("\x1B[31m", "\x1B[39m"),
64
+ green: f("\x1B[32m", "\x1B[39m"),
65
+ yellow: f("\x1B[33m", "\x1B[39m"),
66
+ blue: f("\x1B[34m", "\x1B[39m"),
67
+ magenta: f("\x1B[35m", "\x1B[39m"),
68
+ cyan: f("\x1B[36m", "\x1B[39m"),
69
+ white: f("\x1B[37m", "\x1B[39m"),
70
+ gray: f("\x1B[90m", "\x1B[39m"),
71
+ bgBlack: f("\x1B[40m", "\x1B[49m"),
72
+ bgRed: f("\x1B[41m", "\x1B[49m"),
73
+ bgGreen: f("\x1B[42m", "\x1B[49m"),
74
+ bgYellow: f("\x1B[43m", "\x1B[49m"),
75
+ bgBlue: f("\x1B[44m", "\x1B[49m"),
76
+ bgMagenta: f("\x1B[45m", "\x1B[49m"),
77
+ bgCyan: f("\x1B[46m", "\x1B[49m"),
78
+ bgWhite: f("\x1B[47m", "\x1B[49m"),
79
+ blackBright: f("\x1B[90m", "\x1B[39m"),
80
+ redBright: f("\x1B[91m", "\x1B[39m"),
81
+ greenBright: f("\x1B[92m", "\x1B[39m"),
82
+ yellowBright: f("\x1B[93m", "\x1B[39m"),
83
+ blueBright: f("\x1B[94m", "\x1B[39m"),
84
+ magentaBright: f("\x1B[95m", "\x1B[39m"),
85
+ cyanBright: f("\x1B[96m", "\x1B[39m"),
86
+ whiteBright: f("\x1B[97m", "\x1B[39m"),
87
+ bgBlackBright: f("\x1B[100m", "\x1B[49m"),
88
+ bgRedBright: f("\x1B[101m", "\x1B[49m"),
89
+ bgGreenBright: f("\x1B[102m", "\x1B[49m"),
90
+ bgYellowBright: f("\x1B[103m", "\x1B[49m"),
91
+ bgBlueBright: f("\x1B[104m", "\x1B[49m"),
92
+ bgMagentaBright: f("\x1B[105m", "\x1B[49m"),
93
+ bgCyanBright: f("\x1B[106m", "\x1B[49m"),
94
+ bgWhiteBright: f("\x1B[107m", "\x1B[49m")
95
+ };
96
+ };
97
+ module.exports = createColors();
98
+ module.exports.createColors = createColors;
99
+ });
100
+
101
+ // ../../node_modules/sisteransi/src/index.js
102
+ var require_src = __commonJS((exports, module) => {
103
+ var ESC = "\x1B";
104
+ var CSI = `${ESC}[`;
105
+ var beep = "\x07";
106
+ var cursor = {
107
+ to(x, y) {
108
+ if (!y)
109
+ return `${CSI}${x + 1}G`;
110
+ return `${CSI}${y + 1};${x + 1}H`;
111
+ },
112
+ move(x, y) {
113
+ let ret = "";
114
+ if (x < 0)
115
+ ret += `${CSI}${-x}D`;
116
+ else if (x > 0)
117
+ ret += `${CSI}${x}C`;
118
+ if (y < 0)
119
+ ret += `${CSI}${-y}A`;
120
+ else if (y > 0)
121
+ ret += `${CSI}${y}B`;
122
+ return ret;
123
+ },
124
+ up: (count = 1) => `${CSI}${count}A`,
125
+ down: (count = 1) => `${CSI}${count}B`,
126
+ forward: (count = 1) => `${CSI}${count}C`,
127
+ backward: (count = 1) => `${CSI}${count}D`,
128
+ nextLine: (count = 1) => `${CSI}E`.repeat(count),
129
+ prevLine: (count = 1) => `${CSI}F`.repeat(count),
130
+ left: `${CSI}G`,
131
+ hide: `${CSI}?25l`,
132
+ show: `${CSI}?25h`,
133
+ save: `${ESC}7`,
134
+ restore: `${ESC}8`
135
+ };
136
+ var scroll = {
137
+ up: (count = 1) => `${CSI}S`.repeat(count),
138
+ down: (count = 1) => `${CSI}T`.repeat(count)
139
+ };
140
+ var erase = {
141
+ screen: `${CSI}2J`,
142
+ up: (count = 1) => `${CSI}1J`.repeat(count),
143
+ down: (count = 1) => `${CSI}J`.repeat(count),
144
+ line: `${CSI}2K`,
145
+ lineEnd: `${CSI}K`,
146
+ lineStart: `${CSI}1K`,
147
+ lines(count) {
148
+ let clear = "";
149
+ for (let i = 0;i < count; i++)
150
+ clear += this.line + (i < count - 1 ? cursor.up() : "");
151
+ if (count)
152
+ clear += cursor.left;
153
+ return clear;
154
+ }
155
+ };
156
+ module.exports = { cursor, scroll, erase, beep };
157
+ });
158
+
159
+ // src/tui/theme.ts
160
+ var pc = __toESM(require_picocolors(), 1);
161
+ var symbols = {
162
+ harmony: "▲",
163
+ check: "✓",
164
+ cross: "✗",
165
+ bullet: "•",
166
+ arrow: "→",
167
+ arrowRight: "▸",
168
+ dot: "●",
169
+ dotEmpty: "○",
170
+ info: "ℹ",
171
+ warning: "⚠",
172
+ pointer: "❯"
173
+ };
174
+ var colors = {
175
+ brand: (text) => pc.cyan(text),
176
+ brandBold: (text) => pc.bold(pc.cyan(text)),
177
+ success: (text) => pc.green(text),
178
+ error: (text) => pc.red(text),
179
+ warning: (text) => pc.yellow(text),
180
+ info: (text) => pc.blue(text),
181
+ dim: (text) => pc.dim(text),
182
+ bold: (text) => pc.bold(text),
183
+ muted: (text) => pc.gray(text),
184
+ highlight: (text) => pc.cyan(text),
185
+ link: (text) => pc.underline(pc.cyan(text))
186
+ };
187
+ var messages = {
188
+ header: () => {
189
+ return `
190
+ ${colors.brandBold(" HARMONY")}
191
+ ${colors.dim(" Project management for AI agents")}
192
+ `;
193
+ },
194
+ done: (message) => {
195
+ return `${colors.success(symbols.check)} ${message}`;
196
+ },
197
+ fail: (message) => {
198
+ return `${colors.error(symbols.cross)} ${message}`;
199
+ },
200
+ skip: (message) => {
201
+ return `${colors.dim("-")} ${colors.dim(message)}`;
202
+ },
203
+ step: (number, total, message) => {
204
+ return `${colors.dim(`[${number}/${total}]`)} ${message}`;
205
+ },
206
+ fileCreated: (path) => {
207
+ return ` ${colors.success(symbols.check)} ${colors.dim(path)}`;
208
+ },
209
+ fileSkipped: (path) => {
210
+ return ` ${colors.dim(symbols.bullet)} ${colors.dim(path)} ${colors.dim("(exists)")}`;
211
+ },
212
+ fileError: (path, error) => {
213
+ return ` ${colors.error(symbols.cross)} ${path}: ${colors.error(error)}`;
214
+ }
215
+ };
216
+ function box(title, content) {
217
+ const lines = content.split(`
218
+ `);
219
+ const maxWidth = Math.max(title.length, ...lines.map((l) => l.length));
220
+ const width = maxWidth + 4;
221
+ const top = `┌${"─".repeat(width)}┐`;
222
+ const bottom = `└${"─".repeat(width)}┘`;
223
+ const titleLine = `│ ${colors.bold(title)}${" ".repeat(width - title.length - 1)}│`;
224
+ const contentLines = lines.map((line) => `│ ${line}${" ".repeat(width - line.length - 1)}│`).join(`
225
+ `);
226
+ return `${top}
227
+ ${titleLine}
228
+ ${contentLines}
229
+ ${bottom}`;
230
+ }
231
+ function formatPath(path, homeDir) {
232
+ if (path.startsWith(homeDir)) {
233
+ return `~${path.slice(homeDir.length)}`;
234
+ }
235
+ return path;
236
+ }
237
+ function indent(text, spaces = 2) {
238
+ const pad = " ".repeat(spaces);
239
+ return text.split(`
240
+ `).map((line) => `${pad}${line}`).join(`
241
+ `);
242
+ }
243
+
244
+ // src/tui/docs.ts
1
245
  import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
2
246
  import { isAbsolute, join, resolve, sep } from "node:path";
3
- import * as p from "@clack/prompts";
4
- import { colors, symbols } from "./theme.js";
5
- // ── Helpers ─────────────────────────────────────────────────────────────────
6
- const IGNORED_DIRS = new Set([
7
- "node_modules",
8
- ".git",
9
- "dist",
10
- "build",
11
- ".next",
12
- ".nuxt",
13
- ".output",
14
- ".vercel",
15
- ".turbo",
16
- ".cache",
17
- "coverage",
18
- ".harmony-worktrees",
19
- "__pycache__",
20
- "target",
21
- "vendor",
22
- ]);
23
- /** Read a JSON file safely, returning null on failure. */
24
- function readJson(filePath) {
25
- try {
26
- return JSON.parse(readFileSync(filePath, "utf-8"));
247
+
248
+ // ../../node_modules/@clack/core/dist/index.mjs
249
+ var import_sisteransi = __toESM(require_src(), 1);
250
+ var import_picocolors = __toESM(require_picocolors(), 1);
251
+ import { stdin as j, stdout as M } from "node:process";
252
+ import * as g from "node:readline";
253
+ import O from "node:readline";
254
+ import { Writable as X } from "node:stream";
255
+ function DD({ onlyFirst: e = false } = {}) {
256
+ const t = ["[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?(?:\\u0007|\\u001B\\u005C|\\u009C))", "(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-nq-uy=><~]))"].join("|");
257
+ return new RegExp(t, e ? undefined : "g");
258
+ }
259
+ var uD = DD();
260
+ function P(e) {
261
+ if (typeof e != "string")
262
+ throw new TypeError(`Expected a \`string\`, got \`${typeof e}\``);
263
+ return e.replace(uD, "");
264
+ }
265
+ function L(e) {
266
+ return e && e.__esModule && Object.prototype.hasOwnProperty.call(e, "default") ? e.default : e;
267
+ }
268
+ var W = { exports: {} };
269
+ (function(e) {
270
+ var u = {};
271
+ e.exports = u, u.eastAsianWidth = function(F) {
272
+ var s = F.charCodeAt(0), i = F.length == 2 ? F.charCodeAt(1) : 0, D = s;
273
+ return 55296 <= s && s <= 56319 && 56320 <= i && i <= 57343 && (s &= 1023, i &= 1023, D = s << 10 | i, D += 65536), D == 12288 || 65281 <= D && D <= 65376 || 65504 <= D && D <= 65510 ? "F" : D == 8361 || 65377 <= D && D <= 65470 || 65474 <= D && D <= 65479 || 65482 <= D && D <= 65487 || 65490 <= D && D <= 65495 || 65498 <= D && D <= 65500 || 65512 <= D && D <= 65518 ? "H" : 4352 <= D && D <= 4447 || 4515 <= D && D <= 4519 || 4602 <= D && D <= 4607 || 9001 <= D && D <= 9002 || 11904 <= D && D <= 11929 || 11931 <= D && D <= 12019 || 12032 <= D && D <= 12245 || 12272 <= D && D <= 12283 || 12289 <= D && D <= 12350 || 12353 <= D && D <= 12438 || 12441 <= D && D <= 12543 || 12549 <= D && D <= 12589 || 12593 <= D && D <= 12686 || 12688 <= D && D <= 12730 || 12736 <= D && D <= 12771 || 12784 <= D && D <= 12830 || 12832 <= D && D <= 12871 || 12880 <= D && D <= 13054 || 13056 <= D && D <= 19903 || 19968 <= D && D <= 42124 || 42128 <= D && D <= 42182 || 43360 <= D && D <= 43388 || 44032 <= D && D <= 55203 || 55216 <= D && D <= 55238 || 55243 <= D && D <= 55291 || 63744 <= D && D <= 64255 || 65040 <= D && D <= 65049 || 65072 <= D && D <= 65106 || 65108 <= D && D <= 65126 || 65128 <= D && D <= 65131 || 110592 <= D && D <= 110593 || 127488 <= D && D <= 127490 || 127504 <= D && D <= 127546 || 127552 <= D && D <= 127560 || 127568 <= D && D <= 127569 || 131072 <= D && D <= 194367 || 177984 <= D && D <= 196605 || 196608 <= D && D <= 262141 ? "W" : 32 <= D && D <= 126 || 162 <= D && D <= 163 || 165 <= D && D <= 166 || D == 172 || D == 175 || 10214 <= D && D <= 10221 || 10629 <= D && D <= 10630 ? "Na" : D == 161 || D == 164 || 167 <= D && D <= 168 || D == 170 || 173 <= D && D <= 174 || 176 <= D && D <= 180 || 182 <= D && D <= 186 || 188 <= D && D <= 191 || D == 198 || D == 208 || 215 <= D && D <= 216 || 222 <= D && D <= 225 || D == 230 || 232 <= D && D <= 234 || 236 <= D && D <= 237 || D == 240 || 242 <= D && D <= 243 || 247 <= D && D <= 250 || D == 252 || D == 254 || D == 257 || D == 273 || D == 275 || D == 283 || 294 <= D && D <= 295 || D == 299 || 305 <= D && D <= 307 || D == 312 || 319 <= D && D <= 322 || D == 324 || 328 <= D && D <= 331 || D == 333 || 338 <= D && D <= 339 || 358 <= D && D <= 359 || D == 363 || D == 462 || D == 464 || D == 466 || D == 468 || D == 470 || D == 472 || D == 474 || D == 476 || D == 593 || D == 609 || D == 708 || D == 711 || 713 <= D && D <= 715 || D == 717 || D == 720 || 728 <= D && D <= 731 || D == 733 || D == 735 || 768 <= D && D <= 879 || 913 <= D && D <= 929 || 931 <= D && D <= 937 || 945 <= D && D <= 961 || 963 <= D && D <= 969 || D == 1025 || 1040 <= D && D <= 1103 || D == 1105 || D == 8208 || 8211 <= D && D <= 8214 || 8216 <= D && D <= 8217 || 8220 <= D && D <= 8221 || 8224 <= D && D <= 8226 || 8228 <= D && D <= 8231 || D == 8240 || 8242 <= D && D <= 8243 || D == 8245 || D == 8251 || D == 8254 || D == 8308 || D == 8319 || 8321 <= D && D <= 8324 || D == 8364 || D == 8451 || D == 8453 || D == 8457 || D == 8467 || D == 8470 || 8481 <= D && D <= 8482 || D == 8486 || D == 8491 || 8531 <= D && D <= 8532 || 8539 <= D && D <= 8542 || 8544 <= D && D <= 8555 || 8560 <= D && D <= 8569 || D == 8585 || 8592 <= D && D <= 8601 || 8632 <= D && D <= 8633 || D == 8658 || D == 8660 || D == 8679 || D == 8704 || 8706 <= D && D <= 8707 || 8711 <= D && D <= 8712 || D == 8715 || D == 8719 || D == 8721 || D == 8725 || D == 8730 || 8733 <= D && D <= 8736 || D == 8739 || D == 8741 || 8743 <= D && D <= 8748 || D == 8750 || 8756 <= D && D <= 8759 || 8764 <= D && D <= 8765 || D == 8776 || D == 8780 || D == 8786 || 8800 <= D && D <= 8801 || 8804 <= D && D <= 8807 || 8810 <= D && D <= 8811 || 8814 <= D && D <= 8815 || 8834 <= D && D <= 8835 || 8838 <= D && D <= 8839 || D == 8853 || D == 8857 || D == 8869 || D == 8895 || D == 8978 || 9312 <= D && D <= 9449 || 9451 <= D && D <= 9547 || 9552 <= D && D <= 9587 || 9600 <= D && D <= 9615 || 9618 <= D && D <= 9621 || 9632 <= D && D <= 9633 || 9635 <= D && D <= 9641 || 9650 <= D && D <= 9651 || 9654 <= D && D <= 9655 || 9660 <= D && D <= 9661 || 9664 <= D && D <= 9665 || 9670 <= D && D <= 9672 || D == 9675 || 9678 <= D && D <= 9681 || 9698 <= D && D <= 9701 || D == 9711 || 9733 <= D && D <= 9734 || D == 9737 || 9742 <= D && D <= 9743 || 9748 <= D && D <= 9749 || D == 9756 || D == 9758 || D == 9792 || D == 9794 || 9824 <= D && D <= 9825 || 9827 <= D && D <= 9829 || 9831 <= D && D <= 9834 || 9836 <= D && D <= 9837 || D == 9839 || 9886 <= D && D <= 9887 || 9918 <= D && D <= 9919 || 9924 <= D && D <= 9933 || 9935 <= D && D <= 9953 || D == 9955 || 9960 <= D && D <= 9983 || D == 10045 || D == 10071 || 10102 <= D && D <= 10111 || 11093 <= D && D <= 11097 || 12872 <= D && D <= 12879 || 57344 <= D && D <= 63743 || 65024 <= D && D <= 65039 || D == 65533 || 127232 <= D && D <= 127242 || 127248 <= D && D <= 127277 || 127280 <= D && D <= 127337 || 127344 <= D && D <= 127386 || 917760 <= D && D <= 917999 || 983040 <= D && D <= 1048573 || 1048576 <= D && D <= 1114109 ? "A" : "N";
274
+ }, u.characterLength = function(F) {
275
+ var s = this.eastAsianWidth(F);
276
+ return s == "F" || s == "W" || s == "A" ? 2 : 1;
277
+ };
278
+ function t(F) {
279
+ return F.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]|[^\uD800-\uDFFF]/g) || [];
280
+ }
281
+ u.length = function(F) {
282
+ for (var s = t(F), i = 0, D = 0;D < s.length; D++)
283
+ i = i + this.characterLength(s[D]);
284
+ return i;
285
+ }, u.slice = function(F, s, i) {
286
+ textLen = u.length(F), s = s || 0, i = i || 1, s < 0 && (s = textLen + s), i < 0 && (i = textLen + i);
287
+ for (var D = "", C = 0, n = t(F), E = 0;E < n.length; E++) {
288
+ var a = n[E], o = u.length(a);
289
+ if (C >= s - (o == 2 ? 1 : 0))
290
+ if (C + o <= i)
291
+ D += a;
292
+ else
293
+ break;
294
+ C += o;
27
295
  }
28
- catch {
29
- return null;
296
+ return D;
297
+ };
298
+ })(W);
299
+ var tD = W.exports;
300
+ var eD = L(tD);
301
+ var FD = function() {
302
+ return /\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62(?:\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73|\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74|\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67)\uDB40\uDC7F|(?:\uD83E\uDDD1\uD83C\uDFFF\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFF\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFE])|(?:\uD83E\uDDD1\uD83C\uDFFE\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFE\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFD\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFD\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFC\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFC\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|(?:\uD83E\uDDD1\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83E\uDDD1|\uD83D\uDC69\uD83C\uDFFB\u200D\uD83E\uDD1D\u200D(?:\uD83D[\uDC68\uDC69]))(?:\uD83C[\uDFFC-\uDFFF])|\uD83D\uDC68(?:\uD83C\uDFFB(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFC-\uDFFF])|[\u2695\u2696\u2708]\uFE0F|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))?|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFF]))|\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D)?\uD83D\uDC68|(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFE])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB-\uDFFD\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFC\uDFFE\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83E\uDD1D\u200D\uD83D\uDC68(?:\uD83C[\uDFFB\uDFFD-\uDFFF])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])\uFE0F|\u200D(?:(?:\uD83D[\uDC68\uDC69])\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D[\uDC66\uDC67])|\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC)?|(?:\uD83D\uDC69(?:\uD83C\uDFFB\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|(?:\uD83C[\uDFFC-\uDFFF])\u200D\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69]))|\uD83E\uDDD1(?:\uD83C[\uDFFB-\uDFFF])\u200D\uD83E\uDD1D\u200D\uD83E\uDDD1)(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67]))|\uD83D\uDC69(?:\u200D(?:\u2764\uFE0F\u200D(?:\uD83D\uDC8B\u200D(?:\uD83D[\uDC68\uDC69])|\uD83D[\uDC68\uDC69])|\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83E\uDDD1(?:\u200D(?:\uD83E\uDD1D\u200D\uD83E\uDDD1|\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFF\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFE\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFD\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFC\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD])|\uD83C\uDFFB\u200D(?:\uD83C[\uDF3E\uDF73\uDF7C\uDF84\uDF93\uDFA4\uDFA8\uDFEB\uDFED]|\uD83D[\uDCBB\uDCBC\uDD27\uDD2C\uDE80\uDE92]|\uD83E[\uDDAF-\uDDB3\uDDBC\uDDBD]))|\uD83D\uDC69\u200D\uD83D\uDC66\u200D\uD83D\uDC66|\uD83D\uDC69\u200D\uD83D\uDC69\u200D(?:\uD83D[\uDC66\uDC67])|\uD83D\uDC69\u200D\uD83D\uDC67\u200D(?:\uD83D[\uDC66\uDC67])|(?:\uD83D\uDC41\uFE0F\u200D\uD83D\uDDE8|\uD83E\uDDD1(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDC69(?:\uD83C\uDFFF\u200D[\u2695\u2696\u2708]|\uD83C\uDFFE\u200D[\u2695\u2696\u2708]|\uD83C\uDFFD\u200D[\u2695\u2696\u2708]|\uD83C\uDFFC\u200D[\u2695\u2696\u2708]|\uD83C\uDFFB\u200D[\u2695\u2696\u2708]|\u200D[\u2695\u2696\u2708])|\uD83D\uDE36\u200D\uD83C\uDF2B|\uD83C\uDFF3\uFE0F\u200D\u26A7|\uD83D\uDC3B\u200D\u2744|(?:(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF])\u200D[\u2640\u2642]|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])\u200D[\u2640\u2642]|\uD83C\uDFF4\u200D\u2620|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])\u200D[\u2640\u2642]|[\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u2328\u23CF\u23ED-\u23EF\u23F1\u23F2\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB\u25FC\u2600-\u2604\u260E\u2611\u2618\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u2692\u2694-\u2697\u2699\u269B\u269C\u26A0\u26A7\u26B0\u26B1\u26C8\u26CF\u26D1\u26D3\u26E9\u26F0\u26F1\u26F4\u26F7\u26F8\u2702\u2708\u2709\u270F\u2712\u2714\u2716\u271D\u2721\u2733\u2734\u2744\u2747\u2763\u27A1\u2934\u2935\u2B05-\u2B07\u3030\u303D\u3297\u3299]|\uD83C[\uDD70\uDD71\uDD7E\uDD7F\uDE02\uDE37\uDF21\uDF24-\uDF2C\uDF36\uDF7D\uDF96\uDF97\uDF99-\uDF9B\uDF9E\uDF9F\uDFCD\uDFCE\uDFD4-\uDFDF\uDFF5\uDFF7]|\uD83D[\uDC3F\uDCFD\uDD49\uDD4A\uDD6F\uDD70\uDD73\uDD76-\uDD79\uDD87\uDD8A-\uDD8D\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA\uDECB\uDECD-\uDECF\uDEE0-\uDEE5\uDEE9\uDEF0\uDEF3])\uFE0F|\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08|\uD83D\uDC69\u200D\uD83D\uDC67|\uD83D\uDC69\u200D\uD83D\uDC66|\uD83D\uDE35\u200D\uD83D\uDCAB|\uD83D\uDE2E\u200D\uD83D\uDCA8|\uD83D\uDC15\u200D\uD83E\uDDBA|\uD83E\uDDD1(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83D\uDC69(?:\uD83C\uDFFF|\uD83C\uDFFE|\uD83C\uDFFD|\uD83C\uDFFC|\uD83C\uDFFB)?|\uD83C\uDDFD\uD83C\uDDF0|\uD83C\uDDF6\uD83C\uDDE6|\uD83C\uDDF4\uD83C\uDDF2|\uD83D\uDC08\u200D\u2B1B|\u2764\uFE0F\u200D(?:\uD83D\uDD25|\uD83E\uDE79)|\uD83D\uDC41\uFE0F|\uD83C\uDFF3\uFE0F|\uD83C\uDDFF(?:\uD83C[\uDDE6\uDDF2\uDDFC])|\uD83C\uDDFE(?:\uD83C[\uDDEA\uDDF9])|\uD83C\uDDFC(?:\uD83C[\uDDEB\uDDF8])|\uD83C\uDDFB(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDEE\uDDF3\uDDFA])|\uD83C\uDDFA(?:\uD83C[\uDDE6\uDDEC\uDDF2\uDDF3\uDDF8\uDDFE\uDDFF])|\uD83C\uDDF9(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDED\uDDEF-\uDDF4\uDDF7\uDDF9\uDDFB\uDDFC\uDDFF])|\uD83C\uDDF8(?:\uD83C[\uDDE6-\uDDEA\uDDEC-\uDDF4\uDDF7-\uDDF9\uDDFB\uDDFD-\uDDFF])|\uD83C\uDDF7(?:\uD83C[\uDDEA\uDDF4\uDDF8\uDDFA\uDDFC])|\uD83C\uDDF5(?:\uD83C[\uDDE6\uDDEA-\uDDED\uDDF0-\uDDF3\uDDF7-\uDDF9\uDDFC\uDDFE])|\uD83C\uDDF3(?:\uD83C[\uDDE6\uDDE8\uDDEA-\uDDEC\uDDEE\uDDF1\uDDF4\uDDF5\uDDF7\uDDFA\uDDFF])|\uD83C\uDDF2(?:\uD83C[\uDDE6\uDDE8-\uDDED\uDDF0-\uDDFF])|\uD83C\uDDF1(?:\uD83C[\uDDE6-\uDDE8\uDDEE\uDDF0\uDDF7-\uDDFB\uDDFE])|\uD83C\uDDF0(?:\uD83C[\uDDEA\uDDEC-\uDDEE\uDDF2\uDDF3\uDDF5\uDDF7\uDDFC\uDDFE\uDDFF])|\uD83C\uDDEF(?:\uD83C[\uDDEA\uDDF2\uDDF4\uDDF5])|\uD83C\uDDEE(?:\uD83C[\uDDE8-\uDDEA\uDDF1-\uDDF4\uDDF6-\uDDF9])|\uD83C\uDDED(?:\uD83C[\uDDF0\uDDF2\uDDF3\uDDF7\uDDF9\uDDFA])|\uD83C\uDDEC(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEE\uDDF1-\uDDF3\uDDF5-\uDDFA\uDDFC\uDDFE])|\uD83C\uDDEB(?:\uD83C[\uDDEE-\uDDF0\uDDF2\uDDF4\uDDF7])|\uD83C\uDDEA(?:\uD83C[\uDDE6\uDDE8\uDDEA\uDDEC\uDDED\uDDF7-\uDDFA])|\uD83C\uDDE9(?:\uD83C[\uDDEA\uDDEC\uDDEF\uDDF0\uDDF2\uDDF4\uDDFF])|\uD83C\uDDE8(?:\uD83C[\uDDE6\uDDE8\uDDE9\uDDEB-\uDDEE\uDDF0-\uDDF5\uDDF7\uDDFA-\uDDFF])|\uD83C\uDDE7(?:\uD83C[\uDDE6\uDDE7\uDDE9-\uDDEF\uDDF1-\uDDF4\uDDF6-\uDDF9\uDDFB\uDDFC\uDDFE\uDDFF])|\uD83C\uDDE6(?:\uD83C[\uDDE8-\uDDEC\uDDEE\uDDF1\uDDF2\uDDF4\uDDF6-\uDDFA\uDDFC\uDDFD\uDDFF])|[#\*0-9]\uFE0F\u20E3|\u2764\uFE0F|(?:\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])|(?:\u26F9|\uD83C[\uDFCB\uDFCC]|\uD83D\uDD75)(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|\uD83C\uDFF4|(?:[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5])(?:\uD83C[\uDFFB-\uDFFF])|(?:[\u261D\u270C\u270D]|\uD83D[\uDD74\uDD90])(?:\uFE0F|\uD83C[\uDFFB-\uDFFF])|[\u270A\u270B]|\uD83C[\uDF85\uDFC2\uDFC7]|\uD83D[\uDC08\uDC15\uDC3B\uDC42\uDC43\uDC46-\uDC50\uDC66\uDC67\uDC6B-\uDC6D\uDC72\uDC74-\uDC76\uDC78\uDC7C\uDC83\uDC85\uDC8F\uDC91\uDCAA\uDD7A\uDD95\uDD96\uDE2E\uDE35\uDE36\uDE4C\uDE4F\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1C\uDD1E\uDD1F\uDD30-\uDD34\uDD36\uDD77\uDDB5\uDDB6\uDDBB\uDDD2\uDDD3\uDDD5]|\uD83C[\uDFC3\uDFC4\uDFCA]|\uD83D[\uDC6E\uDC70\uDC71\uDC73\uDC77\uDC81\uDC82\uDC86\uDC87\uDE45-\uDE47\uDE4B\uDE4D\uDE4E\uDEA3\uDEB4-\uDEB6]|\uD83E[\uDD26\uDD35\uDD37-\uDD39\uDD3D\uDD3E\uDDB8\uDDB9\uDDCD-\uDDCF\uDDD4\uDDD6-\uDDDD]|\uD83D\uDC6F|\uD83E[\uDD3C\uDDDE\uDDDF]|[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF84\uDF86-\uDF93\uDFA0-\uDFC1\uDFC5\uDFC6\uDFC8\uDFC9\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC07\uDC09-\uDC14\uDC16-\uDC3A\uDC3C-\uDC3E\uDC40\uDC44\uDC45\uDC51-\uDC65\uDC6A\uDC79-\uDC7B\uDC7D-\uDC80\uDC84\uDC88-\uDC8E\uDC90\uDC92-\uDCA9\uDCAB-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDDA4\uDDFB-\uDE2D\uDE2F-\uDE34\uDE37-\uDE44\uDE48-\uDE4A\uDE80-\uDEA2\uDEA4-\uDEB3\uDEB7-\uDEBF\uDEC1-\uDEC5\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0D\uDD0E\uDD10-\uDD17\uDD1D\uDD20-\uDD25\uDD27-\uDD2F\uDD3A\uDD3F-\uDD45\uDD47-\uDD76\uDD78\uDD7A-\uDDB4\uDDB7\uDDBA\uDDBC-\uDDCB\uDDD0\uDDE0-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6]|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDED5-\uDED7\uDEEB\uDEEC\uDEF4-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u265F\u2660\u2663\u2665\u2666\u2668\u267B\u267E\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26A7\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDED5-\uDED7\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEFC\uDFE0-\uDFEB]|\uD83E[\uDD0C-\uDD3A\uDD3C-\uDD45\uDD47-\uDD78\uDD7A-\uDDCB\uDDCD-\uDDFF\uDE70-\uDE74\uDE78-\uDE7A\uDE80-\uDE86\uDE90-\uDEA8\uDEB0-\uDEB6\uDEC0-\uDEC2\uDED0-\uDED6])\uFE0F|(?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDC8F\uDC91\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD0C\uDD0F\uDD18-\uDD1F\uDD26\uDD30-\uDD39\uDD3C-\uDD3E\uDD77\uDDB5\uDDB6\uDDB8\uDDB9\uDDBB\uDDCD-\uDDCF\uDDD1-\uDDDD])/g;
303
+ };
304
+ var sD = L(FD);
305
+ function p(e, u = {}) {
306
+ if (typeof e != "string" || e.length === 0 || (u = { ambiguousIsNarrow: true, ...u }, e = P(e), e.length === 0))
307
+ return 0;
308
+ e = e.replace(sD(), " ");
309
+ const t = u.ambiguousIsNarrow ? 1 : 2;
310
+ let F = 0;
311
+ for (const s of e) {
312
+ const i = s.codePointAt(0);
313
+ if (i <= 31 || i >= 127 && i <= 159 || i >= 768 && i <= 879)
314
+ continue;
315
+ switch (eD.eastAsianWidth(s)) {
316
+ case "F":
317
+ case "W":
318
+ F += 2;
319
+ break;
320
+ case "A":
321
+ F += t;
322
+ break;
323
+ default:
324
+ F += 1;
30
325
  }
326
+ }
327
+ return F;
31
328
  }
32
- /** Read a text file safely, returning null on failure. */
33
- function readText(filePath) {
34
- try {
35
- return readFileSync(filePath, "utf-8");
36
- }
37
- catch {
38
- return null;
329
+ var w = 10;
330
+ var N = (e = 0) => (u) => `\x1B[${u + e}m`;
331
+ var I = (e = 0) => (u) => `\x1B[${38 + e};5;${u}m`;
332
+ var R = (e = 0) => (u, t, F) => `\x1B[${38 + e};2;${u};${t};${F}m`;
333
+ var r = { modifier: { reset: [0, 0], bold: [1, 22], dim: [2, 22], italic: [3, 23], underline: [4, 24], overline: [53, 55], inverse: [7, 27], hidden: [8, 28], strikethrough: [9, 29] }, color: { black: [30, 39], red: [31, 39], green: [32, 39], yellow: [33, 39], blue: [34, 39], magenta: [35, 39], cyan: [36, 39], white: [37, 39], blackBright: [90, 39], gray: [90, 39], grey: [90, 39], redBright: [91, 39], greenBright: [92, 39], yellowBright: [93, 39], blueBright: [94, 39], magentaBright: [95, 39], cyanBright: [96, 39], whiteBright: [97, 39] }, bgColor: { bgBlack: [40, 49], bgRed: [41, 49], bgGreen: [42, 49], bgYellow: [43, 49], bgBlue: [44, 49], bgMagenta: [45, 49], bgCyan: [46, 49], bgWhite: [47, 49], bgBlackBright: [100, 49], bgGray: [100, 49], bgGrey: [100, 49], bgRedBright: [101, 49], bgGreenBright: [102, 49], bgYellowBright: [103, 49], bgBlueBright: [104, 49], bgMagentaBright: [105, 49], bgCyanBright: [106, 49], bgWhiteBright: [107, 49] } };
334
+ Object.keys(r.modifier);
335
+ var iD = Object.keys(r.color);
336
+ var CD = Object.keys(r.bgColor);
337
+ [...iD, ...CD];
338
+ function rD() {
339
+ const e = new Map;
340
+ for (const [u, t] of Object.entries(r)) {
341
+ for (const [F, s] of Object.entries(t))
342
+ r[F] = { open: `\x1B[${s[0]}m`, close: `\x1B[${s[1]}m` }, t[F] = r[F], e.set(s[0], s[1]);
343
+ Object.defineProperty(r, u, { value: t, enumerable: false });
344
+ }
345
+ return Object.defineProperty(r, "codes", { value: e, enumerable: false }), r.color.close = "\x1B[39m", r.bgColor.close = "\x1B[49m", r.color.ansi = N(), r.color.ansi256 = I(), r.color.ansi16m = R(), r.bgColor.ansi = N(w), r.bgColor.ansi256 = I(w), r.bgColor.ansi16m = R(w), Object.defineProperties(r, { rgbToAnsi256: { value: (u, t, F) => u === t && t === F ? u < 8 ? 16 : u > 248 ? 231 : Math.round((u - 8) / 247 * 24) + 232 : 16 + 36 * Math.round(u / 255 * 5) + 6 * Math.round(t / 255 * 5) + Math.round(F / 255 * 5), enumerable: false }, hexToRgb: { value: (u) => {
346
+ const t = /[a-f\d]{6}|[a-f\d]{3}/i.exec(u.toString(16));
347
+ if (!t)
348
+ return [0, 0, 0];
349
+ let [F] = t;
350
+ F.length === 3 && (F = [...F].map((i) => i + i).join(""));
351
+ const s = Number.parseInt(F, 16);
352
+ return [s >> 16 & 255, s >> 8 & 255, s & 255];
353
+ }, enumerable: false }, hexToAnsi256: { value: (u) => r.rgbToAnsi256(...r.hexToRgb(u)), enumerable: false }, ansi256ToAnsi: { value: (u) => {
354
+ if (u < 8)
355
+ return 30 + u;
356
+ if (u < 16)
357
+ return 90 + (u - 8);
358
+ let t, F, s;
359
+ if (u >= 232)
360
+ t = ((u - 232) * 10 + 8) / 255, F = t, s = t;
361
+ else {
362
+ u -= 16;
363
+ const C = u % 36;
364
+ t = Math.floor(u / 36) / 5, F = Math.floor(C / 6) / 5, s = C % 6 / 5;
39
365
  }
366
+ const i = Math.max(t, F, s) * 2;
367
+ if (i === 0)
368
+ return 30;
369
+ let D = 30 + (Math.round(s) << 2 | Math.round(F) << 1 | Math.round(t));
370
+ return i === 2 && (D += 60), D;
371
+ }, enumerable: false }, rgbToAnsi: { value: (u, t, F) => r.ansi256ToAnsi(r.rgbToAnsi256(u, t, F)), enumerable: false }, hexToAnsi: { value: (u) => r.ansi256ToAnsi(r.hexToAnsi256(u)), enumerable: false } }), r;
40
372
  }
41
- /** List immediate subdirectories, excluding ignored names. */
42
- function listDirs(dirPath) {
43
- try {
44
- return readdirSync(dirPath).filter((entry) => {
45
- if (IGNORED_DIRS.has(entry) || entry.startsWith("."))
46
- return false;
47
- try {
48
- return statSync(join(dirPath, entry)).isDirectory();
49
- }
50
- catch {
51
- return false;
52
- }
53
- });
54
- }
55
- catch {
56
- return [];
57
- }
58
- }
59
- /** Map of common directory names to short descriptions. */
60
- const DIR_DESCRIPTIONS = {
61
- components: "UI components",
62
- pages: "Route-level pages",
63
- routes: "Route-level pages",
64
- views: "Route-level pages",
65
- hooks: "Custom hooks",
66
- lib: "Utilities",
67
- utils: "Utilities",
68
- api: "API / server code",
69
- server: "API / server code",
70
- contexts: "State management",
71
- store: "State management",
72
- stores: "State management",
73
- types: "Type definitions",
74
- styles: "Stylesheets",
75
- public: "Static assets",
76
- static: "Static assets",
77
- assets: "Static assets",
78
- supabase: "Supabase backend",
79
- functions: "Edge functions",
80
- packages: "Monorepo packages",
81
- apps: "Monorepo applications",
82
- src: "Source code",
83
- test: "Tests",
84
- tests: "Tests",
85
- __tests__: "Tests",
86
- scripts: "Build / utility scripts",
87
- config: "Configuration",
88
- docs: "Documentation",
89
- migrations: "Database migrations",
90
- prisma: "Prisma schema & migrations",
91
- e2e: "End-to-end tests",
92
- cypress: "Cypress tests",
373
+ var ED = rD();
374
+ var d = new Set(["\x1B", "›"]);
375
+ var oD = 39;
376
+ var y = "\x07";
377
+ var V = "[";
378
+ var nD = "]";
379
+ var G = "m";
380
+ var _ = `${nD}8;;`;
381
+ var z = (e) => `${d.values().next().value}${V}${e}${G}`;
382
+ var K = (e) => `${d.values().next().value}${_}${e}${y}`;
383
+ var aD = (e) => e.split(" ").map((u) => p(u));
384
+ var k = (e, u, t) => {
385
+ const F = [...u];
386
+ let s = false, i = false, D = p(P(e[e.length - 1]));
387
+ for (const [C, n] of F.entries()) {
388
+ const E = p(n);
389
+ if (D + E <= t ? e[e.length - 1] += n : (e.push(n), D = 0), d.has(n) && (s = true, i = F.slice(C + 1).join("").startsWith(_)), s) {
390
+ i ? n === y && (s = false, i = false) : n === G && (s = false);
391
+ continue;
392
+ }
393
+ D += E, D === t && C < F.length - 1 && (e.push(""), D = 0);
394
+ }
395
+ !D && e[e.length - 1].length > 0 && e.length > 1 && (e[e.length - 2] += e.pop());
93
396
  };
94
- function describeDir(name) {
95
- return DIR_DESCRIPTIONS[name.toLowerCase()] ?? name;
96
- }
97
- // ── Core functions ──────────────────────────────────────────────────────────
98
- /**
99
- * Scan the project directory and return structured metadata.
100
- * Pure static analysis — no AI, no network calls.
101
- */
102
- export function scanProject(cwd) {
103
- // Package manager
104
- let packageManager = null;
105
- if (existsSync(join(cwd, "bun.lock")) || existsSync(join(cwd, "bun.lockb"))) {
106
- packageManager = "bun";
107
- }
108
- else if (existsSync(join(cwd, "pnpm-lock.yaml"))) {
109
- packageManager = "pnpm";
110
- }
111
- else if (existsSync(join(cwd, "yarn.lock"))) {
112
- packageManager = "yarn";
113
- }
114
- else if (existsSync(join(cwd, "package.json"))) {
115
- packageManager = "npm";
116
- }
117
- // Scripts
118
- const pkg = readJson(join(cwd, "package.json"));
119
- const scripts = pkg && typeof pkg.scripts === "object" && pkg.scripts !== null
120
- ? pkg.scripts
121
- : {};
122
- // Language
123
- let language = "unknown";
124
- if (existsSync(join(cwd, "tsconfig.json"))) {
125
- language = "typescript";
126
- }
127
- else if (existsSync(join(cwd, "go.mod"))) {
128
- language = "go";
129
- }
130
- else if (existsSync(join(cwd, "Cargo.toml"))) {
131
- language = "rust";
132
- }
133
- else if (existsSync(join(cwd, "setup.py")) ||
134
- existsSync(join(cwd, "pyproject.toml"))) {
135
- language = "python";
136
- }
137
- else if (pkg) {
138
- language = "javascript";
139
- }
140
- // Framework detection (from package.json dependencies)
141
- let framework = null;
142
- if (pkg) {
143
- const deps = {
144
- ...(typeof pkg.dependencies === "object"
145
- ? pkg.dependencies
146
- : {}),
147
- ...(typeof pkg.devDependencies === "object"
148
- ? pkg.devDependencies
149
- : {}),
150
- };
151
- if (deps.next) {
152
- framework = "next";
153
- }
154
- else if (deps.react && deps.vite) {
155
- framework = "react+vite";
156
- }
157
- else if (deps.react) {
158
- framework = "react";
159
- }
160
- else if (deps.vue && deps.vite) {
161
- framework = "vue+vite";
162
- }
163
- else if (deps.vue && deps.nuxt) {
164
- framework = "nuxt";
165
- }
166
- else if (deps.vue) {
167
- framework = "vue";
168
- }
169
- else if (deps.astro) {
170
- framework = "astro";
171
- }
172
- else if (deps.svelte) {
173
- framework = "svelte";
174
- }
175
- else if (deps.express) {
176
- framework = "express";
177
- }
178
- else if (deps.fastify) {
179
- framework = "fastify";
180
- }
181
- else if (deps.hono) {
182
- framework = "hono";
183
- }
397
+ var hD = (e) => {
398
+ const u = e.split(" ");
399
+ let t = u.length;
400
+ for (;t > 0 && !(p(u[t - 1]) > 0); )
401
+ t--;
402
+ return t === u.length ? e : u.slice(0, t).join(" ") + u.slice(t).join("");
403
+ };
404
+ var lD = (e, u, t = {}) => {
405
+ if (t.trim !== false && e.trim() === "")
406
+ return "";
407
+ let F = "", s, i;
408
+ const D = aD(e);
409
+ let C = [""];
410
+ for (const [E, a] of e.split(" ").entries()) {
411
+ t.trim !== false && (C[C.length - 1] = C[C.length - 1].trimStart());
412
+ let o = p(C[C.length - 1]);
413
+ if (E !== 0 && (o >= u && (t.wordWrap === false || t.trim === false) && (C.push(""), o = 0), (o > 0 || t.trim === false) && (C[C.length - 1] += " ", o++)), t.hard && D[E] > u) {
414
+ const c = u - o, f = 1 + Math.floor((D[E] - c - 1) / u);
415
+ Math.floor((D[E] - 1) / u) < f && C.push(""), k(C, a, u);
416
+ continue;
184
417
  }
185
- // Linter
186
- let linter = null;
187
- if (existsSync(join(cwd, "biome.json")) ||
188
- existsSync(join(cwd, "biome.jsonc"))) {
189
- linter = "biome";
418
+ if (o + D[E] > u && o > 0 && D[E] > 0) {
419
+ if (t.wordWrap === false && o < u) {
420
+ k(C, a, u);
421
+ continue;
422
+ }
423
+ C.push("");
190
424
  }
191
- else {
192
- const eslintFiles = [
193
- ".eslintrc",
194
- ".eslintrc.js",
195
- ".eslintrc.cjs",
196
- ".eslintrc.json",
197
- ".eslintrc.yml",
198
- ".eslintrc.yaml",
199
- "eslint.config.js",
200
- "eslint.config.mjs",
201
- "eslint.config.cjs",
202
- "eslint.config.ts",
203
- ];
204
- if (eslintFiles.some((f) => existsSync(join(cwd, f)))) {
205
- linter = "eslint";
425
+ if (o + D[E] > u && t.wordWrap === false) {
426
+ k(C, a, u);
427
+ continue;
428
+ }
429
+ C[C.length - 1] += a;
430
+ }
431
+ t.trim !== false && (C = C.map((E) => hD(E)));
432
+ const n = [...C.join(`
433
+ `)];
434
+ for (const [E, a] of n.entries()) {
435
+ if (F += a, d.has(a)) {
436
+ const { groups: c } = new RegExp(`(?:\\${V}(?<code>\\d+)m|\\${_}(?<uri>.*)${y})`).exec(n.slice(E).join("")) || { groups: {} };
437
+ if (c.code !== undefined) {
438
+ const f = Number.parseFloat(c.code);
439
+ s = f === oD ? undefined : f;
440
+ } else
441
+ c.uri !== undefined && (i = c.uri.length === 0 ? undefined : c.uri);
442
+ }
443
+ const o = ED.codes.get(Number(s));
444
+ n[E + 1] === `
445
+ ` ? (i && (F += K("")), s && o && (F += z(o))) : a === `
446
+ ` && (s && o && (F += z(s)), i && (F += K(i)));
447
+ }
448
+ return F;
449
+ };
450
+ function Y(e, u, t) {
451
+ return String(e).normalize().replace(/\r\n/g, `
452
+ `).split(`
453
+ `).map((F) => lD(F, u, t)).join(`
454
+ `);
455
+ }
456
+ var xD = ["up", "down", "left", "right", "space", "enter", "cancel"];
457
+ var B = { actions: new Set(xD), aliases: new Map([["k", "up"], ["j", "down"], ["h", "left"], ["l", "right"], ["\x03", "cancel"], ["escape", "cancel"]]) };
458
+ function $(e, u) {
459
+ if (typeof e == "string")
460
+ return B.aliases.get(e) === u;
461
+ for (const t of e)
462
+ if (t !== undefined && $(t, u))
463
+ return true;
464
+ return false;
465
+ }
466
+ function BD(e, u) {
467
+ if (e === u)
468
+ return;
469
+ const t = e.split(`
470
+ `), F = u.split(`
471
+ `), s = [];
472
+ for (let i = 0;i < Math.max(t.length, F.length); i++)
473
+ t[i] !== F[i] && s.push(i);
474
+ return s;
475
+ }
476
+ var AD = globalThis.process.platform.startsWith("win");
477
+ var S = Symbol("clack:cancel");
478
+ function pD(e) {
479
+ return e === S;
480
+ }
481
+ function m(e, u) {
482
+ const t = e;
483
+ t.isTTY && t.setRawMode(u);
484
+ }
485
+ function fD({ input: e = j, output: u = M, overwrite: t = true, hideCursor: F = true } = {}) {
486
+ const s = g.createInterface({ input: e, output: u, prompt: "", tabSize: 1 });
487
+ g.emitKeypressEvents(e, s), e.isTTY && e.setRawMode(true);
488
+ const i = (D, { name: C, sequence: n }) => {
489
+ const E = String(D);
490
+ if ($([E, C, n], "cancel")) {
491
+ F && u.write(import_sisteransi.cursor.show), process.exit(0);
492
+ return;
493
+ }
494
+ if (!t)
495
+ return;
496
+ const a = C === "return" ? 0 : -1, o = C === "return" ? -1 : 0;
497
+ g.moveCursor(u, a, o, () => {
498
+ g.clearLine(u, 1, () => {
499
+ e.once("keypress", i);
500
+ });
501
+ });
502
+ };
503
+ return F && u.write(import_sisteransi.cursor.hide), e.once("keypress", i), () => {
504
+ e.off("keypress", i), F && u.write(import_sisteransi.cursor.show), e.isTTY && !AD && e.setRawMode(false), s.terminal = false, s.close();
505
+ };
506
+ }
507
+ var gD = Object.defineProperty;
508
+ var vD = (e, u, t) => (u in e) ? gD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t;
509
+ var h = (e, u, t) => (vD(e, typeof u != "symbol" ? u + "" : u, t), t);
510
+
511
+ class x {
512
+ constructor(u, t = true) {
513
+ h(this, "input"), h(this, "output"), h(this, "_abortSignal"), h(this, "rl"), h(this, "opts"), h(this, "_render"), h(this, "_track", false), h(this, "_prevFrame", ""), h(this, "_subscribers", new Map), h(this, "_cursor", 0), h(this, "state", "initial"), h(this, "error", ""), h(this, "value");
514
+ const { input: F = j, output: s = M, render: i, signal: D, ...C } = u;
515
+ this.opts = C, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = i.bind(this), this._track = t, this._abortSignal = D, this.input = F, this.output = s;
516
+ }
517
+ unsubscribe() {
518
+ this._subscribers.clear();
519
+ }
520
+ setSubscriber(u, t) {
521
+ const F = this._subscribers.get(u) ?? [];
522
+ F.push(t), this._subscribers.set(u, F);
523
+ }
524
+ on(u, t) {
525
+ this.setSubscriber(u, { cb: t });
526
+ }
527
+ once(u, t) {
528
+ this.setSubscriber(u, { cb: t, once: true });
529
+ }
530
+ emit(u, ...t) {
531
+ const F = this._subscribers.get(u) ?? [], s = [];
532
+ for (const i of F)
533
+ i.cb(...t), i.once && s.push(() => F.splice(F.indexOf(i), 1));
534
+ for (const i of s)
535
+ i();
536
+ }
537
+ prompt() {
538
+ return new Promise((u, t) => {
539
+ if (this._abortSignal) {
540
+ if (this._abortSignal.aborted)
541
+ return this.state = "cancel", this.close(), u(S);
542
+ this._abortSignal.addEventListener("abort", () => {
543
+ this.state = "cancel", this.close();
544
+ }, { once: true });
545
+ }
546
+ const F = new X;
547
+ F._write = (s, i, D) => {
548
+ this._track && (this.value = this.rl?.line.replace(/\t/g, ""), this._cursor = this.rl?.cursor ?? 0, this.emit("value", this.value)), D();
549
+ }, this.input.pipe(F), this.rl = O.createInterface({ input: this.input, output: F, tabSize: 2, prompt: "", escapeCodeTimeout: 50, terminal: true }), O.emitKeypressEvents(this.input, this.rl), this.rl.prompt(), this.opts.initialValue !== undefined && this._track && this.rl.write(this.opts.initialValue), this.input.on("keypress", this.onKeypress), m(this.input, true), this.output.on("resize", this.render), this.render(), this.once("submit", () => {
550
+ this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), m(this.input, false), u(this.value);
551
+ }), this.once("cancel", () => {
552
+ this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), m(this.input, false), u(S);
553
+ });
554
+ });
555
+ }
556
+ onKeypress(u, t) {
557
+ if (this.state === "error" && (this.state = "active"), t?.name && (!this._track && B.aliases.has(t.name) && this.emit("cursor", B.aliases.get(t.name)), B.actions.has(t.name) && this.emit("cursor", t.name)), u && (u.toLowerCase() === "y" || u.toLowerCase() === "n") && this.emit("confirm", u.toLowerCase() === "y"), u === "\t" && this.opts.placeholder && (this.value || (this.rl?.write(this.opts.placeholder), this.emit("value", this.opts.placeholder))), u && this.emit("key", u.toLowerCase()), t?.name === "return") {
558
+ if (this.opts.validate) {
559
+ const F = this.opts.validate(this.value);
560
+ F && (this.error = F instanceof Error ? F.message : F, this.state = "error", this.rl?.write(this.value));
561
+ }
562
+ this.state !== "error" && (this.state = "submit");
563
+ }
564
+ $([u, t?.name, t?.sequence], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
565
+ }
566
+ close() {
567
+ this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
568
+ `), m(this.input, false), this.rl?.close(), this.rl = undefined, this.emit(`${this.state}`, this.value), this.unsubscribe();
569
+ }
570
+ restoreCursor() {
571
+ const u = Y(this._prevFrame, process.stdout.columns, { hard: true }).split(`
572
+ `).length - 1;
573
+ this.output.write(import_sisteransi.cursor.move(-999, u * -1));
574
+ }
575
+ render() {
576
+ const u = Y(this._render(this) ?? "", process.stdout.columns, { hard: true });
577
+ if (u !== this._prevFrame) {
578
+ if (this.state === "initial")
579
+ this.output.write(import_sisteransi.cursor.hide);
580
+ else {
581
+ const t = BD(this._prevFrame, u);
582
+ if (this.restoreCursor(), t && t?.length === 1) {
583
+ const F = t[0];
584
+ this.output.write(import_sisteransi.cursor.move(0, F)), this.output.write(import_sisteransi.erase.lines(1));
585
+ const s = u.split(`
586
+ `);
587
+ this.output.write(s[F]), this._prevFrame = u, this.output.write(import_sisteransi.cursor.move(0, s.length - F - 1));
588
+ return;
206
589
  }
207
- else {
208
- const prettierFiles = [
209
- ".prettierrc",
210
- ".prettierrc.js",
211
- ".prettierrc.json",
212
- ".prettierrc.yml",
213
- ".prettierrc.yaml",
214
- "prettier.config.js",
215
- "prettier.config.mjs",
216
- ];
217
- if (prettierFiles.some((f) => existsSync(join(cwd, f)))) {
218
- linter = "prettier";
219
- }
590
+ if (t && t?.length > 1) {
591
+ const F = t[0];
592
+ this.output.write(import_sisteransi.cursor.move(0, F)), this.output.write(import_sisteransi.erase.down());
593
+ const s = u.split(`
594
+ `).slice(F);
595
+ this.output.write(s.join(`
596
+ `)), this._prevFrame = u;
597
+ return;
220
598
  }
599
+ this.output.write(import_sisteransi.erase.down());
600
+ }
601
+ this.output.write(u), this.state === "initial" && (this.state = "active"), this._prevFrame = u;
221
602
  }
222
- // Indent style
223
- let indentStyle = null;
224
- const biome = readJson(join(cwd, "biome.json")) ?? readJson(join(cwd, "biome.jsonc"));
225
- if (biome) {
226
- const formatter = biome.formatter;
227
- if (formatter) {
228
- const type = formatter.indentStyle === "tab" ? "tab" : "space";
229
- const width = typeof formatter.indentWidth === "number" ? formatter.indentWidth : 2;
230
- indentStyle = { type, width };
231
- }
603
+ }
604
+ }
605
+
606
+ class dD extends x {
607
+ get cursor() {
608
+ return this.value ? 0 : 1;
609
+ }
610
+ get _value() {
611
+ return this.cursor === 0;
612
+ }
613
+ constructor(u) {
614
+ super(u, false), this.value = !!u.initialValue, this.on("value", () => {
615
+ this.value = this._value;
616
+ }), this.on("confirm", (t) => {
617
+ this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = t, this.state = "submit", this.close();
618
+ }), this.on("cursor", () => {
619
+ this.value = !this.value;
620
+ });
621
+ }
622
+ }
623
+ var A;
624
+ A = new WeakMap;
625
+ var kD = Object.defineProperty;
626
+ var $D = (e, u, t) => (u in e) ? kD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t;
627
+ var H = (e, u, t) => ($D(e, typeof u != "symbol" ? u + "" : u, t), t);
628
+ var SD = class extends x {
629
+ constructor(u) {
630
+ super(u, false), H(this, "options"), H(this, "cursor", 0), this.options = u.options, this.value = [...u.initialValues ?? []], this.cursor = Math.max(this.options.findIndex(({ value: t }) => t === u.cursorAt), 0), this.on("key", (t) => {
631
+ t === "a" && this.toggleAll();
632
+ }), this.on("cursor", (t) => {
633
+ switch (t) {
634
+ case "left":
635
+ case "up":
636
+ this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
637
+ break;
638
+ case "down":
639
+ case "right":
640
+ this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
641
+ break;
642
+ case "space":
643
+ this.toggleValue();
644
+ break;
645
+ }
646
+ });
647
+ }
648
+ get _value() {
649
+ return this.options[this.cursor].value;
650
+ }
651
+ toggleAll() {
652
+ const u = this.value.length === this.options.length;
653
+ this.value = u ? [] : this.options.map((t) => t.value);
654
+ }
655
+ toggleValue() {
656
+ const u = this.value.includes(this._value);
657
+ this.value = u ? this.value.filter((t) => t !== this._value) : [...this.value, this._value];
658
+ }
659
+ };
660
+ var TD = Object.defineProperty;
661
+ var jD = (e, u, t) => (u in e) ? TD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t;
662
+ var U = (e, u, t) => (jD(e, typeof u != "symbol" ? u + "" : u, t), t);
663
+
664
+ class MD extends x {
665
+ constructor({ mask: u, ...t }) {
666
+ super(t), U(this, "valueWithCursor", ""), U(this, "_mask", "•"), this._mask = u ?? "•", this.on("finalize", () => {
667
+ this.valueWithCursor = this.masked;
668
+ }), this.on("value", () => {
669
+ if (this.cursor >= this.value.length)
670
+ this.valueWithCursor = `${this.masked}${import_picocolors.default.inverse(import_picocolors.default.hidden("_"))}`;
671
+ else {
672
+ const F = this.masked.slice(0, this.cursor), s = this.masked.slice(this.cursor);
673
+ this.valueWithCursor = `${F}${import_picocolors.default.inverse(s[0])}${s.slice(1)}`;
674
+ }
675
+ });
676
+ }
677
+ get cursor() {
678
+ return this._cursor;
679
+ }
680
+ get masked() {
681
+ return this.value.replaceAll(/./g, this._mask);
682
+ }
683
+ }
684
+ var OD = Object.defineProperty;
685
+ var PD = (e, u, t) => (u in e) ? OD(e, u, { enumerable: true, configurable: true, writable: true, value: t }) : e[u] = t;
686
+ var J = (e, u, t) => (PD(e, typeof u != "symbol" ? u + "" : u, t), t);
687
+
688
+ class LD extends x {
689
+ constructor(u) {
690
+ super(u, false), J(this, "options"), J(this, "cursor", 0), this.options = u.options, this.cursor = this.options.findIndex(({ value: t }) => t === u.initialValue), this.cursor === -1 && (this.cursor = 0), this.changeValue(), this.on("cursor", (t) => {
691
+ switch (t) {
692
+ case "left":
693
+ case "up":
694
+ this.cursor = this.cursor === 0 ? this.options.length - 1 : this.cursor - 1;
695
+ break;
696
+ case "down":
697
+ case "right":
698
+ this.cursor = this.cursor === this.options.length - 1 ? 0 : this.cursor + 1;
699
+ break;
700
+ }
701
+ this.changeValue();
702
+ });
703
+ }
704
+ get _value() {
705
+ return this.options[this.cursor];
706
+ }
707
+ changeValue() {
708
+ this.value = this._value.value;
709
+ }
710
+ }
711
+ class RD extends x {
712
+ get valueWithCursor() {
713
+ if (this.state === "submit")
714
+ return this.value;
715
+ if (this.cursor >= this.value.length)
716
+ return `${this.value}█`;
717
+ const u = this.value.slice(0, this.cursor), [t, ...F] = this.value.slice(this.cursor);
718
+ return `${u}${import_picocolors.default.inverse(t)}${F.join("")}`;
719
+ }
720
+ get cursor() {
721
+ return this._cursor;
722
+ }
723
+ constructor(u) {
724
+ super(u), this.on("finalize", () => {
725
+ this.value || (this.value = u.defaultValue);
726
+ });
727
+ }
728
+ }
729
+
730
+ // ../../node_modules/@clack/prompts/dist/index.mjs
731
+ var import_picocolors2 = __toESM(require_picocolors(), 1);
732
+ var import_sisteransi2 = __toESM(require_src(), 1);
733
+ import y2 from "node:process";
734
+ function ce() {
735
+ return y2.platform !== "win32" ? y2.env.TERM !== "linux" : !!y2.env.CI || !!y2.env.WT_SESSION || !!y2.env.TERMINUS_SUBLIME || y2.env.ConEmuTask === "{cmd::Cmder}" || y2.env.TERM_PROGRAM === "Terminus-Sublime" || y2.env.TERM_PROGRAM === "vscode" || y2.env.TERM === "xterm-256color" || y2.env.TERM === "alacritty" || y2.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
736
+ }
737
+ var V2 = ce();
738
+ var u = (t, n) => V2 ? t : n;
739
+ var le = u("◆", "*");
740
+ var L2 = u("■", "x");
741
+ var W2 = u("▲", "x");
742
+ var C = u("◇", "o");
743
+ var ue = u("┌", "T");
744
+ var o = u("│", "|");
745
+ var d2 = u("└", "—");
746
+ var k2 = u("●", ">");
747
+ var P2 = u("○", " ");
748
+ var A2 = u("◻", "[•]");
749
+ var T = u("◼", "[+]");
750
+ var F = u("◻", "[ ]");
751
+ var $e = u("▪", "•");
752
+ var _2 = u("─", "-");
753
+ var me = u("╮", "+");
754
+ var de = u("├", "+");
755
+ var pe = u("╯", "+");
756
+ var q = u("●", "•");
757
+ var D = u("◆", "*");
758
+ var U2 = u("▲", "!");
759
+ var K2 = u("■", "x");
760
+ var b2 = (t) => {
761
+ switch (t) {
762
+ case "initial":
763
+ case "active":
764
+ return import_picocolors2.default.cyan(le);
765
+ case "cancel":
766
+ return import_picocolors2.default.red(L2);
767
+ case "error":
768
+ return import_picocolors2.default.yellow(W2);
769
+ case "submit":
770
+ return import_picocolors2.default.green(C);
771
+ }
772
+ };
773
+ var G2 = (t) => {
774
+ const { cursor: n, options: r2, style: i } = t, s = t.maxItems ?? Number.POSITIVE_INFINITY, c = Math.max(process.stdout.rows - 4, 0), a = Math.min(c, Math.max(s, 5));
775
+ let l2 = 0;
776
+ n >= l2 + a - 3 ? l2 = Math.max(Math.min(n - a + 3, r2.length - a), 0) : n < l2 + 2 && (l2 = Math.max(n - 2, 0));
777
+ const $2 = a < r2.length && l2 > 0, g2 = a < r2.length && l2 + a < r2.length;
778
+ return r2.slice(l2, l2 + a).map((p2, v2, f) => {
779
+ const j2 = v2 === 0 && $2, E = v2 === f.length - 1 && g2;
780
+ return j2 || E ? import_picocolors2.default.dim("...") : i(p2, v2 + l2 === n);
781
+ });
782
+ };
783
+ var he = (t) => new RD({ validate: t.validate, placeholder: t.placeholder, defaultValue: t.defaultValue, initialValue: t.initialValue, render() {
784
+ const n = `${import_picocolors2.default.gray(o)}
785
+ ${b2(this.state)} ${t.message}
786
+ `, r2 = t.placeholder ? import_picocolors2.default.inverse(t.placeholder[0]) + import_picocolors2.default.dim(t.placeholder.slice(1)) : import_picocolors2.default.inverse(import_picocolors2.default.hidden("_")), i = this.value ? this.valueWithCursor : r2;
787
+ switch (this.state) {
788
+ case "error":
789
+ return `${n.trim()}
790
+ ${import_picocolors2.default.yellow(o)} ${i}
791
+ ${import_picocolors2.default.yellow(d2)} ${import_picocolors2.default.yellow(this.error)}
792
+ `;
793
+ case "submit":
794
+ return `${n}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.dim(this.value || t.placeholder)}`;
795
+ case "cancel":
796
+ return `${n}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(this.value ?? ""))}${this.value?.trim() ? `
797
+ ${import_picocolors2.default.gray(o)}` : ""}`;
798
+ default:
799
+ return `${n}${import_picocolors2.default.cyan(o)} ${i}
800
+ ${import_picocolors2.default.cyan(d2)}
801
+ `;
802
+ }
803
+ } }).prompt();
804
+ var ge = (t) => new MD({ validate: t.validate, mask: t.mask ?? $e, render() {
805
+ const n = `${import_picocolors2.default.gray(o)}
806
+ ${b2(this.state)} ${t.message}
807
+ `, r2 = this.valueWithCursor, i = this.masked;
808
+ switch (this.state) {
809
+ case "error":
810
+ return `${n.trim()}
811
+ ${import_picocolors2.default.yellow(o)} ${i}
812
+ ${import_picocolors2.default.yellow(d2)} ${import_picocolors2.default.yellow(this.error)}
813
+ `;
814
+ case "submit":
815
+ return `${n}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.dim(i)}`;
816
+ case "cancel":
817
+ return `${n}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(i ?? ""))}${i ? `
818
+ ${import_picocolors2.default.gray(o)}` : ""}`;
819
+ default:
820
+ return `${n}${import_picocolors2.default.cyan(o)} ${r2}
821
+ ${import_picocolors2.default.cyan(d2)}
822
+ `;
823
+ }
824
+ } }).prompt();
825
+ var ye = (t) => {
826
+ const n = t.active ?? "Yes", r2 = t.inactive ?? "No";
827
+ return new dD({ active: n, inactive: r2, initialValue: t.initialValue ?? true, render() {
828
+ const i = `${import_picocolors2.default.gray(o)}
829
+ ${b2(this.state)} ${t.message}
830
+ `, s = this.value ? n : r2;
831
+ switch (this.state) {
832
+ case "submit":
833
+ return `${i}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.dim(s)}`;
834
+ case "cancel":
835
+ return `${i}${import_picocolors2.default.gray(o)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(s))}
836
+ ${import_picocolors2.default.gray(o)}`;
837
+ default:
838
+ return `${i}${import_picocolors2.default.cyan(o)} ${this.value ? `${import_picocolors2.default.green(k2)} ${n}` : `${import_picocolors2.default.dim(P2)} ${import_picocolors2.default.dim(n)}`} ${import_picocolors2.default.dim("/")} ${this.value ? `${import_picocolors2.default.dim(P2)} ${import_picocolors2.default.dim(r2)}` : `${import_picocolors2.default.green(k2)} ${r2}`}
839
+ ${import_picocolors2.default.cyan(d2)}
840
+ `;
232
841
  }
233
- if (!indentStyle) {
234
- const editorConfig = readText(join(cwd, ".editorconfig"));
235
- if (editorConfig) {
236
- const styleMatch = editorConfig.match(/indent_style\s*=\s*(space|tab)/);
237
- const sizeMatch = editorConfig.match(/indent_size\s*=\s*(\d+)/);
238
- if (styleMatch) {
239
- indentStyle = {
240
- type: styleMatch[1],
241
- width: sizeMatch ? Number.parseInt(sizeMatch[1], 10) : 2,
242
- };
243
- }
244
- }
842
+ } }).prompt();
843
+ };
844
+ var ve = (t) => {
845
+ const n = (r2, i) => {
846
+ const s = r2.label ?? String(r2.value);
847
+ switch (i) {
848
+ case "selected":
849
+ return `${import_picocolors2.default.dim(s)}`;
850
+ case "active":
851
+ return `${import_picocolors2.default.green(k2)} ${s} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}`;
852
+ case "cancelled":
853
+ return `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(s))}`;
854
+ default:
855
+ return `${import_picocolors2.default.dim(P2)} ${import_picocolors2.default.dim(s)}`;
245
856
  }
246
- // Directories
247
- const dirs = listDirs(cwd);
248
- const srcDirs = existsSync(join(cwd, "src"))
249
- ? listDirs(join(cwd, "src"))
250
- : [];
251
- // Monorepo
252
- const monorepo = existsSync(join(cwd, "packages")) || existsSync(join(cwd, "apps"));
253
- // Existing docs
254
- const existingDocs = {
255
- agentsMd: existsSync(join(cwd, "AGENTS.md")),
256
- claudeMd: existsSync(join(cwd, "CLAUDE.md")),
257
- docsDir: existsSync(join(cwd, "docs")),
258
- architectureMd: existsSync(join(cwd, "docs", "architecture.md")),
259
- };
260
- return {
261
- packageManager,
262
- scripts,
263
- language,
264
- framework,
265
- linter,
266
- indentStyle,
267
- dirs,
268
- srcDirs,
269
- monorepo,
270
- existingDocs,
857
+ };
858
+ return new LD({ options: t.options, initialValue: t.initialValue, render() {
859
+ const r2 = `${import_picocolors2.default.gray(o)}
860
+ ${b2(this.state)} ${t.message}
861
+ `;
862
+ switch (this.state) {
863
+ case "submit":
864
+ return `${r2}${import_picocolors2.default.gray(o)} ${n(this.options[this.cursor], "selected")}`;
865
+ case "cancel":
866
+ return `${r2}${import_picocolors2.default.gray(o)} ${n(this.options[this.cursor], "cancelled")}
867
+ ${import_picocolors2.default.gray(o)}`;
868
+ default:
869
+ return `${r2}${import_picocolors2.default.cyan(o)} ${G2({ cursor: this.cursor, options: this.options, maxItems: t.maxItems, style: (i, s) => n(i, s ? "active" : "inactive") }).join(`
870
+ ${import_picocolors2.default.cyan(o)} `)}
871
+ ${import_picocolors2.default.cyan(d2)}
872
+ `;
873
+ }
874
+ } }).prompt();
875
+ };
876
+ var fe = (t) => {
877
+ const n = (r2, i) => {
878
+ const s = r2.label ?? String(r2.value);
879
+ return i === "active" ? `${import_picocolors2.default.cyan(A2)} ${s} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}` : i === "selected" ? `${import_picocolors2.default.green(T)} ${import_picocolors2.default.dim(s)} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(s))}` : i === "active-selected" ? `${import_picocolors2.default.green(T)} ${s} ${r2.hint ? import_picocolors2.default.dim(`(${r2.hint})`) : ""}` : i === "submitted" ? `${import_picocolors2.default.dim(s)}` : `${import_picocolors2.default.dim(F)} ${import_picocolors2.default.dim(s)}`;
880
+ };
881
+ return new SD({ options: t.options, initialValues: t.initialValues, required: t.required ?? true, cursorAt: t.cursorAt, validate(r2) {
882
+ if (this.required && r2.length === 0)
883
+ return `Please select at least one option.
884
+ ${import_picocolors2.default.reset(import_picocolors2.default.dim(`Press ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" space ")))} to select, ${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(" enter ")))} to submit`))}`;
885
+ }, render() {
886
+ const r2 = `${import_picocolors2.default.gray(o)}
887
+ ${b2(this.state)} ${t.message}
888
+ `, i = (s, c) => {
889
+ const a = this.value.includes(s.value);
890
+ return c && a ? n(s, "active-selected") : a ? n(s, "selected") : n(s, c ? "active" : "inactive");
271
891
  };
892
+ switch (this.state) {
893
+ case "submit":
894
+ return `${r2}${import_picocolors2.default.gray(o)} ${this.options.filter(({ value: s }) => this.value.includes(s)).map((s) => n(s, "submitted")).join(import_picocolors2.default.dim(", ")) || import_picocolors2.default.dim("none")}`;
895
+ case "cancel": {
896
+ const s = this.options.filter(({ value: c }) => this.value.includes(c)).map((c) => n(c, "cancelled")).join(import_picocolors2.default.dim(", "));
897
+ return `${r2}${import_picocolors2.default.gray(o)} ${s.trim() ? `${s}
898
+ ${import_picocolors2.default.gray(o)}` : ""}`;
899
+ }
900
+ case "error": {
901
+ const s = this.error.split(`
902
+ `).map((c, a) => a === 0 ? `${import_picocolors2.default.yellow(d2)} ${import_picocolors2.default.yellow(c)}` : ` ${c}`).join(`
903
+ `);
904
+ return `${r2 + import_picocolors2.default.yellow(o)} ${G2({ options: this.options, cursor: this.cursor, maxItems: t.maxItems, style: i }).join(`
905
+ ${import_picocolors2.default.yellow(o)} `)}
906
+ ${s}
907
+ `;
908
+ }
909
+ default:
910
+ return `${r2}${import_picocolors2.default.cyan(o)} ${G2({ options: this.options, cursor: this.cursor, maxItems: t.maxItems, style: i }).join(`
911
+ ${import_picocolors2.default.cyan(o)} `)}
912
+ ${import_picocolors2.default.cyan(d2)}
913
+ `;
914
+ }
915
+ } }).prompt();
916
+ };
917
+ var xe = (t = "") => {
918
+ process.stdout.write(`${import_picocolors2.default.gray(d2)} ${import_picocolors2.default.red(t)}
919
+
920
+ `);
921
+ };
922
+ var Se = (t = "") => {
923
+ process.stdout.write(`${import_picocolors2.default.gray(o)}
924
+ ${import_picocolors2.default.gray(d2)} ${t}
925
+
926
+ `);
927
+ };
928
+ var M2 = { message: (t = "", { symbol: n = import_picocolors2.default.gray(o) } = {}) => {
929
+ const r2 = [`${import_picocolors2.default.gray(o)}`];
930
+ if (t) {
931
+ const [i, ...s] = t.split(`
932
+ `);
933
+ r2.push(`${n} ${i}`, ...s.map((c) => `${import_picocolors2.default.gray(o)} ${c}`));
934
+ }
935
+ process.stdout.write(`${r2.join(`
936
+ `)}
937
+ `);
938
+ }, info: (t) => {
939
+ M2.message(t, { symbol: import_picocolors2.default.blue(q) });
940
+ }, success: (t) => {
941
+ M2.message(t, { symbol: import_picocolors2.default.green(D) });
942
+ }, step: (t) => {
943
+ M2.message(t, { symbol: import_picocolors2.default.green(C) });
944
+ }, warn: (t) => {
945
+ M2.message(t, { symbol: import_picocolors2.default.yellow(U2) });
946
+ }, warning: (t) => {
947
+ M2.warn(t);
948
+ }, error: (t) => {
949
+ M2.message(t, { symbol: import_picocolors2.default.red(K2) });
950
+ } };
951
+ var J2 = `${import_picocolors2.default.gray(o)} `;
952
+ var Y2 = ({ indicator: t = "dots" } = {}) => {
953
+ const n = V2 ? ["◒", "◐", "◓", "◑"] : ["•", "o", "O", "0"], r2 = V2 ? 80 : 120, i = process.env.CI === "true";
954
+ let s, c, a = false, l2 = "", $2, g2 = performance.now();
955
+ const p2 = (m2) => {
956
+ const h2 = m2 > 1 ? "Something went wrong" : "Canceled";
957
+ a && N2(h2, m2);
958
+ }, v2 = () => p2(2), f = () => p2(1), j2 = () => {
959
+ process.on("uncaughtExceptionMonitor", v2), process.on("unhandledRejection", v2), process.on("SIGINT", f), process.on("SIGTERM", f), process.on("exit", p2);
960
+ }, E = () => {
961
+ process.removeListener("uncaughtExceptionMonitor", v2), process.removeListener("unhandledRejection", v2), process.removeListener("SIGINT", f), process.removeListener("SIGTERM", f), process.removeListener("exit", p2);
962
+ }, B2 = () => {
963
+ if ($2 === undefined)
964
+ return;
965
+ i && process.stdout.write(`
966
+ `);
967
+ const m2 = $2.split(`
968
+ `);
969
+ process.stdout.write(import_sisteransi2.cursor.move(-999, m2.length - 1)), process.stdout.write(import_sisteransi2.erase.down(m2.length));
970
+ }, R2 = (m2) => m2.replace(/\.+$/, ""), O2 = (m2) => {
971
+ const h2 = (performance.now() - m2) / 1000, w2 = Math.floor(h2 / 60), I2 = Math.floor(h2 % 60);
972
+ return w2 > 0 ? `[${w2}m ${I2}s]` : `[${I2}s]`;
973
+ }, H2 = (m2 = "") => {
974
+ a = true, s = fD(), l2 = R2(m2), g2 = performance.now(), process.stdout.write(`${import_picocolors2.default.gray(o)}
975
+ `);
976
+ let h2 = 0, w2 = 0;
977
+ j2(), c = setInterval(() => {
978
+ if (i && l2 === $2)
979
+ return;
980
+ B2(), $2 = l2;
981
+ const I2 = import_picocolors2.default.magenta(n[h2]);
982
+ if (i)
983
+ process.stdout.write(`${I2} ${l2}...`);
984
+ else if (t === "timer")
985
+ process.stdout.write(`${I2} ${l2} ${O2(g2)}`);
986
+ else {
987
+ const z2 = ".".repeat(Math.floor(w2)).slice(0, 3);
988
+ process.stdout.write(`${I2} ${l2}${z2}`);
989
+ }
990
+ h2 = h2 + 1 < n.length ? h2 + 1 : 0, w2 = w2 < n.length ? w2 + 0.125 : 0;
991
+ }, r2);
992
+ }, N2 = (m2 = "", h2 = 0) => {
993
+ a = false, clearInterval(c), B2();
994
+ const w2 = h2 === 0 ? import_picocolors2.default.green(C) : h2 === 1 ? import_picocolors2.default.red(L2) : import_picocolors2.default.red(W2);
995
+ l2 = R2(m2 ?? l2), t === "timer" ? process.stdout.write(`${w2} ${l2} ${O2(g2)}
996
+ `) : process.stdout.write(`${w2} ${l2}
997
+ `), E(), s();
998
+ };
999
+ return { start: H2, stop: N2, message: (m2 = "") => {
1000
+ l2 = R2(m2 ?? l2);
1001
+ } };
1002
+ };
1003
+
1004
+ // src/tui/docs.ts
1005
+ var IGNORED_DIRS = new Set([
1006
+ "node_modules",
1007
+ ".git",
1008
+ "dist",
1009
+ "build",
1010
+ ".next",
1011
+ ".nuxt",
1012
+ ".output",
1013
+ ".vercel",
1014
+ ".turbo",
1015
+ ".cache",
1016
+ "coverage",
1017
+ ".harmony-worktrees",
1018
+ "__pycache__",
1019
+ "target",
1020
+ "vendor"
1021
+ ]);
1022
+ function readJson(filePath) {
1023
+ try {
1024
+ return JSON.parse(readFileSync(filePath, "utf-8"));
1025
+ } catch {
1026
+ return null;
1027
+ }
272
1028
  }
273
- // ── Generators ──────────────────────────────────────────────────────────────
274
- /** Build a human-friendly run command prefix. */
275
- function runCmd(pm) {
276
- if (pm === "bun")
277
- return "bun run";
278
- if (pm === "pnpm")
279
- return "pnpm run";
280
- if (pm === "yarn")
281
- return "yarn";
282
- return "npm run";
283
- }
284
- /** Guess a short description for a package.json script based on its name. */
285
- function describeScript(name) {
286
- const map = {
287
- dev: "Dev server",
288
- start: "Start server",
289
- build: "Production build",
290
- lint: "Lint",
291
- "lint:fix": "Lint + autofix",
292
- format: "Format code",
293
- test: "Run tests",
294
- "test:watch": "Run tests (watch)",
295
- "test:e2e": "End-to-end tests",
296
- typecheck: "Type-check",
297
- "type-check": "Type-check",
298
- preview: "Preview production build",
299
- deploy: "Deploy",
300
- generate: "Code generation",
301
- migrate: "Run migrations",
302
- seed: "Seed database",
303
- clean: "Clean build artifacts",
304
- prepare: "Prepare (husky, etc.)",
1029
+ function readText(filePath) {
1030
+ try {
1031
+ return readFileSync(filePath, "utf-8");
1032
+ } catch {
1033
+ return null;
1034
+ }
1035
+ }
1036
+ function listDirs(dirPath) {
1037
+ try {
1038
+ return readdirSync(dirPath).filter((entry) => {
1039
+ if (IGNORED_DIRS.has(entry) || entry.startsWith("."))
1040
+ return false;
1041
+ try {
1042
+ return statSync(join(dirPath, entry)).isDirectory();
1043
+ } catch {
1044
+ return false;
1045
+ }
1046
+ });
1047
+ } catch {
1048
+ return [];
1049
+ }
1050
+ }
1051
+ var DIR_DESCRIPTIONS = {
1052
+ components: "UI components",
1053
+ pages: "Route-level pages",
1054
+ routes: "Route-level pages",
1055
+ views: "Route-level pages",
1056
+ hooks: "Custom hooks",
1057
+ lib: "Utilities",
1058
+ utils: "Utilities",
1059
+ api: "API / server code",
1060
+ server: "API / server code",
1061
+ contexts: "State management",
1062
+ store: "State management",
1063
+ stores: "State management",
1064
+ types: "Type definitions",
1065
+ styles: "Stylesheets",
1066
+ public: "Static assets",
1067
+ static: "Static assets",
1068
+ assets: "Static assets",
1069
+ supabase: "Supabase backend",
1070
+ functions: "Edge functions",
1071
+ packages: "Monorepo packages",
1072
+ apps: "Monorepo applications",
1073
+ src: "Source code",
1074
+ test: "Tests",
1075
+ tests: "Tests",
1076
+ __tests__: "Tests",
1077
+ scripts: "Build / utility scripts",
1078
+ config: "Configuration",
1079
+ docs: "Documentation",
1080
+ migrations: "Database migrations",
1081
+ prisma: "Prisma schema & migrations",
1082
+ e2e: "End-to-end tests",
1083
+ cypress: "Cypress tests"
1084
+ };
1085
+ function describeDir(name) {
1086
+ return DIR_DESCRIPTIONS[name.toLowerCase()] ?? name;
1087
+ }
1088
+ function scanProject(cwd) {
1089
+ let packageManager = null;
1090
+ if (existsSync(join(cwd, "bun.lock")) || existsSync(join(cwd, "bun.lockb"))) {
1091
+ packageManager = "bun";
1092
+ } else if (existsSync(join(cwd, "pnpm-lock.yaml"))) {
1093
+ packageManager = "pnpm";
1094
+ } else if (existsSync(join(cwd, "yarn.lock"))) {
1095
+ packageManager = "yarn";
1096
+ } else if (existsSync(join(cwd, "package.json"))) {
1097
+ packageManager = "npm";
1098
+ }
1099
+ const pkg = readJson(join(cwd, "package.json"));
1100
+ const scripts = pkg && typeof pkg.scripts === "object" && pkg.scripts !== null ? pkg.scripts : {};
1101
+ let language = "unknown";
1102
+ if (existsSync(join(cwd, "tsconfig.json"))) {
1103
+ language = "typescript";
1104
+ } else if (existsSync(join(cwd, "go.mod"))) {
1105
+ language = "go";
1106
+ } else if (existsSync(join(cwd, "Cargo.toml"))) {
1107
+ language = "rust";
1108
+ } else if (existsSync(join(cwd, "setup.py")) || existsSync(join(cwd, "pyproject.toml"))) {
1109
+ language = "python";
1110
+ } else if (pkg) {
1111
+ language = "javascript";
1112
+ }
1113
+ let framework = null;
1114
+ if (pkg) {
1115
+ const deps = {
1116
+ ...typeof pkg.dependencies === "object" ? pkg.dependencies : {},
1117
+ ...typeof pkg.devDependencies === "object" ? pkg.devDependencies : {}
305
1118
  };
306
- return map[name] ?? "";
307
- }
308
- /**
309
- * Generate a scaffold AGENTS.md from project metadata.
310
- */
311
- export function generateAgentsMd(info, _cwd) {
312
- const lang = info.language === "typescript"
313
- ? "TypeScript"
314
- : info.language === "javascript"
315
- ? "JavaScript"
316
- : info.language;
317
- const frameworkLabel = info.framework ? `${info.framework} ` : "";
318
- const monoLabel = info.monorepo ? " (monorepo)" : "";
319
- const lines = [];
320
- lines.push("# AGENTS.md");
321
- lines.push("");
322
- lines.push(`${frameworkLabel}${lang} project${monoLabel}.`);
323
- lines.push("");
324
- // Commands
325
- const scriptEntries = Object.entries(info.scripts);
326
- if (scriptEntries.length > 0 && info.packageManager) {
327
- const prefix = runCmd(info.packageManager);
328
- lines.push("## Commands");
329
- lines.push("");
330
- lines.push("```bash");
331
- // Calculate padding for alignment
332
- const commands = scriptEntries.map(([name]) => `${prefix} ${name}`);
333
- const maxLen = Math.max(...commands.map((c) => c.length));
334
- for (let i = 0; i < scriptEntries.length; i++) {
335
- const [name] = scriptEntries[i];
336
- const cmd = commands[i];
337
- const desc = describeScript(name);
338
- if (desc) {
339
- lines.push(`${cmd}${" ".repeat(maxLen - cmd.length + 4)}# ${desc}`);
340
- }
341
- else {
342
- lines.push(cmd);
343
- }
344
- }
345
- lines.push("```");
346
- lines.push("");
1119
+ if (deps.next) {
1120
+ framework = "next";
1121
+ } else if (deps.react && deps.vite) {
1122
+ framework = "react+vite";
1123
+ } else if (deps.react) {
1124
+ framework = "react";
1125
+ } else if (deps.vue && deps.vite) {
1126
+ framework = "vue+vite";
1127
+ } else if (deps.vue && deps.nuxt) {
1128
+ framework = "nuxt";
1129
+ } else if (deps.vue) {
1130
+ framework = "vue";
1131
+ } else if (deps.astro) {
1132
+ framework = "astro";
1133
+ } else if (deps.svelte) {
1134
+ framework = "svelte";
1135
+ } else if (deps.express) {
1136
+ framework = "express";
1137
+ } else if (deps.fastify) {
1138
+ framework = "fastify";
1139
+ } else if (deps.hono) {
1140
+ framework = "hono";
347
1141
  }
348
- // Code standards
349
- lines.push("## Code Standards");
350
- lines.push("");
351
- const langLabel = info.language === "typescript" ? "TypeScript" : "JavaScript";
352
- if (info.language === "typescript" || info.language === "javascript") {
353
- lines.push(`- ${langLabel} with ES modules`);
1142
+ }
1143
+ let linter = null;
1144
+ if (existsSync(join(cwd, "biome.json")) || existsSync(join(cwd, "biome.jsonc"))) {
1145
+ linter = "biome";
1146
+ } else {
1147
+ const eslintFiles = [
1148
+ ".eslintrc",
1149
+ ".eslintrc.js",
1150
+ ".eslintrc.cjs",
1151
+ ".eslintrc.json",
1152
+ ".eslintrc.yml",
1153
+ ".eslintrc.yaml",
1154
+ "eslint.config.js",
1155
+ "eslint.config.mjs",
1156
+ "eslint.config.cjs",
1157
+ "eslint.config.ts"
1158
+ ];
1159
+ if (eslintFiles.some((f) => existsSync(join(cwd, f)))) {
1160
+ linter = "eslint";
1161
+ } else {
1162
+ const prettierFiles = [
1163
+ ".prettierrc",
1164
+ ".prettierrc.js",
1165
+ ".prettierrc.json",
1166
+ ".prettierrc.yml",
1167
+ ".prettierrc.yaml",
1168
+ "prettier.config.js",
1169
+ "prettier.config.mjs"
1170
+ ];
1171
+ if (prettierFiles.some((f) => existsSync(join(cwd, f)))) {
1172
+ linter = "prettier";
1173
+ }
354
1174
  }
355
- if (info.indentStyle) {
356
- const unit = info.indentStyle.type === "tab" ? "tab" : "space";
357
- lines.push(`- ${info.indentStyle.width}-${unit} indentation`);
1175
+ }
1176
+ let indentStyle = null;
1177
+ const biome = readJson(join(cwd, "biome.json")) ?? readJson(join(cwd, "biome.jsonc"));
1178
+ if (biome) {
1179
+ const formatter = biome.formatter;
1180
+ if (formatter) {
1181
+ const type = formatter.indentStyle === "tab" ? "tab" : "space";
1182
+ const width = typeof formatter.indentWidth === "number" ? formatter.indentWidth : 2;
1183
+ indentStyle = { type, width };
358
1184
  }
359
- if (info.linter) {
360
- lines.push(`- Linted with ${info.linter}`);
1185
+ }
1186
+ if (!indentStyle) {
1187
+ const editorConfig = readText(join(cwd, ".editorconfig"));
1188
+ if (editorConfig) {
1189
+ const styleMatch = editorConfig.match(/indent_style\s*=\s*(space|tab)/);
1190
+ const sizeMatch = editorConfig.match(/indent_size\s*=\s*(\d+)/);
1191
+ if (styleMatch) {
1192
+ indentStyle = {
1193
+ type: styleMatch[1],
1194
+ width: sizeMatch ? Number.parseInt(sizeMatch[1], 10) : 2
1195
+ };
1196
+ }
361
1197
  }
1198
+ }
1199
+ const dirs = listDirs(cwd);
1200
+ const srcDirs = existsSync(join(cwd, "src")) ? listDirs(join(cwd, "src")) : [];
1201
+ const monorepo = existsSync(join(cwd, "packages")) || existsSync(join(cwd, "apps"));
1202
+ const existingDocs = {
1203
+ agentsMd: existsSync(join(cwd, "AGENTS.md")),
1204
+ claudeMd: existsSync(join(cwd, "CLAUDE.md")),
1205
+ docsDir: existsSync(join(cwd, "docs")),
1206
+ architectureMd: existsSync(join(cwd, "docs", "architecture.md"))
1207
+ };
1208
+ return {
1209
+ packageManager,
1210
+ scripts,
1211
+ language,
1212
+ framework,
1213
+ linter,
1214
+ indentStyle,
1215
+ dirs,
1216
+ srcDirs,
1217
+ monorepo,
1218
+ existingDocs
1219
+ };
1220
+ }
1221
+ function runCmd(pm) {
1222
+ if (pm === "bun")
1223
+ return "bun run";
1224
+ if (pm === "pnpm")
1225
+ return "pnpm run";
1226
+ if (pm === "yarn")
1227
+ return "yarn";
1228
+ return "npm run";
1229
+ }
1230
+ function describeScript(name) {
1231
+ const map = {
1232
+ dev: "Dev server",
1233
+ start: "Start server",
1234
+ build: "Production build",
1235
+ lint: "Lint",
1236
+ "lint:fix": "Lint + autofix",
1237
+ format: "Format code",
1238
+ test: "Run tests",
1239
+ "test:watch": "Run tests (watch)",
1240
+ "test:e2e": "End-to-end tests",
1241
+ typecheck: "Type-check",
1242
+ "type-check": "Type-check",
1243
+ preview: "Preview production build",
1244
+ deploy: "Deploy",
1245
+ generate: "Code generation",
1246
+ migrate: "Run migrations",
1247
+ seed: "Seed database",
1248
+ clean: "Clean build artifacts",
1249
+ prepare: "Prepare (husky, etc.)"
1250
+ };
1251
+ return map[name] ?? "";
1252
+ }
1253
+ function generateAgentsMd(info, _cwd) {
1254
+ const lang = info.language === "typescript" ? "TypeScript" : info.language === "javascript" ? "JavaScript" : info.language;
1255
+ const frameworkLabel = info.framework ? `${info.framework} ` : "";
1256
+ const monoLabel = info.monorepo ? " (monorepo)" : "";
1257
+ const lines = [];
1258
+ lines.push("# AGENTS.md");
1259
+ lines.push("");
1260
+ lines.push(`${frameworkLabel}${lang} project${monoLabel}.`);
1261
+ lines.push("");
1262
+ const scriptEntries = Object.entries(info.scripts);
1263
+ if (scriptEntries.length > 0 && info.packageManager) {
1264
+ const prefix = runCmd(info.packageManager);
1265
+ lines.push("## Commands");
362
1266
  lines.push("");
363
- // Architecture
364
- lines.push("## Architecture");
365
- lines.push("");
366
- for (const dir of info.dirs) {
367
- lines.push(`- \`${dir}/\` ${describeDir(dir)}`);
368
- }
369
- if (info.srcDirs.length > 0) {
370
- for (const sub of info.srcDirs) {
371
- lines.push(` - \`src/${sub}/\` — ${describeDir(sub)}`);
372
- }
1267
+ lines.push("```bash");
1268
+ const commands = scriptEntries.map(([name]) => `${prefix} ${name}`);
1269
+ const maxLen = Math.max(...commands.map((c) => c.length));
1270
+ for (let i = 0;i < scriptEntries.length; i++) {
1271
+ const [name] = scriptEntries[i];
1272
+ const cmd = commands[i];
1273
+ const desc = describeScript(name);
1274
+ if (desc) {
1275
+ lines.push(`${cmd}${" ".repeat(maxLen - cmd.length + 4)}# ${desc}`);
1276
+ } else {
1277
+ lines.push(cmd);
1278
+ }
373
1279
  }
1280
+ lines.push("```");
374
1281
  lines.push("");
375
- return lines.join("\n");
376
- }
377
- /**
378
- * Generate a lean CLAUDE.md pointer file.
379
- */
380
- export function generateClaudeMd(info) {
381
- const lines = [];
382
- lines.push("# CLAUDE.md");
383
- lines.push("");
384
- lines.push("@AGENTS.md");
385
- if (info.existingDocs.architectureMd || info.dirs.includes("docs")) {
386
- lines.push("@docs/architecture.md");
1282
+ }
1283
+ lines.push("## Code Standards");
1284
+ lines.push("");
1285
+ const langLabel = info.language === "typescript" ? "TypeScript" : "JavaScript";
1286
+ if (info.language === "typescript" || info.language === "javascript") {
1287
+ lines.push(`- ${langLabel} with ES modules`);
1288
+ }
1289
+ if (info.indentStyle) {
1290
+ const unit = info.indentStyle.type === "tab" ? "tab" : "space";
1291
+ lines.push(`- ${info.indentStyle.width}-${unit} indentation`);
1292
+ }
1293
+ if (info.linter) {
1294
+ lines.push(`- Linted with ${info.linter}`);
1295
+ }
1296
+ lines.push("");
1297
+ lines.push("## Architecture");
1298
+ lines.push("");
1299
+ for (const dir of info.dirs) {
1300
+ lines.push(`- \`${dir}/\` — ${describeDir(dir)}`);
1301
+ }
1302
+ if (info.srcDirs.length > 0) {
1303
+ for (const sub of info.srcDirs) {
1304
+ lines.push(` - \`src/${sub}/\` — ${describeDir(sub)}`);
387
1305
  }
1306
+ }
1307
+ lines.push("");
1308
+ return lines.join(`
1309
+ `);
1310
+ }
1311
+ function generateClaudeMd(info) {
1312
+ const lines = [];
1313
+ lines.push("# CLAUDE.md");
1314
+ lines.push("");
1315
+ lines.push("@AGENTS.md");
1316
+ if (info.existingDocs.architectureMd || info.dirs.includes("docs")) {
1317
+ lines.push("@docs/architecture.md");
1318
+ }
1319
+ lines.push("");
1320
+ return lines.join(`
1321
+ `);
1322
+ }
1323
+ function generateArchitectureMd(info, _cwd) {
1324
+ const lines = [];
1325
+ lines.push("# Architecture");
1326
+ lines.push("");
1327
+ lines.push("## Directory Structure");
1328
+ lines.push("");
1329
+ for (const dir of info.dirs) {
1330
+ lines.push(`- \`${dir}/\` — ${describeDir(dir)}`);
1331
+ }
1332
+ if (info.srcDirs.length > 0) {
388
1333
  lines.push("");
389
- return lines.join("\n");
390
- }
391
- /**
392
- * Generate an architecture.md scaffold.
393
- */
394
- export function generateArchitectureMd(info, _cwd) {
395
- const lines = [];
396
- lines.push("# Architecture");
397
- lines.push("");
398
- lines.push("## Directory Structure");
1334
+ lines.push("### `src/`");
399
1335
  lines.push("");
400
- for (const dir of info.dirs) {
401
- lines.push(`- \`${dir}/\` — ${describeDir(dir)}`);
402
- }
403
- if (info.srcDirs.length > 0) {
404
- lines.push("");
405
- lines.push("### `src/`");
406
- lines.push("");
407
- for (const sub of info.srcDirs) {
408
- lines.push(`- \`src/${sub}/\` — ${describeDir(sub)}`);
409
- }
1336
+ for (const sub of info.srcDirs) {
1337
+ lines.push(`- \`src/${sub}/\` — ${describeDir(sub)}`);
410
1338
  }
411
- lines.push("");
412
- return lines.join("\n");
413
- }
414
- // ── Verification ────────────────────────────────────────────────────────────
415
- /** Vague phrases that provide no actionable guidance to agents. */
416
- const VAGUE_STANDARDS = [
417
- "follow best practices",
418
- "use best practices",
419
- "keep it clean",
420
- "write clean code",
421
- "maintain code quality",
422
- "ensure quality",
423
- "use proper naming",
424
- "follow conventions",
425
- "be consistent",
1339
+ }
1340
+ lines.push("");
1341
+ return lines.join(`
1342
+ `);
1343
+ }
1344
+ var VAGUE_STANDARDS = [
1345
+ "follow best practices",
1346
+ "use best practices",
1347
+ "keep it clean",
1348
+ "write clean code",
1349
+ "maintain code quality",
1350
+ "ensure quality",
1351
+ "use proper naming",
1352
+ "follow conventions",
1353
+ "be consistent"
426
1354
  ];
427
- /**
428
- * Verify existing docs for broken references, stale commands, dead paths,
429
- * and structural quality issues from the setup-agent-docs quality checks.
430
- */
431
- export function verifyDocs(cwd) {
432
- const issues = [];
433
- const claudeMd = readText(join(cwd, "CLAUDE.md"));
434
- const agentsMd = readText(join(cwd, "AGENTS.md"));
435
- const pkg = readJson(join(cwd, "package.json"));
436
- const pkgScripts = pkg && typeof pkg.scripts === "object" && pkg.scripts !== null
437
- ? pkg.scripts
438
- : {};
439
- // ── CLAUDE.md checks ──────────────────────────────────────────────────
440
- const projectRoot = resolve(cwd);
441
- if (claudeMd) {
442
- // Check @-references exist on disk (with path traversal protection)
443
- const importedFiles = [];
444
- for (const line of claudeMd.split("\n")) {
445
- const match = line.match(/^@(.+)$/);
446
- if (match) {
447
- const refPath = match[1].trim();
448
- // Reject absolute paths
449
- if (isAbsolute(refPath)) {
450
- issues.push({
451
- severity: "error",
452
- file: "CLAUDE.md",
453
- message: `@ reference uses an absolute path: ${refPath}`,
454
- fix: "Use a project-relative path under the repository root",
455
- });
456
- continue;
457
- }
458
- // Resolve and ensure the path stays inside the project root
459
- const resolvedPath = resolve(projectRoot, refPath);
460
- if (resolvedPath !== projectRoot &&
461
- !resolvedPath.startsWith(projectRoot + sep)) {
462
- issues.push({
463
- severity: "error",
464
- file: "CLAUDE.md",
465
- message: `@ reference escapes project root: ${refPath}`,
466
- fix: "Remove traversal segments (../) and keep references inside the repo",
467
- });
468
- continue;
469
- }
470
- importedFiles.push({ ref: refPath, resolved: resolvedPath });
471
- if (!existsSync(resolvedPath)) {
472
- issues.push({
473
- severity: "error",
474
- file: "CLAUDE.md",
475
- message: `Referenced file does not exist: ${refPath}`,
476
- fix: `Remove the @${refPath} line or create the file`,
477
- });
478
- }
479
- }
1355
+ function verifyDocs(cwd) {
1356
+ const issues = [];
1357
+ const claudeMd = readText(join(cwd, "CLAUDE.md"));
1358
+ const agentsMd = readText(join(cwd, "AGENTS.md"));
1359
+ const pkg = readJson(join(cwd, "package.json"));
1360
+ const pkgScripts = pkg && typeof pkg.scripts === "object" && pkg.scripts !== null ? pkg.scripts : {};
1361
+ const projectRoot = resolve(cwd);
1362
+ if (claudeMd) {
1363
+ const importedFiles = [];
1364
+ for (const line of claudeMd.split(`
1365
+ `)) {
1366
+ const match = line.match(/^@(.+)$/);
1367
+ if (match) {
1368
+ const refPath = match[1].trim();
1369
+ if (isAbsolute(refPath)) {
1370
+ issues.push({
1371
+ severity: "error",
1372
+ file: "CLAUDE.md",
1373
+ message: `@ reference uses an absolute path: ${refPath}`,
1374
+ fix: "Use a project-relative path under the repository root"
1375
+ });
1376
+ continue;
480
1377
  }
481
- // Line count — CLAUDE.md should be under 100 lines (lean, @imports only)
482
- const claudeLines = claudeMd.split("\n").length;
483
- if (claudeLines > 100) {
484
- issues.push({
485
- severity: "warning",
486
- file: "CLAUDE.md",
487
- message: `CLAUDE.md is ${claudeLines} lines (recommended: under 100)`,
488
- fix: "Move detailed content to AGENTS.md or docs/ files and use @imports",
489
- });
1378
+ const resolvedPath = resolve(projectRoot, refPath);
1379
+ if (resolvedPath !== projectRoot && !resolvedPath.startsWith(projectRoot + sep)) {
1380
+ issues.push({
1381
+ severity: "error",
1382
+ file: "CLAUDE.md",
1383
+ message: `@ reference escapes project root: ${refPath}`,
1384
+ fix: "Remove traversal segments (../) and keep references inside the repo"
1385
+ });
1386
+ continue;
490
1387
  }
491
- // Duplication — check if CLAUDE.md duplicates content from imported files
492
- if (importedFiles.length > 0) {
493
- const claudeHeadings = extractHeadings(claudeMd);
494
- for (const { ref: refPath, resolved: resolvedPath } of importedFiles) {
495
- const refContent = readText(resolvedPath);
496
- if (!refContent)
497
- continue;
498
- const refHeadings = extractHeadings(refContent);
499
- // Flag if CLAUDE.md repeats section headings from imported files
500
- for (const heading of claudeHeadings) {
501
- if (refHeadings.has(heading)) {
502
- issues.push({
503
- severity: "warning",
504
- file: "CLAUDE.md",
505
- message: `Section "${heading}" duplicates content from @${refPath}`,
506
- fix: `Remove the "${heading}" section — it's already included via @import`,
507
- });
508
- }
509
- }
510
- }
1388
+ importedFiles.push({ ref: refPath, resolved: resolvedPath });
1389
+ if (!existsSync(resolvedPath)) {
1390
+ issues.push({
1391
+ severity: "error",
1392
+ file: "CLAUDE.md",
1393
+ message: `Referenced file does not exist: ${refPath}`,
1394
+ fix: `Remove the @${refPath} line or create the file`
1395
+ });
511
1396
  }
1397
+ }
512
1398
  }
513
- // ── AGENTS.md checks ──────────────────────────────────────────────────
514
- if (agentsMd) {
515
- // Project Context first non-heading, non-blank line should be exactly one line
516
- const agentsLines = agentsMd.split("\n");
517
- const contextLines = [];
518
- let pastFirstHeading = false;
519
- let hitNextSection = false;
520
- for (const line of agentsLines) {
521
- if (!pastFirstHeading) {
522
- if (line.startsWith("# ")) {
523
- pastFirstHeading = true;
524
- }
525
- continue;
526
- }
527
- // Stop at next ## heading
528
- if (line.startsWith("## ")) {
529
- hitNextSection = true;
530
- break;
531
- }
532
- const trimmed = line.trim();
533
- if (trimmed)
534
- contextLines.push(trimmed);
535
- }
536
- if (pastFirstHeading && !hitNextSection && contextLines.length === 0) {
537
- issues.push({
538
- severity: "warning",
539
- file: "AGENTS.md",
540
- message: "Missing project context line after the title heading",
541
- fix: "Add a single-line description: stack + what the project does",
542
- });
543
- }
544
- else if (contextLines.length > 1) {
1399
+ const claudeLines = claudeMd.split(`
1400
+ `).length;
1401
+ if (claudeLines > 100) {
1402
+ issues.push({
1403
+ severity: "warning",
1404
+ file: "CLAUDE.md",
1405
+ message: `CLAUDE.md is ${claudeLines} lines (recommended: under 100)`,
1406
+ fix: "Move detailed content to AGENTS.md or docs/ files and use @imports"
1407
+ });
1408
+ }
1409
+ if (importedFiles.length > 0) {
1410
+ const claudeHeadings = extractHeadings(claudeMd);
1411
+ for (const { ref: refPath, resolved: resolvedPath } of importedFiles) {
1412
+ const refContent = readText(resolvedPath);
1413
+ if (!refContent)
1414
+ continue;
1415
+ const refHeadings = extractHeadings(refContent);
1416
+ for (const heading of claudeHeadings) {
1417
+ if (refHeadings.has(heading)) {
545
1418
  issues.push({
546
- severity: "warning",
547
- file: "AGENTS.md",
548
- message: `Project context should be exactly 1 line, found ${contextLines.length}`,
549
- fix: "Condense to a single line: stack + what the project does",
1419
+ severity: "warning",
1420
+ file: "CLAUDE.md",
1421
+ message: `Section "${heading}" duplicates content from @${refPath}`,
1422
+ fix: `Remove the "${heading}" section it's already included via @import`
550
1423
  });
1424
+ }
551
1425
  }
552
- // Commands — check against package.json scripts
553
- const codeBlockRe = /```[\s\S]*?```/g;
554
- let blockMatch;
555
- while ((blockMatch = codeBlockRe.exec(agentsMd)) !== null) {
556
- const block = blockMatch[0];
557
- const cmdRe = /(?:bun|npm|pnpm|yarn)\s+(?:run\s+)?(\S+)/g;
558
- let cmdMatch;
559
- while ((cmdMatch = cmdRe.exec(block)) !== null) {
560
- const scriptName = cmdMatch[1];
561
- const builtins = new Set([
562
- "install",
563
- "init",
564
- "create",
565
- "exec",
566
- "dlx",
567
- "x",
568
- "test",
569
- "start",
570
- ]);
571
- if (builtins.has(scriptName))
572
- continue;
573
- if (Object.keys(pkgScripts).length > 0 && !(scriptName in pkgScripts)) {
574
- issues.push({
575
- severity: "warning",
576
- file: "AGENTS.md",
577
- message: `Command references script "${scriptName}" which is not in package.json`,
578
- fix: `Update the command or add "${scriptName}" to package.json scripts`,
579
- });
580
- }
581
- }
1426
+ }
1427
+ }
1428
+ }
1429
+ if (agentsMd) {
1430
+ const agentsLines = agentsMd.split(`
1431
+ `);
1432
+ const contextLines = [];
1433
+ let pastFirstHeading = false;
1434
+ let hitNextSection = false;
1435
+ for (const line of agentsLines) {
1436
+ if (!pastFirstHeading) {
1437
+ if (line.startsWith("# ")) {
1438
+ pastFirstHeading = true;
582
1439
  }
583
- // Code Standards — flag vague, non-actionable phrases
584
- const standardsSection = extractSection(agentsMd, "Code Standards");
585
- if (standardsSection) {
586
- const lower = standardsSection.toLowerCase();
587
- for (const phrase of VAGUE_STANDARDS) {
588
- if (lower.includes(phrase)) {
589
- issues.push({
590
- severity: "warning",
591
- file: "AGENTS.md",
592
- message: `Code Standards contains vague phrase: "${phrase}"`,
593
- fix: "Replace with specific, verifiable conventions derived from config files",
594
- });
595
- }
596
- }
1440
+ continue;
1441
+ }
1442
+ if (line.startsWith("## ")) {
1443
+ hitNextSection = true;
1444
+ break;
1445
+ }
1446
+ const trimmed = line.trim();
1447
+ if (trimmed)
1448
+ contextLines.push(trimmed);
1449
+ }
1450
+ if (pastFirstHeading && !hitNextSection && contextLines.length === 0) {
1451
+ issues.push({
1452
+ severity: "warning",
1453
+ file: "AGENTS.md",
1454
+ message: "Missing project context line after the title heading",
1455
+ fix: "Add a single-line description: stack + what the project does"
1456
+ });
1457
+ } else if (contextLines.length > 1) {
1458
+ issues.push({
1459
+ severity: "warning",
1460
+ file: "AGENTS.md",
1461
+ message: `Project context should be exactly 1 line, found ${contextLines.length}`,
1462
+ fix: "Condense to a single line: stack + what the project does"
1463
+ });
1464
+ }
1465
+ const codeBlockRe = /```[\s\S]*?```/g;
1466
+ let blockMatch;
1467
+ while ((blockMatch = codeBlockRe.exec(agentsMd)) !== null) {
1468
+ const block = blockMatch[0];
1469
+ const cmdRe = /(?:bun|npm|pnpm|yarn)\s+(?:run\s+)?(\S+)/g;
1470
+ let cmdMatch;
1471
+ while ((cmdMatch = cmdRe.exec(block)) !== null) {
1472
+ const scriptName = cmdMatch[1];
1473
+ const builtins = new Set([
1474
+ "install",
1475
+ "init",
1476
+ "create",
1477
+ "exec",
1478
+ "dlx",
1479
+ "x",
1480
+ "test",
1481
+ "start"
1482
+ ]);
1483
+ if (builtins.has(scriptName))
1484
+ continue;
1485
+ if (Object.keys(pkgScripts).length > 0 && !(scriptName in pkgScripts)) {
1486
+ issues.push({
1487
+ severity: "warning",
1488
+ file: "AGENTS.md",
1489
+ message: `Command references script "${scriptName}" which is not in package.json`,
1490
+ fix: `Update the command or add "${scriptName}" to package.json scripts`
1491
+ });
597
1492
  }
598
- // Missing test command — if no test script exists, AGENTS.md should say so
599
- if (Object.keys(pkgScripts).length > 0) {
600
- const hasTestScript = Object.keys(pkgScripts).some((k) => k === "test" || k.startsWith("test:"));
601
- if (!hasTestScript) {
602
- const mentionsNoTest = agentsMd.toLowerCase().includes("no test");
603
- if (!mentionsNoTest) {
604
- issues.push({
605
- severity: "warning",
606
- file: "AGENTS.md",
607
- message: "No test script in package.json and AGENTS.md doesn't mention it",
608
- fix: 'Add a note like "No test framework. Verify changes with `bun run build`."',
609
- });
610
- }
611
- }
1493
+ }
1494
+ }
1495
+ const standardsSection = extractSection(agentsMd, "Code Standards");
1496
+ if (standardsSection) {
1497
+ const lower = standardsSection.toLowerCase();
1498
+ for (const phrase of VAGUE_STANDARDS) {
1499
+ if (lower.includes(phrase)) {
1500
+ issues.push({
1501
+ severity: "warning",
1502
+ file: "AGENTS.md",
1503
+ message: `Code Standards contains vague phrase: "${phrase}"`,
1504
+ fix: "Replace with specific, verifiable conventions derived from config files"
1505
+ });
612
1506
  }
613
- // Check backtick-quoted paths
614
- checkBacktickPaths(agentsMd, "AGENTS.md", cwd, issues);
1507
+ }
615
1508
  }
616
- // ── docs/architecture.md checks ───────────────────────────────────────
617
- const archMd = readText(join(cwd, "docs", "architecture.md"));
618
- if (archMd) {
619
- checkBacktickPaths(archMd, "docs/architecture.md", cwd, issues);
1509
+ if (Object.keys(pkgScripts).length > 0) {
1510
+ const hasTestScript = Object.keys(pkgScripts).some((k3) => k3 === "test" || k3.startsWith("test:"));
1511
+ if (!hasTestScript) {
1512
+ const mentionsNoTest = agentsMd.toLowerCase().includes("no test");
1513
+ if (!mentionsNoTest) {
1514
+ issues.push({
1515
+ severity: "warning",
1516
+ file: "AGENTS.md",
1517
+ message: "No test script in package.json and AGENTS.md doesn't mention it",
1518
+ fix: 'Add a note like "No test framework. Verify changes with `bun run build`."'
1519
+ });
1520
+ }
1521
+ }
620
1522
  }
621
- return issues;
1523
+ checkBacktickPaths(agentsMd, "AGENTS.md", cwd, issues);
1524
+ }
1525
+ const archMd = readText(join(cwd, "docs", "architecture.md"));
1526
+ if (archMd) {
1527
+ checkBacktickPaths(archMd, "docs/architecture.md", cwd, issues);
1528
+ }
1529
+ return issues;
622
1530
  }
623
- /** Extract ## headings from markdown content. */
624
1531
  function extractHeadings(content) {
625
- const headings = new Set();
626
- for (const line of content.split("\n")) {
627
- const match = line.match(/^#{2,3}\s+(.+)$/);
628
- if (match) {
629
- headings.add(match[1].trim());
630
- }
1532
+ const headings = new Set;
1533
+ for (const line of content.split(`
1534
+ `)) {
1535
+ const match = line.match(/^#{2,3}\s+(.+)$/);
1536
+ if (match) {
1537
+ headings.add(match[1].trim());
631
1538
  }
632
- return headings;
1539
+ }
1540
+ return headings;
633
1541
  }
634
- /** Extract content under a specific ## section heading. */
635
1542
  function extractSection(content, heading) {
636
- const lines = content.split("\n");
637
- let capturing = false;
638
- const result = [];
639
- for (const line of lines) {
640
- if (capturing) {
641
- // Stop at next ## heading
642
- if (line.match(/^#{1,2}\s/))
643
- break;
644
- result.push(line);
645
- }
646
- else if (line.match(new RegExp(`^##\\s+${heading.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`, "i"))) {
647
- capturing = true;
648
- }
1543
+ const lines = content.split(`
1544
+ `);
1545
+ let capturing = false;
1546
+ const result = [];
1547
+ for (const line of lines) {
1548
+ if (capturing) {
1549
+ if (line.match(/^#{1,2}\s/))
1550
+ break;
1551
+ result.push(line);
1552
+ } else if (line.match(new RegExp(`^##\\s+${heading.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`, "i"))) {
1553
+ capturing = true;
649
1554
  }
650
- return result.length > 0 ? result.join("\n") : null;
1555
+ }
1556
+ return result.length > 0 ? result.join(`
1557
+ `) : null;
651
1558
  }
652
- /** Scan markdown for backtick-quoted paths and check they exist. */
653
1559
  function checkBacktickPaths(content, file, cwd, issues) {
654
- const pathRe = /`((?:src\/|packages\/|apps\/|supabase\/|docs\/)[^`]+)`/g;
655
- let match;
656
- const checked = new Set();
657
- const root = resolve(cwd);
658
- while ((match = pathRe.exec(content)) !== null) {
659
- const refPath = match[1].replace(/\/$/, ""); // strip trailing slash
660
- if (checked.has(refPath))
661
- continue;
662
- checked.add(refPath);
663
- // Skip paths that escape the project root (e.g. src/../../etc/hosts)
664
- const resolvedRef = resolve(root, refPath);
665
- if (resolvedRef !== root && !resolvedRef.startsWith(root + sep))
666
- continue;
667
- if (!existsSync(resolvedRef)) {
668
- issues.push({
669
- severity: "warning",
670
- file,
671
- message: `Referenced path does not exist: ${refPath}`,
672
- fix: `Update or remove the \`${refPath}\` reference`,
673
- });
674
- }
1560
+ const pathRe = /`((?:src\/|packages\/|apps\/|supabase\/|docs\/)[^`]+)`/g;
1561
+ let match;
1562
+ const checked = new Set;
1563
+ const root = resolve(cwd);
1564
+ while ((match = pathRe.exec(content)) !== null) {
1565
+ const refPath = match[1].replace(/\/$/, "");
1566
+ if (checked.has(refPath))
1567
+ continue;
1568
+ checked.add(refPath);
1569
+ const resolvedRef = resolve(root, refPath);
1570
+ if (resolvedRef !== root && !resolvedRef.startsWith(root + sep))
1571
+ continue;
1572
+ if (!existsSync(resolvedRef)) {
1573
+ issues.push({
1574
+ severity: "warning",
1575
+ file,
1576
+ message: `Referenced path does not exist: ${refPath}`,
1577
+ fix: `Update or remove the \`${refPath}\` reference`
1578
+ });
675
1579
  }
1580
+ }
676
1581
  }
677
- // ── TUI Entry Point ─────────────────────────────────────────────────────────
678
- /**
679
- * Run the docs step of the setup wizard.
680
- * Scans the project, then either scaffolds new docs or verifies existing ones.
681
- */
682
- export async function runDocsStep(cwd) {
683
- const info = scanProject(cwd);
684
- const hasDocs = info.existingDocs.agentsMd || info.existingDocs.claudeMd;
685
- if (!hasDocs) {
686
- // No docs — offer to generate
687
- const shouldGenerate = await p.confirm({
688
- message: "No project docs found. Generate AGENTS.md and CLAUDE.md?",
689
- initialValue: true,
690
- });
691
- if (p.isCancel(shouldGenerate) || !shouldGenerate) {
692
- return { files: [], issues: [], skipped: true };
693
- }
694
- const files = [];
695
- files.push({
696
- path: join(cwd, "AGENTS.md"),
697
- content: generateAgentsMd(info, cwd),
698
- type: "text",
699
- });
700
- files.push({
701
- path: join(cwd, "CLAUDE.md"),
702
- content: generateClaudeMd(info),
703
- type: "text",
704
- });
705
- // Generate architecture.md if docs/ exists or we referenced it
706
- if (info.dirs.includes("docs") || info.srcDirs.length > 0) {
707
- files.push({
708
- path: join(cwd, "docs", "architecture.md"),
709
- content: generateArchitectureMd(info, cwd),
710
- type: "text",
711
- });
712
- }
713
- p.log.success(`Generated ${files.length} doc file(s): ${files.map((f) => f.path.replace(cwd + "/", "")).join(", ")}`);
714
- return { files, issues: [], skipped: false };
715
- }
716
- // Docs exist — offer to verify
717
- const shouldVerify = await p.confirm({
718
- message: "Project docs found. Verify for issues?",
719
- initialValue: false,
1582
+ async function runDocsStep(cwd) {
1583
+ const info = scanProject(cwd);
1584
+ const hasDocs = info.existingDocs.agentsMd || info.existingDocs.claudeMd;
1585
+ if (!hasDocs) {
1586
+ const shouldGenerate = await ye({
1587
+ message: "No project docs found. Generate AGENTS.md and CLAUDE.md?",
1588
+ initialValue: true
720
1589
  });
721
- if (p.isCancel(shouldVerify) || !shouldVerify) {
722
- return { files: [], issues: [], skipped: true };
1590
+ if (pD(shouldGenerate) || !shouldGenerate) {
1591
+ return { files: [], issues: [], skipped: true };
723
1592
  }
724
- const issues = verifyDocs(cwd);
725
- if (issues.length === 0) {
726
- p.log.success("No issues found in project docs.");
1593
+ const files = [];
1594
+ files.push({
1595
+ path: join(cwd, "AGENTS.md"),
1596
+ content: generateAgentsMd(info, cwd),
1597
+ type: "text"
1598
+ });
1599
+ files.push({
1600
+ path: join(cwd, "CLAUDE.md"),
1601
+ content: generateClaudeMd(info),
1602
+ type: "text"
1603
+ });
1604
+ if (info.dirs.includes("docs") || info.srcDirs.length > 0) {
1605
+ files.push({
1606
+ path: join(cwd, "docs", "architecture.md"),
1607
+ content: generateArchitectureMd(info, cwd),
1608
+ type: "text"
1609
+ });
727
1610
  }
728
- else {
729
- for (const issue of issues) {
730
- const prefix = `${colors.bold(issue.file)}:`;
731
- if (issue.severity === "error") {
732
- p.log.error(`${prefix} ${issue.message}`);
733
- }
734
- else {
735
- p.log.warning(`${prefix} ${issue.message}`);
736
- }
737
- if (issue.fix) {
738
- p.log.message(` ${symbols.arrow} ${colors.dim(issue.fix)}`);
739
- }
740
- }
741
- p.log.info(`Found ${issues.length} issue(s) (${issues.filter((i) => i.severity === "error").length} errors, ${issues.filter((i) => i.severity === "warning").length} warnings)`);
1611
+ M2.success(`Generated ${files.length} doc file(s): ${files.map((f) => f.path.replace(cwd + "/", "")).join(", ")}`);
1612
+ return { files, issues: [], skipped: false };
1613
+ }
1614
+ const shouldVerify = await ye({
1615
+ message: "Project docs found. Verify for issues?",
1616
+ initialValue: false
1617
+ });
1618
+ if (pD(shouldVerify) || !shouldVerify) {
1619
+ return { files: [], issues: [], skipped: true };
1620
+ }
1621
+ const issues = verifyDocs(cwd);
1622
+ if (issues.length === 0) {
1623
+ M2.success("No issues found in project docs.");
1624
+ } else {
1625
+ for (const issue of issues) {
1626
+ const prefix = `${colors.bold(issue.file)}:`;
1627
+ if (issue.severity === "error") {
1628
+ M2.error(`${prefix} ${issue.message}`);
1629
+ } else {
1630
+ M2.warning(`${prefix} ${issue.message}`);
1631
+ }
1632
+ if (issue.fix) {
1633
+ M2.message(` ${symbols.arrow} ${colors.dim(issue.fix)}`);
1634
+ }
742
1635
  }
743
- return { files: [], issues, skipped: false };
1636
+ M2.info(`Found ${issues.length} issue(s) (${issues.filter((i) => i.severity === "error").length} errors, ${issues.filter((i) => i.severity === "warning").length} warnings)`);
1637
+ }
1638
+ return { files: [], issues, skipped: false };
744
1639
  }
1640
+ export {
1641
+ verifyDocs,
1642
+ scanProject,
1643
+ runDocsStep,
1644
+ generateClaudeMd,
1645
+ generateArchitectureMd,
1646
+ generateAgentsMd
1647
+ };