yandecode 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/dist/bin.js +14 -8
  2. package/dist/bin.js.map +7 -1
  3. package/dist/chunks/chunk-23DG7PZZ.js +58 -0
  4. package/dist/chunks/chunk-23DG7PZZ.js.map +7 -0
  5. package/dist/chunks/chunk-2S6B3DDQ.js +1769 -0
  6. package/dist/chunks/chunk-2S6B3DDQ.js.map +7 -0
  7. package/dist/chunks/chunk-6J5CZVCJ.js +120 -0
  8. package/dist/chunks/chunk-6J5CZVCJ.js.map +7 -0
  9. package/dist/chunks/chunk-7L6DD2VD.js +768 -0
  10. package/dist/chunks/chunk-7L6DD2VD.js.map +7 -0
  11. package/dist/chunks/chunk-DWD37AI2.js +39 -0
  12. package/dist/chunks/chunk-DWD37AI2.js.map +7 -0
  13. package/dist/chunks/chunk-KPDBXQ62.js +62 -0
  14. package/dist/chunks/chunk-KPDBXQ62.js.map +7 -0
  15. package/dist/chunks/chunk-KVBKQXTU.js +351 -0
  16. package/dist/chunks/chunk-KVBKQXTU.js.map +7 -0
  17. package/dist/chunks/chunk-L2DDIZPI.js +53 -0
  18. package/dist/chunks/chunk-L2DDIZPI.js.map +7 -0
  19. package/dist/chunks/chunk-OIAMKDTQ.js +27 -0
  20. package/dist/chunks/chunk-OIAMKDTQ.js.map +7 -0
  21. package/dist/chunks/chunk-PUWSEWX3.js +61 -0
  22. package/dist/chunks/chunk-PUWSEWX3.js.map +7 -0
  23. package/dist/chunks/chunk-QCQC73WX.js +122 -0
  24. package/dist/chunks/chunk-QCQC73WX.js.map +7 -0
  25. package/dist/chunks/chunk-TYLH4NIC.js +39 -0
  26. package/dist/chunks/chunk-TYLH4NIC.js.map +7 -0
  27. package/dist/chunks/chunk-VKVJGBNJ.js +72 -0
  28. package/dist/chunks/chunk-VKVJGBNJ.js.map +7 -0
  29. package/dist/chunks/chunk-Y2MIXROU.js +20072 -0
  30. package/dist/chunks/chunk-Y2MIXROU.js.map +7 -0
  31. package/dist/chunks/cli-V6PJTDLM.js +3464 -0
  32. package/dist/chunks/cli-V6PJTDLM.js.map +7 -0
  33. package/dist/chunks/doctor-LLDVEPWL.js +184 -0
  34. package/dist/chunks/doctor-LLDVEPWL.js.map +7 -0
  35. package/dist/chunks/entry-YAOEX3EB.js +187 -0
  36. package/dist/chunks/entry-YAOEX3EB.js.map +7 -0
  37. package/dist/chunks/init-4ZJFCKIJ.js +46 -0
  38. package/dist/chunks/init-4ZJFCKIJ.js.map +7 -0
  39. package/dist/chunks/mcp-serve-KWKMUGWZ.js +22575 -0
  40. package/dist/chunks/mcp-serve-KWKMUGWZ.js.map +7 -0
  41. package/dist/chunks/modules-CJB5IKUJ.js +121 -0
  42. package/dist/chunks/modules-CJB5IKUJ.js.map +7 -0
  43. package/dist/chunks/runtime-3E4NIFAL.js +208 -0
  44. package/dist/chunks/runtime-3E4NIFAL.js.map +7 -0
  45. package/dist/chunks/runtime-7CRR63B5.js +395 -0
  46. package/dist/chunks/runtime-7CRR63B5.js.map +7 -0
  47. package/dist/chunks/runtime-CKMVHAU4.js +64 -0
  48. package/dist/chunks/runtime-CKMVHAU4.js.map +7 -0
  49. package/dist/chunks/runtime-CVZMWIJO.js +318 -0
  50. package/dist/chunks/runtime-CVZMWIJO.js.map +7 -0
  51. package/dist/chunks/runtime-DBNXBOAL.js +295 -0
  52. package/dist/chunks/runtime-DBNXBOAL.js.map +7 -0
  53. package/dist/chunks/runtime-EKHO2JXB.js +197 -0
  54. package/dist/chunks/runtime-EKHO2JXB.js.map +7 -0
  55. package/dist/chunks/runtime-EY6SVZYP.js +539 -0
  56. package/dist/chunks/runtime-EY6SVZYP.js.map +7 -0
  57. package/dist/chunks/runtime-UB2O2HUN.js +212 -0
  58. package/dist/chunks/runtime-UB2O2HUN.js.map +7 -0
  59. package/dist/chunks/runtime-WAFQWW4M.js +755 -0
  60. package/dist/chunks/runtime-WAFQWW4M.js.map +7 -0
  61. package/dist/chunks/runtime-ZGGF6RVA.js +271 -0
  62. package/dist/chunks/runtime-ZGGF6RVA.js.map +7 -0
  63. package/dist/chunks/status-SPIESL4F.js +38 -0
  64. package/dist/chunks/status-SPIESL4F.js.map +7 -0
  65. package/dist/chunks/uninstall-J2OWCX4A.js +54 -0
  66. package/dist/chunks/uninstall-J2OWCX4A.js.map +7 -0
  67. package/dist/chunks/update-OX5MZYQY.js +34 -0
  68. package/dist/chunks/update-OX5MZYQY.js.map +7 -0
  69. package/dist/content/agents/yandecode-reviewer.md +22 -0
  70. package/dist/content/agents/yandecode-security-reviewer.md +23 -0
  71. package/dist/content/skills/NOTICE.md +29 -0
  72. package/dist/content/skills/yandecode-code-review/SKILL.md +37 -0
  73. package/dist/content/skills/yandecode-debugging/SKILL.md +33 -0
  74. package/dist/content/skills/yandecode-instructions/SKILL.md +26 -0
  75. package/dist/content/skills/yandecode-memory/SKILL.md +36 -0
  76. package/dist/content/skills/yandecode-security-review/SKILL.md +24 -0
  77. package/dist/content/skills/yandecode-tdd/SKILL.md +38 -0
  78. package/dist/content/skills/yandecode-verification/SKILL.md +29 -0
  79. package/dist/content/skills/yandecode-workflow/SKILL.md +50 -0
  80. package/package.json +25 -19
  81. package/dist/bin.d.ts +0 -3
  82. package/dist/bin.d.ts.map +0 -1
  83. package/dist/cli.d.ts +0 -6
  84. package/dist/cli.d.ts.map +0 -1
  85. package/dist/cli.js +0 -21
  86. package/dist/cli.js.map +0 -1
  87. package/dist/commands/doctor.d.ts +0 -2
  88. package/dist/commands/doctor.d.ts.map +0 -1
  89. package/dist/commands/doctor.js +0 -19
  90. package/dist/commands/doctor.js.map +0 -1
  91. package/dist/commands/hook.d.ts +0 -2
  92. package/dist/commands/hook.d.ts.map +0 -1
  93. package/dist/commands/hook.js +0 -23
  94. package/dist/commands/hook.js.map +0 -1
  95. package/dist/commands/index-cmd.d.ts +0 -2
  96. package/dist/commands/index-cmd.d.ts.map +0 -1
  97. package/dist/commands/index-cmd.js +0 -47
  98. package/dist/commands/index-cmd.js.map +0 -1
  99. package/dist/commands/index.d.ts +0 -13
  100. package/dist/commands/index.d.ts.map +0 -1
  101. package/dist/commands/index.js +0 -15
  102. package/dist/commands/index.js.map +0 -1
  103. package/dist/commands/init.d.ts +0 -2
  104. package/dist/commands/init.d.ts.map +0 -1
  105. package/dist/commands/init.js +0 -22
  106. package/dist/commands/init.js.map +0 -1
  107. package/dist/commands/mcp.d.ts +0 -2
  108. package/dist/commands/mcp.d.ts.map +0 -1
  109. package/dist/commands/mcp.js +0 -71
  110. package/dist/commands/mcp.js.map +0 -1
  111. package/dist/commands/rag.d.ts +0 -2
  112. package/dist/commands/rag.d.ts.map +0 -1
  113. package/dist/commands/rag.js +0 -27
  114. package/dist/commands/rag.js.map +0 -1
  115. package/dist/commands/start.d.ts +0 -6
  116. package/dist/commands/start.d.ts.map +0 -1
  117. package/dist/commands/start.js +0 -76
  118. package/dist/commands/start.js.map +0 -1
  119. package/dist/commands/status.d.ts +0 -2
  120. package/dist/commands/status.d.ts.map +0 -1
  121. package/dist/commands/status.js +0 -29
  122. package/dist/commands/status.js.map +0 -1
  123. package/dist/commands/statusline.d.ts +0 -2
  124. package/dist/commands/statusline.d.ts.map +0 -1
  125. package/dist/commands/statusline.js +0 -90
  126. package/dist/commands/statusline.js.map +0 -1
  127. package/dist/commands/swarm.d.ts +0 -4
  128. package/dist/commands/swarm.d.ts.map +0 -1
  129. package/dist/commands/swarm.js +0 -48
  130. package/dist/commands/swarm.js.map +0 -1
  131. package/dist/commands/uninstall.d.ts +0 -2
  132. package/dist/commands/uninstall.d.ts.map +0 -1
  133. package/dist/commands/uninstall.js +0 -16
  134. package/dist/commands/uninstall.js.map +0 -1
  135. package/dist/context.d.ts +0 -13
  136. package/dist/context.d.ts.map +0 -1
  137. package/dist/context.js +0 -31
  138. package/dist/context.js.map +0 -1
  139. package/dist/doctor/checks.d.ts +0 -18
  140. package/dist/doctor/checks.d.ts.map +0 -1
  141. package/dist/doctor/checks.js +0 -269
  142. package/dist/doctor/checks.js.map +0 -1
  143. package/dist/hooks/handlers.d.ts +0 -21
  144. package/dist/hooks/handlers.d.ts.map +0 -1
  145. package/dist/hooks/handlers.js +0 -191
  146. package/dist/hooks/handlers.js.map +0 -1
  147. package/dist/index.d.ts +0 -9
  148. package/dist/index.d.ts.map +0 -1
  149. package/dist/index.js +0 -9
  150. package/dist/index.js.map +0 -1
  151. package/dist/integration/claude-md.d.ts +0 -6
  152. package/dist/integration/claude-md.d.ts.map +0 -1
  153. package/dist/integration/claude-md.js +0 -30
  154. package/dist/integration/claude-md.js.map +0 -1
  155. package/dist/integration/gitignore.d.ts +0 -3
  156. package/dist/integration/gitignore.d.ts.map +0 -1
  157. package/dist/integration/gitignore.js +0 -13
  158. package/dist/integration/gitignore.js.map +0 -1
  159. package/dist/integration/init.d.ts +0 -17
  160. package/dist/integration/init.d.ts.map +0 -1
  161. package/dist/integration/init.js +0 -86
  162. package/dist/integration/init.js.map +0 -1
  163. package/dist/integration/json-utils.d.ts +0 -13
  164. package/dist/integration/json-utils.d.ts.map +0 -1
  165. package/dist/integration/json-utils.js +0 -33
  166. package/dist/integration/json-utils.js.map +0 -1
  167. package/dist/integration/manifest.d.ts +0 -17
  168. package/dist/integration/manifest.d.ts.map +0 -1
  169. package/dist/integration/manifest.js +0 -26
  170. package/dist/integration/manifest.js.map +0 -1
  171. package/dist/integration/materialize.d.ts +0 -9
  172. package/dist/integration/materialize.d.ts.map +0 -1
  173. package/dist/integration/materialize.js +0 -21
  174. package/dist/integration/materialize.js.map +0 -1
  175. package/dist/integration/mcp-config.d.ts +0 -4
  176. package/dist/integration/mcp-config.d.ts.map +0 -1
  177. package/dist/integration/mcp-config.js +0 -11
  178. package/dist/integration/mcp-config.js.map +0 -1
  179. package/dist/integration/settings.d.ts +0 -7
  180. package/dist/integration/settings.d.ts.map +0 -1
  181. package/dist/integration/settings.js +0 -70
  182. package/dist/integration/settings.js.map +0 -1
  183. package/dist/integration/uninstall.d.ts +0 -10
  184. package/dist/integration/uninstall.d.ts.map +0 -1
  185. package/dist/integration/uninstall.js +0 -71
  186. package/dist/integration/uninstall.js.map +0 -1
  187. package/dist/launcher.d.ts +0 -8
  188. package/dist/launcher.d.ts.map +0 -1
  189. package/dist/launcher.js +0 -18
  190. package/dist/launcher.js.map +0 -1
  191. package/dist/mcp/server.d.ts +0 -27
  192. package/dist/mcp/server.d.ts.map +0 -1
  193. package/dist/mcp/server.js +0 -311
  194. package/dist/mcp/server.js.map +0 -1
  195. package/dist/plugin-content.d.ts +0 -21
  196. package/dist/plugin-content.d.ts.map +0 -1
  197. package/dist/plugin-content.js +0 -67
  198. package/dist/plugin-content.js.map +0 -1
  199. package/dist/rag/format.d.ts +0 -3
  200. package/dist/rag/format.d.ts.map +0 -1
  201. package/dist/rag/format.js +0 -12
  202. package/dist/rag/format.js.map +0 -1
  203. package/dist/retrieval-runtime.d.ts +0 -21
  204. package/dist/retrieval-runtime.d.ts.map +0 -1
  205. package/dist/retrieval-runtime.js +0 -47
  206. package/dist/retrieval-runtime.js.map +0 -1
  207. package/dist/status-line/git.d.ts +0 -3
  208. package/dist/status-line/git.d.ts.map +0 -1
  209. package/dist/status-line/git.js +0 -34
  210. package/dist/status-line/git.js.map +0 -1
  211. package/dist/status-line/render.d.ts +0 -29
  212. package/dist/status-line/render.d.ts.map +0 -1
  213. package/dist/status-line/render.js +0 -72
  214. package/dist/status-line/render.js.map +0 -1
  215. package/dist/swarm-runtime.d.ts +0 -11
  216. package/dist/swarm-runtime.d.ts.map +0 -1
  217. package/dist/swarm-runtime.js +0 -76
  218. package/dist/swarm-runtime.js.map +0 -1
  219. package/dist/version.d.ts +0 -2
  220. package/dist/version.d.ts.map +0 -1
  221. package/dist/version.js +0 -5
  222. package/dist/version.js.map +0 -1
@@ -0,0 +1,184 @@
1
+ import { createRequire as __yandecodeCreateRequire } from 'node:module';
2
+ const require = __yandecodeCreateRequire(import.meta.url);
3
+ import {
4
+ hookGroupsFor,
5
+ readJsonSafe,
6
+ resolveLauncher
7
+ } from "./chunk-KVBKQXTU.js";
8
+ import "./chunk-L2DDIZPI.js";
9
+ import {
10
+ readManifest
11
+ } from "./chunk-DWD37AI2.js";
12
+ import {
13
+ VERSION
14
+ } from "./chunk-PUWSEWX3.js";
15
+ import {
16
+ enabledModules,
17
+ moduleContext,
18
+ openWorkspace
19
+ } from "./chunk-QCQC73WX.js";
20
+ import "./chunk-7L6DD2VD.js";
21
+ import {
22
+ openDatabase
23
+ } from "./chunk-Y2MIXROU.js";
24
+
25
+ // packages/cli/src/commands/doctor.ts
26
+ import { spawnSync } from "node:child_process";
27
+ import { join } from "node:path";
28
+ var MARK = {
29
+ ok: "OK ",
30
+ warn: "WARN",
31
+ fail: "FAIL",
32
+ skip: "SKIP"
33
+ };
34
+ function commandVersion(command) {
35
+ const r = spawnSync(command, ["--version"], {
36
+ encoding: "utf8",
37
+ timeout: 1e4,
38
+ shell: process.platform === "win32"
39
+ });
40
+ return r.status === 0 ? r.stdout.trim().split("\n")[0] : null;
41
+ }
42
+ function environmentChecks() {
43
+ const major = Number(process.versions.node.split(".")[0]);
44
+ const checks = [
45
+ major >= 22 ? { name: "node", status: "ok", detail: process.version } : {
46
+ name: "node",
47
+ status: "fail",
48
+ detail: `${process.version} < 22`,
49
+ fix: "install Node.js 22 or newer"
50
+ }
51
+ ];
52
+ const git = commandVersion("git");
53
+ checks.push(
54
+ git ? { name: "git", status: "ok", detail: git } : {
55
+ name: "git",
56
+ status: "warn",
57
+ detail: "not found",
58
+ fix: "install git (used to honour .gitignore)"
59
+ }
60
+ );
61
+ const claude = commandVersion("claude");
62
+ checks.push(
63
+ claude ? { name: "claude code", status: "ok", detail: claude } : {
64
+ name: "claude code",
65
+ status: "warn",
66
+ detail: "claude not on PATH",
67
+ fix: "install Claude Code: https://code.claude.com/docs/en/setup"
68
+ }
69
+ );
70
+ try {
71
+ openDatabase(":memory:").close();
72
+ checks.push({ name: "sqlite", status: "ok", detail: "better-sqlite3 with FTS5" });
73
+ } catch (error) {
74
+ checks.push({
75
+ name: "sqlite",
76
+ status: "fail",
77
+ detail: error.message,
78
+ fix: "reinstall yandecode (native module build failed?)"
79
+ });
80
+ }
81
+ return checks;
82
+ }
83
+ function integrationChecks(ws, launcher) {
84
+ const modules = enabledModules(ws);
85
+ const manifest = readManifest(ws.paths.managedManifest);
86
+ const checks = [];
87
+ checks.push(
88
+ !manifest ? { name: "integration", status: "fail", detail: "never applied", fix: "yandecode update" } : manifest.version !== VERSION ? {
89
+ name: "integration",
90
+ status: "warn",
91
+ detail: `applied by ${manifest.version}, installed ${VERSION}`,
92
+ fix: "yandecode update"
93
+ } : { name: "integration", status: "ok", detail: `${manifest.files.length} managed file(s)` }
94
+ );
95
+ const settings = readJsonSafe(
96
+ join(ws.root, ".claude", "settings.json"),
97
+ {}
98
+ );
99
+ const expected = hookGroupsFor(modules, launcher);
100
+ const missing = Object.keys(expected).filter(
101
+ (event) => !JSON.stringify(settings.hooks?.[event] ?? []).includes(`hook ${event}`)
102
+ );
103
+ checks.push(
104
+ missing.length === 0 ? { name: "hooks", status: "ok", detail: Object.keys(expected).join(", ") || "none needed" } : {
105
+ name: "hooks",
106
+ status: "fail",
107
+ detail: `missing ${missing.join(", ")}`,
108
+ fix: "yandecode update"
109
+ }
110
+ );
111
+ const hasTools = modules.some((m) => (m.tools ?? []).length > 0);
112
+ const mcp = readJsonSafe(
113
+ join(ws.root, ".mcp.json"),
114
+ {}
115
+ );
116
+ const registered = Boolean(mcp.mcpServers?.yandecode);
117
+ checks.push(
118
+ registered === hasTools ? {
119
+ name: "mcp",
120
+ status: "ok",
121
+ detail: hasTools ? "yandecode server registered in .mcp.json" : "not needed"
122
+ } : {
123
+ name: "mcp",
124
+ status: "fail",
125
+ detail: hasTools ? "server missing from .mcp.json" : "stale server entry",
126
+ fix: "yandecode update"
127
+ }
128
+ );
129
+ return checks;
130
+ }
131
+ async function runDoctor(cwd, io, launcher = resolveLauncher()) {
132
+ const sections = [["environment", environmentChecks()]];
133
+ const ws = openWorkspace(cwd);
134
+ if (!ws) {
135
+ sections.push([
136
+ "project",
137
+ [
138
+ {
139
+ name: "workspace",
140
+ status: "fail",
141
+ detail: "no yandecode.json here or above",
142
+ fix: "yandecode init"
143
+ }
144
+ ]
145
+ ]);
146
+ } else {
147
+ sections.push(["project", integrationChecks(ws, launcher)]);
148
+ for (const module of enabledModules(ws)) {
149
+ let checks;
150
+ try {
151
+ const runtime = await module.load();
152
+ checks = runtime.doctor ? await runtime.doctor(moduleContext(ws, module)) : [{ name: "loaded", status: "ok", detail: "no checks" }];
153
+ await runtime.dispose?.();
154
+ } catch (error) {
155
+ checks = [
156
+ {
157
+ name: "load",
158
+ status: "fail",
159
+ detail: error.message,
160
+ fix: `yandecode modules info ${module.id}`
161
+ }
162
+ ];
163
+ }
164
+ sections.push([`module ${module.id}`, checks]);
165
+ }
166
+ }
167
+ let failed = false;
168
+ for (const [title, checks] of sections) {
169
+ io.out(`${title}
170
+ `);
171
+ for (const c of checks) {
172
+ failed ||= c.status === "fail";
173
+ io.out(` ${MARK[c.status]} ${c.name.padEnd(14)} ${c.detail}
174
+ `);
175
+ if (c.fix && c.status !== "ok") io.out(` fix: ${c.fix}
176
+ `);
177
+ }
178
+ }
179
+ return failed ? 1 : 0;
180
+ }
181
+ export {
182
+ runDoctor
183
+ };
184
+ //# sourceMappingURL=doctor-LLDVEPWL.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/doctor.ts"],
4
+ "sourcesContent": ["import { spawnSync } from 'node:child_process';\nimport { join } from 'node:path';\nimport { openDatabase } from '@yandecode/core';\nimport { hookGroupsFor } from '@cli/integration/apply';\nimport { readJsonSafe } from '@cli/integration/json-utils';\nimport { readManifest } from '@cli/integration/manifest';\nimport type { Io } from '@cli/io';\nimport { resolveLauncher, type Launcher } from '@cli/launcher';\nimport type { DoctorCheck } from '@cli/modules/contract';\nimport { enabledModules, moduleContext, openWorkspace, type Workspace } from '@cli/modules/host';\nimport { VERSION } from '@cli/version';\n\nconst MARK: Record<DoctorCheck['status'], string> = {\n ok: 'OK ',\n warn: 'WARN',\n fail: 'FAIL',\n skip: 'SKIP',\n};\n\nfunction commandVersion(command: string): string | null {\n const r = spawnSync(command, ['--version'], {\n encoding: 'utf8',\n timeout: 10_000,\n shell: process.platform === 'win32',\n });\n return r.status === 0 ? r.stdout.trim().split('\\n')[0]! : null;\n}\n\nfunction environmentChecks(): DoctorCheck[] {\n const major = Number(process.versions.node.split('.')[0]);\n const checks: DoctorCheck[] = [\n major >= 22\n ? { name: 'node', status: 'ok', detail: process.version }\n : {\n name: 'node',\n status: 'fail',\n detail: `${process.version} < 22`,\n fix: 'install Node.js 22 or newer',\n },\n ];\n const git = commandVersion('git');\n checks.push(\n git\n ? { name: 'git', status: 'ok', detail: git }\n : {\n name: 'git',\n status: 'warn',\n detail: 'not found',\n fix: 'install git (used to honour .gitignore)',\n },\n );\n const claude = commandVersion('claude');\n checks.push(\n claude\n ? { name: 'claude code', status: 'ok', detail: claude }\n : {\n name: 'claude code',\n status: 'warn',\n detail: 'claude not on PATH',\n fix: 'install Claude Code: https://code.claude.com/docs/en/setup',\n },\n );\n try {\n openDatabase(':memory:').close();\n checks.push({ name: 'sqlite', status: 'ok', detail: 'better-sqlite3 with FTS5' });\n } catch (error) {\n checks.push({\n name: 'sqlite',\n status: 'fail',\n detail: (error as Error).message,\n fix: 'reinstall yandecode (native module build failed?)',\n });\n }\n return checks;\n}\n\nfunction integrationChecks(ws: Workspace, launcher: Launcher): DoctorCheck[] {\n const modules = enabledModules(ws);\n const manifest = readManifest(ws.paths.managedManifest);\n const checks: DoctorCheck[] = [];\n checks.push(\n !manifest\n ? { name: 'integration', status: 'fail', detail: 'never applied', fix: 'yandecode update' }\n : manifest.version !== VERSION\n ? {\n name: 'integration',\n status: 'warn',\n detail: `applied by ${manifest.version}, installed ${VERSION}`,\n fix: 'yandecode update',\n }\n : { name: 'integration', status: 'ok', detail: `${manifest.files.length} managed file(s)` },\n );\n const settings = readJsonSafe<{ hooks?: Record<string, unknown> }>(\n join(ws.root, '.claude', 'settings.json'),\n {},\n );\n const expected = hookGroupsFor(modules, launcher);\n const missing = Object.keys(expected).filter(\n (event) => !JSON.stringify(settings.hooks?.[event] ?? []).includes(`hook ${event}`),\n );\n checks.push(\n missing.length === 0\n ? { name: 'hooks', status: 'ok', detail: Object.keys(expected).join(', ') || 'none needed' }\n : {\n name: 'hooks',\n status: 'fail',\n detail: `missing ${missing.join(', ')}`,\n fix: 'yandecode update',\n },\n );\n const hasTools = modules.some((m) => (m.tools ?? []).length > 0);\n const mcp = readJsonSafe<{ mcpServers?: Record<string, unknown> }>(\n join(ws.root, '.mcp.json'),\n {},\n );\n const registered = Boolean(mcp.mcpServers?.yandecode);\n checks.push(\n registered === hasTools\n ? {\n name: 'mcp',\n status: 'ok',\n detail: hasTools ? 'yandecode server registered in .mcp.json' : 'not needed',\n }\n : {\n name: 'mcp',\n status: 'fail',\n detail: hasTools ? 'server missing from .mcp.json' : 'stale server entry',\n fix: 'yandecode update',\n },\n );\n return checks;\n}\n\nexport async function runDoctor(\n cwd: string,\n io: Io,\n launcher: Launcher = resolveLauncher(),\n): Promise<number> {\n const sections: [string, DoctorCheck[]][] = [['environment', environmentChecks()]];\n const ws = openWorkspace(cwd);\n if (!ws) {\n sections.push([\n 'project',\n [\n {\n name: 'workspace',\n status: 'fail',\n detail: 'no yandecode.json here or above',\n fix: 'yandecode init',\n },\n ],\n ]);\n } else {\n sections.push(['project', integrationChecks(ws, launcher)]);\n for (const module of enabledModules(ws)) {\n let checks: DoctorCheck[];\n try {\n const runtime = await module.load();\n checks = runtime.doctor\n ? await runtime.doctor(moduleContext(ws, module))\n : [{ name: 'loaded', status: 'ok', detail: 'no checks' }];\n await runtime.dispose?.();\n } catch (error) {\n checks = [\n {\n name: 'load',\n status: 'fail',\n detail: (error as Error).message,\n fix: `yandecode modules info ${module.id}`,\n },\n ];\n }\n sections.push([`module ${module.id}`, checks]);\n }\n }\n let failed = false;\n for (const [title, checks] of sections) {\n io.out(`${title}\\n`);\n for (const c of checks) {\n failed ||= c.status === 'fail';\n io.out(` ${MARK[c.status]} ${c.name.padEnd(14)} ${c.detail}\\n`);\n if (c.fix && c.status !== 'ok') io.out(` fix: ${c.fix}\\n`);\n }\n }\n return failed ? 1 : 0;\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,187 @@
1
+ import { createRequire as __yandecodeCreateRequire } from 'node:module';
2
+ const require = __yandecodeCreateRequire(import.meta.url);
3
+ import {
4
+ enabledModules,
5
+ moduleContext,
6
+ openWorkspace
7
+ } from "./chunk-QCQC73WX.js";
8
+ import "./chunk-7L6DD2VD.js";
9
+ import "./chunk-Y2MIXROU.js";
10
+
11
+ // packages/cli/src/modules/contract.ts
12
+ var HOOK_EVENTS = [
13
+ "SessionStart",
14
+ "UserPromptSubmit",
15
+ "PreToolUse",
16
+ "PostToolUse",
17
+ "Stop",
18
+ "SubagentStop",
19
+ "PreCompact",
20
+ "SessionEnd"
21
+ ];
22
+
23
+ // packages/cli/src/hooks/dispatch.ts
24
+ var CONTEXT_BUDGET_CHARS = 8e3;
25
+ var CONTEXT_EVENTS = /* @__PURE__ */ new Set([
26
+ "SessionStart",
27
+ "UserPromptSubmit",
28
+ "PreToolUse",
29
+ "PostToolUse"
30
+ ]);
31
+ function matches(matcher, toolName) {
32
+ if (matcher === void 0 || matcher === "" || matcher === "*") return true;
33
+ if (toolName === void 0) return false;
34
+ return new RegExp(`^(?:${matcher})$`).test(toolName);
35
+ }
36
+ function withTimeout(promise, ms) {
37
+ return new Promise((resolve, reject) => {
38
+ const timer = setTimeout(() => {
39
+ reject(new Error(`timed out after ${ms} ms`));
40
+ }, ms);
41
+ promise.then(
42
+ (value) => {
43
+ clearTimeout(timer);
44
+ resolve(value);
45
+ },
46
+ (error) => {
47
+ clearTimeout(timer);
48
+ reject(error instanceof Error ? error : new Error(String(error)));
49
+ }
50
+ );
51
+ });
52
+ }
53
+ function fitContext(blocks) {
54
+ const kept = [];
55
+ const dropped = [];
56
+ let used = 0;
57
+ const noteReserve = 200;
58
+ for (const block of blocks) {
59
+ const cost = block.text.length + (kept.length > 0 ? 2 : 0);
60
+ if (used + cost <= CONTEXT_BUDGET_CHARS - noteReserve) {
61
+ kept.push(block.text);
62
+ used += cost;
63
+ } else if (kept.length === 0) {
64
+ const room = CONTEXT_BUDGET_CHARS - noteReserve;
65
+ kept.push(
66
+ `${block.text.slice(0, room)}
67
+ [yandecode: truncated ${block.text.length - room} chars from ${block.module}]`
68
+ );
69
+ used = CONTEXT_BUDGET_CHARS;
70
+ } else {
71
+ dropped.push(block.module);
72
+ }
73
+ }
74
+ if (dropped.length > 0) {
75
+ kept.push(
76
+ `[yandecode: ${dropped.length} context block(s) omitted to fit the hook budget: ${dropped.join(", ")}]`
77
+ );
78
+ }
79
+ return kept.join("\n\n");
80
+ }
81
+ async function dispatchHook(options) {
82
+ const { event, input } = options;
83
+ const subscribed = options.modules.filter(
84
+ (m) => m.hooks.some((b) => b.event === event && matches(b.matcher, input.tool_name))
85
+ );
86
+ const failures = [];
87
+ const results = await Promise.all(
88
+ subscribed.map(async (module) => {
89
+ try {
90
+ const run = async () => {
91
+ const runtime = await module.load();
92
+ const handler = runtime.hooks?.[event];
93
+ if (!handler) return { kind: "none" };
94
+ return handler(input, options.contextFor(module));
95
+ };
96
+ return { module: module.id, result: await withTimeout(run(), options.timeoutMs) };
97
+ } catch (error) {
98
+ failures.push({
99
+ module: module.id,
100
+ error: error instanceof Error ? error.message : String(error)
101
+ });
102
+ return null;
103
+ }
104
+ })
105
+ );
106
+ const denies = [];
107
+ const contexts = [];
108
+ for (const entry of results) {
109
+ if (!entry) continue;
110
+ if (entry.result.kind === "deny" && event === "PreToolUse") {
111
+ denies.push(`[${entry.module}] ${entry.result.reason}`);
112
+ } else if (entry.result.kind === "context" && entry.result.text.trim() !== "") {
113
+ contexts.push({ module: entry.module, text: entry.result.text });
114
+ }
115
+ }
116
+ if (denies.length > 0) {
117
+ return {
118
+ failures,
119
+ stdout: JSON.stringify({
120
+ hookSpecificOutput: {
121
+ hookEventName: "PreToolUse",
122
+ permissionDecision: "deny",
123
+ permissionDecisionReason: denies.join("\n")
124
+ }
125
+ })
126
+ };
127
+ }
128
+ if (contexts.length > 0 && CONTEXT_EVENTS.has(event)) {
129
+ return {
130
+ failures,
131
+ stdout: JSON.stringify({
132
+ hookSpecificOutput: { hookEventName: event, additionalContext: fitContext(contexts) }
133
+ })
134
+ };
135
+ }
136
+ return { stdout: "", failures };
137
+ }
138
+
139
+ // packages/cli/src/hooks/entry.ts
140
+ var BUDGET_MS = { PreToolUse: 1500, PostToolUse: 2500 };
141
+ async function readStdin() {
142
+ if (process.stdin.isTTY) return "";
143
+ const chunks = [];
144
+ for await (const chunk of process.stdin) chunks.push(Buffer.from(chunk));
145
+ return Buffer.concat(chunks).toString("utf8");
146
+ }
147
+ function parseInput(text) {
148
+ try {
149
+ const value = JSON.parse(text);
150
+ return typeof value === "object" && value !== null ? value : {};
151
+ } catch {
152
+ return {};
153
+ }
154
+ }
155
+ async function runHookCli(event) {
156
+ if (!HOOK_EVENTS.includes(event)) {
157
+ process.stderr.write(`yandecode: unknown hook event "${event}"
158
+ `);
159
+ return 0;
160
+ }
161
+ const input = parseInput(await readStdin());
162
+ try {
163
+ const ws = openWorkspace(typeof input.cwd === "string" ? input.cwd : process.cwd());
164
+ if (!ws) return 0;
165
+ const modules = enabledModules(ws);
166
+ const result = await dispatchHook({
167
+ event,
168
+ input,
169
+ modules,
170
+ contextFor: (m) => moduleContext(ws, m),
171
+ timeoutMs: BUDGET_MS[event] ?? 8e3
172
+ });
173
+ for (const failure of result.failures) {
174
+ const module = modules.find((m) => m.id === failure.module);
175
+ if (module) moduleContext(ws, module).log("hook_failure", { event, error: failure.error });
176
+ }
177
+ if (result.stdout) process.stdout.write(result.stdout);
178
+ } catch (error) {
179
+ process.stderr.write(`yandecode hook ${event}: ${error.message}
180
+ `);
181
+ }
182
+ return 0;
183
+ }
184
+ export {
185
+ runHookCli
186
+ };
187
+ //# sourceMappingURL=entry-YAOEX3EB.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/modules/contract.ts", "../../src/hooks/dispatch.ts", "../../src/hooks/entry.ts"],
4
+ "sourcesContent": ["import type { WorkspacePaths, YandeCodeConfig } from '@yandecode/core';\nimport type { Command } from 'commander';\nimport type { ZodRawShape } from 'zod';\n\n/** Claude Code hook events a module may subscribe to. */\nexport const HOOK_EVENTS = [\n 'SessionStart',\n 'UserPromptSubmit',\n 'PreToolUse',\n 'PostToolUse',\n 'Stop',\n 'SubagentStop',\n 'PreCompact',\n 'SessionEnd',\n] as const;\n\nexport type HookEvent = (typeof HOOK_EVENTS)[number];\n\n/** One hook subscription materialized into .claude/settings.json. */\nexport interface HookBinding {\n event: HookEvent;\n /** Tool-name matcher for PreToolUse/PostToolUse (regex alternation, e.g. \"Write|Edit\"). */\n matcher?: string;\n}\n\n/** The subset of Claude Code's hook payload modules read. Unknown fields are preserved. */\nexport interface HookInput {\n session_id?: string;\n cwd?: string;\n hook_event_name?: string;\n source?: string;\n reason?: string;\n prompt?: string;\n tool_name?: string;\n tool_input?: Record<string, unknown>;\n tool_response?: unknown;\n [key: string]: unknown;\n}\n\nexport type HookResult =\n | { kind: 'none' }\n /** Text added to the model's context (SessionStart, UserPromptSubmit, PreToolUse, PostToolUse). */\n | { kind: 'context'; text: string }\n /** PreToolUse only: block the call and tell the model why / what to do instead. */\n | { kind: 'deny'; reason: string };\n\n/** Lazily opened services shared by all modules of one process. */\nexport interface ModuleContext {\n root: string;\n paths: WorkspacePaths;\n config: YandeCodeConfig;\n /** This module's own section of yandecode.json (already defaulted by the module). */\n settings: Record<string, unknown>;\n /** Append a structured line to .yandecode/logs/<module>.jsonl. */\n log(event: string, data?: Record<string, unknown>): void;\n}\n\nexport type HookHandler = (input: HookInput, ctx: ModuleContext) => Promise<HookResult>;\n\nexport interface ToolResult {\n text: string;\n isError?: boolean;\n}\n\nexport type ToolHandler = (\n args: Record<string, unknown>,\n ctx: ModuleContext,\n) => Promise<ToolResult>;\n\n/** Declared up front so the MCP host can list tools without loading the module. */\nexport interface ToolSpec {\n name: string;\n /** Short human title (MCP `title`), e.g. \"Find code\". */\n title: string;\n /** Starts with the intent it serves and what it replaces; mechanics come after. */\n description: string;\n inputSchema: ZodRawShape;\n}\n\n/**\n * One line of the routing table the agent receives (MCP instructions, routing skill): for this\n * intent, call this tool instead of the built-in habit. Agents keep their grep/cat/Bash habits\n * unless told, at the right moment, which tool fits which intent (pacolang A/B, 2026-09-26).\n */\nexport interface RoutingRule {\n /** What the agent is trying to do, phrased as the agent would think it. */\n intent: string;\n /** The tool to call (bare name, e.g. `code_search`), optionally with an argument hint. */\n use: string;\n /** The built-in habit it replaces, e.g. \"grep -rn / rg / find\". */\n insteadOf: string;\n}\n\nexport interface DoctorCheck {\n name: string;\n status: 'ok' | 'warn' | 'fail' | 'skip';\n detail: string;\n fix?: string;\n}\n\n/** The heavy part of a module, imported only when one of its tools/hooks/commands runs. */\nexport interface ModuleRuntime {\n tools?: Record<string, ToolHandler>;\n hooks?: Partial<Record<HookEvent, HookHandler>>;\n doctor?: (ctx: ModuleContext) => Promise<DoctorCheck[]>;\n /** Release long-lived resources (language servers, DB handles). */\n dispose?: () => Promise<void>;\n}\n\nexport interface ModuleDefinition {\n id: string;\n title: string;\n /** One line shown by `init` and `modules list`. */\n summary: string;\n requires: readonly string[];\n defaultEnabled: boolean;\n /** One or two lines for the managed CLAUDE.md block: when the agent should use this module. */\n guidance?: string;\n /** Intent \u2192 tool rules composed into the MCP instructions and the routing skill. */\n routing?: readonly RoutingRule[];\n /** Human-readable external requirements (e.g. \"npm registry access on first use\"). */\n requirements?: readonly string[];\n hooks: readonly HookBinding[];\n tools?: readonly ToolSpec[];\n /** Skill directory names shipped in @yandecode/plugin/skills. */\n skills: readonly string[];\n /** Agent file names (without .md) shipped in @yandecode/plugin/agents. */\n agents: readonly string[];\n /** Registers `yandecode <module-id> \u2026` subcommands; actions must load the runtime lazily. */\n cli?: (program: Command) => void;\n load: () => Promise<ModuleRuntime>;\n}\n", "import type {\n HookEvent,\n HookInput,\n HookResult,\n ModuleContext,\n ModuleDefinition,\n} from '@cli/modules/contract';\n\n/** Claude Code replaces hook stdout above 10 000 chars with a stub; stay well below it. */\nexport const CONTEXT_BUDGET_CHARS = 8_000;\n\nconst CONTEXT_EVENTS: ReadonlySet<HookEvent> = new Set([\n 'SessionStart',\n 'UserPromptSubmit',\n 'PreToolUse',\n 'PostToolUse',\n]);\n\nexport interface DispatchOptions {\n event: HookEvent;\n input: HookInput;\n /** Enabled modules, in dependency order. */\n modules: readonly ModuleDefinition[];\n contextFor: (module: ModuleDefinition) => ModuleContext;\n timeoutMs: number;\n}\n\nexport interface DispatchFailure {\n module: string;\n error: string;\n}\n\nexport interface DispatchResult {\n stdout: string;\n failures: DispatchFailure[];\n}\n\nfunction matches(matcher: string | undefined, toolName: string | undefined): boolean {\n if (matcher === undefined || matcher === '' || matcher === '*') return true;\n if (toolName === undefined) return false;\n return new RegExp(`^(?:${matcher})$`).test(toolName);\n}\n\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n reject(new Error(`timed out after ${ms} ms`));\n }, ms);\n promise.then(\n (value) => {\n clearTimeout(timer);\n resolve(value);\n },\n (error: unknown) => {\n clearTimeout(timer);\n reject(error instanceof Error ? error : new Error(String(error)));\n },\n );\n });\n}\n\nfunction fitContext(blocks: { module: string; text: string }[]): string {\n const kept: string[] = [];\n const dropped: string[] = [];\n let used = 0;\n const noteReserve = 200;\n for (const block of blocks) {\n const cost = block.text.length + (kept.length > 0 ? 2 : 0);\n if (used + cost <= CONTEXT_BUDGET_CHARS - noteReserve) {\n kept.push(block.text);\n used += cost;\n } else if (kept.length === 0) {\n const room = CONTEXT_BUDGET_CHARS - noteReserve;\n kept.push(\n `${block.text.slice(0, room)}\\n[yandecode: truncated ${block.text.length - room} chars from ${block.module}]`,\n );\n used = CONTEXT_BUDGET_CHARS;\n } else {\n dropped.push(block.module);\n }\n }\n if (dropped.length > 0) {\n kept.push(\n `[yandecode: ${dropped.length} context block(s) omitted to fit the hook budget: ${dropped.join(', ')}]`,\n );\n }\n return kept.join('\\n\\n');\n}\n\n/**\n * Runs every enabled module subscribed to `event` (and matching the tool, for tool events),\n * each isolated: a module that throws or exceeds the time budget is recorded and skipped, never\n * blocking Claude Code (fail-open). Decisions merge as deny > context > none.\n */\nexport async function dispatchHook(options: DispatchOptions): Promise<DispatchResult> {\n const { event, input } = options;\n const subscribed = options.modules.filter((m) =>\n m.hooks.some((b) => b.event === event && matches(b.matcher, input.tool_name)),\n );\n\n const failures: DispatchFailure[] = [];\n const results = await Promise.all(\n subscribed.map(async (module): Promise<{ module: string; result: HookResult } | null> => {\n try {\n const run = async (): Promise<HookResult> => {\n const runtime = await module.load();\n const handler = runtime.hooks?.[event];\n if (!handler) return { kind: 'none' };\n return handler(input, options.contextFor(module));\n };\n return { module: module.id, result: await withTimeout(run(), options.timeoutMs) };\n } catch (error) {\n failures.push({\n module: module.id,\n error: error instanceof Error ? error.message : String(error),\n });\n return null;\n }\n }),\n );\n\n const denies: string[] = [];\n const contexts: { module: string; text: string }[] = [];\n for (const entry of results) {\n if (!entry) continue;\n if (entry.result.kind === 'deny' && event === 'PreToolUse') {\n denies.push(`[${entry.module}] ${entry.result.reason}`);\n } else if (entry.result.kind === 'context' && entry.result.text.trim() !== '') {\n contexts.push({ module: entry.module, text: entry.result.text });\n }\n }\n\n if (denies.length > 0) {\n return {\n failures,\n stdout: JSON.stringify({\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n permissionDecision: 'deny',\n permissionDecisionReason: denies.join('\\n'),\n },\n }),\n };\n }\n if (contexts.length > 0 && CONTEXT_EVENTS.has(event)) {\n return {\n failures,\n stdout: JSON.stringify({\n hookSpecificOutput: { hookEventName: event, additionalContext: fitContext(contexts) },\n }),\n };\n }\n return { stdout: '', failures };\n}\n", "import { HOOK_EVENTS, type HookEvent, type HookInput } from '@cli/modules/contract';\nimport { enabledModules, moduleContext, openWorkspace } from '@cli/modules/host';\nimport { dispatchHook } from './dispatch';\n\n/** Must stay below the `timeout` written into settings.json (5 s for tool events, 10 s otherwise). */\nconst BUDGET_MS: Partial<Record<HookEvent, number>> = { PreToolUse: 1_500, PostToolUse: 2_500 };\n\nasync function readStdin(): Promise<string> {\n if (process.stdin.isTTY) return '';\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) chunks.push(Buffer.from(chunk as Buffer));\n return Buffer.concat(chunks).toString('utf8');\n}\n\nfunction parseInput(text: string): HookInput {\n try {\n const value: unknown = JSON.parse(text);\n return typeof value === 'object' && value !== null ? (value as HookInput) : {};\n } catch {\n return {};\n }\n}\n\n/**\n * `yandecode hook <Event>` \u2014 invoked by Claude Code. Always exits 0: a broken or slow module must\n * never block the user's session (fail-open, ADR-016/ADR-022). Decisions travel as JSON on stdout.\n */\nexport async function runHookCli(event: string): Promise<number> {\n if (!(HOOK_EVENTS as readonly string[]).includes(event)) {\n process.stderr.write(`yandecode: unknown hook event \"${event}\"\\n`);\n return 0;\n }\n const input = parseInput(await readStdin());\n try {\n const ws = openWorkspace(typeof input.cwd === 'string' ? input.cwd : process.cwd());\n if (!ws) return 0;\n const modules = enabledModules(ws);\n const result = await dispatchHook({\n event: event as HookEvent,\n input,\n modules,\n contextFor: (m) => moduleContext(ws, m),\n timeoutMs: BUDGET_MS[event as HookEvent] ?? 8_000,\n });\n for (const failure of result.failures) {\n const module = modules.find((m) => m.id === failure.module);\n if (module) moduleContext(ws, module).log('hook_failure', { event, error: failure.error });\n }\n if (result.stdout) process.stdout.write(result.stdout);\n } catch (error) {\n process.stderr.write(`yandecode hook ${event}: ${(error as Error).message}\\n`);\n }\n return 0;\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,46 @@
1
+ import { createRequire as __yandecodeCreateRequire } from 'node:module';
2
+ const require = __yandecodeCreateRequire(import.meta.url);
3
+ import {
4
+ selectModules
5
+ } from "./chunk-23DG7PZZ.js";
6
+ import {
7
+ printApplyReport,
8
+ saveSelectionAndApply
9
+ } from "./chunk-VKVJGBNJ.js";
10
+ import "./chunk-KVBKQXTU.js";
11
+ import "./chunk-L2DDIZPI.js";
12
+ import "./chunk-DWD37AI2.js";
13
+ import "./chunk-PUWSEWX3.js";
14
+ import "./chunk-QCQC73WX.js";
15
+ import {
16
+ MODULES
17
+ } from "./chunk-7L6DD2VD.js";
18
+ import {
19
+ CONFIG_FILENAME,
20
+ loadConfig
21
+ } from "./chunk-Y2MIXROU.js";
22
+
23
+ // packages/cli/src/commands/init.ts
24
+ import { existsSync } from "node:fs";
25
+ async function runInit(cwd, flags, io, deps = {}) {
26
+ const registry = deps.registry ?? MODULES;
27
+ const current = existsSync(`${cwd}/${CONFIG_FILENAME}`) ? loadConfig(cwd).modules : null;
28
+ const requested = await selectModules(registry, current, flags, io);
29
+ const { config, added, report } = saveSelectionAndApply(
30
+ cwd,
31
+ requested,
32
+ deps,
33
+ flags.force ? { force: true } : {}
34
+ );
35
+ io.out(`YandeCode initialized in ${cwd}
36
+ `);
37
+ printApplyReport(io, config.modules, added, report);
38
+ io.out(
39
+ 'Restart Claude Code in this directory to load the changes. Run "yandecode doctor" to verify.\n'
40
+ );
41
+ return 0;
42
+ }
43
+ export {
44
+ runInit
45
+ };
46
+ //# sourceMappingURL=init-4ZJFCKIJ.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/init.ts"],
4
+ "sourcesContent": ["import { existsSync } from 'node:fs';\nimport { CONFIG_FILENAME, loadConfig } from '@yandecode/core';\nimport type { Io } from '@cli/io';\nimport { MODULES } from '@cli/modules/registry';\nimport { selectModules, type SelectionFlags } from './select-modules';\nimport { printApplyReport, saveSelectionAndApply, type SetupDeps } from './setup';\n\nexport interface InitFlags extends SelectionFlags {\n force?: boolean;\n}\n\nexport async function runInit(\n cwd: string,\n flags: InitFlags,\n io: Io,\n deps: SetupDeps = {},\n): Promise<number> {\n const registry = deps.registry ?? MODULES;\n const current = existsSync(`${cwd}/${CONFIG_FILENAME}`) ? loadConfig(cwd).modules : null;\n const requested = await selectModules(registry, current, flags, io);\n const { config, added, report } = saveSelectionAndApply(\n cwd,\n requested,\n deps,\n flags.force ? { force: true } : {},\n );\n io.out(`YandeCode initialized in ${cwd}\\n`);\n printApplyReport(io, config.modules, added, report);\n io.out(\n 'Restart Claude Code in this directory to load the changes. Run \"yandecode doctor\" to verify.\\n',\n );\n return 0;\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,kBAAkB;AAW3B,eAAsB,QACpB,KACA,OACA,IACA,OAAkB,CAAC,GACF;AACjB,QAAM,WAAW,KAAK,YAAY;AAClC,QAAM,UAAU,WAAW,GAAG,GAAG,IAAI,eAAe,EAAE,IAAI,WAAW,GAAG,EAAE,UAAU;AACpF,QAAM,YAAY,MAAM,cAAc,UAAU,SAAS,OAAO,EAAE;AAClE,QAAM,EAAE,QAAQ,OAAO,OAAO,IAAI;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;AAAA,EACnC;AACA,KAAG,IAAI,4BAA4B,GAAG;AAAA,CAAI;AAC1C,mBAAiB,IAAI,OAAO,SAAS,OAAO,MAAM;AAClD,KAAG;AAAA,IACD;AAAA,EACF;AACA,SAAO;AACT;",
6
+ "names": []
7
+ }