opencastle 0.17.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/run.d.ts CHANGED
@@ -2,5 +2,5 @@ import type { CliContext } from './types.js';
2
2
  /**
3
3
  * CLI entry point for the `run` command.
4
4
  */
5
- export default function run({ args }: CliContext): Promise<void>;
5
+ export default function run({ args, pkgRoot }: CliContext): Promise<void>;
6
6
  //# sourceMappingURL=run.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,YAAY,CAAA;AAsJxD;;GAEG;AACH,wBAA8B,GAAG,CAAC,EAAE,IAAI,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAqNrE"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,YAAY,CAAA;AAsJxD;;GAEG;AACH,wBAA8B,GAAG,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAoO9E"}
package/dist/cli/run.js CHANGED
@@ -152,7 +152,7 @@ function printConvoyResult(result) {
152
152
  /**
153
153
  * CLI entry point for the `run` command.
154
154
  */
155
- export default async function run({ args }) {
155
+ export default async function run({ args, pkgRoot }) {
156
156
  const opts = parseArgs(args);
157
157
  if (opts.help) {
158
158
  console.log(HELP);
@@ -330,6 +330,18 @@ export default async function run({ args }) {
330
330
  console.log(` Branch: ${spec.branch}`);
331
331
  if (spec.gates?.length)
332
332
  console.log(` Gates: ${spec.gates.length} validation commands`);
333
+ const { startDashboardServer } = await import('./dashboard.js');
334
+ let dashboardResult = null;
335
+ try {
336
+ dashboardResult = await startDashboardServer({
337
+ pkgRoot,
338
+ openBrowser: true,
339
+ convoyId: 'active',
340
+ });
341
+ }
342
+ catch {
343
+ // Dashboard failure must not block convoy
344
+ }
333
345
  const engine = createConvoyEngine({
334
346
  spec,
335
347
  specYaml: specText,
@@ -338,6 +350,9 @@ export default async function run({ args }) {
338
350
  });
339
351
  const result = await engine.run();
340
352
  printConvoyResult(result);
353
+ if (dashboardResult) {
354
+ dashboardResult.server.close();
355
+ }
341
356
  process.exit(result.status !== 'done' ? 1 : 0);
342
357
  }
343
358
  // ── Legacy executor path ──────────────────────────────────────
@@ -1 +1 @@
1
- {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/cli/run.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencastle",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "type": "module",
5
5
  "description": "Multi-agent orchestration framework for AI coding assistants",
6
6
  "bin": {
@@ -9,6 +9,7 @@ import { createEventEmitter, type ConvoyEventEmitter } from './events.js'
9
9
  import { createWorktreeManager, type WorktreeManager } from './worktree.js'
10
10
  import { createMergeQueue, type MergeQueue } from './merge.js'
11
11
  import { createHealthMonitor } from './health.js'
12
+ import { exportConvoyToNdjson } from './export.js'
12
13
  import type { TaskRecord, ConvoyStatus } from './types.js'
13
14
  import { buildPhases, formatDuration } from '../run/executor.js'
14
15
  import { parseTimeout } from '../run/schema.js'
@@ -438,6 +439,7 @@ export function createConvoyEngine(options: ConvoyEngineOptions): ConvoyEngine {
438
439
  const wtManager = options._worktreeManager ?? createWorktreeManager(basePath)
439
440
  const mergeQueue = options._mergeQueue ?? createMergeQueue(basePath)
440
441
 
442
+ let result: ConvoyResult
441
443
  try {
442
444
  store.insertConvoy({
443
445
  id: convoyId,
@@ -474,13 +476,15 @@ export function createConvoyEngine(options: ConvoyEngineOptions): ConvoyEngine {
474
476
  store.updateConvoyStatus(convoyId, 'running', { started_at: new Date().toISOString() })
475
477
  events.emit('convoy_started', { name: spec.name }, { convoy_id: convoyId })
476
478
 
477
- return await runConvoy(
479
+ result = await runConvoy(
478
480
  convoyId, spec, adapter, store, events,
479
481
  wtManager, mergeQueue, basePath, baseBranch, verbose, startTime,
480
482
  )
481
483
  } finally {
484
+ try { await exportConvoyToNdjson(store, convoyId, options.logsDir) } catch { /* silent */ }
482
485
  store.close()
483
486
  }
487
+ return result
484
488
  }
485
489
 
486
490
  async function resume(convoyId: string): Promise<ConvoyResult> {
@@ -492,6 +496,7 @@ export function createConvoyEngine(options: ConvoyEngineOptions): ConvoyEngine {
492
496
  const wtManager = options._worktreeManager ?? createWorktreeManager(basePath)
493
497
  const mergeQueue = options._mergeQueue ?? createMergeQueue(basePath)
494
498
 
499
+ let result: ConvoyResult
495
500
  try {
496
501
  const convoy = store.getConvoy(convoyId)
497
502
  if (!convoy) {
@@ -531,13 +536,15 @@ export function createConvoyEngine(options: ConvoyEngineOptions): ConvoyEngine {
531
536
  { convoy_id: convoyId },
532
537
  )
533
538
 
534
- return await runConvoy(
539
+ result = await runConvoy(
535
540
  convoyId, spec, adapter, store, events,
536
541
  wtManager, mergeQueue, basePath, baseBranch, verbose, startTime,
537
542
  )
538
543
  } finally {
544
+ try { await exportConvoyToNdjson(store, convoyId, options.logsDir) } catch { /* silent */ }
539
545
  store.close()
540
546
  }
547
+ return result
541
548
  }
542
549
 
543
550
  return { run, resume }
@@ -0,0 +1,190 @@
1
+ import { mkdtempSync, rmSync, readFileSync, existsSync, realpathSync } from 'node:fs'
2
+ import { tmpdir } from 'node:os'
3
+ import { join } from 'node:path'
4
+ import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
5
+ import { exportConvoyToNdjson } from './export.js'
6
+ import { createConvoyStore } from './store.js'
7
+ import type { ConvoyStore } from './store.js'
8
+ import type { ConvoyTaskStatus } from './types.js'
9
+
10
+ vi.mock('../log.js', () => ({
11
+ appendEvent: vi.fn().mockResolvedValue(undefined),
12
+ }))
13
+
14
+ const NOW = '2026-03-08T10:00:00.000Z'
15
+
16
+ let tmpDir: string
17
+ let store: ConvoyStore
18
+
19
+ function insertConvoy(id: string, name = 'Test Convoy') {
20
+ store.insertConvoy({
21
+ id,
22
+ name,
23
+ spec_hash: 'abc123',
24
+ status: 'done',
25
+ branch: 'main',
26
+ created_at: NOW,
27
+ spec_yaml: 'name: test',
28
+ })
29
+ store.updateConvoyStatus(id, 'done', { started_at: NOW, finished_at: NOW })
30
+ }
31
+
32
+ function insertTask(
33
+ taskId: string,
34
+ convoyId: string,
35
+ phase = 1,
36
+ status: ConvoyTaskStatus = 'done',
37
+ ) {
38
+ store.insertTask({
39
+ id: taskId,
40
+ convoy_id: convoyId,
41
+ phase,
42
+ prompt: 'Do something',
43
+ agent: 'developer',
44
+ adapter: 'claude-code',
45
+ model: null,
46
+ timeout_ms: 1_800_000,
47
+ status,
48
+ retries: 0,
49
+ max_retries: 1,
50
+ files: null,
51
+ depends_on: null,
52
+ })
53
+ if (status !== 'pending') {
54
+ store.updateTaskStatus(taskId, convoyId, status, {
55
+ started_at: NOW,
56
+ finished_at: NOW,
57
+ retries: 0,
58
+ })
59
+ }
60
+ }
61
+
62
+ function insertEvent(convoyId: string) {
63
+ store.insertEvent({
64
+ convoy_id: convoyId,
65
+ task_id: null,
66
+ worker_id: null,
67
+ type: 'convoy.started',
68
+ data: null,
69
+ created_at: NOW,
70
+ })
71
+ }
72
+
73
+ beforeEach(() => {
74
+ tmpDir = realpathSync(mkdtempSync(join(tmpdir(), 'convoy-export-test-')))
75
+ store = createConvoyStore(join(tmpDir, 'convoy.db'))
76
+ })
77
+
78
+ afterEach(() => {
79
+ store.close()
80
+ rmSync(tmpDir, { recursive: true, force: true })
81
+ })
82
+
83
+ describe('exportConvoyToNdjson', () => {
84
+ it('creates convoys.ndjson with valid NDJSON', async () => {
85
+ insertConvoy('c1')
86
+ insertTask('t1', 'c1')
87
+ const logsDir = join(tmpDir, 'logs')
88
+
89
+ await exportConvoyToNdjson(store, 'c1', logsDir)
90
+
91
+ const outFile = join(logsDir, 'convoys.ndjson')
92
+ expect(existsSync(outFile)).toBe(true)
93
+ const line = readFileSync(outFile, 'utf8').trimEnd()
94
+ expect(() => JSON.parse(line)).not.toThrow()
95
+ })
96
+
97
+ it('appends on multiple exports (2 convoys -> 2 lines)', async () => {
98
+ insertConvoy('c1')
99
+ insertConvoy('c2', 'Second Convoy')
100
+ const logsDir = join(tmpDir, 'logs')
101
+
102
+ await exportConvoyToNdjson(store, 'c1', logsDir)
103
+ await exportConvoyToNdjson(store, 'c2', logsDir)
104
+
105
+ const content = readFileSync(join(logsDir, 'convoys.ndjson'), 'utf8')
106
+ const lines = content.trim().split('\n').filter(Boolean)
107
+ expect(lines).toHaveLength(2)
108
+ expect(JSON.parse(lines[0]).id).toBe('c1')
109
+ expect(JSON.parse(lines[1]).id).toBe('c2')
110
+ })
111
+
112
+ it('required fields present', async () => {
113
+ insertConvoy('c1')
114
+ insertTask('t1', 'c1', 1, 'done')
115
+ insertTask('t2', 'c1', 1, 'failed')
116
+ insertEvent('c1')
117
+ const logsDir = join(tmpDir, 'logs')
118
+
119
+ await exportConvoyToNdjson(store, 'c1', logsDir)
120
+
121
+ const record = JSON.parse(readFileSync(join(logsDir, 'convoys.ndjson'), 'utf8').trim())
122
+ expect(record.id).toBe('c1')
123
+ expect(record.name).toBe('Test Convoy')
124
+ expect(record.status).toBe('done')
125
+ expect(Array.isArray(record.tasks)).toBe(true)
126
+ expect(record.tasks).toHaveLength(2)
127
+ expect(record.tasks[0]).toMatchObject({
128
+ id: 't1',
129
+ phase: 1,
130
+ agent: 'developer',
131
+ adapter: 'claude-code',
132
+ status: 'done',
133
+ retries: 0,
134
+ })
135
+ expect(record.summary).toMatchObject({ total: 2, done: 1, failed: 1, skipped: 0, timedOut: 0 })
136
+ expect(record.events_count).toBe(1)
137
+ })
138
+
139
+ it('missing convoy -> no error, no file', async () => {
140
+ const logsDir = join(tmpDir, 'logs')
141
+ await expect(exportConvoyToNdjson(store, 'nonexistent', logsDir)).resolves.toBeUndefined()
142
+ expect(existsSync(join(logsDir, 'convoys.ndjson'))).toBe(false)
143
+ })
144
+
145
+ it('creates directory if missing', async () => {
146
+ insertConvoy('c1')
147
+ const logsDir = join(tmpDir, 'deep', 'nested', 'logs')
148
+
149
+ await exportConvoyToNdjson(store, 'c1', logsDir)
150
+
151
+ expect(existsSync(join(logsDir, 'convoys.ndjson'))).toBe(true)
152
+ })
153
+
154
+ it('respects custom logsDir', async () => {
155
+ insertConvoy('c1')
156
+ const customDir = join(tmpDir, 'custom-output')
157
+
158
+ await exportConvoyToNdjson(store, 'c1', customDir)
159
+
160
+ const outFile = join(customDir, 'convoys.ndjson')
161
+ expect(existsSync(outFile)).toBe(true)
162
+ const record = JSON.parse(readFileSync(outFile, 'utf8').trim())
163
+ expect(record.id).toBe('c1')
164
+ })
165
+
166
+ it('never throws on store error — writes warning to stderr', async () => {
167
+ const broken = {
168
+ getConvoy: () => { throw new Error('db exploded') },
169
+ } as unknown as ConvoyStore
170
+ const stderrSpy = vi.spyOn(process.stderr, 'write').mockImplementation(() => true)
171
+
172
+ await expect(exportConvoyToNdjson(broken, 'c1', join(tmpDir, 'logs'))).resolves.toBeUndefined()
173
+ expect(stderrSpy).toHaveBeenCalledWith(expect.stringContaining('exportConvoyToNdjson warning'))
174
+
175
+ stderrSpy.mockRestore()
176
+ })
177
+
178
+ it('defaults to .opencastle/logs when logsDir is omitted', async () => {
179
+ insertConvoy('c1')
180
+ const originalCwd = process.cwd()
181
+ process.chdir(tmpDir)
182
+ try {
183
+ await exportConvoyToNdjson(store, 'c1')
184
+ const outFile = join(tmpDir, '.opencastle', 'logs', 'convoys.ndjson')
185
+ expect(existsSync(outFile)).toBe(true)
186
+ } finally {
187
+ process.chdir(originalCwd)
188
+ }
189
+ })
190
+ })
@@ -0,0 +1,52 @@
1
+ import { appendFileSync, mkdirSync } from 'node:fs'
2
+ import { resolve } from 'node:path'
3
+ import type { ConvoyStore } from './store.js'
4
+ export async function exportConvoyToNdjson(
5
+ store: ConvoyStore,
6
+ convoyId: string,
7
+ logsDir?: string,
8
+ ): Promise<void> {
9
+ try {
10
+ const convoy = store.getConvoy(convoyId)
11
+ if (!convoy) return
12
+
13
+ const tasks = store.getTasksByConvoy(convoyId)
14
+ const eventsCount = store.getEvents(convoyId).length
15
+
16
+ const summary = {
17
+ total: tasks.length,
18
+ done: tasks.filter((t) => t.status === 'done').length,
19
+ failed: tasks.filter((t) => t.status === 'failed').length,
20
+ skipped: tasks.filter((t) => t.status === 'skipped').length,
21
+ timedOut: tasks.filter((t) => t.status === 'timed-out').length,
22
+ }
23
+
24
+ const record = {
25
+ id: convoy.id,
26
+ name: convoy.name,
27
+ status: convoy.status,
28
+ branch: convoy.branch,
29
+ created_at: convoy.created_at,
30
+ started_at: convoy.started_at,
31
+ finished_at: convoy.finished_at,
32
+ summary,
33
+ tasks: tasks.map((t) => ({
34
+ id: t.id,
35
+ phase: t.phase,
36
+ agent: t.agent,
37
+ adapter: t.adapter,
38
+ status: t.status,
39
+ started_at: t.started_at,
40
+ finished_at: t.finished_at,
41
+ retries: t.retries,
42
+ })),
43
+ events_count: eventsCount,
44
+ }
45
+
46
+ const dir = logsDir ?? resolve(process.cwd(), '.opencastle', 'logs')
47
+ mkdirSync(dir, { recursive: true })
48
+ appendFileSync(resolve(dir, 'convoys.ndjson'), JSON.stringify(record) + '\n', 'utf8')
49
+ } catch (err) {
50
+ process.stderr.write(`[opencastle] exportConvoyToNdjson warning: ${String(err)}\n`)
51
+ }
52
+ }
@@ -20,6 +20,7 @@ const MIME_TYPES: Record<string, string> = {
20
20
 
21
21
  const DATA_FILES = [
22
22
  'events.ndjson',
23
+ 'convoys.ndjson',
23
24
  // Legacy individual files — kept for backwards compatibility
24
25
  'sessions.ndjson',
25
26
  'delegations.ndjson',
@@ -32,12 +33,28 @@ interface DashboardArgs {
32
33
  port: number
33
34
  openBrowser: boolean
34
35
  seed: boolean
36
+ convoyId?: string
37
+ }
38
+
39
+ export interface DashboardServerOptions {
40
+ port?: number
41
+ openBrowser?: boolean
42
+ seed?: boolean
43
+ pkgRoot: string
44
+ convoyId?: string
45
+ }
46
+
47
+ export interface DashboardServerResult {
48
+ server: Server
49
+ port: number
50
+ url: string
35
51
  }
36
52
 
37
53
  function parseArgs(args: string[]): DashboardArgs {
38
54
  let port = 4300
39
55
  let openBrowser = true
40
56
  let seed = false
57
+ let convoyId: string | undefined
41
58
 
42
59
  for (let i = 0; i < args.length; i++) {
43
60
  if (args[i] === '--port' && args[i + 1]) {
@@ -47,10 +64,13 @@ function parseArgs(args: string[]): DashboardArgs {
47
64
  openBrowser = false
48
65
  } else if (args[i] === '--seed') {
49
66
  seed = true
67
+ } else if (args[i] === '--convoy' && args[i + 1]) {
68
+ convoyId = args[i + 1]
69
+ i++
50
70
  }
51
71
  }
52
72
 
53
- return { port, openBrowser, seed }
73
+ return { port, openBrowser, seed, convoyId }
54
74
  }
55
75
 
56
76
  function openUrl(url: string): void {
@@ -104,15 +124,17 @@ function tryListen(
104
124
  })
105
125
  }
106
126
 
107
- export default async function dashboard({
108
- pkgRoot,
109
- args,
110
- }: CliContext): Promise<void> {
111
- const { port, openBrowser, seed } = parseArgs(args)
127
+ export async function startDashboardServer(
128
+ options: DashboardServerOptions,
129
+ ): Promise<DashboardServerResult> {
130
+ const port = options.port ?? 4300
131
+ const seed = options.seed ?? false
132
+ const { pkgRoot } = options
112
133
 
113
134
  const distDir = resolve(pkgRoot, 'src', 'dashboard', 'dist')
114
135
  const seedDir = resolve(pkgRoot, 'src', 'dashboard', 'seed-data')
115
136
  const projectRoot = process.cwd()
137
+ const convoyLogsDir = resolve(projectRoot, '.opencastle', 'logs')
116
138
  const logsDir = resolve(projectRoot, '.github', 'customizations', 'logs')
117
139
 
118
140
  // Check if dist exists
@@ -122,18 +144,6 @@ export default async function dashboard({
122
144
  )
123
145
  }
124
146
 
125
- // Check if any log files exist (for messaging)
126
- let hasLogs = false
127
- if (!seed) {
128
- const checkFiles = ['events.ndjson', ...DATA_FILES]
129
- for (const f of checkFiles) {
130
- if (await fileExists(join(logsDir, f))) {
131
- hasLogs = true
132
- break
133
- }
134
- }
135
- }
136
-
137
147
  const server = createServer(
138
148
  async (req: IncomingMessage, res: ServerResponse) => {
139
149
  try {
@@ -149,22 +159,34 @@ export default async function dashboard({
149
159
  const dataMatch = pathname.match(/^\/data\/(.+\.ndjson)$/)
150
160
  if (dataMatch && DATA_FILES.includes(dataMatch[1])) {
151
161
  const filename = dataMatch[1]
152
- let filePath: string
153
162
 
154
163
  if (seed) {
155
- filePath = join(seedDir, filename)
164
+ const filePath = join(seedDir, filename)
165
+ if (await fileExists(filePath)) {
166
+ const content = await readFile(filePath)
167
+ res.writeHead(200, { 'Content-Type': 'application/x-ndjson' })
168
+ res.end(content)
169
+ } else {
170
+ res.writeHead(200, { 'Content-Type': 'application/x-ndjson' })
171
+ res.end('')
172
+ }
156
173
  } else {
157
- filePath = join(logsDir, filename)
158
- }
174
+ const convoyPath = join(convoyLogsDir, filename)
175
+ const logsPath = join(logsDir, filename)
176
+ const inConvoy = await fileExists(convoyPath)
177
+ const inLogs = await fileExists(logsPath)
159
178
 
160
- if (await fileExists(filePath)) {
161
- const content = await readFile(filePath)
162
- res.writeHead(200, { 'Content-Type': 'application/x-ndjson' })
163
- res.end(content)
164
- } else {
165
- // Graceful fallback — empty body
166
179
  res.writeHead(200, { 'Content-Type': 'application/x-ndjson' })
167
- res.end('')
180
+ if (inConvoy && inLogs) {
181
+ const [c1, c2] = await Promise.all([readFile(convoyPath), readFile(logsPath)])
182
+ res.end(Buffer.concat([c1, c2]))
183
+ } else if (inConvoy) {
184
+ res.end(await readFile(convoyPath))
185
+ } else if (inLogs) {
186
+ res.end(await readFile(logsPath))
187
+ } else {
188
+ res.end('')
189
+ }
168
190
  }
169
191
  return
170
192
  }
@@ -197,23 +219,53 @@ export default async function dashboard({
197
219
  )
198
220
 
199
221
  const actualPort = await tryListen(server, port)
200
- const url = `http://localhost:${actualPort}`
222
+ const resolvedUrl = `http://localhost:${actualPort}`
223
+
224
+ return { server, port: actualPort, url: resolvedUrl }
225
+ }
226
+
227
+ export default async function dashboard({
228
+ pkgRoot,
229
+ args,
230
+ }: CliContext): Promise<void> {
231
+ const { port, openBrowser, seed, convoyId } = parseArgs(args)
232
+
233
+ // Check if any log files exist (for messaging)
234
+ let hasLogs = false
235
+ if (!seed) {
236
+ const projectRoot = process.cwd()
237
+ const logsDir = resolve(projectRoot, '.github', 'customizations', 'logs')
238
+ const checkFiles = ['events.ndjson', ...DATA_FILES]
239
+ for (const f of checkFiles) {
240
+ if (await fileExists(join(logsDir, f))) {
241
+ hasLogs = true
242
+ break
243
+ }
244
+ }
245
+ }
246
+
247
+ const dashResult = await startDashboardServer({ port, seed, pkgRoot, convoyId })
201
248
 
202
249
  console.log('')
203
250
  console.log(' \u{1F3F0} OpenCastle Dashboard')
204
251
  console.log('')
205
- console.log(` \u2192 ${url}`)
206
252
 
207
- if (seed) {
208
- console.log(
209
- ' \u{1F4C2} Showing demo data (use without --seed to read project logs)'
210
- )
211
- } else if (hasLogs) {
212
- console.log(' \u{1F4C2} Reading logs from .github/customizations/logs/')
253
+ if (convoyId) {
254
+ console.log(` \u2192 ${dashResult.url}/?convoy=${convoyId}`)
255
+ console.log(` \u{1F4C2} Watching convoy: ${convoyId}`)
213
256
  } else {
214
- console.log(
215
- ' \u{1F4A1} No agent logs found. Run agents with OpenCastle to generate data, or use --seed for demo data.'
216
- )
257
+ console.log(` \u2192 ${dashResult.url}`)
258
+ if (seed) {
259
+ console.log(
260
+ ' \u{1F4C2} Showing demo data (use without --seed to read project logs)'
261
+ )
262
+ } else if (hasLogs) {
263
+ console.log(' \u{1F4C2} Reading logs from .github/customizations/logs/')
264
+ } else {
265
+ console.log(
266
+ ' \u{1F4A1} No agent logs found. Run agents with OpenCastle to generate data, or use --seed for demo data.'
267
+ )
268
+ }
217
269
  }
218
270
 
219
271
  console.log('')
@@ -221,13 +273,13 @@ export default async function dashboard({
221
273
  console.log('')
222
274
 
223
275
  if (openBrowser) {
224
- openUrl(url)
276
+ openUrl(convoyId ? `${dashResult.url}/?convoy=${convoyId}` : dashResult.url)
225
277
  }
226
278
 
227
279
  // Graceful shutdown
228
280
  process.on('SIGINT', () => {
229
281
  console.log('\n Dashboard stopped.\n')
230
- server.close()
282
+ dashResult.server.close()
231
283
  process.exit(0)
232
284
  })
233
285
 
package/src/cli/run.ts CHANGED
@@ -158,7 +158,7 @@ function printConvoyResult(result: ConvoyResult): void {
158
158
  /**
159
159
  * CLI entry point for the `run` command.
160
160
  */
161
- export default async function run({ args }: CliContext): Promise<void> {
161
+ export default async function run({ args, pkgRoot }: CliContext): Promise<void> {
162
162
  const opts = parseArgs(args)
163
163
 
164
164
  if (opts.help) {
@@ -340,6 +340,18 @@ export default async function run({ args }: CliContext): Promise<void> {
340
340
  if (spec.branch) console.log(` Branch: ${spec.branch}`)
341
341
  if (spec.gates?.length) console.log(` Gates: ${spec.gates.length} validation commands`)
342
342
 
343
+ const { startDashboardServer } = await import('./dashboard.js')
344
+ let dashboardResult: { server: import('node:http').Server } | null = null
345
+ try {
346
+ dashboardResult = await startDashboardServer({
347
+ pkgRoot,
348
+ openBrowser: true,
349
+ convoyId: 'active',
350
+ })
351
+ } catch {
352
+ // Dashboard failure must not block convoy
353
+ }
354
+
343
355
  const engine = createConvoyEngine({
344
356
  spec,
345
357
  specYaml: specText,
@@ -349,6 +361,9 @@ export default async function run({ args }: CliContext): Promise<void> {
349
361
 
350
362
  const result = await engine.run()
351
363
  printConvoyResult(result)
364
+ if (dashboardResult) {
365
+ dashboardResult.server.close()
366
+ }
352
367
  process.exit(result.status !== 'done' ? 1 : 0)
353
368
  }
354
369