archondev 2.17.0 → 2.18.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +1 -0
  2. package/dist/a11y-O35BAA25.js +14 -0
  3. package/dist/auth-HQBAG4CR.js +14 -0
  4. package/dist/bug-5WRBCFRT.js +12 -0
  5. package/dist/{chunk-ER4ADSWH.js → chunk-2NSWZDP7.js} +1 -156
  6. package/dist/chunk-3ASILTFB.js +73 -0
  7. package/dist/{chunk-LHCXE6UL.js → chunk-3PZ7WU5I.js} +26 -73
  8. package/dist/{chunk-QGM4M3NI.js → chunk-4VNS5WPM.js} +5 -0
  9. package/dist/chunk-4YEJ26F7.js +183 -0
  10. package/dist/chunk-5CFGPXQ3.js +160 -0
  11. package/dist/{chunk-TRLP7RMZ.js → chunk-75J2JMU3.js} +2 -2
  12. package/dist/{chunk-FGH2UX3E.js → chunk-BFPWDOMA.js} +1 -1
  13. package/dist/{chunk-FA2GAZ7L.js → chunk-CZCY63EY.js} +12 -8
  14. package/dist/{chunk-E7ZTIAQM.js → chunk-EKU62MGC.js} +160 -286
  15. package/dist/chunk-FWLLGLD5.js +353 -0
  16. package/dist/{chunk-BDPGWWQC.js → chunk-HGLPIM7J.js} +1 -1
  17. package/dist/{chunk-NIKN37AY.js → chunk-HJARQDQR.js} +1 -1
  18. package/dist/chunk-JF7JCK6H.js +485 -0
  19. package/dist/{chunk-DUJOT5B6.js → chunk-LBBHM4I5.js} +8 -8
  20. package/dist/{chunk-LPSS2U5V.js → chunk-NCPHO54C.js} +65 -2
  21. package/dist/{chunk-WZIRUPMP.js → chunk-NJF6MRTR.js} +1 -1
  22. package/dist/{chunk-54ATBLYE.js → chunk-P666JE3G.js} +1 -1
  23. package/dist/{chunk-SUGIWSCB.js → chunk-SVU7MLG6.js} +5 -24
  24. package/dist/chunk-UD45ZLV3.js +495 -0
  25. package/dist/{chunk-LXXTCZ2Q.js → chunk-UFR2LX6G.js} +216 -14
  26. package/dist/{chunk-2QIXLBAC.js → chunk-VF2OTDMS.js} +6 -4
  27. package/dist/{chunk-HTJOCKVV.js → chunk-ZJXIOETW.js} +6 -6
  28. package/dist/{code-review-ORCNXANW.js → code-review-6MU4UE5M.js} +4 -4
  29. package/dist/{config-USLUSE4N.js → config-JBPM2YAB.js} +2 -3
  30. package/dist/{constants-AHP5F7HW.js → constants-XDIWFFPN.js} +1 -1
  31. package/dist/execute-MB4ZF3HQ.js +18 -0
  32. package/dist/geo-KV4IRGKN.js +20 -0
  33. package/dist/index.js +928 -1831
  34. package/dist/{init-PSMJLDEZ.js → init-FINETS3Q.js} +2 -2
  35. package/dist/{interviewer-Q6PFSAGT.js → interviewer-NQHNMVH4.js} +5 -6
  36. package/dist/{keys-SXJ6MKPY.js → keys-THCHXIFD.js} +1 -1
  37. package/dist/{keys-VLK3EWSN.js → keys-U4QZE5YB.js} +3 -4
  38. package/dist/list-CNKAH354.js +17 -0
  39. package/dist/{manager-32P6ZZBP.js → manager-YSNTH2DG.js} +1 -1
  40. package/dist/models-UTFGCHAY.js +33 -0
  41. package/dist/{orchestration-X6LHSHBJ.js → orchestration-HIF3KP25.js} +1 -1
  42. package/dist/{parallel-WHFKRBPR.js → parallel-W2ETYYAL.js} +11 -7
  43. package/dist/{parser-4KJH2PT5.js → parser-BFHETZ5B.js} +1 -1
  44. package/dist/{plan-X77BUKNE.js → plan-XALA4SLH.js} +7 -6
  45. package/dist/{preferences-TWEK2RWY.js → preferences-I6WETXOI.js} +6 -6
  46. package/dist/{review-T4ID2QUF.js → review-AUG6GIL6.js} +5 -5
  47. package/dist/seo-PMI42KRZ.js +10 -0
  48. package/dist/{tier-selection-Z2RFHZUX.js → tier-selection-426HA765.js} +3 -4
  49. package/dist/web-checks-4BSYXWDF.js +13 -0
  50. package/package.json +1 -1
  51. package/dist/auth-KUFS3PBS.js +0 -14
  52. package/dist/bug-BJH4X5LI.js +0 -12
  53. package/dist/execute-73QW4ZEZ.js +0 -16
  54. package/dist/list-MMKB5TGX.js +0 -16
package/dist/index.js CHANGED
@@ -1,4 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ createGeoCommand
4
+ } from "./chunk-UD45ZLV3.js";
2
5
  import {
3
6
  reviewAnalyze,
4
7
  reviewExport,
@@ -10,8 +13,8 @@ import {
10
13
  reviewShow,
11
14
  reviewStatus,
12
15
  reviewUpdate
13
- } from "./chunk-FGH2UX3E.js";
14
- import "./chunk-BDPGWWQC.js";
16
+ } from "./chunk-BFPWDOMA.js";
17
+ import "./chunk-HGLPIM7J.js";
15
18
  import {
16
19
  listModels,
17
20
  resetPreferences,
@@ -19,80 +22,92 @@ import {
19
22
  setPreference,
20
23
  showExecutionPreferences,
21
24
  showPreferences
22
- } from "./chunk-HTJOCKVV.js";
25
+ } from "./chunk-ZJXIOETW.js";
26
+ import {
27
+ a11yBadge,
28
+ a11yCheck,
29
+ a11yFix,
30
+ a11yPreDeploy
31
+ } from "./chunk-FWLLGLD5.js";
32
+ import {
33
+ createSeoCommand
34
+ } from "./chunk-JF7JCK6H.js";
35
+ import "./chunk-3ASILTFB.js";
23
36
  import {
24
37
  init,
25
38
  isInitialized
26
- } from "./chunk-54ATBLYE.js";
39
+ } from "./chunk-P666JE3G.js";
27
40
  import {
28
41
  parallelClean,
42
+ parallelExecuteCloud,
29
43
  parallelMerge,
30
44
  parallelRunWaves,
31
45
  parallelSchedule,
32
46
  parallelStatus
33
- } from "./chunk-LPSS2U5V.js";
47
+ } from "./chunk-NCPHO54C.js";
34
48
  import {
35
49
  DependencyParser,
36
50
  EnvironmentConfigLoader,
37
51
  EnvironmentValidator,
52
+ execute
53
+ } from "./chunk-EKU62MGC.js";
54
+ import {
38
55
  cloudCancel,
39
56
  cloudLogs,
40
57
  cloudStatus,
41
- execute
42
- } from "./chunk-E7ZTIAQM.js";
58
+ createAuthedSupabaseClient
59
+ } from "./chunk-4YEJ26F7.js";
43
60
  import {
44
61
  list
45
- } from "./chunk-WZIRUPMP.js";
62
+ } from "./chunk-NJF6MRTR.js";
46
63
  import {
47
64
  listLocalAtoms,
48
65
  loadAtom,
49
66
  plan
50
- } from "./chunk-LHCXE6UL.js";
67
+ } from "./chunk-3PZ7WU5I.js";
51
68
  import {
52
69
  ArchitectureParser
53
70
  } from "./chunk-5EVHUDQX.js";
54
71
  import {
55
72
  bugReport
56
- } from "./chunk-2QIXLBAC.js";
57
- import {
58
- ArchitectAgent
59
- } from "./chunk-ER4ADSWH.js";
60
- import "./chunk-NIKN37AY.js";
61
- import "./chunk-LXXTCZ2Q.js";
73
+ } from "./chunk-VF2OTDMS.js";
74
+ import "./chunk-5CFGPXQ3.js";
75
+ import "./chunk-2NSWZDP7.js";
76
+ import "./chunk-HJARQDQR.js";
77
+ import "./chunk-UFR2LX6G.js";
62
78
  import {
63
79
  addKey,
64
80
  listKeys,
65
81
  removeKey,
66
82
  setPrimaryKey
67
- } from "./chunk-TRLP7RMZ.js";
83
+ } from "./chunk-75J2JMU3.js";
68
84
  import "./chunk-TFSHS7EN.js";
69
85
  import "./chunk-RDG5BUED.js";
70
86
  import {
71
87
  login,
72
88
  logout,
73
89
  status
74
- } from "./chunk-FA2GAZ7L.js";
90
+ } from "./chunk-CZCY63EY.js";
91
+ import {
92
+ API_URL,
93
+ SUPABASE_ANON_KEY,
94
+ SUPABASE_URL
95
+ } from "./chunk-M4LGRTLC.js";
75
96
  import {
76
97
  handleTierSetup,
77
98
  promptTierSelection,
78
99
  updateUserTier
79
- } from "./chunk-DUJOT5B6.js";
100
+ } from "./chunk-LBBHM4I5.js";
80
101
  import {
81
- createAuthedSupabaseClient,
82
102
  getAuthToken,
83
103
  loadConfig,
84
104
  saveConfig
85
- } from "./chunk-SUGIWSCB.js";
86
- import {
87
- API_URL,
88
- SUPABASE_ANON_KEY,
89
- SUPABASE_URL
90
- } from "./chunk-M4LGRTLC.js";
91
- import "./chunk-QGM4M3NI.js";
105
+ } from "./chunk-SVU7MLG6.js";
106
+ import "./chunk-4VNS5WPM.js";
92
107
 
93
108
  // src/cli/index.ts
94
- import { Command as Command4 } from "commander";
95
- import chalk19 from "chalk";
109
+ import { Command as Command2 } from "commander";
110
+ import chalk17 from "chalk";
96
111
  import "dotenv/config";
97
112
 
98
113
  // src/cli/promote.ts
@@ -313,8 +328,8 @@ function formatDateTime(date) {
313
328
  // src/cli/start.ts
314
329
  import chalk6 from "chalk";
315
330
  import readline from "readline";
316
- import { existsSync as existsSync5, readFileSync as readFileSync2, readdirSync as readdirSync2, appendFileSync } from "fs";
317
- import { join as join5 } from "path";
331
+ import { existsSync as existsSync6, readFileSync as readFileSync3, readdirSync as readdirSync3, appendFileSync } from "fs";
332
+ import { join as join6 } from "path";
318
333
 
319
334
  // src/core/context/manager.ts
320
335
  import { existsSync as existsSync2 } from "fs";
@@ -2617,6 +2632,87 @@ function summarizeGeneration(result) {
2617
2632
  return lines.join("\n");
2618
2633
  }
2619
2634
 
2635
+ // src/core/web/detect.ts
2636
+ import { existsSync as existsSync5, readdirSync as readdirSync2, readFileSync as readFileSync2 } from "fs";
2637
+ import { join as join5 } from "path";
2638
+ var FRAMEWORK_MARKERS = [
2639
+ { name: "Next.js", files: ["next.config.js", "next.config.mjs"], deps: ["next"] },
2640
+ { name: "Astro", files: ["astro.config.mjs", "astro.config.ts"], deps: ["astro"] },
2641
+ { name: "Vite", files: ["vite.config.ts", "vite.config.js", "vite.config.mjs"], deps: ["vite"] },
2642
+ { name: "Svelte", files: ["svelte.config.js", "svelte.config.ts"], deps: ["svelte"] },
2643
+ { name: "Vue", files: ["vue.config.js"], deps: ["vue", "nuxt", "vitepress"] },
2644
+ { name: "Nuxt", files: ["nuxt.config.ts", "nuxt.config.js"], deps: ["nuxt"] },
2645
+ { name: "Gatsby", files: ["gatsby-config.js", "gatsby-config.ts"], deps: ["gatsby"] },
2646
+ { name: "Remix", files: ["remix.config.js", "remix.config.ts"], deps: ["@remix-run/react"] },
2647
+ { name: "Angular", files: ["angular.json"], deps: ["@angular/core"] },
2648
+ { name: "React", deps: ["react", "react-dom"] },
2649
+ { name: "Solid", deps: ["solid-js"] }
2650
+ ];
2651
+ var HTML_MARKERS = [
2652
+ "index.html",
2653
+ join5("public", "index.html"),
2654
+ join5("src", "index.html")
2655
+ ];
2656
+ function readPackageJson(cwd) {
2657
+ const pkgPath = join5(cwd, "package.json");
2658
+ if (!existsSync5(pkgPath)) {
2659
+ return null;
2660
+ }
2661
+ try {
2662
+ const content = readFileSync2(pkgPath, "utf-8");
2663
+ return JSON.parse(content);
2664
+ } catch {
2665
+ return null;
2666
+ }
2667
+ }
2668
+ function getDeps(pkg) {
2669
+ if (!pkg) return /* @__PURE__ */ new Set();
2670
+ const deps = pkg["dependencies"] ?? {};
2671
+ const devDeps = pkg["devDependencies"] ?? {};
2672
+ return /* @__PURE__ */ new Set([...Object.keys(deps), ...Object.keys(devDeps)]);
2673
+ }
2674
+ function hasHtmlLikeFiles(cwd, dir) {
2675
+ const target = join5(cwd, dir);
2676
+ if (!existsSync5(target)) return false;
2677
+ try {
2678
+ const entries = readdirSync2(target, { withFileTypes: true });
2679
+ return entries.some((entry) => {
2680
+ if (!entry.isFile()) return false;
2681
+ return entry.name.endsWith(".html") || entry.name.endsWith(".astro") || entry.name.endsWith(".svelte") || entry.name.endsWith(".vue");
2682
+ });
2683
+ } catch {
2684
+ return false;
2685
+ }
2686
+ }
2687
+ function detectWebProject(cwd) {
2688
+ const frameworks = [];
2689
+ const reasons = [];
2690
+ const pkg = readPackageJson(cwd);
2691
+ const deps = getDeps(pkg);
2692
+ for (const marker of FRAMEWORK_MARKERS) {
2693
+ const hasMarkerFile = marker.files?.some((file) => existsSync5(join5(cwd, file))) ?? false;
2694
+ const hasDep = marker.deps?.some((dep) => deps.has(dep)) ?? false;
2695
+ if (hasMarkerFile || hasDep) {
2696
+ frameworks.push(marker.name);
2697
+ reasons.push(`${marker.name} detected`);
2698
+ }
2699
+ }
2700
+ const hasHtml = HTML_MARKERS.some((file) => existsSync5(join5(cwd, file)));
2701
+ if (hasHtml) {
2702
+ reasons.push("HTML entrypoint detected");
2703
+ }
2704
+ const hasWebDirs = hasHtmlLikeFiles(cwd, "src") || hasHtmlLikeFiles(cwd, "public") || hasHtmlLikeFiles(cwd, "pages") || hasHtmlLikeFiles(cwd, "app");
2705
+ if (hasWebDirs) {
2706
+ reasons.push("Web template files detected");
2707
+ }
2708
+ const isWebProject = reasons.length > 0;
2709
+ return {
2710
+ isWebProject,
2711
+ frameworks: Array.from(new Set(frameworks)),
2712
+ reasons
2713
+ };
2714
+ }
2715
+
2620
2716
  // src/cli/start.ts
2621
2717
  async function start(options = {}) {
2622
2718
  const cwd = process.cwd();
@@ -2637,7 +2733,7 @@ async function start(options = {}) {
2637
2733
  }
2638
2734
  }
2639
2735
  if (!config.tier || config.tier === "FREE") {
2640
- const isFirstRun = !existsSync5(join5(cwd, ".archon")) && !existsSync5(join5(cwd, "ARCHITECTURE.md"));
2736
+ const isFirstRun = !existsSync6(join6(cwd, ".archon")) && !existsSync6(join6(cwd, "ARCHITECTURE.md"));
2641
2737
  if (isFirstRun && !config.tierConfirmed) {
2642
2738
  console.log(chalk6.bold("How would you like to use ArchonDev?\n"));
2643
2739
  const selection = await promptTierSelection();
@@ -2708,7 +2804,7 @@ async function start(options = {}) {
2708
2804
  }
2709
2805
  }
2710
2806
  if (currentTier === "BYOK") {
2711
- const { keyManager } = await import("./keys-SXJ6MKPY.js");
2807
+ const { keyManager } = await import("./keys-THCHXIFD.js");
2712
2808
  const hasKeys = await keyManager.hasAnyKey();
2713
2809
  if (!hasKeys) {
2714
2810
  console.log();
@@ -2721,22 +2817,22 @@ async function start(options = {}) {
2721
2817
  const choice = await promptWithCommands("What would you like to do?");
2722
2818
  switch (choice) {
2723
2819
  case "1":
2724
- const { handleTierSetup: handleTierSetup2 } = await import("./tier-selection-Z2RFHZUX.js");
2820
+ const { handleTierSetup: handleTierSetup2 } = await import("./tier-selection-426HA765.js");
2725
2821
  await handleTierSetup2("BYOK");
2726
2822
  break;
2727
2823
  case "2":
2728
- const { updateUserTier: updateUserTier2 } = await import("./tier-selection-Z2RFHZUX.js");
2824
+ const { updateUserTier: updateUserTier2 } = await import("./tier-selection-426HA765.js");
2729
2825
  const result = await updateUserTier2("CREDITS");
2730
2826
  if (result.success) {
2731
2827
  config.tier = "CREDITS";
2732
2828
  await saveConfig(config);
2733
2829
  console.log(chalk6.green("\u2713 Switched to Managed Plan"));
2734
- const { handleTierSetup: setupCredits } = await import("./tier-selection-Z2RFHZUX.js");
2830
+ const { handleTierSetup: setupCredits } = await import("./tier-selection-426HA765.js");
2735
2831
  await setupCredits("CREDITS");
2736
2832
  }
2737
2833
  break;
2738
2834
  case "3":
2739
- const { updateUserTier: downgrade } = await import("./tier-selection-Z2RFHZUX.js");
2835
+ const { updateUserTier: downgrade } = await import("./tier-selection-426HA765.js");
2740
2836
  const downgradeResult = await downgrade("FREE");
2741
2837
  if (downgradeResult.success) {
2742
2838
  config.tier = "FREE";
@@ -2757,7 +2853,7 @@ async function start(options = {}) {
2757
2853
  const projectState = detectProjectState(cwd);
2758
2854
  if (!projectState.hasArchitecture) {
2759
2855
  console.log(chalk6.dim("No project initialized in this folder.\n"));
2760
- const { init: init2 } = await import("./init-PSMJLDEZ.js");
2856
+ const { init: init2 } = await import("./init-FINETS3Q.js");
2761
2857
  await init2({ analyze: true, git: true });
2762
2858
  console.log();
2763
2859
  const newProjectState = detectProjectState(cwd);
@@ -2766,6 +2862,7 @@ async function start(options = {}) {
2766
2862
  const governanceStatus = await gatherGovernanceStatus(cwd);
2767
2863
  displayGovernanceStatus(governanceStatus);
2768
2864
  }
2865
+ await maybePromptWebChecks(cwd, projectState);
2769
2866
  const contextManager = new ContextManager();
2770
2867
  const pendingAtomsData = await contextManager.getPendingAtomsData(cwd);
2771
2868
  if (pendingAtomsData && pendingAtomsData.atoms.length > 0) {
@@ -2815,7 +2912,7 @@ function formatTierName(tier) {
2815
2912
  }
2816
2913
  async function fetchCreditsUsageStats(accessToken) {
2817
2914
  try {
2818
- const { API_URL: API_URL3 } = await import("./constants-AHP5F7HW.js");
2915
+ const { API_URL: API_URL3 } = await import("./constants-XDIWFFPN.js");
2819
2916
  const response = await fetch(`${API_URL3}/api/usage`, {
2820
2917
  headers: {
2821
2918
  "Authorization": `Bearer ${accessToken}`
@@ -2855,14 +2952,14 @@ function detectProjectState(cwd) {
2855
2952
  const sourceExtensions = [".ts", ".tsx", ".js", ".jsx", ".py", ".go", ".rs", ".java", ".rb", ".php"];
2856
2953
  let hasSourceFiles = false;
2857
2954
  for (const dir of sourceDirs) {
2858
- if (existsSync5(join5(cwd, dir))) {
2955
+ if (existsSync6(join6(cwd, dir))) {
2859
2956
  hasSourceFiles = true;
2860
2957
  break;
2861
2958
  }
2862
2959
  }
2863
2960
  if (!hasSourceFiles) {
2864
2961
  try {
2865
- const files = readdirSync2(cwd);
2962
+ const files = readdirSync3(cwd);
2866
2963
  hasSourceFiles = files.some(
2867
2964
  (f) => sourceExtensions.some((ext) => f.endsWith(ext))
2868
2965
  );
@@ -2871,16 +2968,16 @@ function detectProjectState(cwd) {
2871
2968
  }
2872
2969
  const projectMarkers = ["package.json", "Cargo.toml", "pyproject.toml", "go.mod", "pom.xml", "build.gradle"];
2873
2970
  if (!hasSourceFiles) {
2874
- hasSourceFiles = projectMarkers.some((marker) => existsSync5(join5(cwd, marker)));
2971
+ hasSourceFiles = projectMarkers.some((marker) => existsSync6(join6(cwd, marker)));
2875
2972
  }
2876
- const hasArchitecture = existsSync5(join5(cwd, "ARCHITECTURE.md"));
2877
- const hasProgress = existsSync5(join5(cwd, "progress.txt"));
2878
- const hasReviewDb = existsSync5(join5(cwd, "docs", "code-review", "review-tasks.db"));
2973
+ const hasArchitecture = existsSync6(join6(cwd, "ARCHITECTURE.md"));
2974
+ const hasProgress = existsSync6(join6(cwd, "progress.txt"));
2975
+ const hasReviewDb = existsSync6(join6(cwd, "docs", "code-review", "review-tasks.db"));
2879
2976
  let hasProgressEntries = false;
2880
2977
  let lastProgressEntry;
2881
2978
  if (hasProgress) {
2882
2979
  try {
2883
- const progressContent = readFileSync2(join5(cwd, "progress.txt"), "utf-8");
2980
+ const progressContent = readFileSync3(join6(cwd, "progress.txt"), "utf-8");
2884
2981
  const entries = progressContent.match(/^## \d{4}-\d{2}-\d{2}/gm);
2885
2982
  hasProgressEntries = entries !== null && entries.length > 0;
2886
2983
  if (hasProgressEntries) {
@@ -2901,6 +2998,7 @@ function detectProjectState(cwd) {
2901
2998
  } else {
2902
2999
  scenario = "NEW_PROJECT";
2903
3000
  }
3001
+ const webDetection = detectWebProject(cwd);
2904
3002
  return {
2905
3003
  scenario,
2906
3004
  hasSourceFiles,
@@ -2908,7 +3006,9 @@ function detectProjectState(cwd) {
2908
3006
  hasProgress,
2909
3007
  hasProgressEntries,
2910
3008
  hasReviewDb,
2911
- lastProgressEntry
3009
+ lastProgressEntry,
3010
+ isWebProject: webDetection.isWebProject,
3011
+ webFrameworks: webDetection.frameworks
2912
3012
  };
2913
3013
  }
2914
3014
  async function gatherGovernanceStatus(cwd) {
@@ -2919,8 +3019,8 @@ async function gatherGovernanceStatus(cwd) {
2919
3019
  dependencyRulesCount: 0,
2920
3020
  pendingAtomsCount: 0
2921
3021
  };
2922
- const archPath = join5(cwd, "ARCHITECTURE.md");
2923
- if (existsSync5(archPath)) {
3022
+ const archPath = join6(cwd, "ARCHITECTURE.md");
3023
+ if (existsSync6(archPath)) {
2924
3024
  const parser = new ArchitectureParser(archPath);
2925
3025
  const result = await parser.parse();
2926
3026
  if (result.success && result.schema) {
@@ -2937,10 +3037,10 @@ async function gatherGovernanceStatus(cwd) {
2937
3037
  status2.dependencyRulesCount = depResult.document.rules.length;
2938
3038
  }
2939
3039
  }
2940
- const progressPath = join5(cwd, "progress.txt");
2941
- if (existsSync5(progressPath)) {
3040
+ const progressPath = join6(cwd, "progress.txt");
3041
+ if (existsSync6(progressPath)) {
2942
3042
  try {
2943
- const content = readFileSync2(progressPath, "utf-8");
3043
+ const content = readFileSync3(progressPath, "utf-8");
2944
3044
  const dateMatches = content.match(/^## (\d{4}-\d{2}-\d{2})/gm);
2945
3045
  if (dateMatches && dateMatches.length > 0) {
2946
3046
  const lastMatch = dateMatches[dateMatches.length - 1];
@@ -2952,10 +3052,10 @@ async function gatherGovernanceStatus(cwd) {
2952
3052
  } catch {
2953
3053
  }
2954
3054
  }
2955
- const atomsDir = join5(cwd, ".archon", "atoms");
2956
- if (existsSync5(atomsDir)) {
3055
+ const atomsDir = join6(cwd, ".archon", "atoms");
3056
+ if (existsSync6(atomsDir)) {
2957
3057
  try {
2958
- const files = readdirSync2(atomsDir);
3058
+ const files = readdirSync3(atomsDir);
2959
3059
  status2.pendingAtomsCount = files.filter((f) => f.endsWith(".yaml") || f.endsWith(".yml")).length;
2960
3060
  } catch {
2961
3061
  }
@@ -2985,7 +3085,7 @@ async function handleNewProject(cwd, _state) {
2985
3085
  }
2986
3086
  if (intent.mode === "ad_hoc" && intent.confidence >= 0.7) {
2987
3087
  console.log(chalk6.dim("\n> Got it! Creating a task for this...\n"));
2988
- const { plan: plan2 } = await import("./plan-X77BUKNE.js");
3088
+ const { plan: plan2 } = await import("./plan-XALA4SLH.js");
2989
3089
  await plan2(initialResponse, {});
2990
3090
  return;
2991
3091
  }
@@ -3009,7 +3109,7 @@ async function handleNewProject(cwd, _state) {
3009
3109
  break;
3010
3110
  case "2":
3011
3111
  console.log(chalk6.dim("\n> Creating a task for this...\n"));
3012
- const { plan: plan2 } = await import("./plan-X77BUKNE.js");
3112
+ const { plan: plan2 } = await import("./plan-XALA4SLH.js");
3013
3113
  await plan2(initialResponse, {});
3014
3114
  break;
3015
3115
  case "3":
@@ -3039,7 +3139,7 @@ async function showNewProjectMenu(cwd) {
3039
3139
  case "3": {
3040
3140
  const description = await prompt("Describe what you want to do");
3041
3141
  if (description.trim()) {
3042
- const { plan: plan2 } = await import("./plan-X77BUKNE.js");
3142
+ const { plan: plan2 } = await import("./plan-XALA4SLH.js");
3043
3143
  await plan2(description, {});
3044
3144
  }
3045
3145
  break;
@@ -3105,7 +3205,7 @@ async function runExploreFlow(cwd) {
3105
3205
  case "1": {
3106
3206
  const description = await prompt("Describe what you want to do");
3107
3207
  if (description.trim()) {
3108
- const { plan: plan2 } = await import("./plan-X77BUKNE.js");
3208
+ const { plan: plan2 } = await import("./plan-XALA4SLH.js");
3109
3209
  await plan2(description, {});
3110
3210
  }
3111
3211
  break;
@@ -3132,12 +3232,12 @@ async function gatherProjectInfo(cwd) {
3132
3232
  invariantsCount: 0,
3133
3233
  protectedPathsCount: 0
3134
3234
  };
3135
- const packageJsonPath = join5(cwd, "package.json");
3136
- if (existsSync5(packageJsonPath)) {
3235
+ const packageJsonPath = join6(cwd, "package.json");
3236
+ if (existsSync6(packageJsonPath)) {
3137
3237
  try {
3138
- const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
3238
+ const packageJson = JSON.parse(readFileSync3(packageJsonPath, "utf-8"));
3139
3239
  info.name = packageJson.name;
3140
- info.packageManager = existsSync5(join5(cwd, "pnpm-lock.yaml")) ? "pnpm" : existsSync5(join5(cwd, "yarn.lock")) ? "yarn" : "npm";
3240
+ info.packageManager = existsSync6(join6(cwd, "pnpm-lock.yaml")) ? "pnpm" : existsSync6(join6(cwd, "yarn.lock")) ? "yarn" : "npm";
3141
3241
  const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
3142
3242
  if (deps["next"]) info.framework = "Next.js";
3143
3243
  else if (deps["react"]) info.framework = "React";
@@ -3145,7 +3245,7 @@ async function gatherProjectInfo(cwd) {
3145
3245
  else if (deps["svelte"]) info.framework = "Svelte";
3146
3246
  else if (deps["express"]) info.framework = "Express";
3147
3247
  else if (deps["fastify"]) info.framework = "Fastify";
3148
- if (deps["typescript"] || existsSync5(join5(cwd, "tsconfig.json"))) {
3248
+ if (deps["typescript"] || existsSync6(join6(cwd, "tsconfig.json"))) {
3149
3249
  info.language = "TypeScript";
3150
3250
  } else {
3151
3251
  info.language = "JavaScript";
@@ -3153,25 +3253,25 @@ async function gatherProjectInfo(cwd) {
3153
3253
  } catch {
3154
3254
  }
3155
3255
  }
3156
- if (existsSync5(join5(cwd, "Cargo.toml"))) {
3256
+ if (existsSync6(join6(cwd, "Cargo.toml"))) {
3157
3257
  info.language = "Rust";
3158
3258
  info.packageManager = "cargo";
3159
- } else if (existsSync5(join5(cwd, "go.mod"))) {
3259
+ } else if (existsSync6(join6(cwd, "go.mod"))) {
3160
3260
  info.language = "Go";
3161
3261
  info.packageManager = "go";
3162
- } else if (existsSync5(join5(cwd, "pyproject.toml")) || existsSync5(join5(cwd, "requirements.txt"))) {
3262
+ } else if (existsSync6(join6(cwd, "pyproject.toml")) || existsSync6(join6(cwd, "requirements.txt"))) {
3163
3263
  info.language = "Python";
3164
- info.packageManager = existsSync5(join5(cwd, "pyproject.toml")) ? "poetry/pip" : "pip";
3264
+ info.packageManager = existsSync6(join6(cwd, "pyproject.toml")) ? "poetry/pip" : "pip";
3165
3265
  }
3166
3266
  const sourceDirNames = ["src", "lib", "app", "packages", "components", "pages", "api"];
3167
3267
  const sourceExtensions = [".ts", ".tsx", ".js", ".jsx", ".py", ".go", ".rs"];
3168
3268
  for (const dir of sourceDirNames) {
3169
- if (existsSync5(join5(cwd, dir))) {
3269
+ if (existsSync6(join6(cwd, dir))) {
3170
3270
  info.sourceDirs.push(dir);
3171
3271
  }
3172
3272
  }
3173
3273
  try {
3174
- const files = readdirSync2(cwd);
3274
+ const files = readdirSync3(cwd);
3175
3275
  for (const file of files) {
3176
3276
  if (sourceExtensions.some((ext) => file.endsWith(ext))) {
3177
3277
  if (file.includes(".test.") || file.includes(".spec.") || file.includes("_test.")) {
@@ -3183,7 +3283,7 @@ async function gatherProjectInfo(cwd) {
3183
3283
  }
3184
3284
  for (const dir of info.sourceDirs) {
3185
3285
  try {
3186
- const dirFiles = readdirSync2(join5(cwd, dir));
3286
+ const dirFiles = readdirSync3(join6(cwd, dir));
3187
3287
  for (const file of dirFiles) {
3188
3288
  if (sourceExtensions.some((ext) => file.endsWith(ext))) {
3189
3289
  if (file.includes(".test.") || file.includes(".spec.") || file.includes("_test.")) {
@@ -3198,10 +3298,10 @@ async function gatherProjectInfo(cwd) {
3198
3298
  }
3199
3299
  } catch {
3200
3300
  }
3201
- info.hasArchitecture = existsSync5(join5(cwd, "ARCHITECTURE.md"));
3202
- info.hasProgress = existsSync5(join5(cwd, "progress.txt"));
3301
+ info.hasArchitecture = existsSync6(join6(cwd, "ARCHITECTURE.md"));
3302
+ info.hasProgress = existsSync6(join6(cwd, "progress.txt"));
3203
3303
  if (info.hasArchitecture) {
3204
- const archPath = join5(cwd, "ARCHITECTURE.md");
3304
+ const archPath = join6(cwd, "ARCHITECTURE.md");
3205
3305
  const parser = new ArchitectureParser(archPath);
3206
3306
  const result = await parser.parse();
3207
3307
  if (result.success && result.schema) {
@@ -3213,7 +3313,7 @@ async function gatherProjectInfo(cwd) {
3213
3313
  return info;
3214
3314
  }
3215
3315
  async function runConversationalInterview(cwd, initialMessage) {
3216
- const { InterviewerAgent, createInterviewerAgent } = await import("./interviewer-Q6PFSAGT.js");
3316
+ const { InterviewerAgent, createInterviewerAgent } = await import("./interviewer-NQHNMVH4.js");
3217
3317
  const agent = await createInterviewerAgent();
3218
3318
  if (agent && agent.isAvailable()) {
3219
3319
  await runAIInterview(cwd, initialMessage, agent);
@@ -3341,8 +3441,8 @@ ${state.forbiddenPatterns?.length ? `- **Forbidden patterns:** ${state.forbidden
3341
3441
  - Vision and stack recorded in progress.txt
3342
3442
  - Ready for first atom
3343
3443
  `;
3344
- const progressPath = join5(cwd, "progress.txt");
3345
- if (!existsSync5(progressPath)) {
3444
+ const progressPath = join6(cwd, "progress.txt");
3445
+ if (!existsSync6(progressPath)) {
3346
3446
  const { writeFileSync: writeFileSync2 } = await import("fs");
3347
3447
  writeFileSync2(progressPath, "# ArchonDev Progress Log\n\nThis file tracks learnings and decisions across sessions.\n");
3348
3448
  }
@@ -3364,15 +3464,15 @@ ${state.forbiddenPatterns?.length ? `- **Forbidden patterns:** ${state.forbidden
3364
3464
  if (continueChoice) {
3365
3465
  const description = await prompt("Describe what you want to build first");
3366
3466
  if (description.trim()) {
3367
- const { plan: plan2 } = await import("./plan-X77BUKNE.js");
3467
+ const { plan: plan2 } = await import("./plan-XALA4SLH.js");
3368
3468
  await plan2(description, {});
3369
3469
  }
3370
3470
  }
3371
3471
  }
3372
3472
  async function quickStart(cwd) {
3373
3473
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
3374
- const progressPath = join5(cwd, "progress.txt");
3375
- if (!existsSync5(progressPath)) {
3474
+ const progressPath = join6(cwd, "progress.txt");
3475
+ if (!existsSync6(progressPath)) {
3376
3476
  const { writeFileSync: writeFileSync2 } = await import("fs");
3377
3477
  writeFileSync2(progressPath, `# ArchonDev Progress Log
3378
3478
 
@@ -3418,7 +3518,7 @@ async function handleAdaptExisting(cwd, state) {
3418
3518
  }
3419
3519
  if (intent.mode === "ad_hoc" && intent.confidence >= 0.7) {
3420
3520
  console.log(chalk6.dim("\n> Got it! Creating a task for this...\n"));
3421
- const { plan: plan2 } = await import("./plan-X77BUKNE.js");
3521
+ const { plan: plan2 } = await import("./plan-XALA4SLH.js");
3422
3522
  await plan2(response, {});
3423
3523
  return;
3424
3524
  }
@@ -3449,7 +3549,7 @@ async function showAdaptExistingMenu(cwd, state) {
3449
3549
  case "2": {
3450
3550
  const description = await prompt("Describe what you want to do");
3451
3551
  if (description.trim()) {
3452
- const { plan: plan2 } = await import("./plan-X77BUKNE.js");
3552
+ const { plan: plan2 } = await import("./plan-XALA4SLH.js");
3453
3553
  await plan2(description, {});
3454
3554
  }
3455
3555
  break;
@@ -3474,11 +3574,11 @@ async function showAdaptExistingMenu(cwd, state) {
3474
3574
  }
3475
3575
  async function analyzeAndAdapt(cwd) {
3476
3576
  console.log(chalk6.blue("\n-- Analyzing Project --\n"));
3477
- const { init: init2 } = await import("./init-PSMJLDEZ.js");
3577
+ const { init: init2 } = await import("./init-FINETS3Q.js");
3478
3578
  await init2({ analyze: true, git: true });
3479
3579
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
3480
- const progressPath = join5(cwd, "progress.txt");
3481
- if (!existsSync5(progressPath)) {
3580
+ const progressPath = join6(cwd, "progress.txt");
3581
+ if (!existsSync6(progressPath)) {
3482
3582
  const { writeFileSync: writeFileSync2 } = await import("fs");
3483
3583
  writeFileSync2(progressPath, "# ArchonDev Progress Log\n\nThis file tracks learnings and decisions across sessions.\n");
3484
3584
  }
@@ -3501,9 +3601,9 @@ async function analyzeAndAdapt(cwd) {
3501
3601
  async function codeReviewFirst(cwd) {
3502
3602
  console.log(chalk6.blue("\n-- Code Review Mode --\n"));
3503
3603
  console.log(chalk6.dim("I'll analyze your code for issues without making any changes.\n"));
3504
- const { reviewInit: reviewInit2, reviewAnalyze: reviewAnalyze2, reviewRun: reviewRun2 } = await import("./review-T4ID2QUF.js");
3505
- const reviewDbPath = join5(cwd, "docs", "code-review", "review-tasks.db");
3506
- if (!existsSync5(reviewDbPath)) {
3604
+ const { reviewInit: reviewInit2, reviewAnalyze: reviewAnalyze2, reviewRun: reviewRun2 } = await import("./review-AUG6GIL6.js");
3605
+ const reviewDbPath = join6(cwd, "docs", "code-review", "review-tasks.db");
3606
+ if (!existsSync6(reviewDbPath)) {
3507
3607
  await reviewInit2();
3508
3608
  }
3509
3609
  await reviewAnalyze2();
@@ -3537,9 +3637,9 @@ async function handleContinueSession(cwd, state) {
3537
3637
  }
3538
3638
  function checkForHandoff(cwd) {
3539
3639
  try {
3540
- const progressPath = join5(cwd, "progress.txt");
3541
- if (!existsSync5(progressPath)) return null;
3542
- const content = readFileSync2(progressPath, "utf-8");
3640
+ const progressPath = join6(cwd, "progress.txt");
3641
+ if (!existsSync6(progressPath)) return null;
3642
+ const content = readFileSync3(progressPath, "utf-8");
3543
3643
  const handoffMatch = content.match(/## Context Handoff[^\n]*\n([\s\S]*?)(?=\n## |\n*$)/);
3544
3644
  if (handoffMatch && handoffMatch[1]) {
3545
3645
  const handoffContent = handoffMatch[1];
@@ -3556,6 +3656,15 @@ async function showMainMenu() {
3556
3656
  const cwd = process.cwd();
3557
3657
  const state = detectProjectState(cwd);
3558
3658
  console.log(chalk6.bold("What would you like to do?\n"));
3659
+ if (state.isWebProject) {
3660
+ const { loadWebChecks, formatWebCheckStatus } = await import("./web-checks-4BSYXWDF.js");
3661
+ const prefs = await loadWebChecks(cwd);
3662
+ console.log(chalk6.dim("Web checks status:"));
3663
+ console.log(chalk6.dim(` A11y: ${formatWebCheckStatus(prefs.lastRun?.a11y)}`));
3664
+ console.log(chalk6.dim(` SEO: ${formatWebCheckStatus(prefs.lastRun?.seo)}`));
3665
+ console.log(chalk6.dim(` GEO: ${formatWebCheckStatus(prefs.lastRun?.geo)}`));
3666
+ console.log();
3667
+ }
3559
3668
  const choices = [
3560
3669
  { key: "1", label: "Plan a new task", action: () => planTask() },
3561
3670
  { key: "2", label: "List atoms", action: () => listAtoms() },
@@ -3563,9 +3672,13 @@ async function showMainMenu() {
3563
3672
  { key: "4", label: "Report a bug", action: () => reportBug() },
3564
3673
  { key: "5", label: "View status", action: () => viewStatus() },
3565
3674
  { key: "6", label: "Code Review", action: () => reviewCode() },
3675
+ ...state.isWebProject ? [{ key: "w", label: "Web checks (SEO/GEO/A11y)", action: async () => {
3676
+ await showWebChecksMenu();
3677
+ await showMainMenu();
3678
+ } }] : [],
3566
3679
  { key: "7", label: "Settings & Preferences", action: () => settingsMenu() },
3567
3680
  { key: "8", label: "Upgrade tier", action: async () => {
3568
- const { showUpgradeMenu } = await import("./tier-selection-Z2RFHZUX.js");
3681
+ const { showUpgradeMenu } = await import("./tier-selection-426HA765.js");
3569
3682
  await showUpgradeMenu();
3570
3683
  await showMainMenu();
3571
3684
  } },
@@ -3587,7 +3700,7 @@ async function showMainMenu() {
3587
3700
  }
3588
3701
  async function showReviewProgress(cwd) {
3589
3702
  try {
3590
- const { ReviewDatabase } = await import("./code-review-ORCNXANW.js");
3703
+ const { ReviewDatabase } = await import("./code-review-6MU4UE5M.js");
3591
3704
  const db = new ReviewDatabase(cwd);
3592
3705
  db.open();
3593
3706
  const stats = db.getStats();
@@ -3604,23 +3717,24 @@ async function showReviewProgress(cwd) {
3604
3717
  }
3605
3718
  }
3606
3719
  async function planTask() {
3607
- const { plan: plan2 } = await import("./plan-X77BUKNE.js");
3720
+ const { plan: plan2 } = await import("./plan-XALA4SLH.js");
3608
3721
  const description = await prompt("Describe what you want to build");
3609
3722
  if (description.trim()) {
3610
3723
  await plan2(description, {});
3611
3724
  }
3612
3725
  }
3613
3726
  async function listAtoms() {
3614
- const { list: list2 } = await import("./list-MMKB5TGX.js");
3727
+ const { list: list2 } = await import("./list-CNKAH354.js");
3615
3728
  await list2({});
3616
3729
  }
3617
3730
  async function executeNext() {
3618
- const { listLocalAtoms: listLocalAtoms2 } = await import("./plan-X77BUKNE.js");
3619
- const { analyzeProject, getComplexityDescription, getModeDescription } = await import("./orchestration-X6LHSHBJ.js");
3620
- const { loadExecutionPreferences } = await import("./preferences-TWEK2RWY.js");
3731
+ const { listLocalAtoms: listLocalAtoms2 } = await import("./plan-XALA4SLH.js");
3732
+ const { analyzeProject, getComplexityDescription, getModeDescription } = await import("./orchestration-HIF3KP25.js");
3733
+ const { loadExecutionPreferences } = await import("./preferences-I6WETXOI.js");
3621
3734
  const cwd = process.cwd();
3622
3735
  const atoms = await listLocalAtoms2();
3623
3736
  const pendingAtoms = atoms.filter((a) => a.status === "READY" || a.status === "IN_PROGRESS");
3737
+ const readyAtoms = atoms.filter((a) => a.status === "READY");
3624
3738
  if (pendingAtoms.length === 0) {
3625
3739
  console.log(chalk6.yellow('No pending atoms. Use "archon plan" to create one.'));
3626
3740
  return;
@@ -3628,56 +3742,103 @@ async function executeNext() {
3628
3742
  if (pendingAtoms.length > 1) {
3629
3743
  const analysis = analyzeProject(pendingAtoms);
3630
3744
  const prefs = await loadExecutionPreferences(cwd);
3745
+ const config = await loadConfig();
3746
+ const canUseCloud = (config.tier ?? "FREE") === "CREDITS";
3631
3747
  console.log(chalk6.blue("\n-- Project Analysis --\n"));
3632
3748
  console.log(` ${chalk6.bold("Atoms:")} ${analysis.atomCount}`);
3633
3749
  console.log(` ${chalk6.bold("Estimated:")} ${analysis.estimatedMinutes} minutes`);
3634
3750
  console.log(` ${chalk6.bold("Complexity:")} ${analysis.complexity} - ${getComplexityDescription(analysis.complexity)}`);
3635
3751
  console.log(` ${chalk6.bold("Suggested:")} ${analysis.suggestedMode} - ${getModeDescription(analysis.suggestedMode)}`);
3636
3752
  console.log();
3637
- if (analysis.suggestedMode !== "sequential" && prefs.parallelMode === "ask") {
3638
- const useParallel = await promptYesNo(`Use ${analysis.suggestedMode} execution?`, true);
3639
- if (useParallel) {
3640
- console.log(chalk6.green(`
3641
- \u2713 ${analysis.suggestedMode} execution selected`));
3642
- console.log(chalk6.dim("(Parallel/cloud execution coming soon - running sequentially for now)\n"));
3643
- }
3753
+ let selectedMode = "sequential";
3754
+ if (canUseCloud && prefs.cloudMode === "always" && analysis.suggestedMode === "parallel-cloud") {
3755
+ selectedMode = "parallel-cloud";
3756
+ console.log(chalk6.green(`
3757
+ \u2713 Auto-selected parallel cloud execution (preference: always)`));
3644
3758
  } else if (prefs.parallelMode === "always" && analysis.suggestedMode !== "sequential") {
3759
+ selectedMode = "parallel-local";
3645
3760
  console.log(chalk6.green(`
3646
- \u2713 Auto-selected ${analysis.suggestedMode} execution (preference: always)`));
3647
- console.log(chalk6.dim("(Parallel/cloud execution coming soon - running sequentially for now)\n"));
3761
+ \u2713 Auto-selected parallel local execution (preference: always)`));
3762
+ } else if (prefs.parallelMode === "ask" || canUseCloud && prefs.cloudMode === "ask") {
3763
+ const options = [
3764
+ { key: "1", label: "Sequential (local)" },
3765
+ { key: "2", label: "Parallel (local)" }
3766
+ ];
3767
+ if (canUseCloud) {
3768
+ options.push({ key: "3", label: "Parallel (cloud)" });
3769
+ }
3770
+ const choice = await promptChoice("Select execution mode", options);
3771
+ if (choice === "2") selectedMode = "parallel-local";
3772
+ if (choice === "3" && canUseCloud) selectedMode = "parallel-cloud";
3773
+ }
3774
+ if (selectedMode !== "sequential") {
3775
+ if (readyAtoms.length === 0) {
3776
+ console.log(chalk6.yellow("No READY atoms available for parallel execution."));
3777
+ return;
3778
+ }
3779
+ console.log(chalk6.dim("\nPending atoms:"));
3780
+ for (const atom of readyAtoms) {
3781
+ console.log(chalk6.dim(` - ${atom.id}: ${atom.title}`));
3782
+ }
3783
+ console.log();
3784
+ const raw = await prompt("Enter atom IDs to run in parallel (comma-separated, or press Enter for all)");
3785
+ const selectedIds = raw.trim() ? raw.split(",").map((s) => s.trim()).filter(Boolean) : readyAtoms.map((a) => a.id);
3786
+ if (selectedIds.length === 0) {
3787
+ console.log(chalk6.yellow("No atoms selected."));
3788
+ return;
3789
+ }
3790
+ let runIds = selectedIds;
3791
+ if (selectedIds.length > prefs.maxParallelAgents) {
3792
+ const override = await promptYesNo(
3793
+ `Selected ${selectedIds.length} atoms, but max parallel agents is ${prefs.maxParallelAgents}. Override for this run?`,
3794
+ false
3795
+ );
3796
+ if (!override) {
3797
+ runIds = selectedIds.slice(0, prefs.maxParallelAgents);
3798
+ console.log(chalk6.dim(`Running first ${runIds.length} atoms.`));
3799
+ }
3800
+ }
3801
+ if (selectedMode === "parallel-cloud") {
3802
+ const { parallelExecuteCloud: parallelExecuteCloud2 } = await import("./parallel-W2ETYYAL.js");
3803
+ await parallelExecuteCloud2(runIds);
3804
+ return;
3805
+ }
3806
+ const { parallelExecute } = await import("./parallel-W2ETYYAL.js");
3807
+ await parallelExecute(runIds);
3808
+ return;
3648
3809
  }
3649
3810
  }
3650
3811
  const atomId = await prompt("Enter atom ID to execute (or press Enter for first pending)");
3651
3812
  const targetId = atomId.trim() || pendingAtoms[0]?.id;
3652
3813
  if (targetId) {
3653
- const { execute: execute2 } = await import("./execute-73QW4ZEZ.js");
3814
+ const { execute: execute2 } = await import("./execute-MB4ZF3HQ.js");
3654
3815
  await execute2(targetId, {});
3655
3816
  } else {
3656
3817
  console.log(chalk6.yellow("No atom to execute."));
3657
3818
  }
3658
3819
  }
3659
3820
  async function reportBug() {
3660
- const { bugReport: bugReport2 } = await import("./bug-BJH4X5LI.js");
3821
+ const { bugReport: bugReport2 } = await import("./bug-5WRBCFRT.js");
3661
3822
  const title = await prompt("Bug title");
3662
3823
  if (title.trim()) {
3663
3824
  await bugReport2(title, {});
3664
3825
  }
3665
3826
  }
3666
3827
  async function viewStatus() {
3667
- const { status: status2 } = await import("./auth-KUFS3PBS.js");
3828
+ const { status: status2 } = await import("./auth-HQBAG4CR.js");
3668
3829
  await status2();
3669
3830
  }
3670
3831
  async function settingsMenu() {
3671
- const { interactiveSettings } = await import("./preferences-TWEK2RWY.js");
3832
+ const { interactiveSettings } = await import("./preferences-I6WETXOI.js");
3672
3833
  await interactiveSettings();
3673
3834
  await showMainMenu();
3674
3835
  }
3675
3836
  async function reviewCode() {
3676
3837
  const cwd = process.cwd();
3677
- const reviewDbPath = join5(cwd, "docs", "code-review", "review-tasks.db");
3678
- if (!existsSync5(reviewDbPath)) {
3838
+ const reviewDbPath = join6(cwd, "docs", "code-review", "review-tasks.db");
3839
+ if (!existsSync6(reviewDbPath)) {
3679
3840
  console.log(chalk6.dim("Code review not initialized. Starting setup...\n"));
3680
- const { reviewInit: reviewInit2 } = await import("./review-T4ID2QUF.js");
3841
+ const { reviewInit: reviewInit2 } = await import("./review-AUG6GIL6.js");
3681
3842
  await reviewInit2();
3682
3843
  console.log();
3683
3844
  }
@@ -3692,27 +3853,27 @@ async function reviewCode() {
3692
3853
  const choice = await prompt("Enter choice");
3693
3854
  switch (choice.toLowerCase()) {
3694
3855
  case "1": {
3695
- const { reviewAnalyze: reviewAnalyze2 } = await import("./review-T4ID2QUF.js");
3856
+ const { reviewAnalyze: reviewAnalyze2 } = await import("./review-AUG6GIL6.js");
3696
3857
  await reviewAnalyze2();
3697
3858
  break;
3698
3859
  }
3699
3860
  case "2": {
3700
- const { reviewStatus: reviewStatus2 } = await import("./review-T4ID2QUF.js");
3861
+ const { reviewStatus: reviewStatus2 } = await import("./review-AUG6GIL6.js");
3701
3862
  await reviewStatus2();
3702
3863
  break;
3703
3864
  }
3704
3865
  case "3": {
3705
- const { reviewNext: reviewNext2 } = await import("./review-T4ID2QUF.js");
3866
+ const { reviewNext: reviewNext2 } = await import("./review-AUG6GIL6.js");
3706
3867
  await reviewNext2();
3707
3868
  break;
3708
3869
  }
3709
3870
  case "4": {
3710
- const { reviewList: reviewList2 } = await import("./review-T4ID2QUF.js");
3871
+ const { reviewList: reviewList2 } = await import("./review-AUG6GIL6.js");
3711
3872
  await reviewList2({});
3712
3873
  break;
3713
3874
  }
3714
3875
  case "5": {
3715
- const { reviewRun: reviewRun2 } = await import("./review-T4ID2QUF.js");
3876
+ const { reviewRun: reviewRun2 } = await import("./review-AUG6GIL6.js");
3716
3877
  await reviewRun2({ all: true });
3717
3878
  break;
3718
3879
  }
@@ -3727,12 +3888,12 @@ async function reviewCode() {
3727
3888
  async function handleInSessionCommand(input) {
3728
3889
  const normalized = input.toLowerCase().trim();
3729
3890
  if (normalized === "upgrade" || normalized === "archon upgrade" || normalized === "pricing" || normalized === "archon pricing") {
3730
- const { showUpgradeMenu } = await import("./tier-selection-Z2RFHZUX.js");
3891
+ const { showUpgradeMenu } = await import("./tier-selection-426HA765.js");
3731
3892
  await showUpgradeMenu();
3732
3893
  return true;
3733
3894
  }
3734
3895
  if (normalized === "status" || normalized === "archon status") {
3735
- const { status: status2 } = await import("./auth-KUFS3PBS.js");
3896
+ const { status: status2 } = await import("./auth-HQBAG4CR.js");
3736
3897
  await status2();
3737
3898
  return true;
3738
3899
  }
@@ -3748,7 +3909,7 @@ async function handleInSessionCommand(input) {
3748
3909
  return true;
3749
3910
  }
3750
3911
  if (normalized === "keys" || normalized === "archon keys") {
3751
- const { listKeys: listKeys2 } = await import("./keys-VLK3EWSN.js");
3912
+ const { listKeys: listKeys2 } = await import("./keys-U4QZE5YB.js");
3752
3913
  await listKeys2();
3753
3914
  return true;
3754
3915
  }
@@ -3780,6 +3941,111 @@ async function promptWithCommands(question) {
3780
3941
  console.log(chalk6.dim("(Returning to previous question...)\n"));
3781
3942
  }
3782
3943
  }
3944
+ async function runWebChecksSuite() {
3945
+ const { a11yCheck: a11yCheck2 } = await import("./a11y-O35BAA25.js");
3946
+ const { seoCheck } = await import("./seo-PMI42KRZ.js");
3947
+ const { geoAudit } = await import("./geo-KV4IRGKN.js");
3948
+ console.log(chalk6.blue("\nRunning web checks (A11y, SEO, GEO)...\n"));
3949
+ await a11yCheck2({});
3950
+ await seoCheck({});
3951
+ await geoAudit();
3952
+ }
3953
+ async function showWebChecksMenu() {
3954
+ const cwd = process.cwd();
3955
+ const { loadWebChecks, formatWebCheckStatus, setWebPromptMode } = await import("./web-checks-4BSYXWDF.js");
3956
+ const prefs = await loadWebChecks(cwd);
3957
+ console.log(chalk6.bold("\nWeb Checks (SEO / GEO / A11y)\n"));
3958
+ console.log(chalk6.dim(`A11y: ${formatWebCheckStatus(prefs.lastRun?.a11y)}`));
3959
+ console.log(chalk6.dim(`SEO: ${formatWebCheckStatus(prefs.lastRun?.seo)}`));
3960
+ console.log(chalk6.dim(`GEO: ${formatWebCheckStatus(prefs.lastRun?.geo)}`));
3961
+ console.log();
3962
+ console.log(` ${chalk6.cyan("1")}) Run all checks`);
3963
+ console.log(` ${chalk6.cyan("2")}) Run accessibility check`);
3964
+ console.log(` ${chalk6.cyan("3")}) Run SEO check`);
3965
+ console.log(` ${chalk6.cyan("4")}) Run GEO audit`);
3966
+ console.log(` ${chalk6.cyan("5")}) Generate GEO identity`);
3967
+ console.log(` ${chalk6.cyan("6")}) Generate GEO schema`);
3968
+ console.log(` ${chalk6.cyan("7")}) Set prompt mode (ask/always/never)`);
3969
+ console.log(` ${chalk6.cyan("b")}) Back to main menu`);
3970
+ console.log();
3971
+ const choice = await promptWithCommands("Enter choice");
3972
+ switch (choice.toLowerCase()) {
3973
+ case "1":
3974
+ await runWebChecksSuite();
3975
+ break;
3976
+ case "2": {
3977
+ const { a11yCheck: a11yCheck2 } = await import("./a11y-O35BAA25.js");
3978
+ await a11yCheck2({});
3979
+ break;
3980
+ }
3981
+ case "3": {
3982
+ const { seoCheck } = await import("./seo-PMI42KRZ.js");
3983
+ await seoCheck({});
3984
+ break;
3985
+ }
3986
+ case "4": {
3987
+ const { geoAudit } = await import("./geo-KV4IRGKN.js");
3988
+ await geoAudit();
3989
+ break;
3990
+ }
3991
+ case "5": {
3992
+ const { geoIdentity } = await import("./geo-KV4IRGKN.js");
3993
+ await geoIdentity();
3994
+ break;
3995
+ }
3996
+ case "6": {
3997
+ const { geoSchema } = await import("./geo-KV4IRGKN.js");
3998
+ await geoSchema({});
3999
+ break;
4000
+ }
4001
+ case "7": {
4002
+ console.log();
4003
+ console.log(` ${chalk6.cyan("1")}) Ask each session`);
4004
+ console.log(` ${chalk6.cyan("2")}) Always run automatically`);
4005
+ console.log(` ${chalk6.cyan("3")}) Never prompt`);
4006
+ console.log();
4007
+ const modeChoice = await promptWithCommands("Select prompt mode");
4008
+ if (modeChoice === "1") await setWebPromptMode(cwd, "ask");
4009
+ if (modeChoice === "2") await setWebPromptMode(cwd, "always");
4010
+ if (modeChoice === "3") await setWebPromptMode(cwd, "never");
4011
+ break;
4012
+ }
4013
+ default:
4014
+ break;
4015
+ }
4016
+ if (choice.toLowerCase() !== "b") {
4017
+ await showWebChecksMenu();
4018
+ }
4019
+ }
4020
+ async function maybePromptWebChecks(cwd, projectState) {
4021
+ if (!projectState.isWebProject) {
4022
+ return;
4023
+ }
4024
+ const { loadWebChecks, setWebPromptMode } = await import("./web-checks-4BSYXWDF.js");
4025
+ const prefs = await loadWebChecks(cwd);
4026
+ if (prefs.promptMode === "never") {
4027
+ return;
4028
+ }
4029
+ if (prefs.promptMode === "always") {
4030
+ console.log(chalk6.blue("\nWeb project detected. Running web checks automatically...\n"));
4031
+ await runWebChecksSuite();
4032
+ return;
4033
+ }
4034
+ console.log(chalk6.blue("\nWeb project detected."));
4035
+ const choice = await promptChoice("Run web checks now?", [
4036
+ { key: "1", label: "Run all checks (A11y + SEO + GEO)" },
4037
+ { key: "2", label: "Choose checks" },
4038
+ { key: "3", label: "Not now" },
4039
+ { key: "4", label: "Never ask again" }
4040
+ ]);
4041
+ if (choice === "1") {
4042
+ await runWebChecksSuite();
4043
+ } else if (choice === "2") {
4044
+ await showWebChecksMenu();
4045
+ } else if (choice === "4") {
4046
+ await setWebPromptMode(cwd, "never");
4047
+ }
4048
+ }
3783
4049
  function promptYesNo(question, defaultValue) {
3784
4050
  return new Promise((resolve) => {
3785
4051
  const rl = readline.createInterface({
@@ -3797,6 +4063,22 @@ function promptYesNo(question, defaultValue) {
3797
4063
  });
3798
4064
  });
3799
4065
  }
4066
+ function promptChoice(question, options) {
4067
+ return new Promise((resolve) => {
4068
+ console.log(`${chalk6.cyan("?")} ${question}`);
4069
+ for (const opt of options) {
4070
+ console.log(` ${chalk6.dim(opt.key)}) ${opt.label}`);
4071
+ }
4072
+ const rl = readline.createInterface({
4073
+ input: process.stdin,
4074
+ output: process.stdout
4075
+ });
4076
+ rl.question(` ${chalk6.dim("Enter choice")}: `, (answer) => {
4077
+ rl.close();
4078
+ resolve(answer.trim() || "1");
4079
+ });
4080
+ });
4081
+ }
3800
4082
 
3801
4083
  // src/cli/credits.ts
3802
4084
  import chalk7 from "chalk";
@@ -4476,7 +4758,7 @@ async function watch() {
4476
4758
  import { Command } from "commander";
4477
4759
  import chalk8 from "chalk";
4478
4760
  import { readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
4479
- import { existsSync as existsSync7 } from "fs";
4761
+ import { existsSync as existsSync8 } from "fs";
4480
4762
  var DEPENDENCIES_FILENAME = "DEPENDENCIES.md";
4481
4763
  function createDepsCommand() {
4482
4764
  const deps = new Command("deps").description("Manage file-level dependencies (DEPENDENCIES.md)").addHelpText(
@@ -4602,9 +4884,9 @@ Examples:
4602
4884
  reason
4603
4885
  };
4604
4886
  existingRules.push(newRule);
4605
- const yaml3 = generateYamlFrontmatter(existingRules);
4887
+ const yaml2 = generateYamlFrontmatter(existingRules);
4606
4888
  await writeFile4(DEPENDENCIES_FILENAME, `---
4607
- ${yaml3}---${markdownBody}`, "utf-8");
4889
+ ${yaml2}---${markdownBody}`, "utf-8");
4608
4890
  console.log(chalk8.green(`\u2705 Added dependency rule: ${nextId}`));
4609
4891
  console.log(` Source: ${chalk8.cyan(source)}`);
4610
4892
  console.log(` Dependent: ${chalk8.dim(dependent)}`);
@@ -4626,7 +4908,7 @@ ${yaml3}---${markdownBody}`, "utf-8");
4626
4908
  }
4627
4909
  });
4628
4910
  deps.command("init").description("Create a starter DEPENDENCIES.md file").action(async () => {
4629
- if (existsSync7(DEPENDENCIES_FILENAME)) {
4911
+ if (existsSync8(DEPENDENCIES_FILENAME)) {
4630
4912
  console.log(chalk8.yellow("DEPENDENCIES.md already exists."));
4631
4913
  return;
4632
4914
  }
@@ -4711,1379 +4993,87 @@ function generateYamlFrontmatter(rules) {
4711
4993
  return lines.join("\n") + "\n";
4712
4994
  }
4713
4995
 
4714
- // src/cli/a11y.ts
4996
+ // src/cli/session.ts
4715
4997
  import chalk9 from "chalk";
4716
- import { existsSync as existsSync8 } from "fs";
4717
- import { readFile as readFile5, writeFile as writeFile5, mkdir as mkdir3 } from "fs/promises";
4718
- import { join as join7 } from "path";
4719
- import { createInterface } from "readline";
4720
- import { glob } from "glob";
4721
- var ACCESSIBILITY_CHECKS = {
4722
- contrast: {
4723
- name: "Color Contrast",
4724
- wcag: "1.4.3, 1.4.11",
4725
- description: "Text and UI components have sufficient contrast ratios",
4726
- patterns: [
4727
- { regex: /text-primary\/[0-9]+/g, issue: "Opacity-based text colors may have insufficient contrast" },
4728
- { regex: /opacity-[0-9]+/g, issue: "Low opacity text may not meet contrast requirements" },
4729
- { regex: /text-gray-[3-4]00/g, issue: "Light gray text often fails contrast requirements" }
4730
- ]
4731
- },
4732
- images: {
4733
- name: "Image Alt Text",
4734
- wcag: "1.1.1",
4735
- description: "All meaningful images have alt text",
4736
- patterns: [
4737
- { regex: /<img(?![^>]*alt=)[^>]*>/gi, issue: "Image missing alt attribute" },
4738
- { regex: /<img[^>]*alt=["']\s*["'][^>]*>/gi, issue: "Image has empty alt text (verify if decorative)" }
4739
- ]
4740
- },
4741
- forms: {
4742
- name: "Form Labels",
4743
- wcag: "1.3.1, 4.1.2",
4744
- description: "Form inputs have associated labels",
4745
- patterns: [
4746
- { regex: /<input(?![^>]*aria-label)[^>]*(?<![^>]*id=)[^>]*>/gi, issue: "Input without label association" }
4747
- ]
4748
- },
4749
- keyboard: {
4750
- name: "Keyboard Navigation",
4751
- wcag: "2.1.1, 2.4.7",
4752
- description: "All interactive elements are keyboard accessible with visible focus",
4753
- patterns: [
4754
- { regex: /outline:\s*none|outline:\s*0/gi, issue: "Focus outline removed - may break keyboard navigation" },
4755
- { regex: /tabindex=["']-1["']/gi, issue: "Negative tabindex removes element from tab order" }
4756
- ]
4757
- },
4758
- structure: {
4759
- name: "Document Structure",
4760
- wcag: "1.3.1, 2.4.1",
4761
- description: "Proper heading hierarchy and landmarks",
4762
- patterns: [
4763
- { regex: /<html(?![^>]*lang=)[^>]*>/gi, issue: "HTML element missing lang attribute" }
4764
- ]
4765
- },
4766
- aria: {
4767
- name: "ARIA Usage",
4768
- wcag: "4.1.2",
4769
- description: "ARIA attributes are used correctly",
4770
- patterns: [
4771
- { regex: /role=["']button["'](?![^>]*tabindex)/gi, issue: "Custom button missing tabindex" }
4772
- ]
4773
- }
4774
- };
4775
- function createPrompt() {
4776
- const rl = createInterface({
4777
- input: process.stdin,
4778
- output: process.stdout
4779
- });
4780
- return {
4781
- ask: (question) => new Promise((resolve) => {
4782
- rl.question(question, resolve);
4783
- }),
4784
- close: () => rl.close()
4785
- };
4998
+ import ora2 from "ora";
4999
+ import os from "os";
5000
+ import { readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
5001
+ import { existsSync as existsSync9 } from "fs";
5002
+ import { join as join8 } from "path";
5003
+ function getSupabaseClient2(accessToken) {
5004
+ return createAuthedSupabaseClient(SUPABASE_URL, SUPABASE_ANON_KEY, accessToken);
5005
+ }
5006
+ function getDeviceName() {
5007
+ return `${os.hostname()}-${os.platform()}-${os.arch()}`;
4786
5008
  }
4787
- async function scanForIssues(files) {
4788
- const issues = [];
4789
- for (const file of files) {
5009
+ async function getProjectInfo(cwd) {
5010
+ const archonConfigPath = join8(cwd, ".archon", "config.yaml");
5011
+ const packageJsonPath = join8(cwd, "package.json");
5012
+ let projectName = "Unknown Project";
5013
+ if (existsSync9(packageJsonPath)) {
4790
5014
  try {
4791
- const content = await readFile5(file, "utf-8");
4792
- const lines = content.split("\n");
4793
- for (const [checkId, check] of Object.entries(ACCESSIBILITY_CHECKS)) {
4794
- for (const pattern of check.patterns) {
4795
- for (let i = 0; i < lines.length; i++) {
4796
- const line = lines[i];
4797
- if (line && pattern.regex.test(line)) {
4798
- pattern.regex.lastIndex = 0;
4799
- issues.push({
4800
- file: file.replace(process.cwd() + "/", ""),
4801
- line: i + 1,
4802
- check: check.name,
4803
- wcag: check.wcag,
4804
- severity: checkId === "contrast" || checkId === "keyboard" ? "critical" : "major",
4805
- message: pattern.issue
4806
- });
4807
- }
4808
- pattern.regex.lastIndex = 0;
4809
- }
4810
- }
4811
- }
5015
+ const pkg = JSON.parse(await readFile5(packageJsonPath, "utf-8"));
5016
+ projectName = pkg.name || projectName;
4812
5017
  } catch {
4813
5018
  }
4814
5019
  }
4815
- return issues;
4816
- }
4817
- async function a11yCheck(options) {
4818
- console.log(chalk9.blue("\n\u267F Pre-Deploy Accessibility Check\n"));
4819
- console.log(chalk9.dim("Scanning for WCAG 2.2 AA compliance issues...\n"));
4820
- const patterns = [
4821
- "**/*.html",
4822
- "**/*.htm",
4823
- "**/*.jsx",
4824
- "**/*.tsx",
4825
- "**/*.astro",
4826
- "**/*.svelte",
4827
- "**/*.vue"
4828
- ];
4829
- const ignorePatterns = ["**/node_modules/**", "**/dist/**", "**/build/**", "**/.next/**"];
4830
- let allFiles = [];
4831
- for (const pattern of patterns) {
4832
- const files = await glob(pattern, { cwd: process.cwd(), ignore: ignorePatterns });
4833
- allFiles = allFiles.concat(files.map((f) => join7(process.cwd(), f)));
4834
- }
4835
- if (allFiles.length === 0) {
4836
- console.log(chalk9.yellow("No web files found to check."));
4837
- return;
4838
- }
4839
- console.log(chalk9.dim(`Scanning ${allFiles.length} files...
4840
- `));
4841
- const issues = await scanForIssues(allFiles);
4842
- const report = {
4843
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
4844
- totalFiles: allFiles.length,
4845
- issuesFound: issues.length,
4846
- issues,
4847
- passed: issues.length === 0
4848
- };
4849
- const archonDir = join7(process.cwd(), ".archon");
4850
- if (!existsSync8(archonDir)) {
4851
- await mkdir3(archonDir, { recursive: true });
4852
- }
4853
- await writeFile5(join7(archonDir, "a11y-report.json"), JSON.stringify(report, null, 2));
4854
- if (issues.length === 0) {
4855
- console.log(chalk9.green("\u2705 Accessibility Audit Passed\n"));
4856
- console.log(chalk9.dim("Your site meets WCAG 2.2 AA requirements based on static analysis."));
4857
- console.log(chalk9.dim("Note: Run manual testing with screen readers for full compliance.\n"));
4858
- return;
4859
- }
4860
- console.log(chalk9.red(`[!] ${issues.length} Accessibility Issues Found
4861
- `));
4862
- const criticalCount = issues.filter((i) => i.severity === "critical").length;
4863
- const majorCount = issues.filter((i) => i.severity === "major").length;
4864
- const minorCount = issues.filter((i) => i.severity === "minor").length;
4865
- console.log(chalk9.dim("Summary:"));
4866
- if (criticalCount > 0) console.log(chalk9.red(` \u2022 ${criticalCount} critical`));
4867
- if (majorCount > 0) console.log(chalk9.yellow(` \u2022 ${majorCount} major`));
4868
- if (minorCount > 0) console.log(chalk9.dim(` \u2022 ${minorCount} minor`));
4869
- console.log();
4870
- console.log(chalk9.bold("Issues:\n"));
4871
- const issuesByFile = /* @__PURE__ */ new Map();
4872
- for (const issue of issues) {
4873
- const existing = issuesByFile.get(issue.file) || [];
4874
- existing.push(issue);
4875
- issuesByFile.set(issue.file, existing);
4876
- }
4877
- for (const [file, fileIssues] of issuesByFile) {
4878
- console.log(chalk9.cyan(` ${file}`));
4879
- for (const issue of fileIssues.slice(0, 5)) {
4880
- const color = issue.severity === "critical" ? chalk9.red : issue.severity === "major" ? chalk9.yellow : chalk9.dim;
4881
- console.log(color(` Line ${issue.line}: ${issue.message} (WCAG ${issue.wcag})`));
4882
- }
4883
- if (fileIssues.length > 5) {
4884
- console.log(chalk9.dim(` ... and ${fileIssues.length - 5} more issues`));
4885
- }
4886
- console.log();
5020
+ if (!existsSync9(archonConfigPath)) {
5021
+ return null;
4887
5022
  }
4888
- console.log(chalk9.bold.yellow("\n[LEGAL] Notice\n"));
4889
- console.log(chalk9.dim("Websites that don't meet accessibility standards may violate:"));
4890
- console.log(chalk9.dim(" \u2022 ADA (Americans with Disabilities Act) \u2014 US"));
4891
- console.log(chalk9.dim(" \u2022 EAA (European Accessibility Act) \u2014 EU, effective June 2025"));
4892
- console.log(chalk9.dim(" \u2022 Section 508 \u2014 US federal agencies and contractors"));
4893
- console.log(chalk9.dim(" \u2022 AODA (Accessibility for Ontarians) \u2014 Ontario, Canada"));
4894
- console.log();
4895
- console.log(chalk9.dim("Non-compliance can result in lawsuits, fines, and reputational damage."));
4896
- console.log(chalk9.dim("In 2023, over 4,600 ADA web accessibility lawsuits were filed in the US.\n"));
4897
- console.log(chalk9.dim(`Full report saved to: .archon/a11y-report.json`));
5023
+ return { name: projectName, path: cwd };
4898
5024
  }
4899
- async function a11yFix(options) {
4900
- const prompt3 = createPrompt();
5025
+ async function getCurrentAtomId(cwd) {
5026
+ const stateFile = join8(cwd, ".archon", "state.json");
5027
+ if (!existsSync9(stateFile)) return null;
4901
5028
  try {
4902
- console.log(chalk9.blue("\n\u267F Accessibility Auto-Fix\n"));
4903
- const reportPath = join7(process.cwd(), ".archon/a11y-report.json");
4904
- if (!existsSync8(reportPath)) {
4905
- console.log(chalk9.yellow("No accessibility report found. Running check first...\n"));
4906
- await a11yCheck({});
4907
- }
4908
- const reportContent = await readFile5(reportPath, "utf-8");
4909
- const report = JSON.parse(reportContent);
4910
- if (report.passed || report.issues.length === 0) {
4911
- console.log(chalk9.green("No issues to fix!"));
4912
- return;
4913
- }
4914
- console.log(chalk9.dim(`Found ${report.issues.length} issues from last check.
4915
- `));
4916
- const fixablePatterns = [
4917
- {
4918
- pattern: /text-primary\/60/g,
4919
- replacement: "text-text-muted",
4920
- description: "Replace low-opacity text with accessible color"
4921
- },
4922
- {
4923
- pattern: /text-primary\/70/g,
4924
- replacement: "text-text-muted",
4925
- description: "Replace low-opacity text with accessible color"
4926
- },
4927
- {
4928
- pattern: /outline:\s*none/gi,
4929
- replacement: "outline: 2px solid transparent",
4930
- description: "Replace outline:none with accessible alternative"
4931
- },
4932
- {
4933
- pattern: /<html>/gi,
4934
- replacement: '<html lang="en">',
4935
- description: "Add lang attribute to html element"
4936
- }
4937
- ];
4938
- let totalFixes = 0;
4939
- for (const fix of fixablePatterns) {
4940
- const patterns = ["**/*.html", "**/*.jsx", "**/*.tsx", "**/*.astro", "**/*.svelte", "**/*.vue", "**/*.css"];
4941
- const ignorePatterns = ["**/node_modules/**", "**/dist/**", "**/build/**"];
4942
- for (const pattern of patterns) {
4943
- const files = await glob(pattern, { cwd: process.cwd(), ignore: ignorePatterns });
4944
- for (const file of files) {
4945
- const filePath = join7(process.cwd(), file);
4946
- try {
4947
- const content = await readFile5(filePath, "utf-8");
4948
- if (fix.pattern.test(content)) {
4949
- fix.pattern.lastIndex = 0;
4950
- const matches = content.match(fix.pattern);
4951
- const count = matches?.length || 0;
4952
- if (count > 0) {
4953
- console.log(chalk9.cyan(` ${file}: ${count} fixes (${fix.description})`));
4954
- totalFixes += count;
4955
- if (!options.dryRun) {
4956
- const newContent = content.replace(fix.pattern, fix.replacement);
4957
- await writeFile5(filePath, newContent);
4958
- }
4959
- }
4960
- }
4961
- } catch {
4962
- }
4963
- }
4964
- }
4965
- }
4966
- if (totalFixes === 0) {
4967
- console.log(chalk9.dim("No auto-fixable issues found. Some issues require manual fixes."));
4968
- } else if (options.dryRun) {
4969
- console.log(chalk9.yellow(`
4970
- ${totalFixes} fixes would be applied. Run without --dry-run to apply.`));
4971
- } else {
4972
- console.log(chalk9.green(`
4973
- \u2705 Applied ${totalFixes} fixes.`));
4974
- console.log(chalk9.dim('Run "archon a11y check" to verify fixes.'));
4975
- }
4976
- } finally {
4977
- prompt3.close();
4978
- }
4979
- }
4980
- async function a11yBadge(options) {
4981
- console.log(chalk9.blue("\n\u267F Accessibility Badge\n"));
4982
- const badgeHtml = `<!-- WCAG 2.2 AA Compliance Badge -->
4983
- <div class="flex items-center gap-2 text-xs text-text-muted dark:text-cream-300">
4984
- <svg class="h-4 w-4" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
4985
- <path fill-rule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clip-rule="evenodd"/>
4986
- </svg>
4987
- <span>WCAG 2.2 AA Accessible</span>
4988
- </div>`;
4989
- const footerPatterns = ["**/Footer.{jsx,tsx,astro,svelte,vue}", "**/footer.{jsx,tsx,astro,svelte,vue,html}"];
4990
- let footerFiles = [];
4991
- for (const pattern of footerPatterns) {
4992
- const files = await glob(pattern, { cwd: process.cwd(), ignore: ["**/node_modules/**"] });
4993
- footerFiles = footerFiles.concat(files);
4994
- }
4995
- if (footerFiles.length === 0) {
4996
- console.log(chalk9.yellow("No footer files found."));
4997
- console.log(chalk9.dim("\nManually add this badge to your footer:\n"));
4998
- console.log(badgeHtml);
4999
- return;
5000
- }
5001
- console.log(chalk9.dim(`Found ${footerFiles.length} footer file(s):
5002
- `));
5003
- for (const file of footerFiles) {
5004
- console.log(chalk9.cyan(` ${file}`));
5005
- }
5006
- if (options.remove) {
5007
- console.log(chalk9.yellow("\nRemoving accessibility badge..."));
5008
- console.log(chalk9.dim("Badge removal not yet implemented. Manually remove the WCAG badge comment block."));
5009
- } else {
5010
- console.log(chalk9.dim("\nTo add the badge, insert this code before the closing </footer> tag:\n"));
5011
- console.log(chalk9.green(badgeHtml));
5029
+ const state = JSON.parse(await readFile5(stateFile, "utf-8"));
5030
+ return state.currentAtomId || null;
5031
+ } catch {
5032
+ return null;
5012
5033
  }
5013
5034
  }
5014
- async function a11yPreDeploy() {
5015
- const prompt3 = createPrompt();
5035
+ async function getPendingAtoms(cwd) {
5036
+ const stateFile = join8(cwd, ".archon", "state.json");
5037
+ if (!existsSync9(stateFile)) return [];
5016
5038
  try {
5017
- console.log(chalk9.blue("\n[CHECK] Pre-Deploy Accessibility\n"));
5018
- console.log(chalk9.dim("Before deploying a live website, accessibility compliance is required.\n"));
5019
- await a11yCheck({});
5020
- const reportPath = join7(process.cwd(), ".archon/a11y-report.json");
5021
- if (!existsSync8(reportPath)) {
5022
- return false;
5023
- }
5024
- const reportContent = await readFile5(reportPath, "utf-8");
5025
- const report = JSON.parse(reportContent);
5026
- if (report.passed) {
5027
- const addBadge = await prompt3.ask("\nWould you like to add a WCAG 2.2 AA badge to your footer? (y/N): ");
5028
- if (addBadge.toLowerCase() === "y") {
5029
- await a11yBadge({});
5030
- }
5031
- return true;
5032
- }
5033
- console.log(chalk9.bold("\nOptions:\n"));
5034
- console.log(" 1) Fix issues now (recommended)");
5035
- console.log(" 2) Deploy anyway (not recommended)");
5036
- console.log(" 3) Cancel deployment\n");
5037
- const choice = await prompt3.ask("Which would you like to do? (1/2/3): ");
5038
- if (choice === "1") {
5039
- await a11yFix({});
5040
- await a11yCheck({});
5041
- return true;
5042
- } else if (choice === "2") {
5043
- console.log(chalk9.yellow("\n[!] Acknowledged. Proceeding without full accessibility compliance."));
5044
- console.log(chalk9.dim("Consider addressing these issues in a future session.\n"));
5045
- return true;
5046
- } else {
5047
- console.log(chalk9.dim("\nDeployment cancelled."));
5048
- return false;
5049
- }
5050
- } finally {
5051
- prompt3.close();
5039
+ const state = JSON.parse(await readFile5(stateFile, "utf-8"));
5040
+ return state.pendingAtoms || [];
5041
+ } catch {
5042
+ return [];
5052
5043
  }
5053
5044
  }
5054
-
5055
- // src/cli/geo.ts
5056
- import { Command as Command2 } from "commander";
5057
- import chalk10 from "chalk";
5058
- import { readFile as readFile6, writeFile as writeFile6, mkdir as mkdir4 } from "fs/promises";
5059
- import { existsSync as existsSync9 } from "fs";
5060
- import { join as join8 } from "path";
5061
- import { createInterface as createInterface2 } from "readline";
5062
- import { glob as glob2 } from "glob";
5063
- import * as yaml2 from "yaml";
5064
- var CONFIG_PATH2 = ".archon/config.yaml";
5065
- function createPrompt2() {
5066
- const rl = createInterface2({
5067
- input: process.stdin,
5068
- output: process.stdout
5069
- });
5070
- return {
5071
- ask: (question) => new Promise((resolve) => {
5072
- rl.question(question, resolve);
5073
- }),
5074
- close: () => rl.close()
5075
- };
5076
- }
5077
- async function loadGeoConfig(cwd) {
5078
- const configPath = join8(cwd, CONFIG_PATH2);
5079
- if (!existsSync9(configPath)) {
5080
- return {};
5081
- }
5045
+ async function getFileContent(path2) {
5046
+ if (!existsSync9(path2)) return null;
5082
5047
  try {
5083
- const content = await readFile6(configPath, "utf-8");
5084
- return yaml2.parse(content);
5048
+ return await readFile5(path2, "utf-8");
5085
5049
  } catch {
5086
- return {};
5087
- }
5088
- }
5089
- async function saveGeoConfig(cwd, config) {
5090
- const configPath = join8(cwd, CONFIG_PATH2);
5091
- const archonDir = join8(cwd, ".archon");
5092
- if (!existsSync9(archonDir)) {
5093
- await mkdir4(archonDir, { recursive: true });
5094
- }
5095
- let existing = {};
5096
- if (existsSync9(configPath)) {
5097
- try {
5098
- const content = await readFile6(configPath, "utf-8");
5099
- existing = yaml2.parse(content);
5100
- } catch {
5101
- }
5102
- }
5103
- const merged = { ...existing, ...config };
5104
- await writeFile6(configPath, yaml2.stringify(merged), "utf-8");
5105
- }
5106
- async function readPageContent(patterns) {
5107
- const cwd = process.cwd();
5108
- let content = "";
5109
- for (const pattern of patterns) {
5110
- const files = await glob2(pattern, { cwd, ignore: ["**/node_modules/**", "**/dist/**"] });
5111
- for (const file of files.slice(0, 3)) {
5112
- try {
5113
- const fileContent = await readFile6(join8(cwd, file), "utf-8");
5114
- content += `
5115
- --- File: ${file} ---
5116
- ${fileContent.slice(0, 5e3)}
5117
- `;
5118
- } catch {
5119
- }
5120
- }
5121
- }
5122
- return content || "No content found.";
5123
- }
5124
- async function checkStrongModelAccess() {
5125
- const config = await loadConfig();
5126
- const tier = config.tier ?? "FREE";
5127
- if (tier === "CREDITS" || tier === "BYOK") {
5128
- return { allowed: true, tier };
5129
- }
5130
- return { allowed: false, tier };
5131
- }
5132
- var IDENTITY_SYSTEM_PROMPT = `You are a brand strategist and SEO expert. Your job is to create concise, memorable brand identity phrases and descriptions.
5133
-
5134
- Guidelines:
5135
- - Identity phrases should be EXACTLY 7 words
5136
- - Identity phrases should be unique, memorable, and capture the essence of the brand
5137
- - Short descriptions should be EXACTLY 50 words
5138
- - Descriptions should explain what the product/service does and why it matters
5139
- - Both should be optimized for search engines and AI assistants (GEO)
5140
- - Avoid jargon unless it's industry-standard terminology
5141
- - Focus on value proposition and differentiation
5142
-
5143
- Output your response as valid JSON.`;
5144
- async function generateIdentityCandidates(pageContent) {
5145
- const agent = new ArchitectAgent({ temperature: 0.8 });
5146
- const prompt3 = `Based on the following website content, generate brand identity options.
5147
-
5148
- ${pageContent}
5149
-
5150
- Generate EXACTLY 3 candidate 7-word brand phrases and 3 candidate 50-word descriptions.
5151
-
5152
- Output as JSON:
5153
- {
5154
- "phrases": [
5155
- { "phrase": "exactly seven words go right here", "rationale": "why this phrase works" },
5156
- { "phrase": "another seven word phrase goes here", "rationale": "why this phrase works" },
5157
- { "phrase": "third seven word phrase goes here", "rationale": "why this phrase works" }
5158
- ],
5159
- "descriptions": [
5160
- { "description": "exactly 50 words description...", "rationale": "why this works" },
5161
- { "description": "another 50 words description...", "rationale": "why this works" },
5162
- { "description": "third 50 words description...", "rationale": "why this works" }
5163
- ]
5164
- }`;
5165
- const response = await agent.client.chat(
5166
- IDENTITY_SYSTEM_PROMPT,
5167
- prompt3,
5168
- { temperature: 0.8, maxTokens: 2e3 }
5169
- );
5170
- const jsonMatch = response.content.match(/\{[\s\S]*\}/);
5171
- if (!jsonMatch) {
5172
- throw new Error("Failed to parse AI response");
5050
+ return null;
5173
5051
  }
5174
- const parsed = JSON.parse(jsonMatch[0]);
5175
- return parsed;
5176
5052
  }
5177
- async function geoIdentity() {
5053
+ async function saveSession(name) {
5054
+ const spinner = ora2("Saving session...").start();
5178
5055
  const cwd = process.cwd();
5179
- const prompt3 = createPrompt2();
5180
5056
  try {
5181
- console.log(chalk10.blue("\n\u{1F3AF} GEO Identity Generator\n"));
5182
- const { allowed, tier } = await checkStrongModelAccess();
5183
- if (!allowed) {
5184
- console.log(chalk10.yellow(`[!] Your tier (${tier}) uses basic models.`));
5185
- console.log(chalk10.dim("For better results, add credits or use BYOK mode.\n"));
5186
- }
5187
- console.log(chalk10.dim("Reading homepage and about page content...\n"));
5188
- const pageContent = await readPageContent([
5189
- "**/index.html",
5190
- "**/index.{jsx,tsx,astro,svelte,vue}",
5191
- "**/about.{html,jsx,tsx,astro,svelte,vue,md}",
5192
- "**/about/index.{jsx,tsx,astro,svelte,vue}",
5193
- "**/pages/index.{jsx,tsx,astro,svelte,vue}",
5194
- "**/app/page.{jsx,tsx}",
5195
- "README.md"
5196
- ]);
5197
- if (pageContent === "No content found.") {
5198
- console.log(chalk10.yellow("No homepage or about page content found."));
5199
- console.log(chalk10.dim("Create an index file or README.md first.\n"));
5057
+ const config = await loadConfig();
5058
+ if (!config.accessToken || !config.userId) {
5059
+ spinner.fail("Not logged in. Run: archon login");
5200
5060
  return;
5201
5061
  }
5202
- console.log(chalk10.dim("Generating identity candidates with AI...\n"));
5203
- const candidates = await generateIdentityCandidates(pageContent);
5204
- console.log(chalk10.bold("\u{1F4CC} 7-Word Brand Phrases:\n"));
5205
- candidates.phrases.forEach((p, i) => {
5206
- console.log(` ${chalk10.cyan(`${i + 1})`)} ${chalk10.bold(p.phrase)}`);
5207
- console.log(` ${chalk10.dim(p.rationale)}
5208
- `);
5209
- });
5210
- const phraseChoice = await prompt3.ask('Select a phrase (1-3) or "r" to regenerate: ');
5211
- if (phraseChoice.toLowerCase() === "r") {
5212
- console.log(chalk10.dim("\nRegenerating... Run the command again.\n"));
5062
+ const projectInfo = await getProjectInfo(cwd);
5063
+ if (!projectInfo) {
5064
+ spinner.fail("Not an ArchonDev project. Run: archon init");
5213
5065
  return;
5214
5066
  }
5215
- const phraseIndex = parseInt(phraseChoice, 10) - 1;
5216
- const selectedPhrase = candidates.phrases[phraseIndex];
5217
- if (isNaN(phraseIndex) || phraseIndex < 0 || phraseIndex >= candidates.phrases.length || !selectedPhrase) {
5218
- console.log(chalk10.red("Invalid selection."));
5219
- return;
5220
- }
5221
- console.log(chalk10.bold("\n\u{1F4DD} 50-Word Descriptions:\n"));
5222
- candidates.descriptions.forEach((d, i) => {
5223
- console.log(` ${chalk10.cyan(`${i + 1})`)} ${d.description}`);
5224
- console.log(` ${chalk10.dim(d.rationale)}
5225
- `);
5226
- });
5227
- const descChoice = await prompt3.ask('Select a description (1-3) or "r" to regenerate: ');
5228
- if (descChoice.toLowerCase() === "r") {
5229
- console.log(chalk10.dim("\nRegenerating... Run the command again.\n"));
5230
- return;
5231
- }
5232
- const descIndex = parseInt(descChoice, 10) - 1;
5233
- const selectedDescription = candidates.descriptions[descIndex];
5234
- if (isNaN(descIndex) || descIndex < 0 || descIndex >= candidates.descriptions.length || !selectedDescription) {
5235
- console.log(chalk10.red("Invalid selection."));
5236
- return;
5237
- }
5238
- const geoConfig = {
5239
- geo: {
5240
- identityPhrase: selectedPhrase.phrase,
5241
- shortDescription: selectedDescription.description,
5242
- generatedAt: (/* @__PURE__ */ new Date()).toISOString()
5243
- }
5244
- };
5245
- await saveGeoConfig(cwd, geoConfig);
5246
- console.log(chalk10.green("\n\u2705 Identity saved!\n"));
5247
- console.log(chalk10.dim(` Phrase: ${selectedPhrase.phrase}`));
5248
- console.log(chalk10.dim(` Description: ${selectedDescription.description.slice(0, 60)}...`));
5249
- console.log();
5250
- console.log(chalk10.cyan(`Use 'archon geo schema' to generate JSON-LD.`));
5251
- } finally {
5252
- prompt3.close();
5253
- }
5254
- }
5255
- async function geoSchema(options) {
5256
- const cwd = process.cwd();
5257
- console.log(chalk10.blue("\n\u{1F4E6} JSON-LD Schema Generator\n"));
5258
- const config = await loadGeoConfig(cwd);
5259
- if (!config.geo?.identityPhrase || !config.geo?.shortDescription) {
5260
- console.log(chalk10.yellow("No identity defined."));
5261
- console.log(chalk10.dim(`Run 'archon geo identity' first.
5262
- `));
5263
- return;
5264
- }
5265
- const { identityPhrase, shortDescription } = config.geo;
5266
- let orgName = identityPhrase.split(" ").slice(0, 2).join(" ");
5267
- try {
5268
- const pkgPath = join8(cwd, "package.json");
5269
- if (existsSync9(pkgPath)) {
5270
- const pkg = JSON.parse(await readFile6(pkgPath, "utf-8"));
5271
- if (pkg.name) {
5272
- orgName = pkg.name.replace(/-/g, " ").replace(/^\w/, (c) => c.toUpperCase());
5273
- }
5274
- }
5275
- } catch {
5276
- }
5277
- const schema = {
5278
- "@context": "https://schema.org",
5279
- "@graph": [
5280
- {
5281
- "@type": "Organization",
5282
- "@id": "#organization",
5283
- name: orgName,
5284
- description: shortDescription,
5285
- slogan: identityPhrase
5286
- },
5287
- {
5288
- "@type": "WebSite",
5289
- "@id": "#website",
5290
- name: orgName,
5291
- description: shortDescription,
5292
- publisher: { "@id": "#organization" }
5293
- },
5294
- {
5295
- "@type": "Service",
5296
- name: orgName,
5297
- description: shortDescription,
5298
- provider: { "@id": "#organization" }
5299
- }
5300
- ]
5301
- };
5302
- const jsonLd = JSON.stringify(schema, null, 2);
5303
- if (options.output) {
5304
- await writeFile6(options.output, jsonLd, "utf-8");
5305
- console.log(chalk10.green(`\u2705 Schema written to ${options.output}`));
5306
- } else {
5307
- console.log(chalk10.bold("Generated JSON-LD:\n"));
5308
- console.log(chalk10.cyan(jsonLd));
5309
- }
5310
- if (options.apply) {
5311
- console.log(chalk10.dim("\nAttempting to insert into homepage <head>...\n"));
5312
- const indexFiles = await glob2("**/index.html", { cwd, ignore: ["**/node_modules/**", "**/dist/**"] });
5313
- if (indexFiles.length === 0) {
5314
- console.log(chalk10.yellow("No index.html found. Manually add to your HTML <head>:"));
5315
- console.log(chalk10.dim(`<script type="application/ld+json">
5316
- ${jsonLd}
5317
- </script>`));
5318
- return;
5319
- }
5320
- const firstIndexFile = indexFiles[0];
5321
- if (!firstIndexFile) {
5322
- console.log(chalk10.yellow("No index.html found."));
5323
- return;
5324
- }
5325
- const indexPath = join8(cwd, firstIndexFile);
5326
- let indexContent = await readFile6(indexPath, "utf-8");
5327
- const scriptTag = `<script type="application/ld+json">
5328
- ${jsonLd}
5329
- </script>`;
5330
- if (indexContent.includes("application/ld+json")) {
5331
- console.log(chalk10.yellow("JSON-LD already exists in index.html. Remove it first or update manually."));
5332
- return;
5333
- }
5334
- indexContent = indexContent.replace("</head>", `${scriptTag}
5335
- </head>`);
5336
- await writeFile6(indexPath, indexContent, "utf-8");
5337
- console.log(chalk10.green(`\u2705 JSON-LD inserted into ${firstIndexFile}`));
5338
- }
5339
- console.log();
5340
- }
5341
- var FAQ_SYSTEM_PROMPT = `You are an SEO expert creating FAQ content for schema markup.
5342
-
5343
- Guidelines:
5344
- - Generate 6-8 questions that potential customers would ask
5345
- - Answers should be concise but informative (2-4 sentences)
5346
- - Questions should naturally include keywords from the brand identity
5347
- - Answers should demonstrate expertise and build trust
5348
- - Format for FAQPage schema compatibility
5349
-
5350
- Output your response as valid JSON.`;
5351
- async function geoFaq(options) {
5352
- const cwd = process.cwd();
5353
- console.log(chalk10.blue("\n\u2753 FAQ Schema Generator\n"));
5354
- const config = await loadGeoConfig(cwd);
5355
- if (!config.geo?.identityPhrase || !config.geo?.shortDescription) {
5356
- console.log(chalk10.yellow("No identity defined."));
5357
- console.log(chalk10.dim(`Run 'archon geo identity' first.
5358
- `));
5359
- return;
5360
- }
5361
- const { identityPhrase, shortDescription } = config.geo;
5362
- const { allowed, tier } = await checkStrongModelAccess();
5363
- if (!allowed) {
5364
- console.log(chalk10.yellow(`[!] Your tier (${tier}) uses basic models.`));
5365
- console.log(chalk10.dim("For better results, add credits or use BYOK mode.\n"));
5366
- }
5367
- console.log(chalk10.dim("Generating FAQ content with AI...\n"));
5368
- const agent = new ArchitectAgent({ temperature: 0.7 });
5369
- const prompt3 = `Generate FAQ content for a product/service with:
5370
- - Brand phrase: "${identityPhrase}"
5371
- - Description: "${shortDescription}"
5372
-
5373
- Generate 6-8 FAQs as JSON:
5374
- {
5375
- "faqs": [
5376
- { "question": "What is...?", "answer": "..." },
5377
- ...
5378
- ]
5379
- }`;
5380
- const response = await agent.client.chat(
5381
- FAQ_SYSTEM_PROMPT,
5382
- prompt3,
5383
- { temperature: 0.7, maxTokens: 2e3 }
5384
- );
5385
- const jsonMatch = response.content.match(/\{[\s\S]*\}/);
5386
- if (!jsonMatch) {
5387
- console.log(chalk10.red("Failed to generate FAQ content."));
5388
- return;
5389
- }
5390
- const parsed = JSON.parse(jsonMatch[0]);
5391
- const faqSchema = {
5392
- "@context": "https://schema.org",
5393
- "@type": "FAQPage",
5394
- mainEntity: parsed.faqs.map((faq) => ({
5395
- "@type": "Question",
5396
- name: faq.question,
5397
- acceptedAnswer: {
5398
- "@type": "Answer",
5399
- text: faq.answer
5400
- }
5401
- }))
5402
- };
5403
- const jsonLd = JSON.stringify(faqSchema, null, 2);
5404
- if (options.output) {
5405
- await writeFile6(options.output, jsonLd, "utf-8");
5406
- console.log(chalk10.green(`\u2705 FAQ schema written to ${options.output}`));
5407
- } else {
5408
- console.log(chalk10.bold("Generated FAQPage JSON-LD:\n"));
5409
- console.log(chalk10.cyan(jsonLd));
5410
- }
5411
- console.log();
5412
- }
5413
- async function geoAudit() {
5414
- const cwd = process.cwd();
5415
- console.log(chalk10.blue("\n\u{1F50D} GEO Audit\n"));
5416
- const result = {
5417
- identityDefined: false,
5418
- phraseInH1: false,
5419
- phraseInMetaDescription: false,
5420
- hasOrganizationSchema: false,
5421
- hasServiceSchema: false,
5422
- hasFAQSchema: false,
5423
- issues: []
5424
- };
5425
- const config = await loadGeoConfig(cwd);
5426
- if (config.geo?.identityPhrase && config.geo?.shortDescription) {
5427
- result.identityDefined = true;
5428
- console.log(chalk10.green("\u2705 Identity defined"));
5429
- console.log(chalk10.dim(` Phrase: ${config.geo.identityPhrase}`));
5430
- } else {
5431
- result.issues.push('Identity not defined. Run "archon geo identity"');
5432
- console.log(chalk10.red("\u274C Identity not defined"));
5433
- }
5434
- const htmlFiles = await glob2("**/index.html", { cwd, ignore: ["**/node_modules/**", "**/dist/**"] });
5435
- const firstHtmlFile = htmlFiles[0];
5436
- if (firstHtmlFile && config.geo?.identityPhrase) {
5437
- const indexPath = join8(cwd, firstHtmlFile);
5438
- const content = await readFile6(indexPath, "utf-8");
5439
- const identityPhrase = config.geo.identityPhrase;
5440
- const firstKeyword = identityPhrase.toLowerCase().split(" ")[0] ?? "";
5441
- const h1Match = content.match(/<h1[^>]*>(.*?)<\/h1>/is);
5442
- if (h1Match?.[1] && h1Match[1].toLowerCase().includes(firstKeyword)) {
5443
- result.phraseInH1 = true;
5444
- console.log(chalk10.green("\u2705 Brand keyword in H1"));
5445
- } else {
5446
- result.issues.push("Brand phrase keyword not found in H1");
5447
- console.log(chalk10.yellow("[!] Brand keyword not in H1"));
5448
- }
5449
- const metaMatch = content.match(/<meta[^>]*name=["']description["'][^>]*content=["']([^"']*)["']/i);
5450
- if (metaMatch?.[1] && metaMatch[1].toLowerCase().includes(firstKeyword)) {
5451
- result.phraseInMetaDescription = true;
5452
- console.log(chalk10.green("\u2705 Brand keyword in meta description"));
5453
- } else {
5454
- result.issues.push("Brand phrase keyword not found in meta description");
5455
- console.log(chalk10.yellow("[!] Brand keyword not in meta description"));
5456
- }
5457
- if (content.includes("application/ld+json")) {
5458
- if (content.includes('"@type":"Organization"') || content.includes('"@type": "Organization"')) {
5459
- result.hasOrganizationSchema = true;
5460
- console.log(chalk10.green("\u2705 Organization schema present"));
5461
- } else {
5462
- result.issues.push("Organization schema not found");
5463
- console.log(chalk10.yellow("[!] Organization schema missing"));
5464
- }
5465
- if (content.includes('"@type":"Service"') || content.includes('"@type": "Service"')) {
5466
- result.hasServiceSchema = true;
5467
- console.log(chalk10.green("\u2705 Service schema present"));
5468
- } else {
5469
- result.issues.push("Service schema not found");
5470
- console.log(chalk10.yellow("[!] Service schema missing"));
5471
- }
5472
- if (content.includes('"@type":"FAQPage"') || content.includes('"@type": "FAQPage"')) {
5473
- result.hasFAQSchema = true;
5474
- console.log(chalk10.green("\u2705 FAQPage schema present"));
5475
- } else {
5476
- result.issues.push("FAQPage schema not found");
5477
- console.log(chalk10.yellow("[!] FAQPage schema missing"));
5478
- }
5479
- } else {
5480
- result.issues.push("No JSON-LD schemas found");
5481
- console.log(chalk10.red("\u274C No JSON-LD schemas found"));
5482
- }
5483
- } else if (htmlFiles.length === 0) {
5484
- result.issues.push("No index.html found");
5485
- console.log(chalk10.yellow("[!] No index.html found to audit"));
5486
- }
5487
- console.log();
5488
- const passed = result.issues.length === 0;
5489
- if (passed) {
5490
- console.log(chalk10.green.bold("\u2705 GEO Audit Passed"));
5491
- } else {
5492
- console.log(chalk10.yellow.bold(`[!] ${result.issues.length} issue(s) found`));
5493
- console.log();
5494
- console.log(chalk10.bold("Recommendations:"));
5495
- result.issues.forEach((issue, i) => {
5496
- console.log(chalk10.dim(` ${i + 1}. ${issue}`));
5497
- });
5498
- }
5499
- console.log();
5500
- }
5501
- function createGeoCommand() {
5502
- const geo = new Command2("geo").description("GEO (Generative Engine Optimization) for AI-powered SEO").addHelpText(
5503
- "after",
5504
- `
5505
- Examples:
5506
- archon geo identity Generate brand identity phrases
5507
- archon geo schema Generate JSON-LD Organization/Service schemas
5508
- archon geo schema --apply Insert JSON-LD into homepage
5509
- archon geo faq Generate FAQPage schema
5510
- archon geo audit Check GEO compliance status
5511
- `
5512
- );
5513
- geo.command("identity").description("Generate and save brand identity (7-word phrase + 50-word description)").action(async () => {
5514
- await geoIdentity();
5515
- });
5516
- geo.command("schema").description("Generate JSON-LD Organization and Service schemas").option("-o, --output <file>", "Write schema to file").option("-a, --apply", "Insert schema into homepage <head>").action(async (options) => {
5517
- await geoSchema(options);
5518
- });
5519
- geo.command("faq").description("Generate FAQPage JSON-LD schema").option("-o, --output <file>", "Write FAQ schema to file").action(async (options) => {
5520
- await geoFaq(options);
5521
- });
5522
- geo.command("audit").description("Audit GEO compliance (identity, schemas, placement)").action(async () => {
5523
- await geoAudit();
5524
- });
5525
- geo.action(async () => {
5526
- await geoAudit();
5527
- });
5528
- return geo;
5529
- }
5530
-
5531
- // src/cli/seo.ts
5532
- import { Command as Command3 } from "commander";
5533
- import chalk11 from "chalk";
5534
- import { readFile as readFile7, writeFile as writeFile7, mkdir as mkdir5 } from "fs/promises";
5535
- import { existsSync as existsSync10 } from "fs";
5536
- import { join as join9 } from "path";
5537
- import { createInterface as createInterface3 } from "readline";
5538
- import { glob as glob3 } from "glob";
5539
- var SEO_CHECKS = {
5540
- title: {
5541
- name: "Title Tag",
5542
- regex: /<title[^>]*>.*?<\/title>/is,
5543
- required: true,
5544
- recommendation: "Add a <title> tag with 50-60 characters describing the page"
5545
- },
5546
- metaDescription: {
5547
- name: "Meta Description",
5548
- regex: /<meta[^>]*name=["']description["'][^>]*>/i,
5549
- required: true,
5550
- recommendation: 'Add <meta name="description" content="..."> with 150-160 characters'
5551
- },
5552
- viewport: {
5553
- name: "Viewport Meta",
5554
- regex: /<meta[^>]*name=["']viewport["'][^>]*>/i,
5555
- required: true,
5556
- recommendation: 'Add <meta name="viewport" content="width=device-width, initial-scale=1">'
5557
- },
5558
- canonical: {
5559
- name: "Canonical URL",
5560
- regex: /<link[^>]*rel=["']canonical["'][^>]*>/i,
5561
- required: false,
5562
- recommendation: 'Add <link rel="canonical" href="https://..."> to specify preferred URL'
5563
- },
5564
- robots: {
5565
- name: "Robots Meta",
5566
- regex: /<meta[^>]*name=["']robots["'][^>]*>/i,
5567
- required: false,
5568
- recommendation: 'Add <meta name="robots" content="index, follow"> for crawl directives'
5569
- },
5570
- ogTitle: {
5571
- name: "Open Graph Title",
5572
- regex: /<meta[^>]*property=["']og:title["'][^>]*>/i,
5573
- required: false,
5574
- recommendation: 'Add <meta property="og:title" content="..."> for social sharing'
5575
- },
5576
- ogDescription: {
5577
- name: "Open Graph Description",
5578
- regex: /<meta[^>]*property=["']og:description["'][^>]*>/i,
5579
- required: false,
5580
- recommendation: 'Add <meta property="og:description" content="..."> for social sharing'
5581
- },
5582
- ogImage: {
5583
- name: "Open Graph Image",
5584
- regex: /<meta[^>]*property=["']og:image["'][^>]*>/i,
5585
- required: false,
5586
- recommendation: 'Add <meta property="og:image" content="https://..."> (1200x630px recommended)'
5587
- },
5588
- ogUrl: {
5589
- name: "Open Graph URL",
5590
- regex: /<meta[^>]*property=["']og:url["'][^>]*>/i,
5591
- required: false,
5592
- recommendation: 'Add <meta property="og:url" content="https://..."> for canonical social URL'
5593
- },
5594
- twitterCard: {
5595
- name: "Twitter Card",
5596
- regex: /<meta[^>]*name=["']twitter:card["'][^>]*>/i,
5597
- required: false,
5598
- recommendation: 'Add <meta name="twitter:card" content="summary_large_image">'
5599
- },
5600
- twitterTitle: {
5601
- name: "Twitter Title",
5602
- regex: /<meta[^>]*name=["']twitter:title["'][^>]*>/i,
5603
- required: false,
5604
- recommendation: 'Add <meta name="twitter:title" content="...">'
5605
- },
5606
- twitterDescription: {
5607
- name: "Twitter Description",
5608
- regex: /<meta[^>]*name=["']twitter:description["'][^>]*>/i,
5609
- required: false,
5610
- recommendation: 'Add <meta name="twitter:description" content="...">'
5611
- },
5612
- twitterImage: {
5613
- name: "Twitter Image",
5614
- regex: /<meta[^>]*name=["']twitter:image["'][^>]*>/i,
5615
- required: false,
5616
- recommendation: 'Add <meta name="twitter:image" content="https://...">'
5617
- }
5618
- };
5619
- function createPrompt3() {
5620
- const rl = createInterface3({
5621
- input: process.stdin,
5622
- output: process.stdout
5623
- });
5624
- return {
5625
- ask: (question) => new Promise((resolve) => {
5626
- rl.question(question, resolve);
5627
- }),
5628
- close: () => rl.close()
5629
- };
5630
- }
5631
- async function getWebFiles() {
5632
- const patterns = [
5633
- "**/*.html",
5634
- "**/*.htm",
5635
- "**/*.astro",
5636
- "**/*.jsx",
5637
- "**/*.tsx",
5638
- "**/*.vue",
5639
- "**/*.svelte"
5640
- ];
5641
- const ignorePatterns = ["**/node_modules/**", "**/dist/**", "**/build/**", "**/.next/**"];
5642
- let allFiles = [];
5643
- for (const pattern of patterns) {
5644
- const files = await glob3(pattern, { cwd: process.cwd(), ignore: ignorePatterns });
5645
- allFiles = allFiles.concat(files.map((f) => join9(process.cwd(), f)));
5646
- }
5647
- return allFiles;
5648
- }
5649
- async function scanForSeoIssues(files) {
5650
- const issues = [];
5651
- for (const file of files) {
5652
- try {
5653
- const content = await readFile7(file, "utf-8");
5654
- const relativePath = file.replace(process.cwd() + "/", "");
5655
- for (const [checkId, check] of Object.entries(SEO_CHECKS)) {
5656
- const hasTag = check.regex.test(content);
5657
- if (!hasTag) {
5658
- const severity = check.required ? "critical" : checkId.startsWith("og") || checkId.startsWith("twitter") ? "info" : "warning";
5659
- issues.push({
5660
- file: relativePath,
5661
- issue: `Missing ${check.name}`,
5662
- recommendation: check.recommendation,
5663
- severity
5664
- });
5665
- }
5666
- }
5667
- } catch {
5668
- }
5669
- }
5670
- return issues;
5671
- }
5672
- function findHeadInsertionPoint(content) {
5673
- const headMatch = content.match(/<head[^>]*>/i);
5674
- if (headMatch && headMatch.index !== void 0) {
5675
- const afterHead = headMatch.index + headMatch[0].length;
5676
- const nextLineMatch = content.slice(afterHead).match(/\n(\s*)/);
5677
- const indent = nextLineMatch?.[1] ?? " ";
5678
- return { index: afterHead, indent };
5679
- }
5680
- return null;
5681
- }
5682
- async function seoCheck(options) {
5683
- console.log(chalk11.blue("\n\u{1F50D} SEO Check\n"));
5684
- console.log(chalk11.dim("Scanning for SEO issues...\n"));
5685
- const files = await getWebFiles();
5686
- if (files.length === 0) {
5687
- console.log(chalk11.yellow("No web files found to check."));
5688
- return;
5689
- }
5690
- console.log(chalk11.dim(`Scanning ${files.length} files...
5691
- `));
5692
- const issues = await scanForSeoIssues(files);
5693
- const archonDir = join9(process.cwd(), ".archon");
5694
- if (!existsSync10(archonDir)) {
5695
- await mkdir5(archonDir, { recursive: true });
5696
- }
5697
- const report = {
5698
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
5699
- totalFiles: files.length,
5700
- issuesFound: issues.length,
5701
- issues,
5702
- passed: issues.length === 0
5703
- };
5704
- await writeFile7(join9(archonDir, "seo-report.json"), JSON.stringify(report, null, 2));
5705
- if (issues.length === 0) {
5706
- console.log(chalk11.green("\u2705 SEO Check Passed\n"));
5707
- console.log(chalk11.dim("All essential meta tags are present."));
5708
- return;
5709
- }
5710
- console.log(chalk11.yellow(`[!] ${issues.length} SEO Issues Found
5711
- `));
5712
- const criticalCount = issues.filter((i) => i.severity === "critical").length;
5713
- const warningCount = issues.filter((i) => i.severity === "warning").length;
5714
- const infoCount = issues.filter((i) => i.severity === "info").length;
5715
- console.log(chalk11.dim("Summary:"));
5716
- if (criticalCount > 0) console.log(chalk11.red(` \u2022 ${criticalCount} critical`));
5717
- if (warningCount > 0) console.log(chalk11.yellow(` \u2022 ${warningCount} warning`));
5718
- if (infoCount > 0) console.log(chalk11.dim(` \u2022 ${infoCount} info`));
5719
- console.log();
5720
- console.log(chalk11.bold("File | Issue | Recommendation"));
5721
- console.log(chalk11.dim("\u2500".repeat(100)));
5722
- const issuesByFile = /* @__PURE__ */ new Map();
5723
- for (const issue of issues) {
5724
- const existing = issuesByFile.get(issue.file) || [];
5725
- existing.push(issue);
5726
- issuesByFile.set(issue.file, existing);
5727
- }
5728
- for (const [file, fileIssues] of issuesByFile) {
5729
- const displayFile = file.length > 30 ? "..." + file.slice(-27) : file.padEnd(30);
5730
- for (const issue of fileIssues.slice(0, options.verbose ? 20 : 5)) {
5731
- const color = issue.severity === "critical" ? chalk11.red : issue.severity === "warning" ? chalk11.yellow : chalk11.dim;
5732
- const displayIssue = issue.issue.padEnd(24).slice(0, 24);
5733
- const displayRec = issue.recommendation.slice(0, 50);
5734
- console.log(color(`${displayFile} | ${displayIssue} | ${displayRec}`));
5735
- }
5736
- if (!options.verbose && fileIssues.length > 5) {
5737
- console.log(chalk11.dim(`${"".padEnd(30)} | ... and ${fileIssues.length - 5} more issues`));
5738
- }
5739
- }
5740
- console.log(chalk11.dim(`
5741
- Full report saved to: .archon/seo-report.json`));
5742
- }
5743
- async function seoFix(options) {
5744
- const prompt3 = createPrompt3();
5745
- try {
5746
- console.log(chalk11.blue("\n\u{1F527} SEO Auto-Fix\n"));
5747
- const reportPath = join9(process.cwd(), ".archon/seo-report.json");
5748
- if (!existsSync10(reportPath)) {
5749
- console.log(chalk11.yellow("No SEO report found. Running check first...\n"));
5750
- await seoCheck({});
5751
- }
5752
- const reportContent = await readFile7(reportPath, "utf-8");
5753
- const report = JSON.parse(reportContent);
5754
- if (report.passed || report.issues.length === 0) {
5755
- console.log(chalk11.green("No issues to fix!"));
5756
- return;
5757
- }
5758
- const issuesByFile = /* @__PURE__ */ new Map();
5759
- for (const issue of report.issues) {
5760
- const existing = issuesByFile.get(issue.file) || [];
5761
- existing.push(issue);
5762
- issuesByFile.set(issue.file, existing);
5763
- }
5764
- let totalFixes = 0;
5765
- for (const [file, fileIssues] of issuesByFile) {
5766
- const filePath = join9(process.cwd(), file);
5767
- let content;
5768
- try {
5769
- content = await readFile7(filePath, "utf-8");
5770
- } catch {
5771
- continue;
5772
- }
5773
- const insertPoint = findHeadInsertionPoint(content);
5774
- if (!insertPoint) {
5775
- console.log(chalk11.yellow(` ${file}: No <head> tag found, skipping`));
5776
- continue;
5777
- }
5778
- const tagsToAdd = [];
5779
- for (const issue of fileIssues) {
5780
- if (issue.issue === "Missing Title Tag") {
5781
- tagsToAdd.push("<title>Page Title - Site Name</title>");
5782
- } else if (issue.issue === "Missing Meta Description") {
5783
- tagsToAdd.push('<meta name="description" content="Add your page description here (150-160 characters recommended)">');
5784
- } else if (issue.issue === "Missing Viewport Meta") {
5785
- tagsToAdd.push('<meta name="viewport" content="width=device-width, initial-scale=1">');
5786
- } else if (issue.issue === "Missing Canonical URL") {
5787
- tagsToAdd.push('<link rel="canonical" href="https://example.com/page">');
5788
- } else if (issue.issue === "Missing Robots Meta") {
5789
- tagsToAdd.push('<meta name="robots" content="index, follow">');
5790
- }
5791
- }
5792
- if (tagsToAdd.length === 0) continue;
5793
- const newContent = content.slice(0, insertPoint.index) + "\n" + tagsToAdd.map((tag) => insertPoint.indent + tag).join("\n") + content.slice(insertPoint.index);
5794
- console.log(chalk11.cyan(`
5795
- ${file}:`));
5796
- for (const tag of tagsToAdd) {
5797
- console.log(chalk11.green(` + ${tag.slice(0, 70)}${tag.length > 70 ? "..." : ""}`));
5798
- }
5799
- if (!options.dryRun) {
5800
- const confirm = await prompt3.ask(chalk11.dim(" Apply these changes? (y/N): "));
5801
- if (confirm.toLowerCase() === "y") {
5802
- await writeFile7(filePath, newContent);
5803
- totalFixes += tagsToAdd.length;
5804
- console.log(chalk11.green(" \u2713 Applied"));
5805
- } else {
5806
- console.log(chalk11.dim(" Skipped"));
5807
- }
5808
- } else {
5809
- totalFixes += tagsToAdd.length;
5810
- }
5811
- }
5812
- if (totalFixes === 0) {
5813
- console.log(chalk11.dim("\nNo auto-fixable issues found. Some issues require manual configuration."));
5814
- } else if (options.dryRun) {
5815
- console.log(chalk11.yellow(`
5816
- ${totalFixes} fixes would be applied. Run without --dry-run to apply.`));
5817
- } else {
5818
- console.log(chalk11.green(`
5819
- \u2705 Applied ${totalFixes} fixes.`));
5820
- console.log(chalk11.dim('Run "archon seo check" to verify fixes.'));
5821
- }
5822
- } finally {
5823
- prompt3.close();
5824
- }
5825
- }
5826
- async function seoOpenGraph(options) {
5827
- const prompt3 = createPrompt3();
5828
- try {
5829
- console.log(chalk11.blue("\n\u{1F4F1} Add Open Graph Tags\n"));
5830
- let targetFile;
5831
- if (options.file) {
5832
- targetFile = options.file.startsWith("/") ? options.file : join9(process.cwd(), options.file);
5833
- } else {
5834
- const files = await getWebFiles();
5835
- if (files.length === 0) {
5836
- console.log(chalk11.yellow("No web files found."));
5837
- return;
5838
- }
5839
- console.log(chalk11.dim("Available files:"));
5840
- files.slice(0, 10).forEach((f, i) => {
5841
- console.log(` ${i + 1}) ${f.replace(process.cwd() + "/", "")}`);
5842
- });
5843
- if (files.length > 10) {
5844
- console.log(chalk11.dim(` ... and ${files.length - 10} more`));
5845
- }
5846
- const fileChoice = await prompt3.ask("\nEnter file path or number: ");
5847
- const num = parseInt(fileChoice, 10);
5848
- if (num > 0 && num <= files.length) {
5849
- targetFile = files[num - 1] ?? "";
5850
- } else {
5851
- targetFile = fileChoice.startsWith("/") ? fileChoice : join9(process.cwd(), fileChoice);
5852
- }
5853
- }
5854
- if (!existsSync10(targetFile)) {
5855
- console.log(chalk11.red(`File not found: ${targetFile}`));
5856
- return;
5857
- }
5858
- const ogTitle = await prompt3.ask("og:title (page title for social): ");
5859
- const ogDescription = await prompt3.ask("og:description (page description): ");
5860
- const ogImage = await prompt3.ask("og:image (full URL to image): ");
5861
- const ogUrl = await prompt3.ask("og:url (canonical page URL): ");
5862
- const tags = [
5863
- `<meta property="og:type" content="website">`,
5864
- `<meta property="og:title" content="${ogTitle}">`,
5865
- `<meta property="og:description" content="${ogDescription}">`,
5866
- `<meta property="og:image" content="${ogImage}">`,
5867
- `<meta property="og:url" content="${ogUrl}">`
5868
- ];
5869
- const content = await readFile7(targetFile, "utf-8");
5870
- const insertPoint = findHeadInsertionPoint(content);
5871
- if (!insertPoint) {
5872
- console.log(chalk11.yellow("No <head> tag found. Add these tags manually:"));
5873
- tags.forEach((tag) => console.log(chalk11.cyan(` ${tag}`)));
5874
- return;
5875
- }
5876
- console.log(chalk11.dim("\nTags to add:"));
5877
- tags.forEach((tag) => console.log(chalk11.green(` + ${tag}`)));
5878
- const confirm = await prompt3.ask("\nApply changes? (y/N): ");
5879
- if (confirm.toLowerCase() === "y") {
5880
- const newContent = content.slice(0, insertPoint.index) + "\n" + tags.map((tag) => insertPoint.indent + tag).join("\n") + content.slice(insertPoint.index);
5881
- await writeFile7(targetFile, newContent);
5882
- console.log(chalk11.green("\n\u2705 Open Graph tags added."));
5883
- } else {
5884
- console.log(chalk11.dim("Cancelled."));
5885
- }
5886
- } finally {
5887
- prompt3.close();
5888
- }
5889
- }
5890
- async function seoTwitter(options) {
5891
- const prompt3 = createPrompt3();
5892
- try {
5893
- console.log(chalk11.blue("\n\u{1F426} Add Twitter Card Tags\n"));
5894
- let targetFile;
5895
- if (options.file) {
5896
- targetFile = options.file.startsWith("/") ? options.file : join9(process.cwd(), options.file);
5897
- } else {
5898
- const files = await getWebFiles();
5899
- if (files.length === 0) {
5900
- console.log(chalk11.yellow("No web files found."));
5901
- return;
5902
- }
5903
- console.log(chalk11.dim("Available files:"));
5904
- files.slice(0, 10).forEach((f, i) => {
5905
- console.log(` ${i + 1}) ${f.replace(process.cwd() + "/", "")}`);
5906
- });
5907
- if (files.length > 10) {
5908
- console.log(chalk11.dim(` ... and ${files.length - 10} more`));
5909
- }
5910
- const fileChoice = await prompt3.ask("\nEnter file path or number: ");
5911
- const num = parseInt(fileChoice, 10);
5912
- if (num > 0 && num <= files.length) {
5913
- targetFile = files[num - 1] ?? "";
5914
- } else {
5915
- targetFile = fileChoice.startsWith("/") ? fileChoice : join9(process.cwd(), fileChoice);
5916
- }
5917
- }
5918
- if (!existsSync10(targetFile)) {
5919
- console.log(chalk11.red(`File not found: ${targetFile}`));
5920
- return;
5921
- }
5922
- console.log(chalk11.dim("Card types: summary, summary_large_image, app, player"));
5923
- const cardType = await prompt3.ask("twitter:card type (default: summary_large_image): ") || "summary_large_image";
5924
- const twitterTitle = await prompt3.ask("twitter:title: ");
5925
- const twitterDescription = await prompt3.ask("twitter:description: ");
5926
- const twitterImage = await prompt3.ask("twitter:image (full URL): ");
5927
- const tags = [
5928
- `<meta name="twitter:card" content="${cardType}">`,
5929
- `<meta name="twitter:title" content="${twitterTitle}">`,
5930
- `<meta name="twitter:description" content="${twitterDescription}">`,
5931
- `<meta name="twitter:image" content="${twitterImage}">`
5932
- ];
5933
- const content = await readFile7(targetFile, "utf-8");
5934
- const insertPoint = findHeadInsertionPoint(content);
5935
- if (!insertPoint) {
5936
- console.log(chalk11.yellow("No <head> tag found. Add these tags manually:"));
5937
- tags.forEach((tag) => console.log(chalk11.cyan(` ${tag}`)));
5938
- return;
5939
- }
5940
- console.log(chalk11.dim("\nTags to add:"));
5941
- tags.forEach((tag) => console.log(chalk11.green(` + ${tag}`)));
5942
- const confirm = await prompt3.ask("\nApply changes? (y/N): ");
5943
- if (confirm.toLowerCase() === "y") {
5944
- const newContent = content.slice(0, insertPoint.index) + "\n" + tags.map((tag) => insertPoint.indent + tag).join("\n") + content.slice(insertPoint.index);
5945
- await writeFile7(targetFile, newContent);
5946
- console.log(chalk11.green("\n\u2705 Twitter Card tags added."));
5947
- } else {
5948
- console.log(chalk11.dim("Cancelled."));
5949
- }
5950
- } finally {
5951
- prompt3.close();
5952
- }
5953
- }
5954
- function createSeoCommand() {
5955
- const seo = new Command3("seo").description("SEO checking and meta tag management").addHelpText(
5956
- "after",
5957
- `
5958
- Examples:
5959
- archon seo check Scan files for missing SEO meta tags
5960
- archon seo fix Auto-fix missing essential meta tags
5961
- archon seo fix --dry-run Preview fixes without applying
5962
- archon seo og Add Open Graph tags interactively
5963
- archon seo og --file index.html
5964
- archon seo twitter Add Twitter Card tags interactively
5965
- `
5966
- );
5967
- seo.command("check").description("Scan files for missing SEO meta tags").option("-v, --verbose", "Show all issues (not truncated)").action(async (options) => {
5968
- try {
5969
- await seoCheck(options);
5970
- process.exit(0);
5971
- } catch (error) {
5972
- console.error(chalk11.red("Error:"), error instanceof Error ? error.message : error);
5973
- process.exit(1);
5974
- }
5975
- });
5976
- seo.command("fix").description("Auto-fix missing essential meta tags").option("--dry-run", "Preview changes without applying").action(async (options) => {
5977
- try {
5978
- await seoFix(options);
5979
- process.exit(0);
5980
- } catch (error) {
5981
- console.error(chalk11.red("Error:"), error instanceof Error ? error.message : error);
5982
- process.exit(1);
5983
- }
5984
- });
5985
- seo.command("og").description("Add Open Graph meta tags to a file").option("-f, --file <path>", "Target file path").action(async (options) => {
5986
- try {
5987
- await seoOpenGraph(options);
5988
- process.exit(0);
5989
- } catch (error) {
5990
- console.error(chalk11.red("Error:"), error instanceof Error ? error.message : error);
5991
- process.exit(1);
5992
- }
5993
- });
5994
- seo.command("twitter").description("Add Twitter Card meta tags to a file").option("-f, --file <path>", "Target file path").action(async (options) => {
5995
- try {
5996
- await seoTwitter(options);
5997
- process.exit(0);
5998
- } catch (error) {
5999
- console.error(chalk11.red("Error:"), error instanceof Error ? error.message : error);
6000
- process.exit(1);
6001
- }
6002
- });
6003
- return seo;
6004
- }
6005
-
6006
- // src/cli/session.ts
6007
- import chalk12 from "chalk";
6008
- import ora2 from "ora";
6009
- import os from "os";
6010
- import { readFile as readFile8, writeFile as writeFile8 } from "fs/promises";
6011
- import { existsSync as existsSync11 } from "fs";
6012
- import { join as join10 } from "path";
6013
- function getSupabaseClient2(accessToken) {
6014
- return createAuthedSupabaseClient(SUPABASE_URL, SUPABASE_ANON_KEY, accessToken);
6015
- }
6016
- function getDeviceName() {
6017
- return `${os.hostname()}-${os.platform()}-${os.arch()}`;
6018
- }
6019
- async function getProjectInfo(cwd) {
6020
- const archonConfigPath = join10(cwd, ".archon", "config.yaml");
6021
- const packageJsonPath = join10(cwd, "package.json");
6022
- let projectName = "Unknown Project";
6023
- if (existsSync11(packageJsonPath)) {
6024
- try {
6025
- const pkg = JSON.parse(await readFile8(packageJsonPath, "utf-8"));
6026
- projectName = pkg.name || projectName;
6027
- } catch {
6028
- }
6029
- }
6030
- if (!existsSync11(archonConfigPath)) {
6031
- return null;
6032
- }
6033
- return { name: projectName, path: cwd };
6034
- }
6035
- async function getCurrentAtomId(cwd) {
6036
- const stateFile = join10(cwd, ".archon", "state.json");
6037
- if (!existsSync11(stateFile)) return null;
6038
- try {
6039
- const state = JSON.parse(await readFile8(stateFile, "utf-8"));
6040
- return state.currentAtomId || null;
6041
- } catch {
6042
- return null;
6043
- }
6044
- }
6045
- async function getPendingAtoms(cwd) {
6046
- const stateFile = join10(cwd, ".archon", "state.json");
6047
- if (!existsSync11(stateFile)) return [];
6048
- try {
6049
- const state = JSON.parse(await readFile8(stateFile, "utf-8"));
6050
- return state.pendingAtoms || [];
6051
- } catch {
6052
- return [];
6053
- }
6054
- }
6055
- async function getFileContent(path2) {
6056
- if (!existsSync11(path2)) return null;
6057
- try {
6058
- return await readFile8(path2, "utf-8");
6059
- } catch {
6060
- return null;
6061
- }
6062
- }
6063
- async function saveSession(name) {
6064
- const spinner = ora2("Saving session...").start();
6065
- const cwd = process.cwd();
6066
- try {
6067
- const config = await loadConfig();
6068
- if (!config.accessToken || !config.userId) {
6069
- spinner.fail("Not logged in. Run: archon login");
6070
- return;
6071
- }
6072
- const projectInfo = await getProjectInfo(cwd);
6073
- if (!projectInfo) {
6074
- spinner.fail("Not an ArchonDev project. Run: archon init");
6075
- return;
6076
- }
6077
- const supabase = getSupabaseClient2(config.accessToken);
6078
- const { data: profile } = await supabase.from("user_profiles").select("id").eq("auth_id", config.userId).single();
6079
- if (!profile) {
6080
- spinner.fail("Could not find user profile");
5067
+ const supabase = getSupabaseClient2(config.accessToken);
5068
+ const { data: profile } = await supabase.from("user_profiles").select("id").eq("auth_id", config.userId).single();
5069
+ if (!profile) {
5070
+ spinner.fail("Could not find user profile");
6081
5071
  return;
6082
5072
  }
6083
5073
  const currentAtomId = await getCurrentAtomId(cwd);
6084
5074
  const pendingAtoms = await getPendingAtoms(cwd);
6085
- const progressSnapshot = await getFileContent(join10(cwd, "progress.txt"));
6086
- const architectureSnapshot = await getFileContent(join10(cwd, "ARCHITECTURE.md"));
5075
+ const progressSnapshot = await getFileContent(join8(cwd, "progress.txt"));
5076
+ const architectureSnapshot = await getFileContent(join8(cwd, "ARCHITECTURE.md"));
6087
5077
  const sessionData = {
6088
5078
  user_id: profile.id,
6089
5079
  project_name: name || projectInfo.name,
@@ -6100,13 +5090,13 @@ async function saveSession(name) {
6100
5090
  spinner.fail(`Failed to save session: ${error.message}`);
6101
5091
  return;
6102
5092
  }
6103
- spinner.succeed(chalk12.green("Session saved!"));
5093
+ spinner.succeed(chalk9.green("Session saved!"));
6104
5094
  console.log();
6105
- console.log(` ID: ${chalk12.cyan(session.id)}`);
5095
+ console.log(` ID: ${chalk9.cyan(session.id)}`);
6106
5096
  console.log(` Project: ${session.project_name}`);
6107
5097
  console.log(` Device: ${session.last_device}`);
6108
5098
  console.log();
6109
- console.log(chalk12.dim(" Resume on another device: archon session resume " + session.id));
5099
+ console.log(chalk9.dim(" Resume on another device: archon session resume " + session.id));
6110
5100
  console.log();
6111
5101
  } catch (err) {
6112
5102
  spinner.fail("Error saving session");
@@ -6134,23 +5124,23 @@ async function listSessions() {
6134
5124
  }
6135
5125
  spinner.stop();
6136
5126
  if (!sessions || sessions.length === 0) {
6137
- console.log(chalk12.yellow("\nNo saved sessions found.\n"));
6138
- console.log(chalk12.dim(" Save a session: archon session save [name]\n"));
5127
+ console.log(chalk9.yellow("\nNo saved sessions found.\n"));
5128
+ console.log(chalk9.dim(" Save a session: archon session save [name]\n"));
6139
5129
  return;
6140
5130
  }
6141
5131
  console.log();
6142
- console.log(chalk12.bold("\u{1F4C2} Saved Sessions"));
5132
+ console.log(chalk9.bold("\u{1F4C2} Saved Sessions"));
6143
5133
  console.log();
6144
5134
  for (const session of sessions) {
6145
5135
  const date = new Date(session.updated_at).toLocaleDateString();
6146
- const atomInfo = session.current_atom_id ? chalk12.dim(` (atom: ${session.current_atom_id})`) : "";
5136
+ const atomInfo = session.current_atom_id ? chalk9.dim(` (atom: ${session.current_atom_id})`) : "";
6147
5137
  console.log(
6148
- ` ${chalk12.cyan(session.id.slice(0, 8))} ${session.project_name}${atomInfo}`
5138
+ ` ${chalk9.cyan(session.id.slice(0, 8))} ${session.project_name}${atomInfo}`
6149
5139
  );
6150
- console.log(chalk12.dim(` ${date} from ${session.last_device || "unknown device"}`));
5140
+ console.log(chalk9.dim(` ${date} from ${session.last_device || "unknown device"}`));
6151
5141
  console.log();
6152
5142
  }
6153
- console.log(chalk12.dim(" Resume: archon session resume <id>\n"));
5143
+ console.log(chalk9.dim(" Resume: archon session resume <id>\n"));
6154
5144
  } catch (err) {
6155
5145
  spinner.fail("Error fetching sessions");
6156
5146
  console.error(err);
@@ -6177,30 +5167,30 @@ async function resumeSession(sessionId) {
6177
5167
  return;
6178
5168
  }
6179
5169
  const session = sessions[0];
6180
- const stateFile = join10(cwd, ".archon", "state.json");
5170
+ const stateFile = join8(cwd, ".archon", "state.json");
6181
5171
  const state = {
6182
5172
  currentAtomId: session.current_atom_id,
6183
5173
  pendingAtoms: session.pending_atoms,
6184
5174
  resumedFrom: session.id,
6185
5175
  resumedAt: (/* @__PURE__ */ new Date()).toISOString()
6186
5176
  };
6187
- await writeFile8(stateFile, JSON.stringify(state, null, 2));
5177
+ await writeFile5(stateFile, JSON.stringify(state, null, 2));
6188
5178
  if (session.progress_snapshot) {
6189
- const progressPath = join10(cwd, "progress.txt");
6190
- await writeFile8(progressPath, session.progress_snapshot);
5179
+ const progressPath = join8(cwd, "progress.txt");
5180
+ await writeFile5(progressPath, session.progress_snapshot);
6191
5181
  }
6192
5182
  if (session.architecture_snapshot) {
6193
- const archPath = join10(cwd, "ARCHITECTURE.md");
6194
- await writeFile8(archPath, session.architecture_snapshot);
5183
+ const archPath = join8(cwd, "ARCHITECTURE.md");
5184
+ await writeFile5(archPath, session.architecture_snapshot);
6195
5185
  }
6196
5186
  await supabase.from("sessions").update({ last_device: getDeviceName(), updated_at: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", session.id);
6197
- spinner.succeed(chalk12.green("Session resumed!"));
5187
+ spinner.succeed(chalk9.green("Session resumed!"));
6198
5188
  console.log();
6199
5189
  console.log(` Project: ${session.project_name}`);
6200
5190
  console.log(` Current Atom: ${session.current_atom_id || "none"}`);
6201
5191
  console.log(` Pending: ${session.pending_atoms.length} atoms`);
6202
5192
  console.log();
6203
- console.log(chalk12.dim(" Continue working: archon start"));
5193
+ console.log(chalk9.dim(" Continue working: archon start"));
6204
5194
  console.log();
6205
5195
  } catch (err) {
6206
5196
  spinner.fail("Error resuming session");
@@ -6216,12 +5206,12 @@ async function syncSession() {
6216
5206
  spinner.fail("Not logged in. Run: archon login");
6217
5207
  return;
6218
5208
  }
6219
- const stateFile = join10(cwd, ".archon", "state.json");
6220
- if (!existsSync11(stateFile)) {
5209
+ const stateFile = join8(cwd, ".archon", "state.json");
5210
+ if (!existsSync9(stateFile)) {
6221
5211
  spinner.info("No active session to sync");
6222
5212
  return;
6223
5213
  }
6224
- const state = JSON.parse(await readFile8(stateFile, "utf-8"));
5214
+ const state = JSON.parse(await readFile5(stateFile, "utf-8"));
6225
5215
  if (!state.resumedFrom) {
6226
5216
  spinner.info('Session was not resumed from cloud - use "archon session save" to create one');
6227
5217
  return;
@@ -6229,8 +5219,8 @@ async function syncSession() {
6229
5219
  const supabase = getSupabaseClient2(config.accessToken);
6230
5220
  const currentAtomId = await getCurrentAtomId(cwd);
6231
5221
  const pendingAtoms = await getPendingAtoms(cwd);
6232
- const progressSnapshot = await getFileContent(join10(cwd, "progress.txt"));
6233
- const architectureSnapshot = await getFileContent(join10(cwd, "ARCHITECTURE.md"));
5222
+ const progressSnapshot = await getFileContent(join8(cwd, "progress.txt"));
5223
+ const architectureSnapshot = await getFileContent(join8(cwd, "ARCHITECTURE.md"));
6234
5224
  const { error } = await supabase.from("sessions").update({
6235
5225
  current_atom_id: currentAtomId,
6236
5226
  pending_atoms: pendingAtoms,
@@ -6243,7 +5233,7 @@ async function syncSession() {
6243
5233
  spinner.fail(`Failed to sync: ${error.message}`);
6244
5234
  return;
6245
5235
  }
6246
- spinner.succeed(chalk12.green("Session synced to cloud"));
5236
+ spinner.succeed(chalk9.green("Session synced to cloud"));
6247
5237
  } catch (err) {
6248
5238
  spinner.fail("Error syncing session");
6249
5239
  console.error(err);
@@ -6251,66 +5241,66 @@ async function syncSession() {
6251
5241
  }
6252
5242
 
6253
5243
  // src/cli/deploy.ts
6254
- import chalk13 from "chalk";
6255
- import { existsSync as existsSync12 } from "fs";
6256
- import { join as join11 } from "path";
5244
+ import chalk10 from "chalk";
5245
+ import { existsSync as existsSync10 } from "fs";
5246
+ import { join as join9 } from "path";
6257
5247
  import { execSync as execSync3 } from "child_process";
6258
5248
  function detectPlatform(cwd) {
6259
- if (existsSync12(join11(cwd, "fly.toml"))) return "fly";
6260
- if (existsSync12(join11(cwd, "vercel.json"))) return "vercel";
6261
- if (existsSync12(join11(cwd, "netlify.toml"))) return "netlify";
6262
- if (existsSync12(join11(cwd, "railway.json"))) return "railway";
6263
- if (existsSync12(join11(cwd, "render.yaml"))) return "render";
6264
- if (existsSync12(join11(cwd, "Dockerfile"))) return "fly";
5249
+ if (existsSync10(join9(cwd, "fly.toml"))) return "fly";
5250
+ if (existsSync10(join9(cwd, "vercel.json"))) return "vercel";
5251
+ if (existsSync10(join9(cwd, "netlify.toml"))) return "netlify";
5252
+ if (existsSync10(join9(cwd, "railway.json"))) return "railway";
5253
+ if (existsSync10(join9(cwd, "render.yaml"))) return "render";
5254
+ if (existsSync10(join9(cwd, "Dockerfile"))) return "fly";
6265
5255
  return "unknown";
6266
5256
  }
6267
5257
  async function deploy(options) {
6268
5258
  const cwd = process.cwd();
6269
- console.log(chalk13.blue("Running pre-deploy checks..."));
5259
+ console.log(chalk10.blue("Running pre-deploy checks..."));
6270
5260
  const platform = options.platform ?? detectPlatform(cwd);
6271
- console.log(chalk13.dim(`Detected platform: ${platform}`));
5261
+ console.log(chalk10.dim(`Detected platform: ${platform}`));
6272
5262
  if (options.dryRun) {
6273
- console.log(chalk13.dim("Dry run mode - would deploy to:"), platform);
5263
+ console.log(chalk10.dim("Dry run mode - would deploy to:"), platform);
6274
5264
  return;
6275
5265
  }
6276
5266
  switch (platform) {
6277
5267
  case "fly":
6278
- console.log(chalk13.blue("Deploying to Fly.io..."));
5268
+ console.log(chalk10.blue("Deploying to Fly.io..."));
6279
5269
  execSync3("fly deploy", { cwd, stdio: "inherit" });
6280
5270
  break;
6281
5271
  case "vercel": {
6282
- console.log(chalk13.blue("Deploying to Vercel..."));
5272
+ console.log(chalk10.blue("Deploying to Vercel..."));
6283
5273
  const cmd = options.preview ? "vercel" : "vercel --prod";
6284
5274
  execSync3(cmd, { cwd, stdio: "inherit" });
6285
5275
  break;
6286
5276
  }
6287
5277
  case "netlify": {
6288
- console.log(chalk13.blue("Deploying to Netlify..."));
5278
+ console.log(chalk10.blue("Deploying to Netlify..."));
6289
5279
  const netlifyCmd = options.preview ? "netlify deploy" : "netlify deploy --prod";
6290
5280
  execSync3(netlifyCmd, { cwd, stdio: "inherit" });
6291
5281
  break;
6292
5282
  }
6293
5283
  case "railway":
6294
- console.log(chalk13.blue("Deploying to Railway..."));
5284
+ console.log(chalk10.blue("Deploying to Railway..."));
6295
5285
  execSync3("railway up", { cwd, stdio: "inherit" });
6296
5286
  break;
6297
5287
  case "render":
6298
- console.log(chalk13.blue("Deploying to Render..."));
6299
- console.log(chalk13.yellow("Render deploys via git push. Push to your connected branch."));
5288
+ console.log(chalk10.blue("Deploying to Render..."));
5289
+ console.log(chalk10.yellow("Render deploys via git push. Push to your connected branch."));
6300
5290
  break;
6301
5291
  default:
6302
- console.log(chalk13.yellow("Platform not detected. Please specify with --platform"));
6303
- console.log(chalk13.dim("Supported: fly, vercel, netlify, railway, render"));
5292
+ console.log(chalk10.yellow("Platform not detected. Please specify with --platform"));
5293
+ console.log(chalk10.dim("Supported: fly, vercel, netlify, railway, render"));
6304
5294
  }
6305
5295
  }
6306
5296
 
6307
5297
  // src/cli/index-cmd.ts
6308
- import chalk14 from "chalk";
5298
+ import chalk11 from "chalk";
6309
5299
 
6310
5300
  // src/core/indexing/local.ts
6311
- import { existsSync as existsSync13, mkdirSync } from "fs";
6312
- import { readFile as readFile9 } from "fs/promises";
6313
- import { join as join12, extname } from "path";
5301
+ import { existsSync as existsSync11, mkdirSync } from "fs";
5302
+ import { readFile as readFile6 } from "fs/promises";
5303
+ import { join as join10, extname } from "path";
6314
5304
  import Database from "better-sqlite3";
6315
5305
  var CHUNK_SIZE = 1e3;
6316
5306
  var CHUNK_OVERLAP = 200;
@@ -6357,11 +5347,11 @@ var LocalIndexer = class {
6357
5347
  };
6358
5348
  }
6359
5349
  async init(cwd) {
6360
- const archonDir = join12(cwd, ".archon");
6361
- if (!existsSync13(archonDir)) {
5350
+ const archonDir = join10(cwd, ".archon");
5351
+ if (!existsSync11(archonDir)) {
6362
5352
  mkdirSync(archonDir, { recursive: true });
6363
5353
  }
6364
- this.db = new Database(join12(cwd, this.config.dbPath));
5354
+ this.db = new Database(join10(cwd, this.config.dbPath));
6365
5355
  this.db.exec(`
6366
5356
  CREATE TABLE IF NOT EXISTS embeddings (
6367
5357
  id INTEGER PRIMARY KEY,
@@ -6411,11 +5401,11 @@ var LocalIndexer = class {
6411
5401
  if (!this.isIndexableFile(filePath)) {
6412
5402
  return 0;
6413
5403
  }
6414
- const fullPath = join12(cwd, filePath);
6415
- if (!existsSync13(fullPath)) {
5404
+ const fullPath = join10(cwd, filePath);
5405
+ if (!existsSync11(fullPath)) {
6416
5406
  return 0;
6417
5407
  }
6418
- const content = await readFile9(fullPath, "utf-8");
5408
+ const content = await readFile6(fullPath, "utf-8");
6419
5409
  const chunks = this.chunkText(content);
6420
5410
  const deleteStmt = this.db.prepare("DELETE FROM embeddings WHERE file_path = ?");
6421
5411
  deleteStmt.run(filePath);
@@ -6493,9 +5483,9 @@ var LocalIndexer = class {
6493
5483
 
6494
5484
  // src/core/indexing/cloud.ts
6495
5485
  import { createClient } from "@supabase/supabase-js";
6496
- import { readFile as readFile10 } from "fs/promises";
6497
- import { existsSync as existsSync14 } from "fs";
6498
- import { join as join13, extname as extname2 } from "path";
5486
+ import { readFile as readFile7 } from "fs/promises";
5487
+ import { existsSync as existsSync12 } from "fs";
5488
+ import { join as join11, extname as extname2 } from "path";
6499
5489
  import { createHash as createHash2 } from "crypto";
6500
5490
  var CHUNK_SIZE2 = 1e3;
6501
5491
  var CHUNK_OVERLAP2 = 200;
@@ -6622,11 +5612,11 @@ var CloudIndexer = class {
6622
5612
  if (!this.isIndexableFile(filePath)) {
6623
5613
  return 0;
6624
5614
  }
6625
- const fullPath = join13(cwd, filePath);
6626
- if (!existsSync14(fullPath)) {
5615
+ const fullPath = join11(cwd, filePath);
5616
+ if (!existsSync12(fullPath)) {
6627
5617
  return 0;
6628
5618
  }
6629
- const content = await readFile10(fullPath, "utf-8");
5619
+ const content = await readFile7(fullPath, "utf-8");
6630
5620
  const fileHash = await this.computeFileHash(content);
6631
5621
  const { data: existing } = await this.client.from("code_embeddings").select("file_hash").eq("user_id", this.userId).eq("project_id", this.config.projectId).eq("file_path", filePath).eq("chunk_index", 0).single();
6632
5622
  if (existing && existing.file_hash === fileHash) {
@@ -6713,20 +5703,20 @@ var CloudIndexer = class {
6713
5703
  };
6714
5704
 
6715
5705
  // src/cli/index-cmd.ts
6716
- import { glob as glob4 } from "glob";
6717
- import { join as join14, basename } from "path";
5706
+ import { glob } from "glob";
5707
+ import { join as join12, basename } from "path";
6718
5708
  async function getCloudIndexer(cwd) {
6719
5709
  const config = await loadConfig();
6720
5710
  const authToken = getAuthToken(config);
6721
5711
  if (!authToken) {
6722
- console.error(chalk14.red('Not authenticated. Run "archon login" first.'));
5712
+ console.error(chalk11.red('Not authenticated. Run "archon login" first.'));
6723
5713
  return null;
6724
5714
  }
6725
5715
  const openaiKey = process.env["OPENAI_API_KEY"];
6726
5716
  if (!openaiKey) {
6727
- console.error(chalk14.red("OPENAI_API_KEY environment variable not set."));
6728
- console.log(chalk14.dim("Cloud indexing requires an OpenAI API key for embeddings."));
6729
- console.log(chalk14.dim("Set it with: export OPENAI_API_KEY=sk-..."));
5717
+ console.error(chalk11.red("OPENAI_API_KEY environment variable not set."));
5718
+ console.log(chalk11.dim("Cloud indexing requires an OpenAI API key for embeddings."));
5719
+ console.log(chalk11.dim("Set it with: export OPENAI_API_KEY=sk-..."));
6730
5720
  return null;
6731
5721
  }
6732
5722
  const projectId = basename(cwd);
@@ -6737,15 +5727,18 @@ async function getCloudIndexer(cwd) {
6737
5727
  embeddingApiKey: openaiKey,
6738
5728
  projectId
6739
5729
  });
6740
- const client = createAuthedSupabaseClient(SUPABASE_URL, SUPABASE_ANON_KEY, authToken);
5730
+ const { createClient: createClient2 } = await import("@supabase/supabase-js");
5731
+ const client = createClient2(SUPABASE_URL, SUPABASE_ANON_KEY, {
5732
+ global: { headers: { Authorization: `Bearer ${authToken}` } }
5733
+ });
6741
5734
  const { data: { user } } = await client.auth.getUser();
6742
5735
  if (!user) {
6743
- console.error(chalk14.red("Failed to get user. Try logging in again."));
5736
+ console.error(chalk11.red("Failed to get user. Try logging in again."));
6744
5737
  return null;
6745
5738
  }
6746
5739
  const { data: profile } = await client.from("user_profiles").select("id").eq("auth_id", user.id).single();
6747
5740
  if (!profile) {
6748
- console.error(chalk14.red("User profile not found."));
5741
+ console.error(chalk11.red("User profile not found."));
6749
5742
  return null;
6750
5743
  }
6751
5744
  indexer.setUserId(profile.id);
@@ -6754,21 +5747,21 @@ async function getCloudIndexer(cwd) {
6754
5747
  async function indexInit(options) {
6755
5748
  const cwd = process.cwd();
6756
5749
  if (options.cloud) {
6757
- console.log(chalk14.blue("Initializing cloud semantic index..."));
5750
+ console.log(chalk11.blue("Initializing cloud semantic index..."));
6758
5751
  const indexer = await getCloudIndexer(cwd);
6759
5752
  if (!indexer) return;
6760
5753
  try {
6761
5754
  const status2 = await indexer.getStatus();
6762
- console.log(chalk14.green("\u2713 Cloud indexing configured"));
6763
- console.log(chalk14.green(`\u2713 Project ID: ${status2.projectId}`));
6764
- console.log(chalk14.dim("\nRun `archon index update --cloud` to index your codebase."));
5755
+ console.log(chalk11.green("\u2713 Cloud indexing configured"));
5756
+ console.log(chalk11.green(`\u2713 Project ID: ${status2.projectId}`));
5757
+ console.log(chalk11.dim("\nRun `archon index update --cloud` to index your codebase."));
6765
5758
  } catch (error) {
6766
- console.error(chalk14.red(`Failed to initialize cloud index: ${error instanceof Error ? error.message : String(error)}`));
5759
+ console.error(chalk11.red(`Failed to initialize cloud index: ${error instanceof Error ? error.message : String(error)}`));
6767
5760
  process.exit(1);
6768
5761
  }
6769
5762
  return;
6770
5763
  }
6771
- console.log(chalk14.blue("Initializing local semantic index..."));
5764
+ console.log(chalk11.blue("Initializing local semantic index..."));
6772
5765
  try {
6773
5766
  const indexer = new LocalIndexer();
6774
5767
  await indexer.init(cwd);
@@ -6776,18 +5769,18 @@ async function indexInit(options) {
6776
5769
  if (!response.ok) {
6777
5770
  throw new Error("Ollama not responding");
6778
5771
  }
6779
- console.log(chalk14.green("\u2713 Ollama connection verified"));
6780
- console.log(chalk14.green("\u2713 Index database created at .archon/index.db"));
6781
- console.log(chalk14.dim("\nRun `archon index update` to index your codebase."));
5772
+ console.log(chalk11.green("\u2713 Ollama connection verified"));
5773
+ console.log(chalk11.green("\u2713 Index database created at .archon/index.db"));
5774
+ console.log(chalk11.dim("\nRun `archon index update` to index your codebase."));
6782
5775
  indexer.close();
6783
5776
  } catch (error) {
6784
5777
  if (error instanceof Error && error.message.includes("Ollama")) {
6785
- console.log(chalk14.red("\n\u2717 Ollama is not running"));
6786
- console.log(chalk14.dim("Start Ollama with: ollama serve"));
6787
- console.log(chalk14.dim("Then pull the embedding model: ollama pull nomic-embed-text"));
6788
- console.log(chalk14.dim("\nOr use cloud indexing: archon index init --cloud"));
5778
+ console.log(chalk11.red("\n\u2717 Ollama is not running"));
5779
+ console.log(chalk11.dim("Start Ollama with: ollama serve"));
5780
+ console.log(chalk11.dim("Then pull the embedding model: ollama pull nomic-embed-text"));
5781
+ console.log(chalk11.dim("\nOr use cloud indexing: archon index init --cloud"));
6789
5782
  } else {
6790
- console.error(chalk14.red(`Failed to initialize index: ${error instanceof Error ? error.message : String(error)}`));
5783
+ console.error(chalk11.red(`Failed to initialize index: ${error instanceof Error ? error.message : String(error)}`));
6791
5784
  }
6792
5785
  process.exit(1);
6793
5786
  }
@@ -6795,23 +5788,23 @@ async function indexInit(options) {
6795
5788
  async function indexUpdate(options) {
6796
5789
  const cwd = process.cwd();
6797
5790
  if (options?.cloud) {
6798
- console.log(chalk14.blue("Updating cloud semantic index..."));
5791
+ console.log(chalk11.blue("Updating cloud semantic index..."));
6799
5792
  const indexer = await getCloudIndexer(cwd);
6800
5793
  if (!indexer) return;
6801
5794
  try {
6802
- const files = await glob4("**/*.{ts,tsx,js,jsx,py,rb,go,rs,java,md,json,yaml,yml}", {
5795
+ const files = await glob("**/*.{ts,tsx,js,jsx,py,rb,go,rs,java,md,json,yaml,yml}", {
6803
5796
  cwd,
6804
5797
  ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**", "**/build/**", "**/coverage/**"]
6805
5798
  });
6806
- console.log(chalk14.dim(`Found ${files.length} files to index...`));
6807
- console.log(chalk14.dim("This may take a few minutes and will use OpenAI API credits.\n"));
5799
+ console.log(chalk11.dim(`Found ${files.length} files to index...`));
5800
+ console.log(chalk11.dim("This may take a few minutes and will use OpenAI API credits.\n"));
6808
5801
  let totalChunks = 0;
6809
5802
  let indexedFiles = 0;
6810
5803
  let skippedFiles = 0;
6811
5804
  for (let i = 0; i < files.length; i++) {
6812
5805
  const file = files[i];
6813
5806
  if (!file) continue;
6814
- process.stdout.write(`\r${chalk14.dim(`[${i + 1}/${files.length}] ${file.slice(0, 45).padEnd(45)}`)}`);
5807
+ process.stdout.write(`\r${chalk11.dim(`[${i + 1}/${files.length}] ${file.slice(0, 45).padEnd(45)}`)}`);
6815
5808
  try {
6816
5809
  const chunks = await indexer.indexFile(cwd, file);
6817
5810
  if (chunks > 0) {
@@ -6822,34 +5815,34 @@ async function indexUpdate(options) {
6822
5815
  }
6823
5816
  } catch (error) {
6824
5817
  console.log(`
6825
- ${chalk14.yellow(`[!] Skipped ${file}: ${error instanceof Error ? error.message : "Unknown error"}`)}`);
5818
+ ${chalk11.yellow(`[!] Skipped ${file}: ${error instanceof Error ? error.message : "Unknown error"}`)}`);
6826
5819
  }
6827
5820
  }
6828
5821
  console.log("\r" + " ".repeat(70));
6829
- console.log(chalk14.green(`\u2713 Indexed ${indexedFiles} files (${totalChunks} chunks)`));
5822
+ console.log(chalk11.green(`\u2713 Indexed ${indexedFiles} files (${totalChunks} chunks)`));
6830
5823
  if (skippedFiles > 0) {
6831
- console.log(chalk14.dim(` Skipped ${skippedFiles} unchanged files`));
5824
+ console.log(chalk11.dim(` Skipped ${skippedFiles} unchanged files`));
6832
5825
  }
6833
5826
  } catch (error) {
6834
- console.error(chalk14.red(`Failed to update cloud index: ${error instanceof Error ? error.message : String(error)}`));
5827
+ console.error(chalk11.red(`Failed to update cloud index: ${error instanceof Error ? error.message : String(error)}`));
6835
5828
  process.exit(1);
6836
5829
  }
6837
5830
  return;
6838
5831
  }
6839
- console.log(chalk14.blue("Updating local semantic index..."));
5832
+ console.log(chalk11.blue("Updating local semantic index..."));
6840
5833
  try {
6841
5834
  const indexer = new LocalIndexer();
6842
5835
  await indexer.init(cwd);
6843
- const files = await glob4("**/*.{ts,tsx,js,jsx,py,rb,go,rs,java,md,json,yaml,yml}", {
5836
+ const files = await glob("**/*.{ts,tsx,js,jsx,py,rb,go,rs,java,md,json,yaml,yml}", {
6844
5837
  cwd,
6845
5838
  ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**", "**/build/**", "**/coverage/**"]
6846
5839
  });
6847
- console.log(chalk14.dim(`Found ${files.length} files to index...`));
5840
+ console.log(chalk11.dim(`Found ${files.length} files to index...`));
6848
5841
  let totalChunks = 0;
6849
5842
  let indexedFiles = 0;
6850
5843
  for (const file of files) {
6851
5844
  if (!file) continue;
6852
- process.stdout.write(`\r${chalk14.dim(`Indexing: ${file.slice(0, 50).padEnd(50)}`)}`);
5845
+ process.stdout.write(`\r${chalk11.dim(`Indexing: ${file.slice(0, 50).padEnd(50)}`)}`);
6853
5846
  const chunks = await indexer.indexFile(cwd, file);
6854
5847
  if (chunks > 0) {
6855
5848
  totalChunks += chunks;
@@ -6857,10 +5850,10 @@ ${chalk14.yellow(`[!] Skipped ${file}: ${error instanceof Error ? error.message
6857
5850
  }
6858
5851
  }
6859
5852
  console.log("\r" + " ".repeat(60));
6860
- console.log(chalk14.green(`\u2713 Indexed ${indexedFiles} files (${totalChunks} chunks)`));
5853
+ console.log(chalk11.green(`\u2713 Indexed ${indexedFiles} files (${totalChunks} chunks)`));
6861
5854
  indexer.close();
6862
5855
  } catch (error) {
6863
- console.error(chalk14.red(`Failed to update index: ${error instanceof Error ? error.message : String(error)}`));
5856
+ console.error(chalk11.red(`Failed to update index: ${error instanceof Error ? error.message : String(error)}`));
6864
5857
  process.exit(1);
6865
5858
  }
6866
5859
  }
@@ -6870,25 +5863,25 @@ async function indexSearch(query, options) {
6870
5863
  const indexer = await getCloudIndexer(cwd);
6871
5864
  if (!indexer) return;
6872
5865
  try {
6873
- console.log(chalk14.dim("Searching cloud index..."));
5866
+ console.log(chalk11.dim("Searching cloud index..."));
6874
5867
  const results = await indexer.search(query, 10);
6875
5868
  if (results.length === 0) {
6876
- console.log(chalk14.yellow("\nNo results found."));
6877
- console.log(chalk14.dim("Try running `archon index update --cloud` first."));
5869
+ console.log(chalk11.yellow("\nNo results found."));
5870
+ console.log(chalk11.dim("Try running `archon index update --cloud` first."));
6878
5871
  } else {
6879
- console.log(chalk14.blue(`
5872
+ console.log(chalk11.blue(`
6880
5873
  Top ${results.length} results for: "${query}"
6881
5874
  `));
6882
5875
  for (const result of results) {
6883
5876
  const score = (result.score * 100).toFixed(1);
6884
- console.log(chalk14.green(`[${score}%] ${result.file}`));
5877
+ console.log(chalk11.green(`[${score}%] ${result.file}`));
6885
5878
  const preview = result.text.slice(0, 200).replace(/\n/g, " ").trim();
6886
- console.log(chalk14.dim(` ${preview}${result.text.length > 200 ? "..." : ""}`));
5879
+ console.log(chalk11.dim(` ${preview}${result.text.length > 200 ? "..." : ""}`));
6887
5880
  console.log();
6888
5881
  }
6889
5882
  }
6890
5883
  } catch (error) {
6891
- console.error(chalk14.red(`Cloud search failed: ${error instanceof Error ? error.message : String(error)}`));
5884
+ console.error(chalk11.red(`Cloud search failed: ${error instanceof Error ? error.message : String(error)}`));
6892
5885
  process.exit(1);
6893
5886
  }
6894
5887
  return;
@@ -6898,23 +5891,23 @@ Top ${results.length} results for: "${query}"
6898
5891
  await indexer.init(cwd);
6899
5892
  const results = await indexer.search(query, 10);
6900
5893
  if (results.length === 0) {
6901
- console.log(chalk14.yellow("No results found."));
6902
- console.log(chalk14.dim("Try running `archon index update` first."));
5894
+ console.log(chalk11.yellow("No results found."));
5895
+ console.log(chalk11.dim("Try running `archon index update` first."));
6903
5896
  } else {
6904
- console.log(chalk14.blue(`
5897
+ console.log(chalk11.blue(`
6905
5898
  Top ${results.length} results for: "${query}"
6906
5899
  `));
6907
5900
  for (const result of results) {
6908
5901
  const score = (result.score * 100).toFixed(1);
6909
- console.log(chalk14.green(`[${score}%] ${result.file}`));
5902
+ console.log(chalk11.green(`[${score}%] ${result.file}`));
6910
5903
  const preview = result.text.slice(0, 200).replace(/\n/g, " ").trim();
6911
- console.log(chalk14.dim(` ${preview}${result.text.length > 200 ? "..." : ""}`));
5904
+ console.log(chalk11.dim(` ${preview}${result.text.length > 200 ? "..." : ""}`));
6912
5905
  console.log();
6913
5906
  }
6914
5907
  }
6915
5908
  indexer.close();
6916
5909
  } catch (error) {
6917
- console.error(chalk14.red(`Search failed: ${error instanceof Error ? error.message : String(error)}`));
5910
+ console.error(chalk11.red(`Search failed: ${error instanceof Error ? error.message : String(error)}`));
6918
5911
  process.exit(1);
6919
5912
  }
6920
5913
  }
@@ -6925,17 +5918,17 @@ async function indexStatus(options) {
6925
5918
  if (!indexer) return;
6926
5919
  try {
6927
5920
  const status2 = await indexer.getStatus();
6928
- console.log(chalk14.blue("\nCloud Semantic Index Status\n"));
6929
- console.log(` Project ID: ${chalk14.green(status2.projectId)}`);
6930
- console.log(` Files indexed: ${chalk14.green(status2.fileCount)}`);
6931
- console.log(` Total chunks: ${chalk14.green(status2.chunkCount)}`);
6932
- console.log(` Last updated: ${status2.lastUpdated ? chalk14.dim(status2.lastUpdated) : chalk14.yellow("Never")}`);
5921
+ console.log(chalk11.blue("\nCloud Semantic Index Status\n"));
5922
+ console.log(` Project ID: ${chalk11.green(status2.projectId)}`);
5923
+ console.log(` Files indexed: ${chalk11.green(status2.fileCount)}`);
5924
+ console.log(` Total chunks: ${chalk11.green(status2.chunkCount)}`);
5925
+ console.log(` Last updated: ${status2.lastUpdated ? chalk11.dim(status2.lastUpdated) : chalk11.yellow("Never")}`);
6933
5926
  if (status2.jobStatus) {
6934
- console.log(` Job status: ${chalk14.dim(status2.jobStatus)}`);
5927
+ console.log(` Job status: ${chalk11.dim(status2.jobStatus)}`);
6935
5928
  }
6936
- console.log(` Storage: ${chalk14.dim("Supabase pgvector")}`);
5929
+ console.log(` Storage: ${chalk11.dim("Supabase pgvector")}`);
6937
5930
  } catch (error) {
6938
- console.error(chalk14.red(`Failed to get cloud status: ${error instanceof Error ? error.message : String(error)}`));
5931
+ console.error(chalk11.red(`Failed to get cloud status: ${error instanceof Error ? error.message : String(error)}`));
6939
5932
  process.exit(1);
6940
5933
  }
6941
5934
  return;
@@ -6944,14 +5937,14 @@ async function indexStatus(options) {
6944
5937
  const indexer = new LocalIndexer();
6945
5938
  await indexer.init(cwd);
6946
5939
  const status2 = await indexer.getStatus();
6947
- console.log(chalk14.blue("\nLocal Semantic Index Status\n"));
6948
- console.log(` Files indexed: ${chalk14.green(status2.fileCount)}`);
6949
- console.log(` Total chunks: ${chalk14.green(status2.chunkCount)}`);
6950
- console.log(` Last updated: ${status2.lastUpdated ? chalk14.dim(status2.lastUpdated) : chalk14.yellow("Never")}`);
6951
- console.log(` Database: ${chalk14.dim(join14(cwd, ".archon/index.db"))}`);
5940
+ console.log(chalk11.blue("\nLocal Semantic Index Status\n"));
5941
+ console.log(` Files indexed: ${chalk11.green(status2.fileCount)}`);
5942
+ console.log(` Total chunks: ${chalk11.green(status2.chunkCount)}`);
5943
+ console.log(` Last updated: ${status2.lastUpdated ? chalk11.dim(status2.lastUpdated) : chalk11.yellow("Never")}`);
5944
+ console.log(` Database: ${chalk11.dim(join12(cwd, ".archon/index.db"))}`);
6952
5945
  indexer.close();
6953
5946
  } catch (error) {
6954
- console.error(chalk14.red(`Failed to get status: ${error instanceof Error ? error.message : String(error)}`));
5947
+ console.error(chalk11.red(`Failed to get status: ${error instanceof Error ? error.message : String(error)}`));
6955
5948
  process.exit(1);
6956
5949
  }
6957
5950
  }
@@ -6961,30 +5954,30 @@ async function indexClear(options) {
6961
5954
  const indexer = await getCloudIndexer(cwd);
6962
5955
  if (!indexer) return;
6963
5956
  try {
6964
- console.log(chalk14.yellow("Clearing cloud index..."));
5957
+ console.log(chalk11.yellow("Clearing cloud index..."));
6965
5958
  await indexer.clearProject();
6966
- console.log(chalk14.green("\u2713 Cloud index cleared"));
5959
+ console.log(chalk11.green("\u2713 Cloud index cleared"));
6967
5960
  } catch (error) {
6968
- console.error(chalk14.red(`Failed to clear cloud index: ${error instanceof Error ? error.message : String(error)}`));
5961
+ console.error(chalk11.red(`Failed to clear cloud index: ${error instanceof Error ? error.message : String(error)}`));
6969
5962
  process.exit(1);
6970
5963
  }
6971
5964
  return;
6972
5965
  }
6973
- console.log(chalk14.yellow("To clear local index, delete .archon/index.db"));
5966
+ console.log(chalk11.yellow("To clear local index, delete .archon/index.db"));
6974
5967
  }
6975
5968
 
6976
5969
  // src/cli/github.ts
6977
- import chalk15 from "chalk";
5970
+ import chalk12 from "chalk";
6978
5971
  import open2 from "open";
6979
5972
  var API_URL2 = process.env["ARCHONDEV_API_URL"] ?? "https://archondev-api.fly.dev";
6980
5973
  async function githubConnect() {
6981
5974
  const config = await loadConfig();
6982
5975
  const authToken = getAuthToken(config);
6983
5976
  if (!authToken) {
6984
- console.error(chalk15.red('Not authenticated. Run "archon login" first.'));
5977
+ console.error(chalk12.red('Not authenticated. Run "archon login" first.'));
6985
5978
  process.exit(1);
6986
5979
  }
6987
- console.log(chalk15.dim("Starting GitHub connection..."));
5980
+ console.log(chalk12.dim("Starting GitHub connection..."));
6988
5981
  try {
6989
5982
  const response = await fetch(`${API_URL2}/api/github/connect`, {
6990
5983
  headers: {
@@ -6993,18 +5986,18 @@ async function githubConnect() {
6993
5986
  });
6994
5987
  if (!response.ok) {
6995
5988
  const error = await response.json();
6996
- console.error(chalk15.red(error.error ?? "Failed to start GitHub connection"));
5989
+ console.error(chalk12.red(error.error ?? "Failed to start GitHub connection"));
6997
5990
  process.exit(1);
6998
5991
  }
6999
5992
  const data = await response.json();
7000
- console.log(chalk15.dim("\nOpening browser for GitHub authorization..."));
7001
- console.log(chalk15.dim("If browser does not open, visit:"));
7002
- console.log(chalk15.blue(data.url));
5993
+ console.log(chalk12.dim("\nOpening browser for GitHub authorization..."));
5994
+ console.log(chalk12.dim("If browser does not open, visit:"));
5995
+ console.log(chalk12.blue(data.url));
7003
5996
  await open2(data.url);
7004
- console.log(chalk15.dim("\nComplete the authorization in your browser."));
7005
- console.log(chalk15.dim('Then run "archon github status" to verify connection.'));
5997
+ console.log(chalk12.dim("\nComplete the authorization in your browser."));
5998
+ console.log(chalk12.dim('Then run "archon github status" to verify connection.'));
7006
5999
  } catch (error) {
7007
- console.error(chalk15.red(error instanceof Error ? error.message : "Failed to connect"));
6000
+ console.error(chalk12.red(error instanceof Error ? error.message : "Failed to connect"));
7008
6001
  process.exit(1);
7009
6002
  }
7010
6003
  }
@@ -7012,7 +6005,7 @@ async function githubStatus() {
7012
6005
  const config = await loadConfig();
7013
6006
  const authToken = getAuthToken(config);
7014
6007
  if (!authToken) {
7015
- console.error(chalk15.red('Not authenticated. Run "archon login" first.'));
6008
+ console.error(chalk12.red('Not authenticated. Run "archon login" first.'));
7016
6009
  process.exit(1);
7017
6010
  }
7018
6011
  try {
@@ -7023,20 +6016,20 @@ async function githubStatus() {
7023
6016
  });
7024
6017
  if (!response.ok) {
7025
6018
  const error = await response.json();
7026
- console.error(chalk15.red(error.error ?? "Failed to get GitHub status"));
6019
+ console.error(chalk12.red(error.error ?? "Failed to get GitHub status"));
7027
6020
  process.exit(1);
7028
6021
  }
7029
6022
  const data = await response.json();
7030
6023
  if (data.connected) {
7031
- console.log(chalk15.green("\u2713 GitHub connected"));
7032
- console.log(chalk15.dim(` Username: ${data.username}`));
7033
- console.log(chalk15.dim(` Connected: ${data.connectedAt ? new Date(data.connectedAt).toLocaleDateString() : "Unknown"}`));
6024
+ console.log(chalk12.green("\u2713 GitHub connected"));
6025
+ console.log(chalk12.dim(` Username: ${data.username}`));
6026
+ console.log(chalk12.dim(` Connected: ${data.connectedAt ? new Date(data.connectedAt).toLocaleDateString() : "Unknown"}`));
7034
6027
  } else {
7035
- console.log(chalk15.yellow("GitHub not connected"));
7036
- console.log(chalk15.dim('Run "archon github connect" to connect your GitHub account.'));
6028
+ console.log(chalk12.yellow("GitHub not connected"));
6029
+ console.log(chalk12.dim('Run "archon github connect" to connect your GitHub account.'));
7037
6030
  }
7038
6031
  } catch (error) {
7039
- console.error(chalk15.red(error instanceof Error ? error.message : "Failed to get status"));
6032
+ console.error(chalk12.red(error instanceof Error ? error.message : "Failed to get status"));
7040
6033
  process.exit(1);
7041
6034
  }
7042
6035
  }
@@ -7044,7 +6037,7 @@ async function githubDisconnect() {
7044
6037
  const config = await loadConfig();
7045
6038
  const authToken = getAuthToken(config);
7046
6039
  if (!authToken) {
7047
- console.error(chalk15.red('Not authenticated. Run "archon login" first.'));
6040
+ console.error(chalk12.red('Not authenticated. Run "archon login" first.'));
7048
6041
  process.exit(1);
7049
6042
  }
7050
6043
  try {
@@ -7056,62 +6049,62 @@ async function githubDisconnect() {
7056
6049
  });
7057
6050
  if (!response.ok) {
7058
6051
  const error = await response.json();
7059
- console.error(chalk15.red(error.error ?? "Failed to disconnect GitHub"));
6052
+ console.error(chalk12.red(error.error ?? "Failed to disconnect GitHub"));
7060
6053
  process.exit(1);
7061
6054
  }
7062
- console.log(chalk15.green("\u2713 GitHub disconnected"));
6055
+ console.log(chalk12.green("\u2713 GitHub disconnected"));
7063
6056
  } catch (error) {
7064
- console.error(chalk15.red(error instanceof Error ? error.message : "Failed to disconnect"));
6057
+ console.error(chalk12.red(error instanceof Error ? error.message : "Failed to disconnect"));
7065
6058
  process.exit(1);
7066
6059
  }
7067
6060
  }
7068
6061
 
7069
6062
  // src/cli/interview.ts
7070
- import chalk16 from "chalk";
6063
+ import chalk13 from "chalk";
7071
6064
  import readline2 from "readline";
7072
6065
  import ora3 from "ora";
7073
- import { existsSync as existsSync15, readFileSync as readFileSync4, writeFileSync, mkdirSync as mkdirSync2 } from "fs";
7074
- import { join as join15 } from "path";
6066
+ import { existsSync as existsSync13, readFileSync as readFileSync5, writeFileSync, mkdirSync as mkdirSync2 } from "fs";
6067
+ import { join as join13 } from "path";
7075
6068
  import { randomUUID } from "crypto";
7076
6069
  function getConstitutionPath(cwd) {
7077
- return join15(cwd, ".archon", "constitution.json");
6070
+ return join13(cwd, ".archon", "constitution.json");
7078
6071
  }
7079
6072
  function getDraftPath(cwd) {
7080
- return join15(cwd, ".archon", "constitution-draft.json");
6073
+ return join13(cwd, ".archon", "constitution-draft.json");
7081
6074
  }
7082
6075
  async function interview(options = {}) {
7083
6076
  const cwd = process.cwd();
7084
- const archonDir = join15(cwd, ".archon");
7085
- if (!existsSync15(archonDir)) {
6077
+ const archonDir = join13(cwd, ".archon");
6078
+ if (!existsSync13(archonDir)) {
7086
6079
  mkdirSync2(archonDir, { recursive: true });
7087
6080
  }
7088
- console.log(chalk16.bold("\n\u{1F3AF} ArchonDev Project Interview"));
7089
- console.log(chalk16.dim("Let's define what you're building.\n"));
6081
+ console.log(chalk13.bold("\n\u{1F3AF} ArchonDev Project Interview"));
6082
+ console.log(chalk13.dim("Let's define what you're building.\n"));
7090
6083
  const constitutionPath = getConstitutionPath(cwd);
7091
6084
  const draftPath = getDraftPath(cwd);
7092
- if (existsSync15(constitutionPath)) {
7093
- const existing = deserializeConstitution(readFileSync4(constitutionPath, "utf-8"));
6085
+ if (existsSync13(constitutionPath)) {
6086
+ const existing = deserializeConstitution(readFileSync5(constitutionPath, "utf-8"));
7094
6087
  if (existing.state === "FROZEN") {
7095
- console.log(chalk16.yellow("[!] A frozen Constitution already exists."));
7096
- console.log(chalk16.dim(` Project: ${existing.branding.projectName}`));
7097
- console.log(chalk16.dim(` Frozen: ${existing.frozenAt?.toISOString()}`));
6088
+ console.log(chalk13.yellow("[!] A frozen Constitution already exists."));
6089
+ console.log(chalk13.dim(` Project: ${existing.branding.projectName}`));
6090
+ console.log(chalk13.dim(` Frozen: ${existing.frozenAt?.toISOString()}`));
7098
6091
  console.log();
7099
6092
  const action = await prompt2("Start a new interview (overwrite) or view existing? (new/view)");
7100
6093
  if (action.toLowerCase() === "view") {
7101
6094
  console.log("\n" + summarizeConstitution(existing));
7102
6095
  return;
7103
6096
  } else if (action.toLowerCase() !== "new") {
7104
- console.log(chalk16.dim("Cancelled."));
6097
+ console.log(chalk13.dim("Cancelled."));
7105
6098
  return;
7106
6099
  }
7107
6100
  }
7108
6101
  }
7109
6102
  let constitution;
7110
6103
  let startPhase = 1;
7111
- if (existsSync15(draftPath) && options.resume !== false) {
7112
- const draft = deserializeConstitution(readFileSync4(draftPath, "utf-8"));
7113
- console.log(chalk16.blue("[i] Found draft from previous session."));
7114
- console.log(chalk16.dim(` Project: ${draft.branding.projectName || "(unnamed)"}`));
6104
+ if (existsSync13(draftPath) && options.resume !== false) {
6105
+ const draft = deserializeConstitution(readFileSync5(draftPath, "utf-8"));
6106
+ console.log(chalk13.blue("[i] Found draft from previous session."));
6107
+ console.log(chalk13.dim(` Project: ${draft.branding.projectName || "(unnamed)"}`));
7115
6108
  console.log();
7116
6109
  const resumeChoice = await prompt2("Resume draft or start fresh? (resume/fresh)");
7117
6110
  if (resumeChoice.toLowerCase() === "resume") {
@@ -7123,7 +6116,7 @@ async function interview(options = {}) {
7123
6116
  break;
7124
6117
  }
7125
6118
  }
7126
- console.log(chalk16.green(`
6119
+ console.log(chalk13.green(`
7127
6120
  \u2713 Resuming at Phase ${startPhase}: ${INTERVIEW_PHASES[startPhase]?.name}
7128
6121
  `));
7129
6122
  } else {
@@ -7134,19 +6127,19 @@ async function interview(options = {}) {
7134
6127
  }
7135
6128
  if (options.phase && options.phase >= 1 && options.phase <= 5) {
7136
6129
  startPhase = options.phase;
7137
- console.log(chalk16.dim(`Starting at Phase ${startPhase}...
6130
+ console.log(chalk13.dim(`Starting at Phase ${startPhase}...
7138
6131
  `));
7139
6132
  }
7140
- console.log(chalk16.dim("\u2500".repeat(40)));
7141
- console.log(chalk16.dim(formatProgressBar(startPhase)));
7142
- console.log(chalk16.dim("\u2500".repeat(40)));
6133
+ console.log(chalk13.dim("\u2500".repeat(40)));
6134
+ console.log(chalk13.dim(formatProgressBar(startPhase)));
6135
+ console.log(chalk13.dim("\u2500".repeat(40)));
7143
6136
  console.log();
7144
6137
  let currentPhase = startPhase;
7145
6138
  while (currentPhase <= 5) {
7146
6139
  const result = await runPhase(currentPhase, constitution, cwd);
7147
6140
  if (result.action === "exit") {
7148
6141
  saveDraft(cwd, constitution);
7149
- console.log(chalk16.dim("\nDraft saved. Run `archon interview` to resume.\n"));
6142
+ console.log(chalk13.dim("\nDraft saved. Run `archon interview` to resume.\n"));
7150
6143
  return;
7151
6144
  }
7152
6145
  if (result.action === "back" && currentPhase > 1) {
@@ -7161,9 +6154,9 @@ async function interview(options = {}) {
7161
6154
  if (next) {
7162
6155
  currentPhase = next;
7163
6156
  console.log();
7164
- console.log(chalk16.dim("\u2500".repeat(40)));
7165
- console.log(chalk16.dim(formatProgressBar(currentPhase)));
7166
- console.log(chalk16.dim("\u2500".repeat(40)));
6157
+ console.log(chalk13.dim("\u2500".repeat(40)));
6158
+ console.log(chalk13.dim(formatProgressBar(currentPhase)));
6159
+ console.log(chalk13.dim("\u2500".repeat(40)));
7167
6160
  console.log();
7168
6161
  } else {
7169
6162
  break;
@@ -7171,9 +6164,9 @@ async function interview(options = {}) {
7171
6164
  }
7172
6165
  const validationResult = validateConstitution(constitution);
7173
6166
  if (!validationResult.valid) {
7174
- console.log(chalk16.red("\n[!] Constitution has validation errors:\n"));
6167
+ console.log(chalk13.red("\n[!] Constitution has validation errors:\n"));
7175
6168
  for (const error of validationResult.errors) {
7176
- console.log(chalk16.red(` \u2022 ${error}`));
6169
+ console.log(chalk13.red(` \u2022 ${error}`));
7177
6170
  }
7178
6171
  console.log();
7179
6172
  const fix = await promptYesNo2("Would you like to go back and fix these?", true);
@@ -7183,9 +6176,9 @@ async function interview(options = {}) {
7183
6176
  }
7184
6177
  }
7185
6178
  if (validationResult.warnings.length > 0) {
7186
- console.log(chalk16.yellow("\n[!] Warnings:\n"));
6179
+ console.log(chalk13.yellow("\n[!] Warnings:\n"));
7187
6180
  for (const warning of validationResult.warnings) {
7188
- console.log(chalk16.yellow(` \u2022 ${warning}`));
6181
+ console.log(chalk13.yellow(` \u2022 ${warning}`));
7189
6182
  }
7190
6183
  console.log();
7191
6184
  }
@@ -7195,21 +6188,21 @@ async function interview(options = {}) {
7195
6188
  constitution.costs = estimateCosts(constitution, config.tier || "FREE");
7196
6189
  const challengeResult = analyzeForChallenges(constitution);
7197
6190
  if (challengeResult.shouldChallenge) {
7198
- console.log(chalk16.bold("\n\u{1F3AF} Challenge Mode\n"));
7199
- console.log(chalk16.dim("Let me share some observations about your project scope...\n"));
6191
+ console.log(chalk13.bold("\n\u{1F3AF} Challenge Mode\n"));
6192
+ console.log(chalk13.dim("Let me share some observations about your project scope...\n"));
7200
6193
  for (const challenge of challengeResult.challenges) {
7201
6194
  const prompt3 = generateChallengePrompt(challenge);
7202
- const icon = challenge.severity === "critical" ? chalk16.red("\u25CF") : chalk16.yellow("\u25CF");
7203
- console.log(`${icon} ${chalk16.bold(challenge.title)}`);
7204
- console.log(chalk16.dim(` ${prompt3}`));
6195
+ const icon = challenge.severity === "critical" ? chalk13.red("\u25CF") : chalk13.yellow("\u25CF");
6196
+ console.log(`${icon} ${chalk13.bold(challenge.title)}`);
6197
+ console.log(chalk13.dim(` ${prompt3}`));
7205
6198
  console.log();
7206
6199
  }
7207
- console.log(chalk16.dim("\u2500".repeat(40)));
6200
+ console.log(chalk13.dim("\u2500".repeat(40)));
7208
6201
  console.log(summarizeChallenges(challengeResult));
7209
- console.log(chalk16.dim("\u2500".repeat(40)));
6202
+ console.log(chalk13.dim("\u2500".repeat(40)));
7210
6203
  console.log();
7211
6204
  if (challengeResult.featuresToDefer.length > 0) {
7212
- console.log(chalk16.bold("Suggested Features to Defer to Post-MVP:\n"));
6205
+ console.log(chalk13.bold("Suggested Features to Defer to Post-MVP:\n"));
7213
6206
  for (const feature of challengeResult.featuresToDefer) {
7214
6207
  console.log(` \u2022 ${feature.name}`);
7215
6208
  }
@@ -7224,58 +6217,58 @@ async function interview(options = {}) {
7224
6217
  constitution.complexity = calculateComplexity(constitution);
7225
6218
  constitution.estimatedBuildHours = estimateBuildHours(constitution.complexity);
7226
6219
  constitution.costs = estimateCosts(constitution, config.tier || "FREE");
7227
- console.log(chalk16.green("\n\u2713 Features deferred. Updated estimates:"));
7228
- console.log(chalk16.dim(` Complexity: ${constitution.complexity.tier}`));
7229
- console.log(chalk16.dim(` Build time: ~${Math.round(constitution.estimatedBuildHours)} hours`));
6220
+ console.log(chalk13.green("\n\u2713 Features deferred. Updated estimates:"));
6221
+ console.log(chalk13.dim(` Complexity: ${constitution.complexity.tier}`));
6222
+ console.log(chalk13.dim(` Build time: ~${Math.round(constitution.estimatedBuildHours)} hours`));
7230
6223
  console.log();
7231
6224
  saveDraft(cwd, constitution);
7232
6225
  }
7233
6226
  }
7234
6227
  const criticalCount = challengeResult.challenges.filter((c) => c.severity === "critical").length;
7235
6228
  if (criticalCount > 0) {
7236
- console.log(chalk16.red(`
6229
+ console.log(chalk13.red(`
7237
6230
  \u26A0\uFE0F ${criticalCount} critical issue(s) detected.`));
7238
6231
  const proceed = await promptYesNo2("Proceed anyway?", false);
7239
6232
  if (!proceed) {
7240
6233
  saveDraft(cwd, constitution);
7241
- console.log(chalk16.dim("\nDraft saved. Address the issues and run `archon interview` again.\n"));
6234
+ console.log(chalk13.dim("\nDraft saved. Address the issues and run `archon interview` again.\n"));
7242
6235
  return;
7243
6236
  }
7244
6237
  }
7245
6238
  } else {
7246
- console.log(chalk16.green("\n\u2713 Scope looks reasonable! No major concerns detected.\n"));
6239
+ console.log(chalk13.green("\n\u2713 Scope looks reasonable! No major concerns detected.\n"));
7247
6240
  }
7248
- console.log(chalk16.bold("\n\u{1F4CB} Constitution Summary\n"));
6241
+ console.log(chalk13.bold("\n\u{1F4CB} Constitution Summary\n"));
7249
6242
  console.log(summarizeConstitution(constitution));
7250
6243
  console.log();
7251
6244
  if (options.dryRun) {
7252
- console.log(chalk16.dim("(Dry run mode - not freezing Constitution)"));
6245
+ console.log(chalk13.dim("(Dry run mode - not freezing Constitution)"));
7253
6246
  saveDraft(cwd, constitution);
7254
6247
  return;
7255
6248
  }
7256
6249
  const confirmFreeze = await promptYesNo2("Freeze this Constitution and start building?", true);
7257
6250
  if (!confirmFreeze) {
7258
6251
  saveDraft(cwd, constitution);
7259
- console.log(chalk16.dim("\nDraft saved. Run `archon interview` to continue.\n"));
6252
+ console.log(chalk13.dim("\nDraft saved. Run `archon interview` to continue.\n"));
7260
6253
  return;
7261
6254
  }
7262
6255
  const spinner = ora3("Freezing Constitution...").start();
7263
6256
  try {
7264
6257
  const frozen = freezeConstitution(constitution);
7265
6258
  writeFileSync(constitutionPath, serializeConstitution(frozen));
7266
- if (existsSync15(draftPath)) {
6259
+ if (existsSync13(draftPath)) {
7267
6260
  const { unlinkSync } = await import("fs");
7268
6261
  unlinkSync(draftPath);
7269
6262
  }
7270
- spinner.succeed(chalk16.green("Constitution frozen!"));
6263
+ spinner.succeed(chalk13.green("Constitution frozen!"));
7271
6264
  console.log();
7272
- console.log(chalk16.dim(`Hash: ${frozen.hash?.substring(0, 32)}...`));
7273
- console.log(chalk16.dim(`Saved: ${constitutionPath}`));
6265
+ console.log(chalk13.dim(`Hash: ${frozen.hash?.substring(0, 32)}...`));
6266
+ console.log(chalk13.dim(`Saved: ${constitutionPath}`));
7274
6267
  console.log();
7275
- console.log(chalk16.bold("Next Steps:\n"));
7276
- console.log(` ${chalk16.cyan("1.")} Run ${chalk16.bold("archon generate")} to create atoms from this Constitution`);
7277
- console.log(` ${chalk16.cyan("2.")} Run ${chalk16.bold("archon list")} to see generated atoms`);
7278
- console.log(` ${chalk16.cyan("3.")} Run ${chalk16.bold("archon execute <atom-id>")} to start building`);
6268
+ console.log(chalk13.bold("Next Steps:\n"));
6269
+ console.log(` ${chalk13.cyan("1.")} Run ${chalk13.bold("archon generate")} to create atoms from this Constitution`);
6270
+ console.log(` ${chalk13.cyan("2.")} Run ${chalk13.bold("archon list")} to see generated atoms`);
6271
+ console.log(` ${chalk13.cyan("3.")} Run ${chalk13.bold("archon execute <atom-id>")} to start building`);
7279
6272
  console.log();
7280
6273
  } catch (err) {
7281
6274
  spinner.fail("Failed to freeze Constitution");
@@ -7284,18 +6277,18 @@ async function interview(options = {}) {
7284
6277
  }
7285
6278
  async function runPhase(phase, constitution, cwd) {
7286
6279
  const phaseInfo = INTERVIEW_PHASES[phase];
7287
- console.log(chalk16.bold(`Phase ${phase}: ${phaseInfo.name}`));
7288
- console.log(chalk16.dim(phaseInfo.description));
6280
+ console.log(chalk13.bold(`Phase ${phase}: ${phaseInfo.name}`));
6281
+ console.log(chalk13.dim(phaseInfo.description));
7289
6282
  console.log();
7290
6283
  const skippable = getSkippableQuestions(phase, constitution);
7291
6284
  let updatedConstitution = { ...constitution };
7292
6285
  for (const question of phaseInfo.questions) {
7293
6286
  if (skippable.includes(question.id)) {
7294
- console.log(chalk16.dim(`[\u2713] ${question.prompt.split("?")[0]}... (already answered)`));
6287
+ console.log(chalk13.dim(`[\u2713] ${question.prompt.split("?")[0]}... (already answered)`));
7295
6288
  continue;
7296
6289
  }
7297
6290
  if (phase === 5 && question.id === "review_summary") {
7298
- console.log(chalk16.bold("\n\u{1F4CB} Current State:\n"));
6291
+ console.log(chalk13.bold("\n\u{1F4CB} Current State:\n"));
7299
6292
  console.log(summarizeConstitution(updatedConstitution));
7300
6293
  console.log();
7301
6294
  }
@@ -7312,14 +6305,14 @@ async function runPhase(phase, constitution, cwd) {
7312
6305
  if (question.validator) {
7313
6306
  const validation = question.validator(answer);
7314
6307
  if (!validation.valid) {
7315
- console.log(chalk16.red(` ${validation.error}`));
6308
+ console.log(chalk13.red(` ${validation.error}`));
7316
6309
  continue;
7317
6310
  }
7318
6311
  }
7319
6312
  const extracted = question.extractor(answer, updatedConstitution);
7320
6313
  updatedConstitution = { ...updatedConstitution, ...extracted };
7321
6314
  if (question.followUp && answer.length > 10) {
7322
- console.log(chalk16.dim(` ${question.followUp}`));
6315
+ console.log(chalk13.dim(` ${question.followUp}`));
7323
6316
  }
7324
6317
  }
7325
6318
  return { action: "next", constitution: updatedConstitution };
@@ -7329,7 +6322,7 @@ function saveDraft(cwd, constitution) {
7329
6322
  writeFileSync(draftPath, serializeConstitution(constitution));
7330
6323
  }
7331
6324
  async function promptQuestion(question) {
7332
- const prefix = question.required ? chalk16.red("*") : " ";
6325
+ const prefix = question.required ? chalk13.red("*") : " ";
7333
6326
  return prompt2(`${prefix} ${question.prompt}`);
7334
6327
  }
7335
6328
  function prompt2(question) {
@@ -7338,7 +6331,7 @@ function prompt2(question) {
7338
6331
  input: process.stdin,
7339
6332
  output: process.stdout
7340
6333
  });
7341
- rl.question(`${chalk16.cyan("?")} ${question}
6334
+ rl.question(`${chalk13.cyan("?")} ${question}
7342
6335
  > `, (answer) => {
7343
6336
  rl.close();
7344
6337
  resolve(answer.trim());
@@ -7352,7 +6345,7 @@ function promptYesNo2(question, defaultValue) {
7352
6345
  output: process.stdout
7353
6346
  });
7354
6347
  const hint = defaultValue ? "(Y/n)" : "(y/N)";
7355
- rl.question(`${chalk16.cyan("?")} ${question} ${hint}: `, (answer) => {
6348
+ rl.question(`${chalk13.cyan("?")} ${question} ${hint}: `, (answer) => {
7356
6349
  rl.close();
7357
6350
  if (answer.trim() === "") {
7358
6351
  resolve(defaultValue);
@@ -7366,51 +6359,51 @@ async function showConstitution() {
7366
6359
  const cwd = process.cwd();
7367
6360
  const constitutionPath = getConstitutionPath(cwd);
7368
6361
  const draftPath = getDraftPath(cwd);
7369
- if (existsSync15(constitutionPath)) {
7370
- const constitution = deserializeConstitution(readFileSync4(constitutionPath, "utf-8"));
6362
+ if (existsSync13(constitutionPath)) {
6363
+ const constitution = deserializeConstitution(readFileSync5(constitutionPath, "utf-8"));
7371
6364
  console.log(summarizeConstitution(constitution));
7372
- } else if (existsSync15(draftPath)) {
7373
- const draft = deserializeConstitution(readFileSync4(draftPath, "utf-8"));
7374
- console.log(chalk16.yellow("[DRAFT]"));
6365
+ } else if (existsSync13(draftPath)) {
6366
+ const draft = deserializeConstitution(readFileSync5(draftPath, "utf-8"));
6367
+ console.log(chalk13.yellow("[DRAFT]"));
7375
6368
  console.log(summarizeConstitution(draft));
7376
6369
  } else {
7377
- console.log(chalk16.dim("No Constitution found. Run `archon interview` to create one."));
6370
+ console.log(chalk13.dim("No Constitution found. Run `archon interview` to create one."));
7378
6371
  }
7379
6372
  }
7380
6373
  async function validateConstitutionCommand() {
7381
6374
  const cwd = process.cwd();
7382
6375
  const constitutionPath = getConstitutionPath(cwd);
7383
6376
  const draftPath = getDraftPath(cwd);
7384
- const path2 = existsSync15(constitutionPath) ? constitutionPath : draftPath;
7385
- if (!existsSync15(path2)) {
7386
- console.log(chalk16.dim("No Constitution found. Run `archon interview` to create one."));
6377
+ const path2 = existsSync13(constitutionPath) ? constitutionPath : draftPath;
6378
+ if (!existsSync13(path2)) {
6379
+ console.log(chalk13.dim("No Constitution found. Run `archon interview` to create one."));
7387
6380
  return;
7388
6381
  }
7389
- const constitution = deserializeConstitution(readFileSync4(path2, "utf-8"));
6382
+ const constitution = deserializeConstitution(readFileSync5(path2, "utf-8"));
7390
6383
  const result = validateConstitution(constitution);
7391
6384
  if (result.valid) {
7392
- console.log(chalk16.green("\u2713 Constitution is valid"));
6385
+ console.log(chalk13.green("\u2713 Constitution is valid"));
7393
6386
  } else {
7394
- console.log(chalk16.red("\u2717 Constitution has errors:"));
6387
+ console.log(chalk13.red("\u2717 Constitution has errors:"));
7395
6388
  for (const error of result.errors) {
7396
- console.log(chalk16.red(` \u2022 ${error}`));
6389
+ console.log(chalk13.red(` \u2022 ${error}`));
7397
6390
  }
7398
6391
  }
7399
6392
  if (result.warnings.length > 0) {
7400
- console.log(chalk16.yellow("\nWarnings:"));
6393
+ console.log(chalk13.yellow("\nWarnings:"));
7401
6394
  for (const warning of result.warnings) {
7402
- console.log(chalk16.yellow(` \u2022 ${warning}`));
6395
+ console.log(chalk13.yellow(` \u2022 ${warning}`));
7403
6396
  }
7404
6397
  }
7405
6398
  }
7406
6399
  async function exportConstitution(format) {
7407
6400
  const cwd = process.cwd();
7408
6401
  const constitutionPath = getConstitutionPath(cwd);
7409
- if (!existsSync15(constitutionPath)) {
7410
- console.log(chalk16.dim("No frozen Constitution found."));
6402
+ if (!existsSync13(constitutionPath)) {
6403
+ console.log(chalk13.dim("No frozen Constitution found."));
7411
6404
  return;
7412
6405
  }
7413
- const constitution = deserializeConstitution(readFileSync4(constitutionPath, "utf-8"));
6406
+ const constitution = deserializeConstitution(readFileSync5(constitutionPath, "utf-8"));
7414
6407
  switch (format.toLowerCase()) {
7415
6408
  case "json":
7416
6409
  console.log(serializeConstitution(constitution));
@@ -7420,26 +6413,26 @@ async function exportConstitution(format) {
7420
6413
  console.log(summarizeConstitution(constitution));
7421
6414
  break;
7422
6415
  default:
7423
- console.log(chalk16.red(`Unknown format: ${format}. Use 'json' or 'markdown'.`));
6416
+ console.log(chalk13.red(`Unknown format: ${format}. Use 'json' or 'markdown'.`));
7424
6417
  }
7425
6418
  }
7426
6419
  async function generateAtoms(options = {}) {
7427
6420
  const cwd = process.cwd();
7428
6421
  const constitutionPath = getConstitutionPath(cwd);
7429
- if (!existsSync15(constitutionPath)) {
7430
- console.log(chalk16.red("No frozen Constitution found."));
7431
- console.log(chalk16.dim("Run `archon interview` to create one first."));
6422
+ if (!existsSync13(constitutionPath)) {
6423
+ console.log(chalk13.red("No frozen Constitution found."));
6424
+ console.log(chalk13.dim("Run `archon interview` to create one first."));
7432
6425
  return;
7433
6426
  }
7434
- const constitution = deserializeConstitution(readFileSync4(constitutionPath, "utf-8"));
6427
+ const constitution = deserializeConstitution(readFileSync5(constitutionPath, "utf-8"));
7435
6428
  if (constitution.state !== "FROZEN") {
7436
- console.log(chalk16.yellow("Constitution is not frozen yet."));
7437
- console.log(chalk16.dim("Complete the interview and freeze before generating atoms."));
6429
+ console.log(chalk13.yellow("Constitution is not frozen yet."));
6430
+ console.log(chalk13.dim("Complete the interview and freeze before generating atoms."));
7438
6431
  return;
7439
6432
  }
7440
- console.log(chalk16.bold("\n\u{1F527} Generating Atoms from Constitution\n"));
7441
- console.log(chalk16.dim(`Project: ${constitution.branding.projectName}`));
7442
- console.log(chalk16.dim(`Hash: ${constitution.hash?.substring(0, 16)}...`));
6433
+ console.log(chalk13.bold("\n\u{1F527} Generating Atoms from Constitution\n"));
6434
+ console.log(chalk13.dim(`Project: ${constitution.branding.projectName}`));
6435
+ console.log(chalk13.dim(`Hash: ${constitution.hash?.substring(0, 16)}...`));
7443
6436
  console.log();
7444
6437
  const spinner = ora3("Generating atoms...").start();
7445
6438
  const result = generateAtomsFromConstitution(constitution, {
@@ -7452,34 +6445,34 @@ async function generateAtoms(options = {}) {
7452
6445
  console.log(summarizeGeneration(result));
7453
6446
  console.log();
7454
6447
  if (options.dryRun) {
7455
- console.log(chalk16.dim("(Dry run - not writing prd.json)"));
6448
+ console.log(chalk13.dim("(Dry run - not writing prd.json)"));
7456
6449
  return;
7457
6450
  }
7458
- const prdPath = options.output ?? join15(cwd, "prd.json");
6451
+ const prdPath = options.output ?? join13(cwd, "prd.json");
7459
6452
  const prdContent = formatAsPrdJson(result, constitution);
7460
- if (existsSync15(prdPath)) {
6453
+ if (existsSync13(prdPath)) {
7461
6454
  const overwrite = await promptYesNo2("prd.json already exists. Overwrite?", false);
7462
6455
  if (!overwrite) {
7463
- console.log(chalk16.dim("Cancelled. Existing prd.json preserved."));
6456
+ console.log(chalk13.dim("Cancelled. Existing prd.json preserved."));
7464
6457
  return;
7465
6458
  }
7466
6459
  }
7467
6460
  writeFileSync(prdPath, JSON.stringify(prdContent, null, 2));
7468
- console.log(chalk16.green(`
6461
+ console.log(chalk13.green(`
7469
6462
  \u2713 Written to ${prdPath}`));
7470
6463
  console.log();
7471
- console.log(chalk16.bold("Next Steps:\n"));
7472
- console.log(` ${chalk16.cyan("1.")} Run ${chalk16.bold("archon list")} to see all atoms`);
7473
- console.log(` ${chalk16.cyan("2.")} Run ${chalk16.bold("archon execute ATOM-001")} to start building`);
7474
- console.log(` ${chalk16.cyan("3.")} Run ${chalk16.bold("archon watch")} to monitor progress`);
6464
+ console.log(chalk13.bold("Next Steps:\n"));
6465
+ console.log(` ${chalk13.cyan("1.")} Run ${chalk13.bold("archon list")} to see all atoms`);
6466
+ console.log(` ${chalk13.cyan("2.")} Run ${chalk13.bold("archon execute ATOM-001")} to start building`);
6467
+ console.log(` ${chalk13.cyan("3.")} Run ${chalk13.bold("archon watch")} to monitor progress`);
7475
6468
  console.log();
7476
6469
  }
7477
6470
 
7478
6471
  // src/cli/eject.ts
7479
- import chalk17 from "chalk";
7480
- import { existsSync as existsSync16, rmSync } from "fs";
7481
- import { readFile as readFile11, writeFile as writeFile9 } from "fs/promises";
7482
- import { join as join16 } from "path";
6472
+ import chalk14 from "chalk";
6473
+ import { existsSync as existsSync14, rmSync } from "fs";
6474
+ import { readFile as readFile8, writeFile as writeFile6 } from "fs/promises";
6475
+ import { join as join14 } from "path";
7483
6476
  import readline3 from "readline";
7484
6477
  var ARCHON_FILES = [
7485
6478
  ".archon/",
@@ -7493,70 +6486,70 @@ var METADATA_FILES = [
7493
6486
  ];
7494
6487
  async function eject(options = {}) {
7495
6488
  const cwd = process.cwd();
7496
- console.log(chalk17.blue("\n\u{1F680} ArchonDev Eject\n"));
7497
- const archonDir = join16(cwd, ".archon");
7498
- if (!existsSync16(archonDir)) {
7499
- console.log(chalk17.yellow("This does not appear to be an ArchonDev project (.archon/ not found)."));
6489
+ console.log(chalk14.blue("\n\u{1F680} ArchonDev Eject\n"));
6490
+ const archonDir = join14(cwd, ".archon");
6491
+ if (!existsSync14(archonDir)) {
6492
+ console.log(chalk14.yellow("This does not appear to be an ArchonDev project (.archon/ not found)."));
7500
6493
  return;
7501
6494
  }
7502
- console.log(chalk17.dim("The following will be removed/modified:\n"));
6495
+ console.log(chalk14.dim("The following will be removed/modified:\n"));
7503
6496
  const filesToRemove = [];
7504
6497
  for (const file of ARCHON_FILES) {
7505
- const filePath = join16(cwd, file);
7506
- if (existsSync16(filePath)) {
6498
+ const filePath = join14(cwd, file);
6499
+ if (existsSync14(filePath)) {
7507
6500
  filesToRemove.push(file);
7508
- console.log(chalk17.red(` \u2717 ${file}`));
6501
+ console.log(chalk14.red(` \u2717 ${file}`));
7509
6502
  }
7510
6503
  }
7511
- const archMd = join16(cwd, "ARCHITECTURE.md");
7512
- if (existsSync16(archMd) && !options.keepArchitecture) {
7513
- console.log(chalk17.yellow(` ? ARCHITECTURE.md (will be kept by default)`));
6504
+ const archMd = join14(cwd, "ARCHITECTURE.md");
6505
+ if (existsSync14(archMd) && !options.keepArchitecture) {
6506
+ console.log(chalk14.yellow(` ? ARCHITECTURE.md (will be kept by default)`));
7514
6507
  }
7515
6508
  console.log();
7516
- console.log(chalk17.dim("Files to be modified:"));
6509
+ console.log(chalk14.dim("Files to be modified:"));
7517
6510
  for (const file of METADATA_FILES) {
7518
- const filePath = join16(cwd, file);
7519
- if (existsSync16(filePath)) {
7520
- console.log(chalk17.yellow(` \u25CF ${file}`));
6511
+ const filePath = join14(cwd, file);
6512
+ if (existsSync14(filePath)) {
6513
+ console.log(chalk14.yellow(` \u25CF ${file}`));
7521
6514
  }
7522
6515
  }
7523
6516
  console.log();
7524
6517
  if (!options.force) {
7525
6518
  const confirmed = await promptYesNo3("This will permanently remove ArchonDev from your project. Continue?", false);
7526
6519
  if (!confirmed) {
7527
- console.log(chalk17.dim("Eject cancelled."));
6520
+ console.log(chalk14.dim("Eject cancelled."));
7528
6521
  return;
7529
6522
  }
7530
6523
  }
7531
6524
  console.log();
7532
6525
  const result = await performEject(cwd, options);
7533
6526
  if (result.success) {
7534
- console.log(chalk17.green("\n\u2705 Eject complete!\n"));
6527
+ console.log(chalk14.green("\n\u2705 Eject complete!\n"));
7535
6528
  if (result.filesRemoved.length > 0) {
7536
- console.log(chalk17.dim("Removed:"));
6529
+ console.log(chalk14.dim("Removed:"));
7537
6530
  for (const file of result.filesRemoved) {
7538
- console.log(chalk17.dim(` - ${file}`));
6531
+ console.log(chalk14.dim(` - ${file}`));
7539
6532
  }
7540
6533
  }
7541
6534
  if (result.filesModified.length > 0) {
7542
- console.log(chalk17.dim("\nModified:"));
6535
+ console.log(chalk14.dim("\nModified:"));
7543
6536
  for (const file of result.filesModified) {
7544
- console.log(chalk17.dim(` - ${file}`));
6537
+ console.log(chalk14.dim(` - ${file}`));
7545
6538
  }
7546
6539
  }
7547
6540
  if (result.warnings.length > 0) {
7548
- console.log(chalk17.yellow("\nWarnings:"));
6541
+ console.log(chalk14.yellow("\nWarnings:"));
7549
6542
  for (const warning of result.warnings) {
7550
- console.log(chalk17.yellow(` \u26A0\uFE0F ${warning}`));
6543
+ console.log(chalk14.yellow(` \u26A0\uFE0F ${warning}`));
7551
6544
  }
7552
6545
  }
7553
6546
  console.log();
7554
- console.log(chalk17.blue("Your project is now a standard repository."));
7555
- console.log(chalk17.dim("Thank you for using ArchonDev!"));
6547
+ console.log(chalk14.blue("Your project is now a standard repository."));
6548
+ console.log(chalk14.dim("Thank you for using ArchonDev!"));
7556
6549
  } else {
7557
- console.log(chalk17.red("\n\u274C Eject failed."));
6550
+ console.log(chalk14.red("\n\u274C Eject failed."));
7558
6551
  for (const warning of result.warnings) {
7559
- console.log(chalk17.red(` ${warning}`));
6552
+ console.log(chalk14.red(` ${warning}`));
7560
6553
  }
7561
6554
  }
7562
6555
  }
@@ -7567,8 +6560,8 @@ async function performEject(cwd, options) {
7567
6560
  filesModified: [],
7568
6561
  warnings: []
7569
6562
  };
7570
- const archonDir = join16(cwd, ".archon");
7571
- if (existsSync16(archonDir)) {
6563
+ const archonDir = join14(cwd, ".archon");
6564
+ if (existsSync14(archonDir)) {
7572
6565
  try {
7573
6566
  rmSync(archonDir, { recursive: true, force: true });
7574
6567
  result.filesRemoved.push(".archon/");
@@ -7576,8 +6569,8 @@ async function performEject(cwd, options) {
7576
6569
  result.warnings.push(`Failed to remove .archon/: ${error instanceof Error ? error.message : "Unknown error"}`);
7577
6570
  }
7578
6571
  }
7579
- const prdPath = join16(cwd, "prd.json");
7580
- if (existsSync16(prdPath)) {
6572
+ const prdPath = join14(cwd, "prd.json");
6573
+ if (existsSync14(prdPath)) {
7581
6574
  try {
7582
6575
  rmSync(prdPath);
7583
6576
  result.filesRemoved.push("prd.json");
@@ -7585,8 +6578,8 @@ async function performEject(cwd, options) {
7585
6578
  result.warnings.push(`Failed to remove prd.json: ${error instanceof Error ? error.message : "Unknown error"}`);
7586
6579
  }
7587
6580
  }
7588
- const progressPath = join16(cwd, "progress.txt");
7589
- if (existsSync16(progressPath)) {
6581
+ const progressPath = join14(cwd, "progress.txt");
6582
+ if (existsSync14(progressPath)) {
7590
6583
  try {
7591
6584
  rmSync(progressPath);
7592
6585
  result.filesRemoved.push("progress.txt");
@@ -7594,8 +6587,8 @@ async function performEject(cwd, options) {
7594
6587
  result.warnings.push(`Failed to remove progress.txt: ${error instanceof Error ? error.message : "Unknown error"}`);
7595
6588
  }
7596
6589
  }
7597
- const promptPath = join16(cwd, "prompt.md");
7598
- if (existsSync16(promptPath)) {
6590
+ const promptPath = join14(cwd, "prompt.md");
6591
+ if (existsSync14(promptPath)) {
7599
6592
  try {
7600
6593
  rmSync(promptPath);
7601
6594
  result.filesRemoved.push("prompt.md");
@@ -7603,10 +6596,10 @@ async function performEject(cwd, options) {
7603
6596
  result.warnings.push(`Failed to remove prompt.md: ${error instanceof Error ? error.message : "Unknown error"}`);
7604
6597
  }
7605
6598
  }
7606
- const pkgPath = join16(cwd, "package.json");
7607
- if (existsSync16(pkgPath)) {
6599
+ const pkgPath = join14(cwd, "package.json");
6600
+ if (existsSync14(pkgPath)) {
7608
6601
  try {
7609
- const pkgContent = await readFile11(pkgPath, "utf-8");
6602
+ const pkgContent = await readFile8(pkgPath, "utf-8");
7610
6603
  const pkg = JSON.parse(pkgContent);
7611
6604
  let modified = false;
7612
6605
  if ("archondev" in pkg) {
@@ -7623,7 +6616,7 @@ async function performEject(cwd, options) {
7623
6616
  }
7624
6617
  }
7625
6618
  if (modified) {
7626
- await writeFile9(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
6619
+ await writeFile6(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
7627
6620
  result.filesModified.push("package.json");
7628
6621
  }
7629
6622
  } catch (error) {
@@ -7631,10 +6624,10 @@ async function performEject(cwd, options) {
7631
6624
  }
7632
6625
  }
7633
6626
  if (!options.keepReadme) {
7634
- const readmePath = join16(cwd, "README.md");
7635
- if (existsSync16(readmePath)) {
6627
+ const readmePath = join14(cwd, "README.md");
6628
+ if (existsSync14(readmePath)) {
7636
6629
  try {
7637
- const content = await readFile11(readmePath, "utf-8");
6630
+ const content = await readFile8(readmePath, "utf-8");
7638
6631
  const archonPatterns = [
7639
6632
  /## ArchonDev[^#]*(?=##|$)/gi,
7640
6633
  /\*This project was scaffolded by ArchonDev\.\*/gi,
@@ -7651,7 +6644,7 @@ async function performEject(cwd, options) {
7651
6644
  }
7652
6645
  newContent = newContent.replace(/\n{3,}/g, "\n\n").trim() + "\n";
7653
6646
  if (modified) {
7654
- await writeFile9(readmePath, newContent);
6647
+ await writeFile6(readmePath, newContent);
7655
6648
  result.filesModified.push("README.md");
7656
6649
  }
7657
6650
  } catch (error) {
@@ -7663,29 +6656,29 @@ async function performEject(cwd, options) {
7663
6656
  }
7664
6657
  async function ejectDryRun() {
7665
6658
  const cwd = process.cwd();
7666
- console.log(chalk17.blue("\n\u{1F50D} Eject Dry Run\n"));
7667
- const archonDir = join16(cwd, ".archon");
7668
- if (!existsSync16(archonDir)) {
7669
- console.log(chalk17.yellow("This does not appear to be an ArchonDev project."));
6659
+ console.log(chalk14.blue("\n\u{1F50D} Eject Dry Run\n"));
6660
+ const archonDir = join14(cwd, ".archon");
6661
+ if (!existsSync14(archonDir)) {
6662
+ console.log(chalk14.yellow("This does not appear to be an ArchonDev project."));
7670
6663
  return;
7671
6664
  }
7672
6665
  console.log("The following would be removed:\n");
7673
6666
  for (const file of ARCHON_FILES) {
7674
- const filePath = join16(cwd, file);
7675
- if (existsSync16(filePath)) {
7676
- console.log(chalk17.red(` \u2717 ${file}`));
6667
+ const filePath = join14(cwd, file);
6668
+ if (existsSync14(filePath)) {
6669
+ console.log(chalk14.red(` \u2717 ${file}`));
7677
6670
  }
7678
6671
  }
7679
6672
  console.log();
7680
6673
  console.log("The following would be modified:\n");
7681
6674
  for (const file of METADATA_FILES) {
7682
- const filePath = join16(cwd, file);
7683
- if (existsSync16(filePath)) {
7684
- console.log(chalk17.yellow(` \u25CF ${file}`));
6675
+ const filePath = join14(cwd, file);
6676
+ if (existsSync14(filePath)) {
6677
+ console.log(chalk14.yellow(` \u25CF ${file}`));
7685
6678
  }
7686
6679
  }
7687
6680
  console.log();
7688
- console.log(chalk17.dim('Run "archon eject" to proceed.'));
6681
+ console.log(chalk14.dim('Run "archon eject" to proceed.'));
7689
6682
  }
7690
6683
  function promptYesNo3(question, defaultValue) {
7691
6684
  return new Promise((resolve) => {
@@ -7694,7 +6687,7 @@ function promptYesNo3(question, defaultValue) {
7694
6687
  output: process.stdout
7695
6688
  });
7696
6689
  const hint = defaultValue ? "(Y/n)" : "(y/N)";
7697
- rl.question(`${chalk17.cyan("?")} ${question} ${hint}: `, (answer) => {
6690
+ rl.question(`${chalk14.cyan("?")} ${question} ${hint}: `, (answer) => {
7698
6691
  rl.close();
7699
6692
  if (answer.trim() === "") {
7700
6693
  resolve(defaultValue);
@@ -7706,11 +6699,11 @@ function promptYesNo3(question, defaultValue) {
7706
6699
  }
7707
6700
 
7708
6701
  // src/cli/revert.ts
7709
- import chalk18 from "chalk";
6702
+ import chalk15 from "chalk";
7710
6703
  import { execSync as execSync4 } from "child_process";
7711
- import { existsSync as existsSync17 } from "fs";
7712
- import { readFile as readFile12, writeFile as writeFile10 } from "fs/promises";
7713
- import { join as join17 } from "path";
6704
+ import { existsSync as existsSync15 } from "fs";
6705
+ import { readFile as readFile9, writeFile as writeFile7 } from "fs/promises";
6706
+ import { join as join15 } from "path";
7714
6707
  import readline4 from "readline";
7715
6708
  async function findAtomCommits(limit = 50) {
7716
6709
  const cwd = process.cwd();
@@ -7751,35 +6744,35 @@ async function findAtomCommits(limit = 50) {
7751
6744
  }
7752
6745
  return commits;
7753
6746
  } catch (error) {
7754
- console.error(chalk18.red("Failed to read git history:"), error instanceof Error ? error.message : "Unknown error");
6747
+ console.error(chalk15.red("Failed to read git history:"), error instanceof Error ? error.message : "Unknown error");
7755
6748
  return [];
7756
6749
  }
7757
6750
  }
7758
6751
  async function historyCommand(options) {
7759
6752
  const limit = options.limit ?? 20;
7760
- console.log(chalk18.blue("\n\u{1F4DC} Atom Execution History\n"));
6753
+ console.log(chalk15.blue("\n\u{1F4DC} Atom Execution History\n"));
7761
6754
  const commits = await findAtomCommits(limit);
7762
6755
  if (commits.length === 0) {
7763
- console.log(chalk18.dim("No atom commits found in git history."));
7764
- console.log(chalk18.dim('Atom commits are created when you run "archon execute <atom-id>".'));
6756
+ console.log(chalk15.dim("No atom commits found in git history."));
6757
+ console.log(chalk15.dim('Atom commits are created when you run "archon execute <atom-id>".'));
7765
6758
  return;
7766
6759
  }
7767
- console.log(chalk18.dim(`Showing ${commits.length} atom commit(s):
6760
+ console.log(chalk15.dim(`Showing ${commits.length} atom commit(s):
7768
6761
  `));
7769
6762
  for (const commit of commits) {
7770
6763
  const shortHash = commit.commitHash.substring(0, 7);
7771
6764
  const filesLabel = commit.filesChanged === 1 ? "file" : "files";
7772
- console.log(`${chalk18.yellow(shortHash)} ${chalk18.cyan(commit.atomId)}`);
7773
- console.log(chalk18.dim(` ${commit.message}`));
7774
- console.log(chalk18.dim(` ${commit.date} | ${commit.filesChanged} ${filesLabel} changed`));
6765
+ console.log(`${chalk15.yellow(shortHash)} ${chalk15.cyan(commit.atomId)}`);
6766
+ console.log(chalk15.dim(` ${commit.message}`));
6767
+ console.log(chalk15.dim(` ${commit.date} | ${commit.filesChanged} ${filesLabel} changed`));
7775
6768
  console.log();
7776
6769
  }
7777
- console.log(chalk18.dim("To revert an atom: archon revert <atom-id>"));
7778
- console.log(chalk18.dim("Or by commit hash: archon revert --commit <hash>"));
6770
+ console.log(chalk15.dim("To revert an atom: archon revert <atom-id>"));
6771
+ console.log(chalk15.dim("Or by commit hash: archon revert --commit <hash>"));
7779
6772
  }
7780
6773
  async function revertCommand(atomIdOrHash, options = {}) {
7781
6774
  const cwd = process.cwd();
7782
- console.log(chalk18.blue("\n\u23EA Atom Revert\n"));
6775
+ console.log(chalk15.blue("\n\u23EA Atom Revert\n"));
7783
6776
  let commit;
7784
6777
  if (atomIdOrHash.match(/^[a-f0-9]{7,40}$/i)) {
7785
6778
  const commits = await findAtomCommits(100);
@@ -7789,76 +6782,76 @@ async function revertCommand(atomIdOrHash, options = {}) {
7789
6782
  commit = commits.find((c) => c.atomId.toLowerCase() === atomIdOrHash.toLowerCase());
7790
6783
  }
7791
6784
  if (!commit) {
7792
- console.log(chalk18.red(`No atom commit found for: ${atomIdOrHash}`));
7793
- console.log(chalk18.dim('Run "archon history" to see available atom commits.'));
6785
+ console.log(chalk15.red(`No atom commit found for: ${atomIdOrHash}`));
6786
+ console.log(chalk15.dim('Run "archon history" to see available atom commits.'));
7794
6787
  return;
7795
6788
  }
7796
- console.log(`Atom: ${chalk18.cyan(commit.atomId)}`);
7797
- console.log(`Commit: ${chalk18.yellow(commit.commitHash.substring(0, 7))}`);
6789
+ console.log(`Atom: ${chalk15.cyan(commit.atomId)}`);
6790
+ console.log(`Commit: ${chalk15.yellow(commit.commitHash.substring(0, 7))}`);
7798
6791
  console.log(`Message: ${commit.message}`);
7799
6792
  console.log(`Date: ${commit.date}`);
7800
6793
  console.log(`Files changed: ${commit.filesChanged}`);
7801
6794
  console.log();
7802
6795
  try {
7803
- console.log(chalk18.dim("Changes to be reverted:"));
6796
+ console.log(chalk15.dim("Changes to be reverted:"));
7804
6797
  const diffStat = execSync4(
7805
6798
  `git diff --stat ${commit.commitHash}^..${commit.commitHash}`,
7806
6799
  { cwd, encoding: "utf-8" }
7807
6800
  );
7808
- console.log(chalk18.dim(diffStat));
6801
+ console.log(chalk15.dim(diffStat));
7809
6802
  } catch {
7810
6803
  }
7811
6804
  if (!options.force) {
7812
6805
  const confirmed = await promptYesNo4("Revert this atom commit?", false);
7813
6806
  if (!confirmed) {
7814
- console.log(chalk18.dim("Revert cancelled."));
6807
+ console.log(chalk15.dim("Revert cancelled."));
7815
6808
  return;
7816
6809
  }
7817
6810
  }
7818
6811
  try {
7819
6812
  const revertArgs = options.noCommit ? "--no-commit" : "";
7820
6813
  execSync4(`git revert ${revertArgs} ${commit.commitHash}`, { cwd, stdio: "pipe" });
7821
- console.log(chalk18.green(`
6814
+ console.log(chalk15.green(`
7822
6815
  \u2705 Successfully reverted ${commit.atomId}`));
7823
6816
  if (options.noCommit) {
7824
- console.log(chalk18.dim("Changes are staged but not committed."));
7825
- console.log(chalk18.dim('Run "git commit" to finalize the revert.'));
6817
+ console.log(chalk15.dim("Changes are staged but not committed."));
6818
+ console.log(chalk15.dim('Run "git commit" to finalize the revert.'));
7826
6819
  } else {
7827
- console.log(chalk18.dim("A new commit has been created to undo the changes."));
6820
+ console.log(chalk15.dim("A new commit has been created to undo the changes."));
7828
6821
  }
7829
6822
  await updateAtomStatus(commit.atomId, "REVERTED");
7830
6823
  } catch (error) {
7831
6824
  const errorMsg = error instanceof Error ? error.message : "Unknown error";
7832
6825
  if (errorMsg.includes("conflict")) {
7833
- console.log(chalk18.yellow("\n\u26A0\uFE0F Merge conflict detected during revert."));
7834
- console.log(chalk18.dim("Resolve conflicts manually, then:"));
7835
- console.log(chalk18.dim(" git add ."));
7836
- console.log(chalk18.dim(" git revert --continue"));
6826
+ console.log(chalk15.yellow("\n\u26A0\uFE0F Merge conflict detected during revert."));
6827
+ console.log(chalk15.dim("Resolve conflicts manually, then:"));
6828
+ console.log(chalk15.dim(" git add ."));
6829
+ console.log(chalk15.dim(" git revert --continue"));
7837
6830
  } else {
7838
- console.log(chalk18.red("\n\u274C Revert failed:"), errorMsg);
7839
- console.log(chalk18.dim("You may need to resolve this manually."));
6831
+ console.log(chalk15.red("\n\u274C Revert failed:"), errorMsg);
6832
+ console.log(chalk15.dim("You may need to resolve this manually."));
7840
6833
  }
7841
6834
  }
7842
6835
  }
7843
6836
  async function updateAtomStatus(atomId, status2) {
7844
- const atomPath = join17(process.cwd(), ".archon", "atoms", `${atomId}.json`);
7845
- if (!existsSync17(atomPath)) {
6837
+ const atomPath = join15(process.cwd(), ".archon", "atoms", `${atomId}.json`);
6838
+ if (!existsSync15(atomPath)) {
7846
6839
  return;
7847
6840
  }
7848
6841
  try {
7849
- const content = await readFile12(atomPath, "utf-8");
6842
+ const content = await readFile9(atomPath, "utf-8");
7850
6843
  const atom = JSON.parse(content);
7851
6844
  atom["status"] = status2;
7852
6845
  atom["revertedAt"] = (/* @__PURE__ */ new Date()).toISOString();
7853
- await writeFile10(atomPath, JSON.stringify(atom, null, 2));
6846
+ await writeFile7(atomPath, JSON.stringify(atom, null, 2));
7854
6847
  } catch {
7855
6848
  }
7856
6849
  }
7857
6850
  async function revertableAtoms() {
7858
- console.log(chalk18.blue("\n\u{1F504} Revertable Atoms\n"));
6851
+ console.log(chalk15.blue("\n\u{1F504} Revertable Atoms\n"));
7859
6852
  const commits = await findAtomCommits(30);
7860
6853
  if (commits.length === 0) {
7861
- console.log(chalk18.dim("No atom commits found."));
6854
+ console.log(chalk15.dim("No atom commits found."));
7862
6855
  return;
7863
6856
  }
7864
6857
  const atomMap = /* @__PURE__ */ new Map();
@@ -7867,14 +6860,14 @@ async function revertableAtoms() {
7867
6860
  atomMap.set(commit.atomId, commit);
7868
6861
  }
7869
6862
  }
7870
- console.log(chalk18.dim(`Found ${atomMap.size} unique atom(s) in history:
6863
+ console.log(chalk15.dim(`Found ${atomMap.size} unique atom(s) in history:
7871
6864
  `));
7872
6865
  for (const [atomId, commit] of atomMap) {
7873
6866
  const shortHash = commit.commitHash.substring(0, 7);
7874
- console.log(` ${chalk18.cyan(atomId)} ${chalk18.dim(`(${shortHash})`)} - ${commit.message.substring(0, 50)}`);
6867
+ console.log(` ${chalk15.cyan(atomId)} ${chalk15.dim(`(${shortHash})`)} - ${commit.message.substring(0, 50)}`);
7875
6868
  }
7876
6869
  console.log();
7877
- console.log(chalk18.dim("To revert: archon revert <atom-id>"));
6870
+ console.log(chalk15.dim("To revert: archon revert <atom-id>"));
7878
6871
  }
7879
6872
  function promptYesNo4(question, defaultValue) {
7880
6873
  return new Promise((resolve) => {
@@ -7883,7 +6876,7 @@ function promptYesNo4(question, defaultValue) {
7883
6876
  output: process.stdout
7884
6877
  });
7885
6878
  const hint = defaultValue ? "(Y/n)" : "(y/N)";
7886
- rl.question(`${chalk18.cyan("?")} ${question} ${hint}: `, (answer) => {
6879
+ rl.question(`${chalk15.cyan("?")} ${question} ${hint}: `, (answer) => {
7887
6880
  rl.close();
7888
6881
  if (answer.trim() === "") {
7889
6882
  resolve(defaultValue);
@@ -7894,13 +6887,110 @@ function promptYesNo4(question, defaultValue) {
7894
6887
  });
7895
6888
  }
7896
6889
 
6890
+ // src/cli/models-sync.ts
6891
+ import chalk16 from "chalk";
6892
+ async function modelsSync(options) {
6893
+ const supabaseUrl = process.env["SUPABASE_URL"];
6894
+ const supabaseKey = process.env["SUPABASE_SERVICE_ROLE_KEY"] || process.env["SUPABASE_ANON_KEY"];
6895
+ if (!supabaseUrl) {
6896
+ console.log(chalk16.red("SUPABASE_URL not set. Cannot trigger remote sync."));
6897
+ console.log(chalk16.dim("Run the pricing check locally instead:"));
6898
+ console.log(chalk16.dim(" npx tsx scripts/update-model-pricing.ts --check"));
6899
+ return;
6900
+ }
6901
+ console.log(chalk16.blue("\n\u{1F504} Triggering model registry sync...\n"));
6902
+ try {
6903
+ const functionUrl = `${supabaseUrl}/functions/v1/model-registry-sync`;
6904
+ const response = await fetch(functionUrl, {
6905
+ method: "POST",
6906
+ headers: {
6907
+ "Authorization": `Bearer ${supabaseKey}`,
6908
+ "Content-Type": "application/json"
6909
+ }
6910
+ });
6911
+ if (!response.ok) {
6912
+ const errorText = await response.text();
6913
+ console.log(chalk16.red(`Sync failed: ${response.status} - ${errorText}`));
6914
+ return;
6915
+ }
6916
+ const result = await response.json();
6917
+ console.log(chalk16.bold("Sync Results:"));
6918
+ console.log(` Providers checked: ${result.providersChecked.join(", ")}`);
6919
+ console.log(` Duration: ${result.durationMs}ms`);
6920
+ console.log();
6921
+ console.log(chalk16.bold("Parse Confidence:"));
6922
+ for (const [provider, score] of Object.entries(result.confidenceScores)) {
6923
+ const pct = (score * 100).toFixed(0);
6924
+ const color = score >= 0.8 ? chalk16.green : score >= 0.5 ? chalk16.yellow : chalk16.red;
6925
+ console.log(` ${provider}: ${color(pct + "%")}`);
6926
+ }
6927
+ console.log();
6928
+ if (result.diffs.length === 0) {
6929
+ console.log(chalk16.green("\u2705 All model pricing is up to date. No changes detected."));
6930
+ } else {
6931
+ const pricingChanges = result.diffs.filter((d) => d.type === "PRICING_CHANGE");
6932
+ const newModels = result.diffs.filter((d) => d.type === "NEW_MODEL");
6933
+ if (pricingChanges.length > 0) {
6934
+ console.log(chalk16.yellow(`\u{1F4B0} Pricing Changes (${pricingChanges.length}):`));
6935
+ for (const d of pricingChanges) {
6936
+ console.log(` ${d.provider}/${chalk16.bold(d.modelId)}`);
6937
+ console.log(` Old: ${chalk16.red(d.oldValue ?? "unknown")}`);
6938
+ console.log(` New: ${chalk16.green(d.newValue ?? "unknown")}`);
6939
+ }
6940
+ console.log();
6941
+ }
6942
+ if (newModels.length > 0) {
6943
+ console.log(chalk16.cyan(`\u{1F195} New Models (${newModels.length}):`));
6944
+ for (const d of newModels) {
6945
+ console.log(` ${d.provider}/${chalk16.bold(d.modelId)}: ${d.details}`);
6946
+ }
6947
+ console.log();
6948
+ }
6949
+ console.log(chalk16.bold(`Applied: ${result.modelsUpdated} updated, ${result.modelsAdded} added`));
6950
+ }
6951
+ if (result.parseErrors.length > 0) {
6952
+ console.log();
6953
+ console.log(chalk16.red(`\u26A0\uFE0F Warnings/Errors (${result.parseErrors.length}):`));
6954
+ for (const err of result.parseErrors) {
6955
+ console.log(chalk16.red(` - ${err}`));
6956
+ }
6957
+ }
6958
+ console.log();
6959
+ } catch (err) {
6960
+ console.log(chalk16.red(`Failed to run sync: ${err}`));
6961
+ }
6962
+ }
6963
+ async function modelsList() {
6964
+ const { getAllActiveModels, getModelCost, isFreeModel } = await import("./models-UTFGCHAY.js");
6965
+ const models = getAllActiveModels();
6966
+ console.log(chalk16.bold("\n\u{1F4CB} Model Registry\n"));
6967
+ let currentProvider = "";
6968
+ for (const model of models) {
6969
+ if (model.provider !== currentProvider) {
6970
+ currentProvider = model.provider;
6971
+ console.log(chalk16.bold.blue(`
6972
+ ${currentProvider.toUpperCase()}`));
6973
+ console.log(chalk16.dim(" \u2500".repeat(40)));
6974
+ }
6975
+ const cost = getModelCost(model.modelId);
6976
+ const free = isFreeModel(model.modelId);
6977
+ const tier = free ? chalk16.green(" [FREE]") : "";
6978
+ const category = model.category === "thinking" ? chalk16.magenta("thinking") : chalk16.cyan("fast");
6979
+ const inputPrice = cost ? `$${(cost.costPer1kInput * 1e3).toFixed(2)}/1M` : "?";
6980
+ const outputPrice = cost ? `$${(cost.costPer1kOutput * 1e3).toFixed(2)}/1M` : "?";
6981
+ console.log(` ${chalk16.bold(model.modelId)}${tier}`);
6982
+ console.log(chalk16.dim(` ${category} | Input: ${inputPrice} | Output: ${outputPrice}`));
6983
+ }
6984
+ console.log();
6985
+ }
6986
+
7897
6987
  // src/cli/index.ts
7898
- var program = new Command4();
6988
+ var program = new Command2();
7899
6989
  program.name("archon").description("Local-first AI-powered development governance").version(getCurrentVersion()).action(async () => {
7900
6990
  const cwd = process.cwd();
7901
6991
  const wasInitialized = isInitialized(cwd);
7902
6992
  if (!wasInitialized) {
7903
- console.log(chalk19.blue("\nArchonDev is not initialized in this folder.\n"));
6993
+ console.log(chalk17.blue("\nArchonDev is not initialized in this folder.\n"));
7904
6994
  await init({ analyze: true, git: true });
7905
6995
  }
7906
6996
  await start({ skipGovernanceBanner: !wasInitialized });
@@ -7908,7 +6998,7 @@ program.name("archon").description("Local-first AI-powered development governanc
7908
6998
  program.command("login").description("Authenticate with ArchonDev").option("-p, --provider <provider>", "OAuth provider (github or google)", "github").action(async (options) => {
7909
6999
  const provider = options.provider;
7910
7000
  if (provider !== "github" && provider !== "google") {
7911
- console.error(chalk19.red('Invalid provider. Use "github" or "google"'));
7001
+ console.error(chalk17.red('Invalid provider. Use "github" or "google"'));
7912
7002
  process.exit(1);
7913
7003
  }
7914
7004
  await login(provider);
@@ -7920,11 +7010,11 @@ program.command("status").description("Show current user and project status").ac
7920
7010
  await status();
7921
7011
  });
7922
7012
  program.command("upgrade").description("Upgrade your tier (BYOK for free unlimited, or Managed plan)").action(async () => {
7923
- const { showUpgradeMenu } = await import("./tier-selection-Z2RFHZUX.js");
7013
+ const { showUpgradeMenu } = await import("./tier-selection-426HA765.js");
7924
7014
  await showUpgradeMenu();
7925
7015
  });
7926
7016
  program.command("pricing", { hidden: true }).action(async () => {
7927
- const { showUpgradeMenu } = await import("./tier-selection-Z2RFHZUX.js");
7017
+ const { showUpgradeMenu } = await import("./tier-selection-426HA765.js");
7928
7018
  await showUpgradeMenu();
7929
7019
  });
7930
7020
  program.command("init").description("Initialize ArchonDev in current project").option("--analyze", "Run enhanced analysis of codebase").option("--no-git", "Skip git initialization").action(async (options) => {
@@ -8091,6 +7181,9 @@ parallelCmd.command("merge [atomId]").description("Merge completed worktrees bac
8091
7181
  parallelCmd.command("clean").description("Clean up all parallel execution state and worktrees").action(parallelClean);
8092
7182
  parallelCmd.command("schedule").description("Analyze atom dependencies and show execution schedule").option("--mermaid", "Output dependency graph as mermaid diagram").option("--max-parallelism <n>", "Maximum atoms per wave", parseInt).option("--only-ready", "Only include READY atoms").action(parallelSchedule);
8093
7183
  parallelCmd.command("run-waves").description("Execute all READY atoms in dependency-ordered waves").option("--max-parallelism <n>", "Maximum atoms per wave", parseInt).option("--dry-run", "Show execution plan without running").action(parallelRunWaves);
7184
+ parallelCmd.command("cloud <atomIds...>").description("Queue multiple atoms for cloud execution (Credits tier only)").action(async (atomIds) => {
7185
+ await parallelExecuteCloud(atomIds);
7186
+ });
8094
7187
  parallelCmd.action(parallelStatus);
8095
7188
  var githubCmd = program.command("github").description("GitHub integration for cloud execution");
8096
7189
  githubCmd.command("connect").description("Connect your GitHub account for cloud execution").action(githubConnect);
@@ -8102,7 +7195,7 @@ cleanupCmd.command("check").description("Analyze workspace for bloat and mainten
8102
7195
  cleanupCmd.command("run").description("Execute cleanup (archive old entries, remove stale files)").action(cleanupRun);
8103
7196
  cleanupCmd.command("auto").description("Enable/disable automatic cleanup checks").argument("[action]", "enable, disable, or status", "status").action(async (action) => {
8104
7197
  if (action !== "enable" && action !== "disable" && action !== "status") {
8105
- console.error(chalk19.red("Invalid action. Use: enable, disable, or status"));
7198
+ console.error(chalk17.red("Invalid action. Use: enable, disable, or status"));
8106
7199
  process.exit(1);
8107
7200
  }
8108
7201
  await cleanupAuto(action);
@@ -8137,4 +7230,8 @@ program.command("eject").description("Remove all ArchonDev metadata, leaving a c
8137
7230
  program.command("history").description("Show atom execution history from git commits").option("-n, --limit <n>", "Number of commits to show", parseInt).action(historyCommand);
8138
7231
  program.command("revert <atomIdOrHash>").description("Revert a specific atom execution by atom ID or commit hash").option("--force", "Skip confirmation prompt").option("--no-commit", "Stage changes but do not create revert commit").action(revertCommand);
8139
7232
  program.command("revertable").description("List atoms that can be reverted").action(revertableAtoms);
7233
+ var modelsCmd = program.command("models").description("Manage AI model registry and pricing");
7234
+ modelsCmd.command("sync").description("Sync model registry against provider pricing pages").option("--check", "Check only, do not apply changes").action(modelsSync);
7235
+ modelsCmd.command("list").description("List all active models with pricing").action(modelsList);
7236
+ modelsCmd.action(modelsList);
8140
7237
  program.parse();