archondev 2.19.42 → 2.19.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js
CHANGED
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
showExecutionPreferences,
|
|
39
39
|
showPreferences,
|
|
40
40
|
showUsageDetails
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-SAM5CXO4.js";
|
|
42
42
|
import {
|
|
43
43
|
init,
|
|
44
44
|
isInitialized
|
|
@@ -118,7 +118,7 @@ import "./chunk-4VNS5WPM.js";
|
|
|
118
118
|
|
|
119
119
|
// src/cli/index.ts
|
|
120
120
|
import { Command as Command3 } from "commander";
|
|
121
|
-
import
|
|
121
|
+
import chalk18 from "chalk";
|
|
122
122
|
import "dotenv/config";
|
|
123
123
|
|
|
124
124
|
// src/cli/terminal-compat.ts
|
|
@@ -200,7 +200,7 @@ async function saveAtomEnvironmentState(atomId, cwd, state) {
|
|
|
200
200
|
}
|
|
201
201
|
|
|
202
202
|
// src/cli/start.ts
|
|
203
|
-
import
|
|
203
|
+
import chalk6 from "chalk";
|
|
204
204
|
import readline from "readline";
|
|
205
205
|
import { existsSync as existsSync6, readFileSync as readFileSync3, readdirSync as readdirSync3, appendFileSync } from "fs";
|
|
206
206
|
import { join as join6, relative } from "path";
|
|
@@ -769,8 +769,91 @@ async function runAutoCleanupCheck(cwd) {
|
|
|
769
769
|
return needsAttention;
|
|
770
770
|
}
|
|
771
771
|
|
|
772
|
-
// src/cli/
|
|
772
|
+
// src/cli/policy.ts
|
|
773
773
|
import chalk3 from "chalk";
|
|
774
|
+
var DEFAULT_POLICY = {
|
|
775
|
+
approval: "approve_this_task",
|
|
776
|
+
sentinel: "plan_batch_only",
|
|
777
|
+
routing: "balanced"
|
|
778
|
+
};
|
|
779
|
+
async function loadRuntimePolicy() {
|
|
780
|
+
const config = await loadConfig();
|
|
781
|
+
return {
|
|
782
|
+
approval: config.approvalPolicy ?? DEFAULT_POLICY.approval,
|
|
783
|
+
sentinel: config.sentinelPolicy ?? DEFAULT_POLICY.sentinel,
|
|
784
|
+
routing: config.routingProfile ?? DEFAULT_POLICY.routing
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
async function setRuntimePolicy(update) {
|
|
788
|
+
const config = await loadConfig();
|
|
789
|
+
const next = {
|
|
790
|
+
approval: update.approval ?? config.approvalPolicy ?? DEFAULT_POLICY.approval,
|
|
791
|
+
sentinel: update.sentinel ?? config.sentinelPolicy ?? DEFAULT_POLICY.sentinel,
|
|
792
|
+
routing: update.routing ?? config.routingProfile ?? DEFAULT_POLICY.routing
|
|
793
|
+
};
|
|
794
|
+
await saveConfig({
|
|
795
|
+
...config,
|
|
796
|
+
approvalPolicy: next.approval,
|
|
797
|
+
sentinelPolicy: next.sentinel,
|
|
798
|
+
routingProfile: next.routing
|
|
799
|
+
});
|
|
800
|
+
return next;
|
|
801
|
+
}
|
|
802
|
+
async function showPolicy() {
|
|
803
|
+
const policy = await loadRuntimePolicy();
|
|
804
|
+
console.log(chalk3.green("Runtime Policy:"));
|
|
805
|
+
console.log();
|
|
806
|
+
console.log(` ${chalk3.blue("Approval:")} ${policy.approval}`);
|
|
807
|
+
console.log(` ${chalk3.blue("Sentinel:")} ${policy.sentinel}`);
|
|
808
|
+
console.log(` ${chalk3.blue("Routing:")} ${policy.routing}`);
|
|
809
|
+
}
|
|
810
|
+
async function setPolicy(scope, value) {
|
|
811
|
+
if (scope === "approval") {
|
|
812
|
+
const allowed = [
|
|
813
|
+
"ask_every_time",
|
|
814
|
+
"approve_this_task",
|
|
815
|
+
"approve_this_session",
|
|
816
|
+
"always_approve_safe_ops",
|
|
817
|
+
"full_autopilot"
|
|
818
|
+
];
|
|
819
|
+
if (!allowed.includes(value)) {
|
|
820
|
+
console.error(chalk3.red(`Invalid approval policy: ${value}`));
|
|
821
|
+
console.log(chalk3.dim(`Valid values: ${allowed.join(", ")}`));
|
|
822
|
+
process.exit(1);
|
|
823
|
+
}
|
|
824
|
+
await setRuntimePolicy({ approval: value });
|
|
825
|
+
console.log(chalk3.green(`\u2713 approval policy set to ${value}`));
|
|
826
|
+
return;
|
|
827
|
+
}
|
|
828
|
+
if (scope === "sentinel") {
|
|
829
|
+
const allowed = ["every_atom", "plan_batch_only", "manual_only"];
|
|
830
|
+
if (!allowed.includes(value)) {
|
|
831
|
+
console.error(chalk3.red(`Invalid sentinel policy: ${value}`));
|
|
832
|
+
console.log(chalk3.dim(`Valid values: ${allowed.join(", ")}`));
|
|
833
|
+
process.exit(1);
|
|
834
|
+
}
|
|
835
|
+
await setRuntimePolicy({ sentinel: value });
|
|
836
|
+
console.log(chalk3.green(`\u2713 sentinel policy set to ${value}`));
|
|
837
|
+
return;
|
|
838
|
+
}
|
|
839
|
+
if (scope === "routing") {
|
|
840
|
+
const allowed = ["cheap", "balanced", "max_quality"];
|
|
841
|
+
if (!allowed.includes(value)) {
|
|
842
|
+
console.error(chalk3.red(`Invalid routing profile: ${value}`));
|
|
843
|
+
console.log(chalk3.dim(`Valid values: ${allowed.join(", ")}`));
|
|
844
|
+
process.exit(1);
|
|
845
|
+
}
|
|
846
|
+
await setRuntimePolicy({ routing: value });
|
|
847
|
+
console.log(chalk3.green(`\u2713 routing profile set to ${value}`));
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
850
|
+
console.error(chalk3.red(`Invalid policy scope: ${scope}`));
|
|
851
|
+
console.log(chalk3.dim("Valid scopes: approval, sentinel, routing"));
|
|
852
|
+
process.exit(1);
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// src/cli/update-check.ts
|
|
856
|
+
import chalk4 from "chalk";
|
|
774
857
|
import { readFileSync, existsSync as existsSync4 } from "fs";
|
|
775
858
|
import { join as join4, dirname as dirname3 } from "path";
|
|
776
859
|
import { fileURLToPath } from "url";
|
|
@@ -862,10 +945,10 @@ async function checkForUpdates() {
|
|
|
862
945
|
function displayUpdateBanner(result) {
|
|
863
946
|
if (!result.hasUpdate) return;
|
|
864
947
|
console.log();
|
|
865
|
-
console.log(
|
|
866
|
-
console.log(
|
|
867
|
-
console.log(
|
|
868
|
-
console.log(
|
|
948
|
+
console.log(chalk4.yellow("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"));
|
|
949
|
+
console.log(chalk4.yellow("\u2502") + chalk4.bold(" Update available! ") + chalk4.dim(`${result.currentVersion} \u2192 `) + chalk4.green(result.latestVersion) + chalk4.yellow(" \u2502"));
|
|
950
|
+
console.log(chalk4.yellow("\u2502") + chalk4.dim(` Run: ${result.updateCommand}`) + chalk4.yellow(" \u2502"));
|
|
951
|
+
console.log(chalk4.yellow("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"));
|
|
869
952
|
console.log();
|
|
870
953
|
}
|
|
871
954
|
function startBackgroundUpdateCheck() {
|
|
@@ -873,7 +956,7 @@ function startBackgroundUpdateCheck() {
|
|
|
873
956
|
}
|
|
874
957
|
|
|
875
958
|
// src/cli/logo.ts
|
|
876
|
-
import
|
|
959
|
+
import chalk5 from "chalk";
|
|
877
960
|
var ARCHON_LOGO_MINI = `
|
|
878
961
|
\u2584\u2588\u2580\u2588\u2584
|
|
879
962
|
\u2588\u2588\u2580\u2588\u2580\u2588\u2588
|
|
@@ -898,10 +981,10 @@ function displayBrandedHeader() {
|
|
|
898
981
|
return;
|
|
899
982
|
}
|
|
900
983
|
console.log();
|
|
901
|
-
console.log(
|
|
902
|
-
console.log(
|
|
903
|
-
console.log(
|
|
904
|
-
console.log(
|
|
984
|
+
console.log(chalk5.hex("#374F4E")(ARCHON_LOGO_MINI));
|
|
985
|
+
console.log(chalk5.bold.hex("#374F4E")(" ArchonDev"));
|
|
986
|
+
console.log(chalk5.hex("#AA8552")(" AI-Powered Development Governance"));
|
|
987
|
+
console.log(chalk5.hex("#374F4E")("\u2500".repeat(40)));
|
|
905
988
|
console.log();
|
|
906
989
|
}
|
|
907
990
|
|
|
@@ -2620,6 +2703,9 @@ var pendingProposalMode = "atom";
|
|
|
2620
2703
|
var pendingAnalysisToAtomRequest = null;
|
|
2621
2704
|
var pendingAnalysisReviewedFiles = [];
|
|
2622
2705
|
var pendingAnalysisCapsuleCount = null;
|
|
2706
|
+
function shouldAutoRunOnApproval(policy) {
|
|
2707
|
+
return policy !== "ask_every_time";
|
|
2708
|
+
}
|
|
2623
2709
|
function uiText(rich, plain) {
|
|
2624
2710
|
return isTerminalSafeMode() ? plain : rich;
|
|
2625
2711
|
}
|
|
@@ -2633,21 +2719,21 @@ async function start(options = {}) {
|
|
|
2633
2719
|
let config = await loadConfig();
|
|
2634
2720
|
let token = getAuthToken(config);
|
|
2635
2721
|
if (!token) {
|
|
2636
|
-
console.log(
|
|
2637
|
-
console.log(
|
|
2722
|
+
console.log(chalk6.bold("Welcome to ArchonDev!\n"));
|
|
2723
|
+
console.log(chalk6.dim("Let's get you set up. First, we need to create your account.\n"));
|
|
2638
2724
|
await login();
|
|
2639
2725
|
console.log();
|
|
2640
2726
|
config = await loadConfig();
|
|
2641
2727
|
token = getAuthToken(config);
|
|
2642
2728
|
if (!token) {
|
|
2643
|
-
console.log(
|
|
2729
|
+
console.log(chalk6.yellow("Login is required to continue. Run `archon` again when ready."));
|
|
2644
2730
|
return;
|
|
2645
2731
|
}
|
|
2646
2732
|
}
|
|
2647
2733
|
if (!config.tier || config.tier === "FREE") {
|
|
2648
2734
|
const isFirstRun = !existsSync6(join6(cwd, ".archon")) && resolveArchitecturePath(cwd).path === null;
|
|
2649
2735
|
if (isFirstRun && !config.tierConfirmed) {
|
|
2650
|
-
console.log(
|
|
2736
|
+
console.log(chalk6.bold("How would you like to use ArchonDev?\n"));
|
|
2651
2737
|
const selection = await promptTierSelection();
|
|
2652
2738
|
if (selection && !selection.skipped) {
|
|
2653
2739
|
const updateResult2 = await updateUserTier(selection.tier);
|
|
@@ -2655,7 +2741,7 @@ async function start(options = {}) {
|
|
|
2655
2741
|
config.tier = selection.tier;
|
|
2656
2742
|
config.tierConfirmed = true;
|
|
2657
2743
|
await saveConfig(config);
|
|
2658
|
-
console.log(
|
|
2744
|
+
console.log(chalk6.green(`
|
|
2659
2745
|
\u2713 Tier set to ${formatTierName(selection.tier)}
|
|
2660
2746
|
`));
|
|
2661
2747
|
await handleTierSetup(selection.tier);
|
|
@@ -2663,28 +2749,32 @@ async function start(options = {}) {
|
|
|
2663
2749
|
} else {
|
|
2664
2750
|
config.tierConfirmed = true;
|
|
2665
2751
|
await saveConfig(config);
|
|
2666
|
-
console.log(
|
|
2752
|
+
console.log(chalk6.dim("Using Free tier. You can upgrade anytime with `archon upgrade`\n"));
|
|
2667
2753
|
}
|
|
2668
2754
|
}
|
|
2669
2755
|
}
|
|
2670
2756
|
if (config.email) {
|
|
2671
|
-
console.log(
|
|
2757
|
+
console.log(chalk6.dim(`Logged in as: ${config.email}`));
|
|
2672
2758
|
}
|
|
2673
2759
|
const currentTier = config.tier || "FREE";
|
|
2674
2760
|
const tierDisplay = formatTierName(currentTier);
|
|
2675
|
-
|
|
2761
|
+
const runtimePolicy = await loadRuntimePolicy();
|
|
2762
|
+
console.log(chalk6.dim(`Tier: `) + tierDisplay);
|
|
2676
2763
|
const startupChatModel = await resolveStartupChatModel(currentTier, config.accessToken, config.userId);
|
|
2677
2764
|
if (currentTier !== "FREE") {
|
|
2678
|
-
console.log(
|
|
2679
|
-
console.log(
|
|
2765
|
+
console.log(chalk6.dim(`Chat model: ${formatChatModelDisplay(startupChatModel)}`));
|
|
2766
|
+
console.log(chalk6.dim("Change model: archon preferences"));
|
|
2680
2767
|
}
|
|
2768
|
+
console.log(chalk6.dim(`Approval policy: ${runtimePolicy.approval}`));
|
|
2769
|
+
console.log(chalk6.dim(`Sentinel policy: ${runtimePolicy.sentinel}`));
|
|
2770
|
+
console.log(chalk6.dim(`Routing profile: ${runtimePolicy.routing}`));
|
|
2681
2771
|
if (currentTier === "FREE") {
|
|
2682
2772
|
console.log();
|
|
2683
|
-
console.log(
|
|
2684
|
-
console.log(
|
|
2685
|
-
console.log(
|
|
2686
|
-
console.log(
|
|
2687
|
-
console.log(
|
|
2773
|
+
console.log(chalk6.yellow("\u26A0\uFE0F FREE TIER: Limited usage. Upgrade options:"));
|
|
2774
|
+
console.log(chalk6.dim(" \u2022 ") + chalk6.bold("BYOK (FREE)") + chalk6.dim(" - Unlimited usage with your own API keys"));
|
|
2775
|
+
console.log(chalk6.dim(" \u2022 ") + chalk6.bold("Managed Plan") + chalk6.dim(" - Just 10% fee on AI costs, zero setup"));
|
|
2776
|
+
console.log(chalk6.cyan("\u2192 Run ") + chalk6.bold("'archon upgrade'") + chalk6.cyan(" to unlock unlimited access"));
|
|
2777
|
+
console.log(chalk6.dim("\u2192 Model preferences: archon preferences"));
|
|
2688
2778
|
}
|
|
2689
2779
|
if (currentTier === "CREDITS" && config.accessToken) {
|
|
2690
2780
|
try {
|
|
@@ -2706,41 +2796,41 @@ async function start(options = {}) {
|
|
|
2706
2796
|
}
|
|
2707
2797
|
if (usageStats) {
|
|
2708
2798
|
console.log();
|
|
2709
|
-
console.log(
|
|
2710
|
-
console.log(
|
|
2711
|
-
const balanceColor = usageStats.balance < 1 ?
|
|
2799
|
+
console.log(chalk6.bold(uiText("\u{1F4B0} Credits Balance", "Credits Balance")));
|
|
2800
|
+
console.log(chalk6.dim(uiSeparator()));
|
|
2801
|
+
const balanceColor = usageStats.balance < 1 ? chalk6.red : usageStats.balance < 5 ? chalk6.yellow : chalk6.green;
|
|
2712
2802
|
console.log(` Balance: ${balanceColor(`$${usageStats.balance.toFixed(2)}`)}`);
|
|
2713
2803
|
if (usageStats.periodStart) {
|
|
2714
2804
|
const periodDate = new Date(usageStats.periodStart);
|
|
2715
2805
|
const formatted = isNaN(periodDate.getTime()) ? usageStats.periodStart : periodDate.toLocaleDateString();
|
|
2716
2806
|
const label = usageStats.periodSource === "credit_purchase" ? `Since last top-up (${formatted})` : usageStats.periodSource === "month" ? `Since ${formatted}` : `Period start: ${formatted}`;
|
|
2717
|
-
console.log(
|
|
2807
|
+
console.log(chalk6.dim(` ${label}`));
|
|
2718
2808
|
}
|
|
2719
2809
|
if (usageStats.usedThisPeriod > 0) {
|
|
2720
|
-
console.log(` Used since last top-up: ${
|
|
2810
|
+
console.log(` Used since last top-up: ${chalk6.dim(`$${usageStats.usedThisPeriod.toFixed(2)}`)}`);
|
|
2721
2811
|
} else {
|
|
2722
|
-
console.log(
|
|
2812
|
+
console.log(chalk6.dim(" No usage recorded since last top-up."));
|
|
2723
2813
|
}
|
|
2724
2814
|
console.log();
|
|
2725
|
-
console.log(
|
|
2815
|
+
console.log(chalk6.dim(" Model Usage:"));
|
|
2726
2816
|
if (usageStats.byModel && usageStats.byModel.length > 0) {
|
|
2727
2817
|
for (const model of usageStats.byModel) {
|
|
2728
2818
|
const modelName = model.model.length > 32 ? model.model.slice(0, 29) + "..." : model.model;
|
|
2729
|
-
console.log(
|
|
2819
|
+
console.log(chalk6.dim(` ${modelName.padEnd(34)} $${model.cost.toFixed(4)}`));
|
|
2730
2820
|
}
|
|
2731
2821
|
} else {
|
|
2732
|
-
console.log(
|
|
2822
|
+
console.log(chalk6.dim(` ${"No usage yet".padEnd(34)} $0.0000`));
|
|
2733
2823
|
}
|
|
2734
|
-
console.log(
|
|
2824
|
+
console.log(chalk6.dim(uiSeparator()));
|
|
2735
2825
|
if (usageStatsUnavailable) {
|
|
2736
|
-
console.log(
|
|
2826
|
+
console.log(chalk6.dim("Usage details may be delayed. Run `archon credits` to refresh."));
|
|
2737
2827
|
}
|
|
2738
2828
|
if (usageStats.balance < 5) {
|
|
2739
|
-
console.log(
|
|
2829
|
+
console.log(chalk6.yellow(`\u26A0\uFE0F Low balance! Add credits: `) + chalk6.bold(`archon credits add`));
|
|
2740
2830
|
} else {
|
|
2741
|
-
console.log(
|
|
2831
|
+
console.log(chalk6.dim(`Add credits: archon credits add`));
|
|
2742
2832
|
}
|
|
2743
|
-
console.log(
|
|
2833
|
+
console.log(chalk6.dim(`View details: archon credits | Switch tier: archon upgrade | Models: archon preferences`));
|
|
2744
2834
|
if (usageStats.balance <= 0) {
|
|
2745
2835
|
const topUpNow = await promptYesNo("Balance is $0. Add credits now?", true);
|
|
2746
2836
|
if (topUpNow) {
|
|
@@ -2764,39 +2854,39 @@ async function start(options = {}) {
|
|
|
2764
2854
|
};
|
|
2765
2855
|
}
|
|
2766
2856
|
console.log();
|
|
2767
|
-
console.log(
|
|
2768
|
-
console.log(
|
|
2857
|
+
console.log(chalk6.bold(uiText("\u{1F4CA} BYOK Usage", "BYOK Usage")));
|
|
2858
|
+
console.log(chalk6.dim(uiSeparator()));
|
|
2769
2859
|
if (usageStats.periodStart) {
|
|
2770
2860
|
const periodStart = new Date(usageStats.periodStart);
|
|
2771
2861
|
const periodEnd = usageStats.periodEnd ? new Date(usageStats.periodEnd) : null;
|
|
2772
2862
|
const formattedStart = isNaN(periodStart.getTime()) ? usageStats.periodStart : periodStart.toLocaleDateString();
|
|
2773
2863
|
const formattedEnd = periodEnd && !isNaN(periodEnd.getTime()) ? periodEnd.toLocaleDateString() : void 0;
|
|
2774
2864
|
if (formattedEnd) {
|
|
2775
|
-
console.log(
|
|
2865
|
+
console.log(chalk6.dim(` Period: ${formattedStart} \u2192 ${formattedEnd}`));
|
|
2776
2866
|
} else {
|
|
2777
|
-
console.log(
|
|
2867
|
+
console.log(chalk6.dim(` Period start: ${formattedStart}`));
|
|
2778
2868
|
}
|
|
2779
2869
|
} else {
|
|
2780
|
-
console.log(
|
|
2870
|
+
console.log(chalk6.dim(" Period: Current month to date"));
|
|
2781
2871
|
}
|
|
2782
2872
|
const totalTokens = usageStats.totalInputTokens + usageStats.totalOutputTokens;
|
|
2783
|
-
console.log(` Tokens: ${
|
|
2784
|
-
console.log(` Estimated provider spend: ${
|
|
2873
|
+
console.log(` Tokens: ${chalk6.dim(totalTokens.toLocaleString())}`);
|
|
2874
|
+
console.log(` Estimated provider spend: ${chalk6.dim(`$${usageStats.totalBaseCost.toFixed(4)}`)}`);
|
|
2785
2875
|
console.log();
|
|
2786
|
-
console.log(
|
|
2876
|
+
console.log(chalk6.dim(" Model Usage:"));
|
|
2787
2877
|
if (usageStats.byModel.length > 0) {
|
|
2788
2878
|
for (const model of usageStats.byModel) {
|
|
2789
2879
|
const modelName = model.model.length > 32 ? model.model.slice(0, 29) + "..." : model.model;
|
|
2790
|
-
console.log(
|
|
2880
|
+
console.log(chalk6.dim(` ${modelName.padEnd(34)} $${model.cost.toFixed(4)}`));
|
|
2791
2881
|
}
|
|
2792
2882
|
} else {
|
|
2793
|
-
console.log(
|
|
2883
|
+
console.log(chalk6.dim(` ${"No usage yet".padEnd(34)} $0.0000`));
|
|
2794
2884
|
}
|
|
2795
|
-
console.log(
|
|
2885
|
+
console.log(chalk6.dim(uiSeparator()));
|
|
2796
2886
|
if (usageStatsUnavailable) {
|
|
2797
|
-
console.log(
|
|
2887
|
+
console.log(chalk6.dim("Usage details may be delayed. Run `archon usage` to refresh."));
|
|
2798
2888
|
}
|
|
2799
|
-
console.log(
|
|
2889
|
+
console.log(chalk6.dim("View details: archon usage | Models: archon preferences | Switch tier: archon upgrade"));
|
|
2800
2890
|
} catch {
|
|
2801
2891
|
}
|
|
2802
2892
|
}
|
|
@@ -2805,11 +2895,11 @@ async function start(options = {}) {
|
|
|
2805
2895
|
const hasKeys = await keyManager.hasAnyKey();
|
|
2806
2896
|
if (!hasKeys) {
|
|
2807
2897
|
console.log();
|
|
2808
|
-
console.log(
|
|
2809
|
-
console.log(
|
|
2810
|
-
console.log(` ${
|
|
2811
|
-
console.log(` ${
|
|
2812
|
-
console.log(` ${
|
|
2898
|
+
console.log(chalk6.yellow("\u26A0\uFE0F BYOK MODE: No API keys configured!"));
|
|
2899
|
+
console.log(chalk6.dim("You need at least one API key to use ArchonDev with BYOK.\n"));
|
|
2900
|
+
console.log(` ${chalk6.cyan("1")}) Add an API key now`);
|
|
2901
|
+
console.log(` ${chalk6.cyan("2")}) Switch to Managed Plan (no keys needed)`);
|
|
2902
|
+
console.log(` ${chalk6.cyan("3")}) Continue on Free tier`);
|
|
2813
2903
|
console.log();
|
|
2814
2904
|
const choice = await promptWithCommands("What would you like to do?", { allowMultiline: true });
|
|
2815
2905
|
switch (choice) {
|
|
@@ -2823,7 +2913,7 @@ async function start(options = {}) {
|
|
|
2823
2913
|
if (result.success) {
|
|
2824
2914
|
config.tier = "CREDITS";
|
|
2825
2915
|
await saveConfig(config);
|
|
2826
|
-
console.log(
|
|
2916
|
+
console.log(chalk6.green("\u2713 Switched to Managed Plan"));
|
|
2827
2917
|
const { handleTierSetup: setupCredits } = await import("./tier-selection-XFBM4SZ4.js");
|
|
2828
2918
|
await setupCredits("CREDITS");
|
|
2829
2919
|
}
|
|
@@ -2834,11 +2924,11 @@ async function start(options = {}) {
|
|
|
2834
2924
|
if (downgradeResult.success) {
|
|
2835
2925
|
config.tier = "FREE";
|
|
2836
2926
|
await saveConfig(config);
|
|
2837
|
-
console.log(
|
|
2927
|
+
console.log(chalk6.dim("Switched to Free tier."));
|
|
2838
2928
|
}
|
|
2839
2929
|
break;
|
|
2840
2930
|
default:
|
|
2841
|
-
console.log(
|
|
2931
|
+
console.log(chalk6.dim("Continuing without keys. Some features may not work."));
|
|
2842
2932
|
}
|
|
2843
2933
|
}
|
|
2844
2934
|
}
|
|
@@ -2849,7 +2939,7 @@ async function start(options = {}) {
|
|
|
2849
2939
|
}
|
|
2850
2940
|
const projectState = detectProjectState(cwd);
|
|
2851
2941
|
if (!projectState.hasArchitecture) {
|
|
2852
|
-
console.log(
|
|
2942
|
+
console.log(chalk6.dim("No project initialized in this folder.\n"));
|
|
2853
2943
|
const { init: init2 } = await import("./init-FINETS3Q.js");
|
|
2854
2944
|
await init2({ analyze: true, git: true });
|
|
2855
2945
|
console.log();
|
|
@@ -2863,20 +2953,20 @@ async function start(options = {}) {
|
|
|
2863
2953
|
const contextManager = new ContextManager();
|
|
2864
2954
|
const pendingAtomsData = await contextManager.getPendingAtomsData(cwd);
|
|
2865
2955
|
if (pendingAtomsData && pendingAtomsData.atoms.length > 0) {
|
|
2866
|
-
console.log(
|
|
2956
|
+
console.log(chalk6.yellow("[!] Previous session had pending atoms:\n"));
|
|
2867
2957
|
for (const atomId of pendingAtomsData.atoms) {
|
|
2868
|
-
console.log(
|
|
2958
|
+
console.log(chalk6.dim(` \u2022 ${atomId}`));
|
|
2869
2959
|
}
|
|
2870
2960
|
console.log();
|
|
2871
2961
|
const resume = await promptYesNo("Resume with these atoms?", true);
|
|
2872
2962
|
if (resume) {
|
|
2873
|
-
console.log(
|
|
2963
|
+
console.log(chalk6.green("\n\u2713 Resuming with pending atoms...\n"));
|
|
2874
2964
|
await contextManager.clearPendingAtoms(cwd);
|
|
2875
2965
|
} else {
|
|
2876
2966
|
const clear = await promptYesNo("Clear pending atoms?", false);
|
|
2877
2967
|
if (clear) {
|
|
2878
2968
|
await contextManager.clearPendingAtoms(cwd);
|
|
2879
|
-
console.log(
|
|
2969
|
+
console.log(chalk6.dim("Cleared pending atoms.\n"));
|
|
2880
2970
|
}
|
|
2881
2971
|
}
|
|
2882
2972
|
}
|
|
@@ -3043,18 +3133,18 @@ async function fetchCreditsUsageStatsFromSupabase(accessToken, authId) {
|
|
|
3043
3133
|
}
|
|
3044
3134
|
}
|
|
3045
3135
|
function displayGovernanceStatus(status2) {
|
|
3046
|
-
console.log(
|
|
3136
|
+
console.log(chalk6.dim("Governance Status:"));
|
|
3047
3137
|
if (status2.hasArchitecture) {
|
|
3048
|
-
console.log(
|
|
3138
|
+
console.log(chalk6.green(" \u2713") + ` ARCHITECTURE.md (${status2.posture} posture)`);
|
|
3049
3139
|
if (status2.invariantsCount > 0) {
|
|
3050
|
-
console.log(
|
|
3140
|
+
console.log(chalk6.green(" \u2713") + ` ${status2.invariantsCount} invariants`);
|
|
3051
3141
|
}
|
|
3052
3142
|
if (status2.protectedPathsCount > 0) {
|
|
3053
|
-
console.log(
|
|
3143
|
+
console.log(chalk6.green(" \u2713") + ` ${status2.protectedPathsCount} protected paths`);
|
|
3054
3144
|
}
|
|
3055
3145
|
}
|
|
3056
3146
|
if (status2.pendingAtomsCount > 0) {
|
|
3057
|
-
console.log(
|
|
3147
|
+
console.log(chalk6.cyan(` \u2192 ${status2.pendingAtomsCount} atoms pending`));
|
|
3058
3148
|
}
|
|
3059
3149
|
console.log();
|
|
3060
3150
|
}
|
|
@@ -3186,11 +3276,11 @@ async function gatherGovernanceStatus(cwd) {
|
|
|
3186
3276
|
return status2;
|
|
3187
3277
|
}
|
|
3188
3278
|
async function runExploreFlow(cwd, followUpInput, options = {}) {
|
|
3189
|
-
console.log(
|
|
3279
|
+
console.log(chalk6.blue("-- Analyzing Project --\n"));
|
|
3190
3280
|
const projectInfo = await gatherProjectInfo(cwd);
|
|
3191
|
-
console.log(
|
|
3281
|
+
console.log(chalk6.bold(uiText("\u{1F4C1} Project Overview\n", "Project Overview\n")));
|
|
3192
3282
|
if (projectInfo.name) {
|
|
3193
|
-
console.log(` Name: ${
|
|
3283
|
+
console.log(` Name: ${chalk6.cyan(projectInfo.name)}`);
|
|
3194
3284
|
}
|
|
3195
3285
|
if (projectInfo.language) {
|
|
3196
3286
|
console.log(` Language: ${projectInfo.language}`);
|
|
@@ -3202,35 +3292,35 @@ async function runExploreFlow(cwd, followUpInput, options = {}) {
|
|
|
3202
3292
|
console.log(` Package Manager: ${projectInfo.packageManager}`);
|
|
3203
3293
|
}
|
|
3204
3294
|
console.log();
|
|
3205
|
-
console.log(
|
|
3206
|
-
console.log(` Source directories: ${projectInfo.sourceDirs.length > 0 ? projectInfo.sourceDirs.join(", ") :
|
|
3295
|
+
console.log(chalk6.bold(uiText("\u{1F4CA} Structure\n", "Structure\n")));
|
|
3296
|
+
console.log(` Source directories: ${projectInfo.sourceDirs.length > 0 ? projectInfo.sourceDirs.join(", ") : chalk6.dim("none detected")}`);
|
|
3207
3297
|
console.log(` Source files: ${projectInfo.sourceFileCount}`);
|
|
3208
3298
|
if (projectInfo.testFileCount > 0) {
|
|
3209
3299
|
console.log(` Test files: ${projectInfo.testFileCount}`);
|
|
3210
3300
|
}
|
|
3211
3301
|
console.log();
|
|
3212
|
-
console.log(
|
|
3302
|
+
console.log(chalk6.bold(uiText("\u{1F3DB}\uFE0F Governance\n", "Governance\n")));
|
|
3213
3303
|
if (projectInfo.hasArchitecture) {
|
|
3214
|
-
console.log(` ${
|
|
3304
|
+
console.log(` ${chalk6.green("\u2713")} ARCHITECTURE.md (${projectInfo.posture || "unknown"} posture)`);
|
|
3215
3305
|
if (projectInfo.invariantsCount > 0) {
|
|
3216
|
-
console.log(` ${
|
|
3306
|
+
console.log(` ${chalk6.green("\u2713")} ${projectInfo.invariantsCount} invariants defined`);
|
|
3217
3307
|
}
|
|
3218
3308
|
if (projectInfo.protectedPathsCount > 0) {
|
|
3219
|
-
console.log(` ${
|
|
3309
|
+
console.log(` ${chalk6.green("\u2713")} ${projectInfo.protectedPathsCount} protected paths`);
|
|
3220
3310
|
}
|
|
3221
3311
|
} else {
|
|
3222
|
-
console.log(` ${
|
|
3312
|
+
console.log(` ${chalk6.yellow("\u25CB")} No ARCHITECTURE.md yet`);
|
|
3223
3313
|
}
|
|
3224
3314
|
if (projectInfo.hasProgress) {
|
|
3225
|
-
console.log(` ${
|
|
3315
|
+
console.log(` ${chalk6.green("\u2713")} progress.txt exists`);
|
|
3226
3316
|
}
|
|
3227
3317
|
console.log();
|
|
3228
|
-
console.log(
|
|
3318
|
+
console.log(chalk6.green("\u2713 Analysis complete! I'm ready to work on this project.\n"));
|
|
3229
3319
|
const originalFollowUp = (followUpInput ?? "").trim();
|
|
3230
3320
|
const actionableFollowUp = extractActionableFollowUpFromExplore(originalFollowUp);
|
|
3231
3321
|
if (actionableFollowUp || containsActionIntent(originalFollowUp)) {
|
|
3232
3322
|
const request = actionableFollowUp ?? originalFollowUp;
|
|
3233
|
-
console.log(
|
|
3323
|
+
console.log(chalk6.dim("I finished the project scan. Continuing with your requested task...\n"));
|
|
3234
3324
|
await handlePostExploreAction(cwd, request, {
|
|
3235
3325
|
agentMode: options.agentMode,
|
|
3236
3326
|
originalInput: originalFollowUp
|
|
@@ -3238,17 +3328,17 @@ async function runExploreFlow(cwd, followUpInput, options = {}) {
|
|
|
3238
3328
|
return;
|
|
3239
3329
|
}
|
|
3240
3330
|
if (options.agentMode) {
|
|
3241
|
-
console.log(
|
|
3331
|
+
console.log(chalk6.dim("Tell me the next thing you want to do.\n"));
|
|
3242
3332
|
return;
|
|
3243
3333
|
}
|
|
3244
|
-
console.log(
|
|
3245
|
-
console.log(
|
|
3246
|
-
console.log(` ${
|
|
3247
|
-
console.log(` ${
|
|
3334
|
+
console.log(chalk6.bold("What would you like to do next?\n"));
|
|
3335
|
+
console.log(chalk6.dim("You can describe it naturally, or use shortcuts:\n"));
|
|
3336
|
+
console.log(` ${chalk6.cyan("1")}) ${chalk6.bold("Plan a task")} \u2014 Tell me what to implement, fix, or change`);
|
|
3337
|
+
console.log(` ${chalk6.cyan("2")}) ${chalk6.bold("Review code")} \u2014 Run AI-powered code review`);
|
|
3248
3338
|
if (!projectInfo.hasArchitecture) {
|
|
3249
|
-
console.log(` ${
|
|
3339
|
+
console.log(` ${chalk6.cyan("3")}) ${chalk6.bold("Set up governance")} \u2014 Generate ARCHITECTURE.md from this analysis`);
|
|
3250
3340
|
}
|
|
3251
|
-
console.log(` ${
|
|
3341
|
+
console.log(` ${chalk6.cyan("q")}) ${chalk6.dim("Quit")}`);
|
|
3252
3342
|
console.log();
|
|
3253
3343
|
const choice = await promptWithCommands("Enter choice");
|
|
3254
3344
|
switch (choice.toLowerCase()) {
|
|
@@ -3281,7 +3371,7 @@ async function runExploreFlow(cwd, followUpInput, options = {}) {
|
|
|
3281
3371
|
return;
|
|
3282
3372
|
}
|
|
3283
3373
|
}
|
|
3284
|
-
console.log(
|
|
3374
|
+
console.log(chalk6.yellow("I did not catch that. Tell me what you want to do next."));
|
|
3285
3375
|
await showMainMenu();
|
|
3286
3376
|
}
|
|
3287
3377
|
}
|
|
@@ -3384,7 +3474,7 @@ async function runConversationalInterview(cwd, initialMessage) {
|
|
|
3384
3474
|
if (agent && agent.isAvailable()) {
|
|
3385
3475
|
await runAIInterview(cwd, initialMessage, agent);
|
|
3386
3476
|
} else {
|
|
3387
|
-
console.log(
|
|
3477
|
+
console.log(chalk6.dim("(Using simple setup - add API keys with `archon keys add` for AI-powered interview)\n"));
|
|
3388
3478
|
await runSimpleInterview(cwd, initialMessage);
|
|
3389
3479
|
}
|
|
3390
3480
|
}
|
|
@@ -3394,11 +3484,11 @@ async function runAIInterview(cwd, initialMessage, agent) {
|
|
|
3394
3484
|
try {
|
|
3395
3485
|
let turn = await agent.startInterview(initialMessage);
|
|
3396
3486
|
while (!turn.isComplete && turnCount < MAX_TURNS) {
|
|
3397
|
-
console.log(
|
|
3487
|
+
console.log(chalk6.blue("\u2192 ") + turn.question);
|
|
3398
3488
|
console.log();
|
|
3399
3489
|
const response = await prompt("");
|
|
3400
3490
|
if (wantsToSkip(response)) {
|
|
3401
|
-
console.log(
|
|
3491
|
+
console.log(chalk6.dim("\n> Using defaults for remaining questions.\n"));
|
|
3402
3492
|
break;
|
|
3403
3493
|
}
|
|
3404
3494
|
turn = await agent.continueInterview(response);
|
|
@@ -3410,12 +3500,12 @@ async function runAIInterview(cwd, initialMessage, agent) {
|
|
|
3410
3500
|
}
|
|
3411
3501
|
const usage = agent.getUsage();
|
|
3412
3502
|
if (usage.totalTokens > 0) {
|
|
3413
|
-
console.log(
|
|
3503
|
+
console.log(chalk6.dim(`
|
|
3414
3504
|
(Interview used ${usage.totalTokens} tokens, $${usage.baseCost.toFixed(4)})`));
|
|
3415
3505
|
}
|
|
3416
3506
|
await finishInterview(cwd, state, initialMessage);
|
|
3417
3507
|
} catch (error) {
|
|
3418
|
-
console.log(
|
|
3508
|
+
console.log(chalk6.yellow("\n[!] AI interview unavailable, using simple setup.\n"));
|
|
3419
3509
|
await runSimpleInterview(cwd, initialMessage);
|
|
3420
3510
|
}
|
|
3421
3511
|
}
|
|
@@ -3428,9 +3518,9 @@ async function runSimpleInterview(cwd, initialMessage) {
|
|
|
3428
3518
|
});
|
|
3429
3519
|
const known = getKnownInfo(state);
|
|
3430
3520
|
if (known.length > 0) {
|
|
3431
|
-
console.log(
|
|
3521
|
+
console.log(chalk6.dim("From what you said, I got:"));
|
|
3432
3522
|
for (const info of known) {
|
|
3433
|
-
console.log(
|
|
3523
|
+
console.log(chalk6.dim(` \u2022 ${info}`));
|
|
3434
3524
|
}
|
|
3435
3525
|
console.log();
|
|
3436
3526
|
}
|
|
@@ -3452,7 +3542,7 @@ async function runSimpleInterview(cwd, initialMessage) {
|
|
|
3452
3542
|
await finishInterview(cwd, state, initialMessage);
|
|
3453
3543
|
}
|
|
3454
3544
|
async function finishInterview(cwd, state, initialTaskHint) {
|
|
3455
|
-
console.log(
|
|
3545
|
+
console.log(chalk6.blue("\n-- Recording Project Details --\n"));
|
|
3456
3546
|
const posture = state.posture === "enterprise" ? "enterprise" : state.posture === "prototype" ? "prototype" : "production";
|
|
3457
3547
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
3458
3548
|
const progressEntry = `
|
|
@@ -3484,22 +3574,22 @@ ${state.forbiddenPatterns?.length ? `- **Forbidden patterns:** ${state.forbidden
|
|
|
3484
3574
|
writeFileSync2(progressPath, "# ArchonDev Progress Log\n\nThis file tracks learnings and decisions across sessions.\n");
|
|
3485
3575
|
}
|
|
3486
3576
|
appendFileSync(progressPath, progressEntry);
|
|
3487
|
-
console.log(
|
|
3577
|
+
console.log(chalk6.green("\n\u2713 Project details recorded!\n"));
|
|
3488
3578
|
const finalKnown = getKnownInfo(state);
|
|
3489
3579
|
if (finalKnown.length > 0) {
|
|
3490
|
-
console.log(
|
|
3580
|
+
console.log(chalk6.dim("Project configured with:"));
|
|
3491
3581
|
for (const info of finalKnown) {
|
|
3492
|
-
console.log(
|
|
3582
|
+
console.log(chalk6.dim(` \u2022 ${info}`));
|
|
3493
3583
|
}
|
|
3494
3584
|
console.log();
|
|
3495
3585
|
}
|
|
3496
|
-
console.log(
|
|
3497
|
-
console.log(` 1. ${
|
|
3498
|
-
console.log(` 2. ${
|
|
3586
|
+
console.log(chalk6.bold("Next steps:"));
|
|
3587
|
+
console.log(` 1. ${chalk6.cyan("Review")} ARCHITECTURE.md and customize if needed`);
|
|
3588
|
+
console.log(` 2. ${chalk6.cyan("Run")} ${chalk6.dim('archon plan "your first task"')} to create an atom`);
|
|
3499
3589
|
console.log();
|
|
3500
3590
|
const hintedTask = initialTaskHint?.trim() ?? "";
|
|
3501
3591
|
if (hintedTask) {
|
|
3502
|
-
console.log(
|
|
3592
|
+
console.log(chalk6.dim("Using your request above as the first task.\n"));
|
|
3503
3593
|
const { plan: plan2 } = await import("./plan-I3P6U2ZM.js");
|
|
3504
3594
|
await plan2(hintedTask, { conversational: true });
|
|
3505
3595
|
return;
|
|
@@ -3517,7 +3607,7 @@ ${state.forbiddenPatterns?.length ? `- **Forbidden patterns:** ${state.forbidden
|
|
|
3517
3607
|
const hinted = initialTaskHint?.trim() ?? "";
|
|
3518
3608
|
if (hinted) {
|
|
3519
3609
|
description = hinted;
|
|
3520
|
-
console.log(
|
|
3610
|
+
console.log(chalk6.dim("\nUsing your request above as the first task.\n"));
|
|
3521
3611
|
} else {
|
|
3522
3612
|
description = await promptWithCommands("Describe what you want to build first", { allowMultiline: true });
|
|
3523
3613
|
}
|
|
@@ -3603,7 +3693,7 @@ function inferLanguageFromProjectFiles(cwd) {
|
|
|
3603
3693
|
return best?.language;
|
|
3604
3694
|
}
|
|
3605
3695
|
async function analyzeAndAdapt(cwd) {
|
|
3606
|
-
console.log(
|
|
3696
|
+
console.log(chalk6.blue("\n-- Analyzing Project --\n"));
|
|
3607
3697
|
const { init: init2 } = await import("./init-FINETS3Q.js");
|
|
3608
3698
|
await init2({ analyze: true, git: true });
|
|
3609
3699
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
@@ -3625,12 +3715,12 @@ async function analyzeAndAdapt(cwd) {
|
|
|
3625
3715
|
- .archon/config.yaml - Build commands configured
|
|
3626
3716
|
- progress.txt - This file
|
|
3627
3717
|
`);
|
|
3628
|
-
console.log(
|
|
3718
|
+
console.log(chalk6.green("\n\u2713 Governance files adapted!\n"));
|
|
3629
3719
|
await showMainMenu();
|
|
3630
3720
|
}
|
|
3631
3721
|
async function codeReviewFirst(cwd) {
|
|
3632
|
-
console.log(
|
|
3633
|
-
console.log(
|
|
3722
|
+
console.log(chalk6.blue("\n-- Code Review Mode --\n"));
|
|
3723
|
+
console.log(chalk6.dim("I'll analyze your code for issues without making any changes.\n"));
|
|
3634
3724
|
const { reviewInit: reviewInit2, reviewAnalyze: reviewAnalyze2, reviewRun: reviewRun2 } = await import("./review-7BBVCF7H.js");
|
|
3635
3725
|
const reviewDbPath = join6(cwd, "docs", "code-review", "review-tasks.db");
|
|
3636
3726
|
if (!existsSync6(reviewDbPath)) {
|
|
@@ -3641,22 +3731,22 @@ async function codeReviewFirst(cwd) {
|
|
|
3641
3731
|
if (runReview) {
|
|
3642
3732
|
await reviewRun2({ all: true });
|
|
3643
3733
|
}
|
|
3644
|
-
console.log(
|
|
3734
|
+
console.log(chalk6.dim("\nAfter reviewing, you can run ") + chalk6.cyan("archon") + chalk6.dim(" again to set up governance.\n"));
|
|
3645
3735
|
}
|
|
3646
3736
|
async function runAgentMode(cwd, state) {
|
|
3647
3737
|
if (state.scenario === "CONTINUE_SESSION") {
|
|
3648
|
-
console.log(
|
|
3738
|
+
console.log(chalk6.bold("Welcome back!\n"));
|
|
3649
3739
|
if (state.lastProgressEntry) {
|
|
3650
|
-
console.log(
|
|
3651
|
-
console.log(
|
|
3740
|
+
console.log(chalk6.dim("Last activity:"));
|
|
3741
|
+
console.log(chalk6.dim(" " + state.lastProgressEntry.split("\n")[0]));
|
|
3652
3742
|
console.log();
|
|
3653
3743
|
}
|
|
3654
3744
|
} else if (state.scenario === "NEW_PROJECT") {
|
|
3655
|
-
console.log(
|
|
3656
|
-
console.log(
|
|
3745
|
+
console.log(chalk6.bold("Starting in chat mode.\n"));
|
|
3746
|
+
console.log(chalk6.dim("Tell me what you want to build. I will apply governance checks in the background.\n"));
|
|
3657
3747
|
} else {
|
|
3658
|
-
console.log(
|
|
3659
|
-
console.log(
|
|
3748
|
+
console.log(chalk6.bold("Ready in chat mode.\n"));
|
|
3749
|
+
console.log(chalk6.dim("Tell me what you want to do. Use /workflow for the classic menu.\n"));
|
|
3660
3750
|
}
|
|
3661
3751
|
while (true) {
|
|
3662
3752
|
const response = await promptWithCommands(
|
|
@@ -3673,7 +3763,7 @@ async function runAgentMode(cwd, state) {
|
|
|
3673
3763
|
}
|
|
3674
3764
|
const handled = await handleAgentConversationInput(cwd, trimmed);
|
|
3675
3765
|
if (!handled) {
|
|
3676
|
-
console.log(
|
|
3766
|
+
console.log(chalk6.yellow("I did not catch that. Describe your goal in one sentence."));
|
|
3677
3767
|
}
|
|
3678
3768
|
}
|
|
3679
3769
|
}
|
|
@@ -3688,11 +3778,27 @@ async function handleAgentConversationInput(cwd, input) {
|
|
|
3688
3778
|
const capsuleCount = pendingAnalysisCapsuleCount ?? 1;
|
|
3689
3779
|
pendingAnalysisCapsuleCount = null;
|
|
3690
3780
|
const enrichedRequest = enrichApprovedAnalysisRequest(request, reviewedFiles, capsuleCount);
|
|
3691
|
-
console.log(
|
|
3692
|
-
const
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3781
|
+
console.log(chalk6.dim("\n> Great. Creating a governed task from the approved analysis plan.\n"));
|
|
3782
|
+
const createdAtomIds = await createTaskFromRequest(cwd, enrichedRequest);
|
|
3783
|
+
const policy = await loadRuntimePolicy();
|
|
3784
|
+
if (shouldAutoRunOnApproval(policy.approval)) {
|
|
3785
|
+
console.log(chalk6.dim("\n> Starting implementation now...\n"));
|
|
3786
|
+
await continueWithCurrentTask(cwd, {
|
|
3787
|
+
runAllReady: true,
|
|
3788
|
+
onlyAtomIds: createdAtomIds
|
|
3789
|
+
});
|
|
3790
|
+
} else {
|
|
3791
|
+
const executeNow = await promptYesNo("Plan approved. Execute this task now?", true);
|
|
3792
|
+
if (executeNow) {
|
|
3793
|
+
await continueWithCurrentTask(cwd, {
|
|
3794
|
+
runAllReady: true,
|
|
3795
|
+
onlyAtomIds: createdAtomIds
|
|
3796
|
+
});
|
|
3797
|
+
} else {
|
|
3798
|
+
await showLatestPlannedAtom(cwd);
|
|
3799
|
+
console.log(chalk6.dim('\nReply "continue" when you want execution to start.'));
|
|
3800
|
+
}
|
|
3801
|
+
}
|
|
3696
3802
|
return true;
|
|
3697
3803
|
}
|
|
3698
3804
|
if (pendingProposalRequest && isPlanApprovalDirective(normalized)) {
|
|
@@ -3725,11 +3831,11 @@ async function handleAgentConversationInput(cwd, input) {
|
|
|
3725
3831
|
}
|
|
3726
3832
|
const intent = detectUserIntent(input);
|
|
3727
3833
|
if (isReadOnlyExploreRequest(input) || intent.mode === "explore" && intent.confidence >= 0.7) {
|
|
3728
|
-
console.log(
|
|
3834
|
+
console.log(chalk6.dim("\n> Got it! Analyzing the project...\n"));
|
|
3729
3835
|
await runExploreFlow(cwd, input, { agentMode: true });
|
|
3730
3836
|
return true;
|
|
3731
3837
|
}
|
|
3732
|
-
console.log(
|
|
3838
|
+
console.log(chalk6.dim("\n> Got it! Creating a task for this...\n"));
|
|
3733
3839
|
const { plan: plan2 } = await import("./plan-I3P6U2ZM.js");
|
|
3734
3840
|
await plan2(await withAllowedPathScope(cwd, input), { conversational: true });
|
|
3735
3841
|
if (shouldAutoExecuteAfterPlanning(input)) {
|
|
@@ -3737,7 +3843,7 @@ async function handleAgentConversationInput(cwd, input) {
|
|
|
3737
3843
|
return true;
|
|
3738
3844
|
}
|
|
3739
3845
|
await showLatestPlannedAtom(cwd);
|
|
3740
|
-
console.log(
|
|
3846
|
+
console.log(chalk6.dim('\nReply "execute atom" when you want implementation to start, or tell me what to change.'));
|
|
3741
3847
|
return true;
|
|
3742
3848
|
}
|
|
3743
3849
|
function isReadOnlyExploreRequest(input) {
|
|
@@ -3765,22 +3871,22 @@ function wantsProposalBeforeExecution(input) {
|
|
|
3765
3871
|
async function showProposalForApproval(input) {
|
|
3766
3872
|
pendingProposalRequest = input.trim();
|
|
3767
3873
|
pendingProposalMode = shouldDoAnalysisBeforeAtom(input) ? "analysis" : "atom";
|
|
3768
|
-
console.log(
|
|
3769
|
-
console.log(
|
|
3770
|
-
console.log(
|
|
3771
|
-
console.log(
|
|
3772
|
-
console.log(
|
|
3773
|
-
console.log(
|
|
3874
|
+
console.log(chalk6.dim("\n> Understood. I will not create atoms yet.\n"));
|
|
3875
|
+
console.log(chalk6.bold("Proposed plan (for your approval):"));
|
|
3876
|
+
console.log(chalk6.dim(" 1. Review project files and locate the capsule markdown/source for day 1."));
|
|
3877
|
+
console.log(chalk6.dim(" 2. Evaluate day-1 content boundaries and recommend one capsule vs multiple capsules with rationale."));
|
|
3878
|
+
console.log(chalk6.dim(" 3. Draft a user-friendly capsule structure for day 1."));
|
|
3879
|
+
console.log(chalk6.dim(" 4. Present implementation plan and wait for your approval before creating atoms or executing."));
|
|
3774
3880
|
if (input.trim()) {
|
|
3775
3881
|
console.log();
|
|
3776
|
-
console.log(
|
|
3882
|
+
console.log(chalk6.dim('Reply "approve plan" to proceed, or tell me what to adjust in this plan.'));
|
|
3777
3883
|
}
|
|
3778
3884
|
}
|
|
3779
3885
|
async function showLatestPlannedAtom(cwd) {
|
|
3780
3886
|
const { listLocalAtoms: listLocalAtoms2 } = await import("./plan-I3P6U2ZM.js");
|
|
3781
3887
|
const atoms = await listLocalAtoms2();
|
|
3782
3888
|
if (atoms.length === 0) {
|
|
3783
|
-
console.log(
|
|
3889
|
+
console.log(chalk6.yellow("No atoms found yet. Tell me what to plan."));
|
|
3784
3890
|
return;
|
|
3785
3891
|
}
|
|
3786
3892
|
const latest = atoms.slice().sort((a, b) => {
|
|
@@ -3789,10 +3895,10 @@ async function showLatestPlannedAtom(cwd) {
|
|
|
3789
3895
|
return bTime - aTime;
|
|
3790
3896
|
})[0];
|
|
3791
3897
|
if (!latest) {
|
|
3792
|
-
console.log(
|
|
3898
|
+
console.log(chalk6.yellow("No atoms found yet. Tell me what to plan."));
|
|
3793
3899
|
return;
|
|
3794
3900
|
}
|
|
3795
|
-
console.log(
|
|
3901
|
+
console.log(chalk6.dim(`
|
|
3796
3902
|
Showing latest planned atom (${latest.externalId})...
|
|
3797
3903
|
`));
|
|
3798
3904
|
const { show: show2 } = await import("./show-7HL5NIA7.js");
|
|
@@ -3891,14 +3997,51 @@ async function applyApprovedProposal(cwd) {
|
|
|
3891
3997
|
await provideAnalysisFirstPlan(cwd, approvedRequest);
|
|
3892
3998
|
return;
|
|
3893
3999
|
}
|
|
3894
|
-
console.log(
|
|
3895
|
-
const
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
4000
|
+
console.log(chalk6.dim("\n> Great. I will create the task from your approved request.\n"));
|
|
4001
|
+
const createdAtomIds = await createTaskFromRequest(cwd, approvedRequest);
|
|
4002
|
+
const policy = await loadRuntimePolicy();
|
|
4003
|
+
if (shouldAutoRunOnApproval(policy.approval)) {
|
|
4004
|
+
console.log(chalk6.dim("\n> Approval received. Starting unattended execution for all READY atoms...\n"));
|
|
4005
|
+
await continueWithCurrentTask(cwd, {
|
|
4006
|
+
runAllReady: true,
|
|
4007
|
+
onlyAtomIds: createdAtomIds
|
|
4008
|
+
});
|
|
4009
|
+
return;
|
|
4010
|
+
}
|
|
4011
|
+
const executeNow = await promptYesNo("Plan approved. Execute this task now?", true);
|
|
4012
|
+
if (executeNow) {
|
|
4013
|
+
await continueWithCurrentTask(cwd, {
|
|
4014
|
+
runAllReady: true,
|
|
4015
|
+
onlyAtomIds: createdAtomIds
|
|
4016
|
+
});
|
|
4017
|
+
return;
|
|
4018
|
+
}
|
|
4019
|
+
await showLatestPlannedAtom(cwd);
|
|
4020
|
+
console.log(chalk6.dim('\nReply "continue" when you want execution to start.'));
|
|
4021
|
+
}
|
|
4022
|
+
async function createTaskFromRequest(cwd, request) {
|
|
4023
|
+
const { plan: plan2, listLocalAtoms: listLocalAtoms2 } = await import("./plan-I3P6U2ZM.js");
|
|
4024
|
+
const before = await listLocalAtoms2();
|
|
4025
|
+
const beforeIds = new Set(before.map((atom) => atom.externalId));
|
|
4026
|
+
await plan2(await withAllowedPathScope(cwd, request), { conversational: true });
|
|
4027
|
+
const after = await listLocalAtoms2();
|
|
4028
|
+
const created = after.filter((atom) => atom.status === "READY" && !beforeIds.has(atom.externalId)).sort((a, b) => {
|
|
4029
|
+
const aTime = new Date(String(a.updatedAt ?? a.createdAt ?? "")).getTime() || 0;
|
|
4030
|
+
const bTime = new Date(String(b.updatedAt ?? b.createdAt ?? "")).getTime() || 0;
|
|
4031
|
+
return bTime - aTime;
|
|
4032
|
+
}).map((atom) => atom.externalId);
|
|
4033
|
+
if (created.length === 0) {
|
|
4034
|
+
const latestReady = after.filter((atom) => atom.status === "READY").sort((a, b) => {
|
|
4035
|
+
const aTime = new Date(String(a.updatedAt ?? a.createdAt ?? "")).getTime() || 0;
|
|
4036
|
+
const bTime = new Date(String(b.updatedAt ?? b.createdAt ?? "")).getTime() || 0;
|
|
4037
|
+
return bTime - aTime;
|
|
4038
|
+
})[0];
|
|
4039
|
+
return latestReady ? [latestReady.externalId] : [];
|
|
4040
|
+
}
|
|
4041
|
+
return created;
|
|
3899
4042
|
}
|
|
3900
4043
|
async function provideAnalysisFirstPlan(cwd, request) {
|
|
3901
|
-
console.log(
|
|
4044
|
+
console.log(chalk6.dim("\n> I analyzed your request and generated a recommendation + sample draft first.\n"));
|
|
3902
4045
|
const markdownFiles = collectMarkdownFiles(cwd);
|
|
3903
4046
|
const dayOneCandidates = markdownFiles.filter((file) => isDayOnePath(file));
|
|
3904
4047
|
const capsuleCandidates = markdownFiles.filter((file) => /capsule/i.test(file));
|
|
@@ -3907,43 +4050,43 @@ async function provideAnalysisFirstPlan(cwd, request) {
|
|
|
3907
4050
|
const stats = computeContentStats(cwd, reviewedFiles);
|
|
3908
4051
|
const recommendSplit = stats.totalWords > 900 || stats.totalHeadings >= 6;
|
|
3909
4052
|
const capsuleCount = recommendSplit ? 2 : 1;
|
|
3910
|
-
console.log(
|
|
4053
|
+
console.log(chalk6.bold("Analysis summary (no atoms created):"));
|
|
3911
4054
|
if (reviewedFiles.length === 0) {
|
|
3912
|
-
console.log(
|
|
3913
|
-
console.log(
|
|
4055
|
+
console.log(chalk6.dim(" - I did not find obvious day-1 capsule markdown files automatically."));
|
|
4056
|
+
console.log(chalk6.dim(" - Share the target file path and I will evaluate it directly."));
|
|
3914
4057
|
} else {
|
|
3915
|
-
console.log(
|
|
4058
|
+
console.log(chalk6.dim(" Files reviewed:"));
|
|
3916
4059
|
for (const file of reviewedFiles) {
|
|
3917
|
-
console.log(
|
|
4060
|
+
console.log(chalk6.dim(` - ${file}`));
|
|
3918
4061
|
}
|
|
3919
|
-
console.log(
|
|
4062
|
+
console.log(chalk6.dim(` Content signals: ~${stats.totalWords} words, ${stats.totalHeadings} section headings.`));
|
|
3920
4063
|
}
|
|
3921
4064
|
console.log();
|
|
3922
|
-
console.log(
|
|
4065
|
+
console.log(chalk6.bold("Recommendation:"));
|
|
3923
4066
|
if (reviewedFiles.length === 0) {
|
|
3924
|
-
console.log(
|
|
4067
|
+
console.log(chalk6.dim(" I need the exact day-1 capsule file path to make a reliable one-vs-many capsule recommendation."));
|
|
3925
4068
|
} else if (recommendSplit) {
|
|
3926
|
-
console.log(
|
|
4069
|
+
console.log(chalk6.dim(` Split day 1 into ${capsuleCount} capsules for clarity and lower cognitive load.`));
|
|
3927
4070
|
} else {
|
|
3928
|
-
console.log(
|
|
4071
|
+
console.log(chalk6.dim(" Keep day 1 as one capsule to preserve continuity and reduce context switching."));
|
|
3929
4072
|
}
|
|
3930
4073
|
console.log();
|
|
3931
|
-
console.log(
|
|
3932
|
-
console.log(
|
|
3933
|
-
console.log(
|
|
3934
|
-
console.log(
|
|
3935
|
-
console.log(
|
|
4074
|
+
console.log(chalk6.bold("Implementation plan (proposed):"));
|
|
4075
|
+
console.log(chalk6.dim(" 1. Confirm target source file(s) for day 1 content."));
|
|
4076
|
+
console.log(chalk6.dim(` 2. Define capsule boundaries and titles (${capsuleCount} capsule${capsuleCount > 1 ? "s" : ""}).`));
|
|
4077
|
+
console.log(chalk6.dim(" 3. Draft capsule markdown(s) with consistent template and learning objective per capsule."));
|
|
4078
|
+
console.log(chalk6.dim(" 4. Add index/manifest links and quick validation checks for user flow."));
|
|
3936
4079
|
const sampleDraft = buildSampleCapsuleDraft(cwd, reviewedFiles, capsuleCount);
|
|
3937
4080
|
if (sampleDraft) {
|
|
3938
4081
|
console.log();
|
|
3939
|
-
console.log(
|
|
4082
|
+
console.log(chalk6.bold("Sample output for day 1 (draft):"));
|
|
3940
4083
|
console.log(sampleDraft);
|
|
3941
4084
|
}
|
|
3942
4085
|
pendingAnalysisToAtomRequest = request;
|
|
3943
4086
|
pendingAnalysisReviewedFiles = reviewedFiles;
|
|
3944
4087
|
pendingAnalysisCapsuleCount = capsuleCount;
|
|
3945
4088
|
console.log();
|
|
3946
|
-
console.log(
|
|
4089
|
+
console.log(chalk6.dim('Reply with "yes", "go ahead", or "create atom" when you want me to implement this in governed mode.'));
|
|
3947
4090
|
}
|
|
3948
4091
|
function enrichApprovedAnalysisRequest(request, reviewedFiles, capsuleCount) {
|
|
3949
4092
|
const normalizedFiles = reviewedFiles.map((file) => file.trim()).filter((file) => file.length > 0);
|
|
@@ -4022,27 +4165,27 @@ function buildSampleCapsuleDraft(cwd, files, capsuleCount) {
|
|
|
4022
4165
|
const practice = paragraphs[2] ?? "Give one guided prompt so the learner can apply the idea immediately.";
|
|
4023
4166
|
if (capsuleCount <= 1) {
|
|
4024
4167
|
return [
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4168
|
+
chalk6.dim(" ---"),
|
|
4169
|
+
chalk6.dim(` title: "${heading} - Core Capsule"`),
|
|
4170
|
+
chalk6.dim(' type: "lesson_capsule"'),
|
|
4171
|
+
chalk6.dim(" day: 1"),
|
|
4172
|
+
chalk6.dim(" ---"),
|
|
4173
|
+
chalk6.dim(" ## Objective"),
|
|
4174
|
+
chalk6.dim(` ${objective}`),
|
|
4175
|
+
chalk6.dim(" ## Core Concept"),
|
|
4176
|
+
chalk6.dim(` ${concept}`),
|
|
4177
|
+
chalk6.dim(" ## Practice"),
|
|
4178
|
+
chalk6.dim(` ${practice}`)
|
|
4036
4179
|
].join("\n");
|
|
4037
4180
|
}
|
|
4038
4181
|
return [
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4182
|
+
chalk6.dim(" Capsule 1: Foundation"),
|
|
4183
|
+
chalk6.dim(` - Objective: ${objective}`),
|
|
4184
|
+
chalk6.dim(` - Core Concept: ${concept}`),
|
|
4185
|
+
chalk6.dim(""),
|
|
4186
|
+
chalk6.dim(" Capsule 2: Application"),
|
|
4187
|
+
chalk6.dim(` - Guided Practice: ${practice}`),
|
|
4188
|
+
chalk6.dim(" - Reflection Prompt: What changed in your understanding after this exercise?")
|
|
4046
4189
|
].join("\n");
|
|
4047
4190
|
}
|
|
4048
4191
|
async function continueWithCurrentTask(cwd, options = {}) {
|
|
@@ -4054,50 +4197,59 @@ async function continueWithCurrentTask(cwd, options = {}) {
|
|
|
4054
4197
|
};
|
|
4055
4198
|
const { execute: execute2 } = await import("./execute-AQWHZKDH.js");
|
|
4056
4199
|
const runAllReady = options.runAllReady === true;
|
|
4200
|
+
const scopeIds = options.onlyAtomIds ? new Set(options.onlyAtomIds) : null;
|
|
4057
4201
|
const attempted = /* @__PURE__ */ new Set();
|
|
4058
4202
|
let queueStarted = false;
|
|
4059
4203
|
while (true) {
|
|
4060
4204
|
const atoms = await listLocalAtoms2();
|
|
4061
|
-
const readyAtoms = atoms.filter((a) => a.status === "READY").sort(byMostRecent);
|
|
4205
|
+
const readyAtoms = atoms.filter((a) => a.status === "READY" && (!scopeIds || scopeIds.has(a.externalId))).sort(byMostRecent);
|
|
4062
4206
|
if (readyAtoms.length === 0) {
|
|
4207
|
+
if (scopeIds && scopeIds.size > 0) {
|
|
4208
|
+
if (queueStarted && runAllReady) {
|
|
4209
|
+
console.log(chalk6.green("\nQueue execution complete for this approved task scope."));
|
|
4210
|
+
} else {
|
|
4211
|
+
console.log(chalk6.yellow("No READY atoms found for this approved task scope."));
|
|
4212
|
+
}
|
|
4213
|
+
return;
|
|
4214
|
+
}
|
|
4063
4215
|
const inProgressAtoms = atoms.filter((a) => a.status === "IN_PROGRESS").sort(byMostRecent);
|
|
4064
4216
|
if (inProgressAtoms.length > 0) {
|
|
4065
4217
|
const current = inProgressAtoms[0];
|
|
4066
|
-
console.log(
|
|
4067
|
-
console.log(
|
|
4218
|
+
console.log(chalk6.yellow(`No READY atoms found. Current in-progress atom: ${current?.externalId}.`));
|
|
4219
|
+
console.log(chalk6.dim("Use `archon show <atom-id>` to inspect status, or plan a new task."));
|
|
4068
4220
|
return;
|
|
4069
4221
|
}
|
|
4070
4222
|
const blockedByPath = atoms.filter((a) => a.status === "BLOCKED").sort(byMostRecent).find((a) => (a.errorMessage ?? "").toLowerCase().includes("outside the allowed paths"));
|
|
4071
4223
|
if (blockedByPath) {
|
|
4072
|
-
console.log(
|
|
4073
|
-
console.log(
|
|
4224
|
+
console.log(chalk6.yellow(`No READY atoms found. Latest blocked atom: ${blockedByPath.externalId}.`));
|
|
4225
|
+
console.log(chalk6.dim('This atom is blocked by governance path scope. Tell me: "adjust this atom to allowed paths".'));
|
|
4074
4226
|
return;
|
|
4075
4227
|
}
|
|
4076
4228
|
if (queueStarted && runAllReady) {
|
|
4077
|
-
console.log(
|
|
4229
|
+
console.log(chalk6.green("\nQueue execution complete. No READY atoms remain."));
|
|
4078
4230
|
} else {
|
|
4079
|
-
console.log(
|
|
4231
|
+
console.log(chalk6.yellow("No pending atoms found. Tell me what to plan next."));
|
|
4080
4232
|
}
|
|
4081
4233
|
return;
|
|
4082
4234
|
}
|
|
4083
4235
|
const nextAtom = readyAtoms[0];
|
|
4084
4236
|
if (!nextAtom) {
|
|
4085
|
-
console.log(
|
|
4237
|
+
console.log(chalk6.yellow("No pending atoms found. Tell me what to plan next."));
|
|
4086
4238
|
return;
|
|
4087
4239
|
}
|
|
4088
4240
|
if (runAllReady && attempted.has(nextAtom.externalId)) {
|
|
4089
|
-
console.log(
|
|
4090
|
-
console.log(
|
|
4241
|
+
console.log(chalk6.yellow(`Stopping queue execution: ${nextAtom.externalId} is still READY after an execution attempt.`));
|
|
4242
|
+
console.log(chalk6.dim("Inspect with `archon show <atom-id>` before continuing."));
|
|
4091
4243
|
return;
|
|
4092
4244
|
}
|
|
4093
4245
|
attempted.add(nextAtom.externalId);
|
|
4094
4246
|
queueStarted = true;
|
|
4095
4247
|
if (runAllReady) {
|
|
4096
|
-
console.log(
|
|
4248
|
+
console.log(chalk6.dim(`
|
|
4097
4249
|
Queue execution: running ${nextAtom.externalId}...
|
|
4098
4250
|
`));
|
|
4099
4251
|
} else {
|
|
4100
|
-
console.log(
|
|
4252
|
+
console.log(chalk6.dim(`
|
|
4101
4253
|
Continuing with ${nextAtom.externalId}...
|
|
4102
4254
|
`));
|
|
4103
4255
|
}
|
|
@@ -4112,8 +4264,8 @@ Continuing with ${nextAtom.externalId}...
|
|
|
4112
4264
|
const executedAtom = refreshed.find((a) => a.externalId === nextAtom.externalId);
|
|
4113
4265
|
const status2 = executedAtom?.status ?? "UNKNOWN";
|
|
4114
4266
|
if (status2 !== "DONE") {
|
|
4115
|
-
console.log(
|
|
4116
|
-
console.log(
|
|
4267
|
+
console.log(chalk6.yellow(`Queue execution paused at ${nextAtom.externalId} (status: ${status2}).`));
|
|
4268
|
+
console.log(chalk6.dim('Resolve this atom, then run "continue" to resume the queue.'));
|
|
4117
4269
|
return;
|
|
4118
4270
|
}
|
|
4119
4271
|
}
|
|
@@ -4127,19 +4279,19 @@ async function replanLatestBlockedAtom(cwd) {
|
|
|
4127
4279
|
return bTime - aTime;
|
|
4128
4280
|
})[0];
|
|
4129
4281
|
if (!blocked) {
|
|
4130
|
-
console.log(
|
|
4282
|
+
console.log(chalk6.yellow("No blocked atom with path-scope guidance found."));
|
|
4131
4283
|
return;
|
|
4132
4284
|
}
|
|
4133
4285
|
const allowedPaths = await listArchitecturePaths(cwd);
|
|
4134
4286
|
const scope = allowedPaths.length > 0 ? allowedPaths.join(", ") : "existing architecture component paths";
|
|
4135
|
-
console.log(
|
|
4287
|
+
console.log(chalk6.dim("\n> Re-planning the blocked task with explicit allowed-path constraints...\n"));
|
|
4136
4288
|
await plan2(`${blocked.title}
|
|
4137
4289
|
|
|
4138
4290
|
Constraints:
|
|
4139
4291
|
- Only modify files within these allowed architecture paths: ${scope}
|
|
4140
4292
|
- If required files are outside scope, first propose the minimum ARCHITECTURE.md path update needed.`, { conversational: true });
|
|
4141
4293
|
await showLatestPlannedAtom(cwd);
|
|
4142
|
-
console.log(
|
|
4294
|
+
console.log(chalk6.dim('\nReply "continue" to execute this re-scoped atom.'));
|
|
4143
4295
|
}
|
|
4144
4296
|
async function listArchitecturePaths(cwd) {
|
|
4145
4297
|
try {
|
|
@@ -4156,14 +4308,14 @@ async function showMainMenu() {
|
|
|
4156
4308
|
const cwd = process.cwd();
|
|
4157
4309
|
while (true) {
|
|
4158
4310
|
const state = detectProjectState(cwd);
|
|
4159
|
-
console.log(
|
|
4311
|
+
console.log(chalk6.bold("What would you like to do?\n"));
|
|
4160
4312
|
if (state.isWebProject) {
|
|
4161
4313
|
const { loadWebChecks, formatWebCheckStatus } = await import("./web-checks-4BSYXWDF.js");
|
|
4162
4314
|
const prefs = await loadWebChecks(cwd);
|
|
4163
|
-
console.log(
|
|
4164
|
-
console.log(
|
|
4165
|
-
console.log(
|
|
4166
|
-
console.log(
|
|
4315
|
+
console.log(chalk6.dim("Web checks status:"));
|
|
4316
|
+
console.log(chalk6.dim(` A11y: ${formatWebCheckStatus(prefs.lastRun?.a11y)}`));
|
|
4317
|
+
console.log(chalk6.dim(` SEO: ${formatWebCheckStatus(prefs.lastRun?.seo)}`));
|
|
4318
|
+
console.log(chalk6.dim(` GEO: ${formatWebCheckStatus(prefs.lastRun?.geo)}`));
|
|
4167
4319
|
console.log();
|
|
4168
4320
|
}
|
|
4169
4321
|
const choices = [
|
|
@@ -4184,9 +4336,9 @@ async function showMainMenu() {
|
|
|
4184
4336
|
{ key: "q", label: "Quit", action: async () => process.exit(0) }
|
|
4185
4337
|
];
|
|
4186
4338
|
for (const choice2 of choices) {
|
|
4187
|
-
console.log(` ${
|
|
4339
|
+
console.log(` ${chalk6.cyan(choice2.key)}) ${choice2.label}`);
|
|
4188
4340
|
}
|
|
4189
|
-
console.log(
|
|
4341
|
+
console.log(chalk6.dim(' (Type "/" for quick commands, or "upgrade"/"help" anytime)'));
|
|
4190
4342
|
console.log();
|
|
4191
4343
|
const selected = await promptWithCommands("Tell me what you want to do (or enter a shortcut)", { allowMultiline: true });
|
|
4192
4344
|
const choice = choices.find((c) => c.key === selected.toLowerCase());
|
|
@@ -4197,11 +4349,11 @@ async function showMainMenu() {
|
|
|
4197
4349
|
if (selected.trim()) {
|
|
4198
4350
|
const handled = await handleFreeformJourneyInput(cwd, selected.trim());
|
|
4199
4351
|
if (!handled) {
|
|
4200
|
-
console.log(
|
|
4352
|
+
console.log(chalk6.yellow("I did not catch that. Try describing your goal in one sentence."));
|
|
4201
4353
|
}
|
|
4202
4354
|
continue;
|
|
4203
4355
|
}
|
|
4204
|
-
console.log(
|
|
4356
|
+
console.log(chalk6.yellow("Invalid choice. Please try again."));
|
|
4205
4357
|
}
|
|
4206
4358
|
}
|
|
4207
4359
|
async function handleFreeformJourneyInput(cwd, input) {
|
|
@@ -4217,23 +4369,23 @@ async function handleFreeformJourneyInput(cwd, input) {
|
|
|
4217
4369
|
}
|
|
4218
4370
|
const intent = detectUserIntent(freeform);
|
|
4219
4371
|
if (isReadOnlyExploreRequest(freeform) || intent.mode === "explore" && intent.confidence >= 0.7) {
|
|
4220
|
-
console.log(
|
|
4372
|
+
console.log(chalk6.dim("\n> Got it! Analyzing the project...\n"));
|
|
4221
4373
|
await runExploreFlow(cwd, freeform);
|
|
4222
4374
|
return true;
|
|
4223
4375
|
}
|
|
4224
4376
|
if (intent.mode === "app_builder" && intent.confidence >= 0.7) {
|
|
4225
4377
|
const state = detectProjectState(cwd);
|
|
4226
4378
|
if (state.hasArchitecture) {
|
|
4227
|
-
console.log(
|
|
4379
|
+
console.log(chalk6.dim("\n> Got it! Creating a task for this...\n"));
|
|
4228
4380
|
const { plan: plan3 } = await import("./plan-I3P6U2ZM.js");
|
|
4229
4381
|
await plan3(await withAllowedPathScope(cwd, freeform), { conversational: true });
|
|
4230
4382
|
return true;
|
|
4231
4383
|
}
|
|
4232
|
-
console.log(
|
|
4384
|
+
console.log(chalk6.dim("\n> Let me understand your project better...\n"));
|
|
4233
4385
|
await runConversationalInterview(cwd, freeform);
|
|
4234
4386
|
return true;
|
|
4235
4387
|
}
|
|
4236
|
-
console.log(
|
|
4388
|
+
console.log(chalk6.dim("\n> Got it! Creating a task for this...\n"));
|
|
4237
4389
|
const { plan: plan2 } = await import("./plan-I3P6U2ZM.js");
|
|
4238
4390
|
await plan2(await withAllowedPathScope(cwd, freeform), { conversational: true });
|
|
4239
4391
|
return true;
|
|
@@ -4284,14 +4436,14 @@ async function handlePostExploreAction(cwd, request, options = {}) {
|
|
|
4284
4436
|
}
|
|
4285
4437
|
const intent = detectUserIntent(request);
|
|
4286
4438
|
if (intent.mode === "app_builder" && intent.confidence >= 0.7) {
|
|
4287
|
-
console.log(
|
|
4439
|
+
console.log(chalk6.dim("> Let me understand your project better...\n"));
|
|
4288
4440
|
await runConversationalInterview(cwd, request);
|
|
4289
4441
|
return;
|
|
4290
4442
|
}
|
|
4291
4443
|
if (intent.mode === "explore" && intent.confidence >= 0.7) {
|
|
4292
|
-
console.log(
|
|
4444
|
+
console.log(chalk6.dim("> I can go deeper. Creating a concrete task from your request...\n"));
|
|
4293
4445
|
} else {
|
|
4294
|
-
console.log(
|
|
4446
|
+
console.log(chalk6.dim("> Got it! Creating a task for this...\n"));
|
|
4295
4447
|
}
|
|
4296
4448
|
const { plan: plan2 } = await import("./plan-I3P6U2ZM.js");
|
|
4297
4449
|
await plan2(await withAllowedPathScope(cwd, request), { conversational: true });
|
|
@@ -4301,7 +4453,7 @@ async function handlePostExploreAction(cwd, request, options = {}) {
|
|
|
4301
4453
|
return;
|
|
4302
4454
|
}
|
|
4303
4455
|
await showLatestPlannedAtom(cwd);
|
|
4304
|
-
console.log(
|
|
4456
|
+
console.log(chalk6.dim('\nReply "execute atom" when you want implementation to start, or tell me what to change.'));
|
|
4305
4457
|
}
|
|
4306
4458
|
}
|
|
4307
4459
|
async function withAllowedPathScope(cwd, request) {
|
|
@@ -4330,13 +4482,13 @@ async function listAtoms() {
|
|
|
4330
4482
|
async function executeNext() {
|
|
4331
4483
|
const { listLocalAtoms: listLocalAtoms2 } = await import("./plan-I3P6U2ZM.js");
|
|
4332
4484
|
const { analyzeProject, getComplexityDescription, getModeDescription } = await import("./orchestration-HIF3KP25.js");
|
|
4333
|
-
const { loadExecutionPreferences } = await import("./preferences-
|
|
4485
|
+
const { loadExecutionPreferences } = await import("./preferences-MTGN2VZK.js");
|
|
4334
4486
|
const cwd = process.cwd();
|
|
4335
4487
|
const atoms = await listLocalAtoms2();
|
|
4336
4488
|
const pendingAtoms = atoms.filter((a) => a.status === "READY" || a.status === "IN_PROGRESS");
|
|
4337
4489
|
const readyAtoms = atoms.filter((a) => a.status === "READY");
|
|
4338
4490
|
if (pendingAtoms.length === 0) {
|
|
4339
|
-
console.log(
|
|
4491
|
+
console.log(chalk6.yellow('No pending atoms. Use "archon plan" to create one.'));
|
|
4340
4492
|
return;
|
|
4341
4493
|
}
|
|
4342
4494
|
if (pendingAtoms.length > 1) {
|
|
@@ -4344,20 +4496,20 @@ async function executeNext() {
|
|
|
4344
4496
|
const prefs = await loadExecutionPreferences(cwd);
|
|
4345
4497
|
const config = await loadConfig();
|
|
4346
4498
|
const canUseCloud = (config.tier ?? "FREE") === "CREDITS";
|
|
4347
|
-
console.log(
|
|
4348
|
-
console.log(` ${
|
|
4349
|
-
console.log(` ${
|
|
4350
|
-
console.log(` ${
|
|
4351
|
-
console.log(` ${
|
|
4499
|
+
console.log(chalk6.blue("\n-- Project Analysis --\n"));
|
|
4500
|
+
console.log(` ${chalk6.bold("Atoms:")} ${analysis.atomCount}`);
|
|
4501
|
+
console.log(` ${chalk6.bold("Estimated:")} ${analysis.estimatedMinutes} minutes`);
|
|
4502
|
+
console.log(` ${chalk6.bold("Complexity:")} ${analysis.complexity} - ${getComplexityDescription(analysis.complexity)}`);
|
|
4503
|
+
console.log(` ${chalk6.bold("Suggested:")} ${analysis.suggestedMode} - ${getModeDescription(analysis.suggestedMode)}`);
|
|
4352
4504
|
console.log();
|
|
4353
4505
|
let selectedMode = "sequential";
|
|
4354
4506
|
if (canUseCloud && prefs.cloudMode === "always" && analysis.suggestedMode === "parallel-cloud") {
|
|
4355
4507
|
selectedMode = "parallel-cloud";
|
|
4356
|
-
console.log(
|
|
4508
|
+
console.log(chalk6.green(`
|
|
4357
4509
|
\u2713 Auto-selected parallel cloud execution (preference: always)`));
|
|
4358
4510
|
} else if (prefs.parallelMode === "always" && analysis.suggestedMode !== "sequential") {
|
|
4359
4511
|
selectedMode = "parallel-local";
|
|
4360
|
-
console.log(
|
|
4512
|
+
console.log(chalk6.green(`
|
|
4361
4513
|
\u2713 Auto-selected parallel local execution (preference: always)`));
|
|
4362
4514
|
} else if (prefs.parallelMode === "ask" || canUseCloud && prefs.cloudMode === "ask") {
|
|
4363
4515
|
const options = [
|
|
@@ -4373,18 +4525,18 @@ async function executeNext() {
|
|
|
4373
4525
|
}
|
|
4374
4526
|
if (selectedMode !== "sequential") {
|
|
4375
4527
|
if (readyAtoms.length === 0) {
|
|
4376
|
-
console.log(
|
|
4528
|
+
console.log(chalk6.yellow("No READY atoms available for parallel execution."));
|
|
4377
4529
|
return;
|
|
4378
4530
|
}
|
|
4379
|
-
console.log(
|
|
4531
|
+
console.log(chalk6.dim("\nPending atoms:"));
|
|
4380
4532
|
for (const atom of readyAtoms) {
|
|
4381
|
-
console.log(
|
|
4533
|
+
console.log(chalk6.dim(` - ${atom.id}: ${atom.title}`));
|
|
4382
4534
|
}
|
|
4383
4535
|
console.log();
|
|
4384
4536
|
const raw = await prompt("Enter atom IDs to run in parallel (comma-separated, or press Enter for all)");
|
|
4385
4537
|
const selectedIds = raw.trim() ? raw.split(",").map((s) => s.trim()).filter(Boolean) : readyAtoms.map((a) => a.id);
|
|
4386
4538
|
if (selectedIds.length === 0) {
|
|
4387
|
-
console.log(
|
|
4539
|
+
console.log(chalk6.yellow("No atoms selected."));
|
|
4388
4540
|
return;
|
|
4389
4541
|
}
|
|
4390
4542
|
let runIds = selectedIds;
|
|
@@ -4395,7 +4547,7 @@ async function executeNext() {
|
|
|
4395
4547
|
);
|
|
4396
4548
|
if (!override) {
|
|
4397
4549
|
runIds = selectedIds.slice(0, prefs.maxParallelAgents);
|
|
4398
|
-
console.log(
|
|
4550
|
+
console.log(chalk6.dim(`Running first ${runIds.length} atoms.`));
|
|
4399
4551
|
}
|
|
4400
4552
|
}
|
|
4401
4553
|
if (selectedMode === "parallel-cloud") {
|
|
@@ -4414,7 +4566,7 @@ async function executeNext() {
|
|
|
4414
4566
|
const { execute: execute2 } = await import("./execute-AQWHZKDH.js");
|
|
4415
4567
|
await execute2(targetId, {});
|
|
4416
4568
|
} else {
|
|
4417
|
-
console.log(
|
|
4569
|
+
console.log(chalk6.yellow("No atom to execute."));
|
|
4418
4570
|
}
|
|
4419
4571
|
}
|
|
4420
4572
|
async function reportBug() {
|
|
@@ -4429,26 +4581,26 @@ async function viewStatus() {
|
|
|
4429
4581
|
await status2();
|
|
4430
4582
|
}
|
|
4431
4583
|
async function settingsMenu() {
|
|
4432
|
-
const { interactiveSettings } = await import("./preferences-
|
|
4584
|
+
const { interactiveSettings } = await import("./preferences-MTGN2VZK.js");
|
|
4433
4585
|
await interactiveSettings();
|
|
4434
4586
|
}
|
|
4435
4587
|
async function reviewCode() {
|
|
4436
4588
|
const cwd = process.cwd();
|
|
4437
4589
|
const reviewDbPath = join6(cwd, "docs", "code-review", "review-tasks.db");
|
|
4438
4590
|
if (!existsSync6(reviewDbPath)) {
|
|
4439
|
-
console.log(
|
|
4591
|
+
console.log(chalk6.dim("Code review not initialized. Starting setup...\n"));
|
|
4440
4592
|
const { reviewInit: reviewInit2 } = await import("./review-7BBVCF7H.js");
|
|
4441
4593
|
await reviewInit2();
|
|
4442
4594
|
console.log();
|
|
4443
4595
|
}
|
|
4444
|
-
console.log(
|
|
4445
|
-
console.log(
|
|
4446
|
-
console.log(` ${
|
|
4447
|
-
console.log(` ${
|
|
4448
|
-
console.log(` ${
|
|
4449
|
-
console.log(` ${
|
|
4450
|
-
console.log(` ${
|
|
4451
|
-
console.log(` ${
|
|
4596
|
+
console.log(chalk6.bold("\nCode Review Options:\n"));
|
|
4597
|
+
console.log(chalk6.dim("You can type naturally (recommended) or use a shortcut:\n"));
|
|
4598
|
+
console.log(` ${chalk6.cyan("1")}) Analyze project`);
|
|
4599
|
+
console.log(` ${chalk6.cyan("2")}) Show review status`);
|
|
4600
|
+
console.log(` ${chalk6.cyan("3")}) Review next file`);
|
|
4601
|
+
console.log(` ${chalk6.cyan("4")}) List all tasks`);
|
|
4602
|
+
console.log(` ${chalk6.cyan("5")}) Run AI review on all pending`);
|
|
4603
|
+
console.log(` ${chalk6.cyan("b")}) Back to main menu`);
|
|
4452
4604
|
console.log();
|
|
4453
4605
|
const raw = await promptWithCommands("What do you want to do?", { allowMultiline: true });
|
|
4454
4606
|
const choice = resolveReviewChoice(raw);
|
|
@@ -4487,7 +4639,7 @@ async function reviewCode() {
|
|
|
4487
4639
|
return;
|
|
4488
4640
|
}
|
|
4489
4641
|
}
|
|
4490
|
-
console.log(
|
|
4642
|
+
console.log(chalk6.yellow("I did not catch that. Tell me what review action you want."));
|
|
4491
4643
|
}
|
|
4492
4644
|
await reviewCode();
|
|
4493
4645
|
}
|
|
@@ -4515,13 +4667,13 @@ async function handleInSessionCommand(input) {
|
|
|
4515
4667
|
}
|
|
4516
4668
|
if (normalized === "help" || normalized === "?" || normalized === "archon help") {
|
|
4517
4669
|
console.log();
|
|
4518
|
-
console.log(
|
|
4519
|
-
console.log(
|
|
4520
|
-
console.log(
|
|
4521
|
-
console.log(
|
|
4522
|
-
console.log(
|
|
4523
|
-
console.log(
|
|
4524
|
-
console.log(
|
|
4670
|
+
console.log(chalk6.bold("Available commands (type anytime):"));
|
|
4671
|
+
console.log(chalk6.dim(" upgrade \u2014 Switch to BYOK or Managed plan"));
|
|
4672
|
+
console.log(chalk6.dim(" status \u2014 Show login and tier status"));
|
|
4673
|
+
console.log(chalk6.dim(" keys \u2014 Manage API keys (BYOK tier)"));
|
|
4674
|
+
console.log(chalk6.dim(" /workflow \u2014 Open classic workflow menu"));
|
|
4675
|
+
console.log(chalk6.dim(" quit / q \u2014 Exit ArchonDev"));
|
|
4676
|
+
console.log(chalk6.dim(" skip \u2014 Skip current question"));
|
|
4525
4677
|
console.log();
|
|
4526
4678
|
return true;
|
|
4527
4679
|
}
|
|
@@ -4531,23 +4683,23 @@ async function handleInSessionCommand(input) {
|
|
|
4531
4683
|
return true;
|
|
4532
4684
|
}
|
|
4533
4685
|
if (normalized === "quit" || normalized === "exit" || normalized === "q") {
|
|
4534
|
-
console.log(
|
|
4686
|
+
console.log(chalk6.dim("Goodbye!"));
|
|
4535
4687
|
process.exit(0);
|
|
4536
4688
|
}
|
|
4537
4689
|
return false;
|
|
4538
4690
|
}
|
|
4539
4691
|
function showSlashCommandMenu() {
|
|
4540
4692
|
console.log();
|
|
4541
|
-
console.log(
|
|
4542
|
-
console.log(
|
|
4543
|
-
console.log(
|
|
4544
|
-
console.log(
|
|
4545
|
-
console.log(
|
|
4546
|
-
console.log(
|
|
4547
|
-
console.log(
|
|
4548
|
-
console.log(
|
|
4549
|
-
console.log(
|
|
4550
|
-
console.log(
|
|
4693
|
+
console.log(chalk6.bold("Quick Commands"));
|
|
4694
|
+
console.log(chalk6.dim(" /plan <task> Create a plan from a one-line task"));
|
|
4695
|
+
console.log(chalk6.dim(" /list List atoms"));
|
|
4696
|
+
console.log(chalk6.dim(" /execute Execute next atom"));
|
|
4697
|
+
console.log(chalk6.dim(" /review Open code review menu"));
|
|
4698
|
+
console.log(chalk6.dim(" /status Show account/status"));
|
|
4699
|
+
console.log(chalk6.dim(" /settings Open settings & preferences"));
|
|
4700
|
+
console.log(chalk6.dim(" /upgrade Open tier upgrade menu"));
|
|
4701
|
+
console.log(chalk6.dim(" /workflow Open classic workflow menu"));
|
|
4702
|
+
console.log(chalk6.dim(" /quit Exit ArchonDev"));
|
|
4551
4703
|
console.log();
|
|
4552
4704
|
}
|
|
4553
4705
|
async function handleSlashCommand(input) {
|
|
@@ -4596,7 +4748,7 @@ async function handleSlashCommand(input) {
|
|
|
4596
4748
|
return true;
|
|
4597
4749
|
case "/quit":
|
|
4598
4750
|
case "/exit":
|
|
4599
|
-
console.log(
|
|
4751
|
+
console.log(chalk6.dim("Goodbye!"));
|
|
4600
4752
|
process.exit(0);
|
|
4601
4753
|
}
|
|
4602
4754
|
return false;
|
|
@@ -4604,7 +4756,7 @@ async function handleSlashCommand(input) {
|
|
|
4604
4756
|
function prompt(question) {
|
|
4605
4757
|
return new Promise((resolve) => {
|
|
4606
4758
|
const safeMode = isTerminalSafeMode();
|
|
4607
|
-
const promptPrefix = safeMode ? ">" :
|
|
4759
|
+
const promptPrefix = safeMode ? ">" : chalk6.cyan("?");
|
|
4608
4760
|
const rl = readline.createInterface({
|
|
4609
4761
|
input: process.stdin,
|
|
4610
4762
|
output: process.stdout,
|
|
@@ -4619,7 +4771,7 @@ function prompt(question) {
|
|
|
4619
4771
|
function promptMultiline(question) {
|
|
4620
4772
|
return new Promise((resolve) => {
|
|
4621
4773
|
const safeMode = isTerminalSafeMode();
|
|
4622
|
-
const promptPrefix = safeMode ? ">" :
|
|
4774
|
+
const promptPrefix = safeMode ? ">" : chalk6.cyan("?");
|
|
4623
4775
|
const rl = readline.createInterface({
|
|
4624
4776
|
input: process.stdin,
|
|
4625
4777
|
output: process.stdout,
|
|
@@ -4655,14 +4807,14 @@ async function promptWithCommands(question, options = {}) {
|
|
|
4655
4807
|
if (!handled) {
|
|
4656
4808
|
return answer;
|
|
4657
4809
|
}
|
|
4658
|
-
console.log(
|
|
4810
|
+
console.log(chalk6.dim("(Returning to previous question...)\n"));
|
|
4659
4811
|
}
|
|
4660
4812
|
}
|
|
4661
4813
|
async function runWebChecksSuite() {
|
|
4662
4814
|
const { a11yCheck: a11yCheck2 } = await import("./a11y-O35BAA25.js");
|
|
4663
4815
|
const { seoCheck } = await import("./seo-PMI42KRZ.js");
|
|
4664
4816
|
const { geoAudit } = await import("./geo-KXVALNSF.js");
|
|
4665
|
-
console.log(
|
|
4817
|
+
console.log(chalk6.blue("\nRunning web checks (A11y, SEO, GEO)...\n"));
|
|
4666
4818
|
await a11yCheck2({});
|
|
4667
4819
|
await seoCheck({});
|
|
4668
4820
|
await geoAudit();
|
|
@@ -4671,19 +4823,19 @@ async function showWebChecksMenu() {
|
|
|
4671
4823
|
const cwd = process.cwd();
|
|
4672
4824
|
const { loadWebChecks, formatWebCheckStatus, setWebPromptMode } = await import("./web-checks-4BSYXWDF.js");
|
|
4673
4825
|
const prefs = await loadWebChecks(cwd);
|
|
4674
|
-
console.log(
|
|
4675
|
-
console.log(
|
|
4676
|
-
console.log(
|
|
4677
|
-
console.log(
|
|
4826
|
+
console.log(chalk6.bold("\nWeb Checks (SEO / GEO / A11y)\n"));
|
|
4827
|
+
console.log(chalk6.dim(`A11y: ${formatWebCheckStatus(prefs.lastRun?.a11y)}`));
|
|
4828
|
+
console.log(chalk6.dim(`SEO: ${formatWebCheckStatus(prefs.lastRun?.seo)}`));
|
|
4829
|
+
console.log(chalk6.dim(`GEO: ${formatWebCheckStatus(prefs.lastRun?.geo)}`));
|
|
4678
4830
|
console.log();
|
|
4679
|
-
console.log(` ${
|
|
4680
|
-
console.log(` ${
|
|
4681
|
-
console.log(` ${
|
|
4682
|
-
console.log(` ${
|
|
4683
|
-
console.log(` ${
|
|
4684
|
-
console.log(` ${
|
|
4685
|
-
console.log(` ${
|
|
4686
|
-
console.log(` ${
|
|
4831
|
+
console.log(` ${chalk6.cyan("1")}) Run all checks`);
|
|
4832
|
+
console.log(` ${chalk6.cyan("2")}) Run accessibility check`);
|
|
4833
|
+
console.log(` ${chalk6.cyan("3")}) Run SEO check`);
|
|
4834
|
+
console.log(` ${chalk6.cyan("4")}) Run GEO audit`);
|
|
4835
|
+
console.log(` ${chalk6.cyan("5")}) Generate GEO identity`);
|
|
4836
|
+
console.log(` ${chalk6.cyan("6")}) Generate GEO schema`);
|
|
4837
|
+
console.log(` ${chalk6.cyan("7")}) Set prompt mode (ask/always/never)`);
|
|
4838
|
+
console.log(` ${chalk6.cyan("b")}) Back to main menu`);
|
|
4687
4839
|
console.log();
|
|
4688
4840
|
const raw = await promptWithCommands("What do you want to do?", { allowMultiline: true });
|
|
4689
4841
|
const choice = resolveWebChecksChoice(raw);
|
|
@@ -4718,9 +4870,9 @@ async function showWebChecksMenu() {
|
|
|
4718
4870
|
}
|
|
4719
4871
|
case "7": {
|
|
4720
4872
|
console.log();
|
|
4721
|
-
console.log(` ${
|
|
4722
|
-
console.log(` ${
|
|
4723
|
-
console.log(` ${
|
|
4873
|
+
console.log(` ${chalk6.cyan("1")}) Ask each session`);
|
|
4874
|
+
console.log(` ${chalk6.cyan("2")}) Always run automatically`);
|
|
4875
|
+
console.log(` ${chalk6.cyan("3")}) Never prompt`);
|
|
4724
4876
|
console.log();
|
|
4725
4877
|
const modeChoiceRaw = await promptWithCommands("Set mode (ask / always / never)");
|
|
4726
4878
|
const modeChoice = resolvePromptModeChoice(modeChoiceRaw);
|
|
@@ -4736,7 +4888,7 @@ async function showWebChecksMenu() {
|
|
|
4736
4888
|
return;
|
|
4737
4889
|
}
|
|
4738
4890
|
}
|
|
4739
|
-
console.log(
|
|
4891
|
+
console.log(chalk6.yellow("I did not catch that. Tell me which web check you want."));
|
|
4740
4892
|
}
|
|
4741
4893
|
if (choice.toLowerCase() !== "b") {
|
|
4742
4894
|
await showWebChecksMenu();
|
|
@@ -4752,11 +4904,11 @@ async function maybePromptWebChecks(cwd, projectState) {
|
|
|
4752
4904
|
return;
|
|
4753
4905
|
}
|
|
4754
4906
|
if (prefs.promptMode === "always") {
|
|
4755
|
-
console.log(
|
|
4907
|
+
console.log(chalk6.blue("\nWeb project detected. Running web checks automatically...\n"));
|
|
4756
4908
|
await runWebChecksSuite();
|
|
4757
4909
|
return;
|
|
4758
4910
|
}
|
|
4759
|
-
console.log(
|
|
4911
|
+
console.log(chalk6.blue("\nWeb project detected."));
|
|
4760
4912
|
const choice = await promptChoice("Run web checks now?", [
|
|
4761
4913
|
{ key: "1", label: "Run all checks (A11y + SEO + GEO)" },
|
|
4762
4914
|
{ key: "2", label: "Choose checks" },
|
|
@@ -4778,7 +4930,7 @@ function promptYesNo(question, defaultValue) {
|
|
|
4778
4930
|
output: process.stdout
|
|
4779
4931
|
});
|
|
4780
4932
|
const hint = defaultValue ? "(Y/n)" : "(y/N)";
|
|
4781
|
-
rl.question(`${
|
|
4933
|
+
rl.question(`${chalk6.cyan("?")} ${question} ${hint}: `, (answer) => {
|
|
4782
4934
|
rl.close();
|
|
4783
4935
|
if (answer.trim() === "") {
|
|
4784
4936
|
resolve(defaultValue);
|
|
@@ -4790,15 +4942,15 @@ function promptYesNo(question, defaultValue) {
|
|
|
4790
4942
|
}
|
|
4791
4943
|
function promptChoice(question, options, defaultKey) {
|
|
4792
4944
|
return new Promise((resolve) => {
|
|
4793
|
-
console.log(`${
|
|
4945
|
+
console.log(`${chalk6.cyan("?")} ${question}`);
|
|
4794
4946
|
for (const opt of options) {
|
|
4795
|
-
console.log(` ${
|
|
4947
|
+
console.log(` ${chalk6.dim(opt.key)}) ${opt.label}`);
|
|
4796
4948
|
}
|
|
4797
4949
|
const rl = readline.createInterface({
|
|
4798
4950
|
input: process.stdin,
|
|
4799
4951
|
output: process.stdout
|
|
4800
4952
|
});
|
|
4801
|
-
rl.question(` ${
|
|
4953
|
+
rl.question(` ${chalk6.dim("Enter choice or describe what you want")}: `, (answer) => {
|
|
4802
4954
|
rl.close();
|
|
4803
4955
|
const trimmed = answer.trim();
|
|
4804
4956
|
if (trimmed) {
|
|
@@ -4861,7 +5013,7 @@ function resolvePromptModeChoice(input) {
|
|
|
4861
5013
|
}
|
|
4862
5014
|
|
|
4863
5015
|
// src/cli/credits.ts
|
|
4864
|
-
import
|
|
5016
|
+
import chalk7 from "chalk";
|
|
4865
5017
|
import ora from "ora";
|
|
4866
5018
|
import open from "open";
|
|
4867
5019
|
import readline2 from "readline";
|
|
@@ -4907,20 +5059,20 @@ async function showCredits() {
|
|
|
4907
5059
|
const profile = data;
|
|
4908
5060
|
spinner.stop();
|
|
4909
5061
|
console.log();
|
|
4910
|
-
console.log(
|
|
5062
|
+
console.log(chalk7.bold("\u{1F4B0} Credit Balance"));
|
|
4911
5063
|
console.log();
|
|
4912
5064
|
const balance = (profile.credit_balance_cents || 0) / 100;
|
|
4913
5065
|
console.log(` Tier: ${formatTier(profile.tier)}`);
|
|
4914
|
-
console.log(` Balance: ${
|
|
5066
|
+
console.log(` Balance: ${chalk7.green(`$${balance.toFixed(2)}`)}`);
|
|
4915
5067
|
if (profile.tier === "FREE") {
|
|
4916
5068
|
console.log(` Atoms: ${profile.atoms_used_this_month}/10,000 this month`);
|
|
4917
5069
|
console.log();
|
|
4918
|
-
console.log(
|
|
5070
|
+
console.log(chalk7.dim(" Upgrade to Credits tier: archon credits add"));
|
|
4919
5071
|
printCreditsNextAction("FREE");
|
|
4920
5072
|
} else if (profile.tier === "CREDITS") {
|
|
4921
5073
|
console.log();
|
|
4922
|
-
console.log(
|
|
4923
|
-
console.log(
|
|
5074
|
+
console.log(chalk7.dim(" Add more credits: archon credits add"));
|
|
5075
|
+
console.log(chalk7.dim(" Detailed usage by model: archon usage"));
|
|
4924
5076
|
printCreditsNextAction("CREDITS");
|
|
4925
5077
|
if (balance < 5) {
|
|
4926
5078
|
const addNow = await promptYesNo2("Balance is low. Add credits now?", false);
|
|
@@ -4930,8 +5082,8 @@ async function showCredits() {
|
|
|
4930
5082
|
}
|
|
4931
5083
|
} else if (profile.tier === "BYOK") {
|
|
4932
5084
|
console.log();
|
|
4933
|
-
console.log(
|
|
4934
|
-
console.log(
|
|
5085
|
+
console.log(chalk7.dim(" Using your own API keys - no credit charges"));
|
|
5086
|
+
console.log(chalk7.dim(" Estimated spend by model: archon usage"));
|
|
4935
5087
|
printCreditsNextAction("BYOK");
|
|
4936
5088
|
}
|
|
4937
5089
|
console.log();
|
|
@@ -4978,35 +5130,35 @@ async function addCredits(options = {}) {
|
|
|
4978
5130
|
}
|
|
4979
5131
|
spinner.succeed("Checkout ready");
|
|
4980
5132
|
console.log();
|
|
4981
|
-
console.log(
|
|
5133
|
+
console.log(chalk7.bold("\u{1F6D2} Add Credits"));
|
|
4982
5134
|
console.log();
|
|
4983
|
-
console.log(` Amount: ${
|
|
5135
|
+
console.log(` Amount: ${chalk7.green(`$${amountDollars.toFixed(2)}`)}`);
|
|
4984
5136
|
console.log();
|
|
4985
5137
|
console.log(" Opening checkout in browser...");
|
|
4986
5138
|
console.log();
|
|
4987
|
-
console.log(
|
|
5139
|
+
console.log(chalk7.dim(` Or visit: ${checkoutUrl}`));
|
|
4988
5140
|
console.log();
|
|
4989
5141
|
try {
|
|
4990
5142
|
await open(checkoutUrl);
|
|
4991
5143
|
} catch {
|
|
4992
|
-
console.log(
|
|
5144
|
+
console.log(chalk7.yellow(" Could not open browser. Please visit the URL above."));
|
|
4993
5145
|
}
|
|
4994
|
-
console.log(
|
|
4995
|
-
console.log(
|
|
4996
|
-
console.log(
|
|
5146
|
+
console.log(chalk7.bold("\nNext best action:"));
|
|
5147
|
+
console.log(chalk7.dim(` \u2022 Complete payment in browser, then run ${chalk7.cyan("archon credits")} to verify balance.`));
|
|
5148
|
+
console.log(chalk7.dim(` \u2022 Continue work with ${chalk7.cyan('archon plan "..."')} or ${chalk7.cyan("archon execute <ATOM-ID>")}.`));
|
|
4997
5149
|
} catch (err2) {
|
|
4998
5150
|
spinner.fail("Error preparing checkout");
|
|
4999
5151
|
console.error(err2);
|
|
5000
5152
|
}
|
|
5001
5153
|
}
|
|
5002
5154
|
function printCreditsNextAction(tier) {
|
|
5003
|
-
console.log(
|
|
5155
|
+
console.log(chalk7.bold(" Next best action:"));
|
|
5004
5156
|
if (tier === "CREDITS") {
|
|
5005
|
-
console.log(
|
|
5157
|
+
console.log(chalk7.dim(` \u2022 Keep at least $5 balance to avoid interruptions during plan/execute.`));
|
|
5006
5158
|
} else if (tier === "BYOK") {
|
|
5007
|
-
console.log(
|
|
5159
|
+
console.log(chalk7.dim(` \u2022 Manage provider keys with ${chalk7.cyan("archon keys add/list/remove")}.`));
|
|
5008
5160
|
} else {
|
|
5009
|
-
console.log(
|
|
5161
|
+
console.log(chalk7.dim(` \u2022 Upgrade to BYOK or Credits with ${chalk7.cyan("archon upgrade")}.`));
|
|
5010
5162
|
}
|
|
5011
5163
|
}
|
|
5012
5164
|
function promptYesNo2(question, defaultValue) {
|
|
@@ -5016,7 +5168,7 @@ function promptYesNo2(question, defaultValue) {
|
|
|
5016
5168
|
output: process.stdout
|
|
5017
5169
|
});
|
|
5018
5170
|
const hint = defaultValue ? "(Y/n)" : "(y/N)";
|
|
5019
|
-
rl.question(`${
|
|
5171
|
+
rl.question(`${chalk7.cyan("?")} ${question} ${hint}: `, (answer) => {
|
|
5020
5172
|
rl.close();
|
|
5021
5173
|
if (answer.trim() === "") {
|
|
5022
5174
|
resolve(defaultValue);
|
|
@@ -5050,15 +5202,15 @@ async function showHistory(options = {}) {
|
|
|
5050
5202
|
const usage = data;
|
|
5051
5203
|
spinner.stop();
|
|
5052
5204
|
console.log();
|
|
5053
|
-
console.log(
|
|
5205
|
+
console.log(chalk7.bold("Usage History"));
|
|
5054
5206
|
console.log();
|
|
5055
5207
|
if (!usage || usage.length === 0) {
|
|
5056
|
-
console.log(
|
|
5208
|
+
console.log(chalk7.dim(" No usage recorded yet."));
|
|
5057
5209
|
console.log();
|
|
5058
5210
|
return;
|
|
5059
5211
|
}
|
|
5060
|
-
console.log(
|
|
5061
|
-
console.log(
|
|
5212
|
+
console.log(chalk7.dim(" Model Tokens Cost Date"));
|
|
5213
|
+
console.log(chalk7.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
5062
5214
|
for (const row of usage) {
|
|
5063
5215
|
const model = row.model.padEnd(30).slice(0, 30);
|
|
5064
5216
|
const tokens = (row.input_tokens + row.output_tokens).toString().padStart(8);
|
|
@@ -5068,9 +5220,9 @@ async function showHistory(options = {}) {
|
|
|
5068
5220
|
}
|
|
5069
5221
|
const totalCost = usage.reduce((sum, r) => sum + r.base_cost, 0);
|
|
5070
5222
|
const totalTokens = usage.reduce((sum, r) => sum + r.input_tokens + r.output_tokens, 0);
|
|
5071
|
-
console.log(
|
|
5223
|
+
console.log(chalk7.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
5072
5224
|
console.log(
|
|
5073
|
-
` ${"Total".padEnd(30)} ${totalTokens.toString().padStart(8)} ${
|
|
5225
|
+
` ${"Total".padEnd(30)} ${totalTokens.toString().padStart(8)} ${chalk7.green(`$${totalCost.toFixed(4)}`.padStart(10))}`
|
|
5074
5226
|
);
|
|
5075
5227
|
console.log();
|
|
5076
5228
|
} catch (err2) {
|
|
@@ -5136,24 +5288,24 @@ async function manageBudget(options = {}) {
|
|
|
5136
5288
|
}
|
|
5137
5289
|
spinner.stop();
|
|
5138
5290
|
console.log();
|
|
5139
|
-
console.log(
|
|
5291
|
+
console.log(chalk7.bold("Monthly Budget"));
|
|
5140
5292
|
console.log();
|
|
5141
5293
|
if (profile.monthly_budget_cents === null) {
|
|
5142
|
-
console.log(` Budget: ${
|
|
5294
|
+
console.log(` Budget: ${chalk7.dim("No limit set")}`);
|
|
5143
5295
|
} else {
|
|
5144
5296
|
const budget = profile.monthly_budget_cents / 100;
|
|
5145
5297
|
const spend = (profile.monthly_spend_cents || 0) / 100;
|
|
5146
5298
|
const remaining = budget - spend;
|
|
5147
5299
|
const percent = budget > 0 ? Math.round(spend / budget * 100) : 0;
|
|
5148
|
-
console.log(` Budget: ${
|
|
5300
|
+
console.log(` Budget: ${chalk7.green(`$${budget.toFixed(2)}`)} / month`);
|
|
5149
5301
|
console.log(` Spent: $${spend.toFixed(2)} (${percent}%)`);
|
|
5150
|
-
console.log(` Remaining: ${remaining >= 0 ?
|
|
5302
|
+
console.log(` Remaining: ${remaining >= 0 ? chalk7.green(`$${remaining.toFixed(2)}`) : chalk7.red(`-$${Math.abs(remaining).toFixed(2)}`)}`);
|
|
5151
5303
|
}
|
|
5152
5304
|
console.log(` Alert at: ${profile.budget_alert_threshold_percent}% of budget`);
|
|
5153
5305
|
console.log();
|
|
5154
|
-
console.log(
|
|
5155
|
-
console.log(
|
|
5156
|
-
console.log(
|
|
5306
|
+
console.log(chalk7.dim(" Set budget: archon credits budget --set 50"));
|
|
5307
|
+
console.log(chalk7.dim(" Clear budget: archon credits budget --clear"));
|
|
5308
|
+
console.log(chalk7.dim(" Set alert: archon credits budget --alert 80"));
|
|
5157
5309
|
console.log();
|
|
5158
5310
|
} catch (err2) {
|
|
5159
5311
|
spinner.fail("Error managing budget");
|
|
@@ -5215,12 +5367,12 @@ async function manageAutoRecharge(options = {}) {
|
|
|
5215
5367
|
}
|
|
5216
5368
|
spinner.stop();
|
|
5217
5369
|
console.log();
|
|
5218
|
-
console.log(
|
|
5370
|
+
console.log(chalk7.bold("\u{1F504} Auto-Recharge"));
|
|
5219
5371
|
console.log();
|
|
5220
5372
|
if (!profile.auto_recharge_enabled) {
|
|
5221
|
-
console.log(` Status: ${
|
|
5373
|
+
console.log(` Status: ${chalk7.dim("Disabled")}`);
|
|
5222
5374
|
} else {
|
|
5223
|
-
console.log(` Status: ${
|
|
5375
|
+
console.log(` Status: ${chalk7.green("Enabled")}`);
|
|
5224
5376
|
if (profile.auto_recharge_threshold_cents !== null) {
|
|
5225
5377
|
console.log(` When: Balance drops below $${(profile.auto_recharge_threshold_cents / 100).toFixed(2)}`);
|
|
5226
5378
|
}
|
|
@@ -5228,10 +5380,10 @@ async function manageAutoRecharge(options = {}) {
|
|
|
5228
5380
|
console.log(` Amount: $${(profile.auto_recharge_amount_cents / 100).toFixed(2)}`);
|
|
5229
5381
|
}
|
|
5230
5382
|
}
|
|
5231
|
-
console.log(` Payment: ${profile.stripe_payment_method_id ?
|
|
5383
|
+
console.log(` Payment: ${profile.stripe_payment_method_id ? chalk7.green("Card saved") : chalk7.dim("No card saved")}`);
|
|
5232
5384
|
console.log();
|
|
5233
|
-
console.log(
|
|
5234
|
-
console.log(
|
|
5385
|
+
console.log(chalk7.dim(" Enable: archon credits auto-recharge --enable --threshold 5 --amount 20"));
|
|
5386
|
+
console.log(chalk7.dim(" Disable: archon credits auto-recharge --disable"));
|
|
5235
5387
|
console.log();
|
|
5236
5388
|
} catch (err2) {
|
|
5237
5389
|
spinner.fail("Error managing auto-recharge");
|
|
@@ -5261,21 +5413,21 @@ async function showAuditHistory(options = {}) {
|
|
|
5261
5413
|
});
|
|
5262
5414
|
if (error) {
|
|
5263
5415
|
spinner.fail("Could not fetch audit history");
|
|
5264
|
-
console.error(
|
|
5416
|
+
console.error(chalk7.dim(error.message));
|
|
5265
5417
|
return;
|
|
5266
5418
|
}
|
|
5267
5419
|
const history = data;
|
|
5268
5420
|
spinner.stop();
|
|
5269
5421
|
console.log();
|
|
5270
|
-
console.log(
|
|
5422
|
+
console.log(chalk7.bold("\u{1F4CB} Billing Audit History"));
|
|
5271
5423
|
console.log();
|
|
5272
5424
|
if (!history || history.length === 0) {
|
|
5273
|
-
console.log(
|
|
5425
|
+
console.log(chalk7.dim(" No billing events recorded yet."));
|
|
5274
5426
|
console.log();
|
|
5275
5427
|
return;
|
|
5276
5428
|
}
|
|
5277
|
-
console.log(
|
|
5278
|
-
console.log(
|
|
5429
|
+
console.log(chalk7.dim(" Event Amount Balance Date"));
|
|
5430
|
+
console.log(chalk7.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
5279
5431
|
for (const row of history) {
|
|
5280
5432
|
const eventType = formatEventType(row.event_type).padEnd(22);
|
|
5281
5433
|
const amount = row.amount_cents !== null ? formatAmount(row.event_type, row.amount_cents).padStart(10) : " -";
|
|
@@ -5283,10 +5435,10 @@ async function showAuditHistory(options = {}) {
|
|
|
5283
5435
|
const date = new Date(row.created_at).toLocaleDateString();
|
|
5284
5436
|
console.log(` ${eventType} ${amount} ${balance} ${date}`);
|
|
5285
5437
|
}
|
|
5286
|
-
console.log(
|
|
5438
|
+
console.log(chalk7.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
5287
5439
|
console.log();
|
|
5288
|
-
console.log(
|
|
5289
|
-
console.log(
|
|
5440
|
+
console.log(chalk7.dim(` Showing ${history.length} most recent events`));
|
|
5441
|
+
console.log(chalk7.dim(" Use --limit N to show more"));
|
|
5290
5442
|
console.log();
|
|
5291
5443
|
} catch (err2) {
|
|
5292
5444
|
spinner.fail("Error fetching audit history");
|
|
@@ -5296,19 +5448,19 @@ async function showAuditHistory(options = {}) {
|
|
|
5296
5448
|
function formatEventType(eventType) {
|
|
5297
5449
|
switch (eventType) {
|
|
5298
5450
|
case "CREDITS_PURCHASED":
|
|
5299
|
-
return
|
|
5451
|
+
return chalk7.green("+ Purchase");
|
|
5300
5452
|
case "CREDITS_DEDUCTED":
|
|
5301
|
-
return
|
|
5453
|
+
return chalk7.red("- Usage");
|
|
5302
5454
|
case "CREDITS_REFUNDED":
|
|
5303
|
-
return
|
|
5455
|
+
return chalk7.cyan("+ Refund");
|
|
5304
5456
|
case "BALANCE_ADJUSTED":
|
|
5305
|
-
return
|
|
5457
|
+
return chalk7.yellow("\xB1 Adjustment");
|
|
5306
5458
|
case "BUDGET_CHANGED":
|
|
5307
|
-
return
|
|
5459
|
+
return chalk7.blue("\u25C9 Budget");
|
|
5308
5460
|
case "TIER_CHANGED":
|
|
5309
|
-
return
|
|
5461
|
+
return chalk7.magenta("\u25C9 Tier");
|
|
5310
5462
|
case "USAGE_RECORDED":
|
|
5311
|
-
return
|
|
5463
|
+
return chalk7.dim("\u25C9 Usage");
|
|
5312
5464
|
default:
|
|
5313
5465
|
return eventType;
|
|
5314
5466
|
}
|
|
@@ -5316,20 +5468,20 @@ function formatEventType(eventType) {
|
|
|
5316
5468
|
function formatAmount(eventType, cents) {
|
|
5317
5469
|
const dollars = (cents / 100).toFixed(2);
|
|
5318
5470
|
if (eventType === "CREDITS_PURCHASED" || eventType === "CREDITS_REFUNDED") {
|
|
5319
|
-
return
|
|
5471
|
+
return chalk7.green(`+$${dollars}`);
|
|
5320
5472
|
} else if (eventType === "CREDITS_DEDUCTED") {
|
|
5321
|
-
return
|
|
5473
|
+
return chalk7.red(`-$${dollars}`);
|
|
5322
5474
|
}
|
|
5323
5475
|
return `$${dollars}`;
|
|
5324
5476
|
}
|
|
5325
5477
|
function formatTier(tier) {
|
|
5326
5478
|
switch (tier) {
|
|
5327
5479
|
case "FREE":
|
|
5328
|
-
return
|
|
5480
|
+
return chalk7.blue("Free (10k atoms/month)");
|
|
5329
5481
|
case "CREDITS":
|
|
5330
|
-
return
|
|
5482
|
+
return chalk7.green("Credits (Pay-as-you-go)");
|
|
5331
5483
|
case "BYOK":
|
|
5332
|
-
return
|
|
5484
|
+
return chalk7.magenta("BYOK (Bring Your Own Key)");
|
|
5333
5485
|
default:
|
|
5334
5486
|
return tier;
|
|
5335
5487
|
}
|
|
@@ -5606,7 +5758,7 @@ async function watch() {
|
|
|
5606
5758
|
|
|
5607
5759
|
// src/cli/deps.ts
|
|
5608
5760
|
import { Command } from "commander";
|
|
5609
|
-
import
|
|
5761
|
+
import chalk8 from "chalk";
|
|
5610
5762
|
import { readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
5611
5763
|
import { existsSync as existsSync8 } from "fs";
|
|
5612
5764
|
var DEPENDENCIES_FILENAME = "DEPENDENCIES.md";
|
|
@@ -5624,30 +5776,30 @@ Examples:
|
|
|
5624
5776
|
deps.command("list").description("List all dependency rules").option("-v, --verbose", "Show detailed information").action(async (options) => {
|
|
5625
5777
|
const parser = new DependencyParser();
|
|
5626
5778
|
if (!parser.exists()) {
|
|
5627
|
-
console.log(
|
|
5628
|
-
console.log(
|
|
5779
|
+
console.log(chalk8.yellow("No DEPENDENCIES.md found."));
|
|
5780
|
+
console.log(chalk8.dim("Create one with: archon deps add --source <path> --dependent <path>"));
|
|
5629
5781
|
return;
|
|
5630
5782
|
}
|
|
5631
5783
|
const result = await parser.parse();
|
|
5632
5784
|
if (!result.success) {
|
|
5633
|
-
console.log(
|
|
5785
|
+
console.log(chalk8.red(`Parse error: ${result.error}`));
|
|
5634
5786
|
return;
|
|
5635
5787
|
}
|
|
5636
5788
|
const rules = result.document?.rules ?? [];
|
|
5637
5789
|
if (rules.length === 0) {
|
|
5638
|
-
console.log(
|
|
5790
|
+
console.log(chalk8.dim("No dependency rules defined."));
|
|
5639
5791
|
return;
|
|
5640
5792
|
}
|
|
5641
|
-
console.log(
|
|
5793
|
+
console.log(chalk8.bold(`
|
|
5642
5794
|
\u{1F4E6} Dependency Rules (${rules.length})
|
|
5643
5795
|
`));
|
|
5644
5796
|
for (const rule of rules) {
|
|
5645
|
-
const severityColor = rule.severity === "BLOCKER" ?
|
|
5646
|
-
console.log(`${severityColor(`[${rule.severity}]`)} ${
|
|
5647
|
-
console.log(` Source: ${
|
|
5648
|
-
console.log(` Dependents: ${rule.dependents.map((d) =>
|
|
5797
|
+
const severityColor = rule.severity === "BLOCKER" ? chalk8.red : rule.severity === "WARNING" ? chalk8.yellow : chalk8.blue;
|
|
5798
|
+
console.log(`${severityColor(`[${rule.severity}]`)} ${chalk8.bold(rule.id)}`);
|
|
5799
|
+
console.log(` Source: ${chalk8.cyan(rule.source)}`);
|
|
5800
|
+
console.log(` Dependents: ${rule.dependents.map((d) => chalk8.dim(d)).join(", ")}`);
|
|
5649
5801
|
if (rule.reason && options.verbose) {
|
|
5650
|
-
console.log(` Reason: ${
|
|
5802
|
+
console.log(` Reason: ${chalk8.dim(rule.reason)}`);
|
|
5651
5803
|
}
|
|
5652
5804
|
if (rule.mustTest && options.verbose) {
|
|
5653
5805
|
console.log(` Must test: ${rule.mustTest.join(", ")}`);
|
|
@@ -5659,29 +5811,29 @@ Examples:
|
|
|
5659
5811
|
const files = options.files.split(",").map((f) => f.trim());
|
|
5660
5812
|
const parser = new DependencyParser();
|
|
5661
5813
|
if (!parser.exists()) {
|
|
5662
|
-
console.log(
|
|
5814
|
+
console.log(chalk8.dim("No DEPENDENCIES.md found. No dependency checks performed."));
|
|
5663
5815
|
process.exit(0);
|
|
5664
5816
|
}
|
|
5665
5817
|
const result = await parser.checkFiles(files);
|
|
5666
5818
|
if (result.impacts.length === 0) {
|
|
5667
|
-
console.log(
|
|
5819
|
+
console.log(chalk8.green("\u2705 No downstream dependency impacts found."));
|
|
5668
5820
|
process.exit(0);
|
|
5669
5821
|
}
|
|
5670
|
-
console.log(
|
|
5822
|
+
console.log(chalk8.yellow(`
|
|
5671
5823
|
[!] Found ${result.impacts.length} dependency impact(s):
|
|
5672
5824
|
`));
|
|
5673
5825
|
for (const impact of result.impacts) {
|
|
5674
|
-
const severityColor = impact.rule.severity === "BLOCKER" ?
|
|
5826
|
+
const severityColor = impact.rule.severity === "BLOCKER" ? chalk8.red : impact.rule.severity === "WARNING" ? chalk8.yellow : chalk8.blue;
|
|
5675
5827
|
console.log(severityColor(`[${impact.rule.severity}] ${impact.rule.id}`));
|
|
5676
|
-
console.log(` Changing: ${
|
|
5828
|
+
console.log(` Changing: ${chalk8.cyan(impact.matchedSource)}`);
|
|
5677
5829
|
console.log(` May impact: ${impact.affectedDependents.join(", ")}`);
|
|
5678
5830
|
if (impact.rule.reason) {
|
|
5679
|
-
console.log(` Reason: ${
|
|
5831
|
+
console.log(` Reason: ${chalk8.dim(impact.rule.reason)}`);
|
|
5680
5832
|
}
|
|
5681
5833
|
console.log("");
|
|
5682
5834
|
}
|
|
5683
5835
|
if (result.hasBlockers) {
|
|
5684
|
-
console.log(
|
|
5836
|
+
console.log(chalk8.red("\u274C BLOCKER-level impacts found. Review before proceeding."));
|
|
5685
5837
|
process.exit(1);
|
|
5686
5838
|
}
|
|
5687
5839
|
process.exit(0);
|
|
@@ -5723,7 +5875,7 @@ Examples:
|
|
|
5723
5875
|
(r) => r.source === source && r.dependents.includes(dependent)
|
|
5724
5876
|
);
|
|
5725
5877
|
if (existingRule) {
|
|
5726
|
-
console.log(
|
|
5878
|
+
console.log(chalk8.yellow(`Rule already exists: ${existingRule.id}`));
|
|
5727
5879
|
return;
|
|
5728
5880
|
}
|
|
5729
5881
|
const newRule = {
|
|
@@ -5737,20 +5889,20 @@ Examples:
|
|
|
5737
5889
|
const yaml2 = generateYamlFrontmatter(existingRules);
|
|
5738
5890
|
await writeFile4(DEPENDENCIES_FILENAME, `---
|
|
5739
5891
|
${yaml2}---${markdownBody}`, "utf-8");
|
|
5740
|
-
console.log(
|
|
5741
|
-
console.log(` Source: ${
|
|
5742
|
-
console.log(` Dependent: ${
|
|
5892
|
+
console.log(chalk8.green(`\u2705 Added dependency rule: ${nextId}`));
|
|
5893
|
+
console.log(` Source: ${chalk8.cyan(source)}`);
|
|
5894
|
+
console.log(` Dependent: ${chalk8.dim(dependent)}`);
|
|
5743
5895
|
});
|
|
5744
5896
|
deps.command("graph").description("Generate Mermaid diagram of dependencies").option("--output <file>", "Write to file instead of stdout").action(async (options) => {
|
|
5745
5897
|
const parser = new DependencyParser();
|
|
5746
5898
|
if (!parser.exists()) {
|
|
5747
|
-
console.log(
|
|
5899
|
+
console.log(chalk8.yellow("No DEPENDENCIES.md found."));
|
|
5748
5900
|
return;
|
|
5749
5901
|
}
|
|
5750
5902
|
const mermaid = await parser.generateGraph();
|
|
5751
5903
|
if (options.output) {
|
|
5752
5904
|
await writeFile4(options.output, mermaid, "utf-8");
|
|
5753
|
-
console.log(
|
|
5905
|
+
console.log(chalk8.green(`\u2705 Graph written to ${options.output}`));
|
|
5754
5906
|
} else {
|
|
5755
5907
|
console.log("\n```mermaid");
|
|
5756
5908
|
console.log(mermaid);
|
|
@@ -5759,7 +5911,7 @@ ${yaml2}---${markdownBody}`, "utf-8");
|
|
|
5759
5911
|
});
|
|
5760
5912
|
deps.command("init").description("Create a starter DEPENDENCIES.md file").action(async () => {
|
|
5761
5913
|
if (existsSync8(DEPENDENCIES_FILENAME)) {
|
|
5762
|
-
console.log(
|
|
5914
|
+
console.log(chalk8.yellow("DEPENDENCIES.md already exists."));
|
|
5763
5915
|
return;
|
|
5764
5916
|
}
|
|
5765
5917
|
const template = `---
|
|
@@ -5806,8 +5958,8 @@ rules:
|
|
|
5806
5958
|
*Powered by [ArchonDev](https://archondev.io)*
|
|
5807
5959
|
`;
|
|
5808
5960
|
await writeFile4(DEPENDENCIES_FILENAME, template, "utf-8");
|
|
5809
|
-
console.log(
|
|
5810
|
-
console.log(
|
|
5961
|
+
console.log(chalk8.green("\u2705 Created DEPENDENCIES.md"));
|
|
5962
|
+
console.log(chalk8.dim("Add your first rule with: archon deps add --source <path> --dependent <path>"));
|
|
5811
5963
|
});
|
|
5812
5964
|
return deps;
|
|
5813
5965
|
}
|
|
@@ -5844,7 +5996,7 @@ function generateYamlFrontmatter(rules) {
|
|
|
5844
5996
|
}
|
|
5845
5997
|
|
|
5846
5998
|
// src/cli/session.ts
|
|
5847
|
-
import
|
|
5999
|
+
import chalk9 from "chalk";
|
|
5848
6000
|
import ora2 from "ora";
|
|
5849
6001
|
import os from "os";
|
|
5850
6002
|
import { readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
|
|
@@ -5940,13 +6092,13 @@ async function saveSession(name) {
|
|
|
5940
6092
|
spinner.fail(`Failed to save session: ${error.message}`);
|
|
5941
6093
|
return;
|
|
5942
6094
|
}
|
|
5943
|
-
spinner.succeed(
|
|
6095
|
+
spinner.succeed(chalk9.green("Session saved!"));
|
|
5944
6096
|
console.log();
|
|
5945
|
-
console.log(` ID: ${
|
|
6097
|
+
console.log(` ID: ${chalk9.cyan(session.id)}`);
|
|
5946
6098
|
console.log(` Project: ${session.project_name}`);
|
|
5947
6099
|
console.log(` Device: ${session.last_device}`);
|
|
5948
6100
|
console.log();
|
|
5949
|
-
console.log(
|
|
6101
|
+
console.log(chalk9.dim(" Resume on another device: archon session resume " + session.id));
|
|
5950
6102
|
console.log();
|
|
5951
6103
|
} catch (err2) {
|
|
5952
6104
|
spinner.fail("Error saving session");
|
|
@@ -5974,23 +6126,23 @@ async function listSessions() {
|
|
|
5974
6126
|
}
|
|
5975
6127
|
spinner.stop();
|
|
5976
6128
|
if (!sessions || sessions.length === 0) {
|
|
5977
|
-
console.log(
|
|
5978
|
-
console.log(
|
|
6129
|
+
console.log(chalk9.yellow("\nNo saved sessions found.\n"));
|
|
6130
|
+
console.log(chalk9.dim(" Save a session: archon session save [name]\n"));
|
|
5979
6131
|
return;
|
|
5980
6132
|
}
|
|
5981
6133
|
console.log();
|
|
5982
|
-
console.log(
|
|
6134
|
+
console.log(chalk9.bold("\u{1F4C2} Saved Sessions"));
|
|
5983
6135
|
console.log();
|
|
5984
6136
|
for (const session of sessions) {
|
|
5985
6137
|
const date = new Date(session.updated_at).toLocaleDateString();
|
|
5986
|
-
const atomInfo = session.current_atom_id ?
|
|
6138
|
+
const atomInfo = session.current_atom_id ? chalk9.dim(` (atom: ${session.current_atom_id})`) : "";
|
|
5987
6139
|
console.log(
|
|
5988
|
-
` ${
|
|
6140
|
+
` ${chalk9.cyan(session.id.slice(0, 8))} ${session.project_name}${atomInfo}`
|
|
5989
6141
|
);
|
|
5990
|
-
console.log(
|
|
6142
|
+
console.log(chalk9.dim(` ${date} from ${session.last_device || "unknown device"}`));
|
|
5991
6143
|
console.log();
|
|
5992
6144
|
}
|
|
5993
|
-
console.log(
|
|
6145
|
+
console.log(chalk9.dim(" Resume: archon session resume <id>\n"));
|
|
5994
6146
|
} catch (err2) {
|
|
5995
6147
|
spinner.fail("Error fetching sessions");
|
|
5996
6148
|
console.error(err2);
|
|
@@ -6034,13 +6186,13 @@ async function resumeSession(sessionId) {
|
|
|
6034
6186
|
await writeFile5(archPath, session.architecture_snapshot);
|
|
6035
6187
|
}
|
|
6036
6188
|
await supabase.from("sessions").update({ last_device: getDeviceName(), updated_at: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", session.id);
|
|
6037
|
-
spinner.succeed(
|
|
6189
|
+
spinner.succeed(chalk9.green("Session resumed!"));
|
|
6038
6190
|
console.log();
|
|
6039
6191
|
console.log(` Project: ${session.project_name}`);
|
|
6040
6192
|
console.log(` Current Atom: ${session.current_atom_id || "none"}`);
|
|
6041
6193
|
console.log(` Pending: ${session.pending_atoms.length} atoms`);
|
|
6042
6194
|
console.log();
|
|
6043
|
-
console.log(
|
|
6195
|
+
console.log(chalk9.dim(" Continue working: archon start"));
|
|
6044
6196
|
console.log();
|
|
6045
6197
|
} catch (err2) {
|
|
6046
6198
|
spinner.fail("Error resuming session");
|
|
@@ -6083,7 +6235,7 @@ async function syncSession() {
|
|
|
6083
6235
|
spinner.fail(`Failed to sync: ${error.message}`);
|
|
6084
6236
|
return;
|
|
6085
6237
|
}
|
|
6086
|
-
spinner.succeed(
|
|
6238
|
+
spinner.succeed(chalk9.green("Session synced to cloud"));
|
|
6087
6239
|
} catch (err2) {
|
|
6088
6240
|
spinner.fail("Error syncing session");
|
|
6089
6241
|
console.error(err2);
|
|
@@ -6091,7 +6243,7 @@ async function syncSession() {
|
|
|
6091
6243
|
}
|
|
6092
6244
|
|
|
6093
6245
|
// src/cli/deploy.ts
|
|
6094
|
-
import
|
|
6246
|
+
import chalk10 from "chalk";
|
|
6095
6247
|
import { existsSync as existsSync10 } from "fs";
|
|
6096
6248
|
import { join as join9 } from "path";
|
|
6097
6249
|
import { execSync as execSync3 } from "child_process";
|
|
@@ -6106,46 +6258,46 @@ function detectPlatform(cwd) {
|
|
|
6106
6258
|
}
|
|
6107
6259
|
async function deploy(options) {
|
|
6108
6260
|
const cwd = process.cwd();
|
|
6109
|
-
console.log(
|
|
6261
|
+
console.log(chalk10.blue("Running pre-deploy checks..."));
|
|
6110
6262
|
const platform = options.platform ?? detectPlatform(cwd);
|
|
6111
|
-
console.log(
|
|
6263
|
+
console.log(chalk10.dim(`Detected platform: ${platform}`));
|
|
6112
6264
|
if (options.dryRun) {
|
|
6113
|
-
console.log(
|
|
6265
|
+
console.log(chalk10.dim("Dry run mode - would deploy to:"), platform);
|
|
6114
6266
|
return;
|
|
6115
6267
|
}
|
|
6116
6268
|
switch (platform) {
|
|
6117
6269
|
case "fly":
|
|
6118
|
-
console.log(
|
|
6270
|
+
console.log(chalk10.blue("Deploying to Fly.io..."));
|
|
6119
6271
|
execSync3("fly deploy", { cwd, stdio: "inherit" });
|
|
6120
6272
|
break;
|
|
6121
6273
|
case "vercel": {
|
|
6122
|
-
console.log(
|
|
6274
|
+
console.log(chalk10.blue("Deploying to Vercel..."));
|
|
6123
6275
|
const cmd = options.preview ? "vercel" : "vercel --prod";
|
|
6124
6276
|
execSync3(cmd, { cwd, stdio: "inherit" });
|
|
6125
6277
|
break;
|
|
6126
6278
|
}
|
|
6127
6279
|
case "netlify": {
|
|
6128
|
-
console.log(
|
|
6280
|
+
console.log(chalk10.blue("Deploying to Netlify..."));
|
|
6129
6281
|
const netlifyCmd = options.preview ? "netlify deploy" : "netlify deploy --prod";
|
|
6130
6282
|
execSync3(netlifyCmd, { cwd, stdio: "inherit" });
|
|
6131
6283
|
break;
|
|
6132
6284
|
}
|
|
6133
6285
|
case "railway":
|
|
6134
|
-
console.log(
|
|
6286
|
+
console.log(chalk10.blue("Deploying to Railway..."));
|
|
6135
6287
|
execSync3("railway up", { cwd, stdio: "inherit" });
|
|
6136
6288
|
break;
|
|
6137
6289
|
case "render":
|
|
6138
|
-
console.log(
|
|
6139
|
-
console.log(
|
|
6290
|
+
console.log(chalk10.blue("Deploying to Render..."));
|
|
6291
|
+
console.log(chalk10.yellow("Render deploys via git push. Push to your connected branch."));
|
|
6140
6292
|
break;
|
|
6141
6293
|
default:
|
|
6142
|
-
console.log(
|
|
6143
|
-
console.log(
|
|
6294
|
+
console.log(chalk10.yellow("Platform not detected. Please specify with --platform"));
|
|
6295
|
+
console.log(chalk10.dim("Supported: fly, vercel, netlify, railway, render"));
|
|
6144
6296
|
}
|
|
6145
6297
|
}
|
|
6146
6298
|
|
|
6147
6299
|
// src/cli/index-cmd.ts
|
|
6148
|
-
import
|
|
6300
|
+
import chalk11 from "chalk";
|
|
6149
6301
|
|
|
6150
6302
|
// src/core/indexing/local.ts
|
|
6151
6303
|
import { existsSync as existsSync11, mkdirSync } from "fs";
|
|
@@ -6559,14 +6711,14 @@ async function getCloudIndexer(cwd) {
|
|
|
6559
6711
|
const config = await loadConfig();
|
|
6560
6712
|
const authToken = getAuthToken(config);
|
|
6561
6713
|
if (!authToken) {
|
|
6562
|
-
console.error(
|
|
6714
|
+
console.error(chalk11.red('Not authenticated. Run "archon login" first.'));
|
|
6563
6715
|
return null;
|
|
6564
6716
|
}
|
|
6565
6717
|
const openaiKey = process.env["OPENAI_API_KEY"];
|
|
6566
6718
|
if (!openaiKey) {
|
|
6567
|
-
console.error(
|
|
6568
|
-
console.log(
|
|
6569
|
-
console.log(
|
|
6719
|
+
console.error(chalk11.red("OPENAI_API_KEY environment variable not set."));
|
|
6720
|
+
console.log(chalk11.dim("Cloud indexing requires an OpenAI API key for embeddings."));
|
|
6721
|
+
console.log(chalk11.dim("Set it with: export OPENAI_API_KEY=sk-..."));
|
|
6570
6722
|
return null;
|
|
6571
6723
|
}
|
|
6572
6724
|
const projectId = basename(cwd);
|
|
@@ -6583,12 +6735,12 @@ async function getCloudIndexer(cwd) {
|
|
|
6583
6735
|
});
|
|
6584
6736
|
const { data: { user } } = await client.auth.getUser();
|
|
6585
6737
|
if (!user) {
|
|
6586
|
-
console.error(
|
|
6738
|
+
console.error(chalk11.red("Failed to get user. Try logging in again."));
|
|
6587
6739
|
return null;
|
|
6588
6740
|
}
|
|
6589
6741
|
const { data: profile } = await client.from("user_profiles").select("id").eq("auth_id", user.id).single();
|
|
6590
6742
|
if (!profile) {
|
|
6591
|
-
console.error(
|
|
6743
|
+
console.error(chalk11.red("User profile not found."));
|
|
6592
6744
|
return null;
|
|
6593
6745
|
}
|
|
6594
6746
|
indexer.setUserId(profile.id);
|
|
@@ -6597,21 +6749,21 @@ async function getCloudIndexer(cwd) {
|
|
|
6597
6749
|
async function indexInit(options) {
|
|
6598
6750
|
const cwd = process.cwd();
|
|
6599
6751
|
if (options.cloud) {
|
|
6600
|
-
console.log(
|
|
6752
|
+
console.log(chalk11.blue("Initializing cloud semantic index..."));
|
|
6601
6753
|
const indexer = await getCloudIndexer(cwd);
|
|
6602
6754
|
if (!indexer) return;
|
|
6603
6755
|
try {
|
|
6604
6756
|
const status2 = await indexer.getStatus();
|
|
6605
|
-
console.log(
|
|
6606
|
-
console.log(
|
|
6607
|
-
console.log(
|
|
6757
|
+
console.log(chalk11.green("\u2713 Cloud indexing configured"));
|
|
6758
|
+
console.log(chalk11.green(`\u2713 Project ID: ${status2.projectId}`));
|
|
6759
|
+
console.log(chalk11.dim("\nRun `archon index update --cloud` to index your codebase."));
|
|
6608
6760
|
} catch (error) {
|
|
6609
|
-
console.error(
|
|
6761
|
+
console.error(chalk11.red(`Failed to initialize cloud index: ${error instanceof Error ? error.message : String(error)}`));
|
|
6610
6762
|
process.exit(1);
|
|
6611
6763
|
}
|
|
6612
6764
|
return;
|
|
6613
6765
|
}
|
|
6614
|
-
console.log(
|
|
6766
|
+
console.log(chalk11.blue("Initializing local semantic index..."));
|
|
6615
6767
|
try {
|
|
6616
6768
|
const indexer = new LocalIndexer();
|
|
6617
6769
|
await indexer.init(cwd);
|
|
@@ -6619,18 +6771,18 @@ async function indexInit(options) {
|
|
|
6619
6771
|
if (!response.ok) {
|
|
6620
6772
|
throw new Error("Ollama not responding");
|
|
6621
6773
|
}
|
|
6622
|
-
console.log(
|
|
6623
|
-
console.log(
|
|
6624
|
-
console.log(
|
|
6774
|
+
console.log(chalk11.green("\u2713 Ollama connection verified"));
|
|
6775
|
+
console.log(chalk11.green("\u2713 Index database created at .archon/index.db"));
|
|
6776
|
+
console.log(chalk11.dim("\nRun `archon index update` to index your codebase."));
|
|
6625
6777
|
indexer.close();
|
|
6626
6778
|
} catch (error) {
|
|
6627
6779
|
if (error instanceof Error && error.message.includes("Ollama")) {
|
|
6628
|
-
console.log(
|
|
6629
|
-
console.log(
|
|
6630
|
-
console.log(
|
|
6631
|
-
console.log(
|
|
6780
|
+
console.log(chalk11.red("\n\u2717 Ollama is not running"));
|
|
6781
|
+
console.log(chalk11.dim("Start Ollama with: ollama serve"));
|
|
6782
|
+
console.log(chalk11.dim("Then pull the embedding model: ollama pull nomic-embed-text"));
|
|
6783
|
+
console.log(chalk11.dim("\nOr use cloud indexing: archon index init --cloud"));
|
|
6632
6784
|
} else {
|
|
6633
|
-
console.error(
|
|
6785
|
+
console.error(chalk11.red(`Failed to initialize index: ${error instanceof Error ? error.message : String(error)}`));
|
|
6634
6786
|
}
|
|
6635
6787
|
process.exit(1);
|
|
6636
6788
|
}
|
|
@@ -6638,7 +6790,7 @@ async function indexInit(options) {
|
|
|
6638
6790
|
async function indexUpdate(options) {
|
|
6639
6791
|
const cwd = process.cwd();
|
|
6640
6792
|
if (options?.cloud) {
|
|
6641
|
-
console.log(
|
|
6793
|
+
console.log(chalk11.blue("Updating cloud semantic index..."));
|
|
6642
6794
|
const indexer = await getCloudIndexer(cwd);
|
|
6643
6795
|
if (!indexer) return;
|
|
6644
6796
|
try {
|
|
@@ -6646,15 +6798,15 @@ async function indexUpdate(options) {
|
|
|
6646
6798
|
cwd,
|
|
6647
6799
|
ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**", "**/build/**", "**/coverage/**"]
|
|
6648
6800
|
});
|
|
6649
|
-
console.log(
|
|
6650
|
-
console.log(
|
|
6801
|
+
console.log(chalk11.dim(`Found ${files.length} files to index...`));
|
|
6802
|
+
console.log(chalk11.dim("This may take a few minutes and will use OpenAI API credits.\n"));
|
|
6651
6803
|
let totalChunks = 0;
|
|
6652
6804
|
let indexedFiles = 0;
|
|
6653
6805
|
let skippedFiles = 0;
|
|
6654
6806
|
for (let i = 0; i < files.length; i++) {
|
|
6655
6807
|
const file = files[i];
|
|
6656
6808
|
if (!file) continue;
|
|
6657
|
-
process.stdout.write(`\r${
|
|
6809
|
+
process.stdout.write(`\r${chalk11.dim(`[${i + 1}/${files.length}] ${file.slice(0, 45).padEnd(45)}`)}`);
|
|
6658
6810
|
try {
|
|
6659
6811
|
const chunks = await indexer.indexFile(cwd, file);
|
|
6660
6812
|
if (chunks > 0) {
|
|
@@ -6665,21 +6817,21 @@ async function indexUpdate(options) {
|
|
|
6665
6817
|
}
|
|
6666
6818
|
} catch (error) {
|
|
6667
6819
|
console.log(`
|
|
6668
|
-
${
|
|
6820
|
+
${chalk11.yellow(`[!] Skipped ${file}: ${error instanceof Error ? error.message : "Unknown error"}`)}`);
|
|
6669
6821
|
}
|
|
6670
6822
|
}
|
|
6671
6823
|
console.log("\r" + " ".repeat(70));
|
|
6672
|
-
console.log(
|
|
6824
|
+
console.log(chalk11.green(`\u2713 Indexed ${indexedFiles} files (${totalChunks} chunks)`));
|
|
6673
6825
|
if (skippedFiles > 0) {
|
|
6674
|
-
console.log(
|
|
6826
|
+
console.log(chalk11.dim(` Skipped ${skippedFiles} unchanged files`));
|
|
6675
6827
|
}
|
|
6676
6828
|
} catch (error) {
|
|
6677
|
-
console.error(
|
|
6829
|
+
console.error(chalk11.red(`Failed to update cloud index: ${error instanceof Error ? error.message : String(error)}`));
|
|
6678
6830
|
process.exit(1);
|
|
6679
6831
|
}
|
|
6680
6832
|
return;
|
|
6681
6833
|
}
|
|
6682
|
-
console.log(
|
|
6834
|
+
console.log(chalk11.blue("Updating local semantic index..."));
|
|
6683
6835
|
try {
|
|
6684
6836
|
const indexer = new LocalIndexer();
|
|
6685
6837
|
await indexer.init(cwd);
|
|
@@ -6687,12 +6839,12 @@ ${chalk10.yellow(`[!] Skipped ${file}: ${error instanceof Error ? error.message
|
|
|
6687
6839
|
cwd,
|
|
6688
6840
|
ignore: ["**/node_modules/**", "**/dist/**", "**/.git/**", "**/build/**", "**/coverage/**"]
|
|
6689
6841
|
});
|
|
6690
|
-
console.log(
|
|
6842
|
+
console.log(chalk11.dim(`Found ${files.length} files to index...`));
|
|
6691
6843
|
let totalChunks = 0;
|
|
6692
6844
|
let indexedFiles = 0;
|
|
6693
6845
|
for (const file of files) {
|
|
6694
6846
|
if (!file) continue;
|
|
6695
|
-
process.stdout.write(`\r${
|
|
6847
|
+
process.stdout.write(`\r${chalk11.dim(`Indexing: ${file.slice(0, 50).padEnd(50)}`)}`);
|
|
6696
6848
|
const chunks = await indexer.indexFile(cwd, file);
|
|
6697
6849
|
if (chunks > 0) {
|
|
6698
6850
|
totalChunks += chunks;
|
|
@@ -6700,10 +6852,10 @@ ${chalk10.yellow(`[!] Skipped ${file}: ${error instanceof Error ? error.message
|
|
|
6700
6852
|
}
|
|
6701
6853
|
}
|
|
6702
6854
|
console.log("\r" + " ".repeat(60));
|
|
6703
|
-
console.log(
|
|
6855
|
+
console.log(chalk11.green(`\u2713 Indexed ${indexedFiles} files (${totalChunks} chunks)`));
|
|
6704
6856
|
indexer.close();
|
|
6705
6857
|
} catch (error) {
|
|
6706
|
-
console.error(
|
|
6858
|
+
console.error(chalk11.red(`Failed to update index: ${error instanceof Error ? error.message : String(error)}`));
|
|
6707
6859
|
process.exit(1);
|
|
6708
6860
|
}
|
|
6709
6861
|
}
|
|
@@ -6713,25 +6865,25 @@ async function indexSearch(query, options) {
|
|
|
6713
6865
|
const indexer = await getCloudIndexer(cwd);
|
|
6714
6866
|
if (!indexer) return;
|
|
6715
6867
|
try {
|
|
6716
|
-
console.log(
|
|
6868
|
+
console.log(chalk11.dim("Searching cloud index..."));
|
|
6717
6869
|
const results = await indexer.search(query, 10);
|
|
6718
6870
|
if (results.length === 0) {
|
|
6719
|
-
console.log(
|
|
6720
|
-
console.log(
|
|
6871
|
+
console.log(chalk11.yellow("\nNo results found."));
|
|
6872
|
+
console.log(chalk11.dim("Try running `archon index update --cloud` first."));
|
|
6721
6873
|
} else {
|
|
6722
|
-
console.log(
|
|
6874
|
+
console.log(chalk11.blue(`
|
|
6723
6875
|
Top ${results.length} results for: "${query}"
|
|
6724
6876
|
`));
|
|
6725
6877
|
for (const result of results) {
|
|
6726
6878
|
const score = (result.score * 100).toFixed(1);
|
|
6727
|
-
console.log(
|
|
6879
|
+
console.log(chalk11.green(`[${score}%] ${result.file}`));
|
|
6728
6880
|
const preview = result.text.slice(0, 200).replace(/\n/g, " ").trim();
|
|
6729
|
-
console.log(
|
|
6881
|
+
console.log(chalk11.dim(` ${preview}${result.text.length > 200 ? "..." : ""}`));
|
|
6730
6882
|
console.log();
|
|
6731
6883
|
}
|
|
6732
6884
|
}
|
|
6733
6885
|
} catch (error) {
|
|
6734
|
-
console.error(
|
|
6886
|
+
console.error(chalk11.red(`Cloud search failed: ${error instanceof Error ? error.message : String(error)}`));
|
|
6735
6887
|
process.exit(1);
|
|
6736
6888
|
}
|
|
6737
6889
|
return;
|
|
@@ -6741,23 +6893,23 @@ Top ${results.length} results for: "${query}"
|
|
|
6741
6893
|
await indexer.init(cwd);
|
|
6742
6894
|
const results = await indexer.search(query, 10);
|
|
6743
6895
|
if (results.length === 0) {
|
|
6744
|
-
console.log(
|
|
6745
|
-
console.log(
|
|
6896
|
+
console.log(chalk11.yellow("No results found."));
|
|
6897
|
+
console.log(chalk11.dim("Try running `archon index update` first."));
|
|
6746
6898
|
} else {
|
|
6747
|
-
console.log(
|
|
6899
|
+
console.log(chalk11.blue(`
|
|
6748
6900
|
Top ${results.length} results for: "${query}"
|
|
6749
6901
|
`));
|
|
6750
6902
|
for (const result of results) {
|
|
6751
6903
|
const score = (result.score * 100).toFixed(1);
|
|
6752
|
-
console.log(
|
|
6904
|
+
console.log(chalk11.green(`[${score}%] ${result.file}`));
|
|
6753
6905
|
const preview = result.text.slice(0, 200).replace(/\n/g, " ").trim();
|
|
6754
|
-
console.log(
|
|
6906
|
+
console.log(chalk11.dim(` ${preview}${result.text.length > 200 ? "..." : ""}`));
|
|
6755
6907
|
console.log();
|
|
6756
6908
|
}
|
|
6757
6909
|
}
|
|
6758
6910
|
indexer.close();
|
|
6759
6911
|
} catch (error) {
|
|
6760
|
-
console.error(
|
|
6912
|
+
console.error(chalk11.red(`Search failed: ${error instanceof Error ? error.message : String(error)}`));
|
|
6761
6913
|
process.exit(1);
|
|
6762
6914
|
}
|
|
6763
6915
|
}
|
|
@@ -6768,17 +6920,17 @@ async function indexStatus(options) {
|
|
|
6768
6920
|
if (!indexer) return;
|
|
6769
6921
|
try {
|
|
6770
6922
|
const status2 = await indexer.getStatus();
|
|
6771
|
-
console.log(
|
|
6772
|
-
console.log(` Project ID: ${
|
|
6773
|
-
console.log(` Files indexed: ${
|
|
6774
|
-
console.log(` Total chunks: ${
|
|
6775
|
-
console.log(` Last updated: ${status2.lastUpdated ?
|
|
6923
|
+
console.log(chalk11.blue("\nCloud Semantic Index Status\n"));
|
|
6924
|
+
console.log(` Project ID: ${chalk11.green(status2.projectId)}`);
|
|
6925
|
+
console.log(` Files indexed: ${chalk11.green(status2.fileCount)}`);
|
|
6926
|
+
console.log(` Total chunks: ${chalk11.green(status2.chunkCount)}`);
|
|
6927
|
+
console.log(` Last updated: ${status2.lastUpdated ? chalk11.dim(status2.lastUpdated) : chalk11.yellow("Never")}`);
|
|
6776
6928
|
if (status2.jobStatus) {
|
|
6777
|
-
console.log(` Job status: ${
|
|
6929
|
+
console.log(` Job status: ${chalk11.dim(status2.jobStatus)}`);
|
|
6778
6930
|
}
|
|
6779
|
-
console.log(` Storage: ${
|
|
6931
|
+
console.log(` Storage: ${chalk11.dim("Supabase pgvector")}`);
|
|
6780
6932
|
} catch (error) {
|
|
6781
|
-
console.error(
|
|
6933
|
+
console.error(chalk11.red(`Failed to get cloud status: ${error instanceof Error ? error.message : String(error)}`));
|
|
6782
6934
|
process.exit(1);
|
|
6783
6935
|
}
|
|
6784
6936
|
return;
|
|
@@ -6787,14 +6939,14 @@ async function indexStatus(options) {
|
|
|
6787
6939
|
const indexer = new LocalIndexer();
|
|
6788
6940
|
await indexer.init(cwd);
|
|
6789
6941
|
const status2 = await indexer.getStatus();
|
|
6790
|
-
console.log(
|
|
6791
|
-
console.log(` Files indexed: ${
|
|
6792
|
-
console.log(` Total chunks: ${
|
|
6793
|
-
console.log(` Last updated: ${status2.lastUpdated ?
|
|
6794
|
-
console.log(` Database: ${
|
|
6942
|
+
console.log(chalk11.blue("\nLocal Semantic Index Status\n"));
|
|
6943
|
+
console.log(` Files indexed: ${chalk11.green(status2.fileCount)}`);
|
|
6944
|
+
console.log(` Total chunks: ${chalk11.green(status2.chunkCount)}`);
|
|
6945
|
+
console.log(` Last updated: ${status2.lastUpdated ? chalk11.dim(status2.lastUpdated) : chalk11.yellow("Never")}`);
|
|
6946
|
+
console.log(` Database: ${chalk11.dim(join12(cwd, ".archon/index.db"))}`);
|
|
6795
6947
|
indexer.close();
|
|
6796
6948
|
} catch (error) {
|
|
6797
|
-
console.error(
|
|
6949
|
+
console.error(chalk11.red(`Failed to get status: ${error instanceof Error ? error.message : String(error)}`));
|
|
6798
6950
|
process.exit(1);
|
|
6799
6951
|
}
|
|
6800
6952
|
}
|
|
@@ -6804,30 +6956,30 @@ async function indexClear(options) {
|
|
|
6804
6956
|
const indexer = await getCloudIndexer(cwd);
|
|
6805
6957
|
if (!indexer) return;
|
|
6806
6958
|
try {
|
|
6807
|
-
console.log(
|
|
6959
|
+
console.log(chalk11.yellow("Clearing cloud index..."));
|
|
6808
6960
|
await indexer.clearProject();
|
|
6809
|
-
console.log(
|
|
6961
|
+
console.log(chalk11.green("\u2713 Cloud index cleared"));
|
|
6810
6962
|
} catch (error) {
|
|
6811
|
-
console.error(
|
|
6963
|
+
console.error(chalk11.red(`Failed to clear cloud index: ${error instanceof Error ? error.message : String(error)}`));
|
|
6812
6964
|
process.exit(1);
|
|
6813
6965
|
}
|
|
6814
6966
|
return;
|
|
6815
6967
|
}
|
|
6816
|
-
console.log(
|
|
6968
|
+
console.log(chalk11.yellow("To clear local index, delete .archon/index.db"));
|
|
6817
6969
|
}
|
|
6818
6970
|
|
|
6819
6971
|
// src/cli/github.ts
|
|
6820
|
-
import
|
|
6972
|
+
import chalk12 from "chalk";
|
|
6821
6973
|
import open2 from "open";
|
|
6822
6974
|
var API_URL2 = process.env["ARCHONDEV_API_URL"] ?? "https://archondev-api.fly.dev";
|
|
6823
6975
|
async function githubConnect() {
|
|
6824
6976
|
const config = await loadConfig();
|
|
6825
6977
|
const authToken = getAuthToken(config);
|
|
6826
6978
|
if (!authToken) {
|
|
6827
|
-
console.error(
|
|
6979
|
+
console.error(chalk12.red('Not authenticated. Run "archon login" first.'));
|
|
6828
6980
|
process.exit(1);
|
|
6829
6981
|
}
|
|
6830
|
-
console.log(
|
|
6982
|
+
console.log(chalk12.dim("Starting GitHub connection..."));
|
|
6831
6983
|
try {
|
|
6832
6984
|
const response = await fetch(`${API_URL2}/api/github/connect`, {
|
|
6833
6985
|
headers: {
|
|
@@ -6836,18 +6988,18 @@ async function githubConnect() {
|
|
|
6836
6988
|
});
|
|
6837
6989
|
if (!response.ok) {
|
|
6838
6990
|
const error = await response.json();
|
|
6839
|
-
console.error(
|
|
6991
|
+
console.error(chalk12.red(error.error ?? "Failed to start GitHub connection"));
|
|
6840
6992
|
process.exit(1);
|
|
6841
6993
|
}
|
|
6842
6994
|
const data = await response.json();
|
|
6843
|
-
console.log(
|
|
6844
|
-
console.log(
|
|
6845
|
-
console.log(
|
|
6995
|
+
console.log(chalk12.dim("\nOpening browser for GitHub authorization..."));
|
|
6996
|
+
console.log(chalk12.dim("If browser does not open, visit:"));
|
|
6997
|
+
console.log(chalk12.blue(data.url));
|
|
6846
6998
|
await open2(data.url);
|
|
6847
|
-
console.log(
|
|
6848
|
-
console.log(
|
|
6999
|
+
console.log(chalk12.dim("\nComplete the authorization in your browser."));
|
|
7000
|
+
console.log(chalk12.dim('Then run "archon github status" to verify connection.'));
|
|
6849
7001
|
} catch (error) {
|
|
6850
|
-
console.error(
|
|
7002
|
+
console.error(chalk12.red(error instanceof Error ? error.message : "Failed to connect"));
|
|
6851
7003
|
process.exit(1);
|
|
6852
7004
|
}
|
|
6853
7005
|
}
|
|
@@ -6855,7 +7007,7 @@ async function githubStatus() {
|
|
|
6855
7007
|
const config = await loadConfig();
|
|
6856
7008
|
const authToken = getAuthToken(config);
|
|
6857
7009
|
if (!authToken) {
|
|
6858
|
-
console.error(
|
|
7010
|
+
console.error(chalk12.red('Not authenticated. Run "archon login" first.'));
|
|
6859
7011
|
process.exit(1);
|
|
6860
7012
|
}
|
|
6861
7013
|
try {
|
|
@@ -6866,20 +7018,20 @@ async function githubStatus() {
|
|
|
6866
7018
|
});
|
|
6867
7019
|
if (!response.ok) {
|
|
6868
7020
|
const error = await response.json();
|
|
6869
|
-
console.error(
|
|
7021
|
+
console.error(chalk12.red(error.error ?? "Failed to get GitHub status"));
|
|
6870
7022
|
process.exit(1);
|
|
6871
7023
|
}
|
|
6872
7024
|
const data = await response.json();
|
|
6873
7025
|
if (data.connected) {
|
|
6874
|
-
console.log(
|
|
6875
|
-
console.log(
|
|
6876
|
-
console.log(
|
|
7026
|
+
console.log(chalk12.green("\u2713 GitHub connected"));
|
|
7027
|
+
console.log(chalk12.dim(` Username: ${data.username}`));
|
|
7028
|
+
console.log(chalk12.dim(` Connected: ${data.connectedAt ? new Date(data.connectedAt).toLocaleDateString() : "Unknown"}`));
|
|
6877
7029
|
} else {
|
|
6878
|
-
console.log(
|
|
6879
|
-
console.log(
|
|
7030
|
+
console.log(chalk12.yellow("GitHub not connected"));
|
|
7031
|
+
console.log(chalk12.dim('Run "archon github connect" to connect your GitHub account.'));
|
|
6880
7032
|
}
|
|
6881
7033
|
} catch (error) {
|
|
6882
|
-
console.error(
|
|
7034
|
+
console.error(chalk12.red(error instanceof Error ? error.message : "Failed to get status"));
|
|
6883
7035
|
process.exit(1);
|
|
6884
7036
|
}
|
|
6885
7037
|
}
|
|
@@ -6887,7 +7039,7 @@ async function githubDisconnect() {
|
|
|
6887
7039
|
const config = await loadConfig();
|
|
6888
7040
|
const authToken = getAuthToken(config);
|
|
6889
7041
|
if (!authToken) {
|
|
6890
|
-
console.error(
|
|
7042
|
+
console.error(chalk12.red('Not authenticated. Run "archon login" first.'));
|
|
6891
7043
|
process.exit(1);
|
|
6892
7044
|
}
|
|
6893
7045
|
try {
|
|
@@ -6899,18 +7051,18 @@ async function githubDisconnect() {
|
|
|
6899
7051
|
});
|
|
6900
7052
|
if (!response.ok) {
|
|
6901
7053
|
const error = await response.json();
|
|
6902
|
-
console.error(
|
|
7054
|
+
console.error(chalk12.red(error.error ?? "Failed to disconnect GitHub"));
|
|
6903
7055
|
process.exit(1);
|
|
6904
7056
|
}
|
|
6905
|
-
console.log(
|
|
7057
|
+
console.log(chalk12.green("\u2713 GitHub disconnected"));
|
|
6906
7058
|
} catch (error) {
|
|
6907
|
-
console.error(
|
|
7059
|
+
console.error(chalk12.red(error instanceof Error ? error.message : "Failed to disconnect"));
|
|
6908
7060
|
process.exit(1);
|
|
6909
7061
|
}
|
|
6910
7062
|
}
|
|
6911
7063
|
|
|
6912
7064
|
// src/cli/interview.ts
|
|
6913
|
-
import
|
|
7065
|
+
import chalk13 from "chalk";
|
|
6914
7066
|
import readline3 from "readline";
|
|
6915
7067
|
import ora3 from "ora";
|
|
6916
7068
|
import { existsSync as existsSync13, readFileSync as readFileSync5, writeFileSync, mkdirSync as mkdirSync2 } from "fs";
|
|
@@ -6928,23 +7080,23 @@ async function interview(options = {}) {
|
|
|
6928
7080
|
if (!existsSync13(archonDir)) {
|
|
6929
7081
|
mkdirSync2(archonDir, { recursive: true });
|
|
6930
7082
|
}
|
|
6931
|
-
console.log(
|
|
6932
|
-
console.log(
|
|
7083
|
+
console.log(chalk13.bold("\n\u{1F3AF} ArchonDev Project Interview"));
|
|
7084
|
+
console.log(chalk13.dim("Let's define what you're building.\n"));
|
|
6933
7085
|
const constitutionPath = getConstitutionPath(cwd);
|
|
6934
7086
|
const draftPath = getDraftPath(cwd);
|
|
6935
7087
|
if (existsSync13(constitutionPath)) {
|
|
6936
7088
|
const existing = deserializeConstitution(readFileSync5(constitutionPath, "utf-8"));
|
|
6937
7089
|
if (existing.state === "FROZEN") {
|
|
6938
|
-
console.log(
|
|
6939
|
-
console.log(
|
|
6940
|
-
console.log(
|
|
7090
|
+
console.log(chalk13.yellow("[!] A frozen Constitution already exists."));
|
|
7091
|
+
console.log(chalk13.dim(` Project: ${existing.branding.projectName}`));
|
|
7092
|
+
console.log(chalk13.dim(` Frozen: ${existing.frozenAt?.toISOString()}`));
|
|
6941
7093
|
console.log();
|
|
6942
7094
|
const action = await prompt2("Start a new interview (overwrite) or view existing? (new/view)");
|
|
6943
7095
|
if (action.toLowerCase() === "view") {
|
|
6944
7096
|
console.log("\n" + summarizeConstitution(existing));
|
|
6945
7097
|
return;
|
|
6946
7098
|
} else if (action.toLowerCase() !== "new") {
|
|
6947
|
-
console.log(
|
|
7099
|
+
console.log(chalk13.dim("Cancelled."));
|
|
6948
7100
|
return;
|
|
6949
7101
|
}
|
|
6950
7102
|
}
|
|
@@ -6953,8 +7105,8 @@ async function interview(options = {}) {
|
|
|
6953
7105
|
let startPhase = 1;
|
|
6954
7106
|
if (existsSync13(draftPath) && options.resume !== false) {
|
|
6955
7107
|
const draft = deserializeConstitution(readFileSync5(draftPath, "utf-8"));
|
|
6956
|
-
console.log(
|
|
6957
|
-
console.log(
|
|
7108
|
+
console.log(chalk13.blue("[i] Found draft from previous session."));
|
|
7109
|
+
console.log(chalk13.dim(` Project: ${draft.branding.projectName || "(unnamed)"}`));
|
|
6958
7110
|
console.log();
|
|
6959
7111
|
const resumeChoice = await prompt2("Resume draft or start fresh? (resume/fresh)");
|
|
6960
7112
|
if (resumeChoice.toLowerCase() === "resume") {
|
|
@@ -6966,7 +7118,7 @@ async function interview(options = {}) {
|
|
|
6966
7118
|
break;
|
|
6967
7119
|
}
|
|
6968
7120
|
}
|
|
6969
|
-
console.log(
|
|
7121
|
+
console.log(chalk13.green(`
|
|
6970
7122
|
\u2713 Resuming at Phase ${startPhase}: ${INTERVIEW_PHASES[startPhase]?.name}
|
|
6971
7123
|
`));
|
|
6972
7124
|
} else {
|
|
@@ -6977,19 +7129,19 @@ async function interview(options = {}) {
|
|
|
6977
7129
|
}
|
|
6978
7130
|
if (options.phase && options.phase >= 1 && options.phase <= 5) {
|
|
6979
7131
|
startPhase = options.phase;
|
|
6980
|
-
console.log(
|
|
7132
|
+
console.log(chalk13.dim(`Starting at Phase ${startPhase}...
|
|
6981
7133
|
`));
|
|
6982
7134
|
}
|
|
6983
|
-
console.log(
|
|
6984
|
-
console.log(
|
|
6985
|
-
console.log(
|
|
7135
|
+
console.log(chalk13.dim("\u2500".repeat(40)));
|
|
7136
|
+
console.log(chalk13.dim(formatProgressBar(startPhase)));
|
|
7137
|
+
console.log(chalk13.dim("\u2500".repeat(40)));
|
|
6986
7138
|
console.log();
|
|
6987
7139
|
let currentPhase = startPhase;
|
|
6988
7140
|
while (currentPhase <= 5) {
|
|
6989
7141
|
const result = await runPhase(currentPhase, constitution, cwd);
|
|
6990
7142
|
if (result.action === "exit") {
|
|
6991
7143
|
saveDraft(cwd, constitution);
|
|
6992
|
-
console.log(
|
|
7144
|
+
console.log(chalk13.dim("\nDraft saved. Run `archon interview` to resume.\n"));
|
|
6993
7145
|
return;
|
|
6994
7146
|
}
|
|
6995
7147
|
if (result.action === "back" && currentPhase > 1) {
|
|
@@ -7004,9 +7156,9 @@ async function interview(options = {}) {
|
|
|
7004
7156
|
if (next) {
|
|
7005
7157
|
currentPhase = next;
|
|
7006
7158
|
console.log();
|
|
7007
|
-
console.log(
|
|
7008
|
-
console.log(
|
|
7009
|
-
console.log(
|
|
7159
|
+
console.log(chalk13.dim("\u2500".repeat(40)));
|
|
7160
|
+
console.log(chalk13.dim(formatProgressBar(currentPhase)));
|
|
7161
|
+
console.log(chalk13.dim("\u2500".repeat(40)));
|
|
7010
7162
|
console.log();
|
|
7011
7163
|
} else {
|
|
7012
7164
|
break;
|
|
@@ -7014,9 +7166,9 @@ async function interview(options = {}) {
|
|
|
7014
7166
|
}
|
|
7015
7167
|
const validationResult = validateConstitution(constitution);
|
|
7016
7168
|
if (!validationResult.valid) {
|
|
7017
|
-
console.log(
|
|
7169
|
+
console.log(chalk13.red("\n[!] Constitution has validation errors:\n"));
|
|
7018
7170
|
for (const error of validationResult.errors) {
|
|
7019
|
-
console.log(
|
|
7171
|
+
console.log(chalk13.red(` \u2022 ${error}`));
|
|
7020
7172
|
}
|
|
7021
7173
|
console.log();
|
|
7022
7174
|
const fix = await promptYesNo3("Would you like to go back and fix these?", true);
|
|
@@ -7026,9 +7178,9 @@ async function interview(options = {}) {
|
|
|
7026
7178
|
}
|
|
7027
7179
|
}
|
|
7028
7180
|
if (validationResult.warnings.length > 0) {
|
|
7029
|
-
console.log(
|
|
7181
|
+
console.log(chalk13.yellow("\n[!] Warnings:\n"));
|
|
7030
7182
|
for (const warning of validationResult.warnings) {
|
|
7031
|
-
console.log(
|
|
7183
|
+
console.log(chalk13.yellow(` \u2022 ${warning}`));
|
|
7032
7184
|
}
|
|
7033
7185
|
console.log();
|
|
7034
7186
|
}
|
|
@@ -7038,21 +7190,21 @@ async function interview(options = {}) {
|
|
|
7038
7190
|
constitution.costs = estimateCosts(constitution, config.tier || "FREE");
|
|
7039
7191
|
const challengeResult = analyzeForChallenges(constitution);
|
|
7040
7192
|
if (challengeResult.shouldChallenge) {
|
|
7041
|
-
console.log(
|
|
7042
|
-
console.log(
|
|
7193
|
+
console.log(chalk13.bold("\n\u{1F3AF} Challenge Mode\n"));
|
|
7194
|
+
console.log(chalk13.dim("Let me share some observations about your project scope...\n"));
|
|
7043
7195
|
for (const challenge of challengeResult.challenges) {
|
|
7044
7196
|
const prompt3 = generateChallengePrompt(challenge);
|
|
7045
|
-
const icon = challenge.severity === "critical" ?
|
|
7046
|
-
console.log(`${icon} ${
|
|
7047
|
-
console.log(
|
|
7197
|
+
const icon = challenge.severity === "critical" ? chalk13.red("\u25CF") : chalk13.yellow("\u25CF");
|
|
7198
|
+
console.log(`${icon} ${chalk13.bold(challenge.title)}`);
|
|
7199
|
+
console.log(chalk13.dim(` ${prompt3}`));
|
|
7048
7200
|
console.log();
|
|
7049
7201
|
}
|
|
7050
|
-
console.log(
|
|
7202
|
+
console.log(chalk13.dim("\u2500".repeat(40)));
|
|
7051
7203
|
console.log(summarizeChallenges(challengeResult));
|
|
7052
|
-
console.log(
|
|
7204
|
+
console.log(chalk13.dim("\u2500".repeat(40)));
|
|
7053
7205
|
console.log();
|
|
7054
7206
|
if (challengeResult.featuresToDefer.length > 0) {
|
|
7055
|
-
console.log(
|
|
7207
|
+
console.log(chalk13.bold("Suggested Features to Defer to Post-MVP:\n"));
|
|
7056
7208
|
for (const feature of challengeResult.featuresToDefer) {
|
|
7057
7209
|
console.log(` \u2022 ${feature.name}`);
|
|
7058
7210
|
}
|
|
@@ -7067,39 +7219,39 @@ async function interview(options = {}) {
|
|
|
7067
7219
|
constitution.complexity = calculateComplexity(constitution);
|
|
7068
7220
|
constitution.estimatedBuildHours = estimateBuildHours(constitution.complexity);
|
|
7069
7221
|
constitution.costs = estimateCosts(constitution, config.tier || "FREE");
|
|
7070
|
-
console.log(
|
|
7071
|
-
console.log(
|
|
7072
|
-
console.log(
|
|
7222
|
+
console.log(chalk13.green("\n\u2713 Features deferred. Updated estimates:"));
|
|
7223
|
+
console.log(chalk13.dim(` Complexity: ${constitution.complexity.tier}`));
|
|
7224
|
+
console.log(chalk13.dim(` Build time: ~${Math.round(constitution.estimatedBuildHours)} hours`));
|
|
7073
7225
|
console.log();
|
|
7074
7226
|
saveDraft(cwd, constitution);
|
|
7075
7227
|
}
|
|
7076
7228
|
}
|
|
7077
7229
|
const criticalCount = challengeResult.challenges.filter((c) => c.severity === "critical").length;
|
|
7078
7230
|
if (criticalCount > 0) {
|
|
7079
|
-
console.log(
|
|
7231
|
+
console.log(chalk13.red(`
|
|
7080
7232
|
\u26A0\uFE0F ${criticalCount} critical issue(s) detected.`));
|
|
7081
7233
|
const proceed = await promptYesNo3("Proceed anyway?", false);
|
|
7082
7234
|
if (!proceed) {
|
|
7083
7235
|
saveDraft(cwd, constitution);
|
|
7084
|
-
console.log(
|
|
7236
|
+
console.log(chalk13.dim("\nDraft saved. Address the issues and run `archon interview` again.\n"));
|
|
7085
7237
|
return;
|
|
7086
7238
|
}
|
|
7087
7239
|
}
|
|
7088
7240
|
} else {
|
|
7089
|
-
console.log(
|
|
7241
|
+
console.log(chalk13.green("\n\u2713 Scope looks reasonable! No major concerns detected.\n"));
|
|
7090
7242
|
}
|
|
7091
|
-
console.log(
|
|
7243
|
+
console.log(chalk13.bold("\n\u{1F4CB} Constitution Summary\n"));
|
|
7092
7244
|
console.log(summarizeConstitution(constitution));
|
|
7093
7245
|
console.log();
|
|
7094
7246
|
if (options.dryRun) {
|
|
7095
|
-
console.log(
|
|
7247
|
+
console.log(chalk13.dim("(Dry run mode - not freezing Constitution)"));
|
|
7096
7248
|
saveDraft(cwd, constitution);
|
|
7097
7249
|
return;
|
|
7098
7250
|
}
|
|
7099
7251
|
const confirmFreeze = await promptYesNo3("Freeze this Constitution and start building?", true);
|
|
7100
7252
|
if (!confirmFreeze) {
|
|
7101
7253
|
saveDraft(cwd, constitution);
|
|
7102
|
-
console.log(
|
|
7254
|
+
console.log(chalk13.dim("\nDraft saved. Run `archon interview` to continue.\n"));
|
|
7103
7255
|
return;
|
|
7104
7256
|
}
|
|
7105
7257
|
const spinner = ora3("Freezing Constitution...").start();
|
|
@@ -7110,15 +7262,15 @@ async function interview(options = {}) {
|
|
|
7110
7262
|
const { unlinkSync } = await import("fs");
|
|
7111
7263
|
unlinkSync(draftPath);
|
|
7112
7264
|
}
|
|
7113
|
-
spinner.succeed(
|
|
7265
|
+
spinner.succeed(chalk13.green("Constitution frozen!"));
|
|
7114
7266
|
console.log();
|
|
7115
|
-
console.log(
|
|
7116
|
-
console.log(
|
|
7267
|
+
console.log(chalk13.dim(`Hash: ${frozen.hash?.substring(0, 32)}...`));
|
|
7268
|
+
console.log(chalk13.dim(`Saved: ${constitutionPath}`));
|
|
7117
7269
|
console.log();
|
|
7118
|
-
console.log(
|
|
7119
|
-
console.log(` ${
|
|
7120
|
-
console.log(` ${
|
|
7121
|
-
console.log(` ${
|
|
7270
|
+
console.log(chalk13.bold("Next Steps:\n"));
|
|
7271
|
+
console.log(` ${chalk13.cyan("1.")} Run ${chalk13.bold("archon generate")} to create atoms from this Constitution`);
|
|
7272
|
+
console.log(` ${chalk13.cyan("2.")} Run ${chalk13.bold("archon list")} to see generated atoms`);
|
|
7273
|
+
console.log(` ${chalk13.cyan("3.")} Run ${chalk13.bold("archon execute <atom-id>")} to start building`);
|
|
7122
7274
|
console.log();
|
|
7123
7275
|
} catch (err2) {
|
|
7124
7276
|
spinner.fail("Failed to freeze Constitution");
|
|
@@ -7127,18 +7279,18 @@ async function interview(options = {}) {
|
|
|
7127
7279
|
}
|
|
7128
7280
|
async function runPhase(phase, constitution, cwd) {
|
|
7129
7281
|
const phaseInfo = INTERVIEW_PHASES[phase];
|
|
7130
|
-
console.log(
|
|
7131
|
-
console.log(
|
|
7282
|
+
console.log(chalk13.bold(`Phase ${phase}: ${phaseInfo.name}`));
|
|
7283
|
+
console.log(chalk13.dim(phaseInfo.description));
|
|
7132
7284
|
console.log();
|
|
7133
7285
|
const skippable = getSkippableQuestions(phase, constitution);
|
|
7134
7286
|
let updatedConstitution = { ...constitution };
|
|
7135
7287
|
for (const question of phaseInfo.questions) {
|
|
7136
7288
|
if (skippable.includes(question.id)) {
|
|
7137
|
-
console.log(
|
|
7289
|
+
console.log(chalk13.dim(`[\u2713] ${question.prompt.split("?")[0]}... (already answered)`));
|
|
7138
7290
|
continue;
|
|
7139
7291
|
}
|
|
7140
7292
|
if (phase === 5 && question.id === "review_summary") {
|
|
7141
|
-
console.log(
|
|
7293
|
+
console.log(chalk13.bold("\n\u{1F4CB} Current State:\n"));
|
|
7142
7294
|
console.log(summarizeConstitution(updatedConstitution));
|
|
7143
7295
|
console.log();
|
|
7144
7296
|
}
|
|
@@ -7155,14 +7307,14 @@ async function runPhase(phase, constitution, cwd) {
|
|
|
7155
7307
|
if (question.validator) {
|
|
7156
7308
|
const validation = question.validator(answer);
|
|
7157
7309
|
if (!validation.valid) {
|
|
7158
|
-
console.log(
|
|
7310
|
+
console.log(chalk13.red(` ${validation.error}`));
|
|
7159
7311
|
continue;
|
|
7160
7312
|
}
|
|
7161
7313
|
}
|
|
7162
7314
|
const extracted = question.extractor(answer, updatedConstitution);
|
|
7163
7315
|
updatedConstitution = { ...updatedConstitution, ...extracted };
|
|
7164
7316
|
if (question.followUp && answer.length > 10) {
|
|
7165
|
-
console.log(
|
|
7317
|
+
console.log(chalk13.dim(` ${question.followUp}`));
|
|
7166
7318
|
}
|
|
7167
7319
|
}
|
|
7168
7320
|
return { action: "next", constitution: updatedConstitution };
|
|
@@ -7172,7 +7324,7 @@ function saveDraft(cwd, constitution) {
|
|
|
7172
7324
|
writeFileSync(draftPath, serializeConstitution(constitution));
|
|
7173
7325
|
}
|
|
7174
7326
|
async function promptQuestion(question) {
|
|
7175
|
-
const prefix = question.required ?
|
|
7327
|
+
const prefix = question.required ? chalk13.red("*") : " ";
|
|
7176
7328
|
return prompt2(`${prefix} ${question.prompt}`);
|
|
7177
7329
|
}
|
|
7178
7330
|
function prompt2(question) {
|
|
@@ -7181,7 +7333,7 @@ function prompt2(question) {
|
|
|
7181
7333
|
input: process.stdin,
|
|
7182
7334
|
output: process.stdout
|
|
7183
7335
|
});
|
|
7184
|
-
rl.question(`${
|
|
7336
|
+
rl.question(`${chalk13.cyan("?")} ${question}
|
|
7185
7337
|
> `, (answer) => {
|
|
7186
7338
|
rl.close();
|
|
7187
7339
|
resolve(answer.trim());
|
|
@@ -7195,7 +7347,7 @@ function promptYesNo3(question, defaultValue) {
|
|
|
7195
7347
|
output: process.stdout
|
|
7196
7348
|
});
|
|
7197
7349
|
const hint = defaultValue ? "(Y/n)" : "(y/N)";
|
|
7198
|
-
rl.question(`${
|
|
7350
|
+
rl.question(`${chalk13.cyan("?")} ${question} ${hint}: `, (answer) => {
|
|
7199
7351
|
rl.close();
|
|
7200
7352
|
if (answer.trim() === "") {
|
|
7201
7353
|
resolve(defaultValue);
|
|
@@ -7214,10 +7366,10 @@ async function showConstitution() {
|
|
|
7214
7366
|
console.log(summarizeConstitution(constitution));
|
|
7215
7367
|
} else if (existsSync13(draftPath)) {
|
|
7216
7368
|
const draft = deserializeConstitution(readFileSync5(draftPath, "utf-8"));
|
|
7217
|
-
console.log(
|
|
7369
|
+
console.log(chalk13.yellow("[DRAFT]"));
|
|
7218
7370
|
console.log(summarizeConstitution(draft));
|
|
7219
7371
|
} else {
|
|
7220
|
-
console.log(
|
|
7372
|
+
console.log(chalk13.dim("No Constitution found. Run `archon interview` to create one."));
|
|
7221
7373
|
}
|
|
7222
7374
|
}
|
|
7223
7375
|
async function validateConstitutionCommand() {
|
|
@@ -7226,23 +7378,23 @@ async function validateConstitutionCommand() {
|
|
|
7226
7378
|
const draftPath = getDraftPath(cwd);
|
|
7227
7379
|
const path2 = existsSync13(constitutionPath) ? constitutionPath : draftPath;
|
|
7228
7380
|
if (!existsSync13(path2)) {
|
|
7229
|
-
console.log(
|
|
7381
|
+
console.log(chalk13.dim("No Constitution found. Run `archon interview` to create one."));
|
|
7230
7382
|
return;
|
|
7231
7383
|
}
|
|
7232
7384
|
const constitution = deserializeConstitution(readFileSync5(path2, "utf-8"));
|
|
7233
7385
|
const result = validateConstitution(constitution);
|
|
7234
7386
|
if (result.valid) {
|
|
7235
|
-
console.log(
|
|
7387
|
+
console.log(chalk13.green("\u2713 Constitution is valid"));
|
|
7236
7388
|
} else {
|
|
7237
|
-
console.log(
|
|
7389
|
+
console.log(chalk13.red("\u2717 Constitution has errors:"));
|
|
7238
7390
|
for (const error of result.errors) {
|
|
7239
|
-
console.log(
|
|
7391
|
+
console.log(chalk13.red(` \u2022 ${error}`));
|
|
7240
7392
|
}
|
|
7241
7393
|
}
|
|
7242
7394
|
if (result.warnings.length > 0) {
|
|
7243
|
-
console.log(
|
|
7395
|
+
console.log(chalk13.yellow("\nWarnings:"));
|
|
7244
7396
|
for (const warning of result.warnings) {
|
|
7245
|
-
console.log(
|
|
7397
|
+
console.log(chalk13.yellow(` \u2022 ${warning}`));
|
|
7246
7398
|
}
|
|
7247
7399
|
}
|
|
7248
7400
|
}
|
|
@@ -7250,7 +7402,7 @@ async function exportConstitution(format) {
|
|
|
7250
7402
|
const cwd = process.cwd();
|
|
7251
7403
|
const constitutionPath = getConstitutionPath(cwd);
|
|
7252
7404
|
if (!existsSync13(constitutionPath)) {
|
|
7253
|
-
console.log(
|
|
7405
|
+
console.log(chalk13.dim("No frozen Constitution found."));
|
|
7254
7406
|
return;
|
|
7255
7407
|
}
|
|
7256
7408
|
const constitution = deserializeConstitution(readFileSync5(constitutionPath, "utf-8"));
|
|
@@ -7263,26 +7415,26 @@ async function exportConstitution(format) {
|
|
|
7263
7415
|
console.log(summarizeConstitution(constitution));
|
|
7264
7416
|
break;
|
|
7265
7417
|
default:
|
|
7266
|
-
console.log(
|
|
7418
|
+
console.log(chalk13.red(`Unknown format: ${format}. Use 'json' or 'markdown'.`));
|
|
7267
7419
|
}
|
|
7268
7420
|
}
|
|
7269
7421
|
async function generateAtoms(options = {}) {
|
|
7270
7422
|
const cwd = process.cwd();
|
|
7271
7423
|
const constitutionPath = getConstitutionPath(cwd);
|
|
7272
7424
|
if (!existsSync13(constitutionPath)) {
|
|
7273
|
-
console.log(
|
|
7274
|
-
console.log(
|
|
7425
|
+
console.log(chalk13.red("No frozen Constitution found."));
|
|
7426
|
+
console.log(chalk13.dim("Run `archon interview` to create one first."));
|
|
7275
7427
|
return;
|
|
7276
7428
|
}
|
|
7277
7429
|
const constitution = deserializeConstitution(readFileSync5(constitutionPath, "utf-8"));
|
|
7278
7430
|
if (constitution.state !== "FROZEN") {
|
|
7279
|
-
console.log(
|
|
7280
|
-
console.log(
|
|
7431
|
+
console.log(chalk13.yellow("Constitution is not frozen yet."));
|
|
7432
|
+
console.log(chalk13.dim("Complete the interview and freeze before generating atoms."));
|
|
7281
7433
|
return;
|
|
7282
7434
|
}
|
|
7283
|
-
console.log(
|
|
7284
|
-
console.log(
|
|
7285
|
-
console.log(
|
|
7435
|
+
console.log(chalk13.bold("\n\u{1F527} Generating Atoms from Constitution\n"));
|
|
7436
|
+
console.log(chalk13.dim(`Project: ${constitution.branding.projectName}`));
|
|
7437
|
+
console.log(chalk13.dim(`Hash: ${constitution.hash?.substring(0, 16)}...`));
|
|
7286
7438
|
console.log();
|
|
7287
7439
|
const spinner = ora3("Generating atoms...").start();
|
|
7288
7440
|
const result = generateAtomsFromConstitution(constitution, {
|
|
@@ -7295,7 +7447,7 @@ async function generateAtoms(options = {}) {
|
|
|
7295
7447
|
console.log(summarizeGeneration(result));
|
|
7296
7448
|
console.log();
|
|
7297
7449
|
if (options.dryRun) {
|
|
7298
|
-
console.log(
|
|
7450
|
+
console.log(chalk13.dim("(Dry run - not writing prd.json)"));
|
|
7299
7451
|
return;
|
|
7300
7452
|
}
|
|
7301
7453
|
const prdPath = options.output ?? join13(cwd, "prd.json");
|
|
@@ -7303,23 +7455,23 @@ async function generateAtoms(options = {}) {
|
|
|
7303
7455
|
if (existsSync13(prdPath)) {
|
|
7304
7456
|
const overwrite = await promptYesNo3("prd.json already exists. Overwrite?", false);
|
|
7305
7457
|
if (!overwrite) {
|
|
7306
|
-
console.log(
|
|
7458
|
+
console.log(chalk13.dim("Cancelled. Existing prd.json preserved."));
|
|
7307
7459
|
return;
|
|
7308
7460
|
}
|
|
7309
7461
|
}
|
|
7310
7462
|
writeFileSync(prdPath, JSON.stringify(prdContent, null, 2));
|
|
7311
|
-
console.log(
|
|
7463
|
+
console.log(chalk13.green(`
|
|
7312
7464
|
\u2713 Written to ${prdPath}`));
|
|
7313
7465
|
console.log();
|
|
7314
|
-
console.log(
|
|
7315
|
-
console.log(` ${
|
|
7316
|
-
console.log(` ${
|
|
7317
|
-
console.log(` ${
|
|
7466
|
+
console.log(chalk13.bold("Next Steps:\n"));
|
|
7467
|
+
console.log(` ${chalk13.cyan("1.")} Run ${chalk13.bold("archon list")} to see all atoms`);
|
|
7468
|
+
console.log(` ${chalk13.cyan("2.")} Run ${chalk13.bold("archon execute ATOM-001")} to start building`);
|
|
7469
|
+
console.log(` ${chalk13.cyan("3.")} Run ${chalk13.bold("archon watch")} to monitor progress`);
|
|
7318
7470
|
console.log();
|
|
7319
7471
|
}
|
|
7320
7472
|
|
|
7321
7473
|
// src/cli/eject.ts
|
|
7322
|
-
import
|
|
7474
|
+
import chalk14 from "chalk";
|
|
7323
7475
|
import { existsSync as existsSync14, rmSync } from "fs";
|
|
7324
7476
|
import { readFile as readFile8, writeFile as writeFile6 } from "fs/promises";
|
|
7325
7477
|
import { join as join14 } from "path";
|
|
@@ -7336,70 +7488,70 @@ var METADATA_FILES = [
|
|
|
7336
7488
|
];
|
|
7337
7489
|
async function eject(options = {}) {
|
|
7338
7490
|
const cwd = process.cwd();
|
|
7339
|
-
console.log(
|
|
7491
|
+
console.log(chalk14.blue("\n\u{1F680} ArchonDev Eject\n"));
|
|
7340
7492
|
const archonDir = join14(cwd, ".archon");
|
|
7341
7493
|
if (!existsSync14(archonDir)) {
|
|
7342
|
-
console.log(
|
|
7494
|
+
console.log(chalk14.yellow("This does not appear to be an ArchonDev project (.archon/ not found)."));
|
|
7343
7495
|
return;
|
|
7344
7496
|
}
|
|
7345
|
-
console.log(
|
|
7497
|
+
console.log(chalk14.dim("The following will be removed/modified:\n"));
|
|
7346
7498
|
const filesToRemove = [];
|
|
7347
7499
|
for (const file of ARCHON_FILES) {
|
|
7348
7500
|
const filePath = join14(cwd, file);
|
|
7349
7501
|
if (existsSync14(filePath)) {
|
|
7350
7502
|
filesToRemove.push(file);
|
|
7351
|
-
console.log(
|
|
7503
|
+
console.log(chalk14.red(` \u2717 ${file}`));
|
|
7352
7504
|
}
|
|
7353
7505
|
}
|
|
7354
7506
|
const archMd = join14(cwd, "ARCHITECTURE.md");
|
|
7355
7507
|
if (existsSync14(archMd) && !options.keepArchitecture) {
|
|
7356
|
-
console.log(
|
|
7508
|
+
console.log(chalk14.yellow(` ? ARCHITECTURE.md (will be kept by default)`));
|
|
7357
7509
|
}
|
|
7358
7510
|
console.log();
|
|
7359
|
-
console.log(
|
|
7511
|
+
console.log(chalk14.dim("Files to be modified:"));
|
|
7360
7512
|
for (const file of METADATA_FILES) {
|
|
7361
7513
|
const filePath = join14(cwd, file);
|
|
7362
7514
|
if (existsSync14(filePath)) {
|
|
7363
|
-
console.log(
|
|
7515
|
+
console.log(chalk14.yellow(` \u25CF ${file}`));
|
|
7364
7516
|
}
|
|
7365
7517
|
}
|
|
7366
7518
|
console.log();
|
|
7367
7519
|
if (!options.force) {
|
|
7368
7520
|
const confirmed = await promptYesNo4("This will permanently remove ArchonDev from your project. Continue?", false);
|
|
7369
7521
|
if (!confirmed) {
|
|
7370
|
-
console.log(
|
|
7522
|
+
console.log(chalk14.dim("Eject cancelled."));
|
|
7371
7523
|
return;
|
|
7372
7524
|
}
|
|
7373
7525
|
}
|
|
7374
7526
|
console.log();
|
|
7375
7527
|
const result = await performEject(cwd, options);
|
|
7376
7528
|
if (result.success) {
|
|
7377
|
-
console.log(
|
|
7529
|
+
console.log(chalk14.green("\n\u2705 Eject complete!\n"));
|
|
7378
7530
|
if (result.filesRemoved.length > 0) {
|
|
7379
|
-
console.log(
|
|
7531
|
+
console.log(chalk14.dim("Removed:"));
|
|
7380
7532
|
for (const file of result.filesRemoved) {
|
|
7381
|
-
console.log(
|
|
7533
|
+
console.log(chalk14.dim(` - ${file}`));
|
|
7382
7534
|
}
|
|
7383
7535
|
}
|
|
7384
7536
|
if (result.filesModified.length > 0) {
|
|
7385
|
-
console.log(
|
|
7537
|
+
console.log(chalk14.dim("\nModified:"));
|
|
7386
7538
|
for (const file of result.filesModified) {
|
|
7387
|
-
console.log(
|
|
7539
|
+
console.log(chalk14.dim(` - ${file}`));
|
|
7388
7540
|
}
|
|
7389
7541
|
}
|
|
7390
7542
|
if (result.warnings.length > 0) {
|
|
7391
|
-
console.log(
|
|
7543
|
+
console.log(chalk14.yellow("\nWarnings:"));
|
|
7392
7544
|
for (const warning of result.warnings) {
|
|
7393
|
-
console.log(
|
|
7545
|
+
console.log(chalk14.yellow(` \u26A0\uFE0F ${warning}`));
|
|
7394
7546
|
}
|
|
7395
7547
|
}
|
|
7396
7548
|
console.log();
|
|
7397
|
-
console.log(
|
|
7398
|
-
console.log(
|
|
7549
|
+
console.log(chalk14.blue("Your project is now a standard repository."));
|
|
7550
|
+
console.log(chalk14.dim("Thank you for using ArchonDev!"));
|
|
7399
7551
|
} else {
|
|
7400
|
-
console.log(
|
|
7552
|
+
console.log(chalk14.red("\n\u274C Eject failed."));
|
|
7401
7553
|
for (const warning of result.warnings) {
|
|
7402
|
-
console.log(
|
|
7554
|
+
console.log(chalk14.red(` ${warning}`));
|
|
7403
7555
|
}
|
|
7404
7556
|
}
|
|
7405
7557
|
}
|
|
@@ -7506,17 +7658,17 @@ async function performEject(cwd, options) {
|
|
|
7506
7658
|
}
|
|
7507
7659
|
async function ejectDryRun() {
|
|
7508
7660
|
const cwd = process.cwd();
|
|
7509
|
-
console.log(
|
|
7661
|
+
console.log(chalk14.blue("\n\u{1F50D} Eject Dry Run\n"));
|
|
7510
7662
|
const archonDir = join14(cwd, ".archon");
|
|
7511
7663
|
if (!existsSync14(archonDir)) {
|
|
7512
|
-
console.log(
|
|
7664
|
+
console.log(chalk14.yellow("This does not appear to be an ArchonDev project."));
|
|
7513
7665
|
return;
|
|
7514
7666
|
}
|
|
7515
7667
|
console.log("The following would be removed:\n");
|
|
7516
7668
|
for (const file of ARCHON_FILES) {
|
|
7517
7669
|
const filePath = join14(cwd, file);
|
|
7518
7670
|
if (existsSync14(filePath)) {
|
|
7519
|
-
console.log(
|
|
7671
|
+
console.log(chalk14.red(` \u2717 ${file}`));
|
|
7520
7672
|
}
|
|
7521
7673
|
}
|
|
7522
7674
|
console.log();
|
|
@@ -7524,11 +7676,11 @@ async function ejectDryRun() {
|
|
|
7524
7676
|
for (const file of METADATA_FILES) {
|
|
7525
7677
|
const filePath = join14(cwd, file);
|
|
7526
7678
|
if (existsSync14(filePath)) {
|
|
7527
|
-
console.log(
|
|
7679
|
+
console.log(chalk14.yellow(` \u25CF ${file}`));
|
|
7528
7680
|
}
|
|
7529
7681
|
}
|
|
7530
7682
|
console.log();
|
|
7531
|
-
console.log(
|
|
7683
|
+
console.log(chalk14.dim('Run "archon eject" to proceed.'));
|
|
7532
7684
|
}
|
|
7533
7685
|
function promptYesNo4(question, defaultValue) {
|
|
7534
7686
|
return new Promise((resolve) => {
|
|
@@ -7537,7 +7689,7 @@ function promptYesNo4(question, defaultValue) {
|
|
|
7537
7689
|
output: process.stdout
|
|
7538
7690
|
});
|
|
7539
7691
|
const hint = defaultValue ? "(Y/n)" : "(y/N)";
|
|
7540
|
-
rl.question(`${
|
|
7692
|
+
rl.question(`${chalk14.cyan("?")} ${question} ${hint}: `, (answer) => {
|
|
7541
7693
|
rl.close();
|
|
7542
7694
|
if (answer.trim() === "") {
|
|
7543
7695
|
resolve(defaultValue);
|
|
@@ -7549,7 +7701,7 @@ function promptYesNo4(question, defaultValue) {
|
|
|
7549
7701
|
}
|
|
7550
7702
|
|
|
7551
7703
|
// src/cli/revert.ts
|
|
7552
|
-
import
|
|
7704
|
+
import chalk15 from "chalk";
|
|
7553
7705
|
import { execSync as execSync4 } from "child_process";
|
|
7554
7706
|
import { existsSync as existsSync15 } from "fs";
|
|
7555
7707
|
import { readFile as readFile9, writeFile as writeFile7 } from "fs/promises";
|
|
@@ -7594,35 +7746,35 @@ async function findAtomCommits(limit = 50) {
|
|
|
7594
7746
|
}
|
|
7595
7747
|
return commits;
|
|
7596
7748
|
} catch (error) {
|
|
7597
|
-
console.error(
|
|
7749
|
+
console.error(chalk15.red("Failed to read git history:"), error instanceof Error ? error.message : "Unknown error");
|
|
7598
7750
|
return [];
|
|
7599
7751
|
}
|
|
7600
7752
|
}
|
|
7601
7753
|
async function historyCommand(options) {
|
|
7602
7754
|
const limit = options.limit ?? 20;
|
|
7603
|
-
console.log(
|
|
7755
|
+
console.log(chalk15.blue("\n\u{1F4DC} Atom Execution History\n"));
|
|
7604
7756
|
const commits = await findAtomCommits(limit);
|
|
7605
7757
|
if (commits.length === 0) {
|
|
7606
|
-
console.log(
|
|
7607
|
-
console.log(
|
|
7758
|
+
console.log(chalk15.dim("No atom commits found in git history."));
|
|
7759
|
+
console.log(chalk15.dim('Atom commits are created when you run "archon execute <atom-id>".'));
|
|
7608
7760
|
return;
|
|
7609
7761
|
}
|
|
7610
|
-
console.log(
|
|
7762
|
+
console.log(chalk15.dim(`Showing ${commits.length} atom commit(s):
|
|
7611
7763
|
`));
|
|
7612
7764
|
for (const commit of commits) {
|
|
7613
7765
|
const shortHash = commit.commitHash.substring(0, 7);
|
|
7614
7766
|
const filesLabel = commit.filesChanged === 1 ? "file" : "files";
|
|
7615
|
-
console.log(`${
|
|
7616
|
-
console.log(
|
|
7617
|
-
console.log(
|
|
7767
|
+
console.log(`${chalk15.yellow(shortHash)} ${chalk15.cyan(commit.atomId)}`);
|
|
7768
|
+
console.log(chalk15.dim(` ${commit.message}`));
|
|
7769
|
+
console.log(chalk15.dim(` ${commit.date} | ${commit.filesChanged} ${filesLabel} changed`));
|
|
7618
7770
|
console.log();
|
|
7619
7771
|
}
|
|
7620
|
-
console.log(
|
|
7621
|
-
console.log(
|
|
7772
|
+
console.log(chalk15.dim("To revert an atom: archon revert <atom-id>"));
|
|
7773
|
+
console.log(chalk15.dim("Or by commit hash: archon revert --commit <hash>"));
|
|
7622
7774
|
}
|
|
7623
7775
|
async function revertCommand(atomIdOrHash, options = {}) {
|
|
7624
7776
|
const cwd = process.cwd();
|
|
7625
|
-
console.log(
|
|
7777
|
+
console.log(chalk15.blue("\n\u23EA Atom Revert\n"));
|
|
7626
7778
|
let commit;
|
|
7627
7779
|
if (atomIdOrHash.match(/^[a-f0-9]{7,40}$/i)) {
|
|
7628
7780
|
const commits = await findAtomCommits(100);
|
|
@@ -7632,54 +7784,54 @@ async function revertCommand(atomIdOrHash, options = {}) {
|
|
|
7632
7784
|
commit = commits.find((c) => c.atomId.toLowerCase() === atomIdOrHash.toLowerCase());
|
|
7633
7785
|
}
|
|
7634
7786
|
if (!commit) {
|
|
7635
|
-
console.log(
|
|
7636
|
-
console.log(
|
|
7787
|
+
console.log(chalk15.red(`No atom commit found for: ${atomIdOrHash}`));
|
|
7788
|
+
console.log(chalk15.dim('Run "archon history" to see available atom commits.'));
|
|
7637
7789
|
return;
|
|
7638
7790
|
}
|
|
7639
|
-
console.log(`Atom: ${
|
|
7640
|
-
console.log(`Commit: ${
|
|
7791
|
+
console.log(`Atom: ${chalk15.cyan(commit.atomId)}`);
|
|
7792
|
+
console.log(`Commit: ${chalk15.yellow(commit.commitHash.substring(0, 7))}`);
|
|
7641
7793
|
console.log(`Message: ${commit.message}`);
|
|
7642
7794
|
console.log(`Date: ${commit.date}`);
|
|
7643
7795
|
console.log(`Files changed: ${commit.filesChanged}`);
|
|
7644
7796
|
console.log();
|
|
7645
7797
|
try {
|
|
7646
|
-
console.log(
|
|
7798
|
+
console.log(chalk15.dim("Changes to be reverted:"));
|
|
7647
7799
|
const diffStat = execSync4(
|
|
7648
7800
|
`git diff --stat ${commit.commitHash}^..${commit.commitHash}`,
|
|
7649
7801
|
{ cwd, encoding: "utf-8" }
|
|
7650
7802
|
);
|
|
7651
|
-
console.log(
|
|
7803
|
+
console.log(chalk15.dim(diffStat));
|
|
7652
7804
|
} catch {
|
|
7653
7805
|
}
|
|
7654
7806
|
if (!options.force) {
|
|
7655
7807
|
const confirmed = await promptYesNo5("Revert this atom commit?", false);
|
|
7656
7808
|
if (!confirmed) {
|
|
7657
|
-
console.log(
|
|
7809
|
+
console.log(chalk15.dim("Revert cancelled."));
|
|
7658
7810
|
return;
|
|
7659
7811
|
}
|
|
7660
7812
|
}
|
|
7661
7813
|
try {
|
|
7662
7814
|
const revertArgs = options.noCommit ? "--no-commit" : "";
|
|
7663
7815
|
execSync4(`git revert ${revertArgs} ${commit.commitHash}`, { cwd, stdio: "pipe" });
|
|
7664
|
-
console.log(
|
|
7816
|
+
console.log(chalk15.green(`
|
|
7665
7817
|
\u2705 Successfully reverted ${commit.atomId}`));
|
|
7666
7818
|
if (options.noCommit) {
|
|
7667
|
-
console.log(
|
|
7668
|
-
console.log(
|
|
7819
|
+
console.log(chalk15.dim("Changes are staged but not committed."));
|
|
7820
|
+
console.log(chalk15.dim('Run "git commit" to finalize the revert.'));
|
|
7669
7821
|
} else {
|
|
7670
|
-
console.log(
|
|
7822
|
+
console.log(chalk15.dim("A new commit has been created to undo the changes."));
|
|
7671
7823
|
}
|
|
7672
7824
|
await updateAtomStatus(commit.atomId, "REVERTED");
|
|
7673
7825
|
} catch (error) {
|
|
7674
7826
|
const errorMsg = error instanceof Error ? error.message : "Unknown error";
|
|
7675
7827
|
if (errorMsg.includes("conflict")) {
|
|
7676
|
-
console.log(
|
|
7677
|
-
console.log(
|
|
7678
|
-
console.log(
|
|
7679
|
-
console.log(
|
|
7828
|
+
console.log(chalk15.yellow("\n\u26A0\uFE0F Merge conflict detected during revert."));
|
|
7829
|
+
console.log(chalk15.dim("Resolve conflicts manually, then:"));
|
|
7830
|
+
console.log(chalk15.dim(" git add ."));
|
|
7831
|
+
console.log(chalk15.dim(" git revert --continue"));
|
|
7680
7832
|
} else {
|
|
7681
|
-
console.log(
|
|
7682
|
-
console.log(
|
|
7833
|
+
console.log(chalk15.red("\n\u274C Revert failed:"), errorMsg);
|
|
7834
|
+
console.log(chalk15.dim("You may need to resolve this manually."));
|
|
7683
7835
|
}
|
|
7684
7836
|
}
|
|
7685
7837
|
}
|
|
@@ -7698,10 +7850,10 @@ async function updateAtomStatus(atomId, status2) {
|
|
|
7698
7850
|
}
|
|
7699
7851
|
}
|
|
7700
7852
|
async function revertableAtoms() {
|
|
7701
|
-
console.log(
|
|
7853
|
+
console.log(chalk15.blue("\n\u{1F504} Revertable Atoms\n"));
|
|
7702
7854
|
const commits = await findAtomCommits(30);
|
|
7703
7855
|
if (commits.length === 0) {
|
|
7704
|
-
console.log(
|
|
7856
|
+
console.log(chalk15.dim("No atom commits found."));
|
|
7705
7857
|
return;
|
|
7706
7858
|
}
|
|
7707
7859
|
const atomMap = /* @__PURE__ */ new Map();
|
|
@@ -7710,14 +7862,14 @@ async function revertableAtoms() {
|
|
|
7710
7862
|
atomMap.set(commit.atomId, commit);
|
|
7711
7863
|
}
|
|
7712
7864
|
}
|
|
7713
|
-
console.log(
|
|
7865
|
+
console.log(chalk15.dim(`Found ${atomMap.size} unique atom(s) in history:
|
|
7714
7866
|
`));
|
|
7715
7867
|
for (const [atomId, commit] of atomMap) {
|
|
7716
7868
|
const shortHash = commit.commitHash.substring(0, 7);
|
|
7717
|
-
console.log(` ${
|
|
7869
|
+
console.log(` ${chalk15.cyan(atomId)} ${chalk15.dim(`(${shortHash})`)} - ${commit.message.substring(0, 50)}`);
|
|
7718
7870
|
}
|
|
7719
7871
|
console.log();
|
|
7720
|
-
console.log(
|
|
7872
|
+
console.log(chalk15.dim("To revert: archon revert <atom-id>"));
|
|
7721
7873
|
}
|
|
7722
7874
|
function promptYesNo5(question, defaultValue) {
|
|
7723
7875
|
return new Promise((resolve) => {
|
|
@@ -7726,7 +7878,7 @@ function promptYesNo5(question, defaultValue) {
|
|
|
7726
7878
|
output: process.stdout
|
|
7727
7879
|
});
|
|
7728
7880
|
const hint = defaultValue ? "(Y/n)" : "(y/N)";
|
|
7729
|
-
rl.question(`${
|
|
7881
|
+
rl.question(`${chalk15.cyan("?")} ${question} ${hint}: `, (answer) => {
|
|
7730
7882
|
rl.close();
|
|
7731
7883
|
if (answer.trim() === "") {
|
|
7732
7884
|
resolve(defaultValue);
|
|
@@ -7738,17 +7890,17 @@ function promptYesNo5(question, defaultValue) {
|
|
|
7738
7890
|
}
|
|
7739
7891
|
|
|
7740
7892
|
// src/cli/models-sync.ts
|
|
7741
|
-
import
|
|
7893
|
+
import chalk16 from "chalk";
|
|
7742
7894
|
async function modelsSync(options) {
|
|
7743
7895
|
const supabaseUrl = process.env["SUPABASE_URL"];
|
|
7744
7896
|
const supabaseKey = process.env["SUPABASE_SERVICE_ROLE_KEY"] || process.env["SUPABASE_ANON_KEY"];
|
|
7745
7897
|
if (!supabaseUrl) {
|
|
7746
|
-
console.log(
|
|
7747
|
-
console.log(
|
|
7748
|
-
console.log(
|
|
7898
|
+
console.log(chalk16.red("SUPABASE_URL not set. Cannot trigger remote sync."));
|
|
7899
|
+
console.log(chalk16.dim("Run the pricing check locally instead:"));
|
|
7900
|
+
console.log(chalk16.dim(" npx tsx scripts/update-model-pricing.ts --check"));
|
|
7749
7901
|
return;
|
|
7750
7902
|
}
|
|
7751
|
-
console.log(
|
|
7903
|
+
console.log(chalk16.blue("\n\u{1F504} Triggering model registry sync...\n"));
|
|
7752
7904
|
try {
|
|
7753
7905
|
const functionUrl = `${supabaseUrl}/functions/v1/model-registry-sync`;
|
|
7754
7906
|
const response = await fetch(functionUrl, {
|
|
@@ -7760,83 +7912,83 @@ async function modelsSync(options) {
|
|
|
7760
7912
|
});
|
|
7761
7913
|
if (!response.ok) {
|
|
7762
7914
|
const errorText = await response.text();
|
|
7763
|
-
console.log(
|
|
7915
|
+
console.log(chalk16.red(`Sync failed: ${response.status} - ${errorText}`));
|
|
7764
7916
|
return;
|
|
7765
7917
|
}
|
|
7766
7918
|
const result = await response.json();
|
|
7767
|
-
console.log(
|
|
7919
|
+
console.log(chalk16.bold("Sync Results:"));
|
|
7768
7920
|
console.log(` Providers checked: ${result.providersChecked.join(", ")}`);
|
|
7769
7921
|
console.log(` Duration: ${result.durationMs}ms`);
|
|
7770
7922
|
console.log();
|
|
7771
|
-
console.log(
|
|
7923
|
+
console.log(chalk16.bold("Parse Confidence:"));
|
|
7772
7924
|
for (const [provider, score] of Object.entries(result.confidenceScores)) {
|
|
7773
7925
|
const pct = (score * 100).toFixed(0);
|
|
7774
|
-
const color = score >= 0.8 ?
|
|
7926
|
+
const color = score >= 0.8 ? chalk16.green : score >= 0.5 ? chalk16.yellow : chalk16.red;
|
|
7775
7927
|
console.log(` ${provider}: ${color(pct + "%")}`);
|
|
7776
7928
|
}
|
|
7777
7929
|
console.log();
|
|
7778
7930
|
if (result.diffs.length === 0) {
|
|
7779
|
-
console.log(
|
|
7931
|
+
console.log(chalk16.green("\u2705 All model pricing is up to date. No changes detected."));
|
|
7780
7932
|
} else {
|
|
7781
7933
|
const pricingChanges = result.diffs.filter((d) => d.type === "PRICING_CHANGE");
|
|
7782
7934
|
const newModels = result.diffs.filter((d) => d.type === "NEW_MODEL");
|
|
7783
7935
|
if (pricingChanges.length > 0) {
|
|
7784
|
-
console.log(
|
|
7936
|
+
console.log(chalk16.yellow(`\u{1F4B0} Pricing Changes (${pricingChanges.length}):`));
|
|
7785
7937
|
for (const d of pricingChanges) {
|
|
7786
|
-
console.log(` ${d.provider}/${
|
|
7787
|
-
console.log(` Old: ${
|
|
7788
|
-
console.log(` New: ${
|
|
7938
|
+
console.log(` ${d.provider}/${chalk16.bold(d.modelId)}`);
|
|
7939
|
+
console.log(` Old: ${chalk16.red(d.oldValue ?? "unknown")}`);
|
|
7940
|
+
console.log(` New: ${chalk16.green(d.newValue ?? "unknown")}`);
|
|
7789
7941
|
}
|
|
7790
7942
|
console.log();
|
|
7791
7943
|
}
|
|
7792
7944
|
if (newModels.length > 0) {
|
|
7793
|
-
console.log(
|
|
7945
|
+
console.log(chalk16.cyan(`\u{1F195} New Models (${newModels.length}):`));
|
|
7794
7946
|
for (const d of newModels) {
|
|
7795
|
-
console.log(` ${d.provider}/${
|
|
7947
|
+
console.log(` ${d.provider}/${chalk16.bold(d.modelId)}: ${d.details}`);
|
|
7796
7948
|
}
|
|
7797
7949
|
console.log();
|
|
7798
7950
|
}
|
|
7799
|
-
console.log(
|
|
7951
|
+
console.log(chalk16.bold(`Applied: ${result.modelsUpdated} updated, ${result.modelsAdded} added`));
|
|
7800
7952
|
}
|
|
7801
7953
|
if (result.parseErrors.length > 0) {
|
|
7802
7954
|
console.log();
|
|
7803
|
-
console.log(
|
|
7955
|
+
console.log(chalk16.red(`\u26A0\uFE0F Warnings/Errors (${result.parseErrors.length}):`));
|
|
7804
7956
|
for (const err2 of result.parseErrors) {
|
|
7805
|
-
console.log(
|
|
7957
|
+
console.log(chalk16.red(` - ${err2}`));
|
|
7806
7958
|
}
|
|
7807
7959
|
}
|
|
7808
7960
|
console.log();
|
|
7809
7961
|
} catch (err2) {
|
|
7810
|
-
console.log(
|
|
7962
|
+
console.log(chalk16.red(`Failed to run sync: ${err2}`));
|
|
7811
7963
|
}
|
|
7812
7964
|
}
|
|
7813
7965
|
async function modelsList() {
|
|
7814
7966
|
const { getAllActiveModels, getModelCost, isFreeModel } = await import("./models-D4NV2MVH.js");
|
|
7815
7967
|
const models = getAllActiveModels();
|
|
7816
|
-
console.log(
|
|
7968
|
+
console.log(chalk16.bold("\n\u{1F4CB} Model Registry\n"));
|
|
7817
7969
|
let currentProvider = "";
|
|
7818
7970
|
for (const model of models) {
|
|
7819
7971
|
if (model.provider !== currentProvider) {
|
|
7820
7972
|
currentProvider = model.provider;
|
|
7821
|
-
console.log(
|
|
7973
|
+
console.log(chalk16.bold.blue(`
|
|
7822
7974
|
${currentProvider.toUpperCase()}`));
|
|
7823
|
-
console.log(
|
|
7975
|
+
console.log(chalk16.dim(" \u2500".repeat(40)));
|
|
7824
7976
|
}
|
|
7825
7977
|
const cost = getModelCost(model.modelId);
|
|
7826
7978
|
const free = isFreeModel(model.modelId);
|
|
7827
|
-
const tier = free ?
|
|
7828
|
-
const category = model.category === "thinking" ?
|
|
7979
|
+
const tier = free ? chalk16.green(" [FREE]") : "";
|
|
7980
|
+
const category = model.category === "thinking" ? chalk16.magenta("thinking") : chalk16.cyan("fast");
|
|
7829
7981
|
const inputPrice = cost ? `$${(cost.costPer1kInput * 1e3).toFixed(2)}/1M` : "?";
|
|
7830
7982
|
const outputPrice = cost ? `$${(cost.costPer1kOutput * 1e3).toFixed(2)}/1M` : "?";
|
|
7831
|
-
console.log(` ${
|
|
7832
|
-
console.log(
|
|
7983
|
+
console.log(` ${chalk16.bold(model.modelId)}${tier}`);
|
|
7984
|
+
console.log(chalk16.dim(` ${category} | Input: ${inputPrice} | Output: ${outputPrice}`));
|
|
7833
7985
|
}
|
|
7834
7986
|
console.log();
|
|
7835
7987
|
}
|
|
7836
7988
|
|
|
7837
7989
|
// src/cli/governance.ts
|
|
7838
7990
|
import { Command as Command2 } from "commander";
|
|
7839
|
-
import
|
|
7991
|
+
import chalk17 from "chalk";
|
|
7840
7992
|
import { existsSync as existsSync19, readFileSync as readFileSync7 } from "fs";
|
|
7841
7993
|
import { readFile as readFile12 } from "fs/promises";
|
|
7842
7994
|
import { join as join19 } from "path";
|
|
@@ -8656,9 +8808,9 @@ function parseContextMeta(content) {
|
|
|
8656
8808
|
function renderStatusCounts(counts) {
|
|
8657
8809
|
const total = Object.values(counts).reduce((sum, value) => sum + value, 0);
|
|
8658
8810
|
if (total === 0) return;
|
|
8659
|
-
console.log(
|
|
8811
|
+
console.log(chalk17.dim(` Tasks: ${total} total`));
|
|
8660
8812
|
console.log(
|
|
8661
|
-
|
|
8813
|
+
chalk17.dim(
|
|
8662
8814
|
` pending: ${counts.pending} | in_progress: ${counts.in_progress} | verification: ${counts.verification} | done: ${counts.done}`
|
|
8663
8815
|
)
|
|
8664
8816
|
);
|
|
@@ -8674,22 +8826,22 @@ function createGovernanceCommand() {
|
|
|
8674
8826
|
const cwd = process.cwd();
|
|
8675
8827
|
const store = new GovernanceStore(cwd);
|
|
8676
8828
|
store.ensureStructure();
|
|
8677
|
-
console.log(
|
|
8829
|
+
console.log(chalk17.bold("\nGovernance Status\n"));
|
|
8678
8830
|
const archInfo = resolveArchitecturePath2(cwd);
|
|
8679
8831
|
if (archInfo.path) {
|
|
8680
8832
|
const parser = new ArchitectureParser(archInfo.path);
|
|
8681
8833
|
const parsed = await parser.parse();
|
|
8682
8834
|
if (parsed.success && parsed.schema) {
|
|
8683
8835
|
const posture = parsed.schema.qualityLevel?.posture ?? "unknown";
|
|
8684
|
-
console.log(
|
|
8685
|
-
console.log(
|
|
8686
|
-
console.log(
|
|
8687
|
-
console.log(
|
|
8836
|
+
console.log(chalk17.green(" \u2713") + ` Architecture (${archInfo.source})`);
|
|
8837
|
+
console.log(chalk17.dim(` posture: ${posture}`));
|
|
8838
|
+
console.log(chalk17.dim(` invariants: ${parsed.schema.invariants.length}`));
|
|
8839
|
+
console.log(chalk17.dim(` protected paths: ${parsed.schema.protectedPaths.length}`));
|
|
8688
8840
|
} else {
|
|
8689
|
-
console.log(
|
|
8841
|
+
console.log(chalk17.yellow(" ! Architecture present but failed to parse"));
|
|
8690
8842
|
}
|
|
8691
8843
|
} else {
|
|
8692
|
-
console.log(
|
|
8844
|
+
console.log(chalk17.yellow(" \u25CB No architecture file found"));
|
|
8693
8845
|
}
|
|
8694
8846
|
const tasksPath = join19(cwd, ACTIVE_TASKS_PATH2);
|
|
8695
8847
|
if (existsSync19(tasksPath)) {
|
|
@@ -8699,33 +8851,33 @@ function createGovernanceCommand() {
|
|
|
8699
8851
|
if (tasks2) {
|
|
8700
8852
|
renderStatusCounts(countTaskStatuses(tasks2));
|
|
8701
8853
|
} else {
|
|
8702
|
-
console.log(
|
|
8854
|
+
console.log(chalk17.yellow(" ! tasks.json present but invalid"));
|
|
8703
8855
|
}
|
|
8704
8856
|
} catch {
|
|
8705
|
-
console.log(
|
|
8857
|
+
console.log(chalk17.yellow(" ! tasks.json present but unreadable"));
|
|
8706
8858
|
}
|
|
8707
8859
|
}
|
|
8708
8860
|
const contextPath = join19(cwd, CURRENT_CONTEXT_PATH);
|
|
8709
8861
|
if (existsSync19(contextPath)) {
|
|
8710
8862
|
const content = readFileSync7(contextPath, "utf-8");
|
|
8711
8863
|
const meta = parseContextMeta(content);
|
|
8712
|
-
console.log(
|
|
8864
|
+
console.log(chalk17.dim(` Handoff: ${meta.timestamp ?? "present"}`));
|
|
8713
8865
|
if (meta.reason) {
|
|
8714
|
-
console.log(
|
|
8866
|
+
console.log(chalk17.dim(` reason: ${meta.reason}`));
|
|
8715
8867
|
}
|
|
8716
8868
|
}
|
|
8717
8869
|
const handoffHistoryPath = join19(cwd, HANDOFF_HISTORY_PATH);
|
|
8718
8870
|
if (existsSync19(handoffHistoryPath)) {
|
|
8719
8871
|
const count = lineCount(readFileSync7(handoffHistoryPath, "utf-8"));
|
|
8720
8872
|
if (count > 0) {
|
|
8721
|
-
console.log(
|
|
8873
|
+
console.log(chalk17.dim(` Handoff entries: ${count}`));
|
|
8722
8874
|
}
|
|
8723
8875
|
}
|
|
8724
8876
|
const completedPath = join19(cwd, COMPLETED_TASKS_PATH);
|
|
8725
8877
|
if (existsSync19(completedPath)) {
|
|
8726
8878
|
const count = lineCount(readFileSync7(completedPath, "utf-8"));
|
|
8727
8879
|
if (count > 0) {
|
|
8728
|
-
console.log(
|
|
8880
|
+
console.log(chalk17.dim(` Completed tasks archived: ${count}`));
|
|
8729
8881
|
}
|
|
8730
8882
|
}
|
|
8731
8883
|
console.log("");
|
|
@@ -8736,7 +8888,7 @@ function createGovernanceCommand() {
|
|
|
8736
8888
|
const store = new GovernanceStore(cwd);
|
|
8737
8889
|
const archInfo = resolveArchitecturePath2(cwd);
|
|
8738
8890
|
if (!archInfo.path) {
|
|
8739
|
-
console.log(
|
|
8891
|
+
console.log(chalk17.yellow("No architecture file found."));
|
|
8740
8892
|
return;
|
|
8741
8893
|
}
|
|
8742
8894
|
if (options.raw) {
|
|
@@ -8747,11 +8899,11 @@ function createGovernanceCommand() {
|
|
|
8747
8899
|
if (archInfo.source === "agd") {
|
|
8748
8900
|
const result = await store.readArchitecture();
|
|
8749
8901
|
if (!result.ok) {
|
|
8750
|
-
console.log(
|
|
8902
|
+
console.log(chalk17.red(`Failed to read architecture: ${result.error}`));
|
|
8751
8903
|
return;
|
|
8752
8904
|
}
|
|
8753
8905
|
if (!result.value) {
|
|
8754
|
-
console.log(
|
|
8906
|
+
console.log(chalk17.yellow("Architecture file is empty."));
|
|
8755
8907
|
return;
|
|
8756
8908
|
}
|
|
8757
8909
|
console.log(result.value);
|
|
@@ -8761,7 +8913,7 @@ function createGovernanceCommand() {
|
|
|
8761
8913
|
const legacyParsed = matter4(legacyRaw);
|
|
8762
8914
|
const legacyContent = legacyParsed.content.trim();
|
|
8763
8915
|
if (!legacyContent) {
|
|
8764
|
-
console.log(
|
|
8916
|
+
console.log(chalk17.yellow("Architecture file is empty."));
|
|
8765
8917
|
return;
|
|
8766
8918
|
}
|
|
8767
8919
|
console.log(legacyContent);
|
|
@@ -8770,32 +8922,32 @@ function createGovernanceCommand() {
|
|
|
8770
8922
|
const cwd = process.cwd();
|
|
8771
8923
|
const filePath = options.file;
|
|
8772
8924
|
if (!existsSync19(filePath)) {
|
|
8773
|
-
console.log(
|
|
8925
|
+
console.log(chalk17.red(`File not found: ${filePath}`));
|
|
8774
8926
|
process.exit(1);
|
|
8775
8927
|
}
|
|
8776
8928
|
const content = await readFile12(filePath, "utf-8");
|
|
8777
8929
|
const store = new GovernanceStore(cwd);
|
|
8778
8930
|
const result = await store.updateArchitecture(content, options.reason, options.by);
|
|
8779
8931
|
if (!result.ok) {
|
|
8780
|
-
console.log(
|
|
8932
|
+
console.log(chalk17.red(`Failed to update architecture: ${result.error}`));
|
|
8781
8933
|
process.exit(1);
|
|
8782
8934
|
}
|
|
8783
|
-
console.log(
|
|
8935
|
+
console.log(chalk17.green("\u2713 Architecture updated"));
|
|
8784
8936
|
});
|
|
8785
8937
|
const tasks = governance.command("task").description("Update tasks in governance store");
|
|
8786
8938
|
tasks.command("update <taskId>").description("Update task status and notes").requiredOption("-s, --status <status>", "Status: pending, in_progress, verification, done").option("-n, --notes <text>", "Optional notes").action(async (taskId, options) => {
|
|
8787
8939
|
const status2 = options.status;
|
|
8788
8940
|
if (!isTaskStatus(status2)) {
|
|
8789
|
-
console.log(
|
|
8941
|
+
console.log(chalk17.red(`Invalid status: ${options.status}`));
|
|
8790
8942
|
process.exit(1);
|
|
8791
8943
|
}
|
|
8792
8944
|
const store = new GovernanceStore(process.cwd());
|
|
8793
8945
|
const result = await store.updateTask(taskId, status2, options.notes);
|
|
8794
8946
|
if (!result.ok) {
|
|
8795
|
-
console.log(
|
|
8947
|
+
console.log(chalk17.red(`Failed to update task: ${result.error}`));
|
|
8796
8948
|
process.exit(1);
|
|
8797
8949
|
}
|
|
8798
|
-
console.log(
|
|
8950
|
+
console.log(chalk17.green(`\u2713 Task ${taskId} updated to ${status2}`));
|
|
8799
8951
|
});
|
|
8800
8952
|
governance.command("handoff").description("Log a handoff entry and update current context").requiredOption("-r, --reason <text>", "Reason for handoff").requiredOption("-s, --summary <text>", "Summary (single paragraph)").requiredOption("-n, --next <actions...>", "Next actions (space-separated)").option("-f, --from <agent>", "Agent or source name").option("-t, --timestamp <iso>", "Timestamp override (ISO 8601)").action(async (options) => {
|
|
8801
8953
|
const store = new GovernanceStore(process.cwd());
|
|
@@ -8808,10 +8960,10 @@ function createGovernanceCommand() {
|
|
|
8808
8960
|
};
|
|
8809
8961
|
const result = await store.logHandoff(entry);
|
|
8810
8962
|
if (!result.ok) {
|
|
8811
|
-
console.log(
|
|
8963
|
+
console.log(chalk17.red(`Failed to log handoff: ${result.error}`));
|
|
8812
8964
|
process.exit(1);
|
|
8813
8965
|
}
|
|
8814
|
-
console.log(
|
|
8966
|
+
console.log(chalk17.green("\u2713 Handoff logged"));
|
|
8815
8967
|
});
|
|
8816
8968
|
governance.command("migrate").description("Migrate legacy governance files into AGD structure").option("--remove-legacy", "Archive legacy files after migration").option("--dry-run", "Show what would change without writing files").option("-b, --by <name>", "Updated by label for architecture migration").action(async (options) => {
|
|
8817
8969
|
const result = await migrateLegacyGovernance({
|
|
@@ -8820,23 +8972,23 @@ function createGovernanceCommand() {
|
|
|
8820
8972
|
dryRun: options.dryRun,
|
|
8821
8973
|
updatedBy: options.by
|
|
8822
8974
|
});
|
|
8823
|
-
console.log(
|
|
8975
|
+
console.log(chalk17.bold("\nMigration Summary"));
|
|
8824
8976
|
console.log(
|
|
8825
|
-
result.migratedArchitecture ?
|
|
8977
|
+
result.migratedArchitecture ? chalk17.green(" \u2713 Architecture migrated") : chalk17.dim(" \u25CB Architecture migration skipped")
|
|
8826
8978
|
);
|
|
8827
8979
|
console.log(
|
|
8828
|
-
result.migratedTasks ?
|
|
8980
|
+
result.migratedTasks ? chalk17.green(" \u2713 Tasks migrated") : chalk17.dim(" \u25CB Tasks migration skipped")
|
|
8829
8981
|
);
|
|
8830
8982
|
if (result.archivedLegacyFiles.length > 0) {
|
|
8831
|
-
console.log(
|
|
8983
|
+
console.log(chalk17.dim(" Archived legacy files:"));
|
|
8832
8984
|
for (const file of result.archivedLegacyFiles) {
|
|
8833
|
-
console.log(
|
|
8985
|
+
console.log(chalk17.dim(` - ${file}`));
|
|
8834
8986
|
}
|
|
8835
8987
|
}
|
|
8836
8988
|
if (result.warnings.length > 0) {
|
|
8837
|
-
console.log(
|
|
8989
|
+
console.log(chalk17.yellow("\nWarnings:"));
|
|
8838
8990
|
for (const warning of result.warnings) {
|
|
8839
|
-
console.log(
|
|
8991
|
+
console.log(chalk17.yellow(` - ${warning}`));
|
|
8840
8992
|
}
|
|
8841
8993
|
}
|
|
8842
8994
|
console.log("");
|
|
@@ -8847,7 +8999,7 @@ function createGovernanceCommand() {
|
|
|
8847
8999
|
view.init(cwd);
|
|
8848
9000
|
await view.loadFromDisk(cwd);
|
|
8849
9001
|
view.close();
|
|
8850
|
-
console.log(
|
|
9002
|
+
console.log(chalk17.green("\u2713 Governance SQLite DB initialized"));
|
|
8851
9003
|
});
|
|
8852
9004
|
return governance;
|
|
8853
9005
|
}
|
|
@@ -8859,7 +9011,7 @@ program.name("archon").description("Local-first AI-powered development governanc
|
|
|
8859
9011
|
const cwd = process.cwd();
|
|
8860
9012
|
const wasInitialized = isInitialized(cwd);
|
|
8861
9013
|
if (!wasInitialized) {
|
|
8862
|
-
console.log(
|
|
9014
|
+
console.log(chalk18.blue("\nArchonDev is not initialized in this folder.\n"));
|
|
8863
9015
|
await init({ analyze: true, git: true });
|
|
8864
9016
|
}
|
|
8865
9017
|
await start({ skipGovernanceBanner: !wasInitialized });
|
|
@@ -8867,7 +9019,7 @@ program.name("archon").description("Local-first AI-powered development governanc
|
|
|
8867
9019
|
program.command("login").description("Authenticate with ArchonDev").option("-p, --provider <provider>", "OAuth provider (github or google)", "github").action(async (options) => {
|
|
8868
9020
|
const provider = options.provider;
|
|
8869
9021
|
if (provider !== "github" && provider !== "google") {
|
|
8870
|
-
console.error(
|
|
9022
|
+
console.error(chalk18.red('Invalid provider. Use "github" or "google"'));
|
|
8871
9023
|
process.exit(1);
|
|
8872
9024
|
}
|
|
8873
9025
|
await login(provider);
|
|
@@ -8966,6 +9118,13 @@ preferencesCommand.command("execution-set <key> <value>").description("Set execu
|
|
|
8966
9118
|
preferencesCommand.action(async () => {
|
|
8967
9119
|
await showPreferences();
|
|
8968
9120
|
});
|
|
9121
|
+
var policyCommand = program.command("policy").description("Manage runtime policy (approval, sentinel, routing profile)");
|
|
9122
|
+
policyCommand.command("set <scope> <value>").description("Set policy value: scope in [approval|sentinel|routing]").action(async (scope, value) => {
|
|
9123
|
+
await setPolicy(scope, value);
|
|
9124
|
+
});
|
|
9125
|
+
policyCommand.action(async () => {
|
|
9126
|
+
await showPolicy();
|
|
9127
|
+
});
|
|
8969
9128
|
program.command("watch").description("Live TUI dashboard showing atoms, credits, and activity").action(async () => {
|
|
8970
9129
|
await watch();
|
|
8971
9130
|
});
|
|
@@ -9065,7 +9224,7 @@ cleanupCmd.command("check").description("Analyze workspace for bloat and mainten
|
|
|
9065
9224
|
cleanupCmd.command("run").description("Execute cleanup (archive old entries, remove stale files)").action(cleanupRun);
|
|
9066
9225
|
cleanupCmd.command("auto").description("Enable/disable automatic cleanup checks").argument("[action]", "enable, disable, or status", "status").action(async (action) => {
|
|
9067
9226
|
if (action !== "enable" && action !== "disable" && action !== "status") {
|
|
9068
|
-
console.error(
|
|
9227
|
+
console.error(chalk18.red("Invalid action. Use: enable, disable, or status"));
|
|
9069
9228
|
process.exit(1);
|
|
9070
9229
|
}
|
|
9071
9230
|
await cleanupAuto(action);
|