@proletariat/cli 0.3.64 → 0.3.66

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 (58) hide show
  1. package/dist/commands/agents/index.d.ts +11 -0
  2. package/dist/commands/agents/index.js +105 -0
  3. package/dist/commands/agents/index.js.map +1 -0
  4. package/dist/commands/pr/checks.d.ts +20 -0
  5. package/dist/commands/pr/checks.js +154 -0
  6. package/dist/commands/pr/checks.js.map +1 -0
  7. package/dist/commands/pr/index.js +10 -2
  8. package/dist/commands/pr/index.js.map +1 -1
  9. package/dist/commands/pr/merge.d.ts +22 -0
  10. package/dist/commands/pr/merge.js +145 -0
  11. package/dist/commands/pr/merge.js.map +1 -0
  12. package/dist/commands/version/bump.d.ts +13 -0
  13. package/dist/commands/version/bump.js +125 -0
  14. package/dist/commands/version/bump.js.map +1 -0
  15. package/dist/commands/work/start.js +147 -99
  16. package/dist/commands/work/start.js.map +1 -1
  17. package/dist/lib/database/index.d.ts +1 -1
  18. package/dist/lib/database/index.js +9 -107
  19. package/dist/lib/database/index.js.map +1 -1
  20. package/dist/lib/database/migrations/0001_baseline.d.ts +9 -0
  21. package/dist/lib/database/migrations/0001_baseline.js +18 -0
  22. package/dist/lib/database/migrations/0001_baseline.js.map +1 -0
  23. package/dist/lib/database/migrations/index.d.ts +12 -0
  24. package/dist/lib/database/migrations/index.js +15 -0
  25. package/dist/lib/database/migrations/index.js.map +1 -0
  26. package/dist/lib/database/migrator.d.ts +27 -0
  27. package/dist/lib/database/migrator.js +42 -0
  28. package/dist/lib/database/migrator.js.map +1 -0
  29. package/dist/lib/database/workspace-schema.d.ts +7 -0
  30. package/dist/lib/database/workspace-schema.js +109 -0
  31. package/dist/lib/database/workspace-schema.js.map +1 -0
  32. package/dist/lib/events/events.d.ts +5 -0
  33. package/dist/lib/events/index.d.ts +1 -1
  34. package/dist/lib/events/index.js.map +1 -1
  35. package/dist/lib/execution/runners.js +14 -6
  36. package/dist/lib/execution/runners.js.map +1 -1
  37. package/dist/lib/external-issues/outbound-sync.d.ts +21 -16
  38. package/dist/lib/external-issues/outbound-sync.js +64 -49
  39. package/dist/lib/external-issues/outbound-sync.js.map +1 -1
  40. package/dist/lib/pmo/sync-manager.js +5 -1
  41. package/dist/lib/pmo/sync-manager.js.map +1 -1
  42. package/dist/lib/pr/index.d.ts +28 -0
  43. package/dist/lib/pr/index.js +53 -1
  44. package/dist/lib/pr/index.js.map +1 -1
  45. package/dist/lib/registry/index.d.ts +52 -0
  46. package/dist/lib/registry/index.js +169 -0
  47. package/dist/lib/registry/index.js.map +1 -0
  48. package/dist/lib/work-lifecycle/adapter.d.ts +34 -0
  49. package/dist/lib/work-lifecycle/adapter.js +103 -0
  50. package/dist/lib/work-lifecycle/adapter.js.map +1 -0
  51. package/dist/lib/work-lifecycle/events.d.ts +52 -0
  52. package/dist/lib/work-lifecycle/events.js +12 -0
  53. package/dist/lib/work-lifecycle/events.js.map +1 -0
  54. package/dist/lib/work-lifecycle/index.d.ts +9 -0
  55. package/dist/lib/work-lifecycle/index.js +9 -0
  56. package/dist/lib/work-lifecycle/index.js.map +1 -0
  57. package/oclif.manifest.json +2444 -2203
  58. package/package.json +1 -1
@@ -0,0 +1,125 @@
1
+ import { Command, Args } from '@oclif/core';
2
+ import { execSync } from 'node:child_process';
3
+ import { readFileSync, writeFileSync } from 'node:fs';
4
+ import { resolve } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
6
+ import { styles } from '../../lib/styles.js';
7
+ import { machineOutputFlags } from '../../lib/pmo/index.js';
8
+ import { shouldOutputJson, createMetadata, outputSuccessAsJson, outputErrorAsJson, } from '../../lib/prompt-json.js';
9
+ const __dirname = fileURLToPath(new URL('.', import.meta.url));
10
+ function bumpVersion(current, type) {
11
+ const parts = current.split('.').map(Number);
12
+ if (parts.length !== 3 || parts.some(isNaN)) {
13
+ throw new Error(`Invalid semver version: ${current}`);
14
+ }
15
+ const [major, minor, patch] = parts;
16
+ switch (type) {
17
+ case 'major':
18
+ return `${major + 1}.0.0`;
19
+ case 'minor':
20
+ return `${major}.${minor + 1}.0`;
21
+ case 'patch':
22
+ return `${major}.${minor}.${patch + 1}`;
23
+ }
24
+ }
25
+ export default class VersionBump extends Command {
26
+ static description = 'Bump the CLI version (major, minor, or patch), commit, push, and create a PR';
27
+ static examples = [
28
+ '<%= config.bin %> version bump patch',
29
+ '<%= config.bin %> version bump minor',
30
+ '<%= config.bin %> version bump major',
31
+ '<%= config.bin %> version bump patch --json',
32
+ ];
33
+ static args = {
34
+ type: Args.string({
35
+ description: 'Version bump type',
36
+ required: true,
37
+ options: ['major', 'minor', 'patch'],
38
+ }),
39
+ };
40
+ static flags = {
41
+ ...machineOutputFlags,
42
+ };
43
+ async run() {
44
+ const { args, flags } = await this.parse(VersionBump);
45
+ const jsonMode = shouldOutputJson(flags);
46
+ const bumpType = args.type;
47
+ // Read current version from package.json
48
+ const pkgPath = resolve(__dirname, '..', '..', '..', 'package.json');
49
+ let pkg;
50
+ try {
51
+ pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
52
+ }
53
+ catch {
54
+ const msg = `Failed to read package.json at ${pkgPath}`;
55
+ if (jsonMode) {
56
+ outputErrorAsJson('PACKAGE_READ_ERROR', msg, createMetadata('version bump', flags));
57
+ }
58
+ this.error(msg);
59
+ }
60
+ const oldVersion = pkg.version;
61
+ const newVersion = bumpVersion(oldVersion, bumpType);
62
+ const branchName = `chore/bump-version-to-${newVersion}`;
63
+ if (!jsonMode) {
64
+ this.log(`\n${styles.header('Version Bump')}`);
65
+ this.log('─'.repeat(50));
66
+ this.log(` ${styles.muted('Current:')} ${oldVersion}`);
67
+ this.log(` ${styles.muted('New:')} ${newVersion}`);
68
+ this.log(` ${styles.muted('Type:')} ${bumpType}`);
69
+ this.log('');
70
+ }
71
+ // Update package.json
72
+ pkg.version = newVersion;
73
+ writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
74
+ if (!jsonMode) {
75
+ this.log(`${styles.success('Updated')} package.json`);
76
+ }
77
+ // Git operations
78
+ try {
79
+ const gitOpts = { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] };
80
+ execSync(`git checkout -b ${branchName}`, gitOpts);
81
+ if (!jsonMode) {
82
+ this.log(`${styles.success('Created')} branch ${styles.code(branchName)}`);
83
+ }
84
+ execSync(`git add ${pkgPath}`, gitOpts);
85
+ execSync(`git commit -m "chore: bump version to ${newVersion}"`, gitOpts);
86
+ if (!jsonMode) {
87
+ this.log(`${styles.success('Committed')} version bump`);
88
+ }
89
+ execSync(`git push -u origin ${branchName}`, gitOpts);
90
+ if (!jsonMode) {
91
+ this.log(`${styles.success('Pushed')} to origin`);
92
+ }
93
+ // Create PR
94
+ const prTitle = `chore: bump version to ${newVersion}`;
95
+ const prBody = [
96
+ '## Summary',
97
+ `- Bump CLI version from ${oldVersion} to ${newVersion} (${bumpType})`,
98
+ '',
99
+ 'Automated version bump via `prlt version bump`.',
100
+ ].join('\n');
101
+ const prUrl = execSync(`gh pr create --title "${prTitle}" --body ${JSON.stringify(prBody)} --base main`, gitOpts).trim();
102
+ if (jsonMode) {
103
+ outputSuccessAsJson({
104
+ oldVersion,
105
+ newVersion,
106
+ bumpType,
107
+ branch: branchName,
108
+ prUrl,
109
+ }, createMetadata('version bump', flags));
110
+ }
111
+ this.log(`\n${styles.success('PR created:')} ${prUrl}\n`);
112
+ }
113
+ catch (error) {
114
+ // Revert package.json on failure
115
+ pkg.version = oldVersion;
116
+ writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
117
+ const msg = error instanceof Error ? error.message : String(error);
118
+ if (jsonMode) {
119
+ outputErrorAsJson('GIT_ERROR', msg, createMetadata('version bump', flags));
120
+ }
121
+ this.error(`Git operation failed: ${msg}`);
122
+ }
123
+ }
124
+ }
125
+ //# sourceMappingURL=bump.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bump.js","sourceRoot":"","sources":["../../../src/commands/version/bump.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@ import { execSync } from 'node:child_process';
6
6
  import Database from 'better-sqlite3';
7
7
  import { PMOCommand, pmoBaseFlags, autoExportToBoard } from '../../lib/pmo/index.js';
8
8
  import { trackAgentSpawned } from '../../lib/telemetry/analytics.js';
9
+ import { registerAgent } from '../../lib/registry/index.js';
9
10
  import { shouldOutputJson, outputErrorAsJson, createMetadata, outputConfirmationNeededAsJson, outputExecutionResultAsJson, } from '../../lib/prompt-json.js';
10
11
  import { FlagResolver } from '../../lib/flags/index.js';
11
12
  import { getWorkColumnSetting, findColumnByName } from '../../lib/pmo/utils.js';
@@ -1387,8 +1388,8 @@ export default class WorkStart extends PMOCommand {
1387
1388
  this.log('');
1388
1389
  this.log(styles.warning('Docker daemon is not running. Start Docker Desktop or use --run-on-host.'));
1389
1390
  this.log('');
1390
- if (jsonMode && flags.yes) {
1391
- // In JSON mode with --yes, auto-switch to host
1391
+ if (flags.yes || !process.stdout.isTTY) {
1392
+ // Non-interactive mode: auto-switch to host
1392
1393
  environment = 'host';
1393
1394
  this.log(styles.muted('Switched to host environment (Docker not running).'));
1394
1395
  }
@@ -1441,11 +1442,19 @@ export default class WorkStart extends PMOCommand {
1441
1442
  // Saved preference: OAuth — validate credentials exist
1442
1443
  const hasCredentials = dockerCredentialsExist();
1443
1444
  if (!hasCredentials) {
1444
- this.log('');
1445
- this.log(styles.warning('⚠️ Saved auth method is "oauth" but no OAuth credentials found.'));
1446
- this.log(styles.muted(' Run "' + this.config.bin + ' agent auth" to authenticate.'));
1447
- db.close();
1448
- return;
1445
+ if (flags.yes || !process.stdout.isTTY) {
1446
+ // Non-interactive mode: auto-fallback to host
1447
+ this.log(styles.warning('⚠️ Saved auth method is "oauth" but no OAuth credentials found.'));
1448
+ environment = 'host';
1449
+ this.log(styles.muted('Switched to host environment (OAuth credentials missing).'));
1450
+ }
1451
+ else {
1452
+ this.log('');
1453
+ this.log(styles.warning('⚠️ Saved auth method is "oauth" but no OAuth credentials found.'));
1454
+ this.log(styles.muted(' Run "' + this.config.bin + ' agent auth" to authenticate.'));
1455
+ db.close();
1456
+ return;
1457
+ }
1449
1458
  }
1450
1459
  // OAuth credentials valid — continue (useApiKey stays false)
1451
1460
  }
@@ -1458,9 +1467,10 @@ export default class WorkStart extends PMOCommand {
1458
1467
  }
1459
1468
  else {
1460
1469
  // No saved preference and no OAuth credentials — prompt user
1461
- // In JSON mode with --yes, continue anyway (agent can run /login)
1462
- if (jsonMode && flags.yes) {
1463
- // Continue without prompting - agent will need to handle auth
1470
+ if (flags.yes || !process.stdout.isTTY) {
1471
+ // Non-interactive mode: auto-fallback to host
1472
+ environment = 'host';
1473
+ this.log(styles.warning('⚠️ No OAuth credentials found. Switched to host environment.'));
1464
1474
  }
1465
1475
  else {
1466
1476
  this.log('');
@@ -1985,6 +1995,18 @@ export default class WorkStart extends PMOCommand {
1985
1995
  action: context.actionId || 'implement',
1986
1996
  ephemeral: isEphemeralAgent,
1987
1997
  });
1998
+ // Register in machine-wide agent registry
1999
+ try {
2000
+ registerAgent({
2001
+ agentName: context.agentName,
2002
+ projectPath: workspaceInfo.path,
2003
+ sessionId: result.sessionId,
2004
+ ticketId: context.ticketId,
2005
+ });
2006
+ }
2007
+ catch {
2008
+ // Non-fatal — registry is best-effort
2009
+ }
1988
2010
  // Update execution record with process info
1989
2011
  executionStorage.updateStatus(execution.id, 'running');
1990
2012
  executionStorage.updateProcessInfo(execution.id, {
@@ -2188,115 +2210,129 @@ export default class WorkStart extends PMOCommand {
2188
2210
  this.log('');
2189
2211
  this.log(styles.warning('Docker daemon is not running. Start Docker Desktop or use --run-on-host.'));
2190
2212
  this.log('');
2191
- const { dockerAction } = await this.prompt([
2192
- {
2193
- type: 'list',
2194
- name: 'dockerAction',
2195
- message: 'Docker is not running. What would you like to do?',
2196
- choices: [
2197
- { name: '💻 Run all agents on host instead (--run-on-host)', value: 'host', command: 'prlt work start --all --run-on-host --json' },
2198
- { name: '✗ Cancel', value: 'cancel', command: '' },
2199
- ],
2200
- },
2201
- ], batchJsonModeConfig);
2202
- if (dockerAction === 'cancel') {
2203
- db.close();
2204
- this.log(styles.muted('Cancelled.'));
2205
- return;
2213
+ if (!process.stdout.isTTY) {
2214
+ // Non-interactive mode: auto-switch to host
2215
+ flags['run-on-host'] = true;
2216
+ this.log(styles.muted('All agents will run on host (Docker not running).'));
2206
2217
  }
2207
- flags['run-on-host'] = true;
2208
- this.log(styles.muted('All agents will run on host.'));
2209
- }
2210
- if (!flags['run-on-host']) {
2211
- const hasCredentials = dockerCredentialsExist();
2212
- if (!hasCredentials) {
2213
- const hasApiKey = !!process.env.ANTHROPIC_API_KEY;
2214
- this.log('');
2215
- this.log(styles.warning('⚠️ No Claude Code OAuth credentials found for Docker containers'));
2216
- this.log(styles.muted(' Agents need credentials to authenticate with Claude.'));
2217
- this.log('');
2218
- // Build choices based on available options
2219
- const batchAuthChoices = [
2220
- { name: `🔐 Run ${this.config.bin} agent auth now (recommended — uses Max subscription)`, value: 'auth', command: `${this.config.bin} agent auth` },
2221
- ];
2222
- if (hasApiKey) {
2223
- batchAuthChoices.push({ name: '🔑 Use ANTHROPIC_API_KEY (⚠️ uses API credits, not Max subscription)', value: 'apikey', command: '' });
2224
- }
2225
- batchAuthChoices.push({ name: '💻 Run all agents on host instead (--run-on-host)', value: 'host', command: 'prlt work start --all --run-on-host --json' }, { name: '✗ Cancel', value: 'cancel', command: '' });
2226
- const { authAction } = await this.prompt([
2218
+ else {
2219
+ const { dockerAction } = await this.prompt([
2227
2220
  {
2228
2221
  type: 'list',
2229
- name: 'authAction',
2230
- message: 'What would you like to do?',
2231
- choices: batchAuthChoices,
2222
+ name: 'dockerAction',
2223
+ message: 'Docker is not running. What would you like to do?',
2224
+ choices: [
2225
+ { name: '💻 Run all agents on host instead (--run-on-host)', value: 'host', command: 'prlt work start --all --run-on-host --json' },
2226
+ { name: '✗ Cancel', value: 'cancel', command: '' },
2227
+ ],
2232
2228
  },
2233
2229
  ], batchJsonModeConfig);
2234
- if (authAction === 'cancel') {
2230
+ if (dockerAction === 'cancel') {
2235
2231
  db.close();
2236
2232
  this.log(styles.muted('Cancelled.'));
2237
2233
  return;
2238
2234
  }
2239
- if (authAction === 'host') {
2235
+ flags['run-on-host'] = true;
2236
+ this.log(styles.muted('All agents will run on host.'));
2237
+ }
2238
+ }
2239
+ if (!flags['run-on-host']) {
2240
+ const hasCredentials = dockerCredentialsExist();
2241
+ if (!hasCredentials) {
2242
+ if (!process.stdout.isTTY) {
2243
+ // Non-interactive mode: auto-fallback to host
2244
+ this.log(styles.warning('⚠️ No OAuth credentials found. Switched to host environment.'));
2240
2245
  flags['run-on-host'] = true;
2241
- this.log(styles.muted('All agents will run on host.'));
2242
2246
  }
2243
- else if (authAction === 'apikey') {
2244
- batchUseApiKey = true;
2245
- this.log(styles.warning('Using ANTHROPIC_API_KEY — this will consume API credits.'));
2246
- this.log(styles.muted(`Run "${this.config.bin} agent auth" to set up OAuth and use your Max subscription instead.`));
2247
- this.log('');
2248
- }
2249
- else if (authAction === 'auth') {
2247
+ else {
2248
+ const hasApiKey = !!process.env.ANTHROPIC_API_KEY;
2250
2249
  this.log('');
2251
- this.log(styles.primary(`Opening ${this.config.bin} agent auth in new tab...`));
2250
+ this.log(styles.warning('⚠️ No Claude Code OAuth credentials found for Docker containers'));
2251
+ this.log(styles.muted(' Agents need credentials to authenticate with Claude.'));
2252
2252
  this.log('');
2253
- // Open auth in a new terminal tab
2254
- const authCmd = `${process.argv[1]} agent auth`;
2255
- try {
2256
- execSync(`osascript -e '
2257
- tell application "iTerm"
2258
- tell current window
2259
- create tab with default profile
2260
- tell current session
2261
- write text "${authCmd}"
2262
- end tell
2263
- end tell
2264
- end tell
2265
- '`);
2253
+ // Build choices based on available options
2254
+ const batchAuthChoices = [
2255
+ { name: `🔐 Run ${this.config.bin} agent auth now (recommended — uses Max subscription)`, value: 'auth', command: `${this.config.bin} agent auth` },
2256
+ ];
2257
+ if (hasApiKey) {
2258
+ batchAuthChoices.push({ name: '🔑 Use ANTHROPIC_API_KEY (⚠️ uses API credits, not Max subscription)', value: 'apikey', command: '' });
2266
2259
  }
2267
- catch {
2268
- // Fallback: try Terminal.app
2260
+ batchAuthChoices.push({ name: '💻 Run all agents on host instead (--run-on-host)', value: 'host', command: 'prlt work start --all --run-on-host --json' }, { name: '✗ Cancel', value: 'cancel', command: '' });
2261
+ const { authAction } = await this.prompt([
2262
+ {
2263
+ type: 'list',
2264
+ name: 'authAction',
2265
+ message: 'What would you like to do?',
2266
+ choices: batchAuthChoices,
2267
+ },
2268
+ ], batchJsonModeConfig);
2269
+ if (authAction === 'cancel') {
2270
+ db.close();
2271
+ this.log(styles.muted('Cancelled.'));
2272
+ return;
2273
+ }
2274
+ if (authAction === 'host') {
2275
+ flags['run-on-host'] = true;
2276
+ this.log(styles.muted('All agents will run on host.'));
2277
+ }
2278
+ else if (authAction === 'apikey') {
2279
+ batchUseApiKey = true;
2280
+ this.log(styles.warning('Using ANTHROPIC_API_KEY — this will consume API credits.'));
2281
+ this.log(styles.muted(`Run "${this.config.bin} agent auth" to set up OAuth and use your Max subscription instead.`));
2282
+ this.log('');
2283
+ }
2284
+ else if (authAction === 'auth') {
2285
+ this.log('');
2286
+ this.log(styles.primary(`Opening ${this.config.bin} agent auth in new tab...`));
2287
+ this.log('');
2288
+ // Open auth in a new terminal tab
2289
+ const authCmd = `${process.argv[1]} agent auth`;
2269
2290
  try {
2270
- execSync(`osascript -e 'tell application "Terminal" to do script "${authCmd}"'`);
2291
+ execSync(`osascript -e '
2292
+ tell application "iTerm"
2293
+ tell current window
2294
+ create tab with default profile
2295
+ tell current session
2296
+ write text "${authCmd}"
2297
+ end tell
2298
+ end tell
2299
+ end tell
2300
+ '`);
2271
2301
  }
2272
2302
  catch {
2273
- this.log(styles.warning('Could not open new terminal tab.'));
2274
- this.log(styles.muted(`Please run manually: ${authCmd}`));
2303
+ // Fallback: try Terminal.app
2304
+ try {
2305
+ execSync(`osascript -e 'tell application "Terminal" to do script "${authCmd}"'`);
2306
+ }
2307
+ catch {
2308
+ this.log(styles.warning('Could not open new terminal tab.'));
2309
+ this.log(styles.muted(`Please run manually: ${authCmd}`));
2310
+ }
2311
+ }
2312
+ this.log(styles.muted('Complete the /login flow in the new tab, then press Enter here...'));
2313
+ this.log('');
2314
+ // Wait for user to complete auth
2315
+ await this.prompt([{
2316
+ type: 'input',
2317
+ name: 'done',
2318
+ message: 'Press Enter when authentication is complete:',
2319
+ }], batchJsonModeConfig);
2320
+ // Check if credentials now exist
2321
+ if (!dockerCredentialsExist()) {
2322
+ this.log('');
2323
+ this.log(styles.warning('Authentication did not complete. No credentials found.'));
2324
+ db.close();
2325
+ return;
2326
+ }
2327
+ const info = getDockerCredentialInfo();
2328
+ this.log('');
2329
+ this.log(styles.success('✓ Credentials configured'));
2330
+ if (info) {
2331
+ this.log(styles.muted(` Subscription: ${info.subscriptionType || 'unknown'}`));
2332
+ this.log(styles.muted(` Expires: ${info.expiresAt.toLocaleDateString()}`));
2275
2333
  }
2276
- }
2277
- this.log(styles.muted('Complete the /login flow in the new tab, then press Enter here...'));
2278
- this.log('');
2279
- // Wait for user to complete auth
2280
- await this.prompt([{
2281
- type: 'input',
2282
- name: 'done',
2283
- message: 'Press Enter when authentication is complete:',
2284
- }], batchJsonModeConfig);
2285
- // Check if credentials now exist
2286
- if (!dockerCredentialsExist()) {
2287
2334
  this.log('');
2288
- this.log(styles.warning('Authentication did not complete. No credentials found.'));
2289
- db.close();
2290
- return;
2291
- }
2292
- const info = getDockerCredentialInfo();
2293
- this.log('');
2294
- this.log(styles.success('✓ Credentials configured'));
2295
- if (info) {
2296
- this.log(styles.muted(` Subscription: ${info.subscriptionType || 'unknown'}`));
2297
- this.log(styles.muted(` Expires: ${info.expiresAt.toLocaleDateString()}`));
2298
2335
  }
2299
- this.log('');
2300
2336
  }
2301
2337
  }
2302
2338
  }
@@ -2468,6 +2504,18 @@ export default class WorkStart extends PMOCommand {
2468
2504
  sessionId: result.sessionId,
2469
2505
  logPath: result.logPath,
2470
2506
  });
2507
+ // Register in machine-wide agent registry
2508
+ try {
2509
+ registerAgent({
2510
+ agentName: context.agentName,
2511
+ projectPath: workspaceInfo.path,
2512
+ sessionId: result.sessionId,
2513
+ ticketId: context.ticketId,
2514
+ });
2515
+ }
2516
+ catch {
2517
+ // Non-fatal — registry is best-effort
2518
+ }
2471
2519
  // Update ticket assignee ONLY after successful spawn
2472
2520
  if (!ticket.assignee || ticket.assignee !== agentName) {
2473
2521
  await this.storage.updateTicket(ticket.id, { assignee: agentName });