@ob1-sg/horizon 0.1.10 → 0.1.11

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 (153) hide show
  1. package/dist/cli.d.ts +3 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +43 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/config.d.ts +10 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +293 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/index.d.ts +4 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +629 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/lib/__tests__/attachment-downloader.test.d.ts +2 -0
  14. package/dist/lib/__tests__/attachment-downloader.test.d.ts.map +1 -0
  15. package/dist/lib/__tests__/attachment-downloader.test.js +163 -0
  16. package/dist/lib/__tests__/attachment-downloader.test.js.map +1 -0
  17. package/dist/lib/__tests__/cli-detection.test.d.ts +2 -0
  18. package/dist/lib/__tests__/cli-detection.test.d.ts.map +1 -0
  19. package/dist/lib/__tests__/cli-detection.test.js +119 -0
  20. package/dist/lib/__tests__/cli-detection.test.js.map +1 -0
  21. package/dist/lib/__tests__/config.test.d.ts +2 -0
  22. package/dist/lib/__tests__/config.test.d.ts.map +1 -0
  23. package/dist/lib/__tests__/config.test.js +291 -0
  24. package/dist/lib/__tests__/config.test.js.map +1 -0
  25. package/dist/lib/__tests__/gcp.test.d.ts +2 -0
  26. package/dist/lib/__tests__/gcp.test.d.ts.map +1 -0
  27. package/dist/lib/__tests__/gcp.test.js +104 -0
  28. package/dist/lib/__tests__/gcp.test.js.map +1 -0
  29. package/dist/lib/__tests__/git.test.d.ts +2 -0
  30. package/dist/lib/__tests__/git.test.d.ts.map +1 -0
  31. package/dist/lib/__tests__/git.test.js +62 -0
  32. package/dist/lib/__tests__/git.test.js.map +1 -0
  33. package/dist/lib/__tests__/linear-quick-check.test.d.ts +2 -0
  34. package/dist/lib/__tests__/linear-quick-check.test.d.ts.map +1 -0
  35. package/dist/lib/__tests__/linear-quick-check.test.js +152 -0
  36. package/dist/lib/__tests__/linear-quick-check.test.js.map +1 -0
  37. package/dist/lib/__tests__/loop-instance-name.test.d.ts +2 -0
  38. package/dist/lib/__tests__/loop-instance-name.test.d.ts.map +1 -0
  39. package/dist/lib/__tests__/loop-instance-name.test.js +90 -0
  40. package/dist/lib/__tests__/loop-instance-name.test.js.map +1 -0
  41. package/dist/lib/__tests__/output-logger.test.d.ts +2 -0
  42. package/dist/lib/__tests__/output-logger.test.d.ts.map +1 -0
  43. package/dist/lib/__tests__/output-logger.test.js +136 -0
  44. package/dist/lib/__tests__/output-logger.test.js.map +1 -0
  45. package/dist/lib/__tests__/prompts.test.d.ts +2 -0
  46. package/dist/lib/__tests__/prompts.test.d.ts.map +1 -0
  47. package/dist/lib/__tests__/prompts.test.js +70 -0
  48. package/dist/lib/__tests__/prompts.test.js.map +1 -0
  49. package/dist/lib/__tests__/provider.test.d.ts +2 -0
  50. package/dist/lib/__tests__/provider.test.d.ts.map +1 -0
  51. package/dist/lib/__tests__/provider.test.js +89 -0
  52. package/dist/lib/__tests__/provider.test.js.map +1 -0
  53. package/dist/lib/__tests__/rate-limit.test.d.ts +2 -0
  54. package/dist/lib/__tests__/rate-limit.test.d.ts.map +1 -0
  55. package/dist/lib/__tests__/rate-limit.test.js +275 -0
  56. package/dist/lib/__tests__/rate-limit.test.js.map +1 -0
  57. package/dist/lib/__tests__/readline.test.d.ts +2 -0
  58. package/dist/lib/__tests__/readline.test.d.ts.map +1 -0
  59. package/dist/lib/__tests__/readline.test.js +55 -0
  60. package/dist/lib/__tests__/readline.test.js.map +1 -0
  61. package/dist/lib/__tests__/stats-logger.test.d.ts +2 -0
  62. package/dist/lib/__tests__/stats-logger.test.d.ts.map +1 -0
  63. package/dist/lib/__tests__/stats-logger.test.js +297 -0
  64. package/dist/lib/__tests__/stats-logger.test.js.map +1 -0
  65. package/dist/lib/__tests__/update-checker.test.d.ts +2 -0
  66. package/dist/lib/__tests__/update-checker.test.d.ts.map +1 -0
  67. package/dist/lib/__tests__/update-checker.test.js +141 -0
  68. package/dist/lib/__tests__/update-checker.test.js.map +1 -0
  69. package/dist/lib/__tests__/version.test.d.ts +2 -0
  70. package/dist/lib/__tests__/version.test.d.ts.map +1 -0
  71. package/dist/lib/__tests__/version.test.js +51 -0
  72. package/dist/lib/__tests__/version.test.js.map +1 -0
  73. package/dist/lib/attachment-downloader.d.ts +26 -0
  74. package/dist/lib/attachment-downloader.d.ts.map +1 -0
  75. package/dist/lib/attachment-downloader.js +259 -0
  76. package/dist/lib/attachment-downloader.js.map +1 -0
  77. package/dist/lib/claude.d.ts +6 -0
  78. package/dist/lib/claude.d.ts.map +1 -0
  79. package/dist/lib/claude.js +358 -0
  80. package/dist/lib/claude.js.map +1 -0
  81. package/dist/lib/cli-detection.d.ts +25 -0
  82. package/dist/lib/cli-detection.d.ts.map +1 -0
  83. package/dist/lib/cli-detection.js +53 -0
  84. package/dist/lib/cli-detection.js.map +1 -0
  85. package/dist/lib/codex.d.ts +4 -0
  86. package/dist/lib/codex.d.ts.map +1 -0
  87. package/dist/lib/codex.js +285 -0
  88. package/dist/lib/codex.js.map +1 -0
  89. package/dist/lib/gcp.d.ts +21 -0
  90. package/dist/lib/gcp.d.ts.map +1 -0
  91. package/dist/lib/gcp.js +96 -0
  92. package/dist/lib/gcp.js.map +1 -0
  93. package/dist/lib/git.d.ts +3 -0
  94. package/dist/lib/git.d.ts.map +1 -0
  95. package/dist/lib/git.js +24 -0
  96. package/dist/lib/git.js.map +1 -0
  97. package/dist/lib/init-project.d.ts +13 -0
  98. package/dist/lib/init-project.d.ts.map +1 -0
  99. package/dist/lib/init-project.js +420 -0
  100. package/dist/lib/init-project.js.map +1 -0
  101. package/dist/lib/linear-api.d.ts +32 -0
  102. package/dist/lib/linear-api.d.ts.map +1 -0
  103. package/dist/lib/linear-api.js +267 -0
  104. package/dist/lib/linear-api.js.map +1 -0
  105. package/dist/lib/linear-quick-check.d.ts +13 -0
  106. package/dist/lib/linear-quick-check.d.ts.map +1 -0
  107. package/dist/lib/linear-quick-check.js +61 -0
  108. package/dist/lib/linear-quick-check.js.map +1 -0
  109. package/dist/lib/loop-instance-name.d.ts +29 -0
  110. package/dist/lib/loop-instance-name.d.ts.map +1 -0
  111. package/dist/lib/loop-instance-name.js +105 -0
  112. package/dist/lib/loop-instance-name.js.map +1 -0
  113. package/dist/lib/output-logger.d.ts +23 -0
  114. package/dist/lib/output-logger.d.ts.map +1 -0
  115. package/dist/lib/output-logger.js +104 -0
  116. package/dist/lib/output-logger.js.map +1 -0
  117. package/dist/lib/prompts.d.ts +17 -0
  118. package/dist/lib/prompts.d.ts.map +1 -0
  119. package/dist/lib/prompts.js +65 -0
  120. package/dist/lib/prompts.js.map +1 -0
  121. package/dist/lib/provider.d.ts +32 -0
  122. package/dist/lib/provider.d.ts.map +1 -0
  123. package/dist/lib/provider.js +27 -0
  124. package/dist/lib/provider.js.map +1 -0
  125. package/dist/lib/rate-limit.d.ts +14 -0
  126. package/dist/lib/rate-limit.d.ts.map +1 -0
  127. package/dist/lib/rate-limit.js +154 -0
  128. package/dist/lib/rate-limit.js.map +1 -0
  129. package/dist/lib/readline.d.ts +4 -0
  130. package/dist/lib/readline.d.ts.map +1 -0
  131. package/dist/lib/readline.js +39 -0
  132. package/dist/lib/readline.js.map +1 -0
  133. package/dist/lib/setup.d.ts +123 -0
  134. package/dist/lib/setup.d.ts.map +1 -0
  135. package/dist/lib/setup.js +492 -0
  136. package/dist/lib/setup.js.map +1 -0
  137. package/dist/lib/stats-logger.d.ts +92 -0
  138. package/dist/lib/stats-logger.d.ts.map +1 -0
  139. package/dist/lib/stats-logger.js +258 -0
  140. package/dist/lib/stats-logger.js.map +1 -0
  141. package/dist/lib/update-checker.d.ts +17 -0
  142. package/dist/lib/update-checker.d.ts.map +1 -0
  143. package/dist/lib/update-checker.js +140 -0
  144. package/dist/lib/update-checker.js.map +1 -0
  145. package/dist/lib/version.d.ts +10 -0
  146. package/dist/lib/version.d.ts.map +1 -0
  147. package/dist/lib/version.js +37 -0
  148. package/dist/lib/version.js.map +1 -0
  149. package/dist/types.d.ts +92 -0
  150. package/dist/types.d.ts.map +1 -0
  151. package/dist/types.js +3 -0
  152. package/dist/types.js.map +1 -0
  153. package/package.json +1 -1
@@ -0,0 +1,492 @@
1
+ /**
2
+ * Shared setup module for Horizon configuration.
3
+ * Used by both `horizon` (main loop) and `horizon config` commands.
4
+ */
5
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync, } from 'fs';
6
+ import { join, dirname } from 'path';
7
+ import { fileURLToPath } from 'url';
8
+ import { createInterface } from 'readline';
9
+ import { getRepoRoot } from '../config.js';
10
+ import { createLinearClient, validateApiKey, getTeamByKeyOrId, checkHorizonStatusesExist, ensureHorizonStatuses, } from './linear-api.js';
11
+ import { isClaudeCliInstalled, isCodexCliInstalled, hasAnyCli } from './cli-detection.js';
12
+ // Get the package directory (where Horizon is installed)
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = dirname(__filename);
15
+ const PACKAGE_ROOT = join(__dirname, '../..');
16
+ // ════════════════════════════════════════════════════════════════════════════
17
+ // Directory Setup
18
+ // ════════════════════════════════════════════════════════════════════════════
19
+ /**
20
+ * Ensures .horizon/ directory exists.
21
+ * Returns the path to the directory.
22
+ */
23
+ export function ensureHorizonDir() {
24
+ const horizonDir = join(getRepoRoot(), '.horizon');
25
+ if (!existsSync(horizonDir)) {
26
+ mkdirSync(horizonDir, { recursive: true });
27
+ }
28
+ return horizonDir;
29
+ }
30
+ /**
31
+ * Ensures horizon-docs/ directory exists with README.
32
+ */
33
+ export function ensureHorizonDocsDir() {
34
+ const docsDir = join(getRepoRoot(), 'horizon-docs');
35
+ if (!existsSync(docsDir)) {
36
+ mkdirSync(docsDir, { recursive: true });
37
+ }
38
+ // Create README if it doesn't exist
39
+ const readmePath = join(docsDir, 'README.md');
40
+ if (!existsSync(readmePath)) {
41
+ const readme = `# Horizon Documentation
42
+
43
+ This directory contains documentation automatically generated by [Horizon](https://www.npmjs.com/package/@ob1-sg/horizon), an autonomous product development system.
44
+
45
+ ## Contents
46
+
47
+ - \`research/\` - Research documents for tickets
48
+ - \`plans/\` - Implementation plans
49
+ - \`specifications/\` - Technical specifications
50
+ - \`validation/\` - Validation reports
51
+ - \`oneshot/\` - Quick implementation notes
52
+ - \`shared/\` - Shared context between sessions
53
+
54
+ ## Note for Developers
55
+
56
+ These files are **intended to be committed** to version control. They provide context and history for AI-assisted development work.
57
+
58
+ While the content is AI-generated, it documents real decisions, research, and implementation details that are valuable for understanding the codebase evolution.
59
+
60
+ Learn more: https://www.npmjs.com/package/@ob1-sg/horizon
61
+ `;
62
+ writeFileSync(readmePath, readme);
63
+ }
64
+ }
65
+ /**
66
+ * Ensures .horizon/ is in .gitignore.
67
+ */
68
+ export function ensureGitignore() {
69
+ const gitignorePath = join(getRepoRoot(), '.gitignore');
70
+ const entry = '.horizon/';
71
+ let content = '';
72
+ if (existsSync(gitignorePath)) {
73
+ content = readFileSync(gitignorePath, 'utf-8');
74
+ }
75
+ // Check if already ignored
76
+ const lines = content.split('\n');
77
+ const alreadyIgnored = lines.some((line) => line.trim() === entry || line.trim() === '.horizon');
78
+ if (alreadyIgnored) {
79
+ return;
80
+ }
81
+ // Append to .gitignore
82
+ const newContent = content.endsWith('\n') || content === ''
83
+ ? content + `# Horizon runtime data\n${entry}\n`
84
+ : content + `\n# Horizon runtime data\n${entry}\n`;
85
+ writeFileSync(gitignorePath, newContent, 'utf-8');
86
+ }
87
+ // ════════════════════════════════════════════════════════════════════════════
88
+ // Config Loading/Saving
89
+ // ════════════════════════════════════════════════════════════════════════════
90
+ /**
91
+ * Loads existing configuration from .horizon/env file.
92
+ */
93
+ export function loadExistingConfig() {
94
+ const envPath = join(getRepoRoot(), '.horizon', 'env');
95
+ if (!existsSync(envPath)) {
96
+ return {};
97
+ }
98
+ const content = readFileSync(envPath, 'utf-8');
99
+ const getValue = (key) => {
100
+ const match = content.match(new RegExp(`^${key}=(.+)$`, 'm'));
101
+ return match ? match[1].trim() : undefined;
102
+ };
103
+ const config = {};
104
+ const apiKey = getValue('LINEAR_API_KEY');
105
+ if (apiKey)
106
+ config.linearApiKey = apiKey;
107
+ const teamKey = getValue('LINEAR_TEAM_KEY');
108
+ if (teamKey)
109
+ config.linearTeamKey = teamKey;
110
+ const provider = getValue('HORIZON_PROVIDER');
111
+ if (provider === 'claude' || provider === 'codex') {
112
+ config.provider = provider;
113
+ }
114
+ const claudeModel = getValue('HORIZON_CLAUDE_MODEL');
115
+ if (claudeModel === 'opus' || claudeModel === 'sonnet' || claudeModel === 'haiku') {
116
+ config.claudeModel = claudeModel;
117
+ }
118
+ const codexModel = getValue('CODEX_MODEL');
119
+ if (codexModel)
120
+ config.codexModel = codexModel;
121
+ const codexEffort = getValue('CODEX_REASONING_EFFORT');
122
+ if (codexEffort === 'low' || codexEffort === 'medium' || codexEffort === 'high' || codexEffort === 'extra_high') {
123
+ config.codexReasoningEffort = codexEffort;
124
+ }
125
+ const maxIterations = getValue('HORIZON_MAX_ITERATIONS');
126
+ if (maxIterations !== undefined) {
127
+ const parsed = parseInt(maxIterations, 10);
128
+ if (!isNaN(parsed))
129
+ config.maxIterations = parsed;
130
+ }
131
+ const mergeMode = getValue('HORIZON_MERGE_MODE');
132
+ if (mergeMode === 'auto' || mergeMode === 'merge' || mergeMode === 'pr') {
133
+ config.mergeMode = mergeMode;
134
+ }
135
+ return config;
136
+ }
137
+ /**
138
+ * Saves configuration to .horizon/env file.
139
+ */
140
+ export function saveEnvConfig(config) {
141
+ const envPath = join(ensureHorizonDir(), 'env');
142
+ const lines = [
143
+ '# Horizon Configuration',
144
+ '# Generated by horizon config',
145
+ '',
146
+ '# Linear (required)',
147
+ ];
148
+ if (config.linearApiKey) {
149
+ lines.push(`LINEAR_API_KEY=${config.linearApiKey}`);
150
+ }
151
+ if (config.linearTeamKey) {
152
+ lines.push(`LINEAR_TEAM_KEY=${config.linearTeamKey}`);
153
+ }
154
+ lines.push('');
155
+ lines.push('# Provider: "claude" or "codex"');
156
+ lines.push(`HORIZON_PROVIDER=${config.provider || 'claude'}`);
157
+ lines.push('');
158
+ lines.push('# Claude options');
159
+ lines.push(`HORIZON_CLAUDE_MODEL=${config.claudeModel || 'opus'}`);
160
+ lines.push('');
161
+ lines.push('# Codex options');
162
+ lines.push(`CODEX_MODEL=${config.codexModel || 'gpt-5.2'}`);
163
+ lines.push(`CODEX_REASONING_EFFORT=${config.codexReasoningEffort || 'high'}`);
164
+ lines.push('');
165
+ lines.push('# Loop options (0 = unlimited)');
166
+ lines.push(`HORIZON_MAX_ITERATIONS=${config.maxIterations ?? 0}`);
167
+ lines.push('');
168
+ lines.push('# Merge mode: "auto" (agent decides), "merge" (direct to main), or "pr" (create pull request)');
169
+ lines.push(`HORIZON_MERGE_MODE=${config.mergeMode || 'auto'}`);
170
+ lines.push(''); // Trailing newline
171
+ writeFileSync(envPath, lines.join('\n'), 'utf-8');
172
+ }
173
+ /**
174
+ * Saves MCP configuration with Linear API key.
175
+ */
176
+ export function saveMcpConfig(apiKey) {
177
+ const mcpPath = join(ensureHorizonDir(), 'mcp.json');
178
+ let config = { mcpServers: {} };
179
+ // Read existing config if it exists
180
+ if (existsSync(mcpPath)) {
181
+ try {
182
+ const existing = readFileSync(mcpPath, 'utf-8');
183
+ config = JSON.parse(existing);
184
+ if (!config.mcpServers) {
185
+ config.mcpServers = {};
186
+ }
187
+ }
188
+ catch {
189
+ config = { mcpServers: {} };
190
+ }
191
+ }
192
+ // Add or update Linear MCP server
193
+ config.mcpServers.linear = {
194
+ type: 'http',
195
+ url: 'https://mcp.linear.app/mcp',
196
+ headers: {
197
+ Authorization: `Bearer ${apiKey}`,
198
+ },
199
+ };
200
+ writeFileSync(mcpPath, JSON.stringify(config, null, 2) + '\n', 'utf-8');
201
+ }
202
+ /**
203
+ * Saves Codex MCP configuration to global ~/.codex/config.toml.
204
+ * Uses bearer_token_env_var so the actual API key stays in .horizon/env.
205
+ */
206
+ export function saveCodexMcpConfig() {
207
+ const homeDir = process.env.HOME || process.env.USERPROFILE || '';
208
+ const codexDir = join(homeDir, '.codex');
209
+ const configPath = join(codexDir, 'config.toml');
210
+ // Ensure ~/.codex directory exists
211
+ if (!existsSync(codexDir)) {
212
+ mkdirSync(codexDir, { recursive: true });
213
+ }
214
+ // Read existing config if it exists
215
+ let existingContent = '';
216
+ if (existsSync(configPath)) {
217
+ existingContent = readFileSync(configPath, 'utf-8');
218
+ }
219
+ // Check if [mcp_servers.linear] section already exists
220
+ if (existingContent.includes('[mcp_servers.linear]')) {
221
+ // Update the existing section - find and replace
222
+ const linearSectionRegex = /\[mcp_servers\.linear\][^\[]*(?=\[|$)/s;
223
+ const newSection = `[mcp_servers.linear]
224
+ url = "https://mcp.linear.app/mcp"
225
+ bearer_token_env_var = "LINEAR_API_KEY"
226
+
227
+ `;
228
+ existingContent = existingContent.replace(linearSectionRegex, newSection);
229
+ }
230
+ else {
231
+ // Append the new section
232
+ const newSection = `
233
+ [mcp_servers.linear]
234
+ url = "https://mcp.linear.app/mcp"
235
+ bearer_token_env_var = "LINEAR_API_KEY"
236
+ `;
237
+ existingContent = existingContent.trimEnd() + '\n' + newSection;
238
+ }
239
+ writeFileSync(configPath, existingContent, 'utf-8');
240
+ }
241
+ // ════════════════════════════════════════════════════════════════════════════
242
+ // CLI Detection
243
+ // ════════════════════════════════════════════════════════════════════════════
244
+ /**
245
+ * Checks which CLIs are available and displays results one-by-one.
246
+ * Provides real-time feedback as each check completes.
247
+ * Returns availability, or undefined if neither is installed.
248
+ */
249
+ export function checkAndDisplayCliAvailability() {
250
+ console.log('Detecting CLIs...');
251
+ // Check Claude Code first, display immediately
252
+ process.stdout.write(' Claude Code: checking...');
253
+ const claudeAvailable = isClaudeCliInstalled();
254
+ const claudeStatus = claudeAvailable ? '✓ installed' : '✗ not found';
255
+ process.stdout.write(`\r Claude Code: ${claudeStatus} \n`);
256
+ // Check Codex, display immediately
257
+ process.stdout.write(' Codex CLI: checking...');
258
+ const codexAvailable = isCodexCliInstalled();
259
+ const codexStatus = codexAvailable ? '✓ installed' : '✗ not found';
260
+ process.stdout.write(`\r Codex CLI: ${codexStatus} \n`);
261
+ console.log('');
262
+ const availability = {
263
+ claude: claudeAvailable,
264
+ codex: codexAvailable,
265
+ };
266
+ if (!hasAnyCli(availability)) {
267
+ console.log('❌ Error: No coding CLI found');
268
+ console.log('');
269
+ console.log(' Horizon requires at least one of the following:');
270
+ console.log('');
271
+ console.log(' Claude Code CLI:');
272
+ console.log(' npm install -g @anthropic-ai/claude-code');
273
+ console.log('');
274
+ console.log(' Codex CLI:');
275
+ console.log(' npm install -g @openai/codex');
276
+ console.log('');
277
+ return undefined;
278
+ }
279
+ return availability;
280
+ }
281
+ /**
282
+ * Auto-selects provider based on CLI availability.
283
+ * Prefers Claude if both are available.
284
+ */
285
+ export function autoSelectProvider(availability) {
286
+ if (availability.claude)
287
+ return 'claude';
288
+ return 'codex';
289
+ }
290
+ // ════════════════════════════════════════════════════════════════════════════
291
+ // Linear Setup
292
+ // ════════════════════════════════════════════════════════════════════════════
293
+ /**
294
+ * Validates a Linear API key.
295
+ */
296
+ export async function validateLinearKey(apiKey) {
297
+ const client = createLinearClient(apiKey);
298
+ return await validateApiKey(client);
299
+ }
300
+ /**
301
+ * Fetches available teams from Linear.
302
+ */
303
+ export async function fetchLinearTeams(apiKey) {
304
+ const client = createLinearClient(apiKey);
305
+ const teamsResult = await client.teams();
306
+ return teamsResult.nodes.map((t) => ({
307
+ id: t.id,
308
+ key: t.key,
309
+ name: t.name,
310
+ }));
311
+ }
312
+ /**
313
+ * Checks if Linear ∞ statuses exist.
314
+ */
315
+ export async function checkLinearStatuses(apiKey, teamKey) {
316
+ const client = createLinearClient(apiKey);
317
+ const team = await getTeamByKeyOrId(client, teamKey);
318
+ if (!team)
319
+ return false;
320
+ return await checkHorizonStatusesExist(client, team.id);
321
+ }
322
+ /**
323
+ * Creates Linear ∞ statuses.
324
+ * Returns result with created/existing/errors counts.
325
+ */
326
+ export async function createLinearStatuses(apiKey, teamKey) {
327
+ const client = createLinearClient(apiKey);
328
+ const team = await getTeamByKeyOrId(client, teamKey);
329
+ if (!team) {
330
+ return {
331
+ success: false,
332
+ created: [],
333
+ existing: [],
334
+ errors: [`Team "${teamKey}" not found`],
335
+ };
336
+ }
337
+ return await ensureHorizonStatuses(client, team.id);
338
+ }
339
+ // ════════════════════════════════════════════════════════════════════════════
340
+ // File Operations
341
+ // ════════════════════════════════════════════════════════════════════════════
342
+ /**
343
+ * Copies prompts from package to .horizon/prompts/.
344
+ * Assembles prompts with merge fragment based on current config.
345
+ */
346
+ export function copyPromptsToProject() {
347
+ const sourceDir = join(PACKAGE_ROOT, 'prompts');
348
+ const fragmentsDir = join(sourceDir, 'fragments');
349
+ const destDir = join(ensureHorizonDir(), 'prompts');
350
+ if (!existsSync(destDir)) {
351
+ mkdirSync(destDir, { recursive: true });
352
+ }
353
+ if (!existsSync(sourceDir)) {
354
+ console.log('Warning: Prompts directory not found in package.');
355
+ return;
356
+ }
357
+ // Load current config to determine merge mode
358
+ const config = loadExistingConfig();
359
+ const mergeMode = config.mergeMode || 'auto';
360
+ const provider = config.provider || 'claude';
361
+ // Load the appropriate merge fragment
362
+ const fragmentName = mergeMode === 'auto'
363
+ ? 'merge-auto.md'
364
+ : mergeMode === 'pr'
365
+ ? 'merge-pr.md'
366
+ : 'merge-direct.md';
367
+ const fragmentPath = join(fragmentsDir, fragmentName);
368
+ let mergeFragment = '';
369
+ if (existsSync(fragmentPath)) {
370
+ mergeFragment = readFileSync(fragmentPath, 'utf-8');
371
+ // Substitute provider link in fragment
372
+ const providerLink = provider === 'codex'
373
+ ? '[Codex](https://openai.com/codex)'
374
+ : '[Claude Code](https://claude.ai/claude-code)';
375
+ mergeFragment = mergeFragment.replace(/\{\{PROVIDER_LINK\}\}/g, providerLink);
376
+ }
377
+ const files = readdirSync(sourceDir).filter((f) => f.endsWith('.md'));
378
+ let copied = 0;
379
+ for (const file of files) {
380
+ let content = readFileSync(join(sourceDir, file), 'utf-8');
381
+ // For worker prompts, substitute merge instructions and stage-specific placeholders
382
+ if (file === 'agent2-worker-oneshot.md') {
383
+ content = content.replace('{{MERGE_INSTRUCTIONS}}', mergeFragment
384
+ .replace(/\{\{STAGE\}\}/g, 'oneshot')
385
+ .replace(/\{\{WORKFLOW\}\}/g, 'oneshot')
386
+ .replace(/\{\{ARTIFACT_DIR\}\}/g, 'oneshot'));
387
+ }
388
+ else if (file === 'agent2-worker-validate.md') {
389
+ content = content.replace('{{MERGE_INSTRUCTIONS}}', mergeFragment
390
+ .replace(/\{\{STAGE\}\}/g, 'validate')
391
+ .replace(/\{\{WORKFLOW\}\}/g, 'staged')
392
+ .replace(/\{\{ARTIFACT_DIR\}\}/g, 'validation'));
393
+ }
394
+ writeFileSync(join(destDir, file), content);
395
+ copied++;
396
+ }
397
+ console.log(` Prompts synced (${copied} files, merge mode: ${mergeMode})`);
398
+ }
399
+ // ════════════════════════════════════════════════════════════════════════════
400
+ // Prompt Helpers
401
+ // ════════════════════════════════════════════════════════════════════════════
402
+ /**
403
+ * Creates a readline interface for prompting.
404
+ */
405
+ export function createPromptInterface() {
406
+ return createInterface({ input: process.stdin, output: process.stdout });
407
+ }
408
+ /**
409
+ * Prompts for input with optional default value.
410
+ */
411
+ export async function promptWithDefault(rl, question, defaultValue) {
412
+ return new Promise((resolve) => {
413
+ const displayDefault = defaultValue ? ` [${defaultValue}]` : '';
414
+ rl.question(`${question}${displayDefault}: `, (answer) => {
415
+ resolve(answer.trim() || defaultValue || '');
416
+ });
417
+ });
418
+ }
419
+ /**
420
+ * Prompts for a secret value (doesn't show default).
421
+ */
422
+ export async function promptSecret(rl, question) {
423
+ return new Promise((resolve) => {
424
+ rl.question(`${question}: `, (answer) => {
425
+ resolve(answer.trim());
426
+ });
427
+ });
428
+ }
429
+ /**
430
+ * Prompts for yes/no confirmation.
431
+ */
432
+ export async function promptConfirm(rl, question, defaultYes = true) {
433
+ return new Promise((resolve) => {
434
+ const hint = defaultYes ? '[Y/n]' : '[y/N]';
435
+ rl.question(`${question} ${hint}: `, (answer) => {
436
+ const trimmed = answer.trim().toLowerCase();
437
+ if (trimmed === '') {
438
+ resolve(defaultYes);
439
+ }
440
+ else {
441
+ resolve(trimmed === 'y' || trimmed === 'yes');
442
+ }
443
+ });
444
+ });
445
+ }
446
+ /**
447
+ * Prompts user to select from a numbered list.
448
+ * Shows options as numbered list and accepts number input.
449
+ * Returns the selected option's value.
450
+ */
451
+ export async function promptSelect(rl, options, defaultIndex = 0) {
452
+ return new Promise((resolve) => {
453
+ // Display numbered options
454
+ options.forEach((opt, i) => {
455
+ const desc = opt.description ? ` - ${opt.description}` : '';
456
+ console.log(` ${i + 1}. ${opt.label}${desc}`);
457
+ });
458
+ console.log('');
459
+ rl.question(`Choice [default=${defaultIndex + 1}]: `, (answer) => {
460
+ const trimmed = answer.trim();
461
+ // Empty input = use default
462
+ if (trimmed === '') {
463
+ resolve(options[defaultIndex].value);
464
+ return;
465
+ }
466
+ // Parse number
467
+ const num = parseInt(trimmed, 10);
468
+ if (!isNaN(num) && num >= 1 && num <= options.length) {
469
+ resolve(options[num - 1].value);
470
+ return;
471
+ }
472
+ // Invalid input, use default
473
+ console.log(`Invalid choice, using default (${defaultIndex + 1})`);
474
+ resolve(options[defaultIndex].value);
475
+ });
476
+ });
477
+ }
478
+ /**
479
+ * Masks an API key for display (shows last 4 chars).
480
+ */
481
+ export function maskApiKey(apiKey) {
482
+ if (apiKey.length <= 4)
483
+ return '****';
484
+ return '****' + apiKey.slice(-4);
485
+ }
486
+ // ════════════════════════════════════════════════════════════════════════════
487
+ // Codex MCP Check
488
+ // ════════════════════════════════════════════════════════════════════════════
489
+ export { checkCodexLinearMcpConfigured as checkCodexLinearMcp } from './codex.js';
490
+ // Re-export for convenience
491
+ export { HORIZON_STATUS_PREFIX } from './linear-api.js';
492
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/lib/setup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Stats for a single agent run
3
+ */
4
+ export interface AgentStats {
5
+ agentNumber: number;
6
+ agentName: string;
7
+ provider: string;
8
+ model: string;
9
+ tokens: {
10
+ input: number;
11
+ output: number;
12
+ cached: number;
13
+ };
14
+ cost: number;
15
+ costEstimated: boolean;
16
+ maxContextWindowPercent: number;
17
+ compactionCount: number;
18
+ durationSeconds: number;
19
+ exitCode: number;
20
+ rateLimited: boolean;
21
+ completedAt: string;
22
+ }
23
+ /**
24
+ * Stats for a single loop iteration
25
+ */
26
+ export interface LoopStats {
27
+ loopNumber: number;
28
+ podName: string;
29
+ startedAt: string;
30
+ completedAt?: string;
31
+ agents: AgentStats[];
32
+ totals: {
33
+ tokens: {
34
+ input: number;
35
+ output: number;
36
+ cached: number;
37
+ };
38
+ cost: number;
39
+ costEstimated: boolean;
40
+ durationSeconds: number;
41
+ };
42
+ }
43
+ /**
44
+ * Overall stats file structure
45
+ */
46
+ export interface PodStats {
47
+ podName: string;
48
+ startedAt: string;
49
+ updatedAt: string;
50
+ loops: LoopStats[];
51
+ grandTotals: {
52
+ loopCount: number;
53
+ tokens: {
54
+ input: number;
55
+ output: number;
56
+ cached: number;
57
+ };
58
+ cost: number;
59
+ costEstimated: boolean;
60
+ durationSeconds: number;
61
+ };
62
+ }
63
+ /**
64
+ * Initializes stats tracking for a new loop iteration
65
+ * Should be called at the start of each loop
66
+ * @param podName - The pod name (e.g., "calm-pegasus")
67
+ * @param loopNumber - The loop iteration number (0, 1, 2, ...)
68
+ */
69
+ export declare function initLoopStats(podName: string, loopNumber: number): void;
70
+ /**
71
+ * Logs stats for a completed agent run
72
+ * Should be called after each agent finishes
73
+ */
74
+ export declare function logAgentStats(agentNumber: number, provider: string, model: string, result: {
75
+ tokenUsage: {
76
+ input: number;
77
+ output: number;
78
+ cached: number;
79
+ };
80
+ cost: number;
81
+ costEstimated: boolean;
82
+ duration: number;
83
+ exitCode: number;
84
+ rateLimited: boolean;
85
+ output: string;
86
+ }): Promise<void>;
87
+ /**
88
+ * Marks the current loop as completed
89
+ * Should be called at the end of each loop
90
+ */
91
+ export declare function finalizeLoopStats(): Promise<void>;
92
+ //# sourceMappingURL=stats-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats-logger.d.ts","sourceRoot":"","sources":["../../src/lib/stats-logger.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,OAAO,CAAC;IACvB,uBAAuB,EAAE,MAAM,CAAC;IAChC,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,MAAM,EAAE;QACN,MAAM,EAAE;YACN,KAAK,EAAE,MAAM,CAAC;YACd,MAAM,EAAE,MAAM,CAAC;YACf,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;QACF,IAAI,EAAE,MAAM,CAAC;QACb,aAAa,EAAE,OAAO,CAAC;QACvB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,WAAW,EAAE;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE;YACN,KAAK,EAAE,MAAM,CAAC;YACd,MAAM,EAAE,MAAM,CAAC;YACf,MAAM,EAAE,MAAM,CAAC;SAChB,CAAC;QACF,IAAI,EAAE,MAAM,CAAC;QACb,aAAa,EAAE,OAAO,CAAC;QACvB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;CACH;AAqFD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAIvE;AAuFD;;;GAGG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE;IACN,UAAU,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB,GACA,OAAO,CAAC,IAAI,CAAC,CA2Cf;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAWvD"}