archondev 1.5.0 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- listModels,
4
- resetPreferences,
5
- setPreference,
6
- showPreferences
7
- } from "./chunk-K2VBICW3.js";
3
+ addKey,
4
+ listKeys,
5
+ removeKey,
6
+ setPrimaryKey
7
+ } from "./chunk-IMZN36GC.js";
8
8
  import {
9
9
  reviewAnalyze,
10
10
  reviewExport,
@@ -18,6 +18,12 @@ import {
18
18
  reviewUpdate
19
19
  } from "./chunk-UDBFDXJI.js";
20
20
  import "./chunk-VKM3HAHW.js";
21
+ import {
22
+ listModels,
23
+ resetPreferences,
24
+ setPreference,
25
+ showPreferences
26
+ } from "./chunk-K2VBICW3.js";
21
27
  import {
22
28
  API_URL,
23
29
  SUPABASE_ANON_KEY,
@@ -26,33 +32,31 @@ import {
26
32
  logout,
27
33
  status
28
34
  } from "./chunk-CAYCSBNX.js";
35
+ import {
36
+ init,
37
+ isInitialized
38
+ } from "./chunk-TJXGZB6T.js";
29
39
  import {
30
40
  DependencyParser,
31
41
  EnvironmentConfigLoader,
32
42
  EnvironmentValidator,
33
43
  execute
34
- } from "./chunk-74EEFKVP.js";
44
+ } from "./chunk-S7UXMYWS.js";
35
45
  import {
36
46
  list
37
- } from "./chunk-PK3OQVBG.js";
47
+ } from "./chunk-NCJN4X5A.js";
38
48
  import {
39
49
  listLocalAtoms,
40
50
  loadAtom,
41
51
  plan
42
- } from "./chunk-EDP55FCI.js";
52
+ } from "./chunk-3AAQEUY6.js";
53
+ import "./chunk-SMR7JQK6.js";
43
54
  import "./chunk-2CFO5GVH.js";
44
55
  import {
45
56
  bugReport
46
57
  } from "./chunk-JBKFAD4M.js";
47
58
  import "./chunk-MOZHC2GX.js";
48
59
  import "./chunk-A7QU6JC6.js";
49
- import {
50
- addKey,
51
- listKeys,
52
- removeKey,
53
- setPrimaryKey
54
- } from "./chunk-IMZN36GC.js";
55
- import "./chunk-SMR7JQK6.js";
56
60
  import {
57
61
  loadConfig
58
62
  } from "./chunk-WCCBJSNI.js";
@@ -60,365 +64,27 @@ import "./chunk-QGM4M3NI.js";
60
64
 
61
65
  // src/cli/index.ts
62
66
  import { Command as Command2 } from "commander";
63
- import chalk7 from "chalk";
67
+ import chalk6 from "chalk";
64
68
  import "dotenv/config";
65
69
 
66
- // src/cli/init.ts
67
- import { readdir, readFile, writeFile, mkdir } from "fs/promises";
68
- import { existsSync } from "fs";
69
- import { join, extname } from "path";
70
- import { execSync } from "child_process";
71
- import chalk from "chalk";
72
- import ora from "ora";
73
- import readline from "readline";
74
- function isInitialized(cwd) {
75
- const archMdPath = join(cwd, "ARCHITECTURE.md");
76
- const archonDir = join(cwd, ".archon");
77
- return existsSync(archMdPath) || existsSync(archonDir);
78
- }
79
- var LANGUAGE_EXTENSIONS = {
80
- ".ts": "TypeScript",
81
- ".tsx": "TypeScript",
82
- ".js": "JavaScript",
83
- ".jsx": "JavaScript",
84
- ".py": "Python",
85
- ".go": "Go",
86
- ".rs": "Rust",
87
- ".java": "Java",
88
- ".rb": "Ruby",
89
- ".php": "PHP",
90
- ".cs": "C#",
91
- ".cpp": "C++",
92
- ".c": "C",
93
- ".swift": "Swift",
94
- ".kt": "Kotlin",
95
- ".vue": "Vue",
96
- ".svelte": "Svelte"
97
- };
98
- var IGNORE_DIRS = /* @__PURE__ */ new Set([
99
- "node_modules",
100
- ".git",
101
- "dist",
102
- "build",
103
- ".next",
104
- "coverage",
105
- "__pycache__",
106
- ".venv",
107
- "venv",
108
- "target",
109
- "vendor",
110
- ".archon"
111
- ]);
112
- async function init(options = {}) {
113
- const cwd = process.cwd();
114
- const archMdPath = join(cwd, "ARCHITECTURE.md");
115
- const archonDir = join(cwd, ".archon");
116
- console.log(chalk.blue("\n\u{1F3DB}\uFE0F ArchonDev Initialization\n"));
117
- if (existsSync(archMdPath)) {
118
- const overwrite = await promptYesNo("ARCHITECTURE.md already exists. Overwrite?", false);
119
- if (!overwrite) {
120
- console.log(chalk.yellow("Initialization cancelled."));
121
- return;
122
- }
123
- }
124
- const spinner = ora("Detecting project capabilities...").start();
125
- const capabilities = await detectCapabilities(cwd);
126
- spinner.succeed("Project capabilities detected");
127
- spinner.start("Scanning codebase...");
128
- const stats = await scanRepository(cwd);
129
- spinner.succeed(`Scanned ${stats.totalFiles} files (${formatLines(stats.totalLines)} lines)`);
130
- if (options.git !== false && !capabilities.hasGit) {
131
- spinner.start("Initializing git repository...");
132
- try {
133
- execSync("git init", { cwd, stdio: "pipe" });
134
- spinner.succeed("Git repository initialized");
135
- } catch {
136
- spinner.warn("Could not initialize git");
137
- }
138
- }
139
- if (!existsSync(archonDir)) {
140
- await mkdir(archonDir, { recursive: true });
141
- }
142
- spinner.start("Generating ARCHITECTURE.md...");
143
- const archContent = generateArchitectureMd(capabilities, stats, options.analyze);
144
- await writeFile(archMdPath, archContent);
145
- spinner.succeed("ARCHITECTURE.md created");
146
- printSummary(capabilities, stats, options.analyze);
147
- }
148
- function promptYesNo(question, defaultValue) {
149
- return new Promise((resolve) => {
150
- const rl = readline.createInterface({
151
- input: process.stdin,
152
- output: process.stdout
153
- });
154
- const hint = defaultValue ? "(Y/n)" : "(y/N)";
155
- rl.question(`${question} ${hint} `, (answer) => {
156
- rl.close();
157
- if (answer.trim() === "") {
158
- resolve(defaultValue);
159
- } else {
160
- resolve(answer.toLowerCase().startsWith("y"));
161
- }
162
- });
163
- });
164
- }
165
- async function detectCapabilities(cwd) {
166
- const hasFile = (name) => existsSync(join(cwd, name));
167
- const hasJsonDep = async (name) => {
168
- try {
169
- const pkg = JSON.parse(await readFile(join(cwd, "package.json"), "utf-8"));
170
- return !!(pkg.dependencies?.[name] || pkg.devDependencies?.[name]);
171
- } catch {
172
- return false;
173
- }
174
- };
175
- let packageManager = null;
176
- if (hasFile("pnpm-lock.yaml")) packageManager = "pnpm";
177
- else if (hasFile("yarn.lock")) packageManager = "yarn";
178
- else if (hasFile("bun.lockb")) packageManager = "bun";
179
- else if (hasFile("package-lock.json")) packageManager = "npm";
180
- const hasTypeScript = hasFile("tsconfig.json") || await hasJsonDep("typescript");
181
- const hasESLint = hasFile(".eslintrc") || hasFile(".eslintrc.js") || hasFile("eslint.config.js") || await hasJsonDep("eslint");
182
- const hasJest = hasFile("jest.config.js") || hasFile("jest.config.ts") || await hasJsonDep("jest") || await hasJsonDep("vitest");
183
- const hasPrettier = hasFile(".prettierrc") || hasFile(".prettierrc.js") || await hasJsonDep("prettier");
184
- const hasGit = hasFile(".git");
185
- return {
186
- hasTypeScript,
187
- hasESLint,
188
- hasJest,
189
- hasPrettier,
190
- hasGit,
191
- packageManager,
192
- primaryLanguage: hasTypeScript ? "TypeScript" : "JavaScript"
193
- };
194
- }
195
- async function scanRepository(cwd) {
196
- const stats = {
197
- totalFiles: 0,
198
- totalLines: 0,
199
- languageBreakdown: {},
200
- directories: []
201
- };
202
- async function scanDir(dir, depth = 0) {
203
- if (depth > 10) return;
204
- try {
205
- const entries = await readdir(dir, { withFileTypes: true });
206
- for (const entry of entries) {
207
- if (IGNORE_DIRS.has(entry.name)) continue;
208
- if (entry.name.startsWith(".") && entry.name !== ".github") continue;
209
- const fullPath = join(dir, entry.name);
210
- if (entry.isDirectory()) {
211
- if (depth < 2) {
212
- const relativePath = fullPath.replace(cwd, "").replace(/^\//, "");
213
- if (relativePath) {
214
- stats.directories.push(relativePath);
215
- }
216
- }
217
- await scanDir(fullPath, depth + 1);
218
- } else if (entry.isFile()) {
219
- const ext = extname(entry.name).toLowerCase();
220
- const language = LANGUAGE_EXTENSIONS[ext];
221
- if (language) {
222
- stats.totalFiles++;
223
- try {
224
- const content = await readFile(fullPath, "utf-8");
225
- const lines = content.split("\n").length;
226
- stats.totalLines += lines;
227
- if (!stats.languageBreakdown[language]) {
228
- stats.languageBreakdown[language] = { files: 0, lines: 0 };
229
- }
230
- stats.languageBreakdown[language].files++;
231
- stats.languageBreakdown[language].lines += lines;
232
- } catch {
233
- }
234
- }
235
- }
236
- }
237
- } catch {
238
- }
239
- }
240
- await scanDir(cwd);
241
- return stats;
242
- }
243
- function generateArchitectureMd(capabilities, stats, analyze) {
244
- const now = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
245
- const suggestedComponents = stats.directories.filter((d) => !d.includes("/")).slice(0, 10).map((dir) => ({
246
- id: dir.replace(/[^a-zA-Z0-9]/g, "-"),
247
- name: dir.charAt(0).toUpperCase() + dir.slice(1),
248
- path: `${dir}/**`
249
- }));
250
- const qualityGates = [];
251
- if (capabilities.hasTypeScript) qualityGates.push("SYNTAX");
252
- if (capabilities.hasESLint) qualityGates.push("LINT");
253
- if (capabilities.hasJest) qualityGates.push("UNIT");
254
- return `---
255
- version: "1.0"
256
- updatedAt: "${now}"
257
- profile: "balanced"
258
- strictMode: true
259
-
260
- # System Goals
261
- systemGoals:
262
- - id: "GOAL-001"
263
- title: "Maintain code quality"
264
- description: "All changes must pass quality gates before merging"
265
- priority: "HIGH"
266
-
267
- - id: "GOAL-002"
268
- title: "Preserve architectural boundaries"
269
- description: "Components should not violate defined boundaries"
270
- priority: "HIGH"
271
-
272
- # Components & Boundaries
273
- # Detected ${suggestedComponents.length} top-level directories
274
- components:
275
- ${suggestedComponents.map((c) => ` - id: "${c.id}"
276
- name: "${c.name}"
277
- paths:
278
- - "${c.path}"
279
- boundary: "INTERNAL"
280
- stability: "EVOLVING"`).join("\n\n")}
281
-
282
- # Invariants (Rules to enforce)
283
- invariants:
284
- - id: "INV-001"
285
- severity: "WARN"
286
- rule: "Avoid console.log in production code"
287
- match: "console\\\\.log"
288
- scope: "src"
289
- reason: "Use proper logging library instead"
290
-
291
- # Protected Paths
292
- protectedPaths:
293
- - pattern: "package.json"
294
- level: "SOFT"
295
- reason: "Dependency changes should be reviewed"
296
-
297
- ${capabilities.hasTypeScript ? ` - pattern: "tsconfig.json"
298
- level: "SOFT"
299
- reason: "TypeScript config affects entire project"` : ""}
300
-
301
- # Environment Configuration
302
- environments:
303
- development:
304
- autoApprove: true
305
- qualityGates:
306
- - ARCHITECTURE
307
- ${qualityGates.map((g) => ` - ${g}`).join("\n")}
308
-
309
- production:
310
- autoApprove: false
311
- requiresManualPromotion: true
312
- qualityGates:
313
- - ARCHITECTURE
314
- ${qualityGates.map((g) => ` - ${g}`).join("\n")}
315
- - ACCEPTANCE
316
- ---
317
-
318
- # Project Architecture
319
-
320
- ## Overview
321
-
322
- This architecture document was auto-generated by ArchonDev on ${now}.
323
-
324
- ${analyze ? `## Codebase Analysis
325
-
326
- - **Total Files:** ${stats.totalFiles}
327
- - **Total Lines:** ${formatLines(stats.totalLines)}
328
- - **Primary Language:** ${capabilities.primaryLanguage}
329
-
330
- ### Language Breakdown
331
-
332
- ${Object.entries(stats.languageBreakdown).sort((a, b) => b[1].lines - a[1].lines).map(([lang, data]) => `- ${lang}: ${data.files} files, ${formatLines(data.lines)} lines`).join("\n")}
333
-
334
- ### Detected Capabilities
335
-
336
- - TypeScript: ${capabilities.hasTypeScript ? "\u2705" : "\u274C"}
337
- - ESLint: ${capabilities.hasESLint ? "\u2705" : "\u274C"}
338
- - Testing: ${capabilities.hasJest ? "\u2705" : "\u274C"}
339
- - Package Manager: ${capabilities.packageManager ?? "Not detected"}
340
- ` : ""}
341
- ## Components
342
-
343
- ${suggestedComponents.map((c) => `### ${c.name}
344
-
345
- Path: \`${c.path}\`
346
-
347
- TODO: Add description for this component.
348
- `).join("\n")}
349
-
350
- ## Getting Started
351
-
352
- 1. Review and customize the components above
353
- 2. Add invariants for your specific rules
354
- 3. Define protected paths for sensitive files
355
- 4. Run \`archon plan <description>\` to create your first atom
356
-
357
- ## Architecture Decision Records
358
-
359
- Document important architectural decisions here.
360
- `;
361
- }
362
- function formatLines(n) {
363
- if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
364
- if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
365
- return n.toString();
366
- }
367
- function printSummary(capabilities, stats, analyze) {
368
- console.log();
369
- console.log(chalk.green("\u2713 ArchonDev initialized successfully!"));
370
- console.log();
371
- console.log(chalk.bold("Detected Capabilities:"));
372
- console.log(` ${capabilities.hasTypeScript ? chalk.green("\u2713") : chalk.gray("\u25CB")} TypeScript`);
373
- console.log(` ${capabilities.hasESLint ? chalk.green("\u2713") : chalk.gray("\u25CB")} ESLint`);
374
- console.log(` ${capabilities.hasJest ? chalk.green("\u2713") : chalk.gray("\u25CB")} Testing (Jest/Vitest)`);
375
- console.log(` ${capabilities.packageManager ? chalk.green("\u2713") : chalk.gray("\u25CB")} Package Manager: ${capabilities.packageManager ?? "none"}`);
376
- console.log();
377
- console.log(chalk.bold("Codebase Summary:"));
378
- console.log(` Files: ${stats.totalFiles}`);
379
- console.log(` Lines: ${formatLines(stats.totalLines)}`);
380
- console.log(` Directories: ${stats.directories.length}`);
381
- console.log();
382
- if (Object.keys(stats.languageBreakdown).length > 0) {
383
- console.log(chalk.bold("Languages:"));
384
- Object.entries(stats.languageBreakdown).sort((a, b) => b[1].lines - a[1].lines).slice(0, 5).forEach(([lang, data]) => {
385
- const pct = Math.round(data.lines / stats.totalLines * 100);
386
- console.log(` ${lang}: ${pct}%`);
387
- });
388
- console.log();
389
- }
390
- if (analyze && stats.directories.length > 0) {
391
- console.log(chalk.bold("Suggested Boundaries:"));
392
- stats.directories.filter((d) => !d.includes("/")).slice(0, 5).forEach((dir) => {
393
- console.log(` \u2022 ${dir}/`);
394
- });
395
- console.log();
396
- }
397
- console.log(chalk.bold("Next Steps:"));
398
- console.log(` 1. ${chalk.cyan("Review")} ARCHITECTURE.md and customize components`);
399
- console.log(` 2. ${chalk.cyan("Run")} ${chalk.dim('archon plan "your first task"')} to create an atom`);
400
- console.log(` 3. ${chalk.cyan("Execute")} ${chalk.dim("archon execute ATOM-001")} to implement it`);
401
- console.log();
402
- }
403
-
404
70
  // src/cli/promote.ts
405
- import chalk2 from "chalk";
406
- import { existsSync as existsSync2 } from "fs";
407
- import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
408
- import { join as join2 } from "path";
71
+ import chalk from "chalk";
72
+ import { existsSync } from "fs";
73
+ import { readFile, writeFile } from "fs/promises";
74
+ import { join } from "path";
409
75
  var ATOMS_DIR = ".archon/atoms";
410
76
  async function promote(atomId, options) {
411
77
  const cwd = process.cwd();
412
78
  const atom = await loadAtom(atomId);
413
79
  if (!atom) {
414
- console.error(chalk2.red(`Atom ${atomId} not found.`));
415
- console.log(chalk2.dim(`Use "archon list" to see available atoms.`));
80
+ console.error(chalk.red(`Atom ${atomId} not found.`));
81
+ console.log(chalk.dim(`Use "archon list" to see available atoms.`));
416
82
  process.exit(1);
417
83
  }
418
84
  const envLoader = new EnvironmentConfigLoader(cwd);
419
85
  if (!envLoader.isValidEnvironment(options.to)) {
420
- console.error(chalk2.red(`Invalid target environment: ${options.to}`));
421
- console.log(chalk2.dim("Valid environments: development, staging, production"));
86
+ console.error(chalk.red(`Invalid target environment: ${options.to}`));
87
+ console.log(chalk.dim("Valid environments: development, staging, production"));
422
88
  process.exit(1);
423
89
  }
424
90
  const targetEnv = options.to;
@@ -428,185 +94,185 @@ async function promote(atomId, options) {
428
94
  const currentEnv = envState?.lastExecutedEnv ?? "development";
429
95
  const result = validator.validatePromotion(atom, targetEnv, currentEnv);
430
96
  if (!result.success) {
431
- console.error(chalk2.red("Promotion failed:"));
432
- console.error(chalk2.red(result.message));
97
+ console.error(chalk.red("Promotion failed:"));
98
+ console.error(chalk.red(result.message));
433
99
  process.exit(1);
434
100
  }
435
101
  await saveAtomEnvironmentState(atomId, cwd, {
436
102
  lastExecutedEnv: currentEnv,
437
103
  promotedTo: [...envState?.promotedTo ?? [], targetEnv]
438
104
  });
439
- console.log(chalk2.green(`\u2713 ${result.message}`));
440
- console.log(chalk2.dim(`
105
+ console.log(chalk.green(`\u2713 ${result.message}`));
106
+ console.log(chalk.dim(`
441
107
  To execute in ${targetEnv}:`));
442
- console.log(chalk2.cyan(` archon execute ${atomId} --env=${targetEnv}`));
108
+ console.log(chalk.cyan(` archon execute ${atomId} --env=${targetEnv}`));
443
109
  }
444
110
  async function loadAtomEnvironmentState(atomId, cwd) {
445
- const stateFile = join2(cwd, ATOMS_DIR, `${atomId}.env.json`);
446
- if (!existsSync2(stateFile)) {
111
+ const stateFile = join(cwd, ATOMS_DIR, `${atomId}.env.json`);
112
+ if (!existsSync(stateFile)) {
447
113
  return null;
448
114
  }
449
- const content = await readFile2(stateFile, "utf-8");
115
+ const content = await readFile(stateFile, "utf-8");
450
116
  return JSON.parse(content);
451
117
  }
452
118
  async function saveAtomEnvironmentState(atomId, cwd, state) {
453
- const stateFile = join2(cwd, ATOMS_DIR, `${atomId}.env.json`);
454
- await writeFile2(stateFile, JSON.stringify(state, null, 2));
119
+ const stateFile = join(cwd, ATOMS_DIR, `${atomId}.env.json`);
120
+ await writeFile(stateFile, JSON.stringify(state, null, 2));
455
121
  }
456
122
 
457
123
  // src/cli/show.ts
458
- import chalk3 from "chalk";
124
+ import chalk2 from "chalk";
459
125
  var STATUS_COLORS = {
460
- DRAFT: chalk3.gray,
461
- READY: chalk3.blue,
462
- IN_PROGRESS: chalk3.yellow,
463
- TESTING: chalk3.cyan,
464
- DONE: chalk3.green,
465
- FAILED: chalk3.red,
466
- BLOCKED: chalk3.magenta
126
+ DRAFT: chalk2.gray,
127
+ READY: chalk2.blue,
128
+ IN_PROGRESS: chalk2.yellow,
129
+ TESTING: chalk2.cyan,
130
+ DONE: chalk2.green,
131
+ FAILED: chalk2.red,
132
+ BLOCKED: chalk2.magenta
467
133
  };
468
134
  async function show(atomId) {
469
135
  const atom = await loadAtom(atomId);
470
136
  if (!atom) {
471
- console.error(chalk3.red(`Atom ${atomId} not found.`));
472
- console.log(chalk3.dim('Use "archon list" to see available atoms.'));
137
+ console.error(chalk2.red(`Atom ${atomId} not found.`));
138
+ console.log(chalk2.dim('Use "archon list" to see available atoms.'));
473
139
  process.exit(1);
474
140
  }
475
- const colorFn = STATUS_COLORS[atom.status] ?? chalk3.white;
141
+ const colorFn = STATUS_COLORS[atom.status] ?? chalk2.white;
476
142
  console.log("");
477
- console.log(chalk3.bold(`Atom: ${atom.externalId}`));
478
- console.log(chalk3.dim("\u2550".repeat(60)));
143
+ console.log(chalk2.bold(`Atom: ${atom.externalId}`));
144
+ console.log(chalk2.dim("\u2550".repeat(60)));
479
145
  console.log("");
480
- console.log(chalk3.bold("Title:"), atom.title);
146
+ console.log(chalk2.bold("Title:"), atom.title);
481
147
  if (atom.description) {
482
- console.log(chalk3.bold("Description:"), atom.description);
148
+ console.log(chalk2.bold("Description:"), atom.description);
483
149
  }
484
- console.log(chalk3.bold("Status:"), colorFn(atom.status));
485
- console.log(chalk3.bold("Priority:"), atom.priority);
486
- console.log(chalk3.bold("Created:"), formatDateTime(atom.createdAt));
487
- console.log(chalk3.bold("Updated:"), formatDateTime(atom.updatedAt));
150
+ console.log(chalk2.bold("Status:"), colorFn(atom.status));
151
+ console.log(chalk2.bold("Priority:"), atom.priority);
152
+ console.log(chalk2.bold("Created:"), formatDateTime(atom.createdAt));
153
+ console.log(chalk2.bold("Updated:"), formatDateTime(atom.updatedAt));
488
154
  if (atom.goals && atom.goals.length > 0) {
489
155
  console.log("");
490
- console.log(chalk3.bold("Goals:"));
156
+ console.log(chalk2.bold("Goals:"));
491
157
  for (const goal of atom.goals) {
492
158
  console.log(` \u2022 ${goal}`);
493
159
  }
494
160
  }
495
161
  if (atom.acceptanceCriteria && atom.acceptanceCriteria.length > 0) {
496
162
  console.log("");
497
- console.log(chalk3.bold("Acceptance Criteria:"));
163
+ console.log(chalk2.bold("Acceptance Criteria:"));
498
164
  for (let i = 0; i < atom.acceptanceCriteria.length; i++) {
499
165
  console.log(` ${i + 1}. ${atom.acceptanceCriteria[i]}`);
500
166
  }
501
167
  }
502
168
  if (atom.tags && atom.tags.length > 0) {
503
169
  console.log("");
504
- console.log(chalk3.bold("Tags:"), atom.tags.join(", "));
170
+ console.log(chalk2.bold("Tags:"), atom.tags.join(", "));
505
171
  }
506
172
  if (atom.plan) {
507
173
  console.log("");
508
- console.log(chalk3.bold("Implementation Plan:"));
509
- console.log(chalk3.dim("\u2500".repeat(40)));
510
- console.log(chalk3.bold("Steps:"));
174
+ console.log(chalk2.bold("Implementation Plan:"));
175
+ console.log(chalk2.dim("\u2500".repeat(40)));
176
+ console.log(chalk2.bold("Steps:"));
511
177
  for (let i = 0; i < atom.plan.steps.length; i++) {
512
178
  console.log(` ${i + 1}. ${atom.plan.steps[i]}`);
513
179
  }
514
180
  if (atom.plan.files_to_modify.length > 0) {
515
181
  console.log("");
516
- console.log(chalk3.bold("Files to modify:"));
182
+ console.log(chalk2.bold("Files to modify:"));
517
183
  for (const file of atom.plan.files_to_modify) {
518
184
  console.log(` \u2022 ${file}`);
519
185
  }
520
186
  }
521
187
  if (atom.plan.dependencies.length > 0) {
522
188
  console.log("");
523
- console.log(chalk3.bold("Dependencies:"));
189
+ console.log(chalk2.bold("Dependencies:"));
524
190
  for (const dep of atom.plan.dependencies) {
525
191
  console.log(` \u2022 ${dep}`);
526
192
  }
527
193
  }
528
194
  if (atom.plan.risks.length > 0) {
529
195
  console.log("");
530
- console.log(chalk3.bold("Risks:"));
196
+ console.log(chalk2.bold("Risks:"));
531
197
  for (const risk of atom.plan.risks) {
532
- console.log(chalk3.yellow(` \u26A0 ${risk}`));
198
+ console.log(chalk2.yellow(` \u26A0 ${risk}`));
533
199
  }
534
200
  }
535
201
  console.log("");
536
- console.log(chalk3.bold("Estimated Complexity:"), atom.plan.estimated_complexity);
202
+ console.log(chalk2.bold("Estimated Complexity:"), atom.plan.estimated_complexity);
537
203
  }
538
204
  if (atom.status === "FAILED" && atom.errorMessage) {
539
205
  console.log("");
540
- console.log(chalk3.bold("Error:"));
541
- console.log(chalk3.red(` ${atom.errorMessage}`));
206
+ console.log(chalk2.bold("Error:"));
207
+ console.log(chalk2.red(` ${atom.errorMessage}`));
542
208
  }
543
209
  if (atom.retryCount > 0) {
544
210
  console.log("");
545
- console.log(chalk3.bold("Retry Count:"), chalk3.yellow(String(atom.retryCount)));
211
+ console.log(chalk2.bold("Retry Count:"), chalk2.yellow(String(atom.retryCount)));
546
212
  }
547
213
  if (atom.ownershipPaths && atom.ownershipPaths.length > 0) {
548
214
  console.log("");
549
- console.log(chalk3.bold("Ownership Paths:"));
215
+ console.log(chalk2.bold("Ownership Paths:"));
550
216
  for (const path2 of atom.ownershipPaths) {
551
217
  console.log(` \u2022 ${path2}`);
552
218
  }
553
219
  }
554
220
  if (atom.diffContract) {
555
221
  console.log("");
556
- console.log(chalk3.bold("Diff Contract:"));
222
+ console.log(chalk2.bold("Diff Contract:"));
557
223
  if (atom.diffContract.allowed_paths.length > 0) {
558
- console.log(chalk3.dim(" Allowed paths:"));
224
+ console.log(chalk2.dim(" Allowed paths:"));
559
225
  for (const path2 of atom.diffContract.allowed_paths) {
560
226
  console.log(` \u2713 ${path2}`);
561
227
  }
562
228
  }
563
229
  if (atom.diffContract.forbidden_paths.length > 0) {
564
- console.log(chalk3.dim(" Forbidden paths:"));
230
+ console.log(chalk2.dim(" Forbidden paths:"));
565
231
  for (const path2 of atom.diffContract.forbidden_paths) {
566
- console.log(chalk3.red(` \u2717 ${path2}`));
232
+ console.log(chalk2.red(` \u2717 ${path2}`));
567
233
  }
568
234
  }
569
235
  }
570
236
  if (atom.context && Object.keys(atom.context).length > 0) {
571
237
  console.log("");
572
- console.log(chalk3.bold("Context:"));
238
+ console.log(chalk2.bold("Context:"));
573
239
  if (atom.context.relevantFiles && atom.context.relevantFiles.length > 0) {
574
- console.log(chalk3.dim(" Relevant files:"));
240
+ console.log(chalk2.dim(" Relevant files:"));
575
241
  for (const file of atom.context.relevantFiles) {
576
242
  console.log(` \u2022 ${file}`);
577
243
  }
578
244
  }
579
245
  if (atom.context.recentLearnings && atom.context.recentLearnings.length > 0) {
580
- console.log(chalk3.dim(" Recent learnings:"));
246
+ console.log(chalk2.dim(" Recent learnings:"));
581
247
  for (const learning of atom.context.recentLearnings) {
582
248
  console.log(` \u2022 ${learning}`);
583
249
  }
584
250
  }
585
251
  }
586
252
  console.log("");
587
- console.log(chalk3.dim("\u2500".repeat(60)));
588
- console.log(chalk3.bold("Next Steps:"));
253
+ console.log(chalk2.dim("\u2500".repeat(60)));
254
+ console.log(chalk2.bold("Next Steps:"));
589
255
  switch (atom.status) {
590
256
  case "DRAFT":
591
- console.log(chalk3.dim(` Run "archon plan ${atom.externalId} --continue" to finalize the plan`));
257
+ console.log(chalk2.dim(` Run "archon plan ${atom.externalId} --continue" to finalize the plan`));
592
258
  break;
593
259
  case "READY":
594
- console.log(chalk3.dim(` Run "archon execute ${atom.externalId}" to implement`));
260
+ console.log(chalk2.dim(` Run "archon execute ${atom.externalId}" to implement`));
595
261
  break;
596
262
  case "IN_PROGRESS":
597
- console.log(chalk3.dim(" Execution is in progress..."));
263
+ console.log(chalk2.dim(" Execution is in progress..."));
598
264
  break;
599
265
  case "TESTING":
600
- console.log(chalk3.dim(" Waiting for quality gates to complete..."));
266
+ console.log(chalk2.dim(" Waiting for quality gates to complete..."));
601
267
  break;
602
268
  case "DONE":
603
- console.log(chalk3.green(" \u2713 Atom completed successfully!"));
269
+ console.log(chalk2.green(" \u2713 Atom completed successfully!"));
604
270
  break;
605
271
  case "FAILED":
606
- console.log(chalk3.dim(` Review the error and run "archon execute ${atom.externalId}" to retry`));
272
+ console.log(chalk2.dim(` Review the error and run "archon execute ${atom.externalId}" to retry`));
607
273
  break;
608
274
  case "BLOCKED":
609
- console.log(chalk3.dim(" This atom is blocked. Manual intervention required."));
275
+ console.log(chalk2.dim(" This atom is blocked. Manual intervention required."));
610
276
  break;
611
277
  }
612
278
  console.log("");
@@ -617,47 +283,34 @@ function formatDateTime(date) {
617
283
  }
618
284
 
619
285
  // src/cli/start.ts
620
- import chalk4 from "chalk";
621
- import readline2 from "readline";
622
- import { existsSync as existsSync3, readdirSync } from "fs";
623
- import { join as join3 } from "path";
286
+ import chalk3 from "chalk";
287
+ import readline from "readline";
288
+ import { existsSync as existsSync2, readFileSync, readdirSync, appendFileSync } from "fs";
289
+ import { join as join2 } from "path";
624
290
  async function start() {
625
291
  const cwd = process.cwd();
626
- console.log(chalk4.blue("\n\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\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
627
- console.log(chalk4.bold.white(" ArchonDev - AI-Powered Development Governance"));
628
- console.log(chalk4.blue("\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\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
292
+ console.log(chalk3.blue("\n\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\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
293
+ console.log(chalk3.bold.white(" ArchonDev - AI-Powered Development Governance"));
294
+ console.log(chalk3.blue("\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\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n"));
629
295
  const projectState = detectProjectState(cwd);
630
- await showProjectStatus(cwd, projectState);
631
- const choices = [
632
- { key: "1", label: "Plan a new task", action: () => planTask() },
633
- { key: "2", label: "List atoms", action: () => listAtoms() },
634
- { key: "3", label: "Execute next atom", action: () => executeNext() },
635
- { key: "4", label: "Report a bug", action: () => reportBug() },
636
- { key: "5", label: "View status", action: () => viewStatus() },
637
- { key: "6", label: "Code Review", action: () => reviewCode() },
638
- { key: "7", label: "Settings & Preferences", action: () => settingsMenu() },
639
- { key: "q", label: "Quit", action: async () => process.exit(0) }
640
- ];
641
- console.log(chalk4.bold("What would you like to do?\n"));
642
- for (const choice2 of choices) {
643
- console.log(` ${chalk4.cyan(choice2.key)}) ${choice2.label}`);
644
- }
645
- console.log();
646
- const selected = await prompt("Enter choice");
647
- const choice = choices.find((c) => c.key === selected.toLowerCase());
648
- if (choice) {
649
- await choice.action();
650
- } else {
651
- console.log(chalk4.yellow("Invalid choice. Please try again."));
652
- await start();
296
+ switch (projectState.scenario) {
297
+ case "NEW_PROJECT":
298
+ await handleNewProject(cwd, projectState);
299
+ break;
300
+ case "ADAPT_EXISTING":
301
+ await handleAdaptExisting(cwd, projectState);
302
+ break;
303
+ case "CONTINUE_SESSION":
304
+ await handleContinueSession(cwd, projectState);
305
+ break;
653
306
  }
654
307
  }
655
308
  function detectProjectState(cwd) {
656
- const sourceDirs = ["src", "lib", "app", "packages", "components"];
657
- const sourceExtensions = [".ts", ".tsx", ".js", ".jsx", ".py", ".go", ".rs", ".java"];
309
+ const sourceDirs = ["src", "lib", "app", "packages", "components", "pages", "api"];
310
+ const sourceExtensions = [".ts", ".tsx", ".js", ".jsx", ".py", ".go", ".rs", ".java", ".rb", ".php"];
658
311
  let hasSourceFiles = false;
659
312
  for (const dir of sourceDirs) {
660
- if (existsSync3(join3(cwd, dir))) {
313
+ if (existsSync2(join2(cwd, dir))) {
661
314
  hasSourceFiles = true;
662
315
  break;
663
316
  }
@@ -671,29 +324,351 @@ function detectProjectState(cwd) {
671
324
  } catch {
672
325
  }
673
326
  }
327
+ const projectMarkers = ["package.json", "Cargo.toml", "pyproject.toml", "go.mod", "pom.xml", "build.gradle"];
328
+ if (!hasSourceFiles) {
329
+ hasSourceFiles = projectMarkers.some((marker) => existsSync2(join2(cwd, marker)));
330
+ }
331
+ const hasArchitecture = existsSync2(join2(cwd, "ARCHITECTURE.md"));
332
+ const hasProgress = existsSync2(join2(cwd, "progress.txt"));
333
+ const hasReviewDb = existsSync2(join2(cwd, "docs", "code-review", "review-tasks.db"));
334
+ let hasProgressEntries = false;
335
+ let lastProgressEntry;
336
+ if (hasProgress) {
337
+ try {
338
+ const progressContent = readFileSync(join2(cwd, "progress.txt"), "utf-8");
339
+ const entries = progressContent.match(/^## \d{4}-\d{2}-\d{2}/gm);
340
+ hasProgressEntries = entries !== null && entries.length > 0;
341
+ if (hasProgressEntries) {
342
+ const lastMatch = progressContent.match(/## \d{4}-\d{2}-\d{2}[^\n]*\n([^#]*)/g);
343
+ if (lastMatch && lastMatch.length > 0) {
344
+ const last = lastMatch[lastMatch.length - 1] ?? "";
345
+ lastProgressEntry = last.split("\n").slice(0, 3).join("\n").trim();
346
+ }
347
+ }
348
+ } catch {
349
+ }
350
+ }
351
+ let scenario;
352
+ if (hasProgressEntries) {
353
+ scenario = "CONTINUE_SESSION";
354
+ } else if (hasSourceFiles) {
355
+ scenario = "ADAPT_EXISTING";
356
+ } else {
357
+ scenario = "NEW_PROJECT";
358
+ }
674
359
  return {
360
+ scenario,
675
361
  hasSourceFiles,
676
- hasArchitecture: existsSync3(join3(cwd, "ARCHITECTURE.md")),
677
- hasReviewDb: existsSync3(join3(cwd, "docs", "code-review", "review-tasks.db"))
362
+ hasArchitecture,
363
+ hasProgress,
364
+ hasProgressEntries,
365
+ hasReviewDb,
366
+ lastProgressEntry
678
367
  };
679
368
  }
680
- async function showProjectStatus(cwd, state) {
681
- if (state.hasSourceFiles && !state.hasArchitecture) {
682
- console.log(chalk4.yellow("\u{1F4C1} Existing project detected") + chalk4.dim(" (source files found, no ARCHITECTURE.md)"));
683
- console.log(chalk4.dim(" Consider running ") + chalk4.cyan("Code Review") + chalk4.dim(" first, then set up governance."));
369
+ async function handleNewProject(cwd, state) {
370
+ console.log(chalk3.yellow("\u{1F389}") + chalk3.bold(" Starting a new project? Great!\n"));
371
+ console.log(chalk3.dim("I'll ask you a few quick questions to set things up right."));
372
+ console.log(chalk3.dim("Answer as much or as little as you want \u2014 you can always refine later.\n"));
373
+ console.log(chalk3.bold("What would you like to do?\n"));
374
+ console.log(` ${chalk3.cyan("1")}) ${chalk3.bold("Start interview")} \u2014 I'll ask questions to understand your project`);
375
+ console.log(` ${chalk3.cyan("2")}) ${chalk3.bold("Quick start")} \u2014 Just create basic governance files`);
376
+ console.log(` ${chalk3.cyan("3")}) ${chalk3.bold("Import from template")} \u2014 Use a predefined project template`);
377
+ console.log(` ${chalk3.cyan("q")}) ${chalk3.dim("Quit")}`);
378
+ console.log();
379
+ const choice = await prompt("Enter choice");
380
+ switch (choice.toLowerCase()) {
381
+ case "1":
382
+ await runNewProjectInterview(cwd);
383
+ break;
384
+ case "2":
385
+ await quickStart(cwd);
386
+ break;
387
+ case "3":
388
+ console.log(chalk3.yellow("\nTemplates coming soon! Using quick start for now.\n"));
389
+ await quickStart(cwd);
390
+ break;
391
+ case "q":
392
+ process.exit(0);
393
+ default:
394
+ console.log(chalk3.yellow("Invalid choice. Please try again."));
395
+ await handleNewProject(cwd, state);
396
+ }
397
+ }
398
+ async function runNewProjectInterview(cwd) {
399
+ console.log(chalk3.blue("\n\u2501\u2501\u2501 Project Interview \u2501\u2501\u2501\n"));
400
+ console.log(chalk3.bold("Phase 1: The Vision\n"));
401
+ const projectName = await prompt("What's the project name?");
402
+ const projectDescription = await prompt("In one sentence, what does this project do?");
403
+ const audience = await promptChoice("Who is it for?", [
404
+ { key: "1", label: "Just me (personal project)" },
405
+ { key: "2", label: "My team (internal tool)" },
406
+ { key: "3", label: "End users (product)" }
407
+ ]);
408
+ const experience = await promptChoice("Your experience level with this tech stack?", [
409
+ { key: "1", label: "\u{1F7E2} Expert \u2014 I know this well" },
410
+ { key: "2", label: "\u{1F7E1} Intermediate \u2014 I've done similar work" },
411
+ { key: "3", label: "\u{1F534} Learning \u2014 This is new to me" }
412
+ ]);
413
+ console.log(chalk3.bold("\nPhase 2: Tech Stack\n"));
414
+ const language = await promptChoice("Primary language/framework?", [
415
+ { key: "1", label: "TypeScript / JavaScript" },
416
+ { key: "2", label: "Python" },
417
+ { key: "3", label: "Go" },
418
+ { key: "4", label: "Rust" },
419
+ { key: "5", label: "Other" }
420
+ ]);
421
+ const projectType = await promptChoice("Project type?", [
422
+ { key: "1", label: "Frontend only (web UI)" },
423
+ { key: "2", label: "Backend only (API, CLI, service)" },
424
+ { key: "3", label: "Full-stack (both)" },
425
+ { key: "4", label: "Library/package" }
426
+ ]);
427
+ console.log(chalk3.bold("\nPhase 3: Preferences ") + chalk3.dim("(press Enter to skip)\n"));
428
+ const protectedFiles = await prompt("Any files AI should NEVER modify without asking? (comma-separated)");
429
+ const noNoPatterns = await prompt('Anything AI should NEVER do? (e.g., "no console.log")');
430
+ console.log(chalk3.blue("\n\u2501\u2501\u2501 Generating Project Files \u2501\u2501\u2501\n"));
431
+ const { init: init2 } = await import("./init-YLAHY4CV.js");
432
+ await init2({ analyze: false, git: true });
433
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
434
+ const progressEntry = `
435
+ ## ${today} - Project Initialized via Interview
436
+
437
+ ### Vision
438
+ - **Name:** ${projectName || "Unnamed Project"}
439
+ - **Description:** ${projectDescription || "No description provided"}
440
+ - **Audience:** ${["Personal", "Team", "End Users"][parseInt(audience) - 1] || "Not specified"}
441
+ - **Experience Level:** ${["Expert", "Intermediate", "Learning"][parseInt(experience) - 1] || "Not specified"}
442
+
443
+ ### Stack
444
+ - **Language:** ${["TypeScript/JavaScript", "Python", "Go", "Rust", "Other"][parseInt(language) - 1] || "Not specified"}
445
+ - **Type:** ${["Frontend", "Backend", "Full-stack", "Library"][parseInt(projectType) - 1] || "Not specified"}
446
+
447
+ ### Preferences
448
+ ${protectedFiles ? `- **Protected files:** ${protectedFiles}` : "- No protected files specified"}
449
+ ${noNoPatterns ? `- **Forbidden patterns:** ${noNoPatterns}` : "- No forbidden patterns specified"}
450
+
451
+ ### Files Created
452
+ - ARCHITECTURE.md
453
+ - .archon/config.yaml
454
+ - progress.txt
455
+ `;
456
+ const progressPath = join2(cwd, "progress.txt");
457
+ if (!existsSync2(progressPath)) {
458
+ const { writeFileSync } = await import("fs");
459
+ writeFileSync(progressPath, "# ArchonDev Progress Log\n\nThis file tracks learnings and decisions across sessions.\n");
460
+ }
461
+ appendFileSync(progressPath, progressEntry);
462
+ console.log(chalk3.green("\n\u2713 Project initialized!\n"));
463
+ console.log(chalk3.bold("Next steps:"));
464
+ console.log(` 1. ${chalk3.cyan("Review")} ARCHITECTURE.md and customize if needed`);
465
+ console.log(` 2. ${chalk3.cyan("Run")} ${chalk3.dim('archon plan "your first task"')} to create an atom`);
466
+ console.log();
467
+ const continueChoice = await promptYesNo("Would you like to plan your first task now?", true);
468
+ if (continueChoice) {
469
+ const description = await prompt("Describe what you want to build first");
470
+ if (description.trim()) {
471
+ const { plan: plan2 } = await import("./plan-WQUFH2WB.js");
472
+ await plan2(description, {});
473
+ }
474
+ }
475
+ }
476
+ async function quickStart(cwd) {
477
+ console.log(chalk3.blue("\n\u2501\u2501\u2501 Quick Start \u2501\u2501\u2501\n"));
478
+ const { init: init2 } = await import("./init-YLAHY4CV.js");
479
+ await init2({ analyze: false, git: true });
480
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
481
+ const progressPath = join2(cwd, "progress.txt");
482
+ if (!existsSync2(progressPath)) {
483
+ const { writeFileSync } = await import("fs");
484
+ writeFileSync(progressPath, `# ArchonDev Progress Log
485
+
486
+ This file tracks learnings and decisions across sessions.
487
+
488
+ ## ${today} - Project Initialized (Quick Start)
489
+
490
+ ### What was done
491
+ - Created ARCHITECTURE.md with default template
492
+ - Initialized .archon directory
493
+ - Created this progress.txt
494
+
495
+ ### Next Steps
496
+ 1. Customize ARCHITECTURE.md for your project
497
+ 2. Run \`archon plan "your first task"\` to create an atom
498
+ `);
499
+ }
500
+ console.log();
501
+ await showMainMenu();
502
+ }
503
+ async function handleAdaptExisting(cwd, state) {
504
+ console.log(chalk3.yellow("\u{1F4C1}") + chalk3.bold(" Existing project detected!\n"));
505
+ console.log(chalk3.dim("I can analyze your codebase and adapt the governance files to match your structure."));
506
+ console.log(chalk3.dim("This helps me understand your architecture without changing any code.\n"));
507
+ console.log(chalk3.bold("What would you like to do?\n"));
508
+ console.log(` ${chalk3.cyan("1")}) ${chalk3.bold("Analyze and adapt")} \u2014 I'll scan your project and update ARCHITECTURE.md`);
509
+ console.log(` ${chalk3.cyan("2")}) ${chalk3.bold("Code review first")} \u2014 Review code for issues before setting up governance`);
510
+ console.log(` ${chalk3.cyan("3")}) ${chalk3.bold("Manual setup")} \u2014 Keep template files, customize manually`);
511
+ console.log(` ${chalk3.cyan("4")}) ${chalk3.bold("Just start working")} \u2014 Skip setup, use defaults`);
512
+ console.log(` ${chalk3.cyan("q")}) ${chalk3.dim("Quit")}`);
513
+ console.log();
514
+ const choice = await prompt("Enter choice");
515
+ switch (choice.toLowerCase()) {
516
+ case "1":
517
+ await analyzeAndAdapt(cwd);
518
+ break;
519
+ case "2":
520
+ await codeReviewFirst(cwd);
521
+ break;
522
+ case "3":
523
+ await manualSetup(cwd);
524
+ break;
525
+ case "4":
526
+ await quickAdapt(cwd);
527
+ break;
528
+ case "q":
529
+ process.exit(0);
530
+ default:
531
+ console.log(chalk3.yellow("Invalid choice. Please try again."));
532
+ await handleAdaptExisting(cwd, state);
533
+ }
534
+ }
535
+ async function analyzeAndAdapt(cwd) {
536
+ console.log(chalk3.blue("\n\u2501\u2501\u2501 Analyzing Project \u2501\u2501\u2501\n"));
537
+ const { init: init2 } = await import("./init-YLAHY4CV.js");
538
+ await init2({ analyze: true, git: true });
539
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
540
+ const progressPath = join2(cwd, "progress.txt");
541
+ if (!existsSync2(progressPath)) {
542
+ const { writeFileSync } = await import("fs");
543
+ writeFileSync(progressPath, "# ArchonDev Progress Log\n\nThis file tracks learnings and decisions across sessions.\n");
544
+ }
545
+ appendFileSync(progressPath, `
546
+ ## ${today} - ArchonDev Adapted to Existing Project
547
+
548
+ ### What was done
549
+ - Analyzed existing codebase structure
550
+ - Generated ARCHITECTURE.md based on detected components
551
+ - Created .archon configuration
552
+
553
+ ### Governance Files Created
554
+ - ARCHITECTURE.md - Customized to match project structure
555
+ - .archon/config.yaml - Build commands configured
556
+ - progress.txt - This file
557
+ `);
558
+ console.log(chalk3.green("\n\u2713 Governance files adapted!\n"));
559
+ await showMainMenu();
560
+ }
561
+ async function codeReviewFirst(cwd) {
562
+ console.log(chalk3.blue("\n\u2501\u2501\u2501 Code Review Mode \u2501\u2501\u2501\n"));
563
+ console.log(chalk3.dim("I'll analyze your code for issues without making any changes.\n"));
564
+ const { reviewInit: reviewInit2, reviewAnalyze: reviewAnalyze2, reviewRun: reviewRun2 } = await import("./review-3R6QXAXQ.js");
565
+ const reviewDbPath = join2(cwd, "docs", "code-review", "review-tasks.db");
566
+ if (!existsSync2(reviewDbPath)) {
567
+ await reviewInit2();
568
+ }
569
+ await reviewAnalyze2();
570
+ const runReview = await promptYesNo("Would you like to run the AI-powered review now?", true);
571
+ if (runReview) {
572
+ await reviewRun2({ all: true });
573
+ }
574
+ console.log(chalk3.dim("\nAfter reviewing, you can run ") + chalk3.cyan("archon") + chalk3.dim(" again to set up governance.\n"));
575
+ }
576
+ async function manualSetup(cwd) {
577
+ console.log(chalk3.blue("\n\u2501\u2501\u2501 Manual Setup \u2501\u2501\u2501\n"));
578
+ console.log(chalk3.dim("Creating template files. You can customize them manually.\n"));
579
+ const { init: init2 } = await import("./init-YLAHY4CV.js");
580
+ await init2({ analyze: false, git: true });
581
+ console.log(chalk3.bold("\nWhat to customize:\n"));
582
+ console.log(` ${chalk3.cyan("1. ARCHITECTURE.md")} \u2014 Update components to match your folders`);
583
+ console.log(` ${chalk3.cyan("2. .archon/config.yaml")} \u2014 Change build/test/lint commands`);
584
+ console.log(` ${chalk3.cyan("3. progress.txt")} \u2014 Add project-specific patterns`);
585
+ console.log();
586
+ await showMainMenu();
587
+ }
588
+ async function quickAdapt(cwd) {
589
+ console.log(chalk3.blue("\n\u26A1 Using defaults \u2014 let's go!\n"));
590
+ const { init: init2 } = await import("./init-YLAHY4CV.js");
591
+ await init2({ analyze: true, git: true });
592
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
593
+ const progressPath = join2(cwd, "progress.txt");
594
+ if (!existsSync2(progressPath)) {
595
+ const { writeFileSync } = await import("fs");
596
+ writeFileSync(progressPath, "# ArchonDev Progress Log\n\nThis file tracks learnings and decisions across sessions.\n");
597
+ }
598
+ appendFileSync(progressPath, `
599
+ ## ${today} - Quick Adapt (Defaults)
600
+
601
+ ### What was done
602
+ - Used default governance rules
603
+ - You can customize later by editing ARCHITECTURE.md
604
+ `);
605
+ await showMainMenu();
606
+ }
607
+ async function handleContinueSession(cwd, state) {
608
+ console.log(chalk3.green("\u{1F44B}") + chalk3.bold(" Welcome back!\n"));
609
+ if (state.lastProgressEntry) {
610
+ console.log(chalk3.dim("Last activity:"));
611
+ console.log(chalk3.dim(" " + state.lastProgressEntry.split("\n")[0]));
684
612
  console.log();
685
613
  }
686
- if (state.hasArchitecture) {
687
- console.log(chalk4.green("\u2713") + " ARCHITECTURE.md found");
614
+ const handoff = checkForHandoff(cwd);
615
+ if (handoff) {
616
+ console.log(chalk3.yellow("\u{1F4CB} Found handoff from last session:\n"));
617
+ console.log(chalk3.dim(handoff.nextSteps));
618
+ console.log();
619
+ const continueHandoff = await promptYesNo("Continue from handoff?", true);
620
+ if (continueHandoff) {
621
+ console.log(chalk3.dim("\nPicking up where you left off...\n"));
622
+ }
688
623
  }
689
624
  if (state.hasReviewDb) {
690
625
  await showReviewProgress(cwd);
691
626
  }
692
- const atomsDir = join3(cwd, ".archon", "atoms");
693
- if (existsSync3(atomsDir)) {
694
- console.log(chalk4.dim(" Checking for pending work..."));
627
+ await showMainMenu();
628
+ }
629
+ function checkForHandoff(cwd) {
630
+ try {
631
+ const progressPath = join2(cwd, "progress.txt");
632
+ if (!existsSync2(progressPath)) return null;
633
+ const content = readFileSync(progressPath, "utf-8");
634
+ const handoffMatch = content.match(/## Context Handoff[^\n]*\n([\s\S]*?)(?=\n## |\n*$)/);
635
+ if (handoffMatch && handoffMatch[1]) {
636
+ const handoffContent = handoffMatch[1];
637
+ const nextStepsMatch = handoffContent.match(/### Next Steps[^\n]*\n([\s\S]*?)(?=\n### |$)/);
638
+ if (nextStepsMatch && nextStepsMatch[1]) {
639
+ return { nextSteps: nextStepsMatch[1].trim() };
640
+ }
641
+ }
642
+ } catch {
643
+ }
644
+ return null;
645
+ }
646
+ async function showMainMenu() {
647
+ const cwd = process.cwd();
648
+ const state = detectProjectState(cwd);
649
+ console.log(chalk3.bold("What would you like to do?\n"));
650
+ const choices = [
651
+ { key: "1", label: "Plan a new task", action: () => planTask() },
652
+ { key: "2", label: "List atoms", action: () => listAtoms() },
653
+ { key: "3", label: "Execute next atom", action: () => executeNext() },
654
+ { key: "4", label: "Report a bug", action: () => reportBug() },
655
+ { key: "5", label: "View status", action: () => viewStatus() },
656
+ { key: "6", label: "Code Review", action: () => reviewCode() },
657
+ { key: "7", label: "Settings & Preferences", action: () => settingsMenu() },
658
+ { key: "q", label: "Quit", action: async () => process.exit(0) }
659
+ ];
660
+ for (const choice2 of choices) {
661
+ console.log(` ${chalk3.cyan(choice2.key)}) ${choice2.label}`);
695
662
  }
696
663
  console.log();
664
+ const selected = await prompt("Enter choice");
665
+ const choice = choices.find((c) => c.key === selected.toLowerCase());
666
+ if (choice) {
667
+ await choice.action();
668
+ } else {
669
+ console.log(chalk3.yellow("Invalid choice. Please try again."));
670
+ await showMainMenu();
671
+ }
697
672
  }
698
673
  async function showReviewProgress(cwd) {
699
674
  try {
@@ -707,29 +682,30 @@ async function showReviewProgress(cwd) {
707
682
  const pending = stats.pending + stats.inReview;
708
683
  const needsFix = stats.needsFix;
709
684
  console.log(
710
- chalk4.blue("\u{1F4CA} Review Progress:") + chalk4.dim(` ${completed}/${total} completed`) + (needsFix > 0 ? chalk4.red(` (${needsFix} need fixes)`) : "") + (pending > 0 ? chalk4.yellow(` (${pending} pending)`) : "")
685
+ chalk3.blue("\u{1F4CA} Review Progress:") + chalk3.dim(` ${completed}/${total} completed`) + (needsFix > 0 ? chalk3.red(` (${needsFix} need fixes)`) : "") + (pending > 0 ? chalk3.yellow(` (${pending} pending)`) : "")
711
686
  );
687
+ console.log();
712
688
  } catch {
713
689
  }
714
690
  }
715
691
  async function planTask() {
716
- const { plan: plan2 } = await import("./plan-7VSFESVD.js");
692
+ const { plan: plan2 } = await import("./plan-WQUFH2WB.js");
717
693
  const description = await prompt("Describe what you want to build");
718
694
  if (description.trim()) {
719
695
  await plan2(description, {});
720
696
  }
721
697
  }
722
698
  async function listAtoms() {
723
- const { list: list2 } = await import("./list-VXMVEIL5.js");
699
+ const { list: list2 } = await import("./list-UB4MOGRH.js");
724
700
  await list2({});
725
701
  }
726
702
  async function executeNext() {
727
703
  const atomId = await prompt("Enter atom ID to execute (or press Enter for next planned)");
728
704
  if (atomId.trim()) {
729
- const { execute: execute2 } = await import("./execute-N6CCEJ5I.js");
705
+ const { execute: execute2 } = await import("./execute-6ZGARWT2.js");
730
706
  await execute2(atomId.trim(), {});
731
707
  } else {
732
- console.log(chalk4.yellow('No atom ID provided. Use "archon list" to see available atoms.'));
708
+ console.log(chalk3.yellow('No atom ID provided. Use "archon list" to see available atoms.'));
733
709
  }
734
710
  }
735
711
  async function reportBug() {
@@ -746,23 +722,24 @@ async function viewStatus() {
746
722
  async function settingsMenu() {
747
723
  const { interactiveSettings } = await import("./preferences-QEFXVCZN.js");
748
724
  await interactiveSettings();
749
- await start();
725
+ await showMainMenu();
750
726
  }
751
727
  async function reviewCode() {
752
728
  const cwd = process.cwd();
753
- const reviewDbPath = join3(cwd, "docs", "code-review", "review-tasks.db");
754
- if (!existsSync3(reviewDbPath)) {
755
- console.log(chalk4.dim("Code review not initialized. Starting setup...\n"));
729
+ const reviewDbPath = join2(cwd, "docs", "code-review", "review-tasks.db");
730
+ if (!existsSync2(reviewDbPath)) {
731
+ console.log(chalk3.dim("Code review not initialized. Starting setup...\n"));
756
732
  const { reviewInit: reviewInit2 } = await import("./review-3R6QXAXQ.js");
757
733
  await reviewInit2();
758
734
  console.log();
759
735
  }
760
- console.log(chalk4.bold("\nCode Review Options:\n"));
761
- console.log(` ${chalk4.cyan("1")}) Analyze project`);
762
- console.log(` ${chalk4.cyan("2")}) Show review status`);
763
- console.log(` ${chalk4.cyan("3")}) Review next file`);
764
- console.log(` ${chalk4.cyan("4")}) List all tasks`);
765
- console.log(` ${chalk4.cyan("b")}) Back to main menu`);
736
+ console.log(chalk3.bold("\nCode Review Options:\n"));
737
+ console.log(` ${chalk3.cyan("1")}) Analyze project`);
738
+ console.log(` ${chalk3.cyan("2")}) Show review status`);
739
+ console.log(` ${chalk3.cyan("3")}) Review next file`);
740
+ console.log(` ${chalk3.cyan("4")}) List all tasks`);
741
+ console.log(` ${chalk3.cyan("5")}) Run AI review on all pending`);
742
+ console.log(` ${chalk3.cyan("b")}) Back to main menu`);
766
743
  console.log();
767
744
  const choice = await prompt("Enter choice");
768
745
  switch (choice.toLowerCase()) {
@@ -786,30 +763,68 @@ async function reviewCode() {
786
763
  await reviewList2({});
787
764
  break;
788
765
  }
766
+ case "5": {
767
+ const { reviewRun: reviewRun2 } = await import("./review-3R6QXAXQ.js");
768
+ await reviewRun2({ all: true });
769
+ break;
770
+ }
789
771
  case "b":
790
- await start();
772
+ await showMainMenu();
791
773
  return;
792
774
  default:
793
- console.log(chalk4.yellow("Invalid choice."));
775
+ console.log(chalk3.yellow("Invalid choice."));
794
776
  }
795
777
  await reviewCode();
796
778
  }
797
779
  function prompt(question) {
798
780
  return new Promise((resolve) => {
799
- const rl = readline2.createInterface({
781
+ const rl = readline.createInterface({
800
782
  input: process.stdin,
801
783
  output: process.stdout
802
784
  });
803
- rl.question(`${chalk4.cyan("?")} ${question}: `, (answer) => {
785
+ rl.question(`${chalk3.cyan("?")} ${question}: `, (answer) => {
804
786
  rl.close();
805
787
  resolve(answer);
806
788
  });
807
789
  });
808
790
  }
791
+ function promptYesNo(question, defaultValue) {
792
+ return new Promise((resolve) => {
793
+ const rl = readline.createInterface({
794
+ input: process.stdin,
795
+ output: process.stdout
796
+ });
797
+ const hint = defaultValue ? "(Y/n)" : "(y/N)";
798
+ rl.question(`${chalk3.cyan("?")} ${question} ${hint}: `, (answer) => {
799
+ rl.close();
800
+ if (answer.trim() === "") {
801
+ resolve(defaultValue);
802
+ } else {
803
+ resolve(answer.toLowerCase().startsWith("y"));
804
+ }
805
+ });
806
+ });
807
+ }
808
+ function promptChoice(question, options) {
809
+ return new Promise((resolve) => {
810
+ console.log(`${chalk3.cyan("?")} ${question}`);
811
+ for (const opt of options) {
812
+ console.log(` ${chalk3.dim(opt.key)}) ${opt.label}`);
813
+ }
814
+ const rl = readline.createInterface({
815
+ input: process.stdin,
816
+ output: process.stdout
817
+ });
818
+ rl.question(` ${chalk3.dim("Enter choice")}: `, (answer) => {
819
+ rl.close();
820
+ resolve(answer.trim() || "1");
821
+ });
822
+ });
823
+ }
809
824
 
810
825
  // src/cli/credits.ts
811
- import chalk5 from "chalk";
812
- import ora2 from "ora";
826
+ import chalk4 from "chalk";
827
+ import ora from "ora";
813
828
  import open from "open";
814
829
  import { createClient } from "@supabase/supabase-js";
815
830
  function getSupabaseClient(accessToken) {
@@ -818,7 +833,7 @@ function getSupabaseClient(accessToken) {
818
833
  });
819
834
  }
820
835
  async function showCredits() {
821
- const spinner = ora2("Fetching credit balance...").start();
836
+ const spinner = ora("Fetching credit balance...").start();
822
837
  try {
823
838
  const config = await loadConfig();
824
839
  if (!config.accessToken || !config.userId) {
@@ -834,21 +849,21 @@ async function showCredits() {
834
849
  const profile = data;
835
850
  spinner.stop();
836
851
  console.log();
837
- console.log(chalk5.bold("\u{1F4B0} Credit Balance"));
852
+ console.log(chalk4.bold("\u{1F4B0} Credit Balance"));
838
853
  console.log();
839
854
  const balance = (profile.credit_balance_cents || 0) / 100;
840
855
  console.log(` Tier: ${formatTier(profile.tier)}`);
841
- console.log(` Balance: ${chalk5.green(`$${balance.toFixed(2)}`)}`);
856
+ console.log(` Balance: ${chalk4.green(`$${balance.toFixed(2)}`)}`);
842
857
  if (profile.tier === "FREE") {
843
858
  console.log(` Atoms: ${profile.atoms_used_this_month}/10,000 this month`);
844
859
  console.log();
845
- console.log(chalk5.dim(" Upgrade to Credits tier: archon credits add"));
860
+ console.log(chalk4.dim(" Upgrade to Credits tier: archon credits add"));
846
861
  } else if (profile.tier === "CREDITS") {
847
862
  console.log();
848
- console.log(chalk5.dim(" Add more credits: archon credits add"));
863
+ console.log(chalk4.dim(" Add more credits: archon credits add"));
849
864
  } else if (profile.tier === "BYOK") {
850
865
  console.log();
851
- console.log(chalk5.dim(" Using your own API keys - no credit charges"));
866
+ console.log(chalk4.dim(" Using your own API keys - no credit charges"));
852
867
  }
853
868
  console.log();
854
869
  } catch (err) {
@@ -857,7 +872,7 @@ async function showCredits() {
857
872
  }
858
873
  }
859
874
  async function addCredits(options = {}) {
860
- const spinner = ora2("Preparing checkout...").start();
875
+ const spinner = ora("Preparing checkout...").start();
861
876
  try {
862
877
  const config = await loadConfig();
863
878
  if (!config.accessToken || !config.userId) {
@@ -894,18 +909,18 @@ async function addCredits(options = {}) {
894
909
  }
895
910
  spinner.succeed("Checkout ready");
896
911
  console.log();
897
- console.log(chalk5.bold("\u{1F6D2} Add Credits"));
912
+ console.log(chalk4.bold("\u{1F6D2} Add Credits"));
898
913
  console.log();
899
- console.log(` Amount: ${chalk5.green(`$${amountDollars.toFixed(2)}`)}`);
914
+ console.log(` Amount: ${chalk4.green(`$${amountDollars.toFixed(2)}`)}`);
900
915
  console.log();
901
916
  console.log(" Opening checkout in browser...");
902
917
  console.log();
903
- console.log(chalk5.dim(` Or visit: ${checkoutUrl}`));
918
+ console.log(chalk4.dim(` Or visit: ${checkoutUrl}`));
904
919
  console.log();
905
920
  try {
906
921
  await open(checkoutUrl);
907
922
  } catch {
908
- console.log(chalk5.yellow(" Could not open browser. Please visit the URL above."));
923
+ console.log(chalk4.yellow(" Could not open browser. Please visit the URL above."));
909
924
  }
910
925
  } catch (err) {
911
926
  spinner.fail("Error preparing checkout");
@@ -913,7 +928,7 @@ async function addCredits(options = {}) {
913
928
  }
914
929
  }
915
930
  async function showHistory(options = {}) {
916
- const spinner = ora2("Fetching usage history...").start();
931
+ const spinner = ora("Fetching usage history...").start();
917
932
  try {
918
933
  const config = await loadConfig();
919
934
  if (!config.accessToken || !config.userId) {
@@ -930,15 +945,15 @@ async function showHistory(options = {}) {
930
945
  const usage = data;
931
946
  spinner.stop();
932
947
  console.log();
933
- console.log(chalk5.bold("\u{1F4CA} Usage History"));
948
+ console.log(chalk4.bold("\u{1F4CA} Usage History"));
934
949
  console.log();
935
950
  if (!usage || usage.length === 0) {
936
- console.log(chalk5.dim(" No usage recorded yet."));
951
+ console.log(chalk4.dim(" No usage recorded yet."));
937
952
  console.log();
938
953
  return;
939
954
  }
940
- console.log(chalk5.dim(" Model Tokens Cost Date"));
941
- console.log(chalk5.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"));
955
+ console.log(chalk4.dim(" Model Tokens Cost Date"));
956
+ console.log(chalk4.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"));
942
957
  for (const row of usage) {
943
958
  const model = row.model.padEnd(30).slice(0, 30);
944
959
  const tokens = (row.input_tokens + row.output_tokens).toString().padStart(8);
@@ -948,9 +963,9 @@ async function showHistory(options = {}) {
948
963
  }
949
964
  const totalCost = usage.reduce((sum, r) => sum + r.base_cost, 0);
950
965
  const totalTokens = usage.reduce((sum, r) => sum + r.input_tokens + r.output_tokens, 0);
951
- console.log(chalk5.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"));
966
+ console.log(chalk4.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"));
952
967
  console.log(
953
- ` ${"Total".padEnd(30)} ${totalTokens.toString().padStart(8)} ${chalk5.green(`$${totalCost.toFixed(4)}`.padStart(10))}`
968
+ ` ${"Total".padEnd(30)} ${totalTokens.toString().padStart(8)} ${chalk4.green(`$${totalCost.toFixed(4)}`.padStart(10))}`
954
969
  );
955
970
  console.log();
956
971
  } catch (err) {
@@ -959,7 +974,7 @@ async function showHistory(options = {}) {
959
974
  }
960
975
  }
961
976
  async function manageBudget(options = {}) {
962
- const spinner = ora2("Fetching budget settings...").start();
977
+ const spinner = ora("Fetching budget settings...").start();
963
978
  try {
964
979
  const config = await loadConfig();
965
980
  if (!config.accessToken || !config.userId) {
@@ -1016,24 +1031,24 @@ async function manageBudget(options = {}) {
1016
1031
  }
1017
1032
  spinner.stop();
1018
1033
  console.log();
1019
- console.log(chalk5.bold("\u{1F4CA} Monthly Budget"));
1034
+ console.log(chalk4.bold("\u{1F4CA} Monthly Budget"));
1020
1035
  console.log();
1021
1036
  if (profile.monthly_budget_cents === null) {
1022
- console.log(` Budget: ${chalk5.dim("No limit set")}`);
1037
+ console.log(` Budget: ${chalk4.dim("No limit set")}`);
1023
1038
  } else {
1024
1039
  const budget = profile.monthly_budget_cents / 100;
1025
1040
  const spend = (profile.monthly_spend_cents || 0) / 100;
1026
1041
  const remaining = budget - spend;
1027
1042
  const percent = budget > 0 ? Math.round(spend / budget * 100) : 0;
1028
- console.log(` Budget: ${chalk5.green(`$${budget.toFixed(2)}`)} / month`);
1043
+ console.log(` Budget: ${chalk4.green(`$${budget.toFixed(2)}`)} / month`);
1029
1044
  console.log(` Spent: $${spend.toFixed(2)} (${percent}%)`);
1030
- console.log(` Remaining: ${remaining >= 0 ? chalk5.green(`$${remaining.toFixed(2)}`) : chalk5.red(`-$${Math.abs(remaining).toFixed(2)}`)}`);
1045
+ console.log(` Remaining: ${remaining >= 0 ? chalk4.green(`$${remaining.toFixed(2)}`) : chalk4.red(`-$${Math.abs(remaining).toFixed(2)}`)}`);
1031
1046
  }
1032
1047
  console.log(` Alert at: ${profile.budget_alert_threshold_percent}% of budget`);
1033
1048
  console.log();
1034
- console.log(chalk5.dim(" Set budget: archon credits budget --set 50"));
1035
- console.log(chalk5.dim(" Clear budget: archon credits budget --clear"));
1036
- console.log(chalk5.dim(" Set alert: archon credits budget --alert 80"));
1049
+ console.log(chalk4.dim(" Set budget: archon credits budget --set 50"));
1050
+ console.log(chalk4.dim(" Clear budget: archon credits budget --clear"));
1051
+ console.log(chalk4.dim(" Set alert: archon credits budget --alert 80"));
1037
1052
  console.log();
1038
1053
  } catch (err) {
1039
1054
  spinner.fail("Error managing budget");
@@ -1041,7 +1056,7 @@ async function manageBudget(options = {}) {
1041
1056
  }
1042
1057
  }
1043
1058
  async function manageAutoRecharge(options = {}) {
1044
- const spinner = ora2("Fetching auto-recharge settings...").start();
1059
+ const spinner = ora("Fetching auto-recharge settings...").start();
1045
1060
  try {
1046
1061
  const config = await loadConfig();
1047
1062
  if (!config.accessToken || !config.userId) {
@@ -1095,12 +1110,12 @@ async function manageAutoRecharge(options = {}) {
1095
1110
  }
1096
1111
  spinner.stop();
1097
1112
  console.log();
1098
- console.log(chalk5.bold("\u{1F504} Auto-Recharge"));
1113
+ console.log(chalk4.bold("\u{1F504} Auto-Recharge"));
1099
1114
  console.log();
1100
1115
  if (!profile.auto_recharge_enabled) {
1101
- console.log(` Status: ${chalk5.dim("Disabled")}`);
1116
+ console.log(` Status: ${chalk4.dim("Disabled")}`);
1102
1117
  } else {
1103
- console.log(` Status: ${chalk5.green("Enabled")}`);
1118
+ console.log(` Status: ${chalk4.green("Enabled")}`);
1104
1119
  if (profile.auto_recharge_threshold_cents !== null) {
1105
1120
  console.log(` When: Balance drops below $${(profile.auto_recharge_threshold_cents / 100).toFixed(2)}`);
1106
1121
  }
@@ -1108,10 +1123,10 @@ async function manageAutoRecharge(options = {}) {
1108
1123
  console.log(` Amount: $${(profile.auto_recharge_amount_cents / 100).toFixed(2)}`);
1109
1124
  }
1110
1125
  }
1111
- console.log(` Payment: ${profile.stripe_payment_method_id ? chalk5.green("Card saved") : chalk5.dim("No card saved")}`);
1126
+ console.log(` Payment: ${profile.stripe_payment_method_id ? chalk4.green("Card saved") : chalk4.dim("No card saved")}`);
1112
1127
  console.log();
1113
- console.log(chalk5.dim(" Enable: archon credits auto-recharge --enable --threshold 5 --amount 20"));
1114
- console.log(chalk5.dim(" Disable: archon credits auto-recharge --disable"));
1128
+ console.log(chalk4.dim(" Enable: archon credits auto-recharge --enable --threshold 5 --amount 20"));
1129
+ console.log(chalk4.dim(" Disable: archon credits auto-recharge --disable"));
1115
1130
  console.log();
1116
1131
  } catch (err) {
1117
1132
  spinner.fail("Error managing auto-recharge");
@@ -1121,11 +1136,11 @@ async function manageAutoRecharge(options = {}) {
1121
1136
  function formatTier(tier) {
1122
1137
  switch (tier) {
1123
1138
  case "FREE":
1124
- return chalk5.blue("Free (10k atoms/month)");
1139
+ return chalk4.blue("Free (10k atoms/month)");
1125
1140
  case "CREDITS":
1126
- return chalk5.green("Credits (Pay-as-you-go)");
1141
+ return chalk4.green("Credits (Pay-as-you-go)");
1127
1142
  case "BYOK":
1128
- return chalk5.magenta("BYOK (Bring Your Own Key)");
1143
+ return chalk4.magenta("BYOK (Bring Your Own Key)");
1129
1144
  default:
1130
1145
  return tier;
1131
1146
  }
@@ -1402,9 +1417,9 @@ async function watch() {
1402
1417
 
1403
1418
  // src/cli/deps.ts
1404
1419
  import { Command } from "commander";
1405
- import chalk6 from "chalk";
1406
- import { readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
1407
- import { existsSync as existsSync5 } from "fs";
1420
+ import chalk5 from "chalk";
1421
+ import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
1422
+ import { existsSync as existsSync4 } from "fs";
1408
1423
  var DEPENDENCIES_FILENAME = "DEPENDENCIES.md";
1409
1424
  function createDepsCommand() {
1410
1425
  const deps = new Command("deps").description("Manage file-level dependencies (DEPENDENCIES.md)").addHelpText(
@@ -1420,30 +1435,30 @@ Examples:
1420
1435
  deps.command("list").description("List all dependency rules").option("-v, --verbose", "Show detailed information").action(async (options) => {
1421
1436
  const parser = new DependencyParser();
1422
1437
  if (!parser.exists()) {
1423
- console.log(chalk6.yellow("No DEPENDENCIES.md found."));
1424
- console.log(chalk6.dim("Create one with: archon deps add --source <path> --dependent <path>"));
1438
+ console.log(chalk5.yellow("No DEPENDENCIES.md found."));
1439
+ console.log(chalk5.dim("Create one with: archon deps add --source <path> --dependent <path>"));
1425
1440
  return;
1426
1441
  }
1427
1442
  const result = await parser.parse();
1428
1443
  if (!result.success) {
1429
- console.log(chalk6.red(`Parse error: ${result.error}`));
1444
+ console.log(chalk5.red(`Parse error: ${result.error}`));
1430
1445
  return;
1431
1446
  }
1432
1447
  const rules = result.document?.rules ?? [];
1433
1448
  if (rules.length === 0) {
1434
- console.log(chalk6.dim("No dependency rules defined."));
1449
+ console.log(chalk5.dim("No dependency rules defined."));
1435
1450
  return;
1436
1451
  }
1437
- console.log(chalk6.bold(`
1452
+ console.log(chalk5.bold(`
1438
1453
  \u{1F4E6} Dependency Rules (${rules.length})
1439
1454
  `));
1440
1455
  for (const rule of rules) {
1441
- const severityColor = rule.severity === "BLOCKER" ? chalk6.red : rule.severity === "WARNING" ? chalk6.yellow : chalk6.blue;
1442
- console.log(`${severityColor(`[${rule.severity}]`)} ${chalk6.bold(rule.id)}`);
1443
- console.log(` Source: ${chalk6.cyan(rule.source)}`);
1444
- console.log(` Dependents: ${rule.dependents.map((d) => chalk6.dim(d)).join(", ")}`);
1456
+ const severityColor = rule.severity === "BLOCKER" ? chalk5.red : rule.severity === "WARNING" ? chalk5.yellow : chalk5.blue;
1457
+ console.log(`${severityColor(`[${rule.severity}]`)} ${chalk5.bold(rule.id)}`);
1458
+ console.log(` Source: ${chalk5.cyan(rule.source)}`);
1459
+ console.log(` Dependents: ${rule.dependents.map((d) => chalk5.dim(d)).join(", ")}`);
1445
1460
  if (rule.reason && options.verbose) {
1446
- console.log(` Reason: ${chalk6.dim(rule.reason)}`);
1461
+ console.log(` Reason: ${chalk5.dim(rule.reason)}`);
1447
1462
  }
1448
1463
  if (rule.mustTest && options.verbose) {
1449
1464
  console.log(` Must test: ${rule.mustTest.join(", ")}`);
@@ -1455,29 +1470,29 @@ Examples:
1455
1470
  const files = options.files.split(",").map((f) => f.trim());
1456
1471
  const parser = new DependencyParser();
1457
1472
  if (!parser.exists()) {
1458
- console.log(chalk6.dim("No DEPENDENCIES.md found. No dependency checks performed."));
1473
+ console.log(chalk5.dim("No DEPENDENCIES.md found. No dependency checks performed."));
1459
1474
  process.exit(0);
1460
1475
  }
1461
1476
  const result = await parser.checkFiles(files);
1462
1477
  if (result.impacts.length === 0) {
1463
- console.log(chalk6.green("\u2705 No downstream dependency impacts found."));
1478
+ console.log(chalk5.green("\u2705 No downstream dependency impacts found."));
1464
1479
  process.exit(0);
1465
1480
  }
1466
- console.log(chalk6.yellow(`
1481
+ console.log(chalk5.yellow(`
1467
1482
  \u26A0\uFE0F Found ${result.impacts.length} dependency impact(s):
1468
1483
  `));
1469
1484
  for (const impact of result.impacts) {
1470
- const severityColor = impact.rule.severity === "BLOCKER" ? chalk6.red : impact.rule.severity === "WARNING" ? chalk6.yellow : chalk6.blue;
1485
+ const severityColor = impact.rule.severity === "BLOCKER" ? chalk5.red : impact.rule.severity === "WARNING" ? chalk5.yellow : chalk5.blue;
1471
1486
  console.log(severityColor(`[${impact.rule.severity}] ${impact.rule.id}`));
1472
- console.log(` Changing: ${chalk6.cyan(impact.matchedSource)}`);
1487
+ console.log(` Changing: ${chalk5.cyan(impact.matchedSource)}`);
1473
1488
  console.log(` May impact: ${impact.affectedDependents.join(", ")}`);
1474
1489
  if (impact.rule.reason) {
1475
- console.log(` Reason: ${chalk6.dim(impact.rule.reason)}`);
1490
+ console.log(` Reason: ${chalk5.dim(impact.rule.reason)}`);
1476
1491
  }
1477
1492
  console.log("");
1478
1493
  }
1479
1494
  if (result.hasBlockers) {
1480
- console.log(chalk6.red("\u274C BLOCKER-level impacts found. Review before proceeding."));
1495
+ console.log(chalk5.red("\u274C BLOCKER-level impacts found. Review before proceeding."));
1481
1496
  process.exit(1);
1482
1497
  }
1483
1498
  process.exit(0);
@@ -1491,7 +1506,7 @@ Examples:
1491
1506
  let existingRules = [];
1492
1507
  let markdownBody = "";
1493
1508
  if (parser.exists()) {
1494
- const content = await readFile3(DEPENDENCIES_FILENAME, "utf-8");
1509
+ const content = await readFile2(DEPENDENCIES_FILENAME, "utf-8");
1495
1510
  const result = await parser.parse();
1496
1511
  if (result.success && result.document) {
1497
1512
  existingRules = result.document.rules;
@@ -1519,7 +1534,7 @@ Examples:
1519
1534
  (r) => r.source === source && r.dependents.includes(dependent)
1520
1535
  );
1521
1536
  if (existingRule) {
1522
- console.log(chalk6.yellow(`Rule already exists: ${existingRule.id}`));
1537
+ console.log(chalk5.yellow(`Rule already exists: ${existingRule.id}`));
1523
1538
  return;
1524
1539
  }
1525
1540
  const newRule = {
@@ -1531,22 +1546,22 @@ Examples:
1531
1546
  };
1532
1547
  existingRules.push(newRule);
1533
1548
  const yaml = generateYamlFrontmatter(existingRules);
1534
- await writeFile3(DEPENDENCIES_FILENAME, `---
1549
+ await writeFile2(DEPENDENCIES_FILENAME, `---
1535
1550
  ${yaml}---${markdownBody}`, "utf-8");
1536
- console.log(chalk6.green(`\u2705 Added dependency rule: ${nextId}`));
1537
- console.log(` Source: ${chalk6.cyan(source)}`);
1538
- console.log(` Dependent: ${chalk6.dim(dependent)}`);
1551
+ console.log(chalk5.green(`\u2705 Added dependency rule: ${nextId}`));
1552
+ console.log(` Source: ${chalk5.cyan(source)}`);
1553
+ console.log(` Dependent: ${chalk5.dim(dependent)}`);
1539
1554
  });
1540
1555
  deps.command("graph").description("Generate Mermaid diagram of dependencies").option("--output <file>", "Write to file instead of stdout").action(async (options) => {
1541
1556
  const parser = new DependencyParser();
1542
1557
  if (!parser.exists()) {
1543
- console.log(chalk6.yellow("No DEPENDENCIES.md found."));
1558
+ console.log(chalk5.yellow("No DEPENDENCIES.md found."));
1544
1559
  return;
1545
1560
  }
1546
1561
  const mermaid = await parser.generateGraph();
1547
1562
  if (options.output) {
1548
- await writeFile3(options.output, mermaid, "utf-8");
1549
- console.log(chalk6.green(`\u2705 Graph written to ${options.output}`));
1563
+ await writeFile2(options.output, mermaid, "utf-8");
1564
+ console.log(chalk5.green(`\u2705 Graph written to ${options.output}`));
1550
1565
  } else {
1551
1566
  console.log("\n```mermaid");
1552
1567
  console.log(mermaid);
@@ -1554,8 +1569,8 @@ ${yaml}---${markdownBody}`, "utf-8");
1554
1569
  }
1555
1570
  });
1556
1571
  deps.command("init").description("Create a starter DEPENDENCIES.md file").action(async () => {
1557
- if (existsSync5(DEPENDENCIES_FILENAME)) {
1558
- console.log(chalk6.yellow("DEPENDENCIES.md already exists."));
1572
+ if (existsSync4(DEPENDENCIES_FILENAME)) {
1573
+ console.log(chalk5.yellow("DEPENDENCIES.md already exists."));
1559
1574
  return;
1560
1575
  }
1561
1576
  const template = `---
@@ -1601,9 +1616,9 @@ rules:
1601
1616
 
1602
1617
  *Powered by [ArchonDev](https://archondev.io)*
1603
1618
  `;
1604
- await writeFile3(DEPENDENCIES_FILENAME, template, "utf-8");
1605
- console.log(chalk6.green("\u2705 Created DEPENDENCIES.md"));
1606
- console.log(chalk6.dim("Add your first rule with: archon deps add --source <path> --dependent <path>"));
1619
+ await writeFile2(DEPENDENCIES_FILENAME, template, "utf-8");
1620
+ console.log(chalk5.green("\u2705 Created DEPENDENCIES.md"));
1621
+ console.log(chalk5.dim("Add your first rule with: archon deps add --source <path> --dependent <path>"));
1607
1622
  });
1608
1623
  return deps;
1609
1624
  }
@@ -1644,7 +1659,7 @@ var program = new Command2();
1644
1659
  program.name("archon").description("Local-first AI-powered development governance").version("1.1.0").action(async () => {
1645
1660
  const cwd = process.cwd();
1646
1661
  if (!isInitialized(cwd)) {
1647
- console.log(chalk7.blue("\nArchonDev is not initialized in this folder.\n"));
1662
+ console.log(chalk6.blue("\nArchonDev is not initialized in this folder.\n"));
1648
1663
  await init({ analyze: true, git: true });
1649
1664
  }
1650
1665
  await start();
@@ -1652,7 +1667,7 @@ program.name("archon").description("Local-first AI-powered development governanc
1652
1667
  program.command("login").description("Authenticate with ArchonDev").option("-p, --provider <provider>", "OAuth provider (github or google)", "github").action(async (options) => {
1653
1668
  const provider = options.provider;
1654
1669
  if (provider !== "github" && provider !== "google") {
1655
- console.error(chalk7.red('Invalid provider. Use "github" or "google"'));
1670
+ console.error(chalk6.red('Invalid provider. Use "github" or "google"'));
1656
1671
  process.exit(1);
1657
1672
  }
1658
1673
  await login(provider);