archondev 2.14.0 → 2.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/README.md +2 -0
  2. package/dist/{auth-2E4VORGY.js → auth-KUFS3PBS.js} +3 -3
  3. package/dist/{bug-KUMC6HSR.js → bug-BJH4X5LI.js} +3 -2
  4. package/dist/{chunk-3JURZUY7.js → chunk-2QIXLBAC.js} +1 -1
  5. package/dist/{chunk-P666JE3G.js → chunk-54ATBLYE.js} +1 -1
  6. package/dist/{chunk-NLW75APJ.js → chunk-DUJOT5B6.js} +7 -7
  7. package/dist/{chunk-DQE6E436.js → chunk-E7ZTIAQM.js} +63 -28
  8. package/dist/{chunk-JWY56A3X.js → chunk-FA2GAZ7L.js} +8 -12
  9. package/dist/{chunk-P4KDRIFM.js → chunk-HTJOCKVV.js} +4 -4
  10. package/dist/{chunk-CJ3CFP52.js → chunk-LHCXE6UL.js} +71 -21
  11. package/dist/{chunk-35AOCHTE.js → chunk-LPSS2U5V.js} +7 -3
  12. package/dist/{chunk-SVU7MLG6.js → chunk-SUGIWSCB.js} +24 -5
  13. package/dist/{chunk-KMVMRFQ5.js → chunk-TRLP7RMZ.js} +11 -1
  14. package/dist/{chunk-7NSVJFIZ.js → chunk-WZIRUPMP.js} +1 -1
  15. package/dist/{config-BBQW726O.js → config-USLUSE4N.js} +2 -1
  16. package/dist/{execute-MAFSY5FY.js → execute-73QW4ZEZ.js} +3 -3
  17. package/dist/index.js +356 -104
  18. package/dist/{init-6EXMDCWC.js → init-PSMJLDEZ.js} +1 -1
  19. package/dist/{interviewer-SULVHQW6.js → interviewer-Q6PFSAGT.js} +2 -1
  20. package/dist/{keys-5Y7KQAHI.js → keys-VLK3EWSN.js} +3 -2
  21. package/dist/{list-C224HUQ6.js → list-MMKB5TGX.js} +3 -3
  22. package/dist/{parallel-4NN4ONOH.js → parallel-WHFKRBPR.js} +3 -3
  23. package/dist/{plan-7DPVPUNK.js → plan-X77BUKNE.js} +4 -2
  24. package/dist/{preferences-32J3GUTY.js → preferences-TWEK2RWY.js} +4 -4
  25. package/dist/{tier-selection-3N4BZYWA.js → tier-selection-Z2RFHZUX.js} +3 -2
  26. package/package.json +1 -1
package/README.md CHANGED
@@ -99,6 +99,8 @@ Copy governance files into any project. Works with your existing AI tools: **Cur
99
99
  | `archon cleanup run` | Execute cleanup tasks |
100
100
  | `archon cleanup auto [enable\|disable]` | Enable/disable auto cleanup on start |
101
101
 
102
+ **Tip:** Use `archon plan --edit` to adjust title and acceptance criteria before planning.
103
+
102
104
  ## Pricing
103
105
 
104
106
  | Tier | Cost | What You Get |
@@ -2,10 +2,10 @@ import {
2
2
  login,
3
3
  logout,
4
4
  status
5
- } from "./chunk-JWY56A3X.js";
5
+ } from "./chunk-FA2GAZ7L.js";
6
+ import "./chunk-DUJOT5B6.js";
7
+ import "./chunk-SUGIWSCB.js";
6
8
  import "./chunk-M4LGRTLC.js";
7
- import "./chunk-NLW75APJ.js";
8
- import "./chunk-SVU7MLG6.js";
9
9
  import "./chunk-QGM4M3NI.js";
10
10
  export {
11
11
  login,
@@ -1,10 +1,11 @@
1
1
  import {
2
2
  bugReport
3
- } from "./chunk-3JURZUY7.js";
3
+ } from "./chunk-2QIXLBAC.js";
4
4
  import "./chunk-ER4ADSWH.js";
5
5
  import "./chunk-NIKN37AY.js";
6
6
  import "./chunk-LXXTCZ2Q.js";
7
- import "./chunk-SVU7MLG6.js";
7
+ import "./chunk-SUGIWSCB.js";
8
+ import "./chunk-M4LGRTLC.js";
8
9
  import "./chunk-QGM4M3NI.js";
9
10
  export {
10
11
  bugReport
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-ER4ADSWH.js";
5
5
  import {
6
6
  loadConfig
7
- } from "./chunk-SVU7MLG6.js";
7
+ } from "./chunk-SUGIWSCB.js";
8
8
 
9
9
  // src/cli/bug.ts
10
10
  import chalk from "chalk";
@@ -13,7 +13,7 @@ function isInitialized(cwd) {
13
13
  if (existsSync(archMdPath)) {
14
14
  try {
15
15
  const content = readFileSync(archMdPath, "utf-8");
16
- return content.startsWith("---") && content.includes("version:") && content.includes("qualityLevel:");
16
+ return content.startsWith("---") && content.includes("version:") && (content.includes("systemGoals:") || content.includes("components:") || content.includes("profile:"));
17
17
  } catch {
18
18
  return false;
19
19
  }
@@ -2,7 +2,7 @@ import {
2
2
  getApiUrl,
3
3
  loadConfig,
4
4
  saveConfig
5
- } from "./chunk-SVU7MLG6.js";
5
+ } from "./chunk-SUGIWSCB.js";
6
6
 
7
7
  // src/cli/tier-selection.ts
8
8
  import chalk from "chalk";
@@ -43,9 +43,9 @@ async function offerReauthentication(reason) {
43
43
  return false;
44
44
  }
45
45
  console.log();
46
- const { login } = await import("./auth-2E4VORGY.js");
46
+ const { login } = await import("./auth-KUFS3PBS.js");
47
47
  await login({ skipTierSelection: true });
48
- const { loadConfig: reload } = await import("./config-BBQW726O.js");
48
+ const { loadConfig: reload } = await import("./config-USLUSE4N.js");
49
49
  const config = await reload();
50
50
  return !!(config && config.accessToken);
51
51
  }
@@ -207,7 +207,7 @@ async function promptForApiKey() {
207
207
  return;
208
208
  }
209
209
  if (provider) {
210
- const { addKey } = await import("./keys-5Y7KQAHI.js");
210
+ const { addKey } = await import("./keys-VLK3EWSN.js");
211
211
  await addKey(provider, {});
212
212
  console.log();
213
213
  const addAnother = await promptYesNo("Would you like to add another API key?", false);
@@ -219,7 +219,7 @@ async function promptForApiKey() {
219
219
  async function createCheckoutSession(amountCents) {
220
220
  const spinner = ora("Preparing checkout...").start();
221
221
  try {
222
- const { ensureValidSession, loadConfig: loadConfig2 } = await import("./config-BBQW726O.js");
222
+ const { ensureValidSession, loadConfig: loadConfig2 } = await import("./config-USLUSE4N.js");
223
223
  let config = await ensureValidSession();
224
224
  if (!config || !config.accessToken || !config.userId) {
225
225
  spinner.stop();
@@ -367,7 +367,7 @@ Switching to ${selectedName}...`));
367
367
  var showTierSwitchMenu = showUpgradeMenu;
368
368
  async function updateUserTier(tier, _alreadyRetried = false) {
369
369
  try {
370
- const { ensureValidSession, loadConfig: reload } = await import("./config-BBQW726O.js");
370
+ const { ensureValidSession, loadConfig: reload } = await import("./config-USLUSE4N.js");
371
371
  let config = await ensureValidSession();
372
372
  if (!config || !config.accessToken) {
373
373
  if (_alreadyRetried) {
@@ -455,7 +455,7 @@ function promptYesNo(question, defaultValue) {
455
455
  }
456
456
  async function showKeyManagementMenu() {
457
457
  const { keyManager } = await import("./keys-SXJ6MKPY.js");
458
- const { listKeys, addKey, removeKey } = await import("./keys-5Y7KQAHI.js");
458
+ const { listKeys, addKey, removeKey } = await import("./keys-VLK3EWSN.js");
459
459
  console.log();
460
460
  console.log(chalk.bold("API Key Management"));
461
461
  console.log(chalk.dim("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  UsageRecorder,
3
- loadAtom
4
- } from "./chunk-CJ3CFP52.js";
3
+ loadAtom,
4
+ loadRoleOverrides
5
+ } from "./chunk-LHCXE6UL.js";
5
6
  import {
6
7
  ArchitectureParser
7
8
  } from "./chunk-5EVHUDQX.js";
@@ -12,14 +13,15 @@ import {
12
13
  AnthropicClient,
13
14
  getDefaultModel
14
15
  } from "./chunk-NIKN37AY.js";
16
+ import {
17
+ createAuthedSupabaseClient,
18
+ getAuthToken,
19
+ loadConfig
20
+ } from "./chunk-SUGIWSCB.js";
15
21
  import {
16
22
  SUPABASE_ANON_KEY,
17
23
  SUPABASE_URL
18
24
  } from "./chunk-M4LGRTLC.js";
19
- import {
20
- getAuthToken,
21
- loadConfig
22
- } from "./chunk-SVU7MLG6.js";
23
25
  import {
24
26
  __commonJS,
25
27
  __require,
@@ -2854,15 +2856,13 @@ import chalk3 from "chalk";
2854
2856
  import { existsSync as existsSync8 } from "fs";
2855
2857
  import { readFile as readFile7, writeFile as writeFile4 } from "fs/promises";
2856
2858
  import { join as join3 } from "path";
2857
- import { execSync as execSync3 } from "child_process";
2859
+ import { spawnSync as spawnSync2 } from "child_process";
2858
2860
  import { createInterface } from "readline";
2859
- import { createClient as createClient2 } from "@supabase/supabase-js";
2860
2861
 
2861
2862
  // src/cli/cloud.ts
2862
2863
  import chalk from "chalk";
2863
- import { createClient } from "@supabase/supabase-js";
2864
- function getClient() {
2865
- return createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
2864
+ function getClient(accessToken) {
2865
+ return createAuthedSupabaseClient(SUPABASE_URL, SUPABASE_ANON_KEY, accessToken);
2866
2866
  }
2867
2867
  async function cloudStatus() {
2868
2868
  const config = await loadConfig();
@@ -2871,7 +2871,7 @@ async function cloudStatus() {
2871
2871
  console.error(chalk.red('Not authenticated. Run "archon login" first.'));
2872
2872
  process.exit(1);
2873
2873
  }
2874
- const client = getClient();
2874
+ const client = getClient(authToken);
2875
2875
  const { data, error } = await client.from("cloud_executions").select("*").order("created_at", { ascending: false }).limit(20);
2876
2876
  if (error) {
2877
2877
  console.error(chalk.red("Failed to fetch cloud executions:"), error.message);
@@ -2907,7 +2907,7 @@ async function cloudCancel(executionId) {
2907
2907
  console.error(chalk.red('Not authenticated. Run "archon login" first.'));
2908
2908
  process.exit(1);
2909
2909
  }
2910
- const client = getClient();
2910
+ const client = getClient(authToken);
2911
2911
  const { data: existing, error: fetchError } = await client.from("cloud_executions").select("id, status").eq("id", executionId).single();
2912
2912
  if (fetchError || !existing) {
2913
2913
  console.error(chalk.red(`Execution ${executionId} not found.`));
@@ -2931,7 +2931,7 @@ async function cloudLogs(executionId) {
2931
2931
  console.error(chalk.red('Not authenticated. Run "archon login" first.'));
2932
2932
  process.exit(1);
2933
2933
  }
2934
- const client = getClient();
2934
+ const client = getClient(authToken);
2935
2935
  const { data, error } = await client.from("cloud_executions").select("id, atom_id, status, logs").eq("id", executionId).single();
2936
2936
  if (error || !data) {
2937
2937
  console.error(chalk.red(`Execution ${executionId} not found.`));
@@ -2960,7 +2960,7 @@ async function queueCloudExecution(atomId, projectName, options) {
2960
2960
  if (!authToken) {
2961
2961
  throw new Error('Not authenticated. Run "archon login" first.');
2962
2962
  }
2963
- const client = getClient();
2963
+ const client = getClient(authToken);
2964
2964
  const insertData = {
2965
2965
  atom_id: atomId,
2966
2966
  project_name: projectName,
@@ -4681,6 +4681,33 @@ var TrackedExecutorAgent = class {
4681
4681
  }
4682
4682
  };
4683
4683
 
4684
+ // src/core/git/rollback.ts
4685
+ import { spawnSync } from "child_process";
4686
+ function rollbackFiles(cwd, files) {
4687
+ if (files.length === 0) return;
4688
+ const tracked = [];
4689
+ const untracked = [];
4690
+ for (const file of files) {
4691
+ const result = spawnSync("git", ["ls-files", "--error-unmatch", file], { cwd, stdio: "pipe" });
4692
+ if (result.status === 0) {
4693
+ tracked.push(file);
4694
+ } else {
4695
+ untracked.push(file);
4696
+ }
4697
+ }
4698
+ if (tracked.length > 0) {
4699
+ const checkout = spawnSync("git", ["checkout", "--", ...tracked], { cwd, stdio: "pipe" });
4700
+ if (checkout.status !== 0) {
4701
+ throw new Error(checkout.stderr?.toString() || "git checkout failed");
4702
+ }
4703
+ }
4704
+ const cleanTargets = untracked.length > 0 ? untracked : files;
4705
+ const clean = spawnSync("git", ["clean", "-f", "--", ...cleanTargets], { cwd, stdio: "pipe" });
4706
+ if (clean.status !== 0) {
4707
+ throw new Error(clean.stderr?.toString() || "git clean failed");
4708
+ }
4709
+ }
4710
+
4684
4711
  // src/core/environments/types.ts
4685
4712
  var DEFAULT_ENVIRONMENTS = {
4686
4713
  development: {
@@ -4895,9 +4922,9 @@ function createPrompt() {
4895
4922
  }
4896
4923
  async function execute(atomId, options) {
4897
4924
  if (options.parallel && options.parallel.length > 0) {
4898
- const { parallelExecute } = await import("./parallel-4NN4ONOH.js");
4925
+ const { parallelExecute } = await import("./parallel-WHFKRBPR.js");
4899
4926
  const allAtomIds = [atomId, ...options.parallel];
4900
- await parallelExecute(allAtomIds);
4927
+ await parallelExecute(allAtomIds, { skipGates: options.skipGates === true });
4901
4928
  return;
4902
4929
  }
4903
4930
  const prompt = createPrompt();
@@ -5042,14 +5069,16 @@ ${conflictReport.blockerCount} blocking conflict(s) found.`));
5042
5069
  console.log(chalk3.blue("\n\u{1F680} Executing plan..."));
5043
5070
  const config = await loadConfig();
5044
5071
  let billingContext;
5045
- if (config.userId) {
5046
- const supabase = createClient2(SUPABASE_URL, SUPABASE_ANON_KEY);
5072
+ if (config.userId && config.accessToken) {
5073
+ const supabase = createAuthedSupabaseClient(SUPABASE_URL, SUPABASE_ANON_KEY, config.accessToken);
5047
5074
  billingContext = {
5048
5075
  userId: config.userId,
5049
5076
  supabase
5050
5077
  };
5051
5078
  }
5052
- const executor = billingContext ? new TrackedExecutorAgent({ billing: billingContext }) : new ExecutorAgent();
5079
+ const roleOverrides = await loadRoleOverrides(cwd);
5080
+ const executorConfig = roleOverrides?.executor?.model ? { model: roleOverrides.executor.model } : void 0;
5081
+ const executor = billingContext ? new TrackedExecutorAgent({ billing: billingContext, clientConfig: executorConfig }) : new ExecutorAgent(executorConfig);
5053
5082
  if (billingContext && executor instanceof TrackedExecutorAgent) {
5054
5083
  const balanceCheck = await executor.checkBalance();
5055
5084
  if (!balanceCheck.sufficient && balanceCheck.tier === "CREDITS") {
@@ -5106,10 +5135,11 @@ Running quality gates for ${targetEnvName}...`));
5106
5135
  console.log(chalk3.red("\n\u274C Quality gates failed"));
5107
5136
  console.log(chalk3.yellow("Rolling back changes..."));
5108
5137
  try {
5109
- execSync3("git checkout -- .", { cwd, stdio: "pipe" });
5110
- console.log(chalk3.yellow("Changes rolled back."));
5111
- } catch {
5138
+ rollbackFiles(cwd, filesChanged);
5139
+ console.log(chalk3.yellow("Changes rolled back (scoped to atom files)."));
5140
+ } catch (error) {
5112
5141
  console.log(chalk3.red("Failed to rollback. Please manually revert changes."));
5142
+ console.log(chalk3.dim(error instanceof Error ? error.message : "Unknown rollback error"));
5113
5143
  }
5114
5144
  transitionAtom(atom, "FAILED");
5115
5145
  atom.errorMessage = `Quality gate failed: ${gateResult.failedAt}`;
@@ -5132,8 +5162,14 @@ Running quality gates for ${targetEnvName}...`));
5132
5162
  console.log(chalk3.dim("\nCommitting changes..."));
5133
5163
  try {
5134
5164
  const commitMessage = `feat: [${atom.externalId}] - ${atom.title}`;
5135
- execSync3(`git add -A`, { cwd, stdio: "pipe" });
5136
- execSync3(`git commit -m "${commitMessage}"`, { cwd, stdio: "pipe" });
5165
+ const addResult = spawnSync2("git", ["add", "-A"], { cwd, stdio: "pipe" });
5166
+ if (addResult.status !== 0) {
5167
+ throw new Error(addResult.stderr?.toString() || "git add failed");
5168
+ }
5169
+ const commitResult = spawnSync2("git", ["commit", "-m", commitMessage], { cwd, stdio: "pipe" });
5170
+ if (commitResult.status !== 0) {
5171
+ throw new Error(commitResult.stderr?.toString() || "git commit failed");
5172
+ }
5137
5173
  console.log(chalk3.green(`\u2713 Committed: ${commitMessage}`));
5138
5174
  } catch (error) {
5139
5175
  console.log(chalk3.yellow("No changes to commit or git commit failed."));
@@ -5223,13 +5259,12 @@ async function watchCloudExecution(executionId) {
5223
5259
  const pollInterval = 5e3;
5224
5260
  let lastLogCount = 0;
5225
5261
  const poll = async () => {
5226
- const { loadConfig: loadConfig2, getAuthToken: getAuthToken2 } = await import("./config-BBQW726O.js");
5227
- const { createClient: createClient3 } = await import("@supabase/supabase-js");
5262
+ const { loadConfig: loadConfig2, getAuthToken: getAuthToken2 } = await import("./config-USLUSE4N.js");
5228
5263
  const { SUPABASE_URL: SUPABASE_URL2, SUPABASE_ANON_KEY: SUPABASE_ANON_KEY2 } = await import("./constants-AHP5F7HW.js");
5229
5264
  const config = await loadConfig2();
5230
5265
  const authToken = getAuthToken2(config);
5231
5266
  if (!authToken) return true;
5232
- const client = createClient3(SUPABASE_URL2, SUPABASE_ANON_KEY2);
5267
+ const client = createAuthedSupabaseClient(SUPABASE_URL2, SUPABASE_ANON_KEY2, authToken);
5233
5268
  const { data } = await client.from("cloud_executions").select("status, logs, error_message, result_branch, result_pr_url").eq("id", executionId).single();
5234
5269
  if (!data) return true;
5235
5270
  const logs = data.logs ?? [];
@@ -1,20 +1,20 @@
1
- import {
2
- SUPABASE_ANON_KEY,
3
- SUPABASE_URL
4
- } from "./chunk-M4LGRTLC.js";
5
1
  import {
6
2
  handleTierSetup,
7
3
  promptTierSelection,
8
4
  updateUserTier
9
- } from "./chunk-NLW75APJ.js";
5
+ } from "./chunk-DUJOT5B6.js";
10
6
  import {
11
7
  clearConfig,
8
+ createPkceSupabaseClient,
12
9
  loadConfig,
13
10
  saveConfig
14
- } from "./chunk-SVU7MLG6.js";
11
+ } from "./chunk-SUGIWSCB.js";
12
+ import {
13
+ SUPABASE_ANON_KEY,
14
+ SUPABASE_URL
15
+ } from "./chunk-M4LGRTLC.js";
15
16
 
16
17
  // src/cli/auth.ts
17
- import { createClient } from "@supabase/supabase-js";
18
18
  import { createServer } from "http";
19
19
  import { URL } from "url";
20
20
  import readline from "readline";
@@ -24,11 +24,7 @@ import ora from "ora";
24
24
  var CALLBACK_PORT = 54321;
25
25
  var CALLBACK_URL = `http://localhost:${CALLBACK_PORT}/callback`;
26
26
  function getAuthClient() {
27
- return createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
28
- auth: {
29
- flowType: "pkce"
30
- }
31
- });
27
+ return createPkceSupabaseClient(SUPABASE_URL, SUPABASE_ANON_KEY);
32
28
  }
33
29
  async function login(providerOrOptions = "github") {
34
30
  const options = typeof providerOrOptions === "string" ? { provider: providerOrOptions } : providerOrOptions;
@@ -14,12 +14,12 @@ import {
14
14
  } from "./chunk-RDG5BUED.js";
15
15
  import {
16
16
  login
17
- } from "./chunk-JWY56A3X.js";
17
+ } from "./chunk-FA2GAZ7L.js";
18
18
  import {
19
19
  getApiUrl,
20
20
  getAuthToken,
21
21
  loadConfig
22
- } from "./chunk-SVU7MLG6.js";
22
+ } from "./chunk-SUGIWSCB.js";
23
23
 
24
24
  // src/cli/preferences.ts
25
25
  import chalk from "chalk";
@@ -1071,7 +1071,7 @@ async function manageApiKeys() {
1071
1071
  if (removeIndex >= 0 && removeIndex < providers.length) {
1072
1072
  const providerToRemove = providers[removeIndex];
1073
1073
  if (providerToRemove) {
1074
- const { removeKey } = await import("./keys-5Y7KQAHI.js");
1074
+ const { removeKey } = await import("./keys-VLK3EWSN.js");
1075
1075
  await removeKey(providerToRemove);
1076
1076
  }
1077
1077
  }
@@ -1079,7 +1079,7 @@ async function manageApiKeys() {
1079
1079
  }
1080
1080
  const provider = providerMap[choice];
1081
1081
  if (provider) {
1082
- const { addKey } = await import("./keys-5Y7KQAHI.js");
1082
+ const { addKey } = await import("./keys-VLK3EWSN.js");
1083
1083
  await addKey(provider);
1084
1084
  }
1085
1085
  }
@@ -13,22 +13,22 @@ import {
13
13
  import {
14
14
  KeyManager
15
15
  } from "./chunk-RDG5BUED.js";
16
+ import {
17
+ createAuthedSupabaseClient,
18
+ isAuthenticated,
19
+ loadConfig
20
+ } from "./chunk-SUGIWSCB.js";
16
21
  import {
17
22
  SUPABASE_ANON_KEY,
18
23
  SUPABASE_URL
19
24
  } from "./chunk-M4LGRTLC.js";
20
- import {
21
- isAuthenticated,
22
- loadConfig
23
- } from "./chunk-SVU7MLG6.js";
24
25
 
25
26
  // src/cli/plan.ts
26
27
  import chalk from "chalk";
27
- import { existsSync } from "fs";
28
- import { readFile, writeFile, mkdir } from "fs/promises";
29
- import { join } from "path";
28
+ import { existsSync as existsSync2 } from "fs";
29
+ import { readFile as readFile2, writeFile, mkdir } from "fs/promises";
30
+ import { join as join2 } from "path";
30
31
  import { createInterface } from "readline";
31
- import { createClient } from "@supabase/supabase-js";
32
32
 
33
33
  // src/agents/sentinel.ts
34
34
  var SYSTEM_PROMPT = `You are the Sentinel, a paranoid and skeptical code reviewer responsible for finding issues in implementation plans.
@@ -732,6 +732,31 @@ var TrackedAdversarialPlanner = class {
732
732
  }
733
733
  };
734
734
 
735
+ // src/core/config/roles.ts
736
+ import { existsSync } from "fs";
737
+ import { readFile } from "fs/promises";
738
+ import { join } from "path";
739
+ import yaml from "yaml";
740
+ async function loadRoleOverrides(cwd = process.cwd()) {
741
+ const candidates = [
742
+ join(cwd, ".archon", "config.yaml"),
743
+ join(cwd, "archon.config.yaml")
744
+ ];
745
+ for (const path of candidates) {
746
+ if (!existsSync(path)) continue;
747
+ try {
748
+ const content = await readFile(path, "utf-8");
749
+ const parsed = yaml.parse(content);
750
+ if (parsed?.roles) {
751
+ return parsed.roles;
752
+ }
753
+ } catch {
754
+ continue;
755
+ }
756
+ }
757
+ return null;
758
+ }
759
+
735
760
  // src/cli/plan.ts
736
761
  var ATOMS_DIR = ".archon/atoms";
737
762
  function createPrompt() {
@@ -753,8 +778,8 @@ async function plan(description, options) {
753
778
  console.log(chalk.yellow('Not authenticated. Run "archon login" first.'));
754
779
  console.log(chalk.dim("For local development, you can continue without authentication."));
755
780
  }
756
- const archPath = join(process.cwd(), "ARCHITECTURE.md");
757
- if (!existsSync(archPath)) {
781
+ const archPath = join2(process.cwd(), "ARCHITECTURE.md");
782
+ if (!existsSync2(archPath)) {
758
783
  console.error(chalk.red('ARCHITECTURE.md not found. Run "archon init" first.'));
759
784
  process.exit(1);
760
785
  }
@@ -779,6 +804,26 @@ async function plan(description, options) {
779
804
  }
780
805
  process.exit(1);
781
806
  }
807
+ if (options.edit) {
808
+ console.log(chalk.dim("\nEdit mode: update title and acceptance criteria (press Enter to keep current)."));
809
+ const newTitle = await prompt.ask(`Title [${atom.title}]: `);
810
+ if (newTitle.trim()) {
811
+ atom.title = newTitle.trim();
812
+ }
813
+ const acCurrent = atom.acceptanceCriteria.join(", ");
814
+ const newAc = await prompt.ask(`Acceptance criteria (comma-separated) [${acCurrent}]: `);
815
+ if (newAc.trim()) {
816
+ atom.acceptanceCriteria = newAc.split(",").map((ac) => ac.trim()).filter(Boolean);
817
+ }
818
+ const revalidation = validateAtom(atom);
819
+ if (!revalidation.valid) {
820
+ console.error(chalk.red("Invalid atom after edits:"));
821
+ for (const error of revalidation.errors) {
822
+ console.error(chalk.red(` - ${error.field}: ${error.message}`));
823
+ }
824
+ process.exit(1);
825
+ }
826
+ }
782
827
  console.log(chalk.blue(`
783
828
  Atom created: ${atom.externalId}`));
784
829
  console.log(chalk.dim(`Title: ${atom.title}`));
@@ -804,14 +849,17 @@ Atom saved: ${atom.externalId}`));
804
849
  console.log(chalk.dim("Architect will generate a plan, Sentinel will validate it.\n"));
805
850
  const config = await loadConfig();
806
851
  let billingContext;
807
- if (config.userId) {
808
- const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY);
852
+ if (config.userId && config.accessToken) {
853
+ const supabase = createAuthedSupabaseClient(SUPABASE_URL, SUPABASE_ANON_KEY, config.accessToken);
809
854
  billingContext = {
810
855
  userId: config.userId,
811
856
  supabase
812
857
  };
813
858
  }
814
- const planner = billingContext ? new TrackedAdversarialPlanner({ apiKey, billing: billingContext }) : new AdversarialPlanner({ apiKey });
859
+ const roleOverrides = await loadRoleOverrides(process.cwd());
860
+ const architectConfig = roleOverrides?.architect?.model ? { model: roleOverrides.architect.model } : void 0;
861
+ const sentinelConfig = roleOverrides?.sentinel?.model ? { model: roleOverrides.sentinel.model } : void 0;
862
+ const planner = billingContext ? new TrackedAdversarialPlanner({ apiKey, billing: billingContext, architectConfig, sentinelConfig }) : new AdversarialPlanner({ apiKey, architectConfig, sentinelConfig });
815
863
  if (billingContext && planner instanceof TrackedAdversarialPlanner) {
816
864
  const balanceCheck = await planner.checkBalance();
817
865
  if (!balanceCheck.sufficient && balanceCheck.tier === "CREDITS") {
@@ -925,24 +973,24 @@ function displayPlan(plan2) {
925
973
  console.log(chalk.bold("\nComplexity:"), plan2.estimated_complexity);
926
974
  }
927
975
  async function saveAtom(atom) {
928
- const atomsDir = join(process.cwd(), ATOMS_DIR);
929
- if (!existsSync(atomsDir)) {
976
+ const atomsDir = join2(process.cwd(), ATOMS_DIR);
977
+ if (!existsSync2(atomsDir)) {
930
978
  await mkdir(atomsDir, { recursive: true });
931
979
  }
932
- const atomFile = join(atomsDir, `${atom.externalId}.json`);
980
+ const atomFile = join2(atomsDir, `${atom.externalId}.json`);
933
981
  await writeFile(atomFile, JSON.stringify(atom, null, 2));
934
982
  }
935
983
  async function loadAtom(atomId) {
936
- const atomFile = join(process.cwd(), ATOMS_DIR, `${atomId}.json`);
937
- if (!existsSync(atomFile)) {
984
+ const atomFile = join2(process.cwd(), ATOMS_DIR, `${atomId}.json`);
985
+ if (!existsSync2(atomFile)) {
938
986
  return null;
939
987
  }
940
- const content = await readFile(atomFile, "utf-8");
988
+ const content = await readFile2(atomFile, "utf-8");
941
989
  return JSON.parse(content);
942
990
  }
943
991
  async function listLocalAtoms() {
944
- const atomsDir = join(process.cwd(), ATOMS_DIR);
945
- if (!existsSync(atomsDir)) {
992
+ const atomsDir = join2(process.cwd(), ATOMS_DIR);
993
+ if (!existsSync2(atomsDir)) {
946
994
  return [];
947
995
  }
948
996
  const { readdir } = await import("fs/promises");
@@ -961,7 +1009,9 @@ async function listLocalAtoms() {
961
1009
 
962
1010
  export {
963
1011
  UsageRecorder,
1012
+ loadRoleOverrides,
964
1013
  plan,
1014
+ parseAtomDescription,
965
1015
  loadAtom,
966
1016
  listLocalAtoms
967
1017
  };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  listLocalAtoms,
3
3
  loadAtom
4
- } from "./chunk-CJ3CFP52.js";
4
+ } from "./chunk-LHCXE6UL.js";
5
5
 
6
6
  // src/cli/parallel.ts
7
7
  import chalk from "chalk";
@@ -359,7 +359,7 @@ async function saveParallelState(cwd, state) {
359
359
  const statePath = join2(cwd, PARALLEL_STATE_FILE);
360
360
  await writeFile(statePath, JSON.stringify(state, null, 2));
361
361
  }
362
- async function parallelExecute(atomIds) {
362
+ async function parallelExecute(atomIds, options = {}) {
363
363
  const cwd = process.cwd();
364
364
  const manager = new WorktreeManager(cwd);
365
365
  console.log(chalk.blue(`
@@ -397,7 +397,11 @@ async function parallelExecute(atomIds) {
397
397
  execution.startedAt = (/* @__PURE__ */ new Date()).toISOString();
398
398
  await saveParallelState(cwd, state);
399
399
  return new Promise((resolve) => {
400
- const child = spawn("npx", ["archon", "execute", execution.atomId, "--skip-gates"], {
400
+ const args = [process.argv[1] ?? "archon", "execute", execution.atomId];
401
+ if (options.skipGates) {
402
+ args.push("--skip-gates");
403
+ }
404
+ const child = spawn(process.execPath, args, {
401
405
  cwd: execution.worktreePath,
402
406
  stdio: "pipe"
403
407
  });
@@ -1,13 +1,32 @@
1
+ import {
2
+ SUPABASE_ANON_KEY,
3
+ SUPABASE_URL
4
+ } from "./chunk-M4LGRTLC.js";
5
+
1
6
  // src/cli/config.ts
2
7
  import { homedir } from "os";
3
8
  import { join } from "path";
4
9
  import { readFile, writeFile, mkdir, chmod, unlink } from "fs/promises";
5
10
  import { existsSync } from "fs";
11
+
12
+ // src/core/supabase/client.ts
6
13
  import { createClient } from "@supabase/supabase-js";
14
+ function createPkceSupabaseClient(supabaseUrl, supabaseAnonKey) {
15
+ return createClient(supabaseUrl, supabaseAnonKey, {
16
+ auth: {
17
+ flowType: "pkce"
18
+ }
19
+ });
20
+ }
21
+ function createAuthedSupabaseClient(supabaseUrl, supabaseAnonKey, accessToken) {
22
+ return createClient(supabaseUrl, supabaseAnonKey, {
23
+ global: { headers: { Authorization: `Bearer ${accessToken}` } }
24
+ });
25
+ }
26
+
27
+ // src/cli/config.ts
7
28
  var CONFIG_DIR = join(homedir(), ".archon");
8
29
  var CONFIG_FILE = join(CONFIG_DIR, "config.json");
9
- var SUPABASE_URL = "https://yjdkcepktrbabmzhcmrt.supabase.co";
10
- var SUPABASE_ANON_KEY = "sb_publishable_XSGLVPfLZx-HA2uL6xsGCQ_KjAx2TIa";
11
30
  function getAuthToken(config) {
12
31
  return config.accessToken;
13
32
  }
@@ -72,9 +91,7 @@ async function refreshSession(config) {
72
91
  return false;
73
92
  }
74
93
  try {
75
- const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
76
- auth: { flowType: "pkce" }
77
- });
94
+ const supabase = createPkceSupabaseClient(SUPABASE_URL, SUPABASE_ANON_KEY);
78
95
  const { data, error } = await supabase.auth.refreshSession({
79
96
  refresh_token: config.refreshToken
80
97
  });
@@ -112,6 +129,8 @@ async function getCurrentUser() {
112
129
  }
113
130
 
114
131
  export {
132
+ createPkceSupabaseClient,
133
+ createAuthedSupabaseClient,
115
134
  getAuthToken,
116
135
  getApiUrl,
117
136
  loadConfig,
@@ -7,7 +7,7 @@ import {
7
7
  import {
8
8
  loadConfig,
9
9
  saveConfig
10
- } from "./chunk-SVU7MLG6.js";
10
+ } from "./chunk-SUGIWSCB.js";
11
11
 
12
12
  // src/cli/keys.ts
13
13
  import chalk from "chalk";
@@ -24,10 +24,20 @@ async function promptForKey(provider) {
24
24
  });
25
25
  return new Promise((resolve) => {
26
26
  const providerName = provider.charAt(0).toUpperCase() + provider.slice(1);
27
+ const rlAny = rl;
28
+ const originalWrite = rlAny._writeToOutput?.bind(rlAny);
29
+ rlAny._writeToOutput = (stringToWrite) => {
30
+ if (rlAny.stdoutMuted) {
31
+ rl.output.write("*");
32
+ return;
33
+ }
34
+ originalWrite?.(stringToWrite);
35
+ };
27
36
  rl.question(`Enter your ${providerName} API key: `, (answer) => {
28
37
  rl.close();
29
38
  resolve(answer.trim());
30
39
  });
40
+ rlAny.stdoutMuted = true;
31
41
  });
32
42
  }
33
43
  async function addKey(provider, options = {}) {