archondev 2.19.18 → 2.19.22
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/chunk-3XEHZYXJ.js +169 -0
- package/dist/index.js +750 -1130
- package/dist/show-CXJPLCXD.js +19 -0
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
a11yBadge,
|
|
4
|
+
a11yCheck,
|
|
5
|
+
a11yFix,
|
|
6
|
+
a11yPreDeploy
|
|
7
|
+
} from "./chunk-FWLLGLD5.js";
|
|
2
8
|
import {
|
|
3
9
|
createSeoCommand
|
|
4
10
|
} from "./chunk-JF7JCK6H.js";
|
|
5
11
|
import {
|
|
6
12
|
createGeoCommand
|
|
7
13
|
} from "./chunk-O3B6BE5D.js";
|
|
14
|
+
import {
|
|
15
|
+
show
|
|
16
|
+
} from "./chunk-3XEHZYXJ.js";
|
|
8
17
|
import {
|
|
9
18
|
bugReport
|
|
10
19
|
} from "./chunk-XKYRHJA5.js";
|
|
@@ -21,6 +30,7 @@ import {
|
|
|
21
30
|
reviewUpdate
|
|
22
31
|
} from "./chunk-6XLWTTGJ.js";
|
|
23
32
|
import "./chunk-YGDLWQBK.js";
|
|
33
|
+
import "./chunk-3ASILTFB.js";
|
|
24
34
|
import {
|
|
25
35
|
resetPreferences,
|
|
26
36
|
setExecutionPreference,
|
|
@@ -29,13 +39,6 @@ import {
|
|
|
29
39
|
showPreferences,
|
|
30
40
|
showUsageDetails
|
|
31
41
|
} from "./chunk-MIT5Z5V7.js";
|
|
32
|
-
import {
|
|
33
|
-
a11yBadge,
|
|
34
|
-
a11yCheck,
|
|
35
|
-
a11yFix,
|
|
36
|
-
a11yPreDeploy
|
|
37
|
-
} from "./chunk-FWLLGLD5.js";
|
|
38
|
-
import "./chunk-3ASILTFB.js";
|
|
39
42
|
import {
|
|
40
43
|
init,
|
|
41
44
|
isInitialized
|
|
@@ -113,7 +116,7 @@ import "./chunk-4VNS5WPM.js";
|
|
|
113
116
|
|
|
114
117
|
// src/cli/index.ts
|
|
115
118
|
import { Command as Command3 } from "commander";
|
|
116
|
-
import
|
|
119
|
+
import chalk17 from "chalk";
|
|
117
120
|
import "dotenv/config";
|
|
118
121
|
|
|
119
122
|
// src/cli/terminal-compat.ts
|
|
@@ -124,9 +127,8 @@ function shouldEnableSafeMode() {
|
|
|
124
127
|
}
|
|
125
128
|
return process.env["TERM_PROGRAM"] === "Apple_Terminal";
|
|
126
129
|
}
|
|
127
|
-
function
|
|
128
|
-
|
|
129
|
-
return withoutAnsi.replace(/[^\x09\x0A\x0D\x20-\x7E]/g, "");
|
|
130
|
+
function isTerminalSafeMode() {
|
|
131
|
+
return shouldEnableSafeMode();
|
|
130
132
|
}
|
|
131
133
|
function enableTerminalCompatibilityMode() {
|
|
132
134
|
if (!shouldEnableSafeMode()) {
|
|
@@ -139,19 +141,7 @@ function enableTerminalCompatibilityMode() {
|
|
|
139
141
|
globalObj[SAFE_MODE_FLAG] = true;
|
|
140
142
|
process.env["NO_COLOR"] = "1";
|
|
141
143
|
process.env["FORCE_COLOR"] = "0";
|
|
142
|
-
|
|
143
|
-
for (const method of methods) {
|
|
144
|
-
const original = console[method].bind(console);
|
|
145
|
-
console[method] = (...args) => {
|
|
146
|
-
const patched = args.map((arg) => {
|
|
147
|
-
if (typeof arg === "string") {
|
|
148
|
-
return toAsciiSafe(arg);
|
|
149
|
-
}
|
|
150
|
-
return arg;
|
|
151
|
-
});
|
|
152
|
-
original(...patched);
|
|
153
|
-
};
|
|
154
|
-
}
|
|
144
|
+
process.env["ARCHON_TERMINAL_SAFE_MODE"] = "1";
|
|
155
145
|
}
|
|
156
146
|
|
|
157
147
|
// src/cli/promote.ts
|
|
@@ -207,170 +197,8 @@ async function saveAtomEnvironmentState(atomId, cwd, state) {
|
|
|
207
197
|
await writeFile(stateFile, JSON.stringify(state, null, 2));
|
|
208
198
|
}
|
|
209
199
|
|
|
210
|
-
// src/cli/show.ts
|
|
211
|
-
import chalk2 from "chalk";
|
|
212
|
-
var STATUS_COLORS = {
|
|
213
|
-
DRAFT: chalk2.gray,
|
|
214
|
-
READY: chalk2.blue,
|
|
215
|
-
IN_PROGRESS: chalk2.yellow,
|
|
216
|
-
TESTING: chalk2.cyan,
|
|
217
|
-
DONE: chalk2.green,
|
|
218
|
-
FAILED: chalk2.red,
|
|
219
|
-
BLOCKED: chalk2.magenta
|
|
220
|
-
};
|
|
221
|
-
async function show(atomId) {
|
|
222
|
-
const atom = await loadAtom(atomId);
|
|
223
|
-
if (!atom) {
|
|
224
|
-
console.error(chalk2.red(`Atom ${atomId} not found.`));
|
|
225
|
-
console.log(chalk2.dim('Use "archon list" to see available atoms.'));
|
|
226
|
-
process.exit(1);
|
|
227
|
-
}
|
|
228
|
-
const colorFn = STATUS_COLORS[atom.status] ?? chalk2.white;
|
|
229
|
-
console.log("");
|
|
230
|
-
console.log(chalk2.bold(`Atom: ${atom.externalId}`));
|
|
231
|
-
console.log(chalk2.dim("\u2550".repeat(60)));
|
|
232
|
-
console.log("");
|
|
233
|
-
console.log(chalk2.bold("Title:"), atom.title);
|
|
234
|
-
if (atom.description) {
|
|
235
|
-
console.log(chalk2.bold("Description:"), atom.description);
|
|
236
|
-
}
|
|
237
|
-
console.log(chalk2.bold("Status:"), colorFn(atom.status));
|
|
238
|
-
console.log(chalk2.bold("Priority:"), atom.priority);
|
|
239
|
-
console.log(chalk2.bold("Created:"), formatDateTime(atom.createdAt));
|
|
240
|
-
console.log(chalk2.bold("Updated:"), formatDateTime(atom.updatedAt));
|
|
241
|
-
if (atom.goals && atom.goals.length > 0) {
|
|
242
|
-
console.log("");
|
|
243
|
-
console.log(chalk2.bold("Goals:"));
|
|
244
|
-
for (const goal of atom.goals) {
|
|
245
|
-
console.log(` \u2022 ${goal}`);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
if (atom.acceptanceCriteria && atom.acceptanceCriteria.length > 0) {
|
|
249
|
-
console.log("");
|
|
250
|
-
console.log(chalk2.bold("Acceptance Criteria:"));
|
|
251
|
-
for (let i = 0; i < atom.acceptanceCriteria.length; i++) {
|
|
252
|
-
console.log(` ${i + 1}. ${atom.acceptanceCriteria[i]}`);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
if (atom.tags && atom.tags.length > 0) {
|
|
256
|
-
console.log("");
|
|
257
|
-
console.log(chalk2.bold("Tags:"), atom.tags.join(", "));
|
|
258
|
-
}
|
|
259
|
-
if (atom.plan) {
|
|
260
|
-
console.log("");
|
|
261
|
-
console.log(chalk2.bold("Implementation Plan:"));
|
|
262
|
-
console.log(chalk2.dim("\u2500".repeat(40)));
|
|
263
|
-
console.log(chalk2.bold("Steps:"));
|
|
264
|
-
for (let i = 0; i < atom.plan.steps.length; i++) {
|
|
265
|
-
console.log(` ${i + 1}. ${atom.plan.steps[i]}`);
|
|
266
|
-
}
|
|
267
|
-
if (atom.plan.files_to_modify.length > 0) {
|
|
268
|
-
console.log("");
|
|
269
|
-
console.log(chalk2.bold("Files to modify:"));
|
|
270
|
-
for (const file of atom.plan.files_to_modify) {
|
|
271
|
-
console.log(` \u2022 ${file}`);
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
if (atom.plan.dependencies.length > 0) {
|
|
275
|
-
console.log("");
|
|
276
|
-
console.log(chalk2.bold("Dependencies:"));
|
|
277
|
-
for (const dep of atom.plan.dependencies) {
|
|
278
|
-
console.log(` \u2022 ${dep}`);
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
if (atom.plan.risks.length > 0) {
|
|
282
|
-
console.log("");
|
|
283
|
-
console.log(chalk2.bold("Risks:"));
|
|
284
|
-
for (const risk of atom.plan.risks) {
|
|
285
|
-
console.log(chalk2.yellow(` [!] ${risk}`));
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
console.log("");
|
|
289
|
-
console.log(chalk2.bold("Estimated Complexity:"), atom.plan.estimated_complexity);
|
|
290
|
-
}
|
|
291
|
-
if (atom.status === "FAILED" && atom.errorMessage) {
|
|
292
|
-
console.log("");
|
|
293
|
-
console.log(chalk2.bold("Error:"));
|
|
294
|
-
console.log(chalk2.red(` ${atom.errorMessage}`));
|
|
295
|
-
}
|
|
296
|
-
if (atom.retryCount > 0) {
|
|
297
|
-
console.log("");
|
|
298
|
-
console.log(chalk2.bold("Retry Count:"), chalk2.yellow(String(atom.retryCount)));
|
|
299
|
-
}
|
|
300
|
-
if (atom.ownershipPaths && atom.ownershipPaths.length > 0) {
|
|
301
|
-
console.log("");
|
|
302
|
-
console.log(chalk2.bold("Ownership Paths:"));
|
|
303
|
-
for (const path2 of atom.ownershipPaths) {
|
|
304
|
-
console.log(` \u2022 ${path2}`);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
if (atom.diffContract) {
|
|
308
|
-
console.log("");
|
|
309
|
-
console.log(chalk2.bold("Diff Contract:"));
|
|
310
|
-
if (atom.diffContract.allowed_paths.length > 0) {
|
|
311
|
-
console.log(chalk2.dim(" Allowed paths:"));
|
|
312
|
-
for (const path2 of atom.diffContract.allowed_paths) {
|
|
313
|
-
console.log(` \u2713 ${path2}`);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
if (atom.diffContract.forbidden_paths.length > 0) {
|
|
317
|
-
console.log(chalk2.dim(" Forbidden paths:"));
|
|
318
|
-
for (const path2 of atom.diffContract.forbidden_paths) {
|
|
319
|
-
console.log(chalk2.red(` \u2717 ${path2}`));
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
if (atom.context && Object.keys(atom.context).length > 0) {
|
|
324
|
-
console.log("");
|
|
325
|
-
console.log(chalk2.bold("Context:"));
|
|
326
|
-
if (atom.context.relevantFiles && atom.context.relevantFiles.length > 0) {
|
|
327
|
-
console.log(chalk2.dim(" Relevant files:"));
|
|
328
|
-
for (const file of atom.context.relevantFiles) {
|
|
329
|
-
console.log(` \u2022 ${file}`);
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
if (atom.context.recentLearnings && atom.context.recentLearnings.length > 0) {
|
|
333
|
-
console.log(chalk2.dim(" Recent learnings:"));
|
|
334
|
-
for (const learning of atom.context.recentLearnings) {
|
|
335
|
-
console.log(` \u2022 ${learning}`);
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
console.log("");
|
|
340
|
-
console.log(chalk2.dim("\u2500".repeat(60)));
|
|
341
|
-
console.log(chalk2.bold("Next Steps:"));
|
|
342
|
-
switch (atom.status) {
|
|
343
|
-
case "DRAFT":
|
|
344
|
-
console.log(chalk2.dim(` Run "archon plan ${atom.externalId} --continue" to finalize the plan`));
|
|
345
|
-
break;
|
|
346
|
-
case "READY":
|
|
347
|
-
console.log(chalk2.dim(` Run "archon execute ${atom.externalId}" to implement`));
|
|
348
|
-
break;
|
|
349
|
-
case "IN_PROGRESS":
|
|
350
|
-
console.log(chalk2.dim(" Execution is in progress..."));
|
|
351
|
-
break;
|
|
352
|
-
case "TESTING":
|
|
353
|
-
console.log(chalk2.dim(" Waiting for quality gates to complete..."));
|
|
354
|
-
break;
|
|
355
|
-
case "DONE":
|
|
356
|
-
console.log(chalk2.green(" \u2713 Atom completed successfully!"));
|
|
357
|
-
break;
|
|
358
|
-
case "FAILED":
|
|
359
|
-
console.log(chalk2.dim(` Review the error and run "archon execute ${atom.externalId}" to retry`));
|
|
360
|
-
break;
|
|
361
|
-
case "BLOCKED":
|
|
362
|
-
console.log(chalk2.dim(" This atom is blocked. Manual intervention required."));
|
|
363
|
-
break;
|
|
364
|
-
}
|
|
365
|
-
console.log("");
|
|
366
|
-
}
|
|
367
|
-
function formatDateTime(date) {
|
|
368
|
-
const d = typeof date === "string" ? new Date(date) : date;
|
|
369
|
-
return d.toLocaleString();
|
|
370
|
-
}
|
|
371
|
-
|
|
372
200
|
// src/cli/start.ts
|
|
373
|
-
import
|
|
201
|
+
import chalk5 from "chalk";
|
|
374
202
|
import readline from "readline";
|
|
375
203
|
import { existsSync as existsSync6, readFileSync as readFileSync3, readdirSync as readdirSync3, appendFileSync } from "fs";
|
|
376
204
|
import { join as join6 } from "path";
|
|
@@ -477,7 +305,7 @@ var ContextManager = class _ContextManager {
|
|
|
477
305
|
};
|
|
478
306
|
|
|
479
307
|
// src/cli/cleanup.ts
|
|
480
|
-
import
|
|
308
|
+
import chalk2 from "chalk";
|
|
481
309
|
import { existsSync as existsSync3, readdirSync, statSync } from "fs";
|
|
482
310
|
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir2, unlink, readdir, stat } from "fs/promises";
|
|
483
311
|
import { join as join3 } from "path";
|
|
@@ -656,7 +484,7 @@ async function cleanupCheck() {
|
|
|
656
484
|
const config = await loadCleanupConfig(cwd);
|
|
657
485
|
const progressMaxKb = config?.progressMaxKb ?? DEFAULT_THRESHOLDS.progressMaxKb;
|
|
658
486
|
const archonDirMaxMb = config?.archonDirMaxMb ?? DEFAULT_THRESHOLDS.archonDirMaxMb;
|
|
659
|
-
console.log(
|
|
487
|
+
console.log(chalk2.blue("\n\u{1F50D} Analyzing workspace for maintenance needs...\n"));
|
|
660
488
|
const progressPath = join3(cwd, PROGRESS_FILE);
|
|
661
489
|
if (existsSync3(progressPath)) {
|
|
662
490
|
const size = statSync(progressPath).size;
|
|
@@ -729,12 +557,12 @@ async function cleanupCheck() {
|
|
|
729
557
|
});
|
|
730
558
|
}
|
|
731
559
|
}
|
|
732
|
-
console.log(
|
|
560
|
+
console.log(chalk2.bold("Workspace Analysis Summary\n"));
|
|
733
561
|
console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
|
|
734
562
|
console.log("\u2502 Item \u2502 Size \u2502 Status \u2502");
|
|
735
563
|
console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u253C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");
|
|
736
564
|
for (const result of results) {
|
|
737
|
-
const statusIcon = result.status === "critical" ?
|
|
565
|
+
const statusIcon = result.status === "critical" ? chalk2.red("\u2717") : result.status === "warn" ? chalk2.yellow("!") : chalk2.green("\u2713");
|
|
738
566
|
const name = result.name.padEnd(23);
|
|
739
567
|
const size = result.sizeFormatted.padEnd(14);
|
|
740
568
|
console.log(`\u2502 ${name} \u2502 ${size} \u2502 ${statusIcon} \u2502`);
|
|
@@ -743,13 +571,13 @@ async function cleanupCheck() {
|
|
|
743
571
|
console.log();
|
|
744
572
|
const recommendations = results.filter((r) => r.recommendation && r.status !== "ok");
|
|
745
573
|
if (recommendations.length > 0) {
|
|
746
|
-
console.log(
|
|
574
|
+
console.log(chalk2.yellow("Recommendations:\n"));
|
|
747
575
|
for (const rec of recommendations) {
|
|
748
|
-
console.log(` ${
|
|
576
|
+
console.log(` ${chalk2.dim("\u2022")} ${rec.name}: ${rec.recommendation}`);
|
|
749
577
|
}
|
|
750
578
|
console.log();
|
|
751
579
|
} else {
|
|
752
|
-
console.log(
|
|
580
|
+
console.log(chalk2.green("\u2713 Workspace is in good shape!\n"));
|
|
753
581
|
}
|
|
754
582
|
}
|
|
755
583
|
async function cleanupRun() {
|
|
@@ -760,7 +588,7 @@ async function cleanupRun() {
|
|
|
760
588
|
const progressArchiveDays = config?.progressArchiveDays ?? DEFAULT_THRESHOLDS.progressArchiveDays;
|
|
761
589
|
const cacheRetentionDays = config?.cacheRetentionDays ?? DEFAULT_THRESHOLDS.cacheRetentionDays;
|
|
762
590
|
const cloudLogRetentionDays = config?.cloudLogRetentionDays ?? DEFAULT_THRESHOLDS.cloudLogRetentionDays;
|
|
763
|
-
console.log(
|
|
591
|
+
console.log(chalk2.blue("\n\u{1F9F9} Running workspace cleanup...\n"));
|
|
764
592
|
const progressPath = join3(cwd, PROGRESS_FILE);
|
|
765
593
|
if (existsSync3(progressPath)) {
|
|
766
594
|
const content = await readFile3(progressPath, "utf-8");
|
|
@@ -806,7 +634,7 @@ async function cleanupRun() {
|
|
|
806
634
|
spaceSavedFormatted: "N/A"
|
|
807
635
|
});
|
|
808
636
|
} catch {
|
|
809
|
-
console.log(
|
|
637
|
+
console.log(chalk2.yellow(` Could not remove worktree: ${worktree}`));
|
|
810
638
|
}
|
|
811
639
|
}
|
|
812
640
|
const cachePath = join3(cwd, CACHE_DIR);
|
|
@@ -852,18 +680,18 @@ async function cleanupRun() {
|
|
|
852
680
|
}
|
|
853
681
|
}
|
|
854
682
|
if (results.length === 0) {
|
|
855
|
-
console.log(
|
|
683
|
+
console.log(chalk2.green("\u2713 Nothing to clean up!\n"));
|
|
856
684
|
return;
|
|
857
685
|
}
|
|
858
|
-
console.log(
|
|
686
|
+
console.log(chalk2.bold("Cleanup Results\n"));
|
|
859
687
|
for (const result of results) {
|
|
860
|
-
console.log(` ${
|
|
688
|
+
console.log(` ${chalk2.green("\u2713")} ${result.name}: ${result.action}`);
|
|
861
689
|
if (result.spaceSaved > 0) {
|
|
862
|
-
console.log(
|
|
690
|
+
console.log(chalk2.dim(` Space saved: ${result.spaceSavedFormatted}`));
|
|
863
691
|
}
|
|
864
692
|
}
|
|
865
693
|
console.log();
|
|
866
|
-
console.log(
|
|
694
|
+
console.log(chalk2.green(`\u2713 Total space saved: ${formatBytes(totalSaved)}
|
|
867
695
|
`));
|
|
868
696
|
}
|
|
869
697
|
async function cleanupAuto(action) {
|
|
@@ -871,20 +699,20 @@ async function cleanupAuto(action) {
|
|
|
871
699
|
const config = await loadCleanupConfig(cwd);
|
|
872
700
|
if (action === "status") {
|
|
873
701
|
const enabled = config?.autoEnabled ?? false;
|
|
874
|
-
console.log(
|
|
702
|
+
console.log(chalk2.blue("\n\u{1F527} Auto Cleanup Settings\n"));
|
|
875
703
|
console.log(
|
|
876
|
-
` Status: ${enabled ?
|
|
704
|
+
` Status: ${enabled ? chalk2.green("Enabled") : chalk2.dim("Disabled")}`
|
|
877
705
|
);
|
|
878
706
|
console.log(
|
|
879
|
-
|
|
707
|
+
chalk2.dim(
|
|
880
708
|
` Progress archive threshold: ${config?.progressArchiveDays ?? 30} days`
|
|
881
709
|
)
|
|
882
710
|
);
|
|
883
711
|
console.log(
|
|
884
|
-
|
|
712
|
+
chalk2.dim(` Cache retention: ${config?.cacheRetentionDays ?? 7} days`)
|
|
885
713
|
);
|
|
886
714
|
console.log(
|
|
887
|
-
|
|
715
|
+
chalk2.dim(
|
|
888
716
|
` Cloud log retention: ${config?.cloudLogRetentionDays ?? 30} days`
|
|
889
717
|
)
|
|
890
718
|
);
|
|
@@ -899,14 +727,14 @@ async function cleanupAuto(action) {
|
|
|
899
727
|
};
|
|
900
728
|
await saveCleanupConfig(cwd, newConfig);
|
|
901
729
|
if (action === "enable") {
|
|
902
|
-
console.log(
|
|
730
|
+
console.log(chalk2.green("\n\u2713 Auto cleanup enabled"));
|
|
903
731
|
console.log(
|
|
904
|
-
|
|
732
|
+
chalk2.dim(
|
|
905
733
|
' Cleanup check will run on "archon start" and warn if action needed\n'
|
|
906
734
|
)
|
|
907
735
|
);
|
|
908
736
|
} else {
|
|
909
|
-
console.log(
|
|
737
|
+
console.log(chalk2.green("\n\u2713 Auto cleanup disabled\n"));
|
|
910
738
|
}
|
|
911
739
|
}
|
|
912
740
|
async function shouldRunAutoCleanup(cwd) {
|
|
@@ -940,7 +768,7 @@ async function runAutoCleanupCheck(cwd) {
|
|
|
940
768
|
}
|
|
941
769
|
|
|
942
770
|
// src/cli/update-check.ts
|
|
943
|
-
import
|
|
771
|
+
import chalk3 from "chalk";
|
|
944
772
|
import { readFileSync, existsSync as existsSync4 } from "fs";
|
|
945
773
|
import { join as join4, dirname as dirname3 } from "path";
|
|
946
774
|
import { fileURLToPath } from "url";
|
|
@@ -1032,10 +860,10 @@ async function checkForUpdates() {
|
|
|
1032
860
|
function displayUpdateBanner(result) {
|
|
1033
861
|
if (!result.hasUpdate) return;
|
|
1034
862
|
console.log();
|
|
1035
|
-
console.log(
|
|
1036
|
-
console.log(
|
|
1037
|
-
console.log(
|
|
1038
|
-
console.log(
|
|
863
|
+
console.log(chalk3.yellow("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
|
|
864
|
+
console.log(chalk3.yellow("\u2502") + chalk3.bold(" Update available! ") + chalk3.dim(`${result.currentVersion} \u2192 `) + chalk3.green(result.latestVersion) + chalk3.yellow(" \u2502"));
|
|
865
|
+
console.log(chalk3.yellow("\u2502") + chalk3.dim(` Run: ${result.updateCommand}`) + chalk3.yellow(" \u2502"));
|
|
866
|
+
console.log(chalk3.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));
|
|
1039
867
|
console.log();
|
|
1040
868
|
}
|
|
1041
869
|
function startBackgroundUpdateCheck() {
|
|
@@ -1043,7 +871,7 @@ function startBackgroundUpdateCheck() {
|
|
|
1043
871
|
}
|
|
1044
872
|
|
|
1045
873
|
// src/cli/logo.ts
|
|
1046
|
-
import
|
|
874
|
+
import chalk4 from "chalk";
|
|
1047
875
|
var ARCHON_LOGO_MINI = `
|
|
1048
876
|
\u2584\u2588\u2580\u2588\u2584
|
|
1049
877
|
\u2588\u2588\u2580\u2588\u2580\u2588\u2588
|
|
@@ -1051,11 +879,19 @@ var ARCHON_LOGO_MINI = `
|
|
|
1051
879
|
\u2588\u2588\u2588\u2588\u2588\u2588
|
|
1052
880
|
`;
|
|
1053
881
|
function displayBrandedHeader() {
|
|
882
|
+
if (process.env["ARCHON_TERMINAL_SAFE_MODE"] === "1") {
|
|
883
|
+
console.log();
|
|
884
|
+
console.log("ArchonDev");
|
|
885
|
+
console.log("AI-Powered Development Governance");
|
|
886
|
+
console.log("----------------------------------------");
|
|
887
|
+
console.log();
|
|
888
|
+
return;
|
|
889
|
+
}
|
|
1054
890
|
console.log();
|
|
1055
|
-
console.log(
|
|
1056
|
-
console.log(
|
|
1057
|
-
console.log(
|
|
1058
|
-
console.log(
|
|
891
|
+
console.log(chalk4.hex("#374F4E")(ARCHON_LOGO_MINI));
|
|
892
|
+
console.log(chalk4.bold.hex("#374F4E")(" ArchonDev"));
|
|
893
|
+
console.log(chalk4.hex("#AA8552")(" AI-Powered Development Governance"));
|
|
894
|
+
console.log(chalk4.hex("#374F4E")("\u2500".repeat(40)));
|
|
1059
895
|
console.log();
|
|
1060
896
|
}
|
|
1061
897
|
|
|
@@ -1226,9 +1062,6 @@ function detectUserIntent(message) {
|
|
|
1226
1062
|
suggestedAction: "clarify"
|
|
1227
1063
|
};
|
|
1228
1064
|
}
|
|
1229
|
-
function needsClarification(result) {
|
|
1230
|
-
return result.confidence < 0.65 || result.suggestedAction === "clarify";
|
|
1231
|
-
}
|
|
1232
1065
|
function wantsToSkip(message) {
|
|
1233
1066
|
return ESCAPE_PHRASES.some((pattern) => pattern.test(message.trim()));
|
|
1234
1067
|
}
|
|
@@ -2771,6 +2604,12 @@ function detectWebProject(cwd) {
|
|
|
2771
2604
|
}
|
|
2772
2605
|
|
|
2773
2606
|
// src/cli/start.ts
|
|
2607
|
+
function uiText(rich, plain) {
|
|
2608
|
+
return isTerminalSafeMode() ? plain : rich;
|
|
2609
|
+
}
|
|
2610
|
+
function uiSeparator() {
|
|
2611
|
+
return isTerminalSafeMode() ? "-".repeat(40) : "\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501";
|
|
2612
|
+
}
|
|
2774
2613
|
async function start(options = {}) {
|
|
2775
2614
|
const cwd = process.cwd();
|
|
2776
2615
|
displayBrandedHeader();
|
|
@@ -2778,21 +2617,21 @@ async function start(options = {}) {
|
|
|
2778
2617
|
let config = await loadConfig();
|
|
2779
2618
|
let token = getAuthToken(config);
|
|
2780
2619
|
if (!token) {
|
|
2781
|
-
console.log(
|
|
2782
|
-
console.log(
|
|
2620
|
+
console.log(chalk5.bold("Welcome to ArchonDev!\n"));
|
|
2621
|
+
console.log(chalk5.dim("Let's get you set up. First, we need to create your account.\n"));
|
|
2783
2622
|
await login();
|
|
2784
2623
|
console.log();
|
|
2785
2624
|
config = await loadConfig();
|
|
2786
2625
|
token = getAuthToken(config);
|
|
2787
2626
|
if (!token) {
|
|
2788
|
-
console.log(
|
|
2627
|
+
console.log(chalk5.yellow("Login is required to continue. Run `archon` again when ready."));
|
|
2789
2628
|
return;
|
|
2790
2629
|
}
|
|
2791
2630
|
}
|
|
2792
2631
|
if (!config.tier || config.tier === "FREE") {
|
|
2793
2632
|
const isFirstRun = !existsSync6(join6(cwd, ".archon")) && resolveArchitecturePath(cwd).path === null;
|
|
2794
2633
|
if (isFirstRun && !config.tierConfirmed) {
|
|
2795
|
-
console.log(
|
|
2634
|
+
console.log(chalk5.bold("How would you like to use ArchonDev?\n"));
|
|
2796
2635
|
const selection = await promptTierSelection();
|
|
2797
2636
|
if (selection && !selection.skipped) {
|
|
2798
2637
|
const updateResult2 = await updateUserTier(selection.tier);
|
|
@@ -2800,7 +2639,7 @@ async function start(options = {}) {
|
|
|
2800
2639
|
config.tier = selection.tier;
|
|
2801
2640
|
config.tierConfirmed = true;
|
|
2802
2641
|
await saveConfig(config);
|
|
2803
|
-
console.log(
|
|
2642
|
+
console.log(chalk5.green(`
|
|
2804
2643
|
\u2713 Tier set to ${formatTierName(selection.tier)}
|
|
2805
2644
|
`));
|
|
2806
2645
|
await handleTierSetup(selection.tier);
|
|
@@ -2808,23 +2647,23 @@ async function start(options = {}) {
|
|
|
2808
2647
|
} else {
|
|
2809
2648
|
config.tierConfirmed = true;
|
|
2810
2649
|
await saveConfig(config);
|
|
2811
|
-
console.log(
|
|
2650
|
+
console.log(chalk5.dim("Using Free tier. You can upgrade anytime with `archon upgrade`\n"));
|
|
2812
2651
|
}
|
|
2813
2652
|
}
|
|
2814
2653
|
}
|
|
2815
2654
|
if (config.email) {
|
|
2816
|
-
console.log(
|
|
2655
|
+
console.log(chalk5.dim(`Logged in as: ${config.email}`));
|
|
2817
2656
|
}
|
|
2818
2657
|
const currentTier = config.tier || "FREE";
|
|
2819
2658
|
const tierDisplay = formatTierName(currentTier);
|
|
2820
|
-
console.log(
|
|
2659
|
+
console.log(chalk5.dim(`Tier: `) + tierDisplay);
|
|
2821
2660
|
if (currentTier === "FREE") {
|
|
2822
2661
|
console.log();
|
|
2823
|
-
console.log(
|
|
2824
|
-
console.log(
|
|
2825
|
-
console.log(
|
|
2826
|
-
console.log(
|
|
2827
|
-
console.log(
|
|
2662
|
+
console.log(chalk5.yellow("\u26A0\uFE0F FREE TIER: Limited usage. Upgrade options:"));
|
|
2663
|
+
console.log(chalk5.dim(" \u2022 ") + chalk5.bold("BYOK (FREE)") + chalk5.dim(" - Unlimited usage with your own API keys"));
|
|
2664
|
+
console.log(chalk5.dim(" \u2022 ") + chalk5.bold("Managed Plan") + chalk5.dim(" - Just 10% fee on AI costs, zero setup"));
|
|
2665
|
+
console.log(chalk5.cyan("\u2192 Run ") + chalk5.bold("'archon upgrade'") + chalk5.cyan(" to unlock unlimited access"));
|
|
2666
|
+
console.log(chalk5.dim("\u2192 Model preferences: archon preferences"));
|
|
2828
2667
|
}
|
|
2829
2668
|
if (currentTier === "CREDITS" && config.accessToken) {
|
|
2830
2669
|
try {
|
|
@@ -2846,41 +2685,41 @@ async function start(options = {}) {
|
|
|
2846
2685
|
}
|
|
2847
2686
|
if (usageStats) {
|
|
2848
2687
|
console.log();
|
|
2849
|
-
console.log(
|
|
2850
|
-
console.log(
|
|
2851
|
-
const balanceColor = usageStats.balance < 1 ?
|
|
2688
|
+
console.log(chalk5.bold(uiText("\u{1F4B0} Credits Balance", "Credits Balance")));
|
|
2689
|
+
console.log(chalk5.dim(uiSeparator()));
|
|
2690
|
+
const balanceColor = usageStats.balance < 1 ? chalk5.red : usageStats.balance < 5 ? chalk5.yellow : chalk5.green;
|
|
2852
2691
|
console.log(` Balance: ${balanceColor(`$${usageStats.balance.toFixed(2)}`)}`);
|
|
2853
2692
|
if (usageStats.periodStart) {
|
|
2854
2693
|
const periodDate = new Date(usageStats.periodStart);
|
|
2855
2694
|
const formatted = isNaN(periodDate.getTime()) ? usageStats.periodStart : periodDate.toLocaleDateString();
|
|
2856
2695
|
const label = usageStats.periodSource === "credit_purchase" ? `Since last top-up (${formatted})` : usageStats.periodSource === "month" ? `Since ${formatted}` : `Period start: ${formatted}`;
|
|
2857
|
-
console.log(
|
|
2696
|
+
console.log(chalk5.dim(` ${label}`));
|
|
2858
2697
|
}
|
|
2859
2698
|
if (usageStats.usedThisPeriod > 0) {
|
|
2860
|
-
console.log(` Used since last top-up: ${
|
|
2699
|
+
console.log(` Used since last top-up: ${chalk5.dim(`$${usageStats.usedThisPeriod.toFixed(2)}`)}`);
|
|
2861
2700
|
} else {
|
|
2862
|
-
console.log(
|
|
2701
|
+
console.log(chalk5.dim(" No usage recorded since last top-up."));
|
|
2863
2702
|
}
|
|
2864
2703
|
console.log();
|
|
2865
|
-
console.log(
|
|
2704
|
+
console.log(chalk5.dim(" Model Usage:"));
|
|
2866
2705
|
if (usageStats.byModel && usageStats.byModel.length > 0) {
|
|
2867
2706
|
for (const model of usageStats.byModel) {
|
|
2868
2707
|
const modelName = model.model.length > 32 ? model.model.slice(0, 29) + "..." : model.model;
|
|
2869
|
-
console.log(
|
|
2708
|
+
console.log(chalk5.dim(` ${modelName.padEnd(34)} $${model.cost.toFixed(4)}`));
|
|
2870
2709
|
}
|
|
2871
2710
|
} else {
|
|
2872
|
-
console.log(
|
|
2711
|
+
console.log(chalk5.dim(` ${"No usage yet".padEnd(34)} $0.0000`));
|
|
2873
2712
|
}
|
|
2874
|
-
console.log(
|
|
2713
|
+
console.log(chalk5.dim(uiSeparator()));
|
|
2875
2714
|
if (usageStatsUnavailable) {
|
|
2876
|
-
console.log(
|
|
2715
|
+
console.log(chalk5.dim("Usage details may be delayed. Run `archon credits` to refresh."));
|
|
2877
2716
|
}
|
|
2878
2717
|
if (usageStats.balance < 5) {
|
|
2879
|
-
console.log(
|
|
2718
|
+
console.log(chalk5.yellow(`\u26A0\uFE0F Low balance! Add credits: `) + chalk5.bold(`archon credits add`));
|
|
2880
2719
|
} else {
|
|
2881
|
-
console.log(
|
|
2720
|
+
console.log(chalk5.dim(`Add credits: archon credits add`));
|
|
2882
2721
|
}
|
|
2883
|
-
console.log(
|
|
2722
|
+
console.log(chalk5.dim(`View details: archon credits | Switch tier: archon upgrade | Models: archon preferences`));
|
|
2884
2723
|
if (usageStats.balance <= 0) {
|
|
2885
2724
|
const topUpNow = await promptYesNo("Balance is $0. Add credits now?", true);
|
|
2886
2725
|
if (topUpNow) {
|
|
@@ -2904,39 +2743,39 @@ async function start(options = {}) {
|
|
|
2904
2743
|
};
|
|
2905
2744
|
}
|
|
2906
2745
|
console.log();
|
|
2907
|
-
console.log(
|
|
2908
|
-
console.log(
|
|
2746
|
+
console.log(chalk5.bold(uiText("\u{1F4CA} BYOK Usage", "BYOK Usage")));
|
|
2747
|
+
console.log(chalk5.dim(uiSeparator()));
|
|
2909
2748
|
if (usageStats.periodStart) {
|
|
2910
2749
|
const periodStart = new Date(usageStats.periodStart);
|
|
2911
2750
|
const periodEnd = usageStats.periodEnd ? new Date(usageStats.periodEnd) : null;
|
|
2912
2751
|
const formattedStart = isNaN(periodStart.getTime()) ? usageStats.periodStart : periodStart.toLocaleDateString();
|
|
2913
2752
|
const formattedEnd = periodEnd && !isNaN(periodEnd.getTime()) ? periodEnd.toLocaleDateString() : void 0;
|
|
2914
2753
|
if (formattedEnd) {
|
|
2915
|
-
console.log(
|
|
2754
|
+
console.log(chalk5.dim(` Period: ${formattedStart} \u2192 ${formattedEnd}`));
|
|
2916
2755
|
} else {
|
|
2917
|
-
console.log(
|
|
2756
|
+
console.log(chalk5.dim(` Period start: ${formattedStart}`));
|
|
2918
2757
|
}
|
|
2919
2758
|
} else {
|
|
2920
|
-
console.log(
|
|
2759
|
+
console.log(chalk5.dim(" Period: Current month to date"));
|
|
2921
2760
|
}
|
|
2922
2761
|
const totalTokens = usageStats.totalInputTokens + usageStats.totalOutputTokens;
|
|
2923
|
-
console.log(` Tokens: ${
|
|
2924
|
-
console.log(` Estimated provider spend: ${
|
|
2762
|
+
console.log(` Tokens: ${chalk5.dim(totalTokens.toLocaleString())}`);
|
|
2763
|
+
console.log(` Estimated provider spend: ${chalk5.dim(`$${usageStats.totalBaseCost.toFixed(4)}`)}`);
|
|
2925
2764
|
console.log();
|
|
2926
|
-
console.log(
|
|
2765
|
+
console.log(chalk5.dim(" Model Usage:"));
|
|
2927
2766
|
if (usageStats.byModel.length > 0) {
|
|
2928
2767
|
for (const model of usageStats.byModel) {
|
|
2929
2768
|
const modelName = model.model.length > 32 ? model.model.slice(0, 29) + "..." : model.model;
|
|
2930
|
-
console.log(
|
|
2769
|
+
console.log(chalk5.dim(` ${modelName.padEnd(34)} $${model.cost.toFixed(4)}`));
|
|
2931
2770
|
}
|
|
2932
2771
|
} else {
|
|
2933
|
-
console.log(
|
|
2772
|
+
console.log(chalk5.dim(` ${"No usage yet".padEnd(34)} $0.0000`));
|
|
2934
2773
|
}
|
|
2935
|
-
console.log(
|
|
2774
|
+
console.log(chalk5.dim(uiSeparator()));
|
|
2936
2775
|
if (usageStatsUnavailable) {
|
|
2937
|
-
console.log(
|
|
2776
|
+
console.log(chalk5.dim("Usage details may be delayed. Run `archon usage` to refresh."));
|
|
2938
2777
|
}
|
|
2939
|
-
console.log(
|
|
2778
|
+
console.log(chalk5.dim("View details: archon usage | Models: archon preferences | Switch tier: archon upgrade"));
|
|
2940
2779
|
} catch {
|
|
2941
2780
|
}
|
|
2942
2781
|
}
|
|
@@ -2945,11 +2784,11 @@ async function start(options = {}) {
|
|
|
2945
2784
|
const hasKeys = await keyManager.hasAnyKey();
|
|
2946
2785
|
if (!hasKeys) {
|
|
2947
2786
|
console.log();
|
|
2948
|
-
console.log(
|
|
2949
|
-
console.log(
|
|
2950
|
-
console.log(` ${
|
|
2951
|
-
console.log(` ${
|
|
2952
|
-
console.log(` ${
|
|
2787
|
+
console.log(chalk5.yellow("\u26A0\uFE0F BYOK MODE: No API keys configured!"));
|
|
2788
|
+
console.log(chalk5.dim("You need at least one API key to use ArchonDev with BYOK.\n"));
|
|
2789
|
+
console.log(` ${chalk5.cyan("1")}) Add an API key now`);
|
|
2790
|
+
console.log(` ${chalk5.cyan("2")}) Switch to Managed Plan (no keys needed)`);
|
|
2791
|
+
console.log(` ${chalk5.cyan("3")}) Continue on Free tier`);
|
|
2953
2792
|
console.log();
|
|
2954
2793
|
const choice = await promptWithCommands("What would you like to do?", { allowMultiline: true });
|
|
2955
2794
|
switch (choice) {
|
|
@@ -2963,7 +2802,7 @@ async function start(options = {}) {
|
|
|
2963
2802
|
if (result.success) {
|
|
2964
2803
|
config.tier = "CREDITS";
|
|
2965
2804
|
await saveConfig(config);
|
|
2966
|
-
console.log(
|
|
2805
|
+
console.log(chalk5.green("\u2713 Switched to Managed Plan"));
|
|
2967
2806
|
const { handleTierSetup: setupCredits } = await import("./tier-selection-XFBM4SZ4.js");
|
|
2968
2807
|
await setupCredits("CREDITS");
|
|
2969
2808
|
}
|
|
@@ -2974,11 +2813,11 @@ async function start(options = {}) {
|
|
|
2974
2813
|
if (downgradeResult.success) {
|
|
2975
2814
|
config.tier = "FREE";
|
|
2976
2815
|
await saveConfig(config);
|
|
2977
|
-
console.log(
|
|
2816
|
+
console.log(chalk5.dim("Switched to Free tier."));
|
|
2978
2817
|
}
|
|
2979
2818
|
break;
|
|
2980
2819
|
default:
|
|
2981
|
-
console.log(
|
|
2820
|
+
console.log(chalk5.dim("Continuing without keys. Some features may not work."));
|
|
2982
2821
|
}
|
|
2983
2822
|
}
|
|
2984
2823
|
}
|
|
@@ -2989,7 +2828,7 @@ async function start(options = {}) {
|
|
|
2989
2828
|
}
|
|
2990
2829
|
const projectState = detectProjectState(cwd);
|
|
2991
2830
|
if (!projectState.hasArchitecture) {
|
|
2992
|
-
console.log(
|
|
2831
|
+
console.log(chalk5.dim("No project initialized in this folder.\n"));
|
|
2993
2832
|
const { init: init2 } = await import("./init-FINETS3Q.js");
|
|
2994
2833
|
await init2({ analyze: true, git: true });
|
|
2995
2834
|
console.log();
|
|
@@ -3003,37 +2842,27 @@ async function start(options = {}) {
|
|
|
3003
2842
|
const contextManager = new ContextManager();
|
|
3004
2843
|
const pendingAtomsData = await contextManager.getPendingAtomsData(cwd);
|
|
3005
2844
|
if (pendingAtomsData && pendingAtomsData.atoms.length > 0) {
|
|
3006
|
-
console.log(
|
|
2845
|
+
console.log(chalk5.yellow("[!] Previous session had pending atoms:\n"));
|
|
3007
2846
|
for (const atomId of pendingAtomsData.atoms) {
|
|
3008
|
-
console.log(
|
|
2847
|
+
console.log(chalk5.dim(` \u2022 ${atomId}`));
|
|
3009
2848
|
}
|
|
3010
2849
|
console.log();
|
|
3011
2850
|
const resume = await promptYesNo("Resume with these atoms?", true);
|
|
3012
2851
|
if (resume) {
|
|
3013
|
-
console.log(
|
|
2852
|
+
console.log(chalk5.green("\n\u2713 Resuming with pending atoms...\n"));
|
|
3014
2853
|
await contextManager.clearPendingAtoms(cwd);
|
|
3015
2854
|
} else {
|
|
3016
2855
|
const clear = await promptYesNo("Clear pending atoms?", false);
|
|
3017
2856
|
if (clear) {
|
|
3018
2857
|
await contextManager.clearPendingAtoms(cwd);
|
|
3019
|
-
console.log(
|
|
2858
|
+
console.log(chalk5.dim("Cleared pending atoms.\n"));
|
|
3020
2859
|
}
|
|
3021
2860
|
}
|
|
3022
2861
|
}
|
|
3023
2862
|
if (await shouldRunAutoCleanup(cwd)) {
|
|
3024
2863
|
await runAutoCleanupCheck(cwd);
|
|
3025
2864
|
}
|
|
3026
|
-
|
|
3027
|
-
case "NEW_PROJECT":
|
|
3028
|
-
await handleNewProject(cwd, projectState);
|
|
3029
|
-
break;
|
|
3030
|
-
case "ADAPT_EXISTING":
|
|
3031
|
-
await handleAdaptExisting(cwd, projectState);
|
|
3032
|
-
break;
|
|
3033
|
-
case "CONTINUE_SESSION":
|
|
3034
|
-
await handleContinueSession(cwd, projectState);
|
|
3035
|
-
break;
|
|
3036
|
-
}
|
|
2865
|
+
await runAgentMode(cwd, projectState);
|
|
3037
2866
|
}
|
|
3038
2867
|
function formatTierName(tier) {
|
|
3039
2868
|
switch (tier) {
|
|
@@ -3155,18 +2984,18 @@ async function fetchCreditsUsageStatsFromSupabase(accessToken, authId) {
|
|
|
3155
2984
|
}
|
|
3156
2985
|
}
|
|
3157
2986
|
function displayGovernanceStatus(status2) {
|
|
3158
|
-
console.log(
|
|
2987
|
+
console.log(chalk5.dim("Governance Status:"));
|
|
3159
2988
|
if (status2.hasArchitecture) {
|
|
3160
|
-
console.log(
|
|
2989
|
+
console.log(chalk5.green(" \u2713") + ` ARCHITECTURE.md (${status2.posture} posture)`);
|
|
3161
2990
|
if (status2.invariantsCount > 0) {
|
|
3162
|
-
console.log(
|
|
2991
|
+
console.log(chalk5.green(" \u2713") + ` ${status2.invariantsCount} invariants`);
|
|
3163
2992
|
}
|
|
3164
2993
|
if (status2.protectedPathsCount > 0) {
|
|
3165
|
-
console.log(
|
|
2994
|
+
console.log(chalk5.green(" \u2713") + ` ${status2.protectedPathsCount} protected paths`);
|
|
3166
2995
|
}
|
|
3167
2996
|
}
|
|
3168
2997
|
if (status2.pendingAtomsCount > 0) {
|
|
3169
|
-
console.log(
|
|
2998
|
+
console.log(chalk5.cyan(` \u2192 ${status2.pendingAtomsCount} atoms pending`));
|
|
3170
2999
|
}
|
|
3171
3000
|
console.log();
|
|
3172
3001
|
}
|
|
@@ -3297,117 +3126,12 @@ async function gatherGovernanceStatus(cwd) {
|
|
|
3297
3126
|
}
|
|
3298
3127
|
return status2;
|
|
3299
3128
|
}
|
|
3300
|
-
async function
|
|
3301
|
-
console.log(
|
|
3302
|
-
console.log(chalk6.dim("Answer as much or as little as you want \u2014 you can always refine later."));
|
|
3303
|
-
console.log(chalk6.dim('Type "just start" or "skip" to use defaults.\n'));
|
|
3304
|
-
const initialResponse = await promptWithCommands("What do you want to do?", { allowMultiline: true });
|
|
3305
|
-
if (!initialResponse.trim()) {
|
|
3306
|
-
console.log(chalk6.yellow("\nNo response provided. Showing options...\n"));
|
|
3307
|
-
await showNewProjectMenu(cwd);
|
|
3308
|
-
return;
|
|
3309
|
-
}
|
|
3310
|
-
const intent = detectUserIntent(initialResponse);
|
|
3311
|
-
if (wantsToSkip(initialResponse)) {
|
|
3312
|
-
console.log(chalk6.dim("\n> Using defaults \u2014 let's go!\n"));
|
|
3313
|
-
await quickStart(cwd);
|
|
3314
|
-
return;
|
|
3315
|
-
}
|
|
3316
|
-
if (intent.mode === "explore" && intent.confidence >= 0.7) {
|
|
3317
|
-
console.log(chalk6.dim("\n> Got it! Analyzing the project...\n"));
|
|
3318
|
-
await runExploreFlow(cwd, initialResponse);
|
|
3319
|
-
return;
|
|
3320
|
-
}
|
|
3321
|
-
if (intent.mode === "ad_hoc" && intent.confidence >= 0.7) {
|
|
3322
|
-
console.log(chalk6.dim("\n> Got it! Creating a task for this...\n"));
|
|
3323
|
-
const { plan: plan2 } = await import("./plan-W4WQY7BR.js");
|
|
3324
|
-
await plan2(initialResponse, { conversational: true });
|
|
3325
|
-
return;
|
|
3326
|
-
}
|
|
3327
|
-
if (intent.mode === "app_builder" && intent.confidence >= 0.7) {
|
|
3328
|
-
console.log(chalk6.dim("\n> Sounds like a bigger project. Let me ask a few quick questions...\n"));
|
|
3329
|
-
await runConversationalInterview(cwd, initialResponse);
|
|
3330
|
-
return;
|
|
3331
|
-
}
|
|
3332
|
-
if (needsClarification(intent)) {
|
|
3333
|
-
console.log();
|
|
3334
|
-
console.log(chalk6.dim("I'm not sure yet. You can tell me in plain language, or use shortcuts:"));
|
|
3335
|
-
console.log();
|
|
3336
|
-
console.log(` ${chalk6.cyan("1")}) ${chalk6.bold("Build something new")}`);
|
|
3337
|
-
console.log(` ${chalk6.cyan("2")}) ${chalk6.bold("Do a specific task")}`);
|
|
3338
|
-
console.log(` ${chalk6.cyan("3")}) ${chalk6.bold("Explore project/status")}`);
|
|
3339
|
-
console.log();
|
|
3340
|
-
const clarification = await promptWithCommands("What are you trying to do?", { allowMultiline: true });
|
|
3341
|
-
const trimmed = clarification.trim();
|
|
3342
|
-
if (trimmed === "1") {
|
|
3343
|
-
await runConversationalInterview(cwd, initialResponse);
|
|
3344
|
-
return;
|
|
3345
|
-
}
|
|
3346
|
-
if (trimmed === "2") {
|
|
3347
|
-
console.log(chalk6.dim("\n> Creating a task for this...\n"));
|
|
3348
|
-
const { plan: plan2 } = await import("./plan-W4WQY7BR.js");
|
|
3349
|
-
await plan2(initialResponse, { conversational: true });
|
|
3350
|
-
return;
|
|
3351
|
-
}
|
|
3352
|
-
if (trimmed === "3") {
|
|
3353
|
-
await showNewProjectMenu(cwd);
|
|
3354
|
-
return;
|
|
3355
|
-
}
|
|
3356
|
-
if (trimmed) {
|
|
3357
|
-
const handled = await handleFreeformJourneyInput(cwd, trimmed);
|
|
3358
|
-
if (handled) {
|
|
3359
|
-
return;
|
|
3360
|
-
}
|
|
3361
|
-
}
|
|
3362
|
-
await showNewProjectMenu(cwd);
|
|
3363
|
-
return;
|
|
3364
|
-
}
|
|
3365
|
-
await runConversationalInterview(cwd, initialResponse);
|
|
3366
|
-
}
|
|
3367
|
-
async function showNewProjectMenu(cwd) {
|
|
3368
|
-
console.log(chalk6.bold("What would you like to do?\n"));
|
|
3369
|
-
console.log(chalk6.dim("You can type naturally (recommended) or use a shortcut number:\n"));
|
|
3370
|
-
console.log(` ${chalk6.cyan("1")}) ${chalk6.bold("Start interview")} \u2014 I'll ask questions to understand your project`);
|
|
3371
|
-
console.log(` ${chalk6.cyan("2")}) ${chalk6.bold("Quick start")} \u2014 Just create basic governance files`);
|
|
3372
|
-
console.log(` ${chalk6.cyan("3")}) ${chalk6.bold("Plan a task")} \u2014 Create an atom for a specific task`);
|
|
3373
|
-
console.log(` ${chalk6.cyan("q")}) ${chalk6.dim("Quit")}`);
|
|
3374
|
-
console.log(chalk6.dim(' (Type "upgrade" or "help" anytime)'));
|
|
3375
|
-
console.log();
|
|
3376
|
-
const choice = await promptWithCommands("Enter choice");
|
|
3377
|
-
switch (choice.toLowerCase()) {
|
|
3378
|
-
case "1":
|
|
3379
|
-
await runConversationalInterview(cwd, "");
|
|
3380
|
-
break;
|
|
3381
|
-
case "2":
|
|
3382
|
-
await quickStart(cwd);
|
|
3383
|
-
break;
|
|
3384
|
-
case "3": {
|
|
3385
|
-
const description = await promptWithCommands("Describe what you want to do", { allowMultiline: true });
|
|
3386
|
-
if (description.trim()) {
|
|
3387
|
-
const { plan: plan2 } = await import("./plan-W4WQY7BR.js");
|
|
3388
|
-
await plan2(description, { conversational: true });
|
|
3389
|
-
}
|
|
3390
|
-
break;
|
|
3391
|
-
}
|
|
3392
|
-
case "q":
|
|
3393
|
-
process.exit(0);
|
|
3394
|
-
default:
|
|
3395
|
-
if (choice.trim()) {
|
|
3396
|
-
const handled = await handleFreeformJourneyInput(cwd, choice);
|
|
3397
|
-
if (handled) {
|
|
3398
|
-
return;
|
|
3399
|
-
}
|
|
3400
|
-
}
|
|
3401
|
-
console.log(chalk6.yellow("I did not catch that. Try again or describe what you want in plain language."));
|
|
3402
|
-
await showNewProjectMenu(cwd);
|
|
3403
|
-
}
|
|
3404
|
-
}
|
|
3405
|
-
async function runExploreFlow(cwd, followUpInput) {
|
|
3406
|
-
console.log(chalk6.blue("-- Analyzing Project --\n"));
|
|
3129
|
+
async function runExploreFlow(cwd, followUpInput, options = {}) {
|
|
3130
|
+
console.log(chalk5.blue("-- Analyzing Project --\n"));
|
|
3407
3131
|
const projectInfo = await gatherProjectInfo(cwd);
|
|
3408
|
-
console.log(
|
|
3132
|
+
console.log(chalk5.bold(uiText("\u{1F4C1} Project Overview\n", "Project Overview\n")));
|
|
3409
3133
|
if (projectInfo.name) {
|
|
3410
|
-
console.log(` Name: ${
|
|
3134
|
+
console.log(` Name: ${chalk5.cyan(projectInfo.name)}`);
|
|
3411
3135
|
}
|
|
3412
3136
|
if (projectInfo.language) {
|
|
3413
3137
|
console.log(` Language: ${projectInfo.language}`);
|
|
@@ -3419,46 +3143,50 @@ async function runExploreFlow(cwd, followUpInput) {
|
|
|
3419
3143
|
console.log(` Package Manager: ${projectInfo.packageManager}`);
|
|
3420
3144
|
}
|
|
3421
3145
|
console.log();
|
|
3422
|
-
console.log(
|
|
3423
|
-
console.log(` Source directories: ${projectInfo.sourceDirs.length > 0 ? projectInfo.sourceDirs.join(", ") :
|
|
3146
|
+
console.log(chalk5.bold(uiText("\u{1F4CA} Structure\n", "Structure\n")));
|
|
3147
|
+
console.log(` Source directories: ${projectInfo.sourceDirs.length > 0 ? projectInfo.sourceDirs.join(", ") : chalk5.dim("none detected")}`);
|
|
3424
3148
|
console.log(` Source files: ${projectInfo.sourceFileCount}`);
|
|
3425
3149
|
if (projectInfo.testFileCount > 0) {
|
|
3426
3150
|
console.log(` Test files: ${projectInfo.testFileCount}`);
|
|
3427
3151
|
}
|
|
3428
3152
|
console.log();
|
|
3429
|
-
console.log(
|
|
3153
|
+
console.log(chalk5.bold(uiText("\u{1F3DB}\uFE0F Governance\n", "Governance\n")));
|
|
3430
3154
|
if (projectInfo.hasArchitecture) {
|
|
3431
|
-
console.log(` ${
|
|
3155
|
+
console.log(` ${chalk5.green("\u2713")} ARCHITECTURE.md (${projectInfo.posture || "unknown"} posture)`);
|
|
3432
3156
|
if (projectInfo.invariantsCount > 0) {
|
|
3433
|
-
console.log(` ${
|
|
3157
|
+
console.log(` ${chalk5.green("\u2713")} ${projectInfo.invariantsCount} invariants defined`);
|
|
3434
3158
|
}
|
|
3435
3159
|
if (projectInfo.protectedPathsCount > 0) {
|
|
3436
|
-
console.log(` ${
|
|
3160
|
+
console.log(` ${chalk5.green("\u2713")} ${projectInfo.protectedPathsCount} protected paths`);
|
|
3437
3161
|
}
|
|
3438
3162
|
} else {
|
|
3439
|
-
console.log(` ${
|
|
3163
|
+
console.log(` ${chalk5.yellow("\u25CB")} No ARCHITECTURE.md yet`);
|
|
3440
3164
|
}
|
|
3441
3165
|
if (projectInfo.hasProgress) {
|
|
3442
|
-
console.log(` ${
|
|
3166
|
+
console.log(` ${chalk5.green("\u2713")} progress.txt exists`);
|
|
3443
3167
|
}
|
|
3444
3168
|
console.log();
|
|
3445
|
-
console.log(
|
|
3169
|
+
console.log(chalk5.green("\u2713 Analysis complete! I'm ready to work on this project.\n"));
|
|
3446
3170
|
const originalFollowUp = (followUpInput ?? "").trim();
|
|
3447
3171
|
const actionableFollowUp = extractActionableFollowUpFromExplore(originalFollowUp);
|
|
3448
3172
|
if (actionableFollowUp || containsActionIntent(originalFollowUp)) {
|
|
3449
3173
|
const request = actionableFollowUp ?? originalFollowUp;
|
|
3450
|
-
console.log(
|
|
3174
|
+
console.log(chalk5.dim("I finished the project scan. Continuing with your requested task...\n"));
|
|
3451
3175
|
await handlePostExploreAction(cwd, request);
|
|
3452
3176
|
return;
|
|
3453
3177
|
}
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3178
|
+
if (options.agentMode) {
|
|
3179
|
+
console.log(chalk5.dim("Tell me the next thing you want to do.\n"));
|
|
3180
|
+
return;
|
|
3181
|
+
}
|
|
3182
|
+
console.log(chalk5.bold("What would you like to do next?\n"));
|
|
3183
|
+
console.log(chalk5.dim("You can describe it naturally, or use shortcuts:\n"));
|
|
3184
|
+
console.log(` ${chalk5.cyan("1")}) ${chalk5.bold("Plan a task")} \u2014 Tell me what to implement, fix, or change`);
|
|
3185
|
+
console.log(` ${chalk5.cyan("2")}) ${chalk5.bold("Review code")} \u2014 Run AI-powered code review`);
|
|
3458
3186
|
if (!projectInfo.hasArchitecture) {
|
|
3459
|
-
console.log(` ${
|
|
3187
|
+
console.log(` ${chalk5.cyan("3")}) ${chalk5.bold("Set up governance")} \u2014 Generate ARCHITECTURE.md from this analysis`);
|
|
3460
3188
|
}
|
|
3461
|
-
console.log(` ${
|
|
3189
|
+
console.log(` ${chalk5.cyan("q")}) ${chalk5.dim("Quit")}`);
|
|
3462
3190
|
console.log();
|
|
3463
3191
|
const choice = await promptWithCommands("Enter choice");
|
|
3464
3192
|
switch (choice.toLowerCase()) {
|
|
@@ -3491,7 +3219,7 @@ async function runExploreFlow(cwd, followUpInput) {
|
|
|
3491
3219
|
return;
|
|
3492
3220
|
}
|
|
3493
3221
|
}
|
|
3494
|
-
console.log(
|
|
3222
|
+
console.log(chalk5.yellow("I did not catch that. Tell me what you want to do next."));
|
|
3495
3223
|
await showMainMenu();
|
|
3496
3224
|
}
|
|
3497
3225
|
}
|
|
@@ -3594,7 +3322,7 @@ async function runConversationalInterview(cwd, initialMessage) {
|
|
|
3594
3322
|
if (agent && agent.isAvailable()) {
|
|
3595
3323
|
await runAIInterview(cwd, initialMessage, agent);
|
|
3596
3324
|
} else {
|
|
3597
|
-
console.log(
|
|
3325
|
+
console.log(chalk5.dim("(Using simple setup - add API keys with `archon keys add` for AI-powered interview)\n"));
|
|
3598
3326
|
await runSimpleInterview(cwd, initialMessage);
|
|
3599
3327
|
}
|
|
3600
3328
|
}
|
|
@@ -3604,11 +3332,11 @@ async function runAIInterview(cwd, initialMessage, agent) {
|
|
|
3604
3332
|
try {
|
|
3605
3333
|
let turn = await agent.startInterview(initialMessage);
|
|
3606
3334
|
while (!turn.isComplete && turnCount < MAX_TURNS) {
|
|
3607
|
-
console.log(
|
|
3335
|
+
console.log(chalk5.blue("\u2192 ") + turn.question);
|
|
3608
3336
|
console.log();
|
|
3609
3337
|
const response = await prompt("");
|
|
3610
3338
|
if (wantsToSkip(response)) {
|
|
3611
|
-
console.log(
|
|
3339
|
+
console.log(chalk5.dim("\n> Using defaults for remaining questions.\n"));
|
|
3612
3340
|
break;
|
|
3613
3341
|
}
|
|
3614
3342
|
turn = await agent.continueInterview(response);
|
|
@@ -3620,12 +3348,12 @@ async function runAIInterview(cwd, initialMessage, agent) {
|
|
|
3620
3348
|
}
|
|
3621
3349
|
const usage = agent.getUsage();
|
|
3622
3350
|
if (usage.totalTokens > 0) {
|
|
3623
|
-
console.log(
|
|
3351
|
+
console.log(chalk5.dim(`
|
|
3624
3352
|
(Interview used ${usage.totalTokens} tokens, $${usage.baseCost.toFixed(4)})`));
|
|
3625
3353
|
}
|
|
3626
3354
|
await finishInterview(cwd, state, initialMessage);
|
|
3627
3355
|
} catch (error) {
|
|
3628
|
-
console.log(
|
|
3356
|
+
console.log(chalk5.yellow("\n[!] AI interview unavailable, using simple setup.\n"));
|
|
3629
3357
|
await runSimpleInterview(cwd, initialMessage);
|
|
3630
3358
|
}
|
|
3631
3359
|
}
|
|
@@ -3638,9 +3366,9 @@ async function runSimpleInterview(cwd, initialMessage) {
|
|
|
3638
3366
|
});
|
|
3639
3367
|
const known = getKnownInfo(state);
|
|
3640
3368
|
if (known.length > 0) {
|
|
3641
|
-
console.log(
|
|
3369
|
+
console.log(chalk5.dim("From what you said, I got:"));
|
|
3642
3370
|
for (const info of known) {
|
|
3643
|
-
console.log(
|
|
3371
|
+
console.log(chalk5.dim(` \u2022 ${info}`));
|
|
3644
3372
|
}
|
|
3645
3373
|
console.log();
|
|
3646
3374
|
}
|
|
@@ -3662,7 +3390,7 @@ async function runSimpleInterview(cwd, initialMessage) {
|
|
|
3662
3390
|
await finishInterview(cwd, state, initialMessage);
|
|
3663
3391
|
}
|
|
3664
3392
|
async function finishInterview(cwd, state, initialTaskHint) {
|
|
3665
|
-
console.log(
|
|
3393
|
+
console.log(chalk5.blue("\n-- Recording Project Details --\n"));
|
|
3666
3394
|
const posture = state.posture === "enterprise" ? "enterprise" : state.posture === "prototype" ? "prototype" : "production";
|
|
3667
3395
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
3668
3396
|
const progressEntry = `
|
|
@@ -3694,22 +3422,22 @@ ${state.forbiddenPatterns?.length ? `- **Forbidden patterns:** ${state.forbidden
|
|
|
3694
3422
|
writeFileSync2(progressPath, "# ArchonDev Progress Log\n\nThis file tracks learnings and decisions across sessions.\n");
|
|
3695
3423
|
}
|
|
3696
3424
|
appendFileSync(progressPath, progressEntry);
|
|
3697
|
-
console.log(
|
|
3425
|
+
console.log(chalk5.green("\n\u2713 Project details recorded!\n"));
|
|
3698
3426
|
const finalKnown = getKnownInfo(state);
|
|
3699
3427
|
if (finalKnown.length > 0) {
|
|
3700
|
-
console.log(
|
|
3428
|
+
console.log(chalk5.dim("Project configured with:"));
|
|
3701
3429
|
for (const info of finalKnown) {
|
|
3702
|
-
console.log(
|
|
3430
|
+
console.log(chalk5.dim(` \u2022 ${info}`));
|
|
3703
3431
|
}
|
|
3704
3432
|
console.log();
|
|
3705
3433
|
}
|
|
3706
|
-
console.log(
|
|
3707
|
-
console.log(` 1. ${
|
|
3708
|
-
console.log(` 2. ${
|
|
3434
|
+
console.log(chalk5.bold("Next steps:"));
|
|
3435
|
+
console.log(` 1. ${chalk5.cyan("Review")} ARCHITECTURE.md and customize if needed`);
|
|
3436
|
+
console.log(` 2. ${chalk5.cyan("Run")} ${chalk5.dim('archon plan "your first task"')} to create an atom`);
|
|
3709
3437
|
console.log();
|
|
3710
3438
|
const hintedTask = initialTaskHint?.trim() ?? "";
|
|
3711
3439
|
if (hintedTask) {
|
|
3712
|
-
console.log(
|
|
3440
|
+
console.log(chalk5.dim("Using your request above as the first task.\n"));
|
|
3713
3441
|
const { plan: plan2 } = await import("./plan-W4WQY7BR.js");
|
|
3714
3442
|
await plan2(hintedTask, { conversational: true });
|
|
3715
3443
|
return;
|
|
@@ -3727,7 +3455,7 @@ ${state.forbiddenPatterns?.length ? `- **Forbidden patterns:** ${state.forbidden
|
|
|
3727
3455
|
const hinted = initialTaskHint?.trim() ?? "";
|
|
3728
3456
|
if (hinted) {
|
|
3729
3457
|
description = hinted;
|
|
3730
|
-
console.log(
|
|
3458
|
+
console.log(chalk5.dim("\nUsing your request above as the first task.\n"));
|
|
3731
3459
|
} else {
|
|
3732
3460
|
description = await promptWithCommands("Describe what you want to build first", { allowMultiline: true });
|
|
3733
3461
|
}
|
|
@@ -3812,124 +3540,8 @@ function inferLanguageFromProjectFiles(cwd) {
|
|
|
3812
3540
|
}
|
|
3813
3541
|
return best?.language;
|
|
3814
3542
|
}
|
|
3815
|
-
async function quickStart(cwd) {
|
|
3816
|
-
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
3817
|
-
const progressPath = join6(cwd, "progress.txt");
|
|
3818
|
-
if (!existsSync6(progressPath)) {
|
|
3819
|
-
const { writeFileSync: writeFileSync2 } = await import("fs");
|
|
3820
|
-
writeFileSync2(progressPath, `# ArchonDev Progress Log
|
|
3821
|
-
|
|
3822
|
-
This file tracks learnings and decisions across sessions.
|
|
3823
|
-
|
|
3824
|
-
## ${today} - Project Initialized (Quick Start)
|
|
3825
|
-
|
|
3826
|
-
### What was done
|
|
3827
|
-
- Created ARCHITECTURE.md with default template
|
|
3828
|
-
- Initialized .archon directory
|
|
3829
|
-
- Created this progress.txt
|
|
3830
|
-
|
|
3831
|
-
### Next Steps
|
|
3832
|
-
1. Customize ARCHITECTURE.md for your project
|
|
3833
|
-
2. Run \`archon plan "your first task"\` to create an atom
|
|
3834
|
-
`);
|
|
3835
|
-
}
|
|
3836
|
-
console.log(chalk6.green("\u2713 Ready to go!\n"));
|
|
3837
|
-
await showMainMenu();
|
|
3838
|
-
}
|
|
3839
|
-
async function handleAdaptExisting(cwd, state) {
|
|
3840
|
-
if (state.hasArchitecture) {
|
|
3841
|
-
console.log(chalk6.bold("Project governance is set up!\n"));
|
|
3842
|
-
console.log(chalk6.dim("Type what you want to do, or choose an option below.\n"));
|
|
3843
|
-
} else {
|
|
3844
|
-
console.log(chalk6.bold("Existing project detected!\n"));
|
|
3845
|
-
console.log(chalk6.dim("I can analyze your codebase and adapt the governance files to match your structure."));
|
|
3846
|
-
console.log(chalk6.dim("This helps me understand your architecture without changing any code.\n"));
|
|
3847
|
-
}
|
|
3848
|
-
const response = await promptWithCommands("What would you like to do?", { allowMultiline: true });
|
|
3849
|
-
if (response.toLowerCase() === "q" || response.toLowerCase() === "quit") {
|
|
3850
|
-
process.exit(0);
|
|
3851
|
-
}
|
|
3852
|
-
if (!response.trim()) {
|
|
3853
|
-
await showAdaptExistingMenu(cwd, state);
|
|
3854
|
-
return;
|
|
3855
|
-
}
|
|
3856
|
-
const intent = detectUserIntent(response);
|
|
3857
|
-
if (intent.mode === "explore" && intent.confidence >= 0.7) {
|
|
3858
|
-
console.log(chalk6.dim("\n> Got it! Analyzing the project...\n"));
|
|
3859
|
-
await runExploreFlow(cwd, response);
|
|
3860
|
-
return;
|
|
3861
|
-
}
|
|
3862
|
-
if (intent.mode === "ad_hoc" && intent.confidence >= 0.7) {
|
|
3863
|
-
console.log(chalk6.dim("\n> Got it! Creating a task for this...\n"));
|
|
3864
|
-
const { plan: plan2 } = await import("./plan-W4WQY7BR.js");
|
|
3865
|
-
await plan2(response, { conversational: true });
|
|
3866
|
-
return;
|
|
3867
|
-
}
|
|
3868
|
-
if (intent.mode === "app_builder" && intent.confidence >= 0.7) {
|
|
3869
|
-
console.log(chalk6.dim("\n> Let me understand your project better...\n"));
|
|
3870
|
-
await runConversationalInterview(cwd, response);
|
|
3871
|
-
return;
|
|
3872
|
-
}
|
|
3873
|
-
if (response.trim()) {
|
|
3874
|
-
const handled = await handleFreeformJourneyInput(cwd, response);
|
|
3875
|
-
if (handled) {
|
|
3876
|
-
return;
|
|
3877
|
-
}
|
|
3878
|
-
}
|
|
3879
|
-
await showAdaptExistingMenu(cwd, state);
|
|
3880
|
-
}
|
|
3881
|
-
async function showAdaptExistingMenu(cwd, state) {
|
|
3882
|
-
console.log();
|
|
3883
|
-
console.log(chalk6.bold("What would you like to do?\n"));
|
|
3884
|
-
console.log(chalk6.dim("You can type naturally (recommended) or use a shortcut number:\n"));
|
|
3885
|
-
console.log(` ${chalk6.cyan("1")}) ${chalk6.bold("Analyze project")} \u2014 Scan and summarize the codebase`);
|
|
3886
|
-
console.log(` ${chalk6.cyan("2")}) ${chalk6.bold("Plan a task")} \u2014 Create an implementation plan for something specific`);
|
|
3887
|
-
console.log(` ${chalk6.cyan("3")}) ${chalk6.bold("Code review")} \u2014 Review code for issues`);
|
|
3888
|
-
if (!state.hasArchitecture) {
|
|
3889
|
-
console.log(` ${chalk6.cyan("4")}) ${chalk6.bold("Set up governance")} \u2014 Create ARCHITECTURE.md from your code`);
|
|
3890
|
-
}
|
|
3891
|
-
console.log(` ${chalk6.cyan("q")}) ${chalk6.dim("Quit")}`);
|
|
3892
|
-
console.log(chalk6.dim(' (Type "upgrade" or "help" anytime)'));
|
|
3893
|
-
console.log();
|
|
3894
|
-
const choice = await promptWithCommands("Enter choice");
|
|
3895
|
-
switch (choice.toLowerCase()) {
|
|
3896
|
-
case "1":
|
|
3897
|
-
await runExploreFlow(cwd);
|
|
3898
|
-
break;
|
|
3899
|
-
case "2": {
|
|
3900
|
-
const description = await promptWithCommands("Describe what you want to do", { allowMultiline: true });
|
|
3901
|
-
if (description.trim()) {
|
|
3902
|
-
const { plan: plan2 } = await import("./plan-W4WQY7BR.js");
|
|
3903
|
-
await plan2(description, { conversational: true });
|
|
3904
|
-
}
|
|
3905
|
-
break;
|
|
3906
|
-
}
|
|
3907
|
-
case "3":
|
|
3908
|
-
await codeReviewFirst(cwd);
|
|
3909
|
-
break;
|
|
3910
|
-
case "4":
|
|
3911
|
-
if (!state.hasArchitecture) {
|
|
3912
|
-
await analyzeAndAdapt(cwd);
|
|
3913
|
-
} else {
|
|
3914
|
-
console.log(chalk6.yellow("Invalid choice. Please try again."));
|
|
3915
|
-
await showAdaptExistingMenu(cwd, state);
|
|
3916
|
-
}
|
|
3917
|
-
break;
|
|
3918
|
-
case "q":
|
|
3919
|
-
process.exit(0);
|
|
3920
|
-
default:
|
|
3921
|
-
if (choice.trim()) {
|
|
3922
|
-
const handled = await handleFreeformJourneyInput(cwd, choice);
|
|
3923
|
-
if (handled) {
|
|
3924
|
-
return;
|
|
3925
|
-
}
|
|
3926
|
-
}
|
|
3927
|
-
console.log(chalk6.yellow("I did not catch that. Try again or describe what you want in plain language."));
|
|
3928
|
-
await showAdaptExistingMenu(cwd, state);
|
|
3929
|
-
}
|
|
3930
|
-
}
|
|
3931
3543
|
async function analyzeAndAdapt(cwd) {
|
|
3932
|
-
console.log(
|
|
3544
|
+
console.log(chalk5.blue("\n-- Analyzing Project --\n"));
|
|
3933
3545
|
const { init: init2 } = await import("./init-FINETS3Q.js");
|
|
3934
3546
|
await init2({ analyze: true, git: true });
|
|
3935
3547
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -3951,12 +3563,12 @@ async function analyzeAndAdapt(cwd) {
|
|
|
3951
3563
|
- .archon/config.yaml - Build commands configured
|
|
3952
3564
|
- progress.txt - This file
|
|
3953
3565
|
`);
|
|
3954
|
-
console.log(
|
|
3566
|
+
console.log(chalk5.green("\n\u2713 Governance files adapted!\n"));
|
|
3955
3567
|
await showMainMenu();
|
|
3956
3568
|
}
|
|
3957
3569
|
async function codeReviewFirst(cwd) {
|
|
3958
|
-
console.log(
|
|
3959
|
-
console.log(
|
|
3570
|
+
console.log(chalk5.blue("\n-- Code Review Mode --\n"));
|
|
3571
|
+
console.log(chalk5.dim("I'll analyze your code for issues without making any changes.\n"));
|
|
3960
3572
|
const { reviewInit: reviewInit2, reviewAnalyze: reviewAnalyze2, reviewRun: reviewRun2 } = await import("./review-BXESOS5R.js");
|
|
3961
3573
|
const reviewDbPath = join6(cwd, "docs", "code-review", "review-tasks.db");
|
|
3962
3574
|
if (!existsSync6(reviewDbPath)) {
|
|
@@ -3967,55 +3579,100 @@ async function codeReviewFirst(cwd) {
|
|
|
3967
3579
|
if (runReview) {
|
|
3968
3580
|
await reviewRun2({ all: true });
|
|
3969
3581
|
}
|
|
3970
|
-
console.log(
|
|
3582
|
+
console.log(chalk5.dim("\nAfter reviewing, you can run ") + chalk5.cyan("archon") + chalk5.dim(" again to set up governance.\n"));
|
|
3971
3583
|
}
|
|
3972
|
-
async function
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
const handoff = checkForHandoff(cwd);
|
|
3980
|
-
if (handoff) {
|
|
3981
|
-
console.log(chalk6.yellow("[HANDOFF] Found from last session:\n"));
|
|
3982
|
-
console.log(chalk6.dim(handoff.nextSteps));
|
|
3983
|
-
console.log();
|
|
3984
|
-
const continueHandoff = await promptYesNo("Continue from handoff?", true);
|
|
3985
|
-
if (continueHandoff) {
|
|
3986
|
-
console.log(chalk6.dim("\nPicking up where you left off...\n"));
|
|
3987
|
-
}
|
|
3988
|
-
}
|
|
3989
|
-
if (state.hasReviewDb) {
|
|
3990
|
-
await showReviewProgress(cwd);
|
|
3991
|
-
}
|
|
3992
|
-
const response = await promptWithCommands("What would you like to do next? (press Enter for options)", { allowMultiline: true });
|
|
3993
|
-
if (response.trim()) {
|
|
3994
|
-
const handled = await handleFreeformJourneyInput(cwd, response);
|
|
3995
|
-
if (handled) {
|
|
3996
|
-
await continueConversationLoop(cwd);
|
|
3997
|
-
return;
|
|
3584
|
+
async function runAgentMode(cwd, state) {
|
|
3585
|
+
if (state.scenario === "CONTINUE_SESSION") {
|
|
3586
|
+
console.log(chalk5.bold("Welcome back!\n"));
|
|
3587
|
+
if (state.lastProgressEntry) {
|
|
3588
|
+
console.log(chalk5.dim("Last activity:"));
|
|
3589
|
+
console.log(chalk5.dim(" " + state.lastProgressEntry.split("\n")[0]));
|
|
3590
|
+
console.log();
|
|
3998
3591
|
}
|
|
3592
|
+
} else if (state.scenario === "NEW_PROJECT") {
|
|
3593
|
+
console.log(chalk5.bold("Starting in chat mode.\n"));
|
|
3594
|
+
console.log(chalk5.dim("Tell me what you want to build. I will apply governance checks in the background.\n"));
|
|
3595
|
+
} else {
|
|
3596
|
+
console.log(chalk5.bold("Ready in chat mode.\n"));
|
|
3597
|
+
console.log(chalk5.dim("Tell me what you want to do. Use /workflow for the classic menu.\n"));
|
|
3999
3598
|
}
|
|
4000
|
-
await showMainMenu();
|
|
4001
|
-
}
|
|
4002
|
-
async function continueConversationLoop(cwd) {
|
|
4003
3599
|
while (true) {
|
|
4004
|
-
const response = await promptWithCommands(
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
3600
|
+
const response = await promptWithCommands(
|
|
3601
|
+
"What should we work on next? (use /workflow for menu)",
|
|
3602
|
+
{ allowMultiline: true }
|
|
3603
|
+
);
|
|
3604
|
+
const trimmed = response.trim();
|
|
3605
|
+
if (!trimmed) {
|
|
3606
|
+
continue;
|
|
4008
3607
|
}
|
|
4009
|
-
if (
|
|
4010
|
-
await
|
|
3608
|
+
if (trimmed.toLowerCase() === "/workflow") {
|
|
3609
|
+
await showMainMenu();
|
|
4011
3610
|
continue;
|
|
4012
3611
|
}
|
|
4013
|
-
const handled = await
|
|
3612
|
+
const handled = await handleAgentConversationInput(cwd, trimmed);
|
|
4014
3613
|
if (!handled) {
|
|
4015
|
-
console.log(
|
|
3614
|
+
console.log(chalk5.yellow("I did not catch that. Describe your goal in one sentence."));
|
|
4016
3615
|
}
|
|
4017
3616
|
}
|
|
4018
3617
|
}
|
|
3618
|
+
async function handleAgentConversationInput(cwd, input) {
|
|
3619
|
+
const normalized = input.trim().toLowerCase();
|
|
3620
|
+
if (!normalized) return false;
|
|
3621
|
+
if (isContinuationDirective(normalized)) {
|
|
3622
|
+
await continueWithCurrentTask(cwd);
|
|
3623
|
+
return true;
|
|
3624
|
+
}
|
|
3625
|
+
if (isReferenceToPreviousRequest(normalized)) {
|
|
3626
|
+
await showLatestPlannedAtom(cwd);
|
|
3627
|
+
return true;
|
|
3628
|
+
}
|
|
3629
|
+
const intent = detectUserIntent(input);
|
|
3630
|
+
if (intent.mode === "explore" && intent.confidence >= 0.7) {
|
|
3631
|
+
console.log(chalk5.dim("\n> Got it! Analyzing the project...\n"));
|
|
3632
|
+
await runExploreFlow(cwd, input, { agentMode: true });
|
|
3633
|
+
return true;
|
|
3634
|
+
}
|
|
3635
|
+
console.log(chalk5.dim("\n> Got it! Creating a task for this...\n"));
|
|
3636
|
+
const { plan: plan2 } = await import("./plan-W4WQY7BR.js");
|
|
3637
|
+
await plan2(input, { conversational: true });
|
|
3638
|
+
if (shouldStopAfterPlanning(input)) {
|
|
3639
|
+
await showLatestPlannedAtom(cwd);
|
|
3640
|
+
return true;
|
|
3641
|
+
}
|
|
3642
|
+
await continueWithCurrentTask(cwd);
|
|
3643
|
+
return true;
|
|
3644
|
+
}
|
|
3645
|
+
function isReferenceToPreviousRequest(input) {
|
|
3646
|
+
const normalized = input.toLowerCase().replace(/[^\w\s]/g, " ").replace(/\s+/g, " ").trim();
|
|
3647
|
+
if (!normalized) return false;
|
|
3648
|
+
return normalized === "that" || normalized === "that one" || normalized === "same thing" || normalized === "same request" || normalized.includes("what i wrote already") || normalized.includes("what i already wrote") || normalized.includes("same as above") || normalized.includes("as above") || normalized.includes("same as earlier") || normalized.includes("use what i wrote");
|
|
3649
|
+
}
|
|
3650
|
+
function shouldStopAfterPlanning(input) {
|
|
3651
|
+
const normalized = input.toLowerCase();
|
|
3652
|
+
return normalized.includes("plan before") || normalized.includes("before continuing") || normalized.includes("before we continue") || normalized.includes("show me your plan") || normalized.includes("give me your plan") || normalized.includes("come up with a plan") || normalized.includes("do not start yet");
|
|
3653
|
+
}
|
|
3654
|
+
async function showLatestPlannedAtom(cwd) {
|
|
3655
|
+
const { listLocalAtoms: listLocalAtoms2 } = await import("./plan-W4WQY7BR.js");
|
|
3656
|
+
const atoms = await listLocalAtoms2();
|
|
3657
|
+
if (atoms.length === 0) {
|
|
3658
|
+
console.log(chalk5.yellow("No atoms found yet. Tell me what to plan."));
|
|
3659
|
+
return;
|
|
3660
|
+
}
|
|
3661
|
+
const latest = atoms.slice().sort((a, b) => {
|
|
3662
|
+
const aTime = new Date(String(a.updatedAt)).getTime();
|
|
3663
|
+
const bTime = new Date(String(b.updatedAt)).getTime();
|
|
3664
|
+
return bTime - aTime;
|
|
3665
|
+
})[0];
|
|
3666
|
+
if (!latest) {
|
|
3667
|
+
console.log(chalk5.yellow("No atoms found yet. Tell me what to plan."));
|
|
3668
|
+
return;
|
|
3669
|
+
}
|
|
3670
|
+
console.log(chalk5.dim(`
|
|
3671
|
+
Showing latest planned atom (${latest.externalId})...
|
|
3672
|
+
`));
|
|
3673
|
+
const { show: show2 } = await import("./show-CXJPLCXD.js");
|
|
3674
|
+
await show2(latest.externalId);
|
|
3675
|
+
}
|
|
4019
3676
|
function isContinuationDirective(input) {
|
|
4020
3677
|
const normalized = input.trim().toLowerCase();
|
|
4021
3678
|
return normalized === "continue" || normalized === "continue." || normalized === "go on" || normalized === "go ahead" || normalized === "next" || normalized === "proceed" || normalized === "do it";
|
|
@@ -4025,57 +3682,32 @@ async function continueWithCurrentTask(cwd) {
|
|
|
4025
3682
|
const atoms = await listLocalAtoms2();
|
|
4026
3683
|
const pending = atoms.filter((a) => a.status === "READY" || a.status === "IN_PROGRESS").sort((a, b) => a.externalId.localeCompare(b.externalId));
|
|
4027
3684
|
if (pending.length === 0) {
|
|
4028
|
-
console.log(
|
|
3685
|
+
console.log(chalk5.yellow("No pending atoms found. Tell me what to plan next."));
|
|
4029
3686
|
return;
|
|
4030
3687
|
}
|
|
4031
3688
|
const nextAtom = pending[0];
|
|
4032
3689
|
if (!nextAtom) {
|
|
4033
|
-
console.log(
|
|
3690
|
+
console.log(chalk5.yellow("No pending atoms found. Tell me what to plan next."));
|
|
4034
3691
|
return;
|
|
4035
3692
|
}
|
|
4036
|
-
console.log(
|
|
3693
|
+
console.log(chalk5.dim(`
|
|
4037
3694
|
Continuing with ${nextAtom.externalId}...
|
|
4038
3695
|
`));
|
|
4039
3696
|
const { execute: execute2 } = await import("./execute-3IUO33KY.js");
|
|
4040
3697
|
await execute2(nextAtom.externalId, {});
|
|
4041
3698
|
}
|
|
4042
|
-
function checkForHandoff(cwd) {
|
|
4043
|
-
try {
|
|
4044
|
-
const currentContextPath = join6(cwd, ".archon", "current_context.md");
|
|
4045
|
-
if (existsSync6(currentContextPath)) {
|
|
4046
|
-
const content2 = readFileSync3(currentContextPath, "utf-8");
|
|
4047
|
-
const nextStepsMatch = content2.match(/## Next Actions[^\n]*\n([\s\S]*?)(?=\n## |\n*$)/);
|
|
4048
|
-
if (nextStepsMatch && nextStepsMatch[1]) {
|
|
4049
|
-
return { nextSteps: nextStepsMatch[1].trim() };
|
|
4050
|
-
}
|
|
4051
|
-
}
|
|
4052
|
-
const progressPath = join6(cwd, "progress.txt");
|
|
4053
|
-
if (!existsSync6(progressPath)) return null;
|
|
4054
|
-
const content = readFileSync3(progressPath, "utf-8");
|
|
4055
|
-
const handoffMatch = content.match(/## Context Handoff[^\n]*\n([\s\S]*?)(?=\n## |\n*$)/);
|
|
4056
|
-
if (handoffMatch && handoffMatch[1]) {
|
|
4057
|
-
const handoffContent = handoffMatch[1];
|
|
4058
|
-
const nextStepsMatch = handoffContent.match(/### Next Steps[^\n]*\n([\s\S]*?)(?=\n### |$)/);
|
|
4059
|
-
if (nextStepsMatch && nextStepsMatch[1]) {
|
|
4060
|
-
return { nextSteps: nextStepsMatch[1].trim() };
|
|
4061
|
-
}
|
|
4062
|
-
}
|
|
4063
|
-
} catch {
|
|
4064
|
-
}
|
|
4065
|
-
return null;
|
|
4066
|
-
}
|
|
4067
3699
|
async function showMainMenu() {
|
|
4068
3700
|
const cwd = process.cwd();
|
|
4069
3701
|
while (true) {
|
|
4070
3702
|
const state = detectProjectState(cwd);
|
|
4071
|
-
console.log(
|
|
3703
|
+
console.log(chalk5.bold("What would you like to do?\n"));
|
|
4072
3704
|
if (state.isWebProject) {
|
|
4073
3705
|
const { loadWebChecks, formatWebCheckStatus } = await import("./web-checks-4BSYXWDF.js");
|
|
4074
3706
|
const prefs = await loadWebChecks(cwd);
|
|
4075
|
-
console.log(
|
|
4076
|
-
console.log(
|
|
4077
|
-
console.log(
|
|
4078
|
-
console.log(
|
|
3707
|
+
console.log(chalk5.dim("Web checks status:"));
|
|
3708
|
+
console.log(chalk5.dim(` A11y: ${formatWebCheckStatus(prefs.lastRun?.a11y)}`));
|
|
3709
|
+
console.log(chalk5.dim(` SEO: ${formatWebCheckStatus(prefs.lastRun?.seo)}`));
|
|
3710
|
+
console.log(chalk5.dim(` GEO: ${formatWebCheckStatus(prefs.lastRun?.geo)}`));
|
|
4079
3711
|
console.log();
|
|
4080
3712
|
}
|
|
4081
3713
|
const choices = [
|
|
@@ -4096,9 +3728,9 @@ async function showMainMenu() {
|
|
|
4096
3728
|
{ key: "q", label: "Quit", action: async () => process.exit(0) }
|
|
4097
3729
|
];
|
|
4098
3730
|
for (const choice2 of choices) {
|
|
4099
|
-
console.log(` ${
|
|
3731
|
+
console.log(` ${chalk5.cyan(choice2.key)}) ${choice2.label}`);
|
|
4100
3732
|
}
|
|
4101
|
-
console.log(
|
|
3733
|
+
console.log(chalk5.dim(' (Type "/" for quick commands, or "upgrade"/"help" anytime)'));
|
|
4102
3734
|
console.log();
|
|
4103
3735
|
const selected = await promptWithCommands("Tell me what you want to do (or enter a shortcut)", { allowMultiline: true });
|
|
4104
3736
|
const choice = choices.find((c) => c.key === selected.toLowerCase());
|
|
@@ -4109,11 +3741,11 @@ async function showMainMenu() {
|
|
|
4109
3741
|
if (selected.trim()) {
|
|
4110
3742
|
const handled = await handleFreeformJourneyInput(cwd, selected.trim());
|
|
4111
3743
|
if (!handled) {
|
|
4112
|
-
console.log(
|
|
3744
|
+
console.log(chalk5.yellow("I did not catch that. Try describing your goal in one sentence."));
|
|
4113
3745
|
}
|
|
4114
3746
|
continue;
|
|
4115
3747
|
}
|
|
4116
|
-
console.log(
|
|
3748
|
+
console.log(chalk5.yellow("Invalid choice. Please try again."));
|
|
4117
3749
|
}
|
|
4118
3750
|
}
|
|
4119
3751
|
async function handleFreeformJourneyInput(cwd, input) {
|
|
@@ -4121,23 +3753,23 @@ async function handleFreeformJourneyInput(cwd, input) {
|
|
|
4121
3753
|
if (!freeform) return false;
|
|
4122
3754
|
const intent = detectUserIntent(freeform);
|
|
4123
3755
|
if (intent.mode === "explore" && intent.confidence >= 0.7) {
|
|
4124
|
-
console.log(
|
|
3756
|
+
console.log(chalk5.dim("\n> Got it! Analyzing the project...\n"));
|
|
4125
3757
|
await runExploreFlow(cwd, freeform);
|
|
4126
3758
|
return true;
|
|
4127
3759
|
}
|
|
4128
3760
|
if (intent.mode === "app_builder" && intent.confidence >= 0.7) {
|
|
4129
3761
|
const state = detectProjectState(cwd);
|
|
4130
3762
|
if (state.hasArchitecture) {
|
|
4131
|
-
console.log(
|
|
3763
|
+
console.log(chalk5.dim("\n> Got it! Creating a task for this...\n"));
|
|
4132
3764
|
const { plan: plan3 } = await import("./plan-W4WQY7BR.js");
|
|
4133
3765
|
await plan3(freeform, { conversational: true });
|
|
4134
3766
|
return true;
|
|
4135
3767
|
}
|
|
4136
|
-
console.log(
|
|
3768
|
+
console.log(chalk5.dim("\n> Let me understand your project better...\n"));
|
|
4137
3769
|
await runConversationalInterview(cwd, freeform);
|
|
4138
3770
|
return true;
|
|
4139
3771
|
}
|
|
4140
|
-
console.log(
|
|
3772
|
+
console.log(chalk5.dim("\n> Got it! Creating a task for this...\n"));
|
|
4141
3773
|
const { plan: plan2 } = await import("./plan-W4WQY7BR.js");
|
|
4142
3774
|
await plan2(freeform, { conversational: true });
|
|
4143
3775
|
return true;
|
|
@@ -4179,36 +3811,18 @@ function containsActionIntent(input) {
|
|
|
4179
3811
|
async function handlePostExploreAction(cwd, request) {
|
|
4180
3812
|
const intent = detectUserIntent(request);
|
|
4181
3813
|
if (intent.mode === "app_builder" && intent.confidence >= 0.7) {
|
|
4182
|
-
console.log(
|
|
3814
|
+
console.log(chalk5.dim("> Let me understand your project better...\n"));
|
|
4183
3815
|
await runConversationalInterview(cwd, request);
|
|
4184
3816
|
return;
|
|
4185
3817
|
}
|
|
4186
3818
|
if (intent.mode === "explore" && intent.confidence >= 0.7) {
|
|
4187
|
-
console.log(
|
|
3819
|
+
console.log(chalk5.dim("> I can go deeper. Creating a concrete task from your request...\n"));
|
|
4188
3820
|
} else {
|
|
4189
|
-
console.log(
|
|
3821
|
+
console.log(chalk5.dim("> Got it! Creating a task for this...\n"));
|
|
4190
3822
|
}
|
|
4191
3823
|
const { plan: plan2 } = await import("./plan-W4WQY7BR.js");
|
|
4192
3824
|
await plan2(request, { conversational: true });
|
|
4193
3825
|
}
|
|
4194
|
-
async function showReviewProgress(cwd) {
|
|
4195
|
-
try {
|
|
4196
|
-
const { ReviewDatabase } = await import("./code-review-GJVBZPZA.js");
|
|
4197
|
-
const db = new ReviewDatabase(cwd);
|
|
4198
|
-
db.open();
|
|
4199
|
-
const stats = db.getStats();
|
|
4200
|
-
db.close();
|
|
4201
|
-
const total = stats.total;
|
|
4202
|
-
const completed = stats.completed;
|
|
4203
|
-
const pending = stats.pending + stats.inReview;
|
|
4204
|
-
const needsFix = stats.needsFix;
|
|
4205
|
-
console.log(
|
|
4206
|
-
chalk6.blue("Review Progress:") + chalk6.dim(` ${completed}/${total} completed`) + (needsFix > 0 ? chalk6.red(` (${needsFix} need fixes)`) : "") + (pending > 0 ? chalk6.yellow(` (${pending} pending)`) : "")
|
|
4207
|
-
);
|
|
4208
|
-
console.log();
|
|
4209
|
-
} catch {
|
|
4210
|
-
}
|
|
4211
|
-
}
|
|
4212
3826
|
async function planTask() {
|
|
4213
3827
|
const { plan: plan2 } = await import("./plan-W4WQY7BR.js");
|
|
4214
3828
|
const description = await promptWithCommands("Describe what you want to build", { allowMultiline: true });
|
|
@@ -4229,7 +3843,7 @@ async function executeNext() {
|
|
|
4229
3843
|
const pendingAtoms = atoms.filter((a) => a.status === "READY" || a.status === "IN_PROGRESS");
|
|
4230
3844
|
const readyAtoms = atoms.filter((a) => a.status === "READY");
|
|
4231
3845
|
if (pendingAtoms.length === 0) {
|
|
4232
|
-
console.log(
|
|
3846
|
+
console.log(chalk5.yellow('No pending atoms. Use "archon plan" to create one.'));
|
|
4233
3847
|
return;
|
|
4234
3848
|
}
|
|
4235
3849
|
if (pendingAtoms.length > 1) {
|
|
@@ -4237,20 +3851,20 @@ async function executeNext() {
|
|
|
4237
3851
|
const prefs = await loadExecutionPreferences(cwd);
|
|
4238
3852
|
const config = await loadConfig();
|
|
4239
3853
|
const canUseCloud = (config.tier ?? "FREE") === "CREDITS";
|
|
4240
|
-
console.log(
|
|
4241
|
-
console.log(` ${
|
|
4242
|
-
console.log(` ${
|
|
4243
|
-
console.log(` ${
|
|
4244
|
-
console.log(` ${
|
|
3854
|
+
console.log(chalk5.blue("\n-- Project Analysis --\n"));
|
|
3855
|
+
console.log(` ${chalk5.bold("Atoms:")} ${analysis.atomCount}`);
|
|
3856
|
+
console.log(` ${chalk5.bold("Estimated:")} ${analysis.estimatedMinutes} minutes`);
|
|
3857
|
+
console.log(` ${chalk5.bold("Complexity:")} ${analysis.complexity} - ${getComplexityDescription(analysis.complexity)}`);
|
|
3858
|
+
console.log(` ${chalk5.bold("Suggested:")} ${analysis.suggestedMode} - ${getModeDescription(analysis.suggestedMode)}`);
|
|
4245
3859
|
console.log();
|
|
4246
3860
|
let selectedMode = "sequential";
|
|
4247
3861
|
if (canUseCloud && prefs.cloudMode === "always" && analysis.suggestedMode === "parallel-cloud") {
|
|
4248
3862
|
selectedMode = "parallel-cloud";
|
|
4249
|
-
console.log(
|
|
3863
|
+
console.log(chalk5.green(`
|
|
4250
3864
|
\u2713 Auto-selected parallel cloud execution (preference: always)`));
|
|
4251
3865
|
} else if (prefs.parallelMode === "always" && analysis.suggestedMode !== "sequential") {
|
|
4252
3866
|
selectedMode = "parallel-local";
|
|
4253
|
-
console.log(
|
|
3867
|
+
console.log(chalk5.green(`
|
|
4254
3868
|
\u2713 Auto-selected parallel local execution (preference: always)`));
|
|
4255
3869
|
} else if (prefs.parallelMode === "ask" || canUseCloud && prefs.cloudMode === "ask") {
|
|
4256
3870
|
const options = [
|
|
@@ -4266,18 +3880,18 @@ async function executeNext() {
|
|
|
4266
3880
|
}
|
|
4267
3881
|
if (selectedMode !== "sequential") {
|
|
4268
3882
|
if (readyAtoms.length === 0) {
|
|
4269
|
-
console.log(
|
|
3883
|
+
console.log(chalk5.yellow("No READY atoms available for parallel execution."));
|
|
4270
3884
|
return;
|
|
4271
3885
|
}
|
|
4272
|
-
console.log(
|
|
3886
|
+
console.log(chalk5.dim("\nPending atoms:"));
|
|
4273
3887
|
for (const atom of readyAtoms) {
|
|
4274
|
-
console.log(
|
|
3888
|
+
console.log(chalk5.dim(` - ${atom.id}: ${atom.title}`));
|
|
4275
3889
|
}
|
|
4276
3890
|
console.log();
|
|
4277
3891
|
const raw = await prompt("Enter atom IDs to run in parallel (comma-separated, or press Enter for all)");
|
|
4278
3892
|
const selectedIds = raw.trim() ? raw.split(",").map((s) => s.trim()).filter(Boolean) : readyAtoms.map((a) => a.id);
|
|
4279
3893
|
if (selectedIds.length === 0) {
|
|
4280
|
-
console.log(
|
|
3894
|
+
console.log(chalk5.yellow("No atoms selected."));
|
|
4281
3895
|
return;
|
|
4282
3896
|
}
|
|
4283
3897
|
let runIds = selectedIds;
|
|
@@ -4288,7 +3902,7 @@ async function executeNext() {
|
|
|
4288
3902
|
);
|
|
4289
3903
|
if (!override) {
|
|
4290
3904
|
runIds = selectedIds.slice(0, prefs.maxParallelAgents);
|
|
4291
|
-
console.log(
|
|
3905
|
+
console.log(chalk5.dim(`Running first ${runIds.length} atoms.`));
|
|
4292
3906
|
}
|
|
4293
3907
|
}
|
|
4294
3908
|
if (selectedMode === "parallel-cloud") {
|
|
@@ -4307,7 +3921,7 @@ async function executeNext() {
|
|
|
4307
3921
|
const { execute: execute2 } = await import("./execute-3IUO33KY.js");
|
|
4308
3922
|
await execute2(targetId, {});
|
|
4309
3923
|
} else {
|
|
4310
|
-
console.log(
|
|
3924
|
+
console.log(chalk5.yellow("No atom to execute."));
|
|
4311
3925
|
}
|
|
4312
3926
|
}
|
|
4313
3927
|
async function reportBug() {
|
|
@@ -4329,19 +3943,19 @@ async function reviewCode() {
|
|
|
4329
3943
|
const cwd = process.cwd();
|
|
4330
3944
|
const reviewDbPath = join6(cwd, "docs", "code-review", "review-tasks.db");
|
|
4331
3945
|
if (!existsSync6(reviewDbPath)) {
|
|
4332
|
-
console.log(
|
|
3946
|
+
console.log(chalk5.dim("Code review not initialized. Starting setup...\n"));
|
|
4333
3947
|
const { reviewInit: reviewInit2 } = await import("./review-BXESOS5R.js");
|
|
4334
3948
|
await reviewInit2();
|
|
4335
3949
|
console.log();
|
|
4336
3950
|
}
|
|
4337
|
-
console.log(
|
|
4338
|
-
console.log(
|
|
4339
|
-
console.log(` ${
|
|
4340
|
-
console.log(` ${
|
|
4341
|
-
console.log(` ${
|
|
4342
|
-
console.log(` ${
|
|
4343
|
-
console.log(` ${
|
|
4344
|
-
console.log(` ${
|
|
3951
|
+
console.log(chalk5.bold("\nCode Review Options:\n"));
|
|
3952
|
+
console.log(chalk5.dim("You can type naturally (recommended) or use a shortcut:\n"));
|
|
3953
|
+
console.log(` ${chalk5.cyan("1")}) Analyze project`);
|
|
3954
|
+
console.log(` ${chalk5.cyan("2")}) Show review status`);
|
|
3955
|
+
console.log(` ${chalk5.cyan("3")}) Review next file`);
|
|
3956
|
+
console.log(` ${chalk5.cyan("4")}) List all tasks`);
|
|
3957
|
+
console.log(` ${chalk5.cyan("5")}) Run AI review on all pending`);
|
|
3958
|
+
console.log(` ${chalk5.cyan("b")}) Back to main menu`);
|
|
4345
3959
|
console.log();
|
|
4346
3960
|
const raw = await promptWithCommands("What do you want to do?", { allowMultiline: true });
|
|
4347
3961
|
const choice = resolveReviewChoice(raw);
|
|
@@ -4380,7 +3994,7 @@ async function reviewCode() {
|
|
|
4380
3994
|
return;
|
|
4381
3995
|
}
|
|
4382
3996
|
}
|
|
4383
|
-
console.log(
|
|
3997
|
+
console.log(chalk5.yellow("I did not catch that. Tell me what review action you want."));
|
|
4384
3998
|
}
|
|
4385
3999
|
await reviewCode();
|
|
4386
4000
|
}
|
|
@@ -4408,12 +4022,13 @@ async function handleInSessionCommand(input) {
|
|
|
4408
4022
|
}
|
|
4409
4023
|
if (normalized === "help" || normalized === "?" || normalized === "archon help") {
|
|
4410
4024
|
console.log();
|
|
4411
|
-
console.log(
|
|
4412
|
-
console.log(
|
|
4413
|
-
console.log(
|
|
4414
|
-
console.log(
|
|
4415
|
-
console.log(
|
|
4416
|
-
console.log(
|
|
4025
|
+
console.log(chalk5.bold("Available commands (type anytime):"));
|
|
4026
|
+
console.log(chalk5.dim(" upgrade \u2014 Switch to BYOK or Managed plan"));
|
|
4027
|
+
console.log(chalk5.dim(" status \u2014 Show login and tier status"));
|
|
4028
|
+
console.log(chalk5.dim(" keys \u2014 Manage API keys (BYOK tier)"));
|
|
4029
|
+
console.log(chalk5.dim(" /workflow \u2014 Open classic workflow menu"));
|
|
4030
|
+
console.log(chalk5.dim(" quit / q \u2014 Exit ArchonDev"));
|
|
4031
|
+
console.log(chalk5.dim(" skip \u2014 Skip current question"));
|
|
4417
4032
|
console.log();
|
|
4418
4033
|
return true;
|
|
4419
4034
|
}
|
|
@@ -4423,22 +4038,23 @@ async function handleInSessionCommand(input) {
|
|
|
4423
4038
|
return true;
|
|
4424
4039
|
}
|
|
4425
4040
|
if (normalized === "quit" || normalized === "exit" || normalized === "q") {
|
|
4426
|
-
console.log(
|
|
4041
|
+
console.log(chalk5.dim("Goodbye!"));
|
|
4427
4042
|
process.exit(0);
|
|
4428
4043
|
}
|
|
4429
4044
|
return false;
|
|
4430
4045
|
}
|
|
4431
4046
|
function showSlashCommandMenu() {
|
|
4432
4047
|
console.log();
|
|
4433
|
-
console.log(
|
|
4434
|
-
console.log(
|
|
4435
|
-
console.log(
|
|
4436
|
-
console.log(
|
|
4437
|
-
console.log(
|
|
4438
|
-
console.log(
|
|
4439
|
-
console.log(
|
|
4440
|
-
console.log(
|
|
4441
|
-
console.log(
|
|
4048
|
+
console.log(chalk5.bold("Quick Commands"));
|
|
4049
|
+
console.log(chalk5.dim(" /plan <task> Create a plan from a one-line task"));
|
|
4050
|
+
console.log(chalk5.dim(" /list List atoms"));
|
|
4051
|
+
console.log(chalk5.dim(" /execute Execute next atom"));
|
|
4052
|
+
console.log(chalk5.dim(" /review Open code review menu"));
|
|
4053
|
+
console.log(chalk5.dim(" /status Show account/status"));
|
|
4054
|
+
console.log(chalk5.dim(" /settings Open settings & preferences"));
|
|
4055
|
+
console.log(chalk5.dim(" /upgrade Open tier upgrade menu"));
|
|
4056
|
+
console.log(chalk5.dim(" /workflow Open classic workflow menu"));
|
|
4057
|
+
console.log(chalk5.dim(" /quit Exit ArchonDev"));
|
|
4442
4058
|
console.log();
|
|
4443
4059
|
}
|
|
4444
4060
|
async function handleSlashCommand(input) {
|
|
@@ -4482,9 +4098,12 @@ async function handleSlashCommand(input) {
|
|
|
4482
4098
|
await showUpgradeMenu();
|
|
4483
4099
|
return true;
|
|
4484
4100
|
}
|
|
4101
|
+
case "/workflow":
|
|
4102
|
+
await showMainMenu();
|
|
4103
|
+
return true;
|
|
4485
4104
|
case "/quit":
|
|
4486
4105
|
case "/exit":
|
|
4487
|
-
console.log(
|
|
4106
|
+
console.log(chalk5.dim("Goodbye!"));
|
|
4488
4107
|
process.exit(0);
|
|
4489
4108
|
}
|
|
4490
4109
|
return false;
|
|
@@ -4495,7 +4114,7 @@ function prompt(question) {
|
|
|
4495
4114
|
input: process.stdin,
|
|
4496
4115
|
output: process.stdout
|
|
4497
4116
|
});
|
|
4498
|
-
rl.question(`${
|
|
4117
|
+
rl.question(`${chalk5.cyan("?")} ${question}: `, (answer) => {
|
|
4499
4118
|
rl.close();
|
|
4500
4119
|
resolve(answer);
|
|
4501
4120
|
});
|
|
@@ -4522,28 +4141,29 @@ function promptMultiline(question) {
|
|
|
4522
4141
|
rl.on("close", () => {
|
|
4523
4142
|
resolve(lines.join("\n").trimEnd());
|
|
4524
4143
|
});
|
|
4525
|
-
rl.setPrompt(`${
|
|
4144
|
+
rl.setPrompt(`${chalk5.cyan("?")} ${question} (multi-line: end with a single '.' line or Ctrl+D): `);
|
|
4526
4145
|
rl.prompt();
|
|
4527
4146
|
});
|
|
4528
4147
|
}
|
|
4529
4148
|
async function promptWithCommands(question, options = {}) {
|
|
4149
|
+
const useMultiline = Boolean(options.allowMultiline && !isTerminalSafeMode());
|
|
4530
4150
|
while (true) {
|
|
4531
|
-
const answer =
|
|
4532
|
-
if (
|
|
4151
|
+
const answer = useMultiline ? await promptMultiline(question) : await prompt(question);
|
|
4152
|
+
if (useMultiline && answer.includes("\n")) {
|
|
4533
4153
|
return answer;
|
|
4534
4154
|
}
|
|
4535
4155
|
const handled = await handleInSessionCommand(answer);
|
|
4536
4156
|
if (!handled) {
|
|
4537
4157
|
return answer;
|
|
4538
4158
|
}
|
|
4539
|
-
console.log(
|
|
4159
|
+
console.log(chalk5.dim("(Returning to previous question...)\n"));
|
|
4540
4160
|
}
|
|
4541
4161
|
}
|
|
4542
4162
|
async function runWebChecksSuite() {
|
|
4543
4163
|
const { a11yCheck: a11yCheck2 } = await import("./a11y-O35BAA25.js");
|
|
4544
4164
|
const { seoCheck } = await import("./seo-PMI42KRZ.js");
|
|
4545
4165
|
const { geoAudit } = await import("./geo-HRG7M7YX.js");
|
|
4546
|
-
console.log(
|
|
4166
|
+
console.log(chalk5.blue("\nRunning web checks (A11y, SEO, GEO)...\n"));
|
|
4547
4167
|
await a11yCheck2({});
|
|
4548
4168
|
await seoCheck({});
|
|
4549
4169
|
await geoAudit();
|
|
@@ -4552,19 +4172,19 @@ async function showWebChecksMenu() {
|
|
|
4552
4172
|
const cwd = process.cwd();
|
|
4553
4173
|
const { loadWebChecks, formatWebCheckStatus, setWebPromptMode } = await import("./web-checks-4BSYXWDF.js");
|
|
4554
4174
|
const prefs = await loadWebChecks(cwd);
|
|
4555
|
-
console.log(
|
|
4556
|
-
console.log(
|
|
4557
|
-
console.log(
|
|
4558
|
-
console.log(
|
|
4175
|
+
console.log(chalk5.bold("\nWeb Checks (SEO / GEO / A11y)\n"));
|
|
4176
|
+
console.log(chalk5.dim(`A11y: ${formatWebCheckStatus(prefs.lastRun?.a11y)}`));
|
|
4177
|
+
console.log(chalk5.dim(`SEO: ${formatWebCheckStatus(prefs.lastRun?.seo)}`));
|
|
4178
|
+
console.log(chalk5.dim(`GEO: ${formatWebCheckStatus(prefs.lastRun?.geo)}`));
|
|
4559
4179
|
console.log();
|
|
4560
|
-
console.log(` ${
|
|
4561
|
-
console.log(` ${
|
|
4562
|
-
console.log(` ${
|
|
4563
|
-
console.log(` ${
|
|
4564
|
-
console.log(` ${
|
|
4565
|
-
console.log(` ${
|
|
4566
|
-
console.log(` ${
|
|
4567
|
-
console.log(` ${
|
|
4180
|
+
console.log(` ${chalk5.cyan("1")}) Run all checks`);
|
|
4181
|
+
console.log(` ${chalk5.cyan("2")}) Run accessibility check`);
|
|
4182
|
+
console.log(` ${chalk5.cyan("3")}) Run SEO check`);
|
|
4183
|
+
console.log(` ${chalk5.cyan("4")}) Run GEO audit`);
|
|
4184
|
+
console.log(` ${chalk5.cyan("5")}) Generate GEO identity`);
|
|
4185
|
+
console.log(` ${chalk5.cyan("6")}) Generate GEO schema`);
|
|
4186
|
+
console.log(` ${chalk5.cyan("7")}) Set prompt mode (ask/always/never)`);
|
|
4187
|
+
console.log(` ${chalk5.cyan("b")}) Back to main menu`);
|
|
4568
4188
|
console.log();
|
|
4569
4189
|
const raw = await promptWithCommands("What do you want to do?", { allowMultiline: true });
|
|
4570
4190
|
const choice = resolveWebChecksChoice(raw);
|
|
@@ -4599,9 +4219,9 @@ async function showWebChecksMenu() {
|
|
|
4599
4219
|
}
|
|
4600
4220
|
case "7": {
|
|
4601
4221
|
console.log();
|
|
4602
|
-
console.log(` ${
|
|
4603
|
-
console.log(` ${
|
|
4604
|
-
console.log(` ${
|
|
4222
|
+
console.log(` ${chalk5.cyan("1")}) Ask each session`);
|
|
4223
|
+
console.log(` ${chalk5.cyan("2")}) Always run automatically`);
|
|
4224
|
+
console.log(` ${chalk5.cyan("3")}) Never prompt`);
|
|
4605
4225
|
console.log();
|
|
4606
4226
|
const modeChoiceRaw = await promptWithCommands("Set mode (ask / always / never)");
|
|
4607
4227
|
const modeChoice = resolvePromptModeChoice(modeChoiceRaw);
|
|
@@ -4617,7 +4237,7 @@ async function showWebChecksMenu() {
|
|
|
4617
4237
|
return;
|
|
4618
4238
|
}
|
|
4619
4239
|
}
|
|
4620
|
-
console.log(
|
|
4240
|
+
console.log(chalk5.yellow("I did not catch that. Tell me which web check you want."));
|
|
4621
4241
|
}
|
|
4622
4242
|
if (choice.toLowerCase() !== "b") {
|
|
4623
4243
|
await showWebChecksMenu();
|
|
@@ -4633,11 +4253,11 @@ async function maybePromptWebChecks(cwd, projectState) {
|
|
|
4633
4253
|
return;
|
|
4634
4254
|
}
|
|
4635
4255
|
if (prefs.promptMode === "always") {
|
|
4636
|
-
console.log(
|
|
4256
|
+
console.log(chalk5.blue("\nWeb project detected. Running web checks automatically...\n"));
|
|
4637
4257
|
await runWebChecksSuite();
|
|
4638
4258
|
return;
|
|
4639
4259
|
}
|
|
4640
|
-
console.log(
|
|
4260
|
+
console.log(chalk5.blue("\nWeb project detected."));
|
|
4641
4261
|
const choice = await promptChoice("Run web checks now?", [
|
|
4642
4262
|
{ key: "1", label: "Run all checks (A11y + SEO + GEO)" },
|
|
4643
4263
|
{ key: "2", label: "Choose checks" },
|
|
@@ -4659,7 +4279,7 @@ function promptYesNo(question, defaultValue) {
|
|
|
4659
4279
|
output: process.stdout
|
|
4660
4280
|
});
|
|
4661
4281
|
const hint = defaultValue ? "(Y/n)" : "(y/N)";
|
|
4662
|
-
rl.question(`${
|
|
4282
|
+
rl.question(`${chalk5.cyan("?")} ${question} ${hint}: `, (answer) => {
|
|
4663
4283
|
rl.close();
|
|
4664
4284
|
if (answer.trim() === "") {
|
|
4665
4285
|
resolve(defaultValue);
|
|
@@ -4671,15 +4291,15 @@ function promptYesNo(question, defaultValue) {
|
|
|
4671
4291
|
}
|
|
4672
4292
|
function promptChoice(question, options, defaultKey) {
|
|
4673
4293
|
return new Promise((resolve) => {
|
|
4674
|
-
console.log(`${
|
|
4294
|
+
console.log(`${chalk5.cyan("?")} ${question}`);
|
|
4675
4295
|
for (const opt of options) {
|
|
4676
|
-
console.log(` ${
|
|
4296
|
+
console.log(` ${chalk5.dim(opt.key)}) ${opt.label}`);
|
|
4677
4297
|
}
|
|
4678
4298
|
const rl = readline.createInterface({
|
|
4679
4299
|
input: process.stdin,
|
|
4680
4300
|
output: process.stdout
|
|
4681
4301
|
});
|
|
4682
|
-
rl.question(` ${
|
|
4302
|
+
rl.question(` ${chalk5.dim("Enter choice or describe what you want")}: `, (answer) => {
|
|
4683
4303
|
rl.close();
|
|
4684
4304
|
const trimmed = answer.trim();
|
|
4685
4305
|
if (trimmed) {
|
|
@@ -4742,7 +4362,7 @@ function resolvePromptModeChoice(input) {
|
|
|
4742
4362
|
}
|
|
4743
4363
|
|
|
4744
4364
|
// src/cli/credits.ts
|
|
4745
|
-
import
|
|
4365
|
+
import chalk6 from "chalk";
|
|
4746
4366
|
import ora from "ora";
|
|
4747
4367
|
import open from "open";
|
|
4748
4368
|
import readline2 from "readline";
|
|
@@ -4788,20 +4408,20 @@ async function showCredits() {
|
|
|
4788
4408
|
const profile = data;
|
|
4789
4409
|
spinner.stop();
|
|
4790
4410
|
console.log();
|
|
4791
|
-
console.log(
|
|
4411
|
+
console.log(chalk6.bold("\u{1F4B0} Credit Balance"));
|
|
4792
4412
|
console.log();
|
|
4793
4413
|
const balance = (profile.credit_balance_cents || 0) / 100;
|
|
4794
4414
|
console.log(` Tier: ${formatTier(profile.tier)}`);
|
|
4795
|
-
console.log(` Balance: ${
|
|
4415
|
+
console.log(` Balance: ${chalk6.green(`$${balance.toFixed(2)}`)}`);
|
|
4796
4416
|
if (profile.tier === "FREE") {
|
|
4797
4417
|
console.log(` Atoms: ${profile.atoms_used_this_month}/10,000 this month`);
|
|
4798
4418
|
console.log();
|
|
4799
|
-
console.log(
|
|
4419
|
+
console.log(chalk6.dim(" Upgrade to Credits tier: archon credits add"));
|
|
4800
4420
|
printCreditsNextAction("FREE");
|
|
4801
4421
|
} else if (profile.tier === "CREDITS") {
|
|
4802
4422
|
console.log();
|
|
4803
|
-
console.log(
|
|
4804
|
-
console.log(
|
|
4423
|
+
console.log(chalk6.dim(" Add more credits: archon credits add"));
|
|
4424
|
+
console.log(chalk6.dim(" Detailed usage by model: archon usage"));
|
|
4805
4425
|
printCreditsNextAction("CREDITS");
|
|
4806
4426
|
if (balance < 5) {
|
|
4807
4427
|
const addNow = await promptYesNo2("Balance is low. Add credits now?", false);
|
|
@@ -4811,8 +4431,8 @@ async function showCredits() {
|
|
|
4811
4431
|
}
|
|
4812
4432
|
} else if (profile.tier === "BYOK") {
|
|
4813
4433
|
console.log();
|
|
4814
|
-
console.log(
|
|
4815
|
-
console.log(
|
|
4434
|
+
console.log(chalk6.dim(" Using your own API keys - no credit charges"));
|
|
4435
|
+
console.log(chalk6.dim(" Estimated spend by model: archon usage"));
|
|
4816
4436
|
printCreditsNextAction("BYOK");
|
|
4817
4437
|
}
|
|
4818
4438
|
console.log();
|
|
@@ -4859,35 +4479,35 @@ async function addCredits(options = {}) {
|
|
|
4859
4479
|
}
|
|
4860
4480
|
spinner.succeed("Checkout ready");
|
|
4861
4481
|
console.log();
|
|
4862
|
-
console.log(
|
|
4482
|
+
console.log(chalk6.bold("\u{1F6D2} Add Credits"));
|
|
4863
4483
|
console.log();
|
|
4864
|
-
console.log(` Amount: ${
|
|
4484
|
+
console.log(` Amount: ${chalk6.green(`$${amountDollars.toFixed(2)}`)}`);
|
|
4865
4485
|
console.log();
|
|
4866
4486
|
console.log(" Opening checkout in browser...");
|
|
4867
4487
|
console.log();
|
|
4868
|
-
console.log(
|
|
4488
|
+
console.log(chalk6.dim(` Or visit: ${checkoutUrl}`));
|
|
4869
4489
|
console.log();
|
|
4870
4490
|
try {
|
|
4871
4491
|
await open(checkoutUrl);
|
|
4872
4492
|
} catch {
|
|
4873
|
-
console.log(
|
|
4493
|
+
console.log(chalk6.yellow(" Could not open browser. Please visit the URL above."));
|
|
4874
4494
|
}
|
|
4875
|
-
console.log(
|
|
4876
|
-
console.log(
|
|
4877
|
-
console.log(
|
|
4495
|
+
console.log(chalk6.bold("\nNext best action:"));
|
|
4496
|
+
console.log(chalk6.dim(` \u2022 Complete payment in browser, then run ${chalk6.cyan("archon credits")} to verify balance.`));
|
|
4497
|
+
console.log(chalk6.dim(` \u2022 Continue work with ${chalk6.cyan('archon plan "..."')} or ${chalk6.cyan("archon execute <ATOM-ID>")}.`));
|
|
4878
4498
|
} catch (err2) {
|
|
4879
4499
|
spinner.fail("Error preparing checkout");
|
|
4880
4500
|
console.error(err2);
|
|
4881
4501
|
}
|
|
4882
4502
|
}
|
|
4883
4503
|
function printCreditsNextAction(tier) {
|
|
4884
|
-
console.log(
|
|
4504
|
+
console.log(chalk6.bold(" Next best action:"));
|
|
4885
4505
|
if (tier === "CREDITS") {
|
|
4886
|
-
console.log(
|
|
4506
|
+
console.log(chalk6.dim(` \u2022 Keep at least $5 balance to avoid interruptions during plan/execute.`));
|
|
4887
4507
|
} else if (tier === "BYOK") {
|
|
4888
|
-
console.log(
|
|
4508
|
+
console.log(chalk6.dim(` \u2022 Manage provider keys with ${chalk6.cyan("archon keys add/list/remove")}.`));
|
|
4889
4509
|
} else {
|
|
4890
|
-
console.log(
|
|
4510
|
+
console.log(chalk6.dim(` \u2022 Upgrade to BYOK or Credits with ${chalk6.cyan("archon upgrade")}.`));
|
|
4891
4511
|
}
|
|
4892
4512
|
}
|
|
4893
4513
|
function promptYesNo2(question, defaultValue) {
|
|
@@ -4897,7 +4517,7 @@ function promptYesNo2(question, defaultValue) {
|
|
|
4897
4517
|
output: process.stdout
|
|
4898
4518
|
});
|
|
4899
4519
|
const hint = defaultValue ? "(Y/n)" : "(y/N)";
|
|
4900
|
-
rl.question(`${
|
|
4520
|
+
rl.question(`${chalk6.cyan("?")} ${question} ${hint}: `, (answer) => {
|
|
4901
4521
|
rl.close();
|
|
4902
4522
|
if (answer.trim() === "") {
|
|
4903
4523
|
resolve(defaultValue);
|
|
@@ -4931,15 +4551,15 @@ async function showHistory(options = {}) {
|
|
|
4931
4551
|
const usage = data;
|
|
4932
4552
|
spinner.stop();
|
|
4933
4553
|
console.log();
|
|
4934
|
-
console.log(
|
|
4554
|
+
console.log(chalk6.bold("Usage History"));
|
|
4935
4555
|
console.log();
|
|
4936
4556
|
if (!usage || usage.length === 0) {
|
|
4937
|
-
console.log(
|
|
4557
|
+
console.log(chalk6.dim(" No usage recorded yet."));
|
|
4938
4558
|
console.log();
|
|
4939
4559
|
return;
|
|
4940
4560
|
}
|
|
4941
|
-
console.log(
|
|
4942
|
-
console.log(
|
|
4561
|
+
console.log(chalk6.dim(" Model Tokens Cost Date"));
|
|
4562
|
+
console.log(chalk6.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
4943
4563
|
for (const row of usage) {
|
|
4944
4564
|
const model = row.model.padEnd(30).slice(0, 30);
|
|
4945
4565
|
const tokens = (row.input_tokens + row.output_tokens).toString().padStart(8);
|
|
@@ -4949,9 +4569,9 @@ async function showHistory(options = {}) {
|
|
|
4949
4569
|
}
|
|
4950
4570
|
const totalCost = usage.reduce((sum, r) => sum + r.base_cost, 0);
|
|
4951
4571
|
const totalTokens = usage.reduce((sum, r) => sum + r.input_tokens + r.output_tokens, 0);
|
|
4952
|
-
console.log(
|
|
4572
|
+
console.log(chalk6.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
4953
4573
|
console.log(
|
|
4954
|
-
` ${"Total".padEnd(30)} ${totalTokens.toString().padStart(8)} ${
|
|
4574
|
+
` ${"Total".padEnd(30)} ${totalTokens.toString().padStart(8)} ${chalk6.green(`$${totalCost.toFixed(4)}`.padStart(10))}`
|
|
4955
4575
|
);
|
|
4956
4576
|
console.log();
|
|
4957
4577
|
} catch (err2) {
|
|
@@ -5017,24 +4637,24 @@ async function manageBudget(options = {}) {
|
|
|
5017
4637
|
}
|
|
5018
4638
|
spinner.stop();
|
|
5019
4639
|
console.log();
|
|
5020
|
-
console.log(
|
|
4640
|
+
console.log(chalk6.bold("Monthly Budget"));
|
|
5021
4641
|
console.log();
|
|
5022
4642
|
if (profile.monthly_budget_cents === null) {
|
|
5023
|
-
console.log(` Budget: ${
|
|
4643
|
+
console.log(` Budget: ${chalk6.dim("No limit set")}`);
|
|
5024
4644
|
} else {
|
|
5025
4645
|
const budget = profile.monthly_budget_cents / 100;
|
|
5026
4646
|
const spend = (profile.monthly_spend_cents || 0) / 100;
|
|
5027
4647
|
const remaining = budget - spend;
|
|
5028
4648
|
const percent = budget > 0 ? Math.round(spend / budget * 100) : 0;
|
|
5029
|
-
console.log(` Budget: ${
|
|
4649
|
+
console.log(` Budget: ${chalk6.green(`$${budget.toFixed(2)}`)} / month`);
|
|
5030
4650
|
console.log(` Spent: $${spend.toFixed(2)} (${percent}%)`);
|
|
5031
|
-
console.log(` Remaining: ${remaining >= 0 ?
|
|
4651
|
+
console.log(` Remaining: ${remaining >= 0 ? chalk6.green(`$${remaining.toFixed(2)}`) : chalk6.red(`-$${Math.abs(remaining).toFixed(2)}`)}`);
|
|
5032
4652
|
}
|
|
5033
4653
|
console.log(` Alert at: ${profile.budget_alert_threshold_percent}% of budget`);
|
|
5034
4654
|
console.log();
|
|
5035
|
-
console.log(
|
|
5036
|
-
console.log(
|
|
5037
|
-
console.log(
|
|
4655
|
+
console.log(chalk6.dim(" Set budget: archon credits budget --set 50"));
|
|
4656
|
+
console.log(chalk6.dim(" Clear budget: archon credits budget --clear"));
|
|
4657
|
+
console.log(chalk6.dim(" Set alert: archon credits budget --alert 80"));
|
|
5038
4658
|
console.log();
|
|
5039
4659
|
} catch (err2) {
|
|
5040
4660
|
spinner.fail("Error managing budget");
|
|
@@ -5096,12 +4716,12 @@ async function manageAutoRecharge(options = {}) {
|
|
|
5096
4716
|
}
|
|
5097
4717
|
spinner.stop();
|
|
5098
4718
|
console.log();
|
|
5099
|
-
console.log(
|
|
4719
|
+
console.log(chalk6.bold("\u{1F504} Auto-Recharge"));
|
|
5100
4720
|
console.log();
|
|
5101
4721
|
if (!profile.auto_recharge_enabled) {
|
|
5102
|
-
console.log(` Status: ${
|
|
4722
|
+
console.log(` Status: ${chalk6.dim("Disabled")}`);
|
|
5103
4723
|
} else {
|
|
5104
|
-
console.log(` Status: ${
|
|
4724
|
+
console.log(` Status: ${chalk6.green("Enabled")}`);
|
|
5105
4725
|
if (profile.auto_recharge_threshold_cents !== null) {
|
|
5106
4726
|
console.log(` When: Balance drops below $${(profile.auto_recharge_threshold_cents / 100).toFixed(2)}`);
|
|
5107
4727
|
}
|
|
@@ -5109,10 +4729,10 @@ async function manageAutoRecharge(options = {}) {
|
|
|
5109
4729
|
console.log(` Amount: $${(profile.auto_recharge_amount_cents / 100).toFixed(2)}`);
|
|
5110
4730
|
}
|
|
5111
4731
|
}
|
|
5112
|
-
console.log(` Payment: ${profile.stripe_payment_method_id ?
|
|
4732
|
+
console.log(` Payment: ${profile.stripe_payment_method_id ? chalk6.green("Card saved") : chalk6.dim("No card saved")}`);
|
|
5113
4733
|
console.log();
|
|
5114
|
-
console.log(
|
|
5115
|
-
console.log(
|
|
4734
|
+
console.log(chalk6.dim(" Enable: archon credits auto-recharge --enable --threshold 5 --amount 20"));
|
|
4735
|
+
console.log(chalk6.dim(" Disable: archon credits auto-recharge --disable"));
|
|
5116
4736
|
console.log();
|
|
5117
4737
|
} catch (err2) {
|
|
5118
4738
|
spinner.fail("Error managing auto-recharge");
|
|
@@ -5142,21 +4762,21 @@ async function showAuditHistory(options = {}) {
|
|
|
5142
4762
|
});
|
|
5143
4763
|
if (error) {
|
|
5144
4764
|
spinner.fail("Could not fetch audit history");
|
|
5145
|
-
console.error(
|
|
4765
|
+
console.error(chalk6.dim(error.message));
|
|
5146
4766
|
return;
|
|
5147
4767
|
}
|
|
5148
4768
|
const history = data;
|
|
5149
4769
|
spinner.stop();
|
|
5150
4770
|
console.log();
|
|
5151
|
-
console.log(
|
|
4771
|
+
console.log(chalk6.bold("\u{1F4CB} Billing Audit History"));
|
|
5152
4772
|
console.log();
|
|
5153
4773
|
if (!history || history.length === 0) {
|
|
5154
|
-
console.log(
|
|
4774
|
+
console.log(chalk6.dim(" No billing events recorded yet."));
|
|
5155
4775
|
console.log();
|
|
5156
4776
|
return;
|
|
5157
4777
|
}
|
|
5158
|
-
console.log(
|
|
5159
|
-
console.log(
|
|
4778
|
+
console.log(chalk6.dim(" Event Amount Balance Date"));
|
|
4779
|
+
console.log(chalk6.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
5160
4780
|
for (const row of history) {
|
|
5161
4781
|
const eventType = formatEventType(row.event_type).padEnd(22);
|
|
5162
4782
|
const amount = row.amount_cents !== null ? formatAmount(row.event_type, row.amount_cents).padStart(10) : " -";
|
|
@@ -5164,10 +4784,10 @@ async function showAuditHistory(options = {}) {
|
|
|
5164
4784
|
const date = new Date(row.created_at).toLocaleDateString();
|
|
5165
4785
|
console.log(` ${eventType} ${amount} ${balance} ${date}`);
|
|
5166
4786
|
}
|
|
5167
|
-
console.log(
|
|
4787
|
+
console.log(chalk6.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
5168
4788
|
console.log();
|
|
5169
|
-
console.log(
|
|
5170
|
-
console.log(
|
|
4789
|
+
console.log(chalk6.dim(` Showing ${history.length} most recent events`));
|
|
4790
|
+
console.log(chalk6.dim(" Use --limit N to show more"));
|
|
5171
4791
|
console.log();
|
|
5172
4792
|
} catch (err2) {
|
|
5173
4793
|
spinner.fail("Error fetching audit history");
|
|
@@ -5177,19 +4797,19 @@ async function showAuditHistory(options = {}) {
|
|
|
5177
4797
|
function formatEventType(eventType) {
|
|
5178
4798
|
switch (eventType) {
|
|
5179
4799
|
case "CREDITS_PURCHASED":
|
|
5180
|
-
return
|
|
4800
|
+
return chalk6.green("+ Purchase");
|
|
5181
4801
|
case "CREDITS_DEDUCTED":
|
|
5182
|
-
return
|
|
4802
|
+
return chalk6.red("- Usage");
|
|
5183
4803
|
case "CREDITS_REFUNDED":
|
|
5184
|
-
return
|
|
4804
|
+
return chalk6.cyan("+ Refund");
|
|
5185
4805
|
case "BALANCE_ADJUSTED":
|
|
5186
|
-
return
|
|
4806
|
+
return chalk6.yellow("\xB1 Adjustment");
|
|
5187
4807
|
case "BUDGET_CHANGED":
|
|
5188
|
-
return
|
|
4808
|
+
return chalk6.blue("\u25C9 Budget");
|
|
5189
4809
|
case "TIER_CHANGED":
|
|
5190
|
-
return
|
|
4810
|
+
return chalk6.magenta("\u25C9 Tier");
|
|
5191
4811
|
case "USAGE_RECORDED":
|
|
5192
|
-
return
|
|
4812
|
+
return chalk6.dim("\u25C9 Usage");
|
|
5193
4813
|
default:
|
|
5194
4814
|
return eventType;
|
|
5195
4815
|
}
|
|
@@ -5197,20 +4817,20 @@ function formatEventType(eventType) {
|
|
|
5197
4817
|
function formatAmount(eventType, cents) {
|
|
5198
4818
|
const dollars = (cents / 100).toFixed(2);
|
|
5199
4819
|
if (eventType === "CREDITS_PURCHASED" || eventType === "CREDITS_REFUNDED") {
|
|
5200
|
-
return
|
|
4820
|
+
return chalk6.green(`+$${dollars}`);
|
|
5201
4821
|
} else if (eventType === "CREDITS_DEDUCTED") {
|
|
5202
|
-
return
|
|
4822
|
+
return chalk6.red(`-$${dollars}`);
|
|
5203
4823
|
}
|
|
5204
4824
|
return `$${dollars}`;
|
|
5205
4825
|
}
|
|
5206
4826
|
function formatTier(tier) {
|
|
5207
4827
|
switch (tier) {
|
|
5208
4828
|
case "FREE":
|
|
5209
|
-
return
|
|
4829
|
+
return chalk6.blue("Free (10k atoms/month)");
|
|
5210
4830
|
case "CREDITS":
|
|
5211
|
-
return
|
|
4831
|
+
return chalk6.green("Credits (Pay-as-you-go)");
|
|
5212
4832
|
case "BYOK":
|
|
5213
|
-
return
|
|
4833
|
+
return chalk6.magenta("BYOK (Bring Your Own Key)");
|
|
5214
4834
|
default:
|
|
5215
4835
|
return tier;
|
|
5216
4836
|
}
|
|
@@ -5223,7 +4843,7 @@ import Spinner from "ink-spinner";
|
|
|
5223
4843
|
import * as fs from "fs";
|
|
5224
4844
|
import * as path from "path";
|
|
5225
4845
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5226
|
-
var
|
|
4846
|
+
var STATUS_COLORS = {
|
|
5227
4847
|
DRAFT: "gray",
|
|
5228
4848
|
READY: "blue",
|
|
5229
4849
|
IN_PROGRESS: "yellow",
|
|
@@ -5306,7 +4926,7 @@ function AtomList({ atoms }) {
|
|
|
5306
4926
|
] }),
|
|
5307
4927
|
atoms.slice(0, 15).map((atom) => /* @__PURE__ */ jsxs(Box, { paddingX: 1, children: [
|
|
5308
4928
|
/* @__PURE__ */ jsx(Box, { width: 12, children: /* @__PURE__ */ jsx(Text, { children: atom.id.slice(0, 10) }) }),
|
|
5309
|
-
/* @__PURE__ */ jsx(Box, { width: 10, children: /* @__PURE__ */ jsxs(Text, { color:
|
|
4929
|
+
/* @__PURE__ */ jsx(Box, { width: 10, children: /* @__PURE__ */ jsxs(Text, { color: STATUS_COLORS[atom.status], children: [
|
|
5310
4930
|
STATUS_ICONS[atom.status],
|
|
5311
4931
|
" ",
|
|
5312
4932
|
atom.status.slice(0, 7)
|
|
@@ -5367,7 +4987,7 @@ function RecentActivity({ atoms }) {
|
|
|
5367
4987
|
/* @__PURE__ */ jsx(Box, { marginBottom: 1, children: /* @__PURE__ */ jsx(Text, { bold: true, children: "Recent Activity" }) }),
|
|
5368
4988
|
recentAtoms.map((atom) => /* @__PURE__ */ jsxs(Box, { marginBottom: 0, children: [
|
|
5369
4989
|
/* @__PURE__ */ jsx(Box, { width: 20, children: /* @__PURE__ */ jsx(Text, { dimColor: true, children: formatTime(new Date(atom.updatedAt)) }) }),
|
|
5370
|
-
/* @__PURE__ */ jsx(Box, { width: 10, children: /* @__PURE__ */ jsxs(Text, { color:
|
|
4990
|
+
/* @__PURE__ */ jsx(Box, { width: 10, children: /* @__PURE__ */ jsxs(Text, { color: STATUS_COLORS[atom.status], children: [
|
|
5371
4991
|
STATUS_ICONS[atom.status],
|
|
5372
4992
|
" ",
|
|
5373
4993
|
atom.status.slice(0, 7)
|
|
@@ -5487,7 +5107,7 @@ async function watch() {
|
|
|
5487
5107
|
|
|
5488
5108
|
// src/cli/deps.ts
|
|
5489
5109
|
import { Command } from "commander";
|
|
5490
|
-
import
|
|
5110
|
+
import chalk7 from "chalk";
|
|
5491
5111
|
import { readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
5492
5112
|
import { existsSync as existsSync8 } from "fs";
|
|
5493
5113
|
var DEPENDENCIES_FILENAME = "DEPENDENCIES.md";
|
|
@@ -5505,30 +5125,30 @@ Examples:
|
|
|
5505
5125
|
deps.command("list").description("List all dependency rules").option("-v, --verbose", "Show detailed information").action(async (options) => {
|
|
5506
5126
|
const parser = new DependencyParser();
|
|
5507
5127
|
if (!parser.exists()) {
|
|
5508
|
-
console.log(
|
|
5509
|
-
console.log(
|
|
5128
|
+
console.log(chalk7.yellow("No DEPENDENCIES.md found."));
|
|
5129
|
+
console.log(chalk7.dim("Create one with: archon deps add --source <path> --dependent <path>"));
|
|
5510
5130
|
return;
|
|
5511
5131
|
}
|
|
5512
5132
|
const result = await parser.parse();
|
|
5513
5133
|
if (!result.success) {
|
|
5514
|
-
console.log(
|
|
5134
|
+
console.log(chalk7.red(`Parse error: ${result.error}`));
|
|
5515
5135
|
return;
|
|
5516
5136
|
}
|
|
5517
5137
|
const rules = result.document?.rules ?? [];
|
|
5518
5138
|
if (rules.length === 0) {
|
|
5519
|
-
console.log(
|
|
5139
|
+
console.log(chalk7.dim("No dependency rules defined."));
|
|
5520
5140
|
return;
|
|
5521
5141
|
}
|
|
5522
|
-
console.log(
|
|
5142
|
+
console.log(chalk7.bold(`
|
|
5523
5143
|
\u{1F4E6} Dependency Rules (${rules.length})
|
|
5524
5144
|
`));
|
|
5525
5145
|
for (const rule of rules) {
|
|
5526
|
-
const severityColor = rule.severity === "BLOCKER" ?
|
|
5527
|
-
console.log(`${severityColor(`[${rule.severity}]`)} ${
|
|
5528
|
-
console.log(` Source: ${
|
|
5529
|
-
console.log(` Dependents: ${rule.dependents.map((d) =>
|
|
5146
|
+
const severityColor = rule.severity === "BLOCKER" ? chalk7.red : rule.severity === "WARNING" ? chalk7.yellow : chalk7.blue;
|
|
5147
|
+
console.log(`${severityColor(`[${rule.severity}]`)} ${chalk7.bold(rule.id)}`);
|
|
5148
|
+
console.log(` Source: ${chalk7.cyan(rule.source)}`);
|
|
5149
|
+
console.log(` Dependents: ${rule.dependents.map((d) => chalk7.dim(d)).join(", ")}`);
|
|
5530
5150
|
if (rule.reason && options.verbose) {
|
|
5531
|
-
console.log(` Reason: ${
|
|
5151
|
+
console.log(` Reason: ${chalk7.dim(rule.reason)}`);
|
|
5532
5152
|
}
|
|
5533
5153
|
if (rule.mustTest && options.verbose) {
|
|
5534
5154
|
console.log(` Must test: ${rule.mustTest.join(", ")}`);
|
|
@@ -5540,29 +5160,29 @@ Examples:
|
|
|
5540
5160
|
const files = options.files.split(",").map((f) => f.trim());
|
|
5541
5161
|
const parser = new DependencyParser();
|
|
5542
5162
|
if (!parser.exists()) {
|
|
5543
|
-
console.log(
|
|
5163
|
+
console.log(chalk7.dim("No DEPENDENCIES.md found. No dependency checks performed."));
|
|
5544
5164
|
process.exit(0);
|
|
5545
5165
|
}
|
|
5546
5166
|
const result = await parser.checkFiles(files);
|
|
5547
5167
|
if (result.impacts.length === 0) {
|
|
5548
|
-
console.log(
|
|
5168
|
+
console.log(chalk7.green("\u2705 No downstream dependency impacts found."));
|
|
5549
5169
|
process.exit(0);
|
|
5550
5170
|
}
|
|
5551
|
-
console.log(
|
|
5171
|
+
console.log(chalk7.yellow(`
|
|
5552
5172
|
[!] Found ${result.impacts.length} dependency impact(s):
|
|
5553
5173
|
`));
|
|
5554
5174
|
for (const impact of result.impacts) {
|
|
5555
|
-
const severityColor = impact.rule.severity === "BLOCKER" ?
|
|
5175
|
+
const severityColor = impact.rule.severity === "BLOCKER" ? chalk7.red : impact.rule.severity === "WARNING" ? chalk7.yellow : chalk7.blue;
|
|
5556
5176
|
console.log(severityColor(`[${impact.rule.severity}] ${impact.rule.id}`));
|
|
5557
|
-
console.log(` Changing: ${
|
|
5177
|
+
console.log(` Changing: ${chalk7.cyan(impact.matchedSource)}`);
|
|
5558
5178
|
console.log(` May impact: ${impact.affectedDependents.join(", ")}`);
|
|
5559
5179
|
if (impact.rule.reason) {
|
|
5560
|
-
console.log(` Reason: ${
|
|
5180
|
+
console.log(` Reason: ${chalk7.dim(impact.rule.reason)}`);
|
|
5561
5181
|
}
|
|
5562
5182
|
console.log("");
|
|
5563
5183
|
}
|
|
5564
5184
|
if (result.hasBlockers) {
|
|
5565
|
-
console.log(
|
|
5185
|
+
console.log(chalk7.red("\u274C BLOCKER-level impacts found. Review before proceeding."));
|
|
5566
5186
|
process.exit(1);
|
|
5567
5187
|
}
|
|
5568
5188
|
process.exit(0);
|
|
@@ -5604,7 +5224,7 @@ Examples:
|
|
|
5604
5224
|
(r) => r.source === source && r.dependents.includes(dependent)
|
|
5605
5225
|
);
|
|
5606
5226
|
if (existingRule) {
|
|
5607
|
-
console.log(
|
|
5227
|
+
console.log(chalk7.yellow(`Rule already exists: ${existingRule.id}`));
|
|
5608
5228
|
return;
|
|
5609
5229
|
}
|
|
5610
5230
|
const newRule = {
|
|
@@ -5618,20 +5238,20 @@ Examples:
|
|
|
5618
5238
|
const yaml2 = generateYamlFrontmatter(existingRules);
|
|
5619
5239
|
await writeFile4(DEPENDENCIES_FILENAME, `---
|
|
5620
5240
|
${yaml2}---${markdownBody}`, "utf-8");
|
|
5621
|
-
console.log(
|
|
5622
|
-
console.log(` Source: ${
|
|
5623
|
-
console.log(` Dependent: ${
|
|
5241
|
+
console.log(chalk7.green(`\u2705 Added dependency rule: ${nextId}`));
|
|
5242
|
+
console.log(` Source: ${chalk7.cyan(source)}`);
|
|
5243
|
+
console.log(` Dependent: ${chalk7.dim(dependent)}`);
|
|
5624
5244
|
});
|
|
5625
5245
|
deps.command("graph").description("Generate Mermaid diagram of dependencies").option("--output <file>", "Write to file instead of stdout").action(async (options) => {
|
|
5626
5246
|
const parser = new DependencyParser();
|
|
5627
5247
|
if (!parser.exists()) {
|
|
5628
|
-
console.log(
|
|
5248
|
+
console.log(chalk7.yellow("No DEPENDENCIES.md found."));
|
|
5629
5249
|
return;
|
|
5630
5250
|
}
|
|
5631
5251
|
const mermaid = await parser.generateGraph();
|
|
5632
5252
|
if (options.output) {
|
|
5633
5253
|
await writeFile4(options.output, mermaid, "utf-8");
|
|
5634
|
-
console.log(
|
|
5254
|
+
console.log(chalk7.green(`\u2705 Graph written to ${options.output}`));
|
|
5635
5255
|
} else {
|
|
5636
5256
|
console.log("\n```mermaid");
|
|
5637
5257
|
console.log(mermaid);
|
|
@@ -5640,7 +5260,7 @@ ${yaml2}---${markdownBody}`, "utf-8");
|
|
|
5640
5260
|
});
|
|
5641
5261
|
deps.command("init").description("Create a starter DEPENDENCIES.md file").action(async () => {
|
|
5642
5262
|
if (existsSync8(DEPENDENCIES_FILENAME)) {
|
|
5643
|
-
console.log(
|
|
5263
|
+
console.log(chalk7.yellow("DEPENDENCIES.md already exists."));
|
|
5644
5264
|
return;
|
|
5645
5265
|
}
|
|
5646
5266
|
const template = `---
|
|
@@ -5687,8 +5307,8 @@ rules:
|
|
|
5687
5307
|
*Powered by [ArchonDev](https://archondev.io)*
|
|
5688
5308
|
`;
|
|
5689
5309
|
await writeFile4(DEPENDENCIES_FILENAME, template, "utf-8");
|
|
5690
|
-
console.log(
|
|
5691
|
-
console.log(
|
|
5310
|
+
console.log(chalk7.green("\u2705 Created DEPENDENCIES.md"));
|
|
5311
|
+
console.log(chalk7.dim("Add your first rule with: archon deps add --source <path> --dependent <path>"));
|
|
5692
5312
|
});
|
|
5693
5313
|
return deps;
|
|
5694
5314
|
}
|
|
@@ -5725,7 +5345,7 @@ function generateYamlFrontmatter(rules) {
|
|
|
5725
5345
|
}
|
|
5726
5346
|
|
|
5727
5347
|
// src/cli/session.ts
|
|
5728
|
-
import
|
|
5348
|
+
import chalk8 from "chalk";
|
|
5729
5349
|
import ora2 from "ora";
|
|
5730
5350
|
import os from "os";
|
|
5731
5351
|
import { readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
@@ -5821,13 +5441,13 @@ async function saveSession(name) {
|
|
|
5821
5441
|
spinner.fail(`Failed to save session: ${error.message}`);
|
|
5822
5442
|
return;
|
|
5823
5443
|
}
|
|
5824
|
-
spinner.succeed(
|
|
5444
|
+
spinner.succeed(chalk8.green("Session saved!"));
|
|
5825
5445
|
console.log();
|
|
5826
|
-
console.log(` ID: ${
|
|
5446
|
+
console.log(` ID: ${chalk8.cyan(session.id)}`);
|
|
5827
5447
|
console.log(` Project: ${session.project_name}`);
|
|
5828
5448
|
console.log(` Device: ${session.last_device}`);
|
|
5829
5449
|
console.log();
|
|
5830
|
-
console.log(
|
|
5450
|
+
console.log(chalk8.dim(" Resume on another device: archon session resume " + session.id));
|
|
5831
5451
|
console.log();
|
|
5832
5452
|
} catch (err2) {
|
|
5833
5453
|
spinner.fail("Error saving session");
|
|
@@ -5855,23 +5475,23 @@ async function listSessions() {
|
|
|
5855
5475
|
}
|
|
5856
5476
|
spinner.stop();
|
|
5857
5477
|
if (!sessions || sessions.length === 0) {
|
|
5858
|
-
console.log(
|
|
5859
|
-
console.log(
|
|
5478
|
+
console.log(chalk8.yellow("\nNo saved sessions found.\n"));
|
|
5479
|
+
console.log(chalk8.dim(" Save a session: archon session save [name]\n"));
|
|
5860
5480
|
return;
|
|
5861
5481
|
}
|
|
5862
5482
|
console.log();
|
|
5863
|
-
console.log(
|
|
5483
|
+
console.log(chalk8.bold("\u{1F4C2} Saved Sessions"));
|
|
5864
5484
|
console.log();
|
|
5865
5485
|
for (const session of sessions) {
|
|
5866
5486
|
const date = new Date(session.updated_at).toLocaleDateString();
|
|
5867
|
-
const atomInfo = session.current_atom_id ?
|
|
5487
|
+
const atomInfo = session.current_atom_id ? chalk8.dim(` (atom: ${session.current_atom_id})`) : "";
|
|
5868
5488
|
console.log(
|
|
5869
|
-
` ${
|
|
5489
|
+
` ${chalk8.cyan(session.id.slice(0, 8))} ${session.project_name}${atomInfo}`
|
|
5870
5490
|
);
|
|
5871
|
-
console.log(
|
|
5491
|
+
console.log(chalk8.dim(` ${date} from ${session.last_device || "unknown device"}`));
|
|
5872
5492
|
console.log();
|
|
5873
5493
|
}
|
|
5874
|
-
console.log(
|
|
5494
|
+
console.log(chalk8.dim(" Resume: archon session resume <id>\n"));
|
|
5875
5495
|
} catch (err2) {
|
|
5876
5496
|
spinner.fail("Error fetching sessions");
|
|
5877
5497
|
console.error(err2);
|
|
@@ -5915,13 +5535,13 @@ async function resumeSession(sessionId) {
|
|
|
5915
5535
|
await writeFile5(archPath, session.architecture_snapshot);
|
|
5916
5536
|
}
|
|
5917
5537
|
await supabase.from("sessions").update({ last_device: getDeviceName(), updated_at: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", session.id);
|
|
5918
|
-
spinner.succeed(
|
|
5538
|
+
spinner.succeed(chalk8.green("Session resumed!"));
|
|
5919
5539
|
console.log();
|
|
5920
5540
|
console.log(` Project: ${session.project_name}`);
|
|
5921
5541
|
console.log(` Current Atom: ${session.current_atom_id || "none"}`);
|
|
5922
5542
|
console.log(` Pending: ${session.pending_atoms.length} atoms`);
|
|
5923
5543
|
console.log();
|
|
5924
|
-
console.log(
|
|
5544
|
+
console.log(chalk8.dim(" Continue working: archon start"));
|
|
5925
5545
|
console.log();
|
|
5926
5546
|
} catch (err2) {
|
|
5927
5547
|
spinner.fail("Error resuming session");
|
|
@@ -5964,7 +5584,7 @@ async function syncSession() {
|
|
|
5964
5584
|
spinner.fail(`Failed to sync: ${error.message}`);
|
|
5965
5585
|
return;
|
|
5966
5586
|
}
|
|
5967
|
-
spinner.succeed(
|
|
5587
|
+
spinner.succeed(chalk8.green("Session synced to cloud"));
|
|
5968
5588
|
} catch (err2) {
|
|
5969
5589
|
spinner.fail("Error syncing session");
|
|
5970
5590
|
console.error(err2);
|
|
@@ -5972,7 +5592,7 @@ async function syncSession() {
|
|
|
5972
5592
|
}
|
|
5973
5593
|
|
|
5974
5594
|
// src/cli/deploy.ts
|
|
5975
|
-
import
|
|
5595
|
+
import chalk9 from "chalk";
|
|
5976
5596
|
import { existsSync as existsSync10 } from "fs";
|
|
5977
5597
|
import { join as join9 } from "path";
|
|
5978
5598
|
import { execSync as execSync3 } from "child_process";
|
|
@@ -5987,46 +5607,46 @@ function detectPlatform(cwd) {
|
|
|
5987
5607
|
}
|
|
5988
5608
|
async function deploy(options) {
|
|
5989
5609
|
const cwd = process.cwd();
|
|
5990
|
-
console.log(
|
|
5610
|
+
console.log(chalk9.blue("Running pre-deploy checks..."));
|
|
5991
5611
|
const platform = options.platform ?? detectPlatform(cwd);
|
|
5992
|
-
console.log(
|
|
5612
|
+
console.log(chalk9.dim(`Detected platform: ${platform}`));
|
|
5993
5613
|
if (options.dryRun) {
|
|
5994
|
-
console.log(
|
|
5614
|
+
console.log(chalk9.dim("Dry run mode - would deploy to:"), platform);
|
|
5995
5615
|
return;
|
|
5996
5616
|
}
|
|
5997
5617
|
switch (platform) {
|
|
5998
5618
|
case "fly":
|
|
5999
|
-
console.log(
|
|
5619
|
+
console.log(chalk9.blue("Deploying to Fly.io..."));
|
|
6000
5620
|
execSync3("fly deploy", { cwd, stdio: "inherit" });
|
|
6001
5621
|
break;
|
|
6002
5622
|
case "vercel": {
|
|
6003
|
-
console.log(
|
|
5623
|
+
console.log(chalk9.blue("Deploying to Vercel..."));
|
|
6004
5624
|
const cmd = options.preview ? "vercel" : "vercel --prod";
|
|
6005
5625
|
execSync3(cmd, { cwd, stdio: "inherit" });
|
|
6006
5626
|
break;
|
|
6007
5627
|
}
|
|
6008
5628
|
case "netlify": {
|
|
6009
|
-
console.log(
|
|
5629
|
+
console.log(chalk9.blue("Deploying to Netlify..."));
|
|
6010
5630
|
const netlifyCmd = options.preview ? "netlify deploy" : "netlify deploy --prod";
|
|
6011
5631
|
execSync3(netlifyCmd, { cwd, stdio: "inherit" });
|
|
6012
5632
|
break;
|
|
6013
5633
|
}
|
|
6014
5634
|
case "railway":
|
|
6015
|
-
console.log(
|
|
5635
|
+
console.log(chalk9.blue("Deploying to Railway..."));
|
|
6016
5636
|
execSync3("railway up", { cwd, stdio: "inherit" });
|
|
6017
5637
|
break;
|
|
6018
5638
|
case "render":
|
|
6019
|
-
console.log(
|
|
6020
|
-
console.log(
|
|
5639
|
+
console.log(chalk9.blue("Deploying to Render..."));
|
|
5640
|
+
console.log(chalk9.yellow("Render deploys via git push. Push to your connected branch."));
|
|
6021
5641
|
break;
|
|
6022
5642
|
default:
|
|
6023
|
-
console.log(
|
|
6024
|
-
console.log(
|
|
5643
|
+
console.log(chalk9.yellow("Platform not detected. Please specify with --platform"));
|
|
5644
|
+
console.log(chalk9.dim("Supported: fly, vercel, netlify, railway, render"));
|
|
6025
5645
|
}
|
|
6026
5646
|
}
|
|
6027
5647
|
|
|
6028
5648
|
// src/cli/index-cmd.ts
|
|
6029
|
-
import
|
|
5649
|
+
import chalk10 from "chalk";
|
|
6030
5650
|
|
|
6031
5651
|
// src/core/indexing/local.ts
|
|
6032
5652
|
import { existsSync as existsSync11, mkdirSync } from "fs";
|
|
@@ -6440,14 +6060,14 @@ async function getCloudIndexer(cwd) {
|
|
|
6440
6060
|
const config = await loadConfig();
|
|
6441
6061
|
const authToken = getAuthToken(config);
|
|
6442
6062
|
if (!authToken) {
|
|
6443
|
-
console.error(
|
|
6063
|
+
console.error(chalk10.red('Not authenticated. Run "archon login" first.'));
|
|
6444
6064
|
return null;
|
|
6445
6065
|
}
|
|
6446
6066
|
const openaiKey = process.env["OPENAI_API_KEY"];
|
|
6447
6067
|
if (!openaiKey) {
|
|
6448
|
-
console.error(
|
|
6449
|
-
console.log(
|
|
6450
|
-
console.log(
|
|
6068
|
+
console.error(chalk10.red("OPENAI_API_KEY environment variable not set."));
|
|
6069
|
+
console.log(chalk10.dim("Cloud indexing requires an OpenAI API key for embeddings."));
|
|
6070
|
+
console.log(chalk10.dim("Set it with: export OPENAI_API_KEY=sk-..."));
|
|
6451
6071
|
return null;
|
|
6452
6072
|
}
|
|
6453
6073
|
const projectId = basename(cwd);
|
|
@@ -6464,12 +6084,12 @@ async function getCloudIndexer(cwd) {
|
|
|
6464
6084
|
});
|
|
6465
6085
|
const { data: { user } } = await client.auth.getUser();
|
|
6466
6086
|
if (!user) {
|
|
6467
|
-
console.error(
|
|
6087
|
+
console.error(chalk10.red("Failed to get user. Try logging in again."));
|
|
6468
6088
|
return null;
|
|
6469
6089
|
}
|
|
6470
6090
|
const { data: profile } = await client.from("user_profiles").select("id").eq("auth_id", user.id).single();
|
|
6471
6091
|
if (!profile) {
|
|
6472
|
-
console.error(
|
|
6092
|
+
console.error(chalk10.red("User profile not found."));
|
|
6473
6093
|
return null;
|
|
6474
6094
|
}
|
|
6475
6095
|
indexer.setUserId(profile.id);
|
|
@@ -6478,21 +6098,21 @@ async function getCloudIndexer(cwd) {
|
|
|
6478
6098
|
async function indexInit(options) {
|
|
6479
6099
|
const cwd = process.cwd();
|
|
6480
6100
|
if (options.cloud) {
|
|
6481
|
-
console.log(
|
|
6101
|
+
console.log(chalk10.blue("Initializing cloud semantic index..."));
|
|
6482
6102
|
const indexer = await getCloudIndexer(cwd);
|
|
6483
6103
|
if (!indexer) return;
|
|
6484
6104
|
try {
|
|
6485
6105
|
const status2 = await indexer.getStatus();
|
|
6486
|
-
console.log(
|
|
6487
|
-
console.log(
|
|
6488
|
-
console.log(
|
|
6106
|
+
console.log(chalk10.green("\u2713 Cloud indexing configured"));
|
|
6107
|
+
console.log(chalk10.green(`\u2713 Project ID: ${status2.projectId}`));
|
|
6108
|
+
console.log(chalk10.dim("\nRun `archon index update --cloud` to index your codebase."));
|
|
6489
6109
|
} catch (error) {
|
|
6490
|
-
console.error(
|
|
6110
|
+
console.error(chalk10.red(`Failed to initialize cloud index: ${error instanceof Error ? error.message : String(error)}`));
|
|
6491
6111
|
process.exit(1);
|
|
6492
6112
|
}
|
|
6493
6113
|
return;
|
|
6494
6114
|
}
|
|
6495
|
-
console.log(
|
|
6115
|
+
console.log(chalk10.blue("Initializing local semantic index..."));
|
|
6496
6116
|
try {
|
|
6497
6117
|
const indexer = new LocalIndexer();
|
|
6498
6118
|
await indexer.init(cwd);
|
|
@@ -6500,18 +6120,18 @@ async function indexInit(options) {
|
|
|
6500
6120
|
if (!response.ok) {
|
|
6501
6121
|
throw new Error("Ollama not responding");
|
|
6502
6122
|
}
|
|
6503
|
-
console.log(
|
|
6504
|
-
console.log(
|
|
6505
|
-
console.log(
|
|
6123
|
+
console.log(chalk10.green("\u2713 Ollama connection verified"));
|
|
6124
|
+
console.log(chalk10.green("\u2713 Index database created at .archon/index.db"));
|
|
6125
|
+
console.log(chalk10.dim("\nRun `archon index update` to index your codebase."));
|
|
6506
6126
|
indexer.close();
|
|
6507
6127
|
} catch (error) {
|
|
6508
6128
|
if (error instanceof Error && error.message.includes("Ollama")) {
|
|
6509
|
-
console.log(
|
|
6510
|
-
console.log(
|
|
6511
|
-
console.log(
|
|
6512
|
-
console.log(
|
|
6129
|
+
console.log(chalk10.red("\n\u2717 Ollama is not running"));
|
|
6130
|
+
console.log(chalk10.dim("Start Ollama with: ollama serve"));
|
|
6131
|
+
console.log(chalk10.dim("Then pull the embedding model: ollama pull nomic-embed-text"));
|
|
6132
|
+
console.log(chalk10.dim("\nOr use cloud indexing: archon index init --cloud"));
|
|
6513
6133
|
} else {
|
|
6514
|
-
console.error(
|
|
6134
|
+
console.error(chalk10.red(`Failed to initialize index: ${error instanceof Error ? error.message : String(error)}`));
|
|
6515
6135
|
}
|
|
6516
6136
|
process.exit(1);
|
|
6517
6137
|
}
|
|
@@ -6519,7 +6139,7 @@ async function indexInit(options) {
|
|
|
6519
6139
|
async function indexUpdate(options) {
|
|
6520
6140
|
const cwd = process.cwd();
|
|
6521
6141
|
if (options?.cloud) {
|
|
6522
|
-
console.log(
|
|
6142
|
+
console.log(chalk10.blue("Updating cloud semantic index..."));
|
|
6523
6143
|
const indexer = await getCloudIndexer(cwd);
|
|
6524
6144
|
if (!indexer) return;
|
|
6525
6145
|
try {
|
|
@@ -6527,15 +6147,15 @@ async function indexUpdate(options) {
|
|
|
6527
6147
|
cwd,
|
|
6528
6148
|
ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**", "**/build/**", "**/coverage/**"]
|
|
6529
6149
|
});
|
|
6530
|
-
console.log(
|
|
6531
|
-
console.log(
|
|
6150
|
+
console.log(chalk10.dim(`Found ${files.length} files to index...`));
|
|
6151
|
+
console.log(chalk10.dim("This may take a few minutes and will use OpenAI API credits.\n"));
|
|
6532
6152
|
let totalChunks = 0;
|
|
6533
6153
|
let indexedFiles = 0;
|
|
6534
6154
|
let skippedFiles = 0;
|
|
6535
6155
|
for (let i = 0; i < files.length; i++) {
|
|
6536
6156
|
const file = files[i];
|
|
6537
6157
|
if (!file) continue;
|
|
6538
|
-
process.stdout.write(`\r${
|
|
6158
|
+
process.stdout.write(`\r${chalk10.dim(`[${i + 1}/${files.length}] ${file.slice(0, 45).padEnd(45)}`)}`);
|
|
6539
6159
|
try {
|
|
6540
6160
|
const chunks = await indexer.indexFile(cwd, file);
|
|
6541
6161
|
if (chunks > 0) {
|
|
@@ -6546,21 +6166,21 @@ async function indexUpdate(options) {
|
|
|
6546
6166
|
}
|
|
6547
6167
|
} catch (error) {
|
|
6548
6168
|
console.log(`
|
|
6549
|
-
${
|
|
6169
|
+
${chalk10.yellow(`[!] Skipped ${file}: ${error instanceof Error ? error.message : "Unknown error"}`)}`);
|
|
6550
6170
|
}
|
|
6551
6171
|
}
|
|
6552
6172
|
console.log("\r" + " ".repeat(70));
|
|
6553
|
-
console.log(
|
|
6173
|
+
console.log(chalk10.green(`\u2713 Indexed ${indexedFiles} files (${totalChunks} chunks)`));
|
|
6554
6174
|
if (skippedFiles > 0) {
|
|
6555
|
-
console.log(
|
|
6175
|
+
console.log(chalk10.dim(` Skipped ${skippedFiles} unchanged files`));
|
|
6556
6176
|
}
|
|
6557
6177
|
} catch (error) {
|
|
6558
|
-
console.error(
|
|
6178
|
+
console.error(chalk10.red(`Failed to update cloud index: ${error instanceof Error ? error.message : String(error)}`));
|
|
6559
6179
|
process.exit(1);
|
|
6560
6180
|
}
|
|
6561
6181
|
return;
|
|
6562
6182
|
}
|
|
6563
|
-
console.log(
|
|
6183
|
+
console.log(chalk10.blue("Updating local semantic index..."));
|
|
6564
6184
|
try {
|
|
6565
6185
|
const indexer = new LocalIndexer();
|
|
6566
6186
|
await indexer.init(cwd);
|
|
@@ -6568,12 +6188,12 @@ ${chalk11.yellow(`[!] Skipped ${file}: ${error instanceof Error ? error.message
|
|
|
6568
6188
|
cwd,
|
|
6569
6189
|
ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**", "**/build/**", "**/coverage/**"]
|
|
6570
6190
|
});
|
|
6571
|
-
console.log(
|
|
6191
|
+
console.log(chalk10.dim(`Found ${files.length} files to index...`));
|
|
6572
6192
|
let totalChunks = 0;
|
|
6573
6193
|
let indexedFiles = 0;
|
|
6574
6194
|
for (const file of files) {
|
|
6575
6195
|
if (!file) continue;
|
|
6576
|
-
process.stdout.write(`\r${
|
|
6196
|
+
process.stdout.write(`\r${chalk10.dim(`Indexing: ${file.slice(0, 50).padEnd(50)}`)}`);
|
|
6577
6197
|
const chunks = await indexer.indexFile(cwd, file);
|
|
6578
6198
|
if (chunks > 0) {
|
|
6579
6199
|
totalChunks += chunks;
|
|
@@ -6581,10 +6201,10 @@ ${chalk11.yellow(`[!] Skipped ${file}: ${error instanceof Error ? error.message
|
|
|
6581
6201
|
}
|
|
6582
6202
|
}
|
|
6583
6203
|
console.log("\r" + " ".repeat(60));
|
|
6584
|
-
console.log(
|
|
6204
|
+
console.log(chalk10.green(`\u2713 Indexed ${indexedFiles} files (${totalChunks} chunks)`));
|
|
6585
6205
|
indexer.close();
|
|
6586
6206
|
} catch (error) {
|
|
6587
|
-
console.error(
|
|
6207
|
+
console.error(chalk10.red(`Failed to update index: ${error instanceof Error ? error.message : String(error)}`));
|
|
6588
6208
|
process.exit(1);
|
|
6589
6209
|
}
|
|
6590
6210
|
}
|
|
@@ -6594,25 +6214,25 @@ async function indexSearch(query, options) {
|
|
|
6594
6214
|
const indexer = await getCloudIndexer(cwd);
|
|
6595
6215
|
if (!indexer) return;
|
|
6596
6216
|
try {
|
|
6597
|
-
console.log(
|
|
6217
|
+
console.log(chalk10.dim("Searching cloud index..."));
|
|
6598
6218
|
const results = await indexer.search(query, 10);
|
|
6599
6219
|
if (results.length === 0) {
|
|
6600
|
-
console.log(
|
|
6601
|
-
console.log(
|
|
6220
|
+
console.log(chalk10.yellow("\nNo results found."));
|
|
6221
|
+
console.log(chalk10.dim("Try running `archon index update --cloud` first."));
|
|
6602
6222
|
} else {
|
|
6603
|
-
console.log(
|
|
6223
|
+
console.log(chalk10.blue(`
|
|
6604
6224
|
Top ${results.length} results for: "${query}"
|
|
6605
6225
|
`));
|
|
6606
6226
|
for (const result of results) {
|
|
6607
6227
|
const score = (result.score * 100).toFixed(1);
|
|
6608
|
-
console.log(
|
|
6228
|
+
console.log(chalk10.green(`[${score}%] ${result.file}`));
|
|
6609
6229
|
const preview = result.text.slice(0, 200).replace(/\n/g, " ").trim();
|
|
6610
|
-
console.log(
|
|
6230
|
+
console.log(chalk10.dim(` ${preview}${result.text.length > 200 ? "..." : ""}`));
|
|
6611
6231
|
console.log();
|
|
6612
6232
|
}
|
|
6613
6233
|
}
|
|
6614
6234
|
} catch (error) {
|
|
6615
|
-
console.error(
|
|
6235
|
+
console.error(chalk10.red(`Cloud search failed: ${error instanceof Error ? error.message : String(error)}`));
|
|
6616
6236
|
process.exit(1);
|
|
6617
6237
|
}
|
|
6618
6238
|
return;
|
|
@@ -6622,23 +6242,23 @@ Top ${results.length} results for: "${query}"
|
|
|
6622
6242
|
await indexer.init(cwd);
|
|
6623
6243
|
const results = await indexer.search(query, 10);
|
|
6624
6244
|
if (results.length === 0) {
|
|
6625
|
-
console.log(
|
|
6626
|
-
console.log(
|
|
6245
|
+
console.log(chalk10.yellow("No results found."));
|
|
6246
|
+
console.log(chalk10.dim("Try running `archon index update` first."));
|
|
6627
6247
|
} else {
|
|
6628
|
-
console.log(
|
|
6248
|
+
console.log(chalk10.blue(`
|
|
6629
6249
|
Top ${results.length} results for: "${query}"
|
|
6630
6250
|
`));
|
|
6631
6251
|
for (const result of results) {
|
|
6632
6252
|
const score = (result.score * 100).toFixed(1);
|
|
6633
|
-
console.log(
|
|
6253
|
+
console.log(chalk10.green(`[${score}%] ${result.file}`));
|
|
6634
6254
|
const preview = result.text.slice(0, 200).replace(/\n/g, " ").trim();
|
|
6635
|
-
console.log(
|
|
6255
|
+
console.log(chalk10.dim(` ${preview}${result.text.length > 200 ? "..." : ""}`));
|
|
6636
6256
|
console.log();
|
|
6637
6257
|
}
|
|
6638
6258
|
}
|
|
6639
6259
|
indexer.close();
|
|
6640
6260
|
} catch (error) {
|
|
6641
|
-
console.error(
|
|
6261
|
+
console.error(chalk10.red(`Search failed: ${error instanceof Error ? error.message : String(error)}`));
|
|
6642
6262
|
process.exit(1);
|
|
6643
6263
|
}
|
|
6644
6264
|
}
|
|
@@ -6649,17 +6269,17 @@ async function indexStatus(options) {
|
|
|
6649
6269
|
if (!indexer) return;
|
|
6650
6270
|
try {
|
|
6651
6271
|
const status2 = await indexer.getStatus();
|
|
6652
|
-
console.log(
|
|
6653
|
-
console.log(` Project ID: ${
|
|
6654
|
-
console.log(` Files indexed: ${
|
|
6655
|
-
console.log(` Total chunks: ${
|
|
6656
|
-
console.log(` Last updated: ${status2.lastUpdated ?
|
|
6272
|
+
console.log(chalk10.blue("\nCloud Semantic Index Status\n"));
|
|
6273
|
+
console.log(` Project ID: ${chalk10.green(status2.projectId)}`);
|
|
6274
|
+
console.log(` Files indexed: ${chalk10.green(status2.fileCount)}`);
|
|
6275
|
+
console.log(` Total chunks: ${chalk10.green(status2.chunkCount)}`);
|
|
6276
|
+
console.log(` Last updated: ${status2.lastUpdated ? chalk10.dim(status2.lastUpdated) : chalk10.yellow("Never")}`);
|
|
6657
6277
|
if (status2.jobStatus) {
|
|
6658
|
-
console.log(` Job status: ${
|
|
6278
|
+
console.log(` Job status: ${chalk10.dim(status2.jobStatus)}`);
|
|
6659
6279
|
}
|
|
6660
|
-
console.log(` Storage: ${
|
|
6280
|
+
console.log(` Storage: ${chalk10.dim("Supabase pgvector")}`);
|
|
6661
6281
|
} catch (error) {
|
|
6662
|
-
console.error(
|
|
6282
|
+
console.error(chalk10.red(`Failed to get cloud status: ${error instanceof Error ? error.message : String(error)}`));
|
|
6663
6283
|
process.exit(1);
|
|
6664
6284
|
}
|
|
6665
6285
|
return;
|
|
@@ -6668,14 +6288,14 @@ async function indexStatus(options) {
|
|
|
6668
6288
|
const indexer = new LocalIndexer();
|
|
6669
6289
|
await indexer.init(cwd);
|
|
6670
6290
|
const status2 = await indexer.getStatus();
|
|
6671
|
-
console.log(
|
|
6672
|
-
console.log(` Files indexed: ${
|
|
6673
|
-
console.log(` Total chunks: ${
|
|
6674
|
-
console.log(` Last updated: ${status2.lastUpdated ?
|
|
6675
|
-
console.log(` Database: ${
|
|
6291
|
+
console.log(chalk10.blue("\nLocal Semantic Index Status\n"));
|
|
6292
|
+
console.log(` Files indexed: ${chalk10.green(status2.fileCount)}`);
|
|
6293
|
+
console.log(` Total chunks: ${chalk10.green(status2.chunkCount)}`);
|
|
6294
|
+
console.log(` Last updated: ${status2.lastUpdated ? chalk10.dim(status2.lastUpdated) : chalk10.yellow("Never")}`);
|
|
6295
|
+
console.log(` Database: ${chalk10.dim(join12(cwd, ".archon/index.db"))}`);
|
|
6676
6296
|
indexer.close();
|
|
6677
6297
|
} catch (error) {
|
|
6678
|
-
console.error(
|
|
6298
|
+
console.error(chalk10.red(`Failed to get status: ${error instanceof Error ? error.message : String(error)}`));
|
|
6679
6299
|
process.exit(1);
|
|
6680
6300
|
}
|
|
6681
6301
|
}
|
|
@@ -6685,30 +6305,30 @@ async function indexClear(options) {
|
|
|
6685
6305
|
const indexer = await getCloudIndexer(cwd);
|
|
6686
6306
|
if (!indexer) return;
|
|
6687
6307
|
try {
|
|
6688
|
-
console.log(
|
|
6308
|
+
console.log(chalk10.yellow("Clearing cloud index..."));
|
|
6689
6309
|
await indexer.clearProject();
|
|
6690
|
-
console.log(
|
|
6310
|
+
console.log(chalk10.green("\u2713 Cloud index cleared"));
|
|
6691
6311
|
} catch (error) {
|
|
6692
|
-
console.error(
|
|
6312
|
+
console.error(chalk10.red(`Failed to clear cloud index: ${error instanceof Error ? error.message : String(error)}`));
|
|
6693
6313
|
process.exit(1);
|
|
6694
6314
|
}
|
|
6695
6315
|
return;
|
|
6696
6316
|
}
|
|
6697
|
-
console.log(
|
|
6317
|
+
console.log(chalk10.yellow("To clear local index, delete .archon/index.db"));
|
|
6698
6318
|
}
|
|
6699
6319
|
|
|
6700
6320
|
// src/cli/github.ts
|
|
6701
|
-
import
|
|
6321
|
+
import chalk11 from "chalk";
|
|
6702
6322
|
import open2 from "open";
|
|
6703
6323
|
var API_URL2 = process.env["ARCHONDEV_API_URL"] ?? "https://archondev-api.fly.dev";
|
|
6704
6324
|
async function githubConnect() {
|
|
6705
6325
|
const config = await loadConfig();
|
|
6706
6326
|
const authToken = getAuthToken(config);
|
|
6707
6327
|
if (!authToken) {
|
|
6708
|
-
console.error(
|
|
6328
|
+
console.error(chalk11.red('Not authenticated. Run "archon login" first.'));
|
|
6709
6329
|
process.exit(1);
|
|
6710
6330
|
}
|
|
6711
|
-
console.log(
|
|
6331
|
+
console.log(chalk11.dim("Starting GitHub connection..."));
|
|
6712
6332
|
try {
|
|
6713
6333
|
const response = await fetch(`${API_URL2}/api/github/connect`, {
|
|
6714
6334
|
headers: {
|
|
@@ -6717,18 +6337,18 @@ async function githubConnect() {
|
|
|
6717
6337
|
});
|
|
6718
6338
|
if (!response.ok) {
|
|
6719
6339
|
const error = await response.json();
|
|
6720
|
-
console.error(
|
|
6340
|
+
console.error(chalk11.red(error.error ?? "Failed to start GitHub connection"));
|
|
6721
6341
|
process.exit(1);
|
|
6722
6342
|
}
|
|
6723
6343
|
const data = await response.json();
|
|
6724
|
-
console.log(
|
|
6725
|
-
console.log(
|
|
6726
|
-
console.log(
|
|
6344
|
+
console.log(chalk11.dim("\nOpening browser for GitHub authorization..."));
|
|
6345
|
+
console.log(chalk11.dim("If browser does not open, visit:"));
|
|
6346
|
+
console.log(chalk11.blue(data.url));
|
|
6727
6347
|
await open2(data.url);
|
|
6728
|
-
console.log(
|
|
6729
|
-
console.log(
|
|
6348
|
+
console.log(chalk11.dim("\nComplete the authorization in your browser."));
|
|
6349
|
+
console.log(chalk11.dim('Then run "archon github status" to verify connection.'));
|
|
6730
6350
|
} catch (error) {
|
|
6731
|
-
console.error(
|
|
6351
|
+
console.error(chalk11.red(error instanceof Error ? error.message : "Failed to connect"));
|
|
6732
6352
|
process.exit(1);
|
|
6733
6353
|
}
|
|
6734
6354
|
}
|
|
@@ -6736,7 +6356,7 @@ async function githubStatus() {
|
|
|
6736
6356
|
const config = await loadConfig();
|
|
6737
6357
|
const authToken = getAuthToken(config);
|
|
6738
6358
|
if (!authToken) {
|
|
6739
|
-
console.error(
|
|
6359
|
+
console.error(chalk11.red('Not authenticated. Run "archon login" first.'));
|
|
6740
6360
|
process.exit(1);
|
|
6741
6361
|
}
|
|
6742
6362
|
try {
|
|
@@ -6747,20 +6367,20 @@ async function githubStatus() {
|
|
|
6747
6367
|
});
|
|
6748
6368
|
if (!response.ok) {
|
|
6749
6369
|
const error = await response.json();
|
|
6750
|
-
console.error(
|
|
6370
|
+
console.error(chalk11.red(error.error ?? "Failed to get GitHub status"));
|
|
6751
6371
|
process.exit(1);
|
|
6752
6372
|
}
|
|
6753
6373
|
const data = await response.json();
|
|
6754
6374
|
if (data.connected) {
|
|
6755
|
-
console.log(
|
|
6756
|
-
console.log(
|
|
6757
|
-
console.log(
|
|
6375
|
+
console.log(chalk11.green("\u2713 GitHub connected"));
|
|
6376
|
+
console.log(chalk11.dim(` Username: ${data.username}`));
|
|
6377
|
+
console.log(chalk11.dim(` Connected: ${data.connectedAt ? new Date(data.connectedAt).toLocaleDateString() : "Unknown"}`));
|
|
6758
6378
|
} else {
|
|
6759
|
-
console.log(
|
|
6760
|
-
console.log(
|
|
6379
|
+
console.log(chalk11.yellow("GitHub not connected"));
|
|
6380
|
+
console.log(chalk11.dim('Run "archon github connect" to connect your GitHub account.'));
|
|
6761
6381
|
}
|
|
6762
6382
|
} catch (error) {
|
|
6763
|
-
console.error(
|
|
6383
|
+
console.error(chalk11.red(error instanceof Error ? error.message : "Failed to get status"));
|
|
6764
6384
|
process.exit(1);
|
|
6765
6385
|
}
|
|
6766
6386
|
}
|
|
@@ -6768,7 +6388,7 @@ async function githubDisconnect() {
|
|
|
6768
6388
|
const config = await loadConfig();
|
|
6769
6389
|
const authToken = getAuthToken(config);
|
|
6770
6390
|
if (!authToken) {
|
|
6771
|
-
console.error(
|
|
6391
|
+
console.error(chalk11.red('Not authenticated. Run "archon login" first.'));
|
|
6772
6392
|
process.exit(1);
|
|
6773
6393
|
}
|
|
6774
6394
|
try {
|
|
@@ -6780,18 +6400,18 @@ async function githubDisconnect() {
|
|
|
6780
6400
|
});
|
|
6781
6401
|
if (!response.ok) {
|
|
6782
6402
|
const error = await response.json();
|
|
6783
|
-
console.error(
|
|
6403
|
+
console.error(chalk11.red(error.error ?? "Failed to disconnect GitHub"));
|
|
6784
6404
|
process.exit(1);
|
|
6785
6405
|
}
|
|
6786
|
-
console.log(
|
|
6406
|
+
console.log(chalk11.green("\u2713 GitHub disconnected"));
|
|
6787
6407
|
} catch (error) {
|
|
6788
|
-
console.error(
|
|
6408
|
+
console.error(chalk11.red(error instanceof Error ? error.message : "Failed to disconnect"));
|
|
6789
6409
|
process.exit(1);
|
|
6790
6410
|
}
|
|
6791
6411
|
}
|
|
6792
6412
|
|
|
6793
6413
|
// src/cli/interview.ts
|
|
6794
|
-
import
|
|
6414
|
+
import chalk12 from "chalk";
|
|
6795
6415
|
import readline3 from "readline";
|
|
6796
6416
|
import ora3 from "ora";
|
|
6797
6417
|
import { existsSync as existsSync13, readFileSync as readFileSync5, writeFileSync, mkdirSync as mkdirSync2 } from "fs";
|
|
@@ -6809,23 +6429,23 @@ async function interview(options = {}) {
|
|
|
6809
6429
|
if (!existsSync13(archonDir)) {
|
|
6810
6430
|
mkdirSync2(archonDir, { recursive: true });
|
|
6811
6431
|
}
|
|
6812
|
-
console.log(
|
|
6813
|
-
console.log(
|
|
6432
|
+
console.log(chalk12.bold("\n\u{1F3AF} ArchonDev Project Interview"));
|
|
6433
|
+
console.log(chalk12.dim("Let's define what you're building.\n"));
|
|
6814
6434
|
const constitutionPath = getConstitutionPath(cwd);
|
|
6815
6435
|
const draftPath = getDraftPath(cwd);
|
|
6816
6436
|
if (existsSync13(constitutionPath)) {
|
|
6817
6437
|
const existing = deserializeConstitution(readFileSync5(constitutionPath, "utf-8"));
|
|
6818
6438
|
if (existing.state === "FROZEN") {
|
|
6819
|
-
console.log(
|
|
6820
|
-
console.log(
|
|
6821
|
-
console.log(
|
|
6439
|
+
console.log(chalk12.yellow("[!] A frozen Constitution already exists."));
|
|
6440
|
+
console.log(chalk12.dim(` Project: ${existing.branding.projectName}`));
|
|
6441
|
+
console.log(chalk12.dim(` Frozen: ${existing.frozenAt?.toISOString()}`));
|
|
6822
6442
|
console.log();
|
|
6823
6443
|
const action = await prompt2("Start a new interview (overwrite) or view existing? (new/view)");
|
|
6824
6444
|
if (action.toLowerCase() === "view") {
|
|
6825
6445
|
console.log("\n" + summarizeConstitution(existing));
|
|
6826
6446
|
return;
|
|
6827
6447
|
} else if (action.toLowerCase() !== "new") {
|
|
6828
|
-
console.log(
|
|
6448
|
+
console.log(chalk12.dim("Cancelled."));
|
|
6829
6449
|
return;
|
|
6830
6450
|
}
|
|
6831
6451
|
}
|
|
@@ -6834,8 +6454,8 @@ async function interview(options = {}) {
|
|
|
6834
6454
|
let startPhase = 1;
|
|
6835
6455
|
if (existsSync13(draftPath) && options.resume !== false) {
|
|
6836
6456
|
const draft = deserializeConstitution(readFileSync5(draftPath, "utf-8"));
|
|
6837
|
-
console.log(
|
|
6838
|
-
console.log(
|
|
6457
|
+
console.log(chalk12.blue("[i] Found draft from previous session."));
|
|
6458
|
+
console.log(chalk12.dim(` Project: ${draft.branding.projectName || "(unnamed)"}`));
|
|
6839
6459
|
console.log();
|
|
6840
6460
|
const resumeChoice = await prompt2("Resume draft or start fresh? (resume/fresh)");
|
|
6841
6461
|
if (resumeChoice.toLowerCase() === "resume") {
|
|
@@ -6847,7 +6467,7 @@ async function interview(options = {}) {
|
|
|
6847
6467
|
break;
|
|
6848
6468
|
}
|
|
6849
6469
|
}
|
|
6850
|
-
console.log(
|
|
6470
|
+
console.log(chalk12.green(`
|
|
6851
6471
|
\u2713 Resuming at Phase ${startPhase}: ${INTERVIEW_PHASES[startPhase]?.name}
|
|
6852
6472
|
`));
|
|
6853
6473
|
} else {
|
|
@@ -6858,19 +6478,19 @@ async function interview(options = {}) {
|
|
|
6858
6478
|
}
|
|
6859
6479
|
if (options.phase && options.phase >= 1 && options.phase <= 5) {
|
|
6860
6480
|
startPhase = options.phase;
|
|
6861
|
-
console.log(
|
|
6481
|
+
console.log(chalk12.dim(`Starting at Phase ${startPhase}...
|
|
6862
6482
|
`));
|
|
6863
6483
|
}
|
|
6864
|
-
console.log(
|
|
6865
|
-
console.log(
|
|
6866
|
-
console.log(
|
|
6484
|
+
console.log(chalk12.dim("\u2500".repeat(40)));
|
|
6485
|
+
console.log(chalk12.dim(formatProgressBar(startPhase)));
|
|
6486
|
+
console.log(chalk12.dim("\u2500".repeat(40)));
|
|
6867
6487
|
console.log();
|
|
6868
6488
|
let currentPhase = startPhase;
|
|
6869
6489
|
while (currentPhase <= 5) {
|
|
6870
6490
|
const result = await runPhase(currentPhase, constitution, cwd);
|
|
6871
6491
|
if (result.action === "exit") {
|
|
6872
6492
|
saveDraft(cwd, constitution);
|
|
6873
|
-
console.log(
|
|
6493
|
+
console.log(chalk12.dim("\nDraft saved. Run `archon interview` to resume.\n"));
|
|
6874
6494
|
return;
|
|
6875
6495
|
}
|
|
6876
6496
|
if (result.action === "back" && currentPhase > 1) {
|
|
@@ -6885,9 +6505,9 @@ async function interview(options = {}) {
|
|
|
6885
6505
|
if (next) {
|
|
6886
6506
|
currentPhase = next;
|
|
6887
6507
|
console.log();
|
|
6888
|
-
console.log(
|
|
6889
|
-
console.log(
|
|
6890
|
-
console.log(
|
|
6508
|
+
console.log(chalk12.dim("\u2500".repeat(40)));
|
|
6509
|
+
console.log(chalk12.dim(formatProgressBar(currentPhase)));
|
|
6510
|
+
console.log(chalk12.dim("\u2500".repeat(40)));
|
|
6891
6511
|
console.log();
|
|
6892
6512
|
} else {
|
|
6893
6513
|
break;
|
|
@@ -6895,9 +6515,9 @@ async function interview(options = {}) {
|
|
|
6895
6515
|
}
|
|
6896
6516
|
const validationResult = validateConstitution(constitution);
|
|
6897
6517
|
if (!validationResult.valid) {
|
|
6898
|
-
console.log(
|
|
6518
|
+
console.log(chalk12.red("\n[!] Constitution has validation errors:\n"));
|
|
6899
6519
|
for (const error of validationResult.errors) {
|
|
6900
|
-
console.log(
|
|
6520
|
+
console.log(chalk12.red(` \u2022 ${error}`));
|
|
6901
6521
|
}
|
|
6902
6522
|
console.log();
|
|
6903
6523
|
const fix = await promptYesNo3("Would you like to go back and fix these?", true);
|
|
@@ -6907,9 +6527,9 @@ async function interview(options = {}) {
|
|
|
6907
6527
|
}
|
|
6908
6528
|
}
|
|
6909
6529
|
if (validationResult.warnings.length > 0) {
|
|
6910
|
-
console.log(
|
|
6530
|
+
console.log(chalk12.yellow("\n[!] Warnings:\n"));
|
|
6911
6531
|
for (const warning of validationResult.warnings) {
|
|
6912
|
-
console.log(
|
|
6532
|
+
console.log(chalk12.yellow(` \u2022 ${warning}`));
|
|
6913
6533
|
}
|
|
6914
6534
|
console.log();
|
|
6915
6535
|
}
|
|
@@ -6919,21 +6539,21 @@ async function interview(options = {}) {
|
|
|
6919
6539
|
constitution.costs = estimateCosts(constitution, config.tier || "FREE");
|
|
6920
6540
|
const challengeResult = analyzeForChallenges(constitution);
|
|
6921
6541
|
if (challengeResult.shouldChallenge) {
|
|
6922
|
-
console.log(
|
|
6923
|
-
console.log(
|
|
6542
|
+
console.log(chalk12.bold("\n\u{1F3AF} Challenge Mode\n"));
|
|
6543
|
+
console.log(chalk12.dim("Let me share some observations about your project scope...\n"));
|
|
6924
6544
|
for (const challenge of challengeResult.challenges) {
|
|
6925
6545
|
const prompt3 = generateChallengePrompt(challenge);
|
|
6926
|
-
const icon = challenge.severity === "critical" ?
|
|
6927
|
-
console.log(`${icon} ${
|
|
6928
|
-
console.log(
|
|
6546
|
+
const icon = challenge.severity === "critical" ? chalk12.red("\u25CF") : chalk12.yellow("\u25CF");
|
|
6547
|
+
console.log(`${icon} ${chalk12.bold(challenge.title)}`);
|
|
6548
|
+
console.log(chalk12.dim(` ${prompt3}`));
|
|
6929
6549
|
console.log();
|
|
6930
6550
|
}
|
|
6931
|
-
console.log(
|
|
6551
|
+
console.log(chalk12.dim("\u2500".repeat(40)));
|
|
6932
6552
|
console.log(summarizeChallenges(challengeResult));
|
|
6933
|
-
console.log(
|
|
6553
|
+
console.log(chalk12.dim("\u2500".repeat(40)));
|
|
6934
6554
|
console.log();
|
|
6935
6555
|
if (challengeResult.featuresToDefer.length > 0) {
|
|
6936
|
-
console.log(
|
|
6556
|
+
console.log(chalk12.bold("Suggested Features to Defer to Post-MVP:\n"));
|
|
6937
6557
|
for (const feature of challengeResult.featuresToDefer) {
|
|
6938
6558
|
console.log(` \u2022 ${feature.name}`);
|
|
6939
6559
|
}
|
|
@@ -6948,39 +6568,39 @@ async function interview(options = {}) {
|
|
|
6948
6568
|
constitution.complexity = calculateComplexity(constitution);
|
|
6949
6569
|
constitution.estimatedBuildHours = estimateBuildHours(constitution.complexity);
|
|
6950
6570
|
constitution.costs = estimateCosts(constitution, config.tier || "FREE");
|
|
6951
|
-
console.log(
|
|
6952
|
-
console.log(
|
|
6953
|
-
console.log(
|
|
6571
|
+
console.log(chalk12.green("\n\u2713 Features deferred. Updated estimates:"));
|
|
6572
|
+
console.log(chalk12.dim(` Complexity: ${constitution.complexity.tier}`));
|
|
6573
|
+
console.log(chalk12.dim(` Build time: ~${Math.round(constitution.estimatedBuildHours)} hours`));
|
|
6954
6574
|
console.log();
|
|
6955
6575
|
saveDraft(cwd, constitution);
|
|
6956
6576
|
}
|
|
6957
6577
|
}
|
|
6958
6578
|
const criticalCount = challengeResult.challenges.filter((c) => c.severity === "critical").length;
|
|
6959
6579
|
if (criticalCount > 0) {
|
|
6960
|
-
console.log(
|
|
6580
|
+
console.log(chalk12.red(`
|
|
6961
6581
|
\u26A0\uFE0F ${criticalCount} critical issue(s) detected.`));
|
|
6962
6582
|
const proceed = await promptYesNo3("Proceed anyway?", false);
|
|
6963
6583
|
if (!proceed) {
|
|
6964
6584
|
saveDraft(cwd, constitution);
|
|
6965
|
-
console.log(
|
|
6585
|
+
console.log(chalk12.dim("\nDraft saved. Address the issues and run `archon interview` again.\n"));
|
|
6966
6586
|
return;
|
|
6967
6587
|
}
|
|
6968
6588
|
}
|
|
6969
6589
|
} else {
|
|
6970
|
-
console.log(
|
|
6590
|
+
console.log(chalk12.green("\n\u2713 Scope looks reasonable! No major concerns detected.\n"));
|
|
6971
6591
|
}
|
|
6972
|
-
console.log(
|
|
6592
|
+
console.log(chalk12.bold("\n\u{1F4CB} Constitution Summary\n"));
|
|
6973
6593
|
console.log(summarizeConstitution(constitution));
|
|
6974
6594
|
console.log();
|
|
6975
6595
|
if (options.dryRun) {
|
|
6976
|
-
console.log(
|
|
6596
|
+
console.log(chalk12.dim("(Dry run mode - not freezing Constitution)"));
|
|
6977
6597
|
saveDraft(cwd, constitution);
|
|
6978
6598
|
return;
|
|
6979
6599
|
}
|
|
6980
6600
|
const confirmFreeze = await promptYesNo3("Freeze this Constitution and start building?", true);
|
|
6981
6601
|
if (!confirmFreeze) {
|
|
6982
6602
|
saveDraft(cwd, constitution);
|
|
6983
|
-
console.log(
|
|
6603
|
+
console.log(chalk12.dim("\nDraft saved. Run `archon interview` to continue.\n"));
|
|
6984
6604
|
return;
|
|
6985
6605
|
}
|
|
6986
6606
|
const spinner = ora3("Freezing Constitution...").start();
|
|
@@ -6991,15 +6611,15 @@ async function interview(options = {}) {
|
|
|
6991
6611
|
const { unlinkSync } = await import("fs");
|
|
6992
6612
|
unlinkSync(draftPath);
|
|
6993
6613
|
}
|
|
6994
|
-
spinner.succeed(
|
|
6614
|
+
spinner.succeed(chalk12.green("Constitution frozen!"));
|
|
6995
6615
|
console.log();
|
|
6996
|
-
console.log(
|
|
6997
|
-
console.log(
|
|
6616
|
+
console.log(chalk12.dim(`Hash: ${frozen.hash?.substring(0, 32)}...`));
|
|
6617
|
+
console.log(chalk12.dim(`Saved: ${constitutionPath}`));
|
|
6998
6618
|
console.log();
|
|
6999
|
-
console.log(
|
|
7000
|
-
console.log(` ${
|
|
7001
|
-
console.log(` ${
|
|
7002
|
-
console.log(` ${
|
|
6619
|
+
console.log(chalk12.bold("Next Steps:\n"));
|
|
6620
|
+
console.log(` ${chalk12.cyan("1.")} Run ${chalk12.bold("archon generate")} to create atoms from this Constitution`);
|
|
6621
|
+
console.log(` ${chalk12.cyan("2.")} Run ${chalk12.bold("archon list")} to see generated atoms`);
|
|
6622
|
+
console.log(` ${chalk12.cyan("3.")} Run ${chalk12.bold("archon execute <atom-id>")} to start building`);
|
|
7003
6623
|
console.log();
|
|
7004
6624
|
} catch (err2) {
|
|
7005
6625
|
spinner.fail("Failed to freeze Constitution");
|
|
@@ -7008,18 +6628,18 @@ async function interview(options = {}) {
|
|
|
7008
6628
|
}
|
|
7009
6629
|
async function runPhase(phase, constitution, cwd) {
|
|
7010
6630
|
const phaseInfo = INTERVIEW_PHASES[phase];
|
|
7011
|
-
console.log(
|
|
7012
|
-
console.log(
|
|
6631
|
+
console.log(chalk12.bold(`Phase ${phase}: ${phaseInfo.name}`));
|
|
6632
|
+
console.log(chalk12.dim(phaseInfo.description));
|
|
7013
6633
|
console.log();
|
|
7014
6634
|
const skippable = getSkippableQuestions(phase, constitution);
|
|
7015
6635
|
let updatedConstitution = { ...constitution };
|
|
7016
6636
|
for (const question of phaseInfo.questions) {
|
|
7017
6637
|
if (skippable.includes(question.id)) {
|
|
7018
|
-
console.log(
|
|
6638
|
+
console.log(chalk12.dim(`[\u2713] ${question.prompt.split("?")[0]}... (already answered)`));
|
|
7019
6639
|
continue;
|
|
7020
6640
|
}
|
|
7021
6641
|
if (phase === 5 && question.id === "review_summary") {
|
|
7022
|
-
console.log(
|
|
6642
|
+
console.log(chalk12.bold("\n\u{1F4CB} Current State:\n"));
|
|
7023
6643
|
console.log(summarizeConstitution(updatedConstitution));
|
|
7024
6644
|
console.log();
|
|
7025
6645
|
}
|
|
@@ -7036,14 +6656,14 @@ async function runPhase(phase, constitution, cwd) {
|
|
|
7036
6656
|
if (question.validator) {
|
|
7037
6657
|
const validation = question.validator(answer);
|
|
7038
6658
|
if (!validation.valid) {
|
|
7039
|
-
console.log(
|
|
6659
|
+
console.log(chalk12.red(` ${validation.error}`));
|
|
7040
6660
|
continue;
|
|
7041
6661
|
}
|
|
7042
6662
|
}
|
|
7043
6663
|
const extracted = question.extractor(answer, updatedConstitution);
|
|
7044
6664
|
updatedConstitution = { ...updatedConstitution, ...extracted };
|
|
7045
6665
|
if (question.followUp && answer.length > 10) {
|
|
7046
|
-
console.log(
|
|
6666
|
+
console.log(chalk12.dim(` ${question.followUp}`));
|
|
7047
6667
|
}
|
|
7048
6668
|
}
|
|
7049
6669
|
return { action: "next", constitution: updatedConstitution };
|
|
@@ -7053,7 +6673,7 @@ function saveDraft(cwd, constitution) {
|
|
|
7053
6673
|
writeFileSync(draftPath, serializeConstitution(constitution));
|
|
7054
6674
|
}
|
|
7055
6675
|
async function promptQuestion(question) {
|
|
7056
|
-
const prefix = question.required ?
|
|
6676
|
+
const prefix = question.required ? chalk12.red("*") : " ";
|
|
7057
6677
|
return prompt2(`${prefix} ${question.prompt}`);
|
|
7058
6678
|
}
|
|
7059
6679
|
function prompt2(question) {
|
|
@@ -7062,7 +6682,7 @@ function prompt2(question) {
|
|
|
7062
6682
|
input: process.stdin,
|
|
7063
6683
|
output: process.stdout
|
|
7064
6684
|
});
|
|
7065
|
-
rl.question(`${
|
|
6685
|
+
rl.question(`${chalk12.cyan("?")} ${question}
|
|
7066
6686
|
> `, (answer) => {
|
|
7067
6687
|
rl.close();
|
|
7068
6688
|
resolve(answer.trim());
|
|
@@ -7076,7 +6696,7 @@ function promptYesNo3(question, defaultValue) {
|
|
|
7076
6696
|
output: process.stdout
|
|
7077
6697
|
});
|
|
7078
6698
|
const hint = defaultValue ? "(Y/n)" : "(y/N)";
|
|
7079
|
-
rl.question(`${
|
|
6699
|
+
rl.question(`${chalk12.cyan("?")} ${question} ${hint}: `, (answer) => {
|
|
7080
6700
|
rl.close();
|
|
7081
6701
|
if (answer.trim() === "") {
|
|
7082
6702
|
resolve(defaultValue);
|
|
@@ -7095,10 +6715,10 @@ async function showConstitution() {
|
|
|
7095
6715
|
console.log(summarizeConstitution(constitution));
|
|
7096
6716
|
} else if (existsSync13(draftPath)) {
|
|
7097
6717
|
const draft = deserializeConstitution(readFileSync5(draftPath, "utf-8"));
|
|
7098
|
-
console.log(
|
|
6718
|
+
console.log(chalk12.yellow("[DRAFT]"));
|
|
7099
6719
|
console.log(summarizeConstitution(draft));
|
|
7100
6720
|
} else {
|
|
7101
|
-
console.log(
|
|
6721
|
+
console.log(chalk12.dim("No Constitution found. Run `archon interview` to create one."));
|
|
7102
6722
|
}
|
|
7103
6723
|
}
|
|
7104
6724
|
async function validateConstitutionCommand() {
|
|
@@ -7107,23 +6727,23 @@ async function validateConstitutionCommand() {
|
|
|
7107
6727
|
const draftPath = getDraftPath(cwd);
|
|
7108
6728
|
const path2 = existsSync13(constitutionPath) ? constitutionPath : draftPath;
|
|
7109
6729
|
if (!existsSync13(path2)) {
|
|
7110
|
-
console.log(
|
|
6730
|
+
console.log(chalk12.dim("No Constitution found. Run `archon interview` to create one."));
|
|
7111
6731
|
return;
|
|
7112
6732
|
}
|
|
7113
6733
|
const constitution = deserializeConstitution(readFileSync5(path2, "utf-8"));
|
|
7114
6734
|
const result = validateConstitution(constitution);
|
|
7115
6735
|
if (result.valid) {
|
|
7116
|
-
console.log(
|
|
6736
|
+
console.log(chalk12.green("\u2713 Constitution is valid"));
|
|
7117
6737
|
} else {
|
|
7118
|
-
console.log(
|
|
6738
|
+
console.log(chalk12.red("\u2717 Constitution has errors:"));
|
|
7119
6739
|
for (const error of result.errors) {
|
|
7120
|
-
console.log(
|
|
6740
|
+
console.log(chalk12.red(` \u2022 ${error}`));
|
|
7121
6741
|
}
|
|
7122
6742
|
}
|
|
7123
6743
|
if (result.warnings.length > 0) {
|
|
7124
|
-
console.log(
|
|
6744
|
+
console.log(chalk12.yellow("\nWarnings:"));
|
|
7125
6745
|
for (const warning of result.warnings) {
|
|
7126
|
-
console.log(
|
|
6746
|
+
console.log(chalk12.yellow(` \u2022 ${warning}`));
|
|
7127
6747
|
}
|
|
7128
6748
|
}
|
|
7129
6749
|
}
|
|
@@ -7131,7 +6751,7 @@ async function exportConstitution(format) {
|
|
|
7131
6751
|
const cwd = process.cwd();
|
|
7132
6752
|
const constitutionPath = getConstitutionPath(cwd);
|
|
7133
6753
|
if (!existsSync13(constitutionPath)) {
|
|
7134
|
-
console.log(
|
|
6754
|
+
console.log(chalk12.dim("No frozen Constitution found."));
|
|
7135
6755
|
return;
|
|
7136
6756
|
}
|
|
7137
6757
|
const constitution = deserializeConstitution(readFileSync5(constitutionPath, "utf-8"));
|
|
@@ -7144,26 +6764,26 @@ async function exportConstitution(format) {
|
|
|
7144
6764
|
console.log(summarizeConstitution(constitution));
|
|
7145
6765
|
break;
|
|
7146
6766
|
default:
|
|
7147
|
-
console.log(
|
|
6767
|
+
console.log(chalk12.red(`Unknown format: ${format}. Use 'json' or 'markdown'.`));
|
|
7148
6768
|
}
|
|
7149
6769
|
}
|
|
7150
6770
|
async function generateAtoms(options = {}) {
|
|
7151
6771
|
const cwd = process.cwd();
|
|
7152
6772
|
const constitutionPath = getConstitutionPath(cwd);
|
|
7153
6773
|
if (!existsSync13(constitutionPath)) {
|
|
7154
|
-
console.log(
|
|
7155
|
-
console.log(
|
|
6774
|
+
console.log(chalk12.red("No frozen Constitution found."));
|
|
6775
|
+
console.log(chalk12.dim("Run `archon interview` to create one first."));
|
|
7156
6776
|
return;
|
|
7157
6777
|
}
|
|
7158
6778
|
const constitution = deserializeConstitution(readFileSync5(constitutionPath, "utf-8"));
|
|
7159
6779
|
if (constitution.state !== "FROZEN") {
|
|
7160
|
-
console.log(
|
|
7161
|
-
console.log(
|
|
6780
|
+
console.log(chalk12.yellow("Constitution is not frozen yet."));
|
|
6781
|
+
console.log(chalk12.dim("Complete the interview and freeze before generating atoms."));
|
|
7162
6782
|
return;
|
|
7163
6783
|
}
|
|
7164
|
-
console.log(
|
|
7165
|
-
console.log(
|
|
7166
|
-
console.log(
|
|
6784
|
+
console.log(chalk12.bold("\n\u{1F527} Generating Atoms from Constitution\n"));
|
|
6785
|
+
console.log(chalk12.dim(`Project: ${constitution.branding.projectName}`));
|
|
6786
|
+
console.log(chalk12.dim(`Hash: ${constitution.hash?.substring(0, 16)}...`));
|
|
7167
6787
|
console.log();
|
|
7168
6788
|
const spinner = ora3("Generating atoms...").start();
|
|
7169
6789
|
const result = generateAtomsFromConstitution(constitution, {
|
|
@@ -7176,7 +6796,7 @@ async function generateAtoms(options = {}) {
|
|
|
7176
6796
|
console.log(summarizeGeneration(result));
|
|
7177
6797
|
console.log();
|
|
7178
6798
|
if (options.dryRun) {
|
|
7179
|
-
console.log(
|
|
6799
|
+
console.log(chalk12.dim("(Dry run - not writing prd.json)"));
|
|
7180
6800
|
return;
|
|
7181
6801
|
}
|
|
7182
6802
|
const prdPath = options.output ?? join13(cwd, "prd.json");
|
|
@@ -7184,23 +6804,23 @@ async function generateAtoms(options = {}) {
|
|
|
7184
6804
|
if (existsSync13(prdPath)) {
|
|
7185
6805
|
const overwrite = await promptYesNo3("prd.json already exists. Overwrite?", false);
|
|
7186
6806
|
if (!overwrite) {
|
|
7187
|
-
console.log(
|
|
6807
|
+
console.log(chalk12.dim("Cancelled. Existing prd.json preserved."));
|
|
7188
6808
|
return;
|
|
7189
6809
|
}
|
|
7190
6810
|
}
|
|
7191
6811
|
writeFileSync(prdPath, JSON.stringify(prdContent, null, 2));
|
|
7192
|
-
console.log(
|
|
6812
|
+
console.log(chalk12.green(`
|
|
7193
6813
|
\u2713 Written to ${prdPath}`));
|
|
7194
6814
|
console.log();
|
|
7195
|
-
console.log(
|
|
7196
|
-
console.log(` ${
|
|
7197
|
-
console.log(` ${
|
|
7198
|
-
console.log(` ${
|
|
6815
|
+
console.log(chalk12.bold("Next Steps:\n"));
|
|
6816
|
+
console.log(` ${chalk12.cyan("1.")} Run ${chalk12.bold("archon list")} to see all atoms`);
|
|
6817
|
+
console.log(` ${chalk12.cyan("2.")} Run ${chalk12.bold("archon execute ATOM-001")} to start building`);
|
|
6818
|
+
console.log(` ${chalk12.cyan("3.")} Run ${chalk12.bold("archon watch")} to monitor progress`);
|
|
7199
6819
|
console.log();
|
|
7200
6820
|
}
|
|
7201
6821
|
|
|
7202
6822
|
// src/cli/eject.ts
|
|
7203
|
-
import
|
|
6823
|
+
import chalk13 from "chalk";
|
|
7204
6824
|
import { existsSync as existsSync14, rmSync } from "fs";
|
|
7205
6825
|
import { readFile as readFile8, writeFile as writeFile6 } from "fs/promises";
|
|
7206
6826
|
import { join as join14 } from "path";
|
|
@@ -7217,70 +6837,70 @@ var METADATA_FILES = [
|
|
|
7217
6837
|
];
|
|
7218
6838
|
async function eject(options = {}) {
|
|
7219
6839
|
const cwd = process.cwd();
|
|
7220
|
-
console.log(
|
|
6840
|
+
console.log(chalk13.blue("\n\u{1F680} ArchonDev Eject\n"));
|
|
7221
6841
|
const archonDir = join14(cwd, ".archon");
|
|
7222
6842
|
if (!existsSync14(archonDir)) {
|
|
7223
|
-
console.log(
|
|
6843
|
+
console.log(chalk13.yellow("This does not appear to be an ArchonDev project (.archon/ not found)."));
|
|
7224
6844
|
return;
|
|
7225
6845
|
}
|
|
7226
|
-
console.log(
|
|
6846
|
+
console.log(chalk13.dim("The following will be removed/modified:\n"));
|
|
7227
6847
|
const filesToRemove = [];
|
|
7228
6848
|
for (const file of ARCHON_FILES) {
|
|
7229
6849
|
const filePath = join14(cwd, file);
|
|
7230
6850
|
if (existsSync14(filePath)) {
|
|
7231
6851
|
filesToRemove.push(file);
|
|
7232
|
-
console.log(
|
|
6852
|
+
console.log(chalk13.red(` \u2717 ${file}`));
|
|
7233
6853
|
}
|
|
7234
6854
|
}
|
|
7235
6855
|
const archMd = join14(cwd, "ARCHITECTURE.md");
|
|
7236
6856
|
if (existsSync14(archMd) && !options.keepArchitecture) {
|
|
7237
|
-
console.log(
|
|
6857
|
+
console.log(chalk13.yellow(` ? ARCHITECTURE.md (will be kept by default)`));
|
|
7238
6858
|
}
|
|
7239
6859
|
console.log();
|
|
7240
|
-
console.log(
|
|
6860
|
+
console.log(chalk13.dim("Files to be modified:"));
|
|
7241
6861
|
for (const file of METADATA_FILES) {
|
|
7242
6862
|
const filePath = join14(cwd, file);
|
|
7243
6863
|
if (existsSync14(filePath)) {
|
|
7244
|
-
console.log(
|
|
6864
|
+
console.log(chalk13.yellow(` \u25CF ${file}`));
|
|
7245
6865
|
}
|
|
7246
6866
|
}
|
|
7247
6867
|
console.log();
|
|
7248
6868
|
if (!options.force) {
|
|
7249
6869
|
const confirmed = await promptYesNo4("This will permanently remove ArchonDev from your project. Continue?", false);
|
|
7250
6870
|
if (!confirmed) {
|
|
7251
|
-
console.log(
|
|
6871
|
+
console.log(chalk13.dim("Eject cancelled."));
|
|
7252
6872
|
return;
|
|
7253
6873
|
}
|
|
7254
6874
|
}
|
|
7255
6875
|
console.log();
|
|
7256
6876
|
const result = await performEject(cwd, options);
|
|
7257
6877
|
if (result.success) {
|
|
7258
|
-
console.log(
|
|
6878
|
+
console.log(chalk13.green("\n\u2705 Eject complete!\n"));
|
|
7259
6879
|
if (result.filesRemoved.length > 0) {
|
|
7260
|
-
console.log(
|
|
6880
|
+
console.log(chalk13.dim("Removed:"));
|
|
7261
6881
|
for (const file of result.filesRemoved) {
|
|
7262
|
-
console.log(
|
|
6882
|
+
console.log(chalk13.dim(` - ${file}`));
|
|
7263
6883
|
}
|
|
7264
6884
|
}
|
|
7265
6885
|
if (result.filesModified.length > 0) {
|
|
7266
|
-
console.log(
|
|
6886
|
+
console.log(chalk13.dim("\nModified:"));
|
|
7267
6887
|
for (const file of result.filesModified) {
|
|
7268
|
-
console.log(
|
|
6888
|
+
console.log(chalk13.dim(` - ${file}`));
|
|
7269
6889
|
}
|
|
7270
6890
|
}
|
|
7271
6891
|
if (result.warnings.length > 0) {
|
|
7272
|
-
console.log(
|
|
6892
|
+
console.log(chalk13.yellow("\nWarnings:"));
|
|
7273
6893
|
for (const warning of result.warnings) {
|
|
7274
|
-
console.log(
|
|
6894
|
+
console.log(chalk13.yellow(` \u26A0\uFE0F ${warning}`));
|
|
7275
6895
|
}
|
|
7276
6896
|
}
|
|
7277
6897
|
console.log();
|
|
7278
|
-
console.log(
|
|
7279
|
-
console.log(
|
|
6898
|
+
console.log(chalk13.blue("Your project is now a standard repository."));
|
|
6899
|
+
console.log(chalk13.dim("Thank you for using ArchonDev!"));
|
|
7280
6900
|
} else {
|
|
7281
|
-
console.log(
|
|
6901
|
+
console.log(chalk13.red("\n\u274C Eject failed."));
|
|
7282
6902
|
for (const warning of result.warnings) {
|
|
7283
|
-
console.log(
|
|
6903
|
+
console.log(chalk13.red(` ${warning}`));
|
|
7284
6904
|
}
|
|
7285
6905
|
}
|
|
7286
6906
|
}
|
|
@@ -7387,17 +7007,17 @@ async function performEject(cwd, options) {
|
|
|
7387
7007
|
}
|
|
7388
7008
|
async function ejectDryRun() {
|
|
7389
7009
|
const cwd = process.cwd();
|
|
7390
|
-
console.log(
|
|
7010
|
+
console.log(chalk13.blue("\n\u{1F50D} Eject Dry Run\n"));
|
|
7391
7011
|
const archonDir = join14(cwd, ".archon");
|
|
7392
7012
|
if (!existsSync14(archonDir)) {
|
|
7393
|
-
console.log(
|
|
7013
|
+
console.log(chalk13.yellow("This does not appear to be an ArchonDev project."));
|
|
7394
7014
|
return;
|
|
7395
7015
|
}
|
|
7396
7016
|
console.log("The following would be removed:\n");
|
|
7397
7017
|
for (const file of ARCHON_FILES) {
|
|
7398
7018
|
const filePath = join14(cwd, file);
|
|
7399
7019
|
if (existsSync14(filePath)) {
|
|
7400
|
-
console.log(
|
|
7020
|
+
console.log(chalk13.red(` \u2717 ${file}`));
|
|
7401
7021
|
}
|
|
7402
7022
|
}
|
|
7403
7023
|
console.log();
|
|
@@ -7405,11 +7025,11 @@ async function ejectDryRun() {
|
|
|
7405
7025
|
for (const file of METADATA_FILES) {
|
|
7406
7026
|
const filePath = join14(cwd, file);
|
|
7407
7027
|
if (existsSync14(filePath)) {
|
|
7408
|
-
console.log(
|
|
7028
|
+
console.log(chalk13.yellow(` \u25CF ${file}`));
|
|
7409
7029
|
}
|
|
7410
7030
|
}
|
|
7411
7031
|
console.log();
|
|
7412
|
-
console.log(
|
|
7032
|
+
console.log(chalk13.dim('Run "archon eject" to proceed.'));
|
|
7413
7033
|
}
|
|
7414
7034
|
function promptYesNo4(question, defaultValue) {
|
|
7415
7035
|
return new Promise((resolve) => {
|
|
@@ -7418,7 +7038,7 @@ function promptYesNo4(question, defaultValue) {
|
|
|
7418
7038
|
output: process.stdout
|
|
7419
7039
|
});
|
|
7420
7040
|
const hint = defaultValue ? "(Y/n)" : "(y/N)";
|
|
7421
|
-
rl.question(`${
|
|
7041
|
+
rl.question(`${chalk13.cyan("?")} ${question} ${hint}: `, (answer) => {
|
|
7422
7042
|
rl.close();
|
|
7423
7043
|
if (answer.trim() === "") {
|
|
7424
7044
|
resolve(defaultValue);
|
|
@@ -7430,7 +7050,7 @@ function promptYesNo4(question, defaultValue) {
|
|
|
7430
7050
|
}
|
|
7431
7051
|
|
|
7432
7052
|
// src/cli/revert.ts
|
|
7433
|
-
import
|
|
7053
|
+
import chalk14 from "chalk";
|
|
7434
7054
|
import { execSync as execSync4 } from "child_process";
|
|
7435
7055
|
import { existsSync as existsSync15 } from "fs";
|
|
7436
7056
|
import { readFile as readFile9, writeFile as writeFile7 } from "fs/promises";
|
|
@@ -7475,35 +7095,35 @@ async function findAtomCommits(limit = 50) {
|
|
|
7475
7095
|
}
|
|
7476
7096
|
return commits;
|
|
7477
7097
|
} catch (error) {
|
|
7478
|
-
console.error(
|
|
7098
|
+
console.error(chalk14.red("Failed to read git history:"), error instanceof Error ? error.message : "Unknown error");
|
|
7479
7099
|
return [];
|
|
7480
7100
|
}
|
|
7481
7101
|
}
|
|
7482
7102
|
async function historyCommand(options) {
|
|
7483
7103
|
const limit = options.limit ?? 20;
|
|
7484
|
-
console.log(
|
|
7104
|
+
console.log(chalk14.blue("\n\u{1F4DC} Atom Execution History\n"));
|
|
7485
7105
|
const commits = await findAtomCommits(limit);
|
|
7486
7106
|
if (commits.length === 0) {
|
|
7487
|
-
console.log(
|
|
7488
|
-
console.log(
|
|
7107
|
+
console.log(chalk14.dim("No atom commits found in git history."));
|
|
7108
|
+
console.log(chalk14.dim('Atom commits are created when you run "archon execute <atom-id>".'));
|
|
7489
7109
|
return;
|
|
7490
7110
|
}
|
|
7491
|
-
console.log(
|
|
7111
|
+
console.log(chalk14.dim(`Showing ${commits.length} atom commit(s):
|
|
7492
7112
|
`));
|
|
7493
7113
|
for (const commit of commits) {
|
|
7494
7114
|
const shortHash = commit.commitHash.substring(0, 7);
|
|
7495
7115
|
const filesLabel = commit.filesChanged === 1 ? "file" : "files";
|
|
7496
|
-
console.log(`${
|
|
7497
|
-
console.log(
|
|
7498
|
-
console.log(
|
|
7116
|
+
console.log(`${chalk14.yellow(shortHash)} ${chalk14.cyan(commit.atomId)}`);
|
|
7117
|
+
console.log(chalk14.dim(` ${commit.message}`));
|
|
7118
|
+
console.log(chalk14.dim(` ${commit.date} | ${commit.filesChanged} ${filesLabel} changed`));
|
|
7499
7119
|
console.log();
|
|
7500
7120
|
}
|
|
7501
|
-
console.log(
|
|
7502
|
-
console.log(
|
|
7121
|
+
console.log(chalk14.dim("To revert an atom: archon revert <atom-id>"));
|
|
7122
|
+
console.log(chalk14.dim("Or by commit hash: archon revert --commit <hash>"));
|
|
7503
7123
|
}
|
|
7504
7124
|
async function revertCommand(atomIdOrHash, options = {}) {
|
|
7505
7125
|
const cwd = process.cwd();
|
|
7506
|
-
console.log(
|
|
7126
|
+
console.log(chalk14.blue("\n\u23EA Atom Revert\n"));
|
|
7507
7127
|
let commit;
|
|
7508
7128
|
if (atomIdOrHash.match(/^[a-f0-9]{7,40}$/i)) {
|
|
7509
7129
|
const commits = await findAtomCommits(100);
|
|
@@ -7513,54 +7133,54 @@ async function revertCommand(atomIdOrHash, options = {}) {
|
|
|
7513
7133
|
commit = commits.find((c) => c.atomId.toLowerCase() === atomIdOrHash.toLowerCase());
|
|
7514
7134
|
}
|
|
7515
7135
|
if (!commit) {
|
|
7516
|
-
console.log(
|
|
7517
|
-
console.log(
|
|
7136
|
+
console.log(chalk14.red(`No atom commit found for: ${atomIdOrHash}`));
|
|
7137
|
+
console.log(chalk14.dim('Run "archon history" to see available atom commits.'));
|
|
7518
7138
|
return;
|
|
7519
7139
|
}
|
|
7520
|
-
console.log(`Atom: ${
|
|
7521
|
-
console.log(`Commit: ${
|
|
7140
|
+
console.log(`Atom: ${chalk14.cyan(commit.atomId)}`);
|
|
7141
|
+
console.log(`Commit: ${chalk14.yellow(commit.commitHash.substring(0, 7))}`);
|
|
7522
7142
|
console.log(`Message: ${commit.message}`);
|
|
7523
7143
|
console.log(`Date: ${commit.date}`);
|
|
7524
7144
|
console.log(`Files changed: ${commit.filesChanged}`);
|
|
7525
7145
|
console.log();
|
|
7526
7146
|
try {
|
|
7527
|
-
console.log(
|
|
7147
|
+
console.log(chalk14.dim("Changes to be reverted:"));
|
|
7528
7148
|
const diffStat = execSync4(
|
|
7529
7149
|
`git diff --stat ${commit.commitHash}^..${commit.commitHash}`,
|
|
7530
7150
|
{ cwd, encoding: "utf-8" }
|
|
7531
7151
|
);
|
|
7532
|
-
console.log(
|
|
7152
|
+
console.log(chalk14.dim(diffStat));
|
|
7533
7153
|
} catch {
|
|
7534
7154
|
}
|
|
7535
7155
|
if (!options.force) {
|
|
7536
7156
|
const confirmed = await promptYesNo5("Revert this atom commit?", false);
|
|
7537
7157
|
if (!confirmed) {
|
|
7538
|
-
console.log(
|
|
7158
|
+
console.log(chalk14.dim("Revert cancelled."));
|
|
7539
7159
|
return;
|
|
7540
7160
|
}
|
|
7541
7161
|
}
|
|
7542
7162
|
try {
|
|
7543
7163
|
const revertArgs = options.noCommit ? "--no-commit" : "";
|
|
7544
7164
|
execSync4(`git revert ${revertArgs} ${commit.commitHash}`, { cwd, stdio: "pipe" });
|
|
7545
|
-
console.log(
|
|
7165
|
+
console.log(chalk14.green(`
|
|
7546
7166
|
\u2705 Successfully reverted ${commit.atomId}`));
|
|
7547
7167
|
if (options.noCommit) {
|
|
7548
|
-
console.log(
|
|
7549
|
-
console.log(
|
|
7168
|
+
console.log(chalk14.dim("Changes are staged but not committed."));
|
|
7169
|
+
console.log(chalk14.dim('Run "git commit" to finalize the revert.'));
|
|
7550
7170
|
} else {
|
|
7551
|
-
console.log(
|
|
7171
|
+
console.log(chalk14.dim("A new commit has been created to undo the changes."));
|
|
7552
7172
|
}
|
|
7553
7173
|
await updateAtomStatus(commit.atomId, "REVERTED");
|
|
7554
7174
|
} catch (error) {
|
|
7555
7175
|
const errorMsg = error instanceof Error ? error.message : "Unknown error";
|
|
7556
7176
|
if (errorMsg.includes("conflict")) {
|
|
7557
|
-
console.log(
|
|
7558
|
-
console.log(
|
|
7559
|
-
console.log(
|
|
7560
|
-
console.log(
|
|
7177
|
+
console.log(chalk14.yellow("\n\u26A0\uFE0F Merge conflict detected during revert."));
|
|
7178
|
+
console.log(chalk14.dim("Resolve conflicts manually, then:"));
|
|
7179
|
+
console.log(chalk14.dim(" git add ."));
|
|
7180
|
+
console.log(chalk14.dim(" git revert --continue"));
|
|
7561
7181
|
} else {
|
|
7562
|
-
console.log(
|
|
7563
|
-
console.log(
|
|
7182
|
+
console.log(chalk14.red("\n\u274C Revert failed:"), errorMsg);
|
|
7183
|
+
console.log(chalk14.dim("You may need to resolve this manually."));
|
|
7564
7184
|
}
|
|
7565
7185
|
}
|
|
7566
7186
|
}
|
|
@@ -7579,10 +7199,10 @@ async function updateAtomStatus(atomId, status2) {
|
|
|
7579
7199
|
}
|
|
7580
7200
|
}
|
|
7581
7201
|
async function revertableAtoms() {
|
|
7582
|
-
console.log(
|
|
7202
|
+
console.log(chalk14.blue("\n\u{1F504} Revertable Atoms\n"));
|
|
7583
7203
|
const commits = await findAtomCommits(30);
|
|
7584
7204
|
if (commits.length === 0) {
|
|
7585
|
-
console.log(
|
|
7205
|
+
console.log(chalk14.dim("No atom commits found."));
|
|
7586
7206
|
return;
|
|
7587
7207
|
}
|
|
7588
7208
|
const atomMap = /* @__PURE__ */ new Map();
|
|
@@ -7591,14 +7211,14 @@ async function revertableAtoms() {
|
|
|
7591
7211
|
atomMap.set(commit.atomId, commit);
|
|
7592
7212
|
}
|
|
7593
7213
|
}
|
|
7594
|
-
console.log(
|
|
7214
|
+
console.log(chalk14.dim(`Found ${atomMap.size} unique atom(s) in history:
|
|
7595
7215
|
`));
|
|
7596
7216
|
for (const [atomId, commit] of atomMap) {
|
|
7597
7217
|
const shortHash = commit.commitHash.substring(0, 7);
|
|
7598
|
-
console.log(` ${
|
|
7218
|
+
console.log(` ${chalk14.cyan(atomId)} ${chalk14.dim(`(${shortHash})`)} - ${commit.message.substring(0, 50)}`);
|
|
7599
7219
|
}
|
|
7600
7220
|
console.log();
|
|
7601
|
-
console.log(
|
|
7221
|
+
console.log(chalk14.dim("To revert: archon revert <atom-id>"));
|
|
7602
7222
|
}
|
|
7603
7223
|
function promptYesNo5(question, defaultValue) {
|
|
7604
7224
|
return new Promise((resolve) => {
|
|
@@ -7607,7 +7227,7 @@ function promptYesNo5(question, defaultValue) {
|
|
|
7607
7227
|
output: process.stdout
|
|
7608
7228
|
});
|
|
7609
7229
|
const hint = defaultValue ? "(Y/n)" : "(y/N)";
|
|
7610
|
-
rl.question(`${
|
|
7230
|
+
rl.question(`${chalk14.cyan("?")} ${question} ${hint}: `, (answer) => {
|
|
7611
7231
|
rl.close();
|
|
7612
7232
|
if (answer.trim() === "") {
|
|
7613
7233
|
resolve(defaultValue);
|
|
@@ -7619,17 +7239,17 @@ function promptYesNo5(question, defaultValue) {
|
|
|
7619
7239
|
}
|
|
7620
7240
|
|
|
7621
7241
|
// src/cli/models-sync.ts
|
|
7622
|
-
import
|
|
7242
|
+
import chalk15 from "chalk";
|
|
7623
7243
|
async function modelsSync(options) {
|
|
7624
7244
|
const supabaseUrl = process.env["SUPABASE_URL"];
|
|
7625
7245
|
const supabaseKey = process.env["SUPABASE_SERVICE_ROLE_KEY"] || process.env["SUPABASE_ANON_KEY"];
|
|
7626
7246
|
if (!supabaseUrl) {
|
|
7627
|
-
console.log(
|
|
7628
|
-
console.log(
|
|
7629
|
-
console.log(
|
|
7247
|
+
console.log(chalk15.red("SUPABASE_URL not set. Cannot trigger remote sync."));
|
|
7248
|
+
console.log(chalk15.dim("Run the pricing check locally instead:"));
|
|
7249
|
+
console.log(chalk15.dim(" npx tsx scripts/update-model-pricing.ts --check"));
|
|
7630
7250
|
return;
|
|
7631
7251
|
}
|
|
7632
|
-
console.log(
|
|
7252
|
+
console.log(chalk15.blue("\n\u{1F504} Triggering model registry sync...\n"));
|
|
7633
7253
|
try {
|
|
7634
7254
|
const functionUrl = `${supabaseUrl}/functions/v1/model-registry-sync`;
|
|
7635
7255
|
const response = await fetch(functionUrl, {
|
|
@@ -7641,83 +7261,83 @@ async function modelsSync(options) {
|
|
|
7641
7261
|
});
|
|
7642
7262
|
if (!response.ok) {
|
|
7643
7263
|
const errorText = await response.text();
|
|
7644
|
-
console.log(
|
|
7264
|
+
console.log(chalk15.red(`Sync failed: ${response.status} - ${errorText}`));
|
|
7645
7265
|
return;
|
|
7646
7266
|
}
|
|
7647
7267
|
const result = await response.json();
|
|
7648
|
-
console.log(
|
|
7268
|
+
console.log(chalk15.bold("Sync Results:"));
|
|
7649
7269
|
console.log(` Providers checked: ${result.providersChecked.join(", ")}`);
|
|
7650
7270
|
console.log(` Duration: ${result.durationMs}ms`);
|
|
7651
7271
|
console.log();
|
|
7652
|
-
console.log(
|
|
7272
|
+
console.log(chalk15.bold("Parse Confidence:"));
|
|
7653
7273
|
for (const [provider, score] of Object.entries(result.confidenceScores)) {
|
|
7654
7274
|
const pct = (score * 100).toFixed(0);
|
|
7655
|
-
const color = score >= 0.8 ?
|
|
7275
|
+
const color = score >= 0.8 ? chalk15.green : score >= 0.5 ? chalk15.yellow : chalk15.red;
|
|
7656
7276
|
console.log(` ${provider}: ${color(pct + "%")}`);
|
|
7657
7277
|
}
|
|
7658
7278
|
console.log();
|
|
7659
7279
|
if (result.diffs.length === 0) {
|
|
7660
|
-
console.log(
|
|
7280
|
+
console.log(chalk15.green("\u2705 All model pricing is up to date. No changes detected."));
|
|
7661
7281
|
} else {
|
|
7662
7282
|
const pricingChanges = result.diffs.filter((d) => d.type === "PRICING_CHANGE");
|
|
7663
7283
|
const newModels = result.diffs.filter((d) => d.type === "NEW_MODEL");
|
|
7664
7284
|
if (pricingChanges.length > 0) {
|
|
7665
|
-
console.log(
|
|
7285
|
+
console.log(chalk15.yellow(`\u{1F4B0} Pricing Changes (${pricingChanges.length}):`));
|
|
7666
7286
|
for (const d of pricingChanges) {
|
|
7667
|
-
console.log(` ${d.provider}/${
|
|
7668
|
-
console.log(` Old: ${
|
|
7669
|
-
console.log(` New: ${
|
|
7287
|
+
console.log(` ${d.provider}/${chalk15.bold(d.modelId)}`);
|
|
7288
|
+
console.log(` Old: ${chalk15.red(d.oldValue ?? "unknown")}`);
|
|
7289
|
+
console.log(` New: ${chalk15.green(d.newValue ?? "unknown")}`);
|
|
7670
7290
|
}
|
|
7671
7291
|
console.log();
|
|
7672
7292
|
}
|
|
7673
7293
|
if (newModels.length > 0) {
|
|
7674
|
-
console.log(
|
|
7294
|
+
console.log(chalk15.cyan(`\u{1F195} New Models (${newModels.length}):`));
|
|
7675
7295
|
for (const d of newModels) {
|
|
7676
|
-
console.log(` ${d.provider}/${
|
|
7296
|
+
console.log(` ${d.provider}/${chalk15.bold(d.modelId)}: ${d.details}`);
|
|
7677
7297
|
}
|
|
7678
7298
|
console.log();
|
|
7679
7299
|
}
|
|
7680
|
-
console.log(
|
|
7300
|
+
console.log(chalk15.bold(`Applied: ${result.modelsUpdated} updated, ${result.modelsAdded} added`));
|
|
7681
7301
|
}
|
|
7682
7302
|
if (result.parseErrors.length > 0) {
|
|
7683
7303
|
console.log();
|
|
7684
|
-
console.log(
|
|
7304
|
+
console.log(chalk15.red(`\u26A0\uFE0F Warnings/Errors (${result.parseErrors.length}):`));
|
|
7685
7305
|
for (const err2 of result.parseErrors) {
|
|
7686
|
-
console.log(
|
|
7306
|
+
console.log(chalk15.red(` - ${err2}`));
|
|
7687
7307
|
}
|
|
7688
7308
|
}
|
|
7689
7309
|
console.log();
|
|
7690
7310
|
} catch (err2) {
|
|
7691
|
-
console.log(
|
|
7311
|
+
console.log(chalk15.red(`Failed to run sync: ${err2}`));
|
|
7692
7312
|
}
|
|
7693
7313
|
}
|
|
7694
7314
|
async function modelsList() {
|
|
7695
7315
|
const { getAllActiveModels, getModelCost, isFreeModel } = await import("./models-UTFGCHAY.js");
|
|
7696
7316
|
const models = getAllActiveModels();
|
|
7697
|
-
console.log(
|
|
7317
|
+
console.log(chalk15.bold("\n\u{1F4CB} Model Registry\n"));
|
|
7698
7318
|
let currentProvider = "";
|
|
7699
7319
|
for (const model of models) {
|
|
7700
7320
|
if (model.provider !== currentProvider) {
|
|
7701
7321
|
currentProvider = model.provider;
|
|
7702
|
-
console.log(
|
|
7322
|
+
console.log(chalk15.bold.blue(`
|
|
7703
7323
|
${currentProvider.toUpperCase()}`));
|
|
7704
|
-
console.log(
|
|
7324
|
+
console.log(chalk15.dim(" \u2500".repeat(40)));
|
|
7705
7325
|
}
|
|
7706
7326
|
const cost = getModelCost(model.modelId);
|
|
7707
7327
|
const free = isFreeModel(model.modelId);
|
|
7708
|
-
const tier = free ?
|
|
7709
|
-
const category = model.category === "thinking" ?
|
|
7328
|
+
const tier = free ? chalk15.green(" [FREE]") : "";
|
|
7329
|
+
const category = model.category === "thinking" ? chalk15.magenta("thinking") : chalk15.cyan("fast");
|
|
7710
7330
|
const inputPrice = cost ? `$${(cost.costPer1kInput * 1e3).toFixed(2)}/1M` : "?";
|
|
7711
7331
|
const outputPrice = cost ? `$${(cost.costPer1kOutput * 1e3).toFixed(2)}/1M` : "?";
|
|
7712
|
-
console.log(` ${
|
|
7713
|
-
console.log(
|
|
7332
|
+
console.log(` ${chalk15.bold(model.modelId)}${tier}`);
|
|
7333
|
+
console.log(chalk15.dim(` ${category} | Input: ${inputPrice} | Output: ${outputPrice}`));
|
|
7714
7334
|
}
|
|
7715
7335
|
console.log();
|
|
7716
7336
|
}
|
|
7717
7337
|
|
|
7718
7338
|
// src/cli/governance.ts
|
|
7719
7339
|
import { Command as Command2 } from "commander";
|
|
7720
|
-
import
|
|
7340
|
+
import chalk16 from "chalk";
|
|
7721
7341
|
import { existsSync as existsSync19, readFileSync as readFileSync7 } from "fs";
|
|
7722
7342
|
import { readFile as readFile12 } from "fs/promises";
|
|
7723
7343
|
import { join as join19 } from "path";
|
|
@@ -8537,9 +8157,9 @@ function parseContextMeta(content) {
|
|
|
8537
8157
|
function renderStatusCounts(counts) {
|
|
8538
8158
|
const total = Object.values(counts).reduce((sum, value) => sum + value, 0);
|
|
8539
8159
|
if (total === 0) return;
|
|
8540
|
-
console.log(
|
|
8160
|
+
console.log(chalk16.dim(` Tasks: ${total} total`));
|
|
8541
8161
|
console.log(
|
|
8542
|
-
|
|
8162
|
+
chalk16.dim(
|
|
8543
8163
|
` pending: ${counts.pending} | in_progress: ${counts.in_progress} | verification: ${counts.verification} | done: ${counts.done}`
|
|
8544
8164
|
)
|
|
8545
8165
|
);
|
|
@@ -8555,22 +8175,22 @@ function createGovernanceCommand() {
|
|
|
8555
8175
|
const cwd = process.cwd();
|
|
8556
8176
|
const store = new GovernanceStore(cwd);
|
|
8557
8177
|
store.ensureStructure();
|
|
8558
|
-
console.log(
|
|
8178
|
+
console.log(chalk16.bold("\nGovernance Status\n"));
|
|
8559
8179
|
const archInfo = resolveArchitecturePath2(cwd);
|
|
8560
8180
|
if (archInfo.path) {
|
|
8561
8181
|
const parser = new ArchitectureParser(archInfo.path);
|
|
8562
8182
|
const parsed = await parser.parse();
|
|
8563
8183
|
if (parsed.success && parsed.schema) {
|
|
8564
8184
|
const posture = parsed.schema.qualityLevel?.posture ?? "unknown";
|
|
8565
|
-
console.log(
|
|
8566
|
-
console.log(
|
|
8567
|
-
console.log(
|
|
8568
|
-
console.log(
|
|
8185
|
+
console.log(chalk16.green(" \u2713") + ` Architecture (${archInfo.source})`);
|
|
8186
|
+
console.log(chalk16.dim(` posture: ${posture}`));
|
|
8187
|
+
console.log(chalk16.dim(` invariants: ${parsed.schema.invariants.length}`));
|
|
8188
|
+
console.log(chalk16.dim(` protected paths: ${parsed.schema.protectedPaths.length}`));
|
|
8569
8189
|
} else {
|
|
8570
|
-
console.log(
|
|
8190
|
+
console.log(chalk16.yellow(" ! Architecture present but failed to parse"));
|
|
8571
8191
|
}
|
|
8572
8192
|
} else {
|
|
8573
|
-
console.log(
|
|
8193
|
+
console.log(chalk16.yellow(" \u25CB No architecture file found"));
|
|
8574
8194
|
}
|
|
8575
8195
|
const tasksPath = join19(cwd, ACTIVE_TASKS_PATH2);
|
|
8576
8196
|
if (existsSync19(tasksPath)) {
|
|
@@ -8580,33 +8200,33 @@ function createGovernanceCommand() {
|
|
|
8580
8200
|
if (tasks2) {
|
|
8581
8201
|
renderStatusCounts(countTaskStatuses(tasks2));
|
|
8582
8202
|
} else {
|
|
8583
|
-
console.log(
|
|
8203
|
+
console.log(chalk16.yellow(" ! tasks.json present but invalid"));
|
|
8584
8204
|
}
|
|
8585
8205
|
} catch {
|
|
8586
|
-
console.log(
|
|
8206
|
+
console.log(chalk16.yellow(" ! tasks.json present but unreadable"));
|
|
8587
8207
|
}
|
|
8588
8208
|
}
|
|
8589
8209
|
const contextPath = join19(cwd, CURRENT_CONTEXT_PATH);
|
|
8590
8210
|
if (existsSync19(contextPath)) {
|
|
8591
8211
|
const content = readFileSync7(contextPath, "utf-8");
|
|
8592
8212
|
const meta = parseContextMeta(content);
|
|
8593
|
-
console.log(
|
|
8213
|
+
console.log(chalk16.dim(` Handoff: ${meta.timestamp ?? "present"}`));
|
|
8594
8214
|
if (meta.reason) {
|
|
8595
|
-
console.log(
|
|
8215
|
+
console.log(chalk16.dim(` reason: ${meta.reason}`));
|
|
8596
8216
|
}
|
|
8597
8217
|
}
|
|
8598
8218
|
const handoffHistoryPath = join19(cwd, HANDOFF_HISTORY_PATH);
|
|
8599
8219
|
if (existsSync19(handoffHistoryPath)) {
|
|
8600
8220
|
const count = lineCount(readFileSync7(handoffHistoryPath, "utf-8"));
|
|
8601
8221
|
if (count > 0) {
|
|
8602
|
-
console.log(
|
|
8222
|
+
console.log(chalk16.dim(` Handoff entries: ${count}`));
|
|
8603
8223
|
}
|
|
8604
8224
|
}
|
|
8605
8225
|
const completedPath = join19(cwd, COMPLETED_TASKS_PATH);
|
|
8606
8226
|
if (existsSync19(completedPath)) {
|
|
8607
8227
|
const count = lineCount(readFileSync7(completedPath, "utf-8"));
|
|
8608
8228
|
if (count > 0) {
|
|
8609
|
-
console.log(
|
|
8229
|
+
console.log(chalk16.dim(` Completed tasks archived: ${count}`));
|
|
8610
8230
|
}
|
|
8611
8231
|
}
|
|
8612
8232
|
console.log("");
|
|
@@ -8617,7 +8237,7 @@ function createGovernanceCommand() {
|
|
|
8617
8237
|
const store = new GovernanceStore(cwd);
|
|
8618
8238
|
const archInfo = resolveArchitecturePath2(cwd);
|
|
8619
8239
|
if (!archInfo.path) {
|
|
8620
|
-
console.log(
|
|
8240
|
+
console.log(chalk16.yellow("No architecture file found."));
|
|
8621
8241
|
return;
|
|
8622
8242
|
}
|
|
8623
8243
|
if (options.raw) {
|
|
@@ -8628,11 +8248,11 @@ function createGovernanceCommand() {
|
|
|
8628
8248
|
if (archInfo.source === "agd") {
|
|
8629
8249
|
const result = await store.readArchitecture();
|
|
8630
8250
|
if (!result.ok) {
|
|
8631
|
-
console.log(
|
|
8251
|
+
console.log(chalk16.red(`Failed to read architecture: ${result.error}`));
|
|
8632
8252
|
return;
|
|
8633
8253
|
}
|
|
8634
8254
|
if (!result.value) {
|
|
8635
|
-
console.log(
|
|
8255
|
+
console.log(chalk16.yellow("Architecture file is empty."));
|
|
8636
8256
|
return;
|
|
8637
8257
|
}
|
|
8638
8258
|
console.log(result.value);
|
|
@@ -8642,7 +8262,7 @@ function createGovernanceCommand() {
|
|
|
8642
8262
|
const legacyParsed = matter4(legacyRaw);
|
|
8643
8263
|
const legacyContent = legacyParsed.content.trim();
|
|
8644
8264
|
if (!legacyContent) {
|
|
8645
|
-
console.log(
|
|
8265
|
+
console.log(chalk16.yellow("Architecture file is empty."));
|
|
8646
8266
|
return;
|
|
8647
8267
|
}
|
|
8648
8268
|
console.log(legacyContent);
|
|
@@ -8651,32 +8271,32 @@ function createGovernanceCommand() {
|
|
|
8651
8271
|
const cwd = process.cwd();
|
|
8652
8272
|
const filePath = options.file;
|
|
8653
8273
|
if (!existsSync19(filePath)) {
|
|
8654
|
-
console.log(
|
|
8274
|
+
console.log(chalk16.red(`File not found: ${filePath}`));
|
|
8655
8275
|
process.exit(1);
|
|
8656
8276
|
}
|
|
8657
8277
|
const content = await readFile12(filePath, "utf-8");
|
|
8658
8278
|
const store = new GovernanceStore(cwd);
|
|
8659
8279
|
const result = await store.updateArchitecture(content, options.reason, options.by);
|
|
8660
8280
|
if (!result.ok) {
|
|
8661
|
-
console.log(
|
|
8281
|
+
console.log(chalk16.red(`Failed to update architecture: ${result.error}`));
|
|
8662
8282
|
process.exit(1);
|
|
8663
8283
|
}
|
|
8664
|
-
console.log(
|
|
8284
|
+
console.log(chalk16.green("\u2713 Architecture updated"));
|
|
8665
8285
|
});
|
|
8666
8286
|
const tasks = governance.command("task").description("Update tasks in governance store");
|
|
8667
8287
|
tasks.command("update <taskId>").description("Update task status and notes").requiredOption("-s, --status <status>", "Status: pending, in_progress, verification, done").option("-n, --notes <text>", "Optional notes").action(async (taskId, options) => {
|
|
8668
8288
|
const status2 = options.status;
|
|
8669
8289
|
if (!isTaskStatus(status2)) {
|
|
8670
|
-
console.log(
|
|
8290
|
+
console.log(chalk16.red(`Invalid status: ${options.status}`));
|
|
8671
8291
|
process.exit(1);
|
|
8672
8292
|
}
|
|
8673
8293
|
const store = new GovernanceStore(process.cwd());
|
|
8674
8294
|
const result = await store.updateTask(taskId, status2, options.notes);
|
|
8675
8295
|
if (!result.ok) {
|
|
8676
|
-
console.log(
|
|
8296
|
+
console.log(chalk16.red(`Failed to update task: ${result.error}`));
|
|
8677
8297
|
process.exit(1);
|
|
8678
8298
|
}
|
|
8679
|
-
console.log(
|
|
8299
|
+
console.log(chalk16.green(`\u2713 Task ${taskId} updated to ${status2}`));
|
|
8680
8300
|
});
|
|
8681
8301
|
governance.command("handoff").description("Log a handoff entry and update current context").requiredOption("-r, --reason <text>", "Reason for handoff").requiredOption("-s, --summary <text>", "Summary (single paragraph)").requiredOption("-n, --next <actions...>", "Next actions (space-separated)").option("-f, --from <agent>", "Agent or source name").option("-t, --timestamp <iso>", "Timestamp override (ISO 8601)").action(async (options) => {
|
|
8682
8302
|
const store = new GovernanceStore(process.cwd());
|
|
@@ -8689,10 +8309,10 @@ function createGovernanceCommand() {
|
|
|
8689
8309
|
};
|
|
8690
8310
|
const result = await store.logHandoff(entry);
|
|
8691
8311
|
if (!result.ok) {
|
|
8692
|
-
console.log(
|
|
8312
|
+
console.log(chalk16.red(`Failed to log handoff: ${result.error}`));
|
|
8693
8313
|
process.exit(1);
|
|
8694
8314
|
}
|
|
8695
|
-
console.log(
|
|
8315
|
+
console.log(chalk16.green("\u2713 Handoff logged"));
|
|
8696
8316
|
});
|
|
8697
8317
|
governance.command("migrate").description("Migrate legacy governance files into AGD structure").option("--remove-legacy", "Archive legacy files after migration").option("--dry-run", "Show what would change without writing files").option("-b, --by <name>", "Updated by label for architecture migration").action(async (options) => {
|
|
8698
8318
|
const result = await migrateLegacyGovernance({
|
|
@@ -8701,23 +8321,23 @@ function createGovernanceCommand() {
|
|
|
8701
8321
|
dryRun: options.dryRun,
|
|
8702
8322
|
updatedBy: options.by
|
|
8703
8323
|
});
|
|
8704
|
-
console.log(
|
|
8324
|
+
console.log(chalk16.bold("\nMigration Summary"));
|
|
8705
8325
|
console.log(
|
|
8706
|
-
result.migratedArchitecture ?
|
|
8326
|
+
result.migratedArchitecture ? chalk16.green(" \u2713 Architecture migrated") : chalk16.dim(" \u25CB Architecture migration skipped")
|
|
8707
8327
|
);
|
|
8708
8328
|
console.log(
|
|
8709
|
-
result.migratedTasks ?
|
|
8329
|
+
result.migratedTasks ? chalk16.green(" \u2713 Tasks migrated") : chalk16.dim(" \u25CB Tasks migration skipped")
|
|
8710
8330
|
);
|
|
8711
8331
|
if (result.archivedLegacyFiles.length > 0) {
|
|
8712
|
-
console.log(
|
|
8332
|
+
console.log(chalk16.dim(" Archived legacy files:"));
|
|
8713
8333
|
for (const file of result.archivedLegacyFiles) {
|
|
8714
|
-
console.log(
|
|
8334
|
+
console.log(chalk16.dim(` - ${file}`));
|
|
8715
8335
|
}
|
|
8716
8336
|
}
|
|
8717
8337
|
if (result.warnings.length > 0) {
|
|
8718
|
-
console.log(
|
|
8338
|
+
console.log(chalk16.yellow("\nWarnings:"));
|
|
8719
8339
|
for (const warning of result.warnings) {
|
|
8720
|
-
console.log(
|
|
8340
|
+
console.log(chalk16.yellow(` - ${warning}`));
|
|
8721
8341
|
}
|
|
8722
8342
|
}
|
|
8723
8343
|
console.log("");
|
|
@@ -8728,7 +8348,7 @@ function createGovernanceCommand() {
|
|
|
8728
8348
|
view.init(cwd);
|
|
8729
8349
|
await view.loadFromDisk(cwd);
|
|
8730
8350
|
view.close();
|
|
8731
|
-
console.log(
|
|
8351
|
+
console.log(chalk16.green("\u2713 Governance SQLite DB initialized"));
|
|
8732
8352
|
});
|
|
8733
8353
|
return governance;
|
|
8734
8354
|
}
|
|
@@ -8740,7 +8360,7 @@ program.name("archon").description("Local-first AI-powered development governanc
|
|
|
8740
8360
|
const cwd = process.cwd();
|
|
8741
8361
|
const wasInitialized = isInitialized(cwd);
|
|
8742
8362
|
if (!wasInitialized) {
|
|
8743
|
-
console.log(
|
|
8363
|
+
console.log(chalk17.blue("\nArchonDev is not initialized in this folder.\n"));
|
|
8744
8364
|
await init({ analyze: true, git: true });
|
|
8745
8365
|
}
|
|
8746
8366
|
await start({ skipGovernanceBanner: !wasInitialized });
|
|
@@ -8748,7 +8368,7 @@ program.name("archon").description("Local-first AI-powered development governanc
|
|
|
8748
8368
|
program.command("login").description("Authenticate with ArchonDev").option("-p, --provider <provider>", "OAuth provider (github or google)", "github").action(async (options) => {
|
|
8749
8369
|
const provider = options.provider;
|
|
8750
8370
|
if (provider !== "github" && provider !== "google") {
|
|
8751
|
-
console.error(
|
|
8371
|
+
console.error(chalk17.red('Invalid provider. Use "github" or "google"'));
|
|
8752
8372
|
process.exit(1);
|
|
8753
8373
|
}
|
|
8754
8374
|
await login(provider);
|
|
@@ -8946,7 +8566,7 @@ cleanupCmd.command("check").description("Analyze workspace for bloat and mainten
|
|
|
8946
8566
|
cleanupCmd.command("run").description("Execute cleanup (archive old entries, remove stale files)").action(cleanupRun);
|
|
8947
8567
|
cleanupCmd.command("auto").description("Enable/disable automatic cleanup checks").argument("[action]", "enable, disable, or status", "status").action(async (action) => {
|
|
8948
8568
|
if (action !== "enable" && action !== "disable" && action !== "status") {
|
|
8949
|
-
console.error(
|
|
8569
|
+
console.error(chalk17.red("Invalid action. Use: enable, disable, or status"));
|
|
8950
8570
|
process.exit(1);
|
|
8951
8571
|
}
|
|
8952
8572
|
await cleanupAuto(action);
|