ikarmic-forge 0.0.0-stage → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +62 -2
  3. package/dist/acp/server.d.ts +55 -0
  4. package/dist/acp/server.d.ts.map +1 -0
  5. package/dist/acp/server.js +276 -0
  6. package/dist/acp/server.js.map +1 -0
  7. package/dist/app.d.ts +22 -0
  8. package/dist/app.d.ts.map +1 -0
  9. package/dist/app.js +159 -0
  10. package/dist/app.js.map +1 -0
  11. package/dist/bin/forge.d.ts +3 -0
  12. package/dist/bin/forge.d.ts.map +1 -0
  13. package/dist/bin/forge.js +786 -0
  14. package/dist/bin/forge.js.map +1 -0
  15. package/dist/chat-files.d.ts +45 -0
  16. package/dist/chat-files.d.ts.map +1 -0
  17. package/dist/chat-files.js +189 -0
  18. package/dist/chat-files.js.map +1 -0
  19. package/dist/clipboard.d.ts +38 -0
  20. package/dist/clipboard.d.ts.map +1 -0
  21. package/dist/clipboard.js +63 -0
  22. package/dist/clipboard.js.map +1 -0
  23. package/dist/commands/acp.d.ts +4 -0
  24. package/dist/commands/acp.d.ts.map +1 -0
  25. package/dist/commands/acp.js +36 -0
  26. package/dist/commands/acp.js.map +1 -0
  27. package/dist/commands/ai-comments.d.ts +9 -0
  28. package/dist/commands/ai-comments.d.ts.map +1 -0
  29. package/dist/commands/ai-comments.js +43 -0
  30. package/dist/commands/ai-comments.js.map +1 -0
  31. package/dist/commands/architect.d.ts +9 -0
  32. package/dist/commands/architect.d.ts.map +1 -0
  33. package/dist/commands/architect.js +27 -0
  34. package/dist/commands/architect.js.map +1 -0
  35. package/dist/commands/checkpoint.d.ts +10 -0
  36. package/dist/commands/checkpoint.d.ts.map +1 -0
  37. package/dist/commands/checkpoint.js +168 -0
  38. package/dist/commands/checkpoint.js.map +1 -0
  39. package/dist/commands/config.d.ts +15 -0
  40. package/dist/commands/config.d.ts.map +1 -0
  41. package/dist/commands/config.js +180 -0
  42. package/dist/commands/config.js.map +1 -0
  43. package/dist/commands/diff.d.ts +29 -0
  44. package/dist/commands/diff.d.ts.map +1 -0
  45. package/dist/commands/diff.js +90 -0
  46. package/dist/commands/diff.js.map +1 -0
  47. package/dist/commands/hook.d.ts +10 -0
  48. package/dist/commands/hook.d.ts.map +1 -0
  49. package/dist/commands/hook.js +121 -0
  50. package/dist/commands/hook.js.map +1 -0
  51. package/dist/commands/mcp.d.ts +10 -0
  52. package/dist/commands/mcp.d.ts.map +1 -0
  53. package/dist/commands/mcp.js +110 -0
  54. package/dist/commands/mcp.js.map +1 -0
  55. package/dist/commands/memory.d.ts +10 -0
  56. package/dist/commands/memory.d.ts.map +1 -0
  57. package/dist/commands/memory.js +77 -0
  58. package/dist/commands/memory.js.map +1 -0
  59. package/dist/commands/orchestrator.d.ts +22 -0
  60. package/dist/commands/orchestrator.d.ts.map +1 -0
  61. package/dist/commands/orchestrator.js +113 -0
  62. package/dist/commands/orchestrator.js.map +1 -0
  63. package/dist/commands/plugin.d.ts +3 -0
  64. package/dist/commands/plugin.d.ts.map +1 -0
  65. package/dist/commands/plugin.js +62 -0
  66. package/dist/commands/plugin.js.map +1 -0
  67. package/dist/commands/policy.d.ts +2 -0
  68. package/dist/commands/policy.d.ts.map +1 -0
  69. package/dist/commands/policy.js +21 -0
  70. package/dist/commands/policy.js.map +1 -0
  71. package/dist/commands/skill.d.ts +13 -0
  72. package/dist/commands/skill.d.ts.map +1 -0
  73. package/dist/commands/skill.js +194 -0
  74. package/dist/commands/skill.js.map +1 -0
  75. package/dist/commands/spec.d.ts +23 -0
  76. package/dist/commands/spec.d.ts.map +1 -0
  77. package/dist/commands/spec.js +147 -0
  78. package/dist/commands/spec.js.map +1 -0
  79. package/dist/commands/watch.d.ts +15 -0
  80. package/dist/commands/watch.d.ts.map +1 -0
  81. package/dist/commands/watch.js +83 -0
  82. package/dist/commands/watch.js.map +1 -0
  83. package/dist/commands/worktree.d.ts +22 -0
  84. package/dist/commands/worktree.d.ts.map +1 -0
  85. package/dist/commands/worktree.js +187 -0
  86. package/dist/commands/worktree.js.map +1 -0
  87. package/dist/components/Approval.d.ts +9 -0
  88. package/dist/components/Approval.d.ts.map +1 -0
  89. package/dist/components/Approval.js +39 -0
  90. package/dist/components/Approval.js.map +1 -0
  91. package/dist/components/Footer.d.ts +22 -0
  92. package/dist/components/Footer.d.ts.map +1 -0
  93. package/dist/components/Footer.js +59 -0
  94. package/dist/components/Footer.js.map +1 -0
  95. package/dist/components/Header.d.ts +11 -0
  96. package/dist/components/Header.d.ts.map +1 -0
  97. package/dist/components/Header.js +23 -0
  98. package/dist/components/Header.js.map +1 -0
  99. package/dist/components/Spinner.d.ts +3 -0
  100. package/dist/components/Spinner.d.ts.map +1 -0
  101. package/dist/components/Spinner.js +8 -0
  102. package/dist/components/Spinner.js.map +1 -0
  103. package/dist/components/Stream.d.ts +10 -0
  104. package/dist/components/Stream.d.ts.map +1 -0
  105. package/dist/components/Stream.js +13 -0
  106. package/dist/components/Stream.js.map +1 -0
  107. package/dist/components/ToolEvent.d.ts +13 -0
  108. package/dist/components/ToolEvent.d.ts.map +1 -0
  109. package/dist/components/ToolEvent.js +54 -0
  110. package/dist/components/ToolEvent.js.map +1 -0
  111. package/dist/credential-store.d.ts +8 -0
  112. package/dist/credential-store.d.ts.map +1 -0
  113. package/dist/credential-store.js +37 -0
  114. package/dist/credential-store.js.map +1 -0
  115. package/dist/git-workflow.d.ts +16 -0
  116. package/dist/git-workflow.d.ts.map +1 -0
  117. package/dist/git-workflow.js +38 -0
  118. package/dist/git-workflow.js.map +1 -0
  119. package/dist/mcp-loader.d.ts +25 -0
  120. package/dist/mcp-loader.d.ts.map +1 -0
  121. package/dist/mcp-loader.js +99 -0
  122. package/dist/mcp-loader.js.map +1 -0
  123. package/dist/notify.d.ts +12 -0
  124. package/dist/notify.d.ts.map +1 -0
  125. package/dist/notify.js +47 -0
  126. package/dist/notify.js.map +1 -0
  127. package/dist/options.d.ts +449 -0
  128. package/dist/options.d.ts.map +1 -0
  129. package/dist/options.js +871 -0
  130. package/dist/options.js.map +1 -0
  131. package/dist/repl-commands.d.ts +92 -0
  132. package/dist/repl-commands.d.ts.map +1 -0
  133. package/dist/repl-commands.js +228 -0
  134. package/dist/repl-commands.js.map +1 -0
  135. package/dist/repl-extras.d.ts +39 -0
  136. package/dist/repl-extras.d.ts.map +1 -0
  137. package/dist/repl-extras.js +120 -0
  138. package/dist/repl-extras.js.map +1 -0
  139. package/dist/repl.d.ts +76 -0
  140. package/dist/repl.d.ts.map +1 -0
  141. package/dist/repl.js +1507 -0
  142. package/dist/repl.js.map +1 -0
  143. package/dist/runner.d.ts +64 -0
  144. package/dist/runner.d.ts.map +1 -0
  145. package/dist/runner.js +61 -0
  146. package/dist/runner.js.map +1 -0
  147. package/dist/session-checkpoints.d.ts +6 -0
  148. package/dist/session-checkpoints.d.ts.map +1 -0
  149. package/dist/session-checkpoints.js +25 -0
  150. package/dist/session-checkpoints.js.map +1 -0
  151. package/dist/specialists-loader.d.ts +22 -0
  152. package/dist/specialists-loader.d.ts.map +1 -0
  153. package/dist/specialists-loader.js +38 -0
  154. package/dist/specialists-loader.js.map +1 -0
  155. package/dist/tool-display.d.ts +19 -0
  156. package/dist/tool-display.d.ts.map +1 -0
  157. package/dist/tool-display.js +57 -0
  158. package/dist/tool-display.js.map +1 -0
  159. package/package.json +70 -3
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `forge skill …` subcommand: list, show, install, search, browse skills.
3
+ *
4
+ * Mirrors how `forge session …` works: no AI provider required, exits
5
+ * with code 0 on success / 2 on user error / 1 on unexpected failure.
6
+ *
7
+ * v2.1: `install <name>` consults the marketplace catalog first; falls
8
+ * back to the GitHub-URL / shorthand path when the name isn't found.
9
+ * `search <query>` fetches + filters the catalog.
10
+ */
11
+ import type { ParsedSkillCommand } from '../options.js';
12
+ export declare function handleSkillCommand(cmd: ParsedSkillCommand, cwd: string): Promise<number>;
13
+ //# sourceMappingURL=skill.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAcH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAWxD,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAoB9F"}
@@ -0,0 +1,194 @@
1
+ /**
2
+ * `forge skill …` subcommand: list, show, install, search, browse skills.
3
+ *
4
+ * Mirrors how `forge session …` works: no AI provider required, exits
5
+ * with code 0 on success / 2 on user error / 1 on unexpected failure.
6
+ *
7
+ * v2.1: `install <name>` consults the marketplace catalog first; falls
8
+ * back to the GitHub-URL / shorthand path when the name isn't found.
9
+ * `search <query>` fetches + filters the catalog.
10
+ */
11
+ import { mkdir, writeFile } from 'node:fs/promises';
12
+ import path from 'node:path';
13
+ import { DEFAULT_SKILL_CATALOG_URL, discoverSkills, fetchSkillsCatalog, installSkillFromCatalog, loadSkillsRegistryAsync, searchSkills, } from '@ikarmic/forge-core';
14
+ /**
15
+ * Skill marketplace catalog URL. The default URL points at a public
16
+ * JSON document hosted on GitHub raw content. Operators can override
17
+ * via `FORGE_SKILL_CATALOG_URL`.
18
+ */
19
+ function catalogUrl() {
20
+ return process.env.FORGE_SKILL_CATALOG_URL ?? DEFAULT_SKILL_CATALOG_URL;
21
+ }
22
+ export async function handleSkillCommand(cmd, cwd) {
23
+ if (cmd.list) {
24
+ return listSkills(cwd);
25
+ }
26
+ if (cmd.show) {
27
+ return showSkill(cwd, cmd.show.name);
28
+ }
29
+ if (cmd.install) {
30
+ return installFromSource(cmd.install.url, cwd);
31
+ }
32
+ if (cmd.search) {
33
+ return searchCatalog(cmd.search.query, cmd.search.limit ?? undefined);
34
+ }
35
+ if (cmd.browse) {
36
+ return browseMarketplace();
37
+ }
38
+ process.stderr.write('forge skill: expected one of list|show|install|search|browse. Try `forge skill --help` (not yet implemented; read the README).\n');
39
+ return 2;
40
+ }
41
+ async function listSkills(cwd) {
42
+ const skills = await discoverSkills(cwd);
43
+ if (skills.length === 0) {
44
+ process.stdout.write(`(no skills found in ${cwd})\n`);
45
+ process.stdout.write('Discovery roots: ./skills/ ./.forge/skills/ ~/.forge/skills/\n');
46
+ return 0;
47
+ }
48
+ for (const skill of skills) {
49
+ const ver = skill.version ? ` v${skill.version}` : '';
50
+ process.stdout.write(`${skill.name}${ver} [${skill.source.kind}] ${skill.source.path}\n`);
51
+ if (skill.description) {
52
+ process.stdout.write(` ${skill.description}\n`);
53
+ }
54
+ }
55
+ return 0;
56
+ }
57
+ async function showSkill(cwd, name) {
58
+ const registry = await loadSkillsRegistryAsync(cwd);
59
+ const skill = registry.get(name);
60
+ if (!skill) {
61
+ process.stderr.write(`forge skill: no skill named "${name}"\n`);
62
+ return 2;
63
+ }
64
+ process.stdout.write(`# ${skill.name}\n`);
65
+ if (skill.version)
66
+ process.stdout.write(`version: ${skill.version}\n`);
67
+ process.stdout.write(`source: ${skill.source.kind} ${skill.source.path}\n`);
68
+ if (skill.description)
69
+ process.stdout.write(`description: ${skill.description}\n`);
70
+ if (skill.allowedTools && skill.allowedTools.length > 0) {
71
+ process.stdout.write(`allowed-tools: ${skill.allowedTools.join(', ')}\n`);
72
+ }
73
+ process.stdout.write('\n');
74
+ process.stdout.write(skill.body);
75
+ if (!skill.body.endsWith('\n'))
76
+ process.stdout.write('\n');
77
+ return 0;
78
+ }
79
+ async function installFromSource(source, cwd) {
80
+ // v2.1: try the marketplace catalog first when `source` looks like a
81
+ // name (no `/`, no scheme, no `.git`). Falls back to GitHub URL /
82
+ // shorthand handling when the catalog fetch fails or the name isn't
83
+ // found.
84
+ if (looksLikeSkillName(source)) {
85
+ const catalog = await fetchSkillsCatalog(catalogUrl());
86
+ if (catalog) {
87
+ const entry = catalog.skills.find((s) => s.name === source);
88
+ if (entry) {
89
+ const result = await installSkillFromCatalog({
90
+ name: source,
91
+ catalog,
92
+ });
93
+ if (result) {
94
+ process.stdout.write(`installed ${result.path}\n`);
95
+ return 0;
96
+ }
97
+ process.stderr.write(`forge skill install: failed to fetch ${entry.github}: falling back\n`);
98
+ }
99
+ else {
100
+ process.stderr.write(`forge skill install: "${source}" not in marketplace: falling back\n`);
101
+ }
102
+ }
103
+ else {
104
+ process.stderr.write(`forge skill install: could not load marketplace catalog (${catalogUrl()}): falling back to URL stub\n`);
105
+ }
106
+ }
107
+ // Fallback: scaffold a SKILL.md stub (the v1.1 behavior).
108
+ const targetDir = path.resolve(cwd, 'skills');
109
+ await mkdir(targetDir, { recursive: true });
110
+ const slug = slugFromUrl(source);
111
+ const skillPath = path.join(targetDir, `${slug}.md`);
112
+ const content = `---
113
+ name: ${slug}
114
+ description: Skill installed from ${source}. Edit this description so the activator picks it up for matching tasks.
115
+ version: 1.0.0
116
+ ---
117
+
118
+ # ${slug}
119
+
120
+ This skill was installed by \`forge skill install ${source}\`.
121
+
122
+ Replace this body with your own instructions. The activator matches on the
123
+ \`description\` field above: keep it focused (1-2 sentences) and free of
124
+ generic words ("the", "and", "use", "tool") so description-scoring
125
+ selects it for the right tasks.
126
+
127
+ Upstream: ${source}
128
+ `;
129
+ await writeFile(skillPath, content, 'utf8');
130
+ process.stdout.write(`installed ${skillPath}\n`);
131
+ process.stdout.write(`Next: edit ${skillPath} and write your skill body.\n`);
132
+ return 0;
133
+ }
134
+ /** Heuristic: does `source` look like a skill name (vs a URL)? */
135
+ function looksLikeSkillName(source) {
136
+ if (!source)
137
+ return false;
138
+ if (source.includes('/') || source.includes('\\'))
139
+ return false;
140
+ if (/^[a-z]+:\/\//i.test(source))
141
+ return false;
142
+ if (source.includes('.'))
143
+ return false; // skip .git, .com, etc.
144
+ return /^[a-z0-9_-]+$/i.test(source);
145
+ }
146
+ async function searchCatalog(query, limit) {
147
+ const catalog = await fetchSkillsCatalog(catalogUrl());
148
+ if (!catalog) {
149
+ process.stderr.write(`forge skill search: could not load marketplace catalog (${catalogUrl()})\n` +
150
+ `Set FORGE_SKILL_CATALOG_URL to override.\n`);
151
+ return 1;
152
+ }
153
+ const result = searchSkills(catalog, query, limit);
154
+ if (result.matches.length === 0) {
155
+ process.stdout.write(`(no skills match "${query}" in ${result.totalScanned} catalog entries)\n`);
156
+ return 0;
157
+ }
158
+ for (const skill of result.matches) {
159
+ const ver = skill.version ? ` v${skill.version}` : '';
160
+ process.stdout.write(`${skill.name}${ver} · ${skill.displayName}\n`);
161
+ if (skill.description)
162
+ process.stdout.write(` ${skill.description}\n`);
163
+ if (skill.tags && skill.tags.length > 0) {
164
+ process.stdout.write(` tags: ${skill.tags.join(', ')}\n`);
165
+ }
166
+ }
167
+ process.stdout.write(`\n${result.matches.length} of ${result.totalScanned} entries matched.\n`);
168
+ process.stdout.write(`Install with: forge skill install <name>\n`);
169
+ return 0;
170
+ }
171
+ function slugFromUrl(url) {
172
+ try {
173
+ const u = new URL(url);
174
+ const segs = u.pathname.split('/').filter((s) => s.length > 0);
175
+ const last = segs[segs.length - 1] ?? 'external-skill';
176
+ return last
177
+ .toLowerCase()
178
+ .replace(/\.git$/, '')
179
+ .replace(/[^a-z0-9_-]+/g, '-')
180
+ .replace(/^-+|-+$/g, '') || 'external-skill';
181
+ }
182
+ catch {
183
+ return 'external-skill';
184
+ }
185
+ }
186
+ function browseMarketplace() {
187
+ process.stdout.write(`IKarmic Forge Skills Marketplace (catalog):\n ${catalogUrl()}\n\n`);
188
+ process.stdout.write('Browse community skills there. To install one:\n');
189
+ process.stdout.write(' forge skill install <github-url> # any GitHub repo with SKILL.md\n');
190
+ process.stdout.write(' forge skill install <name> # from the marketplace catalog\n');
191
+ process.stdout.write(' forge skill search <query> # find skills by keyword\n');
192
+ return 0;
193
+ }
194
+ //# sourceMappingURL=skill.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EACL,yBAAyB,EACzB,cAAc,EACd,kBAAkB,EAClB,uBAAuB,EACvB,uBAAuB,EACvB,YAAY,GACb,MAAM,qBAAqB,CAAC;AAI7B;;;;GAIG;AACH,SAAS,UAAU;IACjB,OAAO,OAAO,CAAC,GAAG,CAAC,uBAAuB,IAAI,yBAAyB,CAAC;AAC1E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,GAAuB,EAAE,GAAW;IAC3E,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QACb,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IACD,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QACb,OAAO,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC;IACD,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;QAChB,OAAO,iBAAiB,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IACjD,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;QACf,OAAO,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,SAAS,CAAC,CAAC;IACxE,CAAC;IACD,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;QACf,OAAO,iBAAiB,EAAE,CAAC;IAC7B,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,kIAAkI,CACnI,CAAC;IACF,OAAO,CAAC,CAAC;AACX,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,GAAW;IACnC,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uBAAuB,GAAG,KAAK,CAAC,CAAC;QACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QACzF,OAAO,CAAC,CAAC;IACX,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,IAAI,GAAG,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,IAAI,MAAM,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;QAC5F,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,KAAK,CAAC,WAAW,IAAI,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,GAAW,EAAE,IAAY;IAChD,MAAM,QAAQ,GAAG,MAAM,uBAAuB,CAAC,GAAG,CAAC,CAAC;IACpD,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,IAAI,KAAK,CAAC,CAAC;QAChE,OAAO,CAAC,CAAC;IACX,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC;IAC1C,IAAI,KAAK,CAAC,OAAO;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;IACvE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;IAC7E,IAAI,KAAK,CAAC,WAAW;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,KAAK,CAAC,WAAW,IAAI,CAAC,CAAC;IACnF,IAAI,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kBAAkB,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC5E,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC3D,OAAO,CAAC,CAAC;AACX,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,MAAc,EAAE,GAAW;IAC1D,qEAAqE;IACrE,kEAAkE;IAClE,oEAAoE;IACpE,SAAS;IACT,IAAI,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,UAAU,EAAE,CAAC,CAAC;QACvD,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;YAC5D,IAAI,KAAK,EAAE,CAAC;gBACV,MAAM,MAAM,GAAG,MAAM,uBAAuB,CAAC;oBAC3C,IAAI,EAAE,MAAM;oBACZ,OAAO;iBACR,CAAC,CAAC;gBACH,IAAI,MAAM,EAAE,CAAC;oBACX,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC;oBACnD,OAAO,CAAC,CAAC;gBACX,CAAC;gBACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wCAAwC,KAAK,CAAC,MAAM,kBAAkB,CAAC,CAAC;YAC/F,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,yBAAyB,MAAM,sCAAsC,CAAC,CAAC;YAC9F,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,4DAA4D,UAAU,EAAE,+BAA+B,CACxG,CAAC;QACJ,CAAC;IACH,CAAC;IAED,0DAA0D;IAC1D,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC9C,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACjC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG;QACV,IAAI;oCACwB,MAAM;;;;IAItC,IAAI;;oDAE4C,MAAM;;;;;;;YAO9C,MAAM;CACjB,CAAC;IACA,MAAM,SAAS,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC5C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,SAAS,IAAI,CAAC,CAAC;IACjD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,SAAS,+BAA+B,CAAC,CAAC;IAC7E,OAAO,CAAC,CAAC;AACX,CAAC;AAED,kEAAkE;AAClE,SAAS,kBAAkB,CAAC,MAAc;IACxC,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IAChE,IAAI,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/C,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC,CAAC,wBAAwB;IAChE,OAAO,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACvC,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,KAAa,EAAE,KAAc;IACxD,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,UAAU,EAAE,CAAC,CAAC;IACvD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,2DAA2D,UAAU,EAAE,KAAK;YAC1E,4CAA4C,CAC/C,CAAC;QACF,OAAO,CAAC,CAAC;IACX,CAAC;IACD,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACnD,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,KAAK,QAAQ,MAAM,CAAC,YAAY,qBAAqB,CAAC,CAAC;QACjG,OAAO,CAAC,CAAC;IACX,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,IAAI,GAAG,GAAG,QAAQ,KAAK,CAAC,WAAW,IAAI,CAAC,CAAC;QACvE,IAAI,KAAK,CAAC,WAAW;YAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,KAAK,CAAC,WAAW,IAAI,CAAC,CAAC;QAC1E,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,OAAO,CAAC,MAAM,OAAO,MAAM,CAAC,YAAY,qBAAqB,CAAC,CAAC;IAChG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;IACnE,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QACvB,MAAM,IAAI,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,gBAAgB,CAAC;QACvD,OAAO,IAAI;aACR,WAAW,EAAE;aACb,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;aACrB,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC;aAC7B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,IAAI,gBAAgB,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,gBAAgB,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB;IACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kDAAkD,UAAU,EAAE,MAAM,CAAC,CAAC;IAC3F,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACzE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gFAAgF,CAAC,CAAC;IACvG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gFAAgF,CAAC,CAAC;IACvG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,0EAA0E,CAAC,CAAC;IACjG,OAAO,CAAC,CAAC;AACX,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * `forge spec …` subcommand: list / show / cancel / sync already-approved
3
+ * spec-driven-planning-mode output (`.forge/specs/<id>/`). `sync` is the one
4
+ * that needs a model: it re-reads the code and updates the documents.
5
+ *
6
+ * Mirrors `commands/checkpoint.ts`'s soft-prefix shape: no AI provider
7
+ * required, exits 0/1/2. Generation itself happens via `--spec "<task>"`
8
+ * (one-shot) or `/spec <task>` (REPL): see `options.ts`'s header
9
+ * comment on `ParsedSpecCommand` for why "approve" isn't a subcommand
10
+ * here.
11
+ */
12
+ import type { ParsedSpecCommand } from '../options.js';
13
+ export interface SpecCommandDeps {
14
+ /** Runs a read-only spec-mode agent on `task` and returns its final text and end reason. */
15
+ runSpecAgent?: (task: string) => Promise<{
16
+ finalText: string;
17
+ reason: string;
18
+ }>;
19
+ /** Asks a yes/no question; defaults to a terminal prompt (no when stdin is not a TTY). */
20
+ confirm?: (question: string) => Promise<boolean>;
21
+ }
22
+ export declare function handleSpecCommand(cmd: ParsedSpecCommand, cwd: string, deps?: SpecCommandDeps): Promise<number>;
23
+ //# sourceMappingURL=spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../src/commands/spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAmBH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAEvD,MAAM,WAAW,eAAe;IAC9B,4FAA4F;IAC5F,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChF,0FAA0F;IAC1F,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAClD;AAED,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,iBAAiB,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAmBxH"}
@@ -0,0 +1,147 @@
1
+ /**
2
+ * `forge spec …` subcommand: list / show / cancel / sync already-approved
3
+ * spec-driven-planning-mode output (`.forge/specs/<id>/`). `sync` is the one
4
+ * that needs a model: it re-reads the code and updates the documents.
5
+ *
6
+ * Mirrors `commands/checkpoint.ts`'s soft-prefix shape: no AI provider
7
+ * required, exits 0/1/2. Generation itself happens via `--spec "<task>"`
8
+ * (one-shot) or `/spec <task>` (REPL): see `options.ts`'s header
9
+ * comment on `ParsedSpecCommand` for why "approve" isn't a subcommand
10
+ * here.
11
+ */
12
+ import process from 'node:process';
13
+ import { readFile } from 'node:fs/promises';
14
+ import path from 'node:path';
15
+ import { createInterface } from 'node:readline/promises';
16
+ import { changeSize, convertToCheckboxes, keepDoneTasks, SpecStore, specDrift, splitSpecSections, syncSpecTask, } from '@ikarmic/forge-core';
17
+ export async function handleSpecCommand(cmd, cwd, deps = {}) {
18
+ const store = new SpecStore(cwd);
19
+ if (cmd.list) {
20
+ return listSpecs(store);
21
+ }
22
+ if (cmd.show) {
23
+ return showSpec(store, cmd.show.id);
24
+ }
25
+ if (cmd.cancel) {
26
+ return cancelSpec(store, cmd.cancel.id, cmd.cancel.yes);
27
+ }
28
+ if (cmd.sync) {
29
+ return syncSpec(store, cwd, cmd.sync.id, cmd.sync.yes, deps);
30
+ }
31
+ process.stderr.write('forge spec: expected one of list|show|cancel|sync. Generate a new spec with `forge --spec "<task>"` or `/spec <task>` in the REPL.\n');
32
+ return 2;
33
+ }
34
+ async function listSpecs(store) {
35
+ const all = await store.list();
36
+ if (all.length === 0) {
37
+ process.stdout.write('(no approved specs found: generate one with `forge --spec "<task>"` or `/spec <task>` in the REPL)\n');
38
+ return 0;
39
+ }
40
+ process.stdout.write('id task when\n');
41
+ process.stdout.write('────────────────────────────────────────────────────────────────────────\n');
42
+ for (const s of all) {
43
+ const id = s.id.length > 36 ? s.id.slice(0, 35) + '…' : s.id.padEnd(36);
44
+ const task = s.task.length > 30 ? s.task.slice(0, 29) + '…' : s.task.padEnd(30);
45
+ const when = s.approvedAt.replace('T', ' ').slice(0, 19);
46
+ process.stdout.write(`${id} ${task} ${when}\n`);
47
+ }
48
+ return 0;
49
+ }
50
+ async function showSpec(store, id) {
51
+ const summary = await store.get(id);
52
+ if (!summary) {
53
+ process.stderr.write(`forge spec: no spec with id "${id}"\n`);
54
+ return 2;
55
+ }
56
+ process.stdout.write(`Spec ${summary.id}\n`);
57
+ process.stdout.write(` task: ${summary.task}\n`);
58
+ process.stdout.write(` approved: ${summary.approvedAt}\n`);
59
+ process.stdout.write(` dir: ${summary.dir}\n\n`);
60
+ for (const file of ['requirements.md', 'design.md', 'tasks.md']) {
61
+ const content = await readFile(path.join(summary.dir, file), 'utf8');
62
+ process.stdout.write(`── ${file} ──\n${content}\n\n`);
63
+ }
64
+ return 0;
65
+ }
66
+ async function cancelSpec(store, id, yes) {
67
+ const summary = await store.get(id);
68
+ if (!summary) {
69
+ process.stderr.write(`forge spec: no spec with id "${id}"\n`);
70
+ return 2;
71
+ }
72
+ if (!yes) {
73
+ process.stderr.write(`About to permanently delete spec "${id}" (${summary.dir}).\n` +
74
+ 'Re-run with --yes to confirm. Refusing to delete without an explicit flag.\n');
75
+ return 2;
76
+ }
77
+ const removed = await store.delete(id);
78
+ process.stdout.write(removed ? `deleted spec ${id}\n` : `forge spec: failed to delete "${id}"\n`);
79
+ return removed ? 0 : 1;
80
+ }
81
+ async function askInTerminal(question) {
82
+ if (!process.stdin.isTTY)
83
+ return false;
84
+ const rl = createInterface({ input: process.stdin, output: process.stderr });
85
+ try {
86
+ return /^y(es)?$/i.test((await rl.question(`${question} [y/N] `)).trim());
87
+ }
88
+ finally {
89
+ rl.close();
90
+ }
91
+ }
92
+ /** Re-read the code and bring the spec's documents up to date; the old ones go to history/. */
93
+ async function syncSpec(store, cwd, id, yes, deps) {
94
+ const spec = await store.get(id);
95
+ const docs = spec ? await store.readDocs(id) : null;
96
+ if (!spec || !docs) {
97
+ process.stderr.write(`forge spec: no spec with id "${id}"\n`);
98
+ return 2;
99
+ }
100
+ if (!deps.runSpecAgent) {
101
+ process.stderr.write('forge spec sync: no model available\n');
102
+ return 2;
103
+ }
104
+ const confirm = deps.confirm ?? askInTerminal;
105
+ // Ask for --yes before spending on a model run whose result could not be written.
106
+ if (!yes && !deps.confirm && !process.stdin.isTTY) {
107
+ process.stderr.write('forge spec sync: not a terminal, so pass --yes to write the updated documents.\n');
108
+ return 2;
109
+ }
110
+ const drift = await specDrift(cwd, spec, docs);
111
+ process.stderr.write(`Spec ${id}: ${drift.changedFiles.length} file(s) changed since ${drift.since.slice(0, 10)}, ` +
112
+ `${drift.missingPaths.length} mentioned path(s) gone, ${drift.tasks.done}/${drift.tasks.total} tasks ticked.\n` +
113
+ 'Re-reading the code (read-only)…\n');
114
+ const result = await deps.runSpecAgent(syncSpecTask(spec, docs, drift));
115
+ if (result.reason !== 'spec' && result.reason !== 'completed') {
116
+ process.stderr.write(`forge spec sync: the run ended (${result.reason}); nothing was changed.\n`);
117
+ return 1;
118
+ }
119
+ let next;
120
+ try {
121
+ next = splitSpecSections(result.finalText);
122
+ }
123
+ catch (err) {
124
+ process.stderr.write(`forge spec sync: ${err.message}; nothing was changed.\n`);
125
+ return 1;
126
+ }
127
+ next = { ...next, tasks: keepDoneTasks(docs.tasks, convertToCheckboxes(next.tasks)) };
128
+ let any = false;
129
+ for (const file of ['requirements', 'design', 'tasks']) {
130
+ const { added, removed } = changeSize(docs[file], next[file]);
131
+ if (added || removed)
132
+ any = true;
133
+ process.stdout.write(` ${file}.md: ${added || removed ? `+${added} -${removed} lines` : 'unchanged'}\n`);
134
+ }
135
+ if (!any) {
136
+ process.stdout.write(`spec ${id} already matches the code\n`);
137
+ return 0;
138
+ }
139
+ if (!yes && !(await confirm(`Write the updated documents to ${spec.dir}?`))) {
140
+ process.stdout.write('not written\n');
141
+ return 1;
142
+ }
143
+ const updated = await store.update(id, next);
144
+ process.stdout.write(`updated spec ${id} (previous version in ${path.join(updated.dir, 'history')})\n`);
145
+ return 0;
146
+ }
147
+ //# sourceMappingURL=spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/commands/spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `forge watch`: runs a filesystem watcher that dispatches FileChanged
3
+ * hook events independent of any active Agent.run(). Runs until
4
+ * SIGINT (Ctrl+C). No agent loop involved.
5
+ *
6
+ * Loads hooks config exactly the way toAgentConfig does elsewhere
7
+ * (loadHooksConfig -> new HooksBus). trustedProjectHooks is never set
8
+ * to true here, same as every other CLI call site: project-level
9
+ * FileChanged hooks stay blocked by default.
10
+ */
11
+ import { type ModelConfig } from '@ikarmic/forge-core';
12
+ export declare function handleWatchCommand(cwd: string, resolveModel?: () => ModelConfig, watchOptions?: {
13
+ aiComments?: boolean;
14
+ }): Promise<number>;
15
+ //# sourceMappingURL=watch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,OAAO,EAUL,KAAK,WAAW,EACjB,MAAM,qBAAqB,CAAC;AAM7B,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,YAAY,CAAC,EAAE,MAAM,WAAW,EAChC,YAAY,GAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAO,GAC1C,OAAO,CAAC,MAAM,CAAC,CA4DjB"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * `forge watch`: runs a filesystem watcher that dispatches FileChanged
3
+ * hook events independent of any active Agent.run(). Runs until
4
+ * SIGINT (Ctrl+C). No agent loop involved.
5
+ *
6
+ * Loads hooks config exactly the way toAgentConfig does elsewhere
7
+ * (loadHooksConfig -> new HooksBus). trustedProjectHooks is never set
8
+ * to true here, same as every other CLI call site: project-level
9
+ * FileChanged hooks stay blocked by default.
10
+ */
11
+ import process from 'node:process';
12
+ import { createAiCommentHandler } from './ai-comments.js';
13
+ import { Agent, createAgentHookRunner, FileChangeCoalescer, HooksBus, loadHooksConfig, watchFilesystem, } from '@ikarmic/forge-core';
14
+ function hasAgentHooks(config) {
15
+ return Object.values(config).some((entries) => entries?.some((e) => e.hooks.some((h) => h.type === 'agent')));
16
+ }
17
+ export async function handleWatchCommand(cwd, resolveModel, watchOptions = {}) {
18
+ const { config, sources, warnings } = await loadHooksConfig(cwd);
19
+ for (const warning of warnings) {
20
+ process.stderr.write(`forge watch: warning: ${warning}\n`);
21
+ }
22
+ if (sources.length === 0) {
23
+ process.stdout.write('(no hooks configured: neither ~/.forge/settings.json nor .forge/settings.json exists; watching anyway, but nothing will run)\n');
24
+ }
25
+ // `type: 'agent'` hooks need a model. Resolve it only when one is configured, so a
26
+ // shell-only watch keeps working with no API key.
27
+ let agentRunner;
28
+ if (hasAgentHooks(config)) {
29
+ try {
30
+ if (!resolveModel)
31
+ throw new Error('no model resolver');
32
+ agentRunner = createAgentHookRunner({ model: resolveModel(), cwd });
33
+ }
34
+ catch (err) {
35
+ process.stderr.write(`forge watch: agent hooks disabled: ${err.message}
36
+ `);
37
+ }
38
+ }
39
+ const bus = new HooksBus(config, agentRunner ? { agentRunner } : {});
40
+ const coalescer = new FileChangeCoalescer((relPath, changeType) => {
41
+ void dispatchAndReport(bus, cwd, relPath, changeType);
42
+ });
43
+ const onAiComments = watchOptions.aiComments
44
+ ? createAiCommentHandler({
45
+ cwd,
46
+ run: async (task, mode) => {
47
+ if (!resolveModel)
48
+ throw new Error('no model configured');
49
+ const agent = new Agent({
50
+ model: resolveModel(),
51
+ cwd,
52
+ auto: true,
53
+ ...(mode === 'question' ? { planMode: true } : {}),
54
+ });
55
+ return (await agent.run({ task })).finalText;
56
+ },
57
+ })
58
+ : null;
59
+ const watcherHandle = watchFilesystem(cwd, (relPath, changeType) => {
60
+ coalescer.notify(relPath, changeType);
61
+ if (onAiComments && changeType !== 'deleted')
62
+ void onAiComments(relPath);
63
+ });
64
+ process.stdout.write(`forge watch: watching ${cwd}${watchOptions.aiComments ? ' for AI!/AI? comments' : ''} (Ctrl+C to stop)\n`);
65
+ return new Promise((resolve) => {
66
+ const shutdown = () => {
67
+ coalescer.dispose();
68
+ void watcherHandle.close().then(() => {
69
+ process.stdout.write('\nforge watch: stopped\n');
70
+ resolve(130);
71
+ });
72
+ };
73
+ process.on('SIGINT', shutdown);
74
+ });
75
+ }
76
+ async function dispatchAndReport(bus, cwd, relPath, changeType) {
77
+ const log = await bus.dispatch({ type: 'FileChanged', path: relPath, changeType, cwd });
78
+ const ranCount = log.results.length;
79
+ if (ranCount > 0) {
80
+ process.stdout.write(`[${changeType}] ${relPath} -> ${ranCount} hook${ranCount === 1 ? '' : 's'} run\n`);
81
+ }
82
+ }
83
+ //# sourceMappingURL=watch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watch.js","sourceRoot":"","sources":["../../src/commands/watch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `forge worktree …` CLI subcommand. v2.11 + v2.14.
3
+ *
4
+ * forge worktree list: show active worktrees
5
+ * forge worktree cleanup [--with-branches|--no-branches] [-f]
6
+ *: remove all (confirms)
7
+ * forge worktree cleanup --force: remove without confirm
8
+ * forge worktree prune: orphan worktrees only
9
+ * forge worktree sweep [--force]: remove orphans + delete
10
+ * their auto-branches
11
+ *
12
+ * v2.14: cleanup now also deletes the auto-created branches by
13
+ * default (pass `--no-branches` to keep them). The new `sweep`
14
+ * subcommand is the one-shot "I'm done with this repo" cleanup:
15
+ * orphans get their branches deleted too.
16
+ *
17
+ * Mirrors the soft-prefix pattern of the other CLI subcommands:
18
+ * doesn't need an AI provider.
19
+ */
20
+ import type { ParsedWorktreeCommand } from '../options.js';
21
+ export declare function handleWorktreeCommand(cmd: ParsedWorktreeCommand, cwd: string): Promise<number>;
22
+ //# sourceMappingURL=worktree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worktree.d.ts","sourceRoot":"","sources":["../../src/commands/worktree.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAE3D,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,qBAAqB,EAC1B,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC,CAmCjB"}