archondev 3.0.1 → 3.1.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/README.md +27 -32
- package/dist/auth-ZMBA5HYH.js +13 -0
- package/dist/{bug-TFICZ4OP.js → bug-MOMNYU5J.js} +2 -2
- package/dist/{chunk-43IIEFB2.js → chunk-7ELR6RW6.js} +1 -1
- package/dist/{chunk-IG3H7C7R.js → chunk-ARHCVLQW.js} +4 -4
- package/dist/chunk-AWHINKO2.js +244 -0
- package/dist/{chunk-7RXZTPXY.js → chunk-BSG5XY3C.js} +6 -6
- package/dist/{chunk-AJNKSFHL.js → chunk-CI5E4EX3.js} +80 -5
- package/dist/{chunk-4TZOCXAI.js → chunk-ECEWULAA.js} +1 -1
- package/dist/chunk-EF66S6ZQ.js +1189 -0
- package/dist/chunk-EV5QU5KG.js +18 -0
- package/dist/{chunk-45T2VB5R.js → chunk-IZFUFXDN.js} +98 -237
- package/dist/{chunk-YK5Z6U5A.js → chunk-LE5EJ6I4.js} +23 -20
- package/dist/{chunk-PQS3TQB6.js → chunk-LSLQIPLQ.js} +6 -6
- package/dist/chunk-NQBS7L2F.js +55 -0
- package/dist/chunk-RAM67KA6.js +57 -0
- package/dist/{chunk-Q3GIFHIQ.js → client-PPPOHAVY.js} +4 -3
- package/dist/constants-BES4STNW.js +11 -0
- package/dist/{execute-HWUL2M3B.js → execute-WSCLLLY6.js} +4 -4
- package/dist/geo-IRUGSLZS.js +50 -0
- package/dist/index.js +760 -1239
- package/dist/{interviewer-ZGKR7YQQ.js → interviewer-ZUYQ5ZFJ.js} +2 -2
- package/dist/{keys-3PRAVIRC.js → keys-SQUTA4L2.js} +2 -2
- package/dist/{list-7IBMJCCF.js → list-HZM7DNVS.js} +4 -4
- package/dist/{parallel-4PXJA2QD.js → parallel-MWPBKEEN.js} +5 -6
- package/dist/{plan-HBAUG3KD.js → plan-3Z6M4LE6.js} +3 -3
- package/dist/{preferences-VVFGRNPD.js → preferences-OXVXWARL.js} +2 -2
- package/dist/{ship-KHL6NVC2.js → ship-CTZU6RYR.js} +1 -1
- package/dist/{chunk-ONH6Y3CS.js → tier-selection-5KPN2RF2.js} +7 -28
- package/dist/truth-layer-7N32HKCE.js +19 -0
- package/package.json +2 -2
- package/dist/auth-T4C7OQWO.js +0 -14
- package/dist/chunk-57NSGWWD.js +0 -270
- package/dist/chunk-CFJECC3B.js +0 -495
- package/dist/chunk-GGRW4NTA.js +0 -118
- package/dist/chunk-M4LGRTLC.js +0 -10
- package/dist/client-PHW2C2HB.js +0 -11
- package/dist/constants-XDIWFFPN.js +0 -11
- package/dist/geo-BWH5PUBK.js +0 -20
- package/dist/tier-selection-O5AFLKD6.js +0 -18
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// src/cli/retired-remote.ts
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
function printRetiredRemotePath(featureName) {
|
|
4
|
+
console.log(chalk.yellow(`${featureName} has been retired.`));
|
|
5
|
+
console.log(chalk.dim("ArchonDev now runs as Free download/governance mode or local BYOK CLI AI."));
|
|
6
|
+
console.log(chalk.dim("Use local provider keys with: archon config ai"));
|
|
7
|
+
console.log(chalk.dim("View local BYOK usage with: archon usage"));
|
|
8
|
+
}
|
|
9
|
+
function retiredRemoteError(featureName) {
|
|
10
|
+
return new Error(
|
|
11
|
+
`${featureName} has been retired. Run locally with BYOK keys instead.`
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export {
|
|
16
|
+
printRetiredRemotePath,
|
|
17
|
+
retiredRemoteError
|
|
18
|
+
};
|
|
@@ -1,21 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
printRetiredRemotePath,
|
|
3
|
+
retiredRemoteError
|
|
4
|
+
} from "./chunk-EV5QU5KG.js";
|
|
4
5
|
import {
|
|
5
6
|
listLocalAtoms,
|
|
6
7
|
loadAtom
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-BSG5XY3C.js";
|
|
8
9
|
import {
|
|
9
|
-
SUPABASE_ANON_KEY,
|
|
10
|
-
SUPABASE_URL
|
|
11
|
-
} from "./chunk-M4LGRTLC.js";
|
|
12
|
-
import {
|
|
13
|
-
getAuthToken,
|
|
14
10
|
loadConfig
|
|
15
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-NQBS7L2F.js";
|
|
16
12
|
|
|
17
13
|
// src/cli/parallel.ts
|
|
18
|
-
import
|
|
14
|
+
import chalk from "chalk";
|
|
19
15
|
import { spawn } from "child_process";
|
|
20
16
|
import { existsSync as existsSync2 } from "fs";
|
|
21
17
|
import { readFile, writeFile } from "fs/promises";
|
|
@@ -357,139 +353,21 @@ function formatAsMermaid(graph) {
|
|
|
357
353
|
}
|
|
358
354
|
|
|
359
355
|
// src/cli/cloud.ts
|
|
360
|
-
import
|
|
361
|
-
function getClient(accessToken) {
|
|
362
|
-
return createAuthedSupabaseClient(SUPABASE_URL, SUPABASE_ANON_KEY, accessToken);
|
|
363
|
-
}
|
|
356
|
+
import { execSync as execSync2 } from "child_process";
|
|
364
357
|
async function cloudStatus() {
|
|
365
|
-
|
|
366
|
-
const authToken = getAuthToken(config);
|
|
367
|
-
if (!authToken) {
|
|
368
|
-
console.error(chalk.red('Not authenticated. Run "archon login" first.'));
|
|
369
|
-
process.exit(1);
|
|
370
|
-
}
|
|
371
|
-
const client = getClient(authToken);
|
|
372
|
-
const { data, error } = await client.from("cloud_executions").select("*").order("created_at", { ascending: false }).limit(20);
|
|
373
|
-
if (error) {
|
|
374
|
-
console.error(chalk.red("Failed to fetch cloud executions:"), error.message);
|
|
375
|
-
process.exit(1);
|
|
376
|
-
}
|
|
377
|
-
if (!data || data.length === 0) {
|
|
378
|
-
console.log(chalk.dim("No cloud executions found."));
|
|
379
|
-
return;
|
|
380
|
-
}
|
|
381
|
-
console.log(chalk.bold("\nCloud Executions:\n"));
|
|
382
|
-
for (const exec of data) {
|
|
383
|
-
const statusIcon = getStatusIcon(exec.status);
|
|
384
|
-
const duration = exec.compute_minutes ? `${exec.compute_minutes} min` : "-";
|
|
385
|
-
console.log(`${statusIcon} ${chalk.bold(exec.id.slice(0, 8))} - ${exec.atom_id}`);
|
|
386
|
-
console.log(chalk.dim(` Project: ${exec.project_name ?? "unknown"}`));
|
|
387
|
-
console.log(chalk.dim(` Status: ${exec.status} | Duration: ${duration}`));
|
|
388
|
-
if (exec.result_branch) {
|
|
389
|
-
console.log(chalk.dim(` Branch: ${exec.result_branch}`));
|
|
390
|
-
}
|
|
391
|
-
if (exec.result_pr_url) {
|
|
392
|
-
console.log(chalk.dim(` PR: ${exec.result_pr_url}`));
|
|
393
|
-
}
|
|
394
|
-
if (exec.error_message) {
|
|
395
|
-
console.log(chalk.red(` Error: ${exec.error_message}`));
|
|
396
|
-
}
|
|
397
|
-
console.log();
|
|
398
|
-
}
|
|
358
|
+
printRetiredRemotePath("Cloud execution");
|
|
399
359
|
}
|
|
400
|
-
async function cloudCancel(
|
|
401
|
-
|
|
402
|
-
const authToken = getAuthToken(config);
|
|
403
|
-
if (!authToken) {
|
|
404
|
-
console.error(chalk.red('Not authenticated. Run "archon login" first.'));
|
|
405
|
-
process.exit(1);
|
|
406
|
-
}
|
|
407
|
-
const client = getClient(authToken);
|
|
408
|
-
const { data: existing, error: fetchError } = await client.from("cloud_executions").select("id, status").eq("id", executionId).single();
|
|
409
|
-
if (fetchError || !existing) {
|
|
410
|
-
console.error(chalk.red(`Execution ${executionId} not found.`));
|
|
411
|
-
process.exit(1);
|
|
412
|
-
}
|
|
413
|
-
if (existing.status === "completed" || existing.status === "failed" || existing.status === "cancelled") {
|
|
414
|
-
console.log(chalk.yellow(`Execution is already ${existing.status}. Cannot cancel.`));
|
|
415
|
-
return;
|
|
416
|
-
}
|
|
417
|
-
const { error } = await client.from("cloud_executions").update({ status: "cancelled" }).eq("id", executionId);
|
|
418
|
-
if (error) {
|
|
419
|
-
console.error(chalk.red("Failed to cancel execution:"), error.message);
|
|
420
|
-
process.exit(1);
|
|
421
|
-
}
|
|
422
|
-
console.log(chalk.green(`\u2713 Execution ${executionId.slice(0, 8)} cancelled.`));
|
|
360
|
+
async function cloudCancel(_executionId) {
|
|
361
|
+
printRetiredRemotePath("Cloud execution");
|
|
423
362
|
}
|
|
424
|
-
async function cloudLogs(
|
|
425
|
-
|
|
426
|
-
const authToken = getAuthToken(config);
|
|
427
|
-
if (!authToken) {
|
|
428
|
-
console.error(chalk.red('Not authenticated. Run "archon login" first.'));
|
|
429
|
-
process.exit(1);
|
|
430
|
-
}
|
|
431
|
-
const client = getClient(authToken);
|
|
432
|
-
const { data, error } = await client.from("cloud_executions").select("id, atom_id, status, logs").eq("id", executionId).single();
|
|
433
|
-
if (error || !data) {
|
|
434
|
-
console.error(chalk.red(`Execution ${executionId} not found.`));
|
|
435
|
-
process.exit(1);
|
|
436
|
-
}
|
|
437
|
-
const exec = data;
|
|
438
|
-
console.log(chalk.bold(`
|
|
439
|
-
Logs for ${exec.id.slice(0, 8)} (${exec.atom_id}):
|
|
440
|
-
`));
|
|
441
|
-
console.log(chalk.dim(`Status: ${exec.status}
|
|
442
|
-
`));
|
|
443
|
-
const logs = exec.logs;
|
|
444
|
-
if (!logs || logs.length === 0) {
|
|
445
|
-
console.log(chalk.dim("No logs available yet."));
|
|
446
|
-
return;
|
|
447
|
-
}
|
|
448
|
-
for (const log of logs) {
|
|
449
|
-
const ts = log.timestamp ? chalk.dim(`[${log.timestamp}]`) : "";
|
|
450
|
-
const level = log.level === "error" ? chalk.red("ERROR") : log.level === "warn" ? chalk.yellow("WARN") : chalk.dim("INFO");
|
|
451
|
-
console.log(`${ts} ${level} ${log.message}`);
|
|
452
|
-
}
|
|
363
|
+
async function cloudLogs(_executionId) {
|
|
364
|
+
printRetiredRemotePath("Cloud execution");
|
|
453
365
|
}
|
|
454
|
-
async function queueCloudExecution(
|
|
455
|
-
|
|
456
|
-
const authToken = getAuthToken(config);
|
|
457
|
-
if (!authToken) {
|
|
458
|
-
throw new Error('Not authenticated. Run "archon login" first.');
|
|
459
|
-
}
|
|
460
|
-
const client = getClient(authToken);
|
|
461
|
-
if (config.userId) {
|
|
462
|
-
const { data: profile, error: profileError } = await client.from("user_profiles").select("tier").eq("auth_id", config.userId).single();
|
|
463
|
-
if (profileError || !profile) {
|
|
464
|
-
throw new Error("Unable to verify billing tier. Try again or re-login.");
|
|
465
|
-
}
|
|
466
|
-
if (profile.tier !== "CREDITS") {
|
|
467
|
-
throw new Error("Cloud execution requires Credits tier. BYOK and Free run locally.");
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
const insertData = {
|
|
471
|
-
atom_id: atomId,
|
|
472
|
-
project_name: projectName,
|
|
473
|
-
status: "queued"
|
|
474
|
-
};
|
|
475
|
-
if (options?.repoUrl) {
|
|
476
|
-
insertData["repo_url"] = options.repoUrl;
|
|
477
|
-
}
|
|
478
|
-
if (options?.repoBranch) {
|
|
479
|
-
insertData["repo_branch"] = options.repoBranch;
|
|
480
|
-
}
|
|
481
|
-
if (options?.atomData) {
|
|
482
|
-
insertData["atom_data"] = options.atomData;
|
|
483
|
-
}
|
|
484
|
-
const { data, error } = await client.from("cloud_executions").insert(insertData).select("id").single();
|
|
485
|
-
if (error) {
|
|
486
|
-
throw new Error(`Failed to queue execution: ${error.message}`);
|
|
487
|
-
}
|
|
488
|
-
return data.id;
|
|
366
|
+
async function queueCloudExecution(_atomId, _projectName, _options) {
|
|
367
|
+
throw retiredRemoteError("Cloud execution");
|
|
489
368
|
}
|
|
490
369
|
async function getGitRemoteUrl(cwd = process.cwd()) {
|
|
491
370
|
try {
|
|
492
|
-
const { execSync: execSync2 } = await import("child_process");
|
|
493
371
|
const output = execSync2("git remote get-url origin", { cwd, encoding: "utf-8" });
|
|
494
372
|
return output.trim();
|
|
495
373
|
} catch {
|
|
@@ -498,29 +376,12 @@ async function getGitRemoteUrl(cwd = process.cwd()) {
|
|
|
498
376
|
}
|
|
499
377
|
async function getGitBranch(cwd = process.cwd()) {
|
|
500
378
|
try {
|
|
501
|
-
const { execSync: execSync2 } = await import("child_process");
|
|
502
379
|
const output = execSync2("git branch --show-current", { cwd, encoding: "utf-8" });
|
|
503
380
|
return output.trim() || "main";
|
|
504
381
|
} catch {
|
|
505
382
|
return "main";
|
|
506
383
|
}
|
|
507
384
|
}
|
|
508
|
-
function getStatusIcon(status) {
|
|
509
|
-
switch (status) {
|
|
510
|
-
case "queued":
|
|
511
|
-
return chalk.blue("\u23F3");
|
|
512
|
-
case "running":
|
|
513
|
-
return chalk.yellow("\u{1F504}");
|
|
514
|
-
case "completed":
|
|
515
|
-
return chalk.green("\u2713");
|
|
516
|
-
case "failed":
|
|
517
|
-
return chalk.red("\u2717");
|
|
518
|
-
case "cancelled":
|
|
519
|
-
return chalk.gray("\u2298");
|
|
520
|
-
default:
|
|
521
|
-
return chalk.dim("?");
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
385
|
|
|
525
386
|
// src/cli/parallel.ts
|
|
526
387
|
var PARALLEL_STATE_FILE = ".archon/parallel-state.json";
|
|
@@ -539,36 +400,36 @@ async function saveParallelState(cwd, state) {
|
|
|
539
400
|
async function parallelExecute(atomIds, options = {}) {
|
|
540
401
|
const cwd = process.cwd();
|
|
541
402
|
const manager = new WorktreeManager(cwd);
|
|
542
|
-
console.log(
|
|
403
|
+
console.log(chalk.blue(`
|
|
543
404
|
\u{1F680} Starting parallel execution of ${atomIds.length} atoms...
|
|
544
405
|
`));
|
|
545
406
|
const state = await loadParallelState(cwd);
|
|
546
407
|
for (const atomId of atomIds) {
|
|
547
408
|
const atom = await loadAtom(atomId);
|
|
548
409
|
if (!atom) {
|
|
549
|
-
console.error(
|
|
410
|
+
console.error(chalk.red(`Atom ${atomId} not found. Skipping.`));
|
|
550
411
|
continue;
|
|
551
412
|
}
|
|
552
413
|
if (atom.status !== "READY") {
|
|
553
|
-
console.log(
|
|
414
|
+
console.log(chalk.yellow(`Atom ${atomId} is not READY (status: ${atom.status}). Skipping.`));
|
|
554
415
|
continue;
|
|
555
416
|
}
|
|
556
417
|
try {
|
|
557
|
-
console.log(
|
|
418
|
+
console.log(chalk.dim(`Creating worktree for ${atomId}...`));
|
|
558
419
|
const worktreePath = await manager.createWorktree(atomId);
|
|
559
420
|
state.executions.push({
|
|
560
421
|
atomId,
|
|
561
422
|
worktreePath,
|
|
562
423
|
status: "pending"
|
|
563
424
|
});
|
|
564
|
-
console.log(
|
|
425
|
+
console.log(chalk.green(`\u2713 Created worktree: ${worktreePath}`));
|
|
565
426
|
} catch (error) {
|
|
566
|
-
console.error(
|
|
567
|
-
console.error(
|
|
427
|
+
console.error(chalk.red(`Failed to create worktree for ${atomId}:`));
|
|
428
|
+
console.error(chalk.dim(error instanceof Error ? error.message : "Unknown error"));
|
|
568
429
|
}
|
|
569
430
|
}
|
|
570
431
|
await saveParallelState(cwd, state);
|
|
571
|
-
console.log(
|
|
432
|
+
console.log(chalk.dim("\nStarting parallel execution..."));
|
|
572
433
|
const promises = state.executions.filter((e) => e.status === "pending").map(async (execution) => {
|
|
573
434
|
execution.status = "running";
|
|
574
435
|
execution.startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -593,11 +454,11 @@ async function parallelExecute(atomIds, options = {}) {
|
|
|
593
454
|
execution.completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
594
455
|
if (code === 0) {
|
|
595
456
|
execution.status = "completed";
|
|
596
|
-
console.log(
|
|
457
|
+
console.log(chalk.green(`\u2713 ${execution.atomId} completed`));
|
|
597
458
|
} else {
|
|
598
459
|
execution.status = "failed";
|
|
599
460
|
execution.error = output.slice(-500);
|
|
600
|
-
console.log(
|
|
461
|
+
console.log(chalk.red(`\u2717 ${execution.atomId} failed`));
|
|
601
462
|
}
|
|
602
463
|
await saveParallelState(cwd, state);
|
|
603
464
|
resolve();
|
|
@@ -607,46 +468,46 @@ async function parallelExecute(atomIds, options = {}) {
|
|
|
607
468
|
await Promise.all(promises);
|
|
608
469
|
const completed = state.executions.filter((e) => e.status === "completed").length;
|
|
609
470
|
const failed = state.executions.filter((e) => e.status === "failed").length;
|
|
610
|
-
console.log(
|
|
471
|
+
console.log(chalk.blue(`
|
|
611
472
|
Parallel execution complete:`));
|
|
612
|
-
console.log(
|
|
473
|
+
console.log(chalk.green(` \u2713 Completed: ${completed}`));
|
|
613
474
|
if (failed > 0) {
|
|
614
|
-
console.log(
|
|
475
|
+
console.log(chalk.red(` \u2717 Failed: ${failed}`));
|
|
615
476
|
}
|
|
616
|
-
console.log(
|
|
477
|
+
console.log(chalk.dim(`
|
|
617
478
|
Run "archon parallel status" to see details.`));
|
|
618
|
-
console.log(
|
|
479
|
+
console.log(chalk.dim(`Run "archon parallel merge" to merge completed worktrees.`));
|
|
619
480
|
}
|
|
620
481
|
async function parallelExecuteCloud(atomIds) {
|
|
621
482
|
const cwd = process.cwd();
|
|
622
483
|
const config = await loadConfig();
|
|
623
484
|
const tier = config.tier ?? "FREE";
|
|
624
|
-
if (tier
|
|
625
|
-
console.log(
|
|
626
|
-
console.log(
|
|
627
|
-
console.log(
|
|
485
|
+
if (tier === "FREE" || tier === "BYOK") {
|
|
486
|
+
console.log(chalk.red("\nCloud execution is retired in the Free/BYOK model."));
|
|
487
|
+
console.log(chalk.dim("Free mode and BYOK mode run locally only."));
|
|
488
|
+
console.log(chalk.dim("Run without cloud execution to use your local provider keys."));
|
|
628
489
|
process.exit(1);
|
|
629
490
|
}
|
|
630
491
|
const projectName = basename(cwd);
|
|
631
492
|
const repoUrl = await getGitRemoteUrl(cwd);
|
|
632
493
|
const repoBranch = await getGitBranch(cwd);
|
|
633
494
|
if (!repoUrl) {
|
|
634
|
-
console.error(
|
|
635
|
-
console.log(
|
|
495
|
+
console.error(chalk.red("No git remote found. Cloud execution requires a GitHub repository."));
|
|
496
|
+
console.log(chalk.dim("Add a remote with: git remote add origin <url>"));
|
|
636
497
|
process.exit(1);
|
|
637
498
|
}
|
|
638
|
-
console.log(
|
|
499
|
+
console.log(chalk.blue(`
|
|
639
500
|
\u2601\uFE0F Queueing ${atomIds.length} cloud execution(s)...
|
|
640
501
|
`));
|
|
641
502
|
const queued = [];
|
|
642
503
|
for (const atomId of atomIds) {
|
|
643
504
|
const atom = await loadAtom(atomId);
|
|
644
505
|
if (!atom) {
|
|
645
|
-
console.error(
|
|
506
|
+
console.error(chalk.red(`Atom ${atomId} not found. Skipping.`));
|
|
646
507
|
continue;
|
|
647
508
|
}
|
|
648
509
|
if (atom.status !== "READY") {
|
|
649
|
-
console.log(
|
|
510
|
+
console.log(chalk.yellow(`Atom ${atomId} is not READY (status: ${atom.status}). Skipping.`));
|
|
650
511
|
continue;
|
|
651
512
|
}
|
|
652
513
|
try {
|
|
@@ -656,42 +517,42 @@ async function parallelExecuteCloud(atomIds) {
|
|
|
656
517
|
atomData: atom
|
|
657
518
|
});
|
|
658
519
|
queued.push({ atomId, executionId });
|
|
659
|
-
console.log(
|
|
520
|
+
console.log(chalk.green(`\u2713 ${atomId} queued (${executionId.slice(0, 8)})`));
|
|
660
521
|
} catch (error) {
|
|
661
|
-
console.error(
|
|
662
|
-
console.error(
|
|
522
|
+
console.error(chalk.red(`Failed to queue ${atomId}:`));
|
|
523
|
+
console.error(chalk.dim(error instanceof Error ? error.message : "Unknown error"));
|
|
663
524
|
}
|
|
664
525
|
}
|
|
665
526
|
if (queued.length === 0) {
|
|
666
|
-
console.log(
|
|
527
|
+
console.log(chalk.dim("\nNo executions were queued."));
|
|
667
528
|
return;
|
|
668
529
|
}
|
|
669
|
-
console.log(
|
|
670
|
-
console.log(
|
|
671
|
-
console.log(
|
|
672
|
-
console.log(
|
|
530
|
+
console.log(chalk.dim("\nCheck progress with:"));
|
|
531
|
+
console.log(chalk.bold(" archon cloud status"));
|
|
532
|
+
console.log(chalk.dim("View logs with:"));
|
|
533
|
+
console.log(chalk.bold(" archon cloud logs <id>"));
|
|
673
534
|
}
|
|
674
535
|
async function parallelStatus() {
|
|
675
536
|
const cwd = process.cwd();
|
|
676
537
|
const state = await loadParallelState(cwd);
|
|
677
538
|
if (state.executions.length === 0) {
|
|
678
|
-
console.log(
|
|
539
|
+
console.log(chalk.dim("No parallel executions found."));
|
|
679
540
|
return;
|
|
680
541
|
}
|
|
681
|
-
console.log(
|
|
542
|
+
console.log(chalk.blue("\nParallel Execution Status\n"));
|
|
682
543
|
for (const execution of state.executions) {
|
|
683
|
-
const statusIcon = execution.status === "completed" ?
|
|
544
|
+
const statusIcon = execution.status === "completed" ? chalk.green("\u2713") : execution.status === "failed" ? chalk.red("\u2717") : execution.status === "running" ? chalk.yellow("\u25CF") : chalk.dim("\u25CB");
|
|
684
545
|
console.log(`${statusIcon} ${execution.atomId}`);
|
|
685
|
-
console.log(
|
|
686
|
-
console.log(
|
|
546
|
+
console.log(chalk.dim(` Path: ${execution.worktreePath}`));
|
|
547
|
+
console.log(chalk.dim(` Status: ${execution.status}`));
|
|
687
548
|
if (execution.startedAt) {
|
|
688
|
-
console.log(
|
|
549
|
+
console.log(chalk.dim(` Started: ${execution.startedAt}`));
|
|
689
550
|
}
|
|
690
551
|
if (execution.completedAt) {
|
|
691
|
-
console.log(
|
|
552
|
+
console.log(chalk.dim(` Completed: ${execution.completedAt}`));
|
|
692
553
|
}
|
|
693
554
|
if (execution.error) {
|
|
694
|
-
console.log(
|
|
555
|
+
console.log(chalk.red(` Error: ${execution.error.slice(0, 100)}...`));
|
|
695
556
|
}
|
|
696
557
|
console.log();
|
|
697
558
|
}
|
|
@@ -702,49 +563,49 @@ async function parallelMerge(atomId) {
|
|
|
702
563
|
const state = await loadParallelState(cwd);
|
|
703
564
|
const toMerge = atomId ? state.executions.filter((e) => e.atomId === atomId && e.status === "completed") : state.executions.filter((e) => e.status === "completed");
|
|
704
565
|
if (toMerge.length === 0) {
|
|
705
|
-
console.log(
|
|
566
|
+
console.log(chalk.yellow("No completed executions to merge."));
|
|
706
567
|
return;
|
|
707
568
|
}
|
|
708
|
-
console.log(
|
|
569
|
+
console.log(chalk.blue(`
|
|
709
570
|
\u{1F500} Merging ${toMerge.length} completed worktree(s)...
|
|
710
571
|
`));
|
|
711
572
|
for (const execution of toMerge) {
|
|
712
573
|
try {
|
|
713
|
-
console.log(
|
|
574
|
+
console.log(chalk.dim(`Merging ${execution.atomId}...`));
|
|
714
575
|
await manager.mergeWorktree(execution.atomId);
|
|
715
|
-
console.log(
|
|
716
|
-
console.log(
|
|
576
|
+
console.log(chalk.green(`\u2713 Merged ${execution.atomId}`));
|
|
577
|
+
console.log(chalk.dim(`Cleaning up worktree...`));
|
|
717
578
|
await manager.removeWorktree(execution.atomId);
|
|
718
|
-
console.log(
|
|
579
|
+
console.log(chalk.green(`\u2713 Removed worktree for ${execution.atomId}`));
|
|
719
580
|
state.executions = state.executions.filter((e) => e.atomId !== execution.atomId);
|
|
720
581
|
} catch (error) {
|
|
721
|
-
console.error(
|
|
722
|
-
console.error(
|
|
723
|
-
console.log(
|
|
582
|
+
console.error(chalk.red(`Failed to merge ${execution.atomId}:`));
|
|
583
|
+
console.error(chalk.dim(error instanceof Error ? error.message : "Unknown error"));
|
|
584
|
+
console.log(chalk.yellow("You may need to resolve merge conflicts manually."));
|
|
724
585
|
}
|
|
725
586
|
}
|
|
726
587
|
await saveParallelState(cwd, state);
|
|
727
|
-
console.log(
|
|
588
|
+
console.log(chalk.green("\n\u2705 Merge complete!"));
|
|
728
589
|
}
|
|
729
590
|
async function parallelClean() {
|
|
730
591
|
const cwd = process.cwd();
|
|
731
592
|
const manager = new WorktreeManager(cwd);
|
|
732
593
|
const state = await loadParallelState(cwd);
|
|
733
|
-
console.log(
|
|
594
|
+
console.log(chalk.blue("\n\u{1F9F9} Cleaning up parallel execution state...\n"));
|
|
734
595
|
for (const execution of state.executions) {
|
|
735
596
|
try {
|
|
736
597
|
if (manager.worktreeExists(execution.atomId)) {
|
|
737
|
-
console.log(
|
|
598
|
+
console.log(chalk.dim(`Removing worktree for ${execution.atomId}...`));
|
|
738
599
|
await manager.removeWorktree(execution.atomId);
|
|
739
|
-
console.log(
|
|
600
|
+
console.log(chalk.green(`\u2713 Removed worktree for ${execution.atomId}`));
|
|
740
601
|
}
|
|
741
602
|
} catch (error) {
|
|
742
|
-
console.error(
|
|
743
|
-
console.error(
|
|
603
|
+
console.error(chalk.red(`Failed to remove worktree for ${execution.atomId}:`));
|
|
604
|
+
console.error(chalk.dim(error instanceof Error ? error.message : "Unknown error"));
|
|
744
605
|
}
|
|
745
606
|
}
|
|
746
607
|
await saveParallelState(cwd, { executions: [] });
|
|
747
|
-
console.log(
|
|
608
|
+
console.log(chalk.green("\n\u2705 Cleanup complete!"));
|
|
748
609
|
}
|
|
749
610
|
function toSchedulableAtom(atom) {
|
|
750
611
|
return {
|
|
@@ -757,15 +618,15 @@ function toSchedulableAtom(atom) {
|
|
|
757
618
|
async function parallelSchedule(options) {
|
|
758
619
|
const atoms = await listLocalAtoms();
|
|
759
620
|
if (atoms.length === 0) {
|
|
760
|
-
console.log(
|
|
621
|
+
console.log(chalk.yellow('No atoms found. Run "archon plan" first.'));
|
|
761
622
|
return;
|
|
762
623
|
}
|
|
763
624
|
const targetAtoms = options.onlyReady ? atoms.filter((a) => a.status === "READY") : atoms;
|
|
764
625
|
if (targetAtoms.length === 0) {
|
|
765
|
-
console.log(
|
|
626
|
+
console.log(chalk.yellow('No READY atoms found. Run "archon plan <atom-id>" first.'));
|
|
766
627
|
return;
|
|
767
628
|
}
|
|
768
|
-
console.log(
|
|
629
|
+
console.log(chalk.blue(`
|
|
769
630
|
\u{1F4CA} Analyzing ${targetAtoms.length} atom(s)...
|
|
770
631
|
`));
|
|
771
632
|
const schedulableAtoms = targetAtoms.map(toSchedulableAtom);
|
|
@@ -774,7 +635,7 @@ async function parallelSchedule(options) {
|
|
|
774
635
|
maxParallelism: options.maxParallelism
|
|
775
636
|
});
|
|
776
637
|
if (options.mermaid) {
|
|
777
|
-
console.log(
|
|
638
|
+
console.log(chalk.dim("Mermaid Diagram:"));
|
|
778
639
|
console.log("```mermaid");
|
|
779
640
|
console.log(formatAsMermaid(graph));
|
|
780
641
|
console.log("```");
|
|
@@ -782,30 +643,30 @@ async function parallelSchedule(options) {
|
|
|
782
643
|
}
|
|
783
644
|
console.log(formatExecutionPlan(plan));
|
|
784
645
|
console.log();
|
|
785
|
-
console.log(
|
|
646
|
+
console.log(chalk.blue("Wave Details:\n"));
|
|
786
647
|
for (const wave of plan.waves) {
|
|
787
|
-
console.log(
|
|
648
|
+
console.log(chalk.bold(`Wave ${wave.waveNumber}:`));
|
|
788
649
|
for (const atom of wave.atoms) {
|
|
789
650
|
const originalAtom = atoms.find((a) => a.id === atom.id);
|
|
790
651
|
const status = originalAtom?.status ?? "UNKNOWN";
|
|
791
|
-
const statusColor = status === "READY" ?
|
|
792
|
-
console.log(` ${statusColor("\u25CF")} ${atom.id}: ${atom.title} ${
|
|
652
|
+
const statusColor = status === "READY" ? chalk.green : status === "DONE" ? chalk.blue : chalk.yellow;
|
|
653
|
+
console.log(` ${statusColor("\u25CF")} ${atom.id}: ${atom.title} ${chalk.dim(`(${status})`)}`);
|
|
793
654
|
}
|
|
794
655
|
console.log();
|
|
795
656
|
}
|
|
796
657
|
const conflictEdges = graph.edges.filter((e) => e.type === "file_conflict");
|
|
797
658
|
if (conflictEdges.length > 0) {
|
|
798
|
-
console.log(
|
|
659
|
+
console.log(chalk.yellow("\u26A0\uFE0F File Conflict Dependencies:\n"));
|
|
799
660
|
for (const edge of conflictEdges) {
|
|
800
661
|
console.log(` ${edge.from} \u2192 ${edge.to}`);
|
|
801
662
|
if (edge.reason) {
|
|
802
|
-
console.log(
|
|
663
|
+
console.log(chalk.dim(` ${edge.reason}`));
|
|
803
664
|
}
|
|
804
665
|
}
|
|
805
666
|
console.log();
|
|
806
667
|
}
|
|
807
|
-
console.log(
|
|
808
|
-
console.log(
|
|
668
|
+
console.log(chalk.dim("To execute atoms in parallel: archon parallel run <atom-ids...>"));
|
|
669
|
+
console.log(chalk.dim("To execute waves sequentially: archon parallel run-waves"));
|
|
809
670
|
}
|
|
810
671
|
async function parallelRunWaves(options) {
|
|
811
672
|
const atoms = await listLocalAtoms();
|
|
@@ -815,29 +676,29 @@ async function parallelRunWaves(options) {
|
|
|
815
676
|
);
|
|
816
677
|
if (readyAtoms.length === 0) {
|
|
817
678
|
if (scopeIds && scopeIds.size > 0) {
|
|
818
|
-
console.log(
|
|
679
|
+
console.log(chalk.yellow("No READY atoms found in the approved scope."));
|
|
819
680
|
return;
|
|
820
681
|
}
|
|
821
|
-
console.log(
|
|
682
|
+
console.log(chalk.yellow("No READY atoms found."));
|
|
822
683
|
return;
|
|
823
684
|
}
|
|
824
685
|
const schedulableAtoms = readyAtoms.map(toSchedulableAtom);
|
|
825
686
|
const graph = buildDependencyGraph(schedulableAtoms);
|
|
826
687
|
const plan = scheduleExecution(graph, { maxParallelism: options.maxParallelism });
|
|
827
|
-
console.log(
|
|
688
|
+
console.log(chalk.blue(`
|
|
828
689
|
\u{1F680} Executing ${plan.totalAtoms} atoms in ${plan.waves.length} waves
|
|
829
690
|
`));
|
|
830
|
-
console.log(
|
|
691
|
+
console.log(chalk.dim(`Estimated speedup: ${plan.estimatedSpeedup}\xD7 vs serial execution
|
|
831
692
|
`));
|
|
832
693
|
if (options.dryRun) {
|
|
833
|
-
console.log(
|
|
694
|
+
console.log(chalk.yellow("DRY RUN - no atoms will be executed\n"));
|
|
834
695
|
console.log(formatExecutionPlan(plan));
|
|
835
696
|
return;
|
|
836
697
|
}
|
|
837
698
|
const cwd = process.cwd();
|
|
838
699
|
const manager = new WorktreeManager(cwd);
|
|
839
700
|
for (const wave of plan.waves) {
|
|
840
|
-
console.log(
|
|
701
|
+
console.log(chalk.blue(`
|
|
841
702
|
\u2550\u2550\u2550 Wave ${wave.waveNumber} (${wave.atoms.length} atoms) \u2550\u2550\u2550
|
|
842
703
|
`));
|
|
843
704
|
const worktrees = [];
|
|
@@ -845,10 +706,10 @@ async function parallelRunWaves(options) {
|
|
|
845
706
|
try {
|
|
846
707
|
const worktreePath = await manager.createWorktree(atom.id);
|
|
847
708
|
worktrees.push({ atomId: atom.id, path: worktreePath });
|
|
848
|
-
console.log(
|
|
709
|
+
console.log(chalk.dim(` Created worktree for ${atom.id}`));
|
|
849
710
|
} catch (error) {
|
|
850
|
-
console.error(
|
|
851
|
-
console.error(
|
|
711
|
+
console.error(chalk.red(` Failed to create worktree for ${atom.id}:`));
|
|
712
|
+
console.error(chalk.dim(error instanceof Error ? error.message : "Unknown error"));
|
|
852
713
|
}
|
|
853
714
|
}
|
|
854
715
|
const results = await Promise.all(
|
|
@@ -857,28 +718,28 @@ async function parallelRunWaves(options) {
|
|
|
857
718
|
const succeeded = results.filter((r) => r.success).length;
|
|
858
719
|
const failed = results.filter((r) => !r.success).length;
|
|
859
720
|
console.log();
|
|
860
|
-
console.log(
|
|
721
|
+
console.log(chalk.green(` \u2713 ${succeeded} succeeded`));
|
|
861
722
|
if (failed > 0) {
|
|
862
|
-
console.log(
|
|
723
|
+
console.log(chalk.red(` \u2717 ${failed} failed`));
|
|
863
724
|
}
|
|
864
725
|
for (const result of results) {
|
|
865
726
|
if (result.success) {
|
|
866
727
|
try {
|
|
867
728
|
await manager.mergeWorktree(result.atomId);
|
|
868
729
|
await manager.removeWorktree(result.atomId);
|
|
869
|
-
console.log(
|
|
730
|
+
console.log(chalk.dim(` Merged and cleaned ${result.atomId}`));
|
|
870
731
|
} catch (error) {
|
|
871
|
-
console.error(
|
|
732
|
+
console.error(chalk.yellow(` Failed to merge ${result.atomId} - manual merge may be required`));
|
|
872
733
|
}
|
|
873
734
|
}
|
|
874
735
|
}
|
|
875
736
|
if (failed > 0) {
|
|
876
|
-
console.log(
|
|
877
|
-
console.log(
|
|
737
|
+
console.log(chalk.red("\n\u26A0\uFE0F Wave had failures. Stopping execution."));
|
|
738
|
+
console.log(chalk.dim("Fix the issues and run again to continue."));
|
|
878
739
|
return;
|
|
879
740
|
}
|
|
880
741
|
}
|
|
881
|
-
console.log(
|
|
742
|
+
console.log(chalk.green("\n\u2705 All waves completed successfully!"));
|
|
882
743
|
}
|
|
883
744
|
async function executeAtomInWorktree(atomId, worktreePath) {
|
|
884
745
|
return new Promise((resolve) => {
|