@evref-bl/dev-nexus 0.1.0-alpha.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 (100) hide show
  1. package/README.md +677 -0
  2. package/dist/browserOpener.d.ts +9 -0
  3. package/dist/browserOpener.js +47 -0
  4. package/dist/cli.d.ts +18 -0
  5. package/dist/cli.js +2374 -0
  6. package/dist/gitWorktreeService.d.ts +57 -0
  7. package/dist/gitWorktreeService.js +157 -0
  8. package/dist/index.d.ts +47 -0
  9. package/dist/index.js +47 -0
  10. package/dist/nexusAgentMcpConfig.d.ts +30 -0
  11. package/dist/nexusAgentMcpConfig.js +228 -0
  12. package/dist/nexusAutomation.d.ts +103 -0
  13. package/dist/nexusAutomation.js +390 -0
  14. package/dist/nexusAutomationAgentLaunch.d.ts +148 -0
  15. package/dist/nexusAutomationAgentLaunch.js +855 -0
  16. package/dist/nexusAutomationAgentProfile.d.ts +39 -0
  17. package/dist/nexusAutomationAgentProfile.js +103 -0
  18. package/dist/nexusAutomationAgentSurface.d.ts +62 -0
  19. package/dist/nexusAutomationAgentSurface.js +90 -0
  20. package/dist/nexusAutomationCommandExecutor.d.ts +29 -0
  21. package/dist/nexusAutomationCommandExecutor.js +251 -0
  22. package/dist/nexusAutomationConfig.d.ts +114 -0
  23. package/dist/nexusAutomationConfig.js +547 -0
  24. package/dist/nexusAutomationEnqueue.d.ts +37 -0
  25. package/dist/nexusAutomationEnqueue.js +128 -0
  26. package/dist/nexusAutomationRunOnce.d.ts +91 -0
  27. package/dist/nexusAutomationRunOnce.js +586 -0
  28. package/dist/nexusAutomationScheduler.d.ts +50 -0
  29. package/dist/nexusAutomationScheduler.js +196 -0
  30. package/dist/nexusAutomationStatus.d.ts +55 -0
  31. package/dist/nexusAutomationStatus.js +462 -0
  32. package/dist/nexusAutomationTarget.d.ts +19 -0
  33. package/dist/nexusAutomationTarget.js +33 -0
  34. package/dist/nexusAutomationTargetCycle.d.ts +90 -0
  35. package/dist/nexusAutomationTargetCycle.js +282 -0
  36. package/dist/nexusAutomationTargetReport.d.ts +136 -0
  37. package/dist/nexusAutomationTargetReport.js +504 -0
  38. package/dist/nexusAutomationWorktreeSetup.d.ts +89 -0
  39. package/dist/nexusAutomationWorktreeSetup.js +661 -0
  40. package/dist/nexusCoordination.d.ts +198 -0
  41. package/dist/nexusCoordination.js +1018 -0
  42. package/dist/nexusExtension.d.ts +31 -0
  43. package/dist/nexusExtension.js +1 -0
  44. package/dist/nexusHomeConfig.d.ts +38 -0
  45. package/dist/nexusHomeConfig.js +133 -0
  46. package/dist/nexusMcpServer.d.ts +31 -0
  47. package/dist/nexusMcpServer.js +1036 -0
  48. package/dist/nexusPluginCapabilities.d.ts +197 -0
  49. package/dist/nexusPluginCapabilities.js +201 -0
  50. package/dist/nexusProjectConfig.d.ts +95 -0
  51. package/dist/nexusProjectConfig.js +880 -0
  52. package/dist/nexusProjectHomeService.d.ts +121 -0
  53. package/dist/nexusProjectHomeService.js +171 -0
  54. package/dist/nexusProjectLifecycle.d.ts +62 -0
  55. package/dist/nexusProjectLifecycle.js +205 -0
  56. package/dist/nexusProjectOperations.d.ts +101 -0
  57. package/dist/nexusProjectOperations.js +296 -0
  58. package/dist/nexusProjectRegistry.d.ts +42 -0
  59. package/dist/nexusProjectRegistry.js +91 -0
  60. package/dist/nexusProjectScaffold.d.ts +25 -0
  61. package/dist/nexusProjectScaffold.js +61 -0
  62. package/dist/nexusProjectTemplate.d.ts +34 -0
  63. package/dist/nexusProjectTemplate.js +354 -0
  64. package/dist/nexusSkills.d.ts +134 -0
  65. package/dist/nexusSkills.js +647 -0
  66. package/dist/nexusWorkerContextBundle.d.ts +142 -0
  67. package/dist/nexusWorkerContextBundle.js +375 -0
  68. package/dist/processSupervisor.d.ts +89 -0
  69. package/dist/processSupervisor.js +440 -0
  70. package/dist/vibeKanbanApi.d.ts +11 -0
  71. package/dist/vibeKanbanApi.js +14 -0
  72. package/dist/vibeKanbanAuth.d.ts +25 -0
  73. package/dist/vibeKanbanAuth.js +101 -0
  74. package/dist/vibeKanbanBoardAdapter.d.ts +36 -0
  75. package/dist/vibeKanbanBoardAdapter.js +196 -0
  76. package/dist/vibeKanbanMcpConfig.d.ts +36 -0
  77. package/dist/vibeKanbanMcpConfig.js +191 -0
  78. package/dist/vibeKanbanProjectAdapter.d.ts +39 -0
  79. package/dist/vibeKanbanProjectAdapter.js +113 -0
  80. package/dist/vibeKanbanWorkspaceSetup.d.ts +1 -0
  81. package/dist/vibeKanbanWorkspaceSetup.js +96 -0
  82. package/dist/workItemService.d.ts +60 -0
  83. package/dist/workItemService.js +163 -0
  84. package/dist/workTrackingGitHubProvider.d.ts +71 -0
  85. package/dist/workTrackingGitHubProvider.js +663 -0
  86. package/dist/workTrackingGitLabProvider.d.ts +62 -0
  87. package/dist/workTrackingGitLabProvider.js +523 -0
  88. package/dist/workTrackingJiraProvider.d.ts +67 -0
  89. package/dist/workTrackingJiraProvider.js +652 -0
  90. package/dist/workTrackingLocalProvider.d.ts +49 -0
  91. package/dist/workTrackingLocalProvider.js +463 -0
  92. package/dist/workTrackingProviderService.d.ts +21 -0
  93. package/dist/workTrackingProviderService.js +117 -0
  94. package/dist/workTrackingTypes.d.ts +202 -0
  95. package/dist/workTrackingTypes.js +1 -0
  96. package/dist/workTrackingVibeProvider.d.ts +35 -0
  97. package/dist/workTrackingVibeProvider.js +119 -0
  98. package/dist/worktreeExecutionMetadata.d.ts +76 -0
  99. package/dist/worktreeExecutionMetadata.js +239 -0
  100. package/package.json +37 -0
@@ -0,0 +1,390 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { normalizeWorktreeExecutionMetadata, } from "./worktreeExecutionMetadata.js";
4
+ export class NexusAutomationError extends Error {
5
+ constructor(message) {
6
+ super(message);
7
+ this.name = "NexusAutomationError";
8
+ }
9
+ }
10
+ export function nexusAutomationLedgerPath(projectRoot, config) {
11
+ return resolveAutomationStatePath(projectRoot, config.ledger.path, "automation.ledger.path");
12
+ }
13
+ export function nexusAutomationLockPath(projectRoot, config) {
14
+ return resolveAutomationStatePath(projectRoot, config.lock.path, "automation.lock.path");
15
+ }
16
+ export function emptyNexusAutomationRunLedger() {
17
+ return {
18
+ version: 1,
19
+ runs: [],
20
+ updatedAt: null,
21
+ };
22
+ }
23
+ export function readNexusAutomationRunLedger(projectRoot, config) {
24
+ const ledgerPath = nexusAutomationLedgerPath(projectRoot, config);
25
+ if (!fs.existsSync(ledgerPath)) {
26
+ return emptyNexusAutomationRunLedger();
27
+ }
28
+ return normalizeNexusAutomationRunLedger(JSON.parse(fs.readFileSync(ledgerPath, "utf8").replace(/^\uFEFF/, "")));
29
+ }
30
+ export function writeNexusAutomationRunLedger(projectRoot, config, ledger) {
31
+ const ledgerPath = nexusAutomationLedgerPath(projectRoot, config);
32
+ const normalized = normalizeNexusAutomationRunLedger(ledger);
33
+ fs.mkdirSync(path.dirname(ledgerPath), { recursive: true });
34
+ fs.writeFileSync(ledgerPath, `${JSON.stringify(normalized, null, 2)}\n`, "utf8");
35
+ return ledgerPath;
36
+ }
37
+ export function appendNexusAutomationRunRecord(options) {
38
+ const recordedAt = isoString(options.now ?? new Date());
39
+ const record = normalizeRunRecordInput(options.record, recordedAt);
40
+ const existing = readNexusAutomationRunLedger(options.projectRoot, options.config);
41
+ const runs = [...existing.runs, record].slice(-options.config.ledger.retention);
42
+ const ledger = {
43
+ version: 1,
44
+ runs,
45
+ updatedAt: recordedAt,
46
+ };
47
+ writeNexusAutomationRunLedger(options.projectRoot, options.config, ledger);
48
+ return ledger;
49
+ }
50
+ export function normalizeNexusAutomationRunLedger(value) {
51
+ if (value === undefined || value === null) {
52
+ return emptyNexusAutomationRunLedger();
53
+ }
54
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
55
+ throw new NexusAutomationError("automation run ledger must be an object");
56
+ }
57
+ const record = value;
58
+ if (record.version !== 1) {
59
+ throw new NexusAutomationError("automation run ledger.version must be 1");
60
+ }
61
+ if (!Array.isArray(record.runs)) {
62
+ throw new NexusAutomationError("automation run ledger.runs must be an array");
63
+ }
64
+ return {
65
+ version: 1,
66
+ runs: record.runs.map(normalizeRunRecord),
67
+ updatedAt: optionalNullableString(record.updatedAt) ?? null,
68
+ };
69
+ }
70
+ export function acquireNexusAutomationRunLock(options) {
71
+ const lockPath = nexusAutomationLockPath(options.projectRoot, options.config);
72
+ const runId = requiredNonEmptyString(options.runId, "runId");
73
+ const now = dateFrom(options.now ?? new Date(), "now");
74
+ const lock = {
75
+ runId,
76
+ owner: optionalNullableString(options.owner) ?? null,
77
+ acquiredAt: now.toISOString(),
78
+ expiresAt: new Date(now.getTime() + options.config.lock.staleAfterMs)
79
+ .toISOString(),
80
+ };
81
+ fs.mkdirSync(path.dirname(lockPath), { recursive: true });
82
+ const initial = tryWriteLock(lockPath, lock);
83
+ if (initial) {
84
+ return { lockPath, lock, replacedStaleLock: false };
85
+ }
86
+ const existing = readExistingLock(lockPath);
87
+ if (dateFrom(existing.expiresAt, "automation lock.expiresAt").getTime() > now.getTime()) {
88
+ throw new NexusAutomationError(`Automation run lock is already held by ${existing.runId} until ${existing.expiresAt}`);
89
+ }
90
+ fs.rmSync(lockPath, { force: true });
91
+ if (!tryWriteLock(lockPath, lock)) {
92
+ throw new NexusAutomationError(`Automation run lock could not be acquired: ${lockPath}`);
93
+ }
94
+ return { lockPath, lock, replacedStaleLock: true };
95
+ }
96
+ export function releaseNexusAutomationRunLock(options) {
97
+ const lockPath = nexusAutomationLockPath(options.projectRoot, options.config);
98
+ if (!fs.existsSync(lockPath)) {
99
+ return false;
100
+ }
101
+ if (options.runId) {
102
+ const existing = readExistingLock(lockPath);
103
+ if (existing.runId !== options.runId) {
104
+ return false;
105
+ }
106
+ }
107
+ fs.rmSync(lockPath, { force: true });
108
+ return true;
109
+ }
110
+ export function buildNexusAutomationWorkItemQuery(config) {
111
+ const selector = config.selector;
112
+ return {
113
+ status: selector.statuses,
114
+ ...(selector.labels.length ? { labels: selector.labels } : {}),
115
+ ...(selector.assignees.length ? { assignees: selector.assignees } : {}),
116
+ ...(selector.search ? { search: selector.search } : {}),
117
+ limit: selector.limit,
118
+ };
119
+ }
120
+ export function selectNexusAutomationWorkItem(items, config) {
121
+ return items.find((item) => matchesSelector(item, config.selector));
122
+ }
123
+ export function eligibleNexusAutomationWorkItems(items, config) {
124
+ return items.filter((item) => matchesSelector(item, config.selector));
125
+ }
126
+ export function evaluateNexusAutomationBackoff(config, consecutiveFailures, lastFailureAt) {
127
+ if (!Number.isInteger(consecutiveFailures) || consecutiveFailures < 0) {
128
+ throw new NexusAutomationError("consecutiveFailures must be a non-negative integer");
129
+ }
130
+ if (consecutiveFailures === 0) {
131
+ return {
132
+ consecutiveFailures,
133
+ shouldRun: true,
134
+ retryAfter: null,
135
+ delayMs: null,
136
+ reason: null,
137
+ };
138
+ }
139
+ if (consecutiveFailures >= config.backoff.failureLimit) {
140
+ return {
141
+ consecutiveFailures,
142
+ shouldRun: false,
143
+ retryAfter: null,
144
+ delayMs: null,
145
+ reason: `automation failure limit reached: ${consecutiveFailures}`,
146
+ };
147
+ }
148
+ const failedAt = dateFrom(lastFailureAt, "lastFailureAt");
149
+ const delayMs = Math.min(config.backoff.maxDelayMs, config.backoff.baseDelayMs * 2 ** (consecutiveFailures - 1));
150
+ return {
151
+ consecutiveFailures,
152
+ shouldRun: false,
153
+ retryAfter: new Date(failedAt.getTime() + delayMs).toISOString(),
154
+ delayMs,
155
+ reason: "automation retry backoff is active",
156
+ };
157
+ }
158
+ export function countConsecutiveNexusAutomationFailures(ledger) {
159
+ let failures = 0;
160
+ for (let index = ledger.runs.length - 1; index >= 0; index -= 1) {
161
+ const run = ledger.runs[index];
162
+ if (run.status === "skipped") {
163
+ continue;
164
+ }
165
+ if (run.status === "failed" || run.status === "blocked") {
166
+ failures += 1;
167
+ continue;
168
+ }
169
+ break;
170
+ }
171
+ return failures;
172
+ }
173
+ export function evaluateNexusAutomationLedgerBackoff(config, ledger, now = new Date()) {
174
+ const consecutiveFailures = countConsecutiveNexusAutomationFailures(ledger);
175
+ if (consecutiveFailures === 0) {
176
+ return {
177
+ consecutiveFailures,
178
+ shouldRun: true,
179
+ retryAfter: null,
180
+ delayMs: null,
181
+ reason: null,
182
+ };
183
+ }
184
+ const lastFailure = [...ledger.runs]
185
+ .reverse()
186
+ .find((run) => run.status === "failed" || run.status === "blocked");
187
+ if (!lastFailure) {
188
+ return {
189
+ consecutiveFailures: 0,
190
+ shouldRun: true,
191
+ retryAfter: null,
192
+ delayMs: null,
193
+ reason: null,
194
+ };
195
+ }
196
+ const decision = evaluateNexusAutomationBackoff(config, consecutiveFailures, lastFailure.finishedAt ?? lastFailure.startedAt);
197
+ if (!decision.retryAfter) {
198
+ return decision;
199
+ }
200
+ const retryAt = dateFrom(decision.retryAfter, "retryAfter");
201
+ if (dateFrom(now, "now").getTime() >= retryAt.getTime()) {
202
+ return {
203
+ ...decision,
204
+ shouldRun: true,
205
+ reason: null,
206
+ };
207
+ }
208
+ return decision;
209
+ }
210
+ function resolveAutomationStatePath(projectRoot, configuredPath, fieldName) {
211
+ const root = path.resolve(projectRoot);
212
+ const target = path.resolve(root, configuredPath);
213
+ const relative = path.relative(root, target);
214
+ if (!relative || relative.startsWith("..") || path.isAbsolute(relative)) {
215
+ throw new NexusAutomationError(`${fieldName} must resolve inside the project root: ${target}`);
216
+ }
217
+ return target;
218
+ }
219
+ function matchesSelector(item, selector) {
220
+ return (selector.statuses.includes(item.status) &&
221
+ includesAll(normalizeStringList(item.labels), selector.labels) &&
222
+ includesNone(normalizeStringList(item.labels), selector.excludeLabels) &&
223
+ includesAll(normalizeStringList(item.assignees), selector.assignees) &&
224
+ matchesSearch(item, selector.search));
225
+ }
226
+ function includesAll(values, expected) {
227
+ return expected.every((value) => values.has(value.toLowerCase()));
228
+ }
229
+ function includesNone(values, blocked) {
230
+ return blocked.every((value) => !values.has(value.toLowerCase()));
231
+ }
232
+ function normalizeStringList(values) {
233
+ return new Set((values ?? []).map((value) => value.toLowerCase()));
234
+ }
235
+ function matchesSearch(item, search) {
236
+ if (!search) {
237
+ return true;
238
+ }
239
+ const needle = search.toLowerCase();
240
+ return [item.id, item.title, item.description ?? ""].some((value) => value.toLowerCase().includes(needle));
241
+ }
242
+ function tryWriteLock(lockPath, lock) {
243
+ try {
244
+ const handle = fs.openSync(lockPath, "wx");
245
+ try {
246
+ fs.writeFileSync(handle, `${JSON.stringify(lock, null, 2)}\n`, "utf8");
247
+ }
248
+ finally {
249
+ fs.closeSync(handle);
250
+ }
251
+ return true;
252
+ }
253
+ catch (error) {
254
+ const code = error.code;
255
+ if (code === "EEXIST") {
256
+ return false;
257
+ }
258
+ throw error;
259
+ }
260
+ }
261
+ function readExistingLock(lockPath) {
262
+ return normalizeRunLock(JSON.parse(fs.readFileSync(lockPath, "utf8").replace(/^\uFEFF/, "")));
263
+ }
264
+ function normalizeRunLock(value) {
265
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
266
+ throw new NexusAutomationError("automation run lock must be an object");
267
+ }
268
+ const record = value;
269
+ return {
270
+ runId: requiredNonEmptyString(record.runId, "automation lock.runId"),
271
+ owner: optionalNullableString(record.owner) ?? null,
272
+ acquiredAt: requiredIsoString(record.acquiredAt, "automation lock.acquiredAt"),
273
+ expiresAt: requiredIsoString(record.expiresAt, "automation lock.expiresAt"),
274
+ };
275
+ }
276
+ function normalizeRunRecordInput(input, recordedAt) {
277
+ return normalizeRunRecord({
278
+ ...input,
279
+ startedAt: input.startedAt ?? recordedAt,
280
+ finishedAt: input.finishedAt ?? null,
281
+ componentId: input.componentId ?? null,
282
+ workItemId: input.workItemId ?? null,
283
+ workItemTitle: input.workItemTitle ?? null,
284
+ sourceRoot: input.sourceRoot ?? null,
285
+ worktreePath: input.worktreePath ?? null,
286
+ branchName: input.branchName ?? null,
287
+ baseRef: input.baseRef ?? null,
288
+ commitIds: input.commitIds ?? [],
289
+ summary: input.summary ?? null,
290
+ verification: input.verification ?? [],
291
+ publicationDecision: input.publicationDecision ?? null,
292
+ error: input.error ?? null,
293
+ nextRunNotBefore: input.nextRunNotBefore ?? null,
294
+ });
295
+ }
296
+ function normalizeRunRecord(value) {
297
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
298
+ throw new NexusAutomationError("automation run record must be an object");
299
+ }
300
+ const record = value;
301
+ return {
302
+ id: requiredNonEmptyString(record.id, "automation run.id"),
303
+ projectId: requiredNonEmptyString(record.projectId, "automation run.projectId"),
304
+ componentId: optionalNullableString(record.componentId) ?? null,
305
+ status: normalizeRunStatus(record.status, "automation run.status"),
306
+ startedAt: requiredIsoString(record.startedAt, "automation run.startedAt"),
307
+ finishedAt: optionalIsoString(record.finishedAt, "automation run.finishedAt"),
308
+ workItemId: optionalNullableString(record.workItemId) ?? null,
309
+ workItemTitle: optionalNullableString(record.workItemTitle) ?? null,
310
+ sourceRoot: optionalNullableString(record.sourceRoot) ?? null,
311
+ worktreePath: optionalNullableString(record.worktreePath) ?? null,
312
+ branchName: optionalNullableString(record.branchName) ?? null,
313
+ baseRef: optionalNullableString(record.baseRef) ?? null,
314
+ commitIds: normalizeStringArray(record.commitIds, "automation run.commitIds"),
315
+ summary: optionalNullableString(record.summary) ?? null,
316
+ verification: normalizeVerificationRecords(record.verification),
317
+ publicationDecision: normalizePublicationDecision(record.publicationDecision),
318
+ error: optionalNullableString(record.error) ?? null,
319
+ nextRunNotBefore: optionalIsoString(record.nextRunNotBefore, "automation run.nextRunNotBefore"),
320
+ };
321
+ }
322
+ function normalizeVerificationRecords(value) {
323
+ return normalizeWorktreeExecutionMetadata({
324
+ verification: value,
325
+ }).verification;
326
+ }
327
+ function normalizeStringArray(value, name) {
328
+ if (value === undefined || value === null) {
329
+ return [];
330
+ }
331
+ if (!Array.isArray(value)) {
332
+ throw new NexusAutomationError(`${name} must be an array`);
333
+ }
334
+ return value.map((item, index) => requiredNonEmptyString(item, `${name}[${index}]`));
335
+ }
336
+ function normalizePublicationDecision(value) {
337
+ if (value === undefined || value === null) {
338
+ return null;
339
+ }
340
+ return normalizeWorktreeExecutionMetadata({
341
+ publicationDecision: value,
342
+ }).publicationDecision;
343
+ }
344
+ function normalizeRunStatus(value, name) {
345
+ if (value === "started" ||
346
+ value === "completed" ||
347
+ value === "failed" ||
348
+ value === "blocked" ||
349
+ value === "skipped") {
350
+ return value;
351
+ }
352
+ throw new NexusAutomationError(`${name} must be started, completed, failed, blocked, or skipped`);
353
+ }
354
+ function optionalIsoString(value, name) {
355
+ const stringValue = optionalNullableString(value);
356
+ if (stringValue === undefined || stringValue === null) {
357
+ return null;
358
+ }
359
+ return requiredIsoString(stringValue, name);
360
+ }
361
+ function requiredIsoString(value, name) {
362
+ const stringValue = requiredNonEmptyString(value, name);
363
+ dateFrom(stringValue, name);
364
+ return stringValue;
365
+ }
366
+ function isoString(value) {
367
+ return dateFrom(value, "date").toISOString();
368
+ }
369
+ function dateFrom(value, name) {
370
+ const date = value instanceof Date ? value : new Date(value);
371
+ if (Number.isNaN(date.getTime())) {
372
+ throw new NexusAutomationError(`${name} must be a valid date`);
373
+ }
374
+ return date;
375
+ }
376
+ function optionalNullableString(value) {
377
+ if (value === undefined) {
378
+ return undefined;
379
+ }
380
+ if (value === null) {
381
+ return null;
382
+ }
383
+ return requiredNonEmptyString(value, "value");
384
+ }
385
+ function requiredNonEmptyString(value, name) {
386
+ if (typeof value !== "string" || value.trim().length === 0) {
387
+ throw new NexusAutomationError(`${name} must be a non-empty string`);
388
+ }
389
+ return value.trim();
390
+ }
@@ -0,0 +1,148 @@
1
+ import { type AcquireNexusAutomationRunLockResult, type NexusAutomationRunLedger, type NexusAutomationRunStatus } from "./nexusAutomation.js";
2
+ import { type NexusAutomationCommandRunner } from "./nexusAutomationCommandExecutor.js";
3
+ import type { NexusAutomationConfig } from "./nexusAutomationConfig.js";
4
+ import { type NexusAutomationAgentPolicy } from "./nexusAutomationAgentProfile.js";
5
+ import { type NexusPluginCapabilityProjection } from "./nexusPluginCapabilities.js";
6
+ import { type NexusProjectConfig } from "./nexusProjectConfig.js";
7
+ import { type NexusAutomationTargetContext } from "./nexusAutomationTarget.js";
8
+ import { type ResolvedNexusProjectComponent } from "./nexusProjectLifecycle.js";
9
+ import type { NexusAutomationPreflightCheck, NexusAutomationWorkTrackerProviderFactory } from "./nexusAutomationRunOnce.js";
10
+ import { type CreateWorkTrackerProviderOptions } from "./workTrackingProviderService.js";
11
+ import type { WorkItem, WorkItemQuery, WorkTrackerProvider } from "./workTrackingTypes.js";
12
+ import type { WorktreePublicationDecisionInput, WorktreeVerificationInput, WorktreeVerificationStatus } from "./worktreeExecutionMetadata.js";
13
+ export type NexusAutomationAgentLaunchStatus = "completed" | "failed" | "blocked";
14
+ export interface NexusAutomationAgentLaunchComponentContext {
15
+ id: string;
16
+ name: string;
17
+ role: ResolvedNexusProjectComponent["role"];
18
+ kind: ResolvedNexusProjectComponent["kind"];
19
+ sourceRoot: string;
20
+ sourceRootExists: boolean;
21
+ worktreesRoot: string;
22
+ worktreesRootExists: boolean;
23
+ remoteUrl: string | null;
24
+ defaultBranch: string | null;
25
+ workTracker: {
26
+ provider: string | null;
27
+ configured: boolean;
28
+ };
29
+ relationships: ResolvedNexusProjectComponent["relationships"];
30
+ }
31
+ export interface NexusAutomationComponentEligibleWorkItems {
32
+ componentId: string;
33
+ workItems: WorkItem[];
34
+ }
35
+ export interface NexusAutomationAgentLaunchContext {
36
+ version: 1;
37
+ runId: string;
38
+ startedAt: string;
39
+ projectRoot: string;
40
+ sourceRoot: string;
41
+ project: {
42
+ id: string;
43
+ name: string;
44
+ componentCount: number;
45
+ };
46
+ components: NexusAutomationAgentLaunchComponentContext[];
47
+ automation: {
48
+ mode: "agent_launch";
49
+ selectorQuery: WorkItemQuery;
50
+ eligibleWorkItemCount: number;
51
+ };
52
+ target: NexusAutomationTargetContext;
53
+ agent: {
54
+ coordinatorProfileId: string | null;
55
+ maxConcurrentSubagents: number;
56
+ safety: NexusAutomationAgentPolicy["safety"];
57
+ coordinatorProfile: NexusAutomationAgentPolicy["coordinatorProfile"];
58
+ profiles: NexusAutomationAgentPolicy["profiles"];
59
+ };
60
+ pluginCapabilities: NexusPluginCapabilityProjection[];
61
+ result: NexusAutomationAgentResultContract;
62
+ eligibleWorkItems: WorkItem[];
63
+ componentEligibleWorkItems: NexusAutomationComponentEligibleWorkItems[];
64
+ safety: NexusAutomationConfig["safety"];
65
+ publication: NexusAutomationConfig["publication"];
66
+ }
67
+ export interface NexusAutomationAgentResultContract {
68
+ file: string;
69
+ requiredFields: string[];
70
+ optionalFields: string[];
71
+ statuses: NexusAutomationAgentLaunchStatus[];
72
+ verificationStatuses: WorktreeVerificationStatus[];
73
+ publicationDecisionTypes: WorktreePublicationDecisionInput["type"][];
74
+ }
75
+ export interface NexusAutomationAgentLaunchInput {
76
+ runId: string;
77
+ startedAt: string;
78
+ projectRoot: string;
79
+ sourceRoot: string;
80
+ components: ResolvedNexusProjectComponent[];
81
+ projectConfig: NexusProjectConfig;
82
+ automationConfig: NexusAutomationConfig;
83
+ selectorQuery: WorkItemQuery;
84
+ eligibleWorkItems: WorkItem[];
85
+ componentEligibleWorkItems: NexusAutomationComponentEligibleWorkItems[];
86
+ contextFile: string;
87
+ resultFile: string;
88
+ }
89
+ export interface NexusAutomationAgentLaunchResult {
90
+ status?: NexusAutomationAgentLaunchStatus;
91
+ summary?: string | null;
92
+ commitIds?: string[];
93
+ verification?: WorktreeVerificationInput[];
94
+ publicationDecision?: WorktreePublicationDecisionInput;
95
+ error?: string | null;
96
+ }
97
+ export type NexusAutomationAgentLauncher = (input: NexusAutomationAgentLaunchInput) => NexusAutomationAgentLaunchResult | Promise<NexusAutomationAgentLaunchResult>;
98
+ export interface CreateNexusAutomationAgentCommandLauncherOptions {
99
+ command: string;
100
+ commandRunner?: NexusAutomationCommandRunner;
101
+ env?: NodeJS.ProcessEnv;
102
+ timeoutMs?: number;
103
+ }
104
+ export interface RunNexusAutomationAgentLaunchOnceOptions {
105
+ projectRoot: string;
106
+ homePath?: string;
107
+ runId?: string;
108
+ owner?: string | null;
109
+ provider?: WorkTrackerProvider;
110
+ providerFactory?: NexusAutomationWorkTrackerProviderFactory;
111
+ providerOptions?: CreateWorkTrackerProviderOptions;
112
+ now?: () => Date | string;
113
+ launcher: NexusAutomationAgentLauncher;
114
+ }
115
+ export interface RunNexusAutomationAgentLaunchOnceResult {
116
+ runId: string;
117
+ projectRoot: string;
118
+ sourceRoot: string | null;
119
+ projectConfig: NexusProjectConfig;
120
+ automationConfig: NexusAutomationConfig | null;
121
+ status: NexusAutomationRunStatus;
122
+ summary: string;
123
+ ledger: NexusAutomationRunLedger | null;
124
+ lock: AcquireNexusAutomationRunLockResult | null;
125
+ preflight: NexusAutomationPreflightCheck[];
126
+ selectorQuery: WorkItemQuery | null;
127
+ eligibleWorkItems: WorkItem[];
128
+ componentEligibleWorkItems: NexusAutomationComponentEligibleWorkItems[];
129
+ components: ResolvedNexusProjectComponent[];
130
+ contextFile: string | null;
131
+ resultFile: string | null;
132
+ launch: NexusAutomationAgentLaunchResult | null;
133
+ }
134
+ export interface NexusAutomationAgentLaunchComponentProvider {
135
+ component: ResolvedNexusProjectComponent;
136
+ provider: WorkTrackerProvider;
137
+ }
138
+ export declare class NexusAutomationAgentLaunchError extends Error {
139
+ constructor(message: string);
140
+ }
141
+ export declare function runNexusAutomationAgentLaunchOnce(options: RunNexusAutomationAgentLaunchOnceOptions): Promise<RunNexusAutomationAgentLaunchOnceResult>;
142
+ export declare function createNexusAutomationAgentCommandLauncher(options: CreateNexusAutomationAgentCommandLauncherOptions): NexusAutomationAgentLauncher;
143
+ export declare function preflightNexusAutomationAgentLaunch(options: {
144
+ components: ResolvedNexusProjectComponent[];
145
+ componentProviders: NexusAutomationAgentLaunchComponentProvider[];
146
+ automationConfig: NexusAutomationConfig;
147
+ }): NexusAutomationPreflightCheck[];
148
+ export declare function generateNexusAutomationAgentRunId(now?: () => Date | string): string;