archondev 2.18.8 → 2.19.1

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
@@ -4,10 +4,10 @@ import {
4
4
  } from "./chunk-JF7JCK6H.js";
5
5
  import {
6
6
  createGeoCommand
7
- } from "./chunk-OAHFRSDS.js";
7
+ } from "./chunk-O3B6BE5D.js";
8
8
  import {
9
9
  bugReport
10
- } from "./chunk-2BCITFWP.js";
10
+ } from "./chunk-DCIIYVJW.js";
11
11
  import {
12
12
  reviewAnalyze,
13
13
  reviewExport,
@@ -19,8 +19,8 @@ import {
19
19
  reviewShow,
20
20
  reviewStatus,
21
21
  reviewUpdate
22
- } from "./chunk-BFPWDOMA.js";
23
- import "./chunk-HGLPIM7J.js";
22
+ } from "./chunk-M6GNIN64.js";
23
+ import "./chunk-KG35EHZY.js";
24
24
  import {
25
25
  resetPreferences,
26
26
  setExecutionPreference,
@@ -46,13 +46,13 @@ import {
46
46
  parallelRunWaves,
47
47
  parallelSchedule,
48
48
  parallelStatus
49
- } from "./chunk-BPYTLJOS.js";
49
+ } from "./chunk-QTBRLNZQ.js";
50
50
  import {
51
51
  DependencyParser,
52
52
  EnvironmentConfigLoader,
53
53
  EnvironmentValidator,
54
54
  execute
55
- } from "./chunk-SLUOXPMX.js";
55
+ } from "./chunk-OREGEFTF.js";
56
56
  import {
57
57
  cloudCancel,
58
58
  cloudLogs,
@@ -60,15 +60,19 @@ import {
60
60
  } from "./chunk-EBHHIUCB.js";
61
61
  import {
62
62
  list
63
- } from "./chunk-HANCO7VL.js";
63
+ } from "./chunk-YA562WHL.js";
64
64
  import {
65
65
  listLocalAtoms,
66
66
  loadAtom,
67
67
  plan
68
- } from "./chunk-AFC2XMZS.js";
69
- import "./chunk-5CFGPXQ3.js";
70
- import "./chunk-5BYCJAFM.js";
71
- import "./chunk-HJARQDQR.js";
68
+ } from "./chunk-ACFMKTDL.js";
69
+ import "./chunk-PCTP3LKJ.js";
70
+ import "./chunk-PJRQI5UN.js";
71
+ import {
72
+ err,
73
+ ok,
74
+ sleep
75
+ } from "./chunk-EIEU3IIY.js";
72
76
  import {
73
77
  createAuthedSupabaseClient
74
78
  } from "./chunk-Q3GIFHIQ.js";
@@ -107,8 +111,8 @@ import {
107
111
  import "./chunk-4VNS5WPM.js";
108
112
 
109
113
  // src/cli/index.ts
110
- import { Command as Command2 } from "commander";
111
- import chalk17 from "chalk";
114
+ import { Command as Command3 } from "commander";
115
+ import chalk18 from "chalk";
112
116
  import "dotenv/config";
113
117
 
114
118
  // src/cli/promote.ts
@@ -427,8 +431,8 @@ var ContextManager = class _ContextManager {
427
431
  async clearPendingAtoms(cwd) {
428
432
  const filePath = join2(cwd, _ContextManager.PENDING_ATOMS_FILE);
429
433
  if (existsSync2(filePath)) {
430
- const { unlink: unlink2 } = await import("fs/promises");
431
- await unlink2(filePath);
434
+ const { unlink: unlink4 } = await import("fs/promises");
435
+ await unlink4(filePath);
432
436
  }
433
437
  }
434
438
  };
@@ -2738,7 +2742,7 @@ async function start(options = {}) {
2738
2742
  }
2739
2743
  }
2740
2744
  if (!config.tier || config.tier === "FREE") {
2741
- const isFirstRun = !existsSync6(join6(cwd, ".archon")) && !existsSync6(join6(cwd, "ARCHITECTURE.md"));
2745
+ const isFirstRun = !existsSync6(join6(cwd, ".archon")) && resolveArchitecturePath(cwd).path === null;
2742
2746
  if (isFirstRun && !config.tierConfirmed) {
2743
2747
  console.log(chalk6.bold("How would you like to use ArchonDev?\n"));
2744
2748
  const selection = await promptTierSelection();
@@ -3030,6 +3034,18 @@ function displayGovernanceStatus(status2) {
3030
3034
  }
3031
3035
  console.log();
3032
3036
  }
3037
+ var ACTIVE_ARCH_PATH = join6(".archon", "active", "architecture.md");
3038
+ function resolveArchitecturePath(cwd) {
3039
+ const agdPath = join6(cwd, ACTIVE_ARCH_PATH);
3040
+ if (existsSync6(agdPath)) {
3041
+ return { path: agdPath, source: "agd" };
3042
+ }
3043
+ const legacyPath = join6(cwd, "ARCHITECTURE.md");
3044
+ if (existsSync6(legacyPath)) {
3045
+ return { path: legacyPath, source: "legacy" };
3046
+ }
3047
+ return { path: null, source: null };
3048
+ }
3033
3049
  function detectProjectState(cwd) {
3034
3050
  const sourceDirs = ["src", "lib", "app", "packages", "components", "pages", "api"];
3035
3051
  const sourceExtensions = [".ts", ".tsx", ".js", ".jsx", ".py", ".go", ".rs", ".java", ".rb", ".php"];
@@ -3053,7 +3069,7 @@ function detectProjectState(cwd) {
3053
3069
  if (!hasSourceFiles) {
3054
3070
  hasSourceFiles = projectMarkers.some((marker) => existsSync6(join6(cwd, marker)));
3055
3071
  }
3056
- const hasArchitecture = existsSync6(join6(cwd, "ARCHITECTURE.md"));
3072
+ const hasArchitecture = resolveArchitecturePath(cwd).path !== null;
3057
3073
  const hasProgress = existsSync6(join6(cwd, "progress.txt"));
3058
3074
  const hasReviewDb = existsSync6(join6(cwd, "docs", "code-review", "review-tasks.db"));
3059
3075
  let hasProgressEntries = false;
@@ -3102,9 +3118,9 @@ async function gatherGovernanceStatus(cwd) {
3102
3118
  dependencyRulesCount: 0,
3103
3119
  pendingAtomsCount: 0
3104
3120
  };
3105
- const archPath = join6(cwd, "ARCHITECTURE.md");
3106
- if (existsSync6(archPath)) {
3107
- const parser = new ArchitectureParser(archPath);
3121
+ const archInfo = resolveArchitecturePath(cwd);
3122
+ if (archInfo.path) {
3123
+ const parser = new ArchitectureParser(archInfo.path);
3108
3124
  const result = await parser.parse();
3109
3125
  if (result.success && result.schema) {
3110
3126
  status2.hasArchitecture = true;
@@ -3168,7 +3184,7 @@ async function handleNewProject(cwd, _state) {
3168
3184
  }
3169
3185
  if (intent.mode === "ad_hoc" && intent.confidence >= 0.7) {
3170
3186
  console.log(chalk6.dim("\n> Got it! Creating a task for this...\n"));
3171
- const { plan: plan2 } = await import("./plan-6AZ3U2DA.js");
3187
+ const { plan: plan2 } = await import("./plan-HCYXLSSD.js");
3172
3188
  await plan2(initialResponse, {});
3173
3189
  return;
3174
3190
  }
@@ -3192,7 +3208,7 @@ async function handleNewProject(cwd, _state) {
3192
3208
  break;
3193
3209
  case "2":
3194
3210
  console.log(chalk6.dim("\n> Creating a task for this...\n"));
3195
- const { plan: plan2 } = await import("./plan-6AZ3U2DA.js");
3211
+ const { plan: plan2 } = await import("./plan-HCYXLSSD.js");
3196
3212
  await plan2(initialResponse, {});
3197
3213
  break;
3198
3214
  case "3":
@@ -3220,9 +3236,9 @@ async function showNewProjectMenu(cwd) {
3220
3236
  await quickStart(cwd);
3221
3237
  break;
3222
3238
  case "3": {
3223
- const description = await prompt("Describe what you want to do");
3239
+ const description = await promptWithCommands("Describe what you want to do", { allowMultiline: true });
3224
3240
  if (description.trim()) {
3225
- const { plan: plan2 } = await import("./plan-6AZ3U2DA.js");
3241
+ const { plan: plan2 } = await import("./plan-HCYXLSSD.js");
3226
3242
  await plan2(description, {});
3227
3243
  }
3228
3244
  break;
@@ -3286,9 +3302,9 @@ async function runExploreFlow(cwd) {
3286
3302
  const choice = await promptWithCommands("Enter choice");
3287
3303
  switch (choice.toLowerCase()) {
3288
3304
  case "1": {
3289
- const description = await prompt("Describe what you want to do");
3305
+ const description = await promptWithCommands("Describe what you want to do", { allowMultiline: true });
3290
3306
  if (description.trim()) {
3291
- const { plan: plan2 } = await import("./plan-6AZ3U2DA.js");
3307
+ const { plan: plan2 } = await import("./plan-HCYXLSSD.js");
3292
3308
  await plan2(description, {});
3293
3309
  }
3294
3310
  break;
@@ -3381,11 +3397,14 @@ async function gatherProjectInfo(cwd) {
3381
3397
  }
3382
3398
  } catch {
3383
3399
  }
3384
- info.hasArchitecture = existsSync6(join6(cwd, "ARCHITECTURE.md"));
3400
+ info.hasArchitecture = resolveArchitecturePath(cwd).path !== null;
3385
3401
  info.hasProgress = existsSync6(join6(cwd, "progress.txt"));
3386
3402
  if (info.hasArchitecture) {
3387
- const archPath = join6(cwd, "ARCHITECTURE.md");
3388
- const parser = new ArchitectureParser(archPath);
3403
+ const archInfo = resolveArchitecturePath(cwd);
3404
+ if (!archInfo.path) {
3405
+ return info;
3406
+ }
3407
+ const parser = new ArchitectureParser(archInfo.path);
3389
3408
  const result = await parser.parse();
3390
3409
  if (result.success && result.schema) {
3391
3410
  info.posture = result.schema.qualityLevel?.posture;
@@ -3396,7 +3415,7 @@ async function gatherProjectInfo(cwd) {
3396
3415
  return info;
3397
3416
  }
3398
3417
  async function runConversationalInterview(cwd, initialMessage) {
3399
- const { InterviewerAgent, createInterviewerAgent } = await import("./interviewer-NQHNMVH4.js");
3418
+ const { InterviewerAgent, createInterviewerAgent } = await import("./interviewer-BWM5SNOE.js");
3400
3419
  const agent = await createInterviewerAgent();
3401
3420
  if (agent && agent.isAvailable()) {
3402
3421
  await runAIInterview(cwd, initialMessage, agent);
@@ -3545,9 +3564,9 @@ ${state.forbiddenPatterns?.length ? `- **Forbidden patterns:** ${state.forbidden
3545
3564
  console.log();
3546
3565
  const continueChoice = await promptYesNo("Would you like to plan your first task now?", true);
3547
3566
  if (continueChoice) {
3548
- const description = await prompt("Describe what you want to build first");
3567
+ const description = await promptWithCommands("Describe what you want to build first", { allowMultiline: true });
3549
3568
  if (description.trim()) {
3550
- const { plan: plan2 } = await import("./plan-6AZ3U2DA.js");
3569
+ const { plan: plan2 } = await import("./plan-HCYXLSSD.js");
3551
3570
  await plan2(description, {});
3552
3571
  }
3553
3572
  }
@@ -3601,7 +3620,7 @@ async function handleAdaptExisting(cwd, state) {
3601
3620
  }
3602
3621
  if (intent.mode === "ad_hoc" && intent.confidence >= 0.7) {
3603
3622
  console.log(chalk6.dim("\n> Got it! Creating a task for this...\n"));
3604
- const { plan: plan2 } = await import("./plan-6AZ3U2DA.js");
3623
+ const { plan: plan2 } = await import("./plan-HCYXLSSD.js");
3605
3624
  await plan2(response, {});
3606
3625
  return;
3607
3626
  }
@@ -3630,9 +3649,9 @@ async function showAdaptExistingMenu(cwd, state) {
3630
3649
  await runExploreFlow(cwd);
3631
3650
  break;
3632
3651
  case "2": {
3633
- const description = await prompt("Describe what you want to do");
3652
+ const description = await promptWithCommands("Describe what you want to do", { allowMultiline: true });
3634
3653
  if (description.trim()) {
3635
- const { plan: plan2 } = await import("./plan-6AZ3U2DA.js");
3654
+ const { plan: plan2 } = await import("./plan-HCYXLSSD.js");
3636
3655
  await plan2(description, {});
3637
3656
  }
3638
3657
  break;
@@ -3684,7 +3703,7 @@ async function analyzeAndAdapt(cwd) {
3684
3703
  async function codeReviewFirst(cwd) {
3685
3704
  console.log(chalk6.blue("\n-- Code Review Mode --\n"));
3686
3705
  console.log(chalk6.dim("I'll analyze your code for issues without making any changes.\n"));
3687
- const { reviewInit: reviewInit2, reviewAnalyze: reviewAnalyze2, reviewRun: reviewRun2 } = await import("./review-AUG6GIL6.js");
3706
+ const { reviewInit: reviewInit2, reviewAnalyze: reviewAnalyze2, reviewRun: reviewRun2 } = await import("./review-F6DHAGDF.js");
3688
3707
  const reviewDbPath = join6(cwd, "docs", "code-review", "review-tasks.db");
3689
3708
  if (!existsSync6(reviewDbPath)) {
3690
3709
  await reviewInit2();
@@ -3720,6 +3739,14 @@ async function handleContinueSession(cwd, state) {
3720
3739
  }
3721
3740
  function checkForHandoff(cwd) {
3722
3741
  try {
3742
+ const currentContextPath = join6(cwd, ".archon", "current_context.md");
3743
+ if (existsSync6(currentContextPath)) {
3744
+ const content2 = readFileSync3(currentContextPath, "utf-8");
3745
+ const nextStepsMatch = content2.match(/## Next Actions[^\n]*\n([\s\S]*?)(?=\n## |\n*$)/);
3746
+ if (nextStepsMatch && nextStepsMatch[1]) {
3747
+ return { nextSteps: nextStepsMatch[1].trim() };
3748
+ }
3749
+ }
3723
3750
  const progressPath = join6(cwd, "progress.txt");
3724
3751
  if (!existsSync6(progressPath)) return null;
3725
3752
  const content = readFileSync3(progressPath, "utf-8");
@@ -3783,7 +3810,7 @@ async function showMainMenu() {
3783
3810
  }
3784
3811
  async function showReviewProgress(cwd) {
3785
3812
  try {
3786
- const { ReviewDatabase } = await import("./code-review-6MU4UE5M.js");
3813
+ const { ReviewDatabase } = await import("./code-review-ODLXGXNZ.js");
3787
3814
  const db = new ReviewDatabase(cwd);
3788
3815
  db.open();
3789
3816
  const stats = db.getStats();
@@ -3800,18 +3827,18 @@ async function showReviewProgress(cwd) {
3800
3827
  }
3801
3828
  }
3802
3829
  async function planTask() {
3803
- const { plan: plan2 } = await import("./plan-6AZ3U2DA.js");
3804
- const description = await prompt("Describe what you want to build");
3830
+ const { plan: plan2 } = await import("./plan-HCYXLSSD.js");
3831
+ const description = await promptWithCommands("Describe what you want to build", { allowMultiline: true });
3805
3832
  if (description.trim()) {
3806
3833
  await plan2(description, {});
3807
3834
  }
3808
3835
  }
3809
3836
  async function listAtoms() {
3810
- const { list: list2 } = await import("./list-QWQ4QBKM.js");
3837
+ const { list: list2 } = await import("./list-REPLUXJF.js");
3811
3838
  await list2({});
3812
3839
  }
3813
3840
  async function executeNext() {
3814
- const { listLocalAtoms: listLocalAtoms2 } = await import("./plan-6AZ3U2DA.js");
3841
+ const { listLocalAtoms: listLocalAtoms2 } = await import("./plan-HCYXLSSD.js");
3815
3842
  const { analyzeProject, getComplexityDescription, getModeDescription } = await import("./orchestration-HIF3KP25.js");
3816
3843
  const { loadExecutionPreferences } = await import("./preferences-I6WETXOI.js");
3817
3844
  const cwd = process.cwd();
@@ -3882,11 +3909,11 @@ async function executeNext() {
3882
3909
  }
3883
3910
  }
3884
3911
  if (selectedMode === "parallel-cloud") {
3885
- const { parallelExecuteCloud: parallelExecuteCloud2 } = await import("./parallel-NXSICGS5.js");
3912
+ const { parallelExecuteCloud: parallelExecuteCloud2 } = await import("./parallel-23VQYK7H.js");
3886
3913
  await parallelExecuteCloud2(runIds);
3887
3914
  return;
3888
3915
  }
3889
- const { parallelExecute } = await import("./parallel-NXSICGS5.js");
3916
+ const { parallelExecute } = await import("./parallel-23VQYK7H.js");
3890
3917
  await parallelExecute(runIds);
3891
3918
  return;
3892
3919
  }
@@ -3894,14 +3921,14 @@ async function executeNext() {
3894
3921
  const atomId = await prompt("Enter atom ID to execute (or press Enter for first pending)");
3895
3922
  const targetId = atomId.trim() || pendingAtoms[0]?.id;
3896
3923
  if (targetId) {
3897
- const { execute: execute2 } = await import("./execute-VGBCOD5W.js");
3924
+ const { execute: execute2 } = await import("./execute-ZTJGSRBW.js");
3898
3925
  await execute2(targetId, {});
3899
3926
  } else {
3900
3927
  console.log(chalk6.yellow("No atom to execute."));
3901
3928
  }
3902
3929
  }
3903
3930
  async function reportBug() {
3904
- const { bugReport: bugReport2 } = await import("./bug-DCFTT2AF.js");
3931
+ const { bugReport: bugReport2 } = await import("./bug-IJCK43FK.js");
3905
3932
  const title = await prompt("Bug title");
3906
3933
  if (title.trim()) {
3907
3934
  await bugReport2(title, {});
@@ -3921,7 +3948,7 @@ async function reviewCode() {
3921
3948
  const reviewDbPath = join6(cwd, "docs", "code-review", "review-tasks.db");
3922
3949
  if (!existsSync6(reviewDbPath)) {
3923
3950
  console.log(chalk6.dim("Code review not initialized. Starting setup...\n"));
3924
- const { reviewInit: reviewInit2 } = await import("./review-AUG6GIL6.js");
3951
+ const { reviewInit: reviewInit2 } = await import("./review-F6DHAGDF.js");
3925
3952
  await reviewInit2();
3926
3953
  console.log();
3927
3954
  }
@@ -3936,27 +3963,27 @@ async function reviewCode() {
3936
3963
  const choice = await prompt("Enter choice");
3937
3964
  switch (choice.toLowerCase()) {
3938
3965
  case "1": {
3939
- const { reviewAnalyze: reviewAnalyze2 } = await import("./review-AUG6GIL6.js");
3966
+ const { reviewAnalyze: reviewAnalyze2 } = await import("./review-F6DHAGDF.js");
3940
3967
  await reviewAnalyze2();
3941
3968
  break;
3942
3969
  }
3943
3970
  case "2": {
3944
- const { reviewStatus: reviewStatus2 } = await import("./review-AUG6GIL6.js");
3971
+ const { reviewStatus: reviewStatus2 } = await import("./review-F6DHAGDF.js");
3945
3972
  await reviewStatus2();
3946
3973
  break;
3947
3974
  }
3948
3975
  case "3": {
3949
- const { reviewNext: reviewNext2 } = await import("./review-AUG6GIL6.js");
3976
+ const { reviewNext: reviewNext2 } = await import("./review-F6DHAGDF.js");
3950
3977
  await reviewNext2();
3951
3978
  break;
3952
3979
  }
3953
3980
  case "4": {
3954
- const { reviewList: reviewList2 } = await import("./review-AUG6GIL6.js");
3981
+ const { reviewList: reviewList2 } = await import("./review-F6DHAGDF.js");
3955
3982
  await reviewList2({});
3956
3983
  break;
3957
3984
  }
3958
3985
  case "5": {
3959
- const { reviewRun: reviewRun2 } = await import("./review-AUG6GIL6.js");
3986
+ const { reviewRun: reviewRun2 } = await import("./review-F6DHAGDF.js");
3960
3987
  await reviewRun2({ all: true });
3961
3988
  break;
3962
3989
  }
@@ -4014,32 +4041,28 @@ function prompt(question) {
4014
4041
  });
4015
4042
  });
4016
4043
  }
4017
- function promptMultiline(question, idleMs = 250) {
4044
+ function promptMultiline(question) {
4018
4045
  return new Promise((resolve) => {
4019
4046
  const rl = readline.createInterface({
4020
4047
  input: process.stdin,
4021
4048
  output: process.stdout
4022
4049
  });
4023
4050
  const lines = [];
4024
- let timer = null;
4025
- const finish = () => {
4026
- if (timer) clearTimeout(timer);
4027
- rl.close();
4028
- resolve(lines.join("\n").trimEnd());
4029
- };
4030
- const scheduleFinish = () => {
4031
- if (timer) clearTimeout(timer);
4032
- timer = setTimeout(finish, idleMs);
4033
- };
4034
4051
  rl.on("line", (line) => {
4052
+ if (line.trim() === ".") {
4053
+ rl.close();
4054
+ return;
4055
+ }
4035
4056
  lines.push(line);
4036
- scheduleFinish();
4037
4057
  });
4038
4058
  rl.on("SIGINT", () => {
4039
4059
  rl.close();
4040
4060
  process.exit(0);
4041
4061
  });
4042
- rl.setPrompt(`${chalk6.cyan("?")} ${question}: `);
4062
+ rl.on("close", () => {
4063
+ resolve(lines.join("\n").trimEnd());
4064
+ });
4065
+ rl.setPrompt(`${chalk6.cyan("?")} ${question} (multi-line: end with a single '.' line or Ctrl+D): `);
4043
4066
  rl.prompt();
4044
4067
  });
4045
4068
  }
@@ -4059,7 +4082,7 @@ async function promptWithCommands(question, options = {}) {
4059
4082
  async function runWebChecksSuite() {
4060
4083
  const { a11yCheck: a11yCheck2 } = await import("./a11y-O35BAA25.js");
4061
4084
  const { seoCheck } = await import("./seo-PMI42KRZ.js");
4062
- const { geoAudit } = await import("./geo-GEWH777F.js");
4085
+ const { geoAudit } = await import("./geo-HRG7M7YX.js");
4063
4086
  console.log(chalk6.blue("\nRunning web checks (A11y, SEO, GEO)...\n"));
4064
4087
  await a11yCheck2({});
4065
4088
  await seoCheck({});
@@ -4099,17 +4122,17 @@ async function showWebChecksMenu() {
4099
4122
  break;
4100
4123
  }
4101
4124
  case "4": {
4102
- const { geoAudit } = await import("./geo-GEWH777F.js");
4125
+ const { geoAudit } = await import("./geo-HRG7M7YX.js");
4103
4126
  await geoAudit();
4104
4127
  break;
4105
4128
  }
4106
4129
  case "5": {
4107
- const { geoIdentity } = await import("./geo-GEWH777F.js");
4130
+ const { geoIdentity } = await import("./geo-HRG7M7YX.js");
4108
4131
  await geoIdentity();
4109
4132
  break;
4110
4133
  }
4111
4134
  case "6": {
4112
- const { geoSchema } = await import("./geo-GEWH777F.js");
4135
+ const { geoSchema } = await import("./geo-HRG7M7YX.js");
4113
4136
  await geoSchema({});
4114
4137
  break;
4115
4138
  }
@@ -4245,9 +4268,9 @@ async function showCredits() {
4245
4268
  console.log(chalk7.dim(" Using your own API keys - no credit charges"));
4246
4269
  }
4247
4270
  console.log();
4248
- } catch (err) {
4271
+ } catch (err2) {
4249
4272
  spinner.fail("Error fetching credits");
4250
- console.error(err);
4273
+ console.error(err2);
4251
4274
  }
4252
4275
  }
4253
4276
  async function addCredits(options = {}) {
@@ -4301,9 +4324,9 @@ async function addCredits(options = {}) {
4301
4324
  } catch {
4302
4325
  console.log(chalk7.yellow(" Could not open browser. Please visit the URL above."));
4303
4326
  }
4304
- } catch (err) {
4327
+ } catch (err2) {
4305
4328
  spinner.fail("Error preparing checkout");
4306
- console.error(err);
4329
+ console.error(err2);
4307
4330
  }
4308
4331
  }
4309
4332
  async function showHistory(options = {}) {
@@ -4347,9 +4370,9 @@ async function showHistory(options = {}) {
4347
4370
  ` ${"Total".padEnd(30)} ${totalTokens.toString().padStart(8)} ${chalk7.green(`$${totalCost.toFixed(4)}`.padStart(10))}`
4348
4371
  );
4349
4372
  console.log();
4350
- } catch (err) {
4373
+ } catch (err2) {
4351
4374
  spinner.fail("Error fetching history");
4352
- console.error(err);
4375
+ console.error(err2);
4353
4376
  }
4354
4377
  }
4355
4378
  async function manageBudget(options = {}) {
@@ -4429,9 +4452,9 @@ async function manageBudget(options = {}) {
4429
4452
  console.log(chalk7.dim(" Clear budget: archon credits budget --clear"));
4430
4453
  console.log(chalk7.dim(" Set alert: archon credits budget --alert 80"));
4431
4454
  console.log();
4432
- } catch (err) {
4455
+ } catch (err2) {
4433
4456
  spinner.fail("Error managing budget");
4434
- console.error(err);
4457
+ console.error(err2);
4435
4458
  }
4436
4459
  }
4437
4460
  async function manageAutoRecharge(options = {}) {
@@ -4507,9 +4530,9 @@ async function manageAutoRecharge(options = {}) {
4507
4530
  console.log(chalk7.dim(" Enable: archon credits auto-recharge --enable --threshold 5 --amount 20"));
4508
4531
  console.log(chalk7.dim(" Disable: archon credits auto-recharge --disable"));
4509
4532
  console.log();
4510
- } catch (err) {
4533
+ } catch (err2) {
4511
4534
  spinner.fail("Error managing auto-recharge");
4512
- console.error(err);
4535
+ console.error(err2);
4513
4536
  }
4514
4537
  }
4515
4538
  async function showAuditHistory(options = {}) {
@@ -4562,9 +4585,9 @@ async function showAuditHistory(options = {}) {
4562
4585
  console.log(chalk7.dim(` Showing ${history.length} most recent events`));
4563
4586
  console.log(chalk7.dim(" Use --limit N to show more"));
4564
4587
  console.log();
4565
- } catch (err) {
4588
+ } catch (err2) {
4566
4589
  spinner.fail("Error fetching audit history");
4567
- console.error(err);
4590
+ console.error(err2);
4568
4591
  }
4569
4592
  }
4570
4593
  function formatEventType(eventType) {
@@ -5222,9 +5245,9 @@ async function saveSession(name) {
5222
5245
  console.log();
5223
5246
  console.log(chalk9.dim(" Resume on another device: archon session resume " + session.id));
5224
5247
  console.log();
5225
- } catch (err) {
5248
+ } catch (err2) {
5226
5249
  spinner.fail("Error saving session");
5227
- console.error(err);
5250
+ console.error(err2);
5228
5251
  }
5229
5252
  }
5230
5253
  async function listSessions() {
@@ -5265,9 +5288,9 @@ async function listSessions() {
5265
5288
  console.log();
5266
5289
  }
5267
5290
  console.log(chalk9.dim(" Resume: archon session resume <id>\n"));
5268
- } catch (err) {
5291
+ } catch (err2) {
5269
5292
  spinner.fail("Error fetching sessions");
5270
- console.error(err);
5293
+ console.error(err2);
5271
5294
  }
5272
5295
  }
5273
5296
  async function resumeSession(sessionId) {
@@ -5316,9 +5339,9 @@ async function resumeSession(sessionId) {
5316
5339
  console.log();
5317
5340
  console.log(chalk9.dim(" Continue working: archon start"));
5318
5341
  console.log();
5319
- } catch (err) {
5342
+ } catch (err2) {
5320
5343
  spinner.fail("Error resuming session");
5321
- console.error(err);
5344
+ console.error(err2);
5322
5345
  }
5323
5346
  }
5324
5347
  async function syncSession() {
@@ -5358,9 +5381,9 @@ async function syncSession() {
5358
5381
  return;
5359
5382
  }
5360
5383
  spinner.succeed(chalk9.green("Session synced to cloud"));
5361
- } catch (err) {
5384
+ } catch (err2) {
5362
5385
  spinner.fail("Error syncing session");
5363
- console.error(err);
5386
+ console.error(err2);
5364
5387
  }
5365
5388
  }
5366
5389
 
@@ -6394,9 +6417,9 @@ async function interview(options = {}) {
6394
6417
  console.log(` ${chalk13.cyan("2.")} Run ${chalk13.bold("archon list")} to see generated atoms`);
6395
6418
  console.log(` ${chalk13.cyan("3.")} Run ${chalk13.bold("archon execute <atom-id>")} to start building`);
6396
6419
  console.log();
6397
- } catch (err) {
6420
+ } catch (err2) {
6398
6421
  spinner.fail("Failed to freeze Constitution");
6399
- console.error(err);
6422
+ console.error(err2);
6400
6423
  }
6401
6424
  }
6402
6425
  async function runPhase(phase, constitution, cwd) {
@@ -7075,13 +7098,13 @@ async function modelsSync(options) {
7075
7098
  if (result.parseErrors.length > 0) {
7076
7099
  console.log();
7077
7100
  console.log(chalk16.red(`\u26A0\uFE0F Warnings/Errors (${result.parseErrors.length}):`));
7078
- for (const err of result.parseErrors) {
7079
- console.log(chalk16.red(` - ${err}`));
7101
+ for (const err2 of result.parseErrors) {
7102
+ console.log(chalk16.red(` - ${err2}`));
7080
7103
  }
7081
7104
  }
7082
7105
  console.log();
7083
- } catch (err) {
7084
- console.log(chalk16.red(`Failed to run sync: ${err}`));
7106
+ } catch (err2) {
7107
+ console.log(chalk16.red(`Failed to run sync: ${err2}`));
7085
7108
  }
7086
7109
  }
7087
7110
  async function modelsList() {
@@ -7108,13 +7131,1031 @@ async function modelsList() {
7108
7131
  console.log();
7109
7132
  }
7110
7133
 
7134
+ // src/cli/governance.ts
7135
+ import { Command as Command2 } from "commander";
7136
+ import chalk17 from "chalk";
7137
+ import { existsSync as existsSync19, readFileSync as readFileSync7 } from "fs";
7138
+ import { readFile as readFile12 } from "fs/promises";
7139
+ import { join as join19 } from "path";
7140
+ import matter4 from "gray-matter";
7141
+
7142
+ // src/core/governance/store.ts
7143
+ import { existsSync as existsSync16, mkdirSync as mkdirSync3 } from "fs";
7144
+ import { readFile as readFile10, writeFile as writeFile8, appendFile, unlink as unlink2, stat as stat2, rename } from "fs/promises";
7145
+ import { join as join16 } from "path";
7146
+ import matter from "gray-matter";
7147
+ var ARCHON_DIR2 = ".archon";
7148
+ var ACTIVE_DIR = join16(ARCHON_DIR2, "active");
7149
+ var HISTORY_DIR = join16(ARCHON_DIR2, "history");
7150
+ var ARCHIVE_DIR2 = join16(ARCHON_DIR2, "archive");
7151
+ var LOCK_FILE = join16(ARCHON_DIR2, "governance.lock");
7152
+ var CURRENT_CONTEXT = join16(ARCHON_DIR2, "current_context.md");
7153
+ var ARCHITECTURE_FILE = join16(ACTIVE_DIR, "architecture.md");
7154
+ var TASKS_FILE = join16(ACTIVE_DIR, "tasks.json");
7155
+ var HANDOFFS_FILE = join16(HISTORY_DIR, "handoffs.jsonl");
7156
+ var DECISION_LOG_FILE = join16(HISTORY_DIR, "decision_log.jsonl");
7157
+ var COMPLETED_TASKS_FILE = join16(ARCHIVE_DIR2, "completed_tasks.jsonl");
7158
+ var DEFAULT_LOCK_TIMEOUT_MS = 5e3;
7159
+ var DEFAULT_LOCK_RETRY_MS = 100;
7160
+ var DEFAULT_STALE_LOCK_MS = 2 * 60 * 1e3;
7161
+ var GovernanceStore = class {
7162
+ cwd;
7163
+ constructor(cwd = process.cwd()) {
7164
+ this.cwd = cwd;
7165
+ }
7166
+ /**
7167
+ * Ensure governance directories exist
7168
+ */
7169
+ ensureStructure() {
7170
+ this.ensureDir(join16(this.cwd, ARCHON_DIR2));
7171
+ this.ensureDir(join16(this.cwd, ACTIVE_DIR));
7172
+ this.ensureDir(join16(this.cwd, HISTORY_DIR));
7173
+ this.ensureDir(join16(this.cwd, ARCHIVE_DIR2));
7174
+ }
7175
+ /**
7176
+ * Read current architecture content (without frontmatter)
7177
+ */
7178
+ async readArchitecture() {
7179
+ const filePath = join16(this.cwd, ARCHITECTURE_FILE);
7180
+ if (!existsSync16(filePath)) {
7181
+ return ok("");
7182
+ }
7183
+ try {
7184
+ const raw = await readFile10(filePath, "utf-8");
7185
+ const parsed = matter(raw);
7186
+ return ok(parsed.content.trim());
7187
+ } catch (error) {
7188
+ return err(error instanceof Error ? error.message : "Failed to read architecture");
7189
+ }
7190
+ }
7191
+ /**
7192
+ * Update architecture with required change_reason and optional updated_by
7193
+ */
7194
+ async updateArchitecture(content, changeReason, updatedBy) {
7195
+ if (!changeReason.trim()) {
7196
+ return err("change_reason is required for architecture updates");
7197
+ }
7198
+ this.ensureStructure();
7199
+ const release = await this.acquireLock();
7200
+ if (!release.ok) return release;
7201
+ try {
7202
+ const now = (/* @__PURE__ */ new Date()).toISOString();
7203
+ const filePath = join16(this.cwd, ARCHITECTURE_FILE);
7204
+ const current = await this.readArchitectureFrontmatter(filePath);
7205
+ const nextVersion = this.nextVersion(current?.version);
7206
+ const frontmatter = {
7207
+ version: nextVersion,
7208
+ last_updated: now,
7209
+ change_reason: changeReason
7210
+ };
7211
+ if (updatedBy) {
7212
+ frontmatter.updated_by = updatedBy;
7213
+ }
7214
+ const output = matter.stringify(content.trim() + "\n", frontmatter);
7215
+ await this.writeFileAtomic(filePath, output);
7216
+ const decision = {
7217
+ timestamp: now,
7218
+ category: "architecture",
7219
+ change_reason: changeReason,
7220
+ updated_by: updatedBy
7221
+ };
7222
+ await this.appendJsonLine(join16(this.cwd, DECISION_LOG_FILE), decision);
7223
+ return ok(void 0);
7224
+ } catch (error) {
7225
+ return err(error instanceof Error ? error.message : "Failed to update architecture");
7226
+ } finally {
7227
+ await release.value();
7228
+ }
7229
+ }
7230
+ /**
7231
+ * Update a task's status and optional notes. Moves to archive when done.
7232
+ */
7233
+ async updateTask(taskId, status2, notes) {
7234
+ this.ensureStructure();
7235
+ const release = await this.acquireLock();
7236
+ if (!release.ok) return release;
7237
+ try {
7238
+ const tasksPath = join16(this.cwd, TASKS_FILE);
7239
+ const tasks = await this.loadTasks(tasksPath);
7240
+ if (!tasks.ok) return tasks;
7241
+ const index = tasks.value.findIndex((task2) => task2.id === taskId);
7242
+ if (index === -1) {
7243
+ return err(`Task not found: ${taskId}`);
7244
+ }
7245
+ const now = (/* @__PURE__ */ new Date()).toISOString();
7246
+ const task = { ...tasks.value[index] };
7247
+ task.status = status2;
7248
+ task.notes = notes ?? task.notes;
7249
+ task.updated_at = now;
7250
+ if (status2 === "done") {
7251
+ tasks.value.splice(index, 1);
7252
+ await this.appendJsonLine(join16(this.cwd, COMPLETED_TASKS_FILE), task);
7253
+ } else {
7254
+ tasks.value[index] = task;
7255
+ }
7256
+ await this.writeJson(tasksPath, tasks.value);
7257
+ return ok(void 0);
7258
+ } catch (error) {
7259
+ return err(error instanceof Error ? error.message : "Failed to update task");
7260
+ } finally {
7261
+ await release.value();
7262
+ }
7263
+ }
7264
+ /**
7265
+ * Append handoff entry and update current_context.md
7266
+ */
7267
+ async logHandoff(entry) {
7268
+ if (!entry.reason.trim()) {
7269
+ return err("reason is required for handoff");
7270
+ }
7271
+ if (!entry.summary.trim()) {
7272
+ return err("summary is required for handoff");
7273
+ }
7274
+ if (!entry.next_actions || entry.next_actions.length === 0) {
7275
+ return err("next_actions are required for handoff");
7276
+ }
7277
+ this.ensureStructure();
7278
+ const release = await this.acquireLock();
7279
+ if (!release.ok) return release;
7280
+ try {
7281
+ await this.appendJsonLine(join16(this.cwd, HANDOFFS_FILE), entry);
7282
+ const contextLines = [
7283
+ "# Current Context",
7284
+ "",
7285
+ `Timestamp: ${entry.timestamp}`,
7286
+ entry.from_agent ? `From: ${entry.from_agent}` : void 0,
7287
+ `Reason: ${entry.reason}`,
7288
+ "",
7289
+ "## Summary",
7290
+ entry.summary.trim(),
7291
+ "",
7292
+ "## Next Actions",
7293
+ ...entry.next_actions.map((action) => `- ${action}`),
7294
+ ""
7295
+ ].filter((line) => typeof line === "string");
7296
+ await this.writeFileAtomic(join16(this.cwd, CURRENT_CONTEXT), contextLines.join("\n"));
7297
+ return ok(void 0);
7298
+ } catch (error) {
7299
+ return err(error instanceof Error ? error.message : "Failed to log handoff");
7300
+ } finally {
7301
+ await release.value();
7302
+ }
7303
+ }
7304
+ ensureDir(path2) {
7305
+ if (!existsSync16(path2)) {
7306
+ mkdirSync3(path2, { recursive: true });
7307
+ }
7308
+ }
7309
+ async acquireLock(timeoutMs = DEFAULT_LOCK_TIMEOUT_MS, retryMs = DEFAULT_LOCK_RETRY_MS, staleMs = DEFAULT_STALE_LOCK_MS) {
7310
+ const lockPath = join16(this.cwd, LOCK_FILE);
7311
+ const deadline = Date.now() + timeoutMs;
7312
+ while (Date.now() < deadline) {
7313
+ try {
7314
+ await this.tryCreateLock(lockPath);
7315
+ return ok(async () => {
7316
+ await this.safeUnlink(lockPath);
7317
+ });
7318
+ } catch (error) {
7319
+ if (error instanceof Error && error.message === "LOCK_EXISTS") {
7320
+ const staleCleared = await this.clearStaleLock(lockPath, staleMs);
7321
+ if (staleCleared) {
7322
+ continue;
7323
+ }
7324
+ await sleep(retryMs);
7325
+ continue;
7326
+ }
7327
+ return err("Failed to acquire governance lock");
7328
+ }
7329
+ }
7330
+ return err("Timed out waiting for governance lock");
7331
+ }
7332
+ async tryCreateLock(lockPath) {
7333
+ if (existsSync16(lockPath)) {
7334
+ throw new Error("LOCK_EXISTS");
7335
+ }
7336
+ const payload = JSON.stringify({ pid: process.pid, created_at: (/* @__PURE__ */ new Date()).toISOString() });
7337
+ await writeFile8(lockPath, payload, { flag: "wx" });
7338
+ }
7339
+ async clearStaleLock(lockPath, staleMs) {
7340
+ try {
7341
+ const info = await stat2(lockPath);
7342
+ const ageByMtime = Date.now() - info.mtimeMs;
7343
+ let ageByCreatedAt = null;
7344
+ try {
7345
+ const raw = await readFile10(lockPath, "utf-8");
7346
+ const parsed = JSON.parse(raw);
7347
+ if (parsed.created_at) {
7348
+ const createdAt = Date.parse(parsed.created_at);
7349
+ if (!Number.isNaN(createdAt)) {
7350
+ ageByCreatedAt = Date.now() - createdAt;
7351
+ }
7352
+ }
7353
+ } catch {
7354
+ }
7355
+ const ageMs = Math.max(ageByMtime, ageByCreatedAt ?? -Infinity);
7356
+ if (ageMs > staleMs) {
7357
+ await this.safeUnlink(lockPath);
7358
+ return true;
7359
+ }
7360
+ } catch {
7361
+ return false;
7362
+ }
7363
+ return false;
7364
+ }
7365
+ async safeUnlink(path2) {
7366
+ try {
7367
+ await unlink2(path2);
7368
+ } catch {
7369
+ }
7370
+ }
7371
+ async readArchitectureFrontmatter(filePath) {
7372
+ if (!existsSync16(filePath)) return null;
7373
+ const raw = await readFile10(filePath, "utf-8");
7374
+ const parsed = matter(raw);
7375
+ const data = parsed.data;
7376
+ const versionRaw = data["version"];
7377
+ const version = typeof versionRaw === "number" ? versionRaw : typeof versionRaw === "string" ? Number.parseFloat(versionRaw) : 1;
7378
+ return {
7379
+ version: Number.isFinite(version) ? version : 1,
7380
+ last_updated: typeof data["last_updated"] === "string" ? data["last_updated"] : "",
7381
+ updated_by: typeof data["updated_by"] === "string" ? data["updated_by"] : void 0,
7382
+ change_reason: typeof data["change_reason"] === "string" ? data["change_reason"] : ""
7383
+ };
7384
+ }
7385
+ nextVersion(current) {
7386
+ if (!current || !Number.isFinite(current)) return 1;
7387
+ return Math.round((current + 0.1) * 10) / 10;
7388
+ }
7389
+ async loadTasks(path2) {
7390
+ if (!existsSync16(path2)) return ok([]);
7391
+ try {
7392
+ const raw = await readFile10(path2, "utf-8");
7393
+ const data = JSON.parse(raw);
7394
+ if (!Array.isArray(data)) {
7395
+ return err("tasks.json must be an array");
7396
+ }
7397
+ const parsed = [];
7398
+ for (const item of data) {
7399
+ const task = this.parseTask(item);
7400
+ if (!task) {
7401
+ return err("tasks.json contains invalid entries");
7402
+ }
7403
+ parsed.push(task);
7404
+ }
7405
+ return ok(parsed);
7406
+ } catch (error) {
7407
+ return err(error instanceof Error ? error.message : "Failed to parse tasks.json");
7408
+ }
7409
+ }
7410
+ parseTask(value) {
7411
+ if (typeof value !== "object" || value === null) return null;
7412
+ const raw = value;
7413
+ const id = typeof raw["id"] === "string" ? raw["id"] : null;
7414
+ const description = typeof raw["description"] === "string" ? raw["description"] : null;
7415
+ const status2 = this.parseStatus(raw["status"]);
7416
+ const createdAt = typeof raw["created_at"] === "string" ? raw["created_at"] : null;
7417
+ if (!id || !description || !status2 || !createdAt) return null;
7418
+ return {
7419
+ id,
7420
+ parent_id: typeof raw["parent_id"] === "string" ? raw["parent_id"] : void 0,
7421
+ description,
7422
+ status: status2,
7423
+ assigned_to: typeof raw["assigned_to"] === "string" ? raw["assigned_to"] : void 0,
7424
+ created_at: createdAt,
7425
+ updated_at: typeof raw["updated_at"] === "string" ? raw["updated_at"] : void 0,
7426
+ notes: typeof raw["notes"] === "string" ? raw["notes"] : void 0
7427
+ };
7428
+ }
7429
+ parseStatus(value) {
7430
+ if (value === "pending" || value === "in_progress" || value === "verification" || value === "done") {
7431
+ return value;
7432
+ }
7433
+ return null;
7434
+ }
7435
+ async writeJson(path2, payload) {
7436
+ const content = JSON.stringify(payload, null, 2) + "\n";
7437
+ await this.writeFileAtomic(path2, content);
7438
+ }
7439
+ async writeFileAtomic(path2, content) {
7440
+ const tmpPath = `${path2}.tmp`;
7441
+ await writeFile8(tmpPath, content, "utf-8");
7442
+ try {
7443
+ await rename(tmpPath, path2);
7444
+ } catch {
7445
+ await this.safeUnlink(path2);
7446
+ await rename(tmpPath, path2);
7447
+ }
7448
+ }
7449
+ async appendJsonLine(path2, payload) {
7450
+ const line = JSON.stringify(payload) + "\n";
7451
+ await appendFile(path2, line, "utf-8");
7452
+ }
7453
+ };
7454
+
7455
+ // src/core/governance/migrate.ts
7456
+ import { existsSync as existsSync17, mkdirSync as mkdirSync4 } from "fs";
7457
+ import { readFile as readFile11, writeFile as writeFile9, unlink as unlink3 } from "fs/promises";
7458
+ import { join as join17 } from "path";
7459
+ import matter2 from "gray-matter";
7460
+ var LEGACY_ARCH_PATH = "ARCHITECTURE.md";
7461
+ var LEGACY_TASKS_PATH = join17(".archon", "current-tasks.md");
7462
+ var ACTIVE_ARCH_PATH2 = join17(".archon", "active", "architecture.md");
7463
+ var ACTIVE_TASKS_PATH = join17(".archon", "active", "tasks.json");
7464
+ var ARCHIVE_COMPLETED_PATH = join17(".archon", "archive", "completed_tasks.jsonl");
7465
+ var HISTORY_LEGACY_DIR = join17(".archon", "history", "legacy");
7466
+ function parseLegacyTasks(content) {
7467
+ const result = { active: [], paused: [] };
7468
+ const activeHeaderMatch = content.match(/##\s+Active\s*\((\d{4}-\d{2}-\d{2})\)/i);
7469
+ if (activeHeaderMatch?.[1]) {
7470
+ result.referenceDate = activeHeaderMatch[1];
7471
+ }
7472
+ const sections = content.split(/\n##\s+/).map((block) => block.trim());
7473
+ for (const section of sections) {
7474
+ const normalized = section.toLowerCase();
7475
+ const lines = section.split("\n").slice(1);
7476
+ if (normalized.startsWith("active")) {
7477
+ for (const line of lines) {
7478
+ const match = line.match(/^\d+\.\s+(.*)$/);
7479
+ if (!match?.[1]) continue;
7480
+ const raw = match[1].trim();
7481
+ if (!raw) continue;
7482
+ const done = /\(done\)\s*$/i.test(raw);
7483
+ const cleaned = raw.replace(/\s*\(done\)\s*$/i, "").trim();
7484
+ result.active.push({ description: cleaned, done });
7485
+ }
7486
+ }
7487
+ if (normalized.startsWith("paused")) {
7488
+ for (const line of lines) {
7489
+ const match = line.match(/^\d+\.\s+(.*)$/);
7490
+ if (!match?.[1]) continue;
7491
+ const raw = match[1].trim();
7492
+ if (!raw) continue;
7493
+ result.paused.push(raw);
7494
+ }
7495
+ }
7496
+ }
7497
+ return result;
7498
+ }
7499
+ function buildTaskEntries(parsed, nowIso) {
7500
+ const active = [];
7501
+ const completed = [];
7502
+ let counter = 1;
7503
+ const referenceDate = parsed.referenceDate ? `${parsed.referenceDate}T00:00:00.000Z` : nowIso;
7504
+ const makeTask = (description, status2, notes) => {
7505
+ const task = {
7506
+ id: `TASK-${String(counter).padStart(3, "0")}`,
7507
+ description,
7508
+ status: status2,
7509
+ created_at: referenceDate,
7510
+ updated_at: nowIso,
7511
+ notes
7512
+ };
7513
+ counter += 1;
7514
+ return task;
7515
+ };
7516
+ for (const item of parsed.active) {
7517
+ if (item.done) {
7518
+ completed.push(makeTask(item.description, "done", "Migrated from current-tasks.md (done)"));
7519
+ } else {
7520
+ active.push(makeTask(item.description, "pending"));
7521
+ }
7522
+ }
7523
+ for (const paused of parsed.paused) {
7524
+ active.push(makeTask(paused, "pending", "Migrated from current-tasks.md (paused)"));
7525
+ }
7526
+ return { active, completed };
7527
+ }
7528
+ async function writeJson(path2, payload, dryRun) {
7529
+ if (dryRun) return;
7530
+ const content = JSON.stringify(payload, null, 2) + "\n";
7531
+ await writeFile9(path2, content, "utf-8");
7532
+ }
7533
+ async function appendJsonLines(path2, items, dryRun) {
7534
+ if (dryRun || items.length === 0) return;
7535
+ const lines = items.map((item) => JSON.stringify(item)).join("\n") + "\n";
7536
+ await writeFile9(path2, lines, { encoding: "utf-8", flag: "a" });
7537
+ }
7538
+ async function archiveLegacyFile(source, destDir, dryRun) {
7539
+ const fileName = source.split("/").pop() ?? source.replace(/[^a-zA-Z0-9._-]/g, "_");
7540
+ const target = join17(destDir, fileName);
7541
+ if (dryRun) return target;
7542
+ if (!existsSync17(destDir)) {
7543
+ mkdirSync4(destDir, { recursive: true });
7544
+ }
7545
+ const content = await readFile11(source, "utf-8");
7546
+ await writeFile9(target, content, "utf-8");
7547
+ return target;
7548
+ }
7549
+ async function migrateLegacyGovernance(options = {}) {
7550
+ const cwd = options.cwd ?? process.cwd();
7551
+ const now = options.now ?? /* @__PURE__ */ new Date();
7552
+ const nowIso = now.toISOString();
7553
+ const result = {
7554
+ migratedArchitecture: false,
7555
+ migratedTasks: false,
7556
+ archivedLegacyFiles: [],
7557
+ warnings: []
7558
+ };
7559
+ const store = new GovernanceStore(cwd);
7560
+ store.ensureStructure();
7561
+ const archPath = join17(cwd, LEGACY_ARCH_PATH);
7562
+ const activeArchPath = join17(cwd, ACTIVE_ARCH_PATH2);
7563
+ if (existsSync17(archPath) && !existsSync17(activeArchPath)) {
7564
+ const raw = await readFile11(archPath, "utf-8");
7565
+ const parsed = matter2(raw);
7566
+ const content = parsed.content.trim();
7567
+ if (!content) {
7568
+ result.warnings.push("Legacy ARCHITECTURE.md was empty; skipping architecture migration.");
7569
+ } else if (!options.dryRun) {
7570
+ const update = await store.updateArchitecture(
7571
+ content,
7572
+ "Migrated from legacy ARCHITECTURE.md",
7573
+ options.updatedBy ?? "archon migration"
7574
+ );
7575
+ if (!update.ok) {
7576
+ result.warnings.push(`Failed to migrate architecture: ${update.error}`);
7577
+ } else {
7578
+ result.migratedArchitecture = true;
7579
+ }
7580
+ } else {
7581
+ result.migratedArchitecture = true;
7582
+ }
7583
+ if (options.removeLegacy) {
7584
+ const archived = await archiveLegacyFile(archPath, join17(cwd, HISTORY_LEGACY_DIR), !!options.dryRun);
7585
+ result.archivedLegacyFiles.push(archived);
7586
+ if (!options.dryRun) {
7587
+ await unlink3(archPath);
7588
+ }
7589
+ }
7590
+ }
7591
+ const legacyTasksPath = join17(cwd, LEGACY_TASKS_PATH);
7592
+ const activeTasksPath = join17(cwd, ACTIVE_TASKS_PATH);
7593
+ if (existsSync17(legacyTasksPath) && !existsSync17(activeTasksPath)) {
7594
+ const rawTasks = await readFile11(legacyTasksPath, "utf-8");
7595
+ const parsedTasks = parseLegacyTasks(rawTasks);
7596
+ const { active, completed } = buildTaskEntries(parsedTasks, nowIso);
7597
+ if (active.length === 0 && completed.length === 0) {
7598
+ result.warnings.push("Legacy current-tasks.md did not contain actionable items.");
7599
+ } else {
7600
+ await writeJson(activeTasksPath, active, !!options.dryRun);
7601
+ await appendJsonLines(join17(cwd, ARCHIVE_COMPLETED_PATH), completed, !!options.dryRun);
7602
+ result.migratedTasks = true;
7603
+ }
7604
+ if (options.removeLegacy) {
7605
+ const archived = await archiveLegacyFile(legacyTasksPath, join17(cwd, HISTORY_LEGACY_DIR), !!options.dryRun);
7606
+ result.archivedLegacyFiles.push(archived);
7607
+ if (!options.dryRun) {
7608
+ await unlink3(legacyTasksPath);
7609
+ }
7610
+ }
7611
+ }
7612
+ if (existsSync17(join17(cwd, ACTIVE_ARCH_PATH2)) && existsSync17(join17(cwd, LEGACY_ARCH_PATH))) {
7613
+ result.warnings.push("Active architecture already exists; legacy ARCHITECTURE.md left untouched.");
7614
+ }
7615
+ if (existsSync17(join17(cwd, ACTIVE_TASKS_PATH)) && existsSync17(join17(cwd, LEGACY_TASKS_PATH))) {
7616
+ result.warnings.push("Active tasks already exist; legacy current-tasks.md left untouched.");
7617
+ }
7618
+ return result;
7619
+ }
7620
+
7621
+ // src/core/governance/sqlite.ts
7622
+ import { existsSync as existsSync18, mkdirSync as mkdirSync5, readFileSync as readFileSync6 } from "fs";
7623
+ import { join as join18 } from "path";
7624
+ import matter3 from "gray-matter";
7625
+ import Database2 from "better-sqlite3";
7626
+ var ARCH_PATH = join18(".archon", "active", "architecture.md");
7627
+ var TASKS_PATH = join18(".archon", "active", "tasks.json");
7628
+ var HANDOFFS_PATH = join18(".archon", "history", "handoffs.jsonl");
7629
+ var DECISIONS_PATH = join18(".archon", "history", "decision_log.jsonl");
7630
+ var COMPLETED_PATH = join18(".archon", "archive", "completed_tasks.jsonl");
7631
+ var GovernanceSqliteView = class {
7632
+ db = null;
7633
+ config;
7634
+ constructor(config = {}) {
7635
+ this.config = config;
7636
+ }
7637
+ init(cwd) {
7638
+ const archonDir = join18(cwd, ".archon");
7639
+ if (!existsSync18(archonDir)) {
7640
+ mkdirSync5(archonDir, { recursive: true });
7641
+ }
7642
+ const dbPath = this.config.inMemory ? ":memory:" : join18(cwd, this.config.dbPath ?? ".archon/governance.db");
7643
+ this.db = new Database2(dbPath);
7644
+ this.db.exec(`
7645
+ PRAGMA journal_mode = WAL;
7646
+ CREATE TABLE IF NOT EXISTS architecture (
7647
+ id TEXT PRIMARY KEY,
7648
+ version REAL,
7649
+ last_updated TEXT,
7650
+ updated_by TEXT,
7651
+ change_reason TEXT,
7652
+ content TEXT
7653
+ );
7654
+ CREATE TABLE IF NOT EXISTS tasks (
7655
+ id TEXT PRIMARY KEY,
7656
+ description TEXT NOT NULL,
7657
+ status TEXT NOT NULL,
7658
+ created_at TEXT NOT NULL,
7659
+ updated_at TEXT,
7660
+ notes TEXT
7661
+ );
7662
+ CREATE TABLE IF NOT EXISTS completed_tasks (
7663
+ id TEXT PRIMARY KEY,
7664
+ description TEXT NOT NULL,
7665
+ status TEXT NOT NULL,
7666
+ created_at TEXT NOT NULL,
7667
+ updated_at TEXT,
7668
+ notes TEXT
7669
+ );
7670
+ CREATE TABLE IF NOT EXISTS handoffs (
7671
+ id TEXT PRIMARY KEY,
7672
+ timestamp TEXT NOT NULL,
7673
+ from_agent TEXT,
7674
+ reason TEXT NOT NULL,
7675
+ summary TEXT NOT NULL,
7676
+ next_actions TEXT NOT NULL
7677
+ );
7678
+ CREATE TABLE IF NOT EXISTS decisions (
7679
+ id TEXT PRIMARY KEY,
7680
+ timestamp TEXT NOT NULL,
7681
+ category TEXT NOT NULL,
7682
+ change_reason TEXT NOT NULL,
7683
+ updated_by TEXT,
7684
+ diff_summary TEXT
7685
+ );
7686
+ CREATE VIRTUAL TABLE IF NOT EXISTS governance_fts USING fts5(
7687
+ source,
7688
+ record_id,
7689
+ text,
7690
+ timestamp
7691
+ );
7692
+ `);
7693
+ }
7694
+ close() {
7695
+ if (this.db) {
7696
+ this.db.close();
7697
+ this.db = null;
7698
+ }
7699
+ }
7700
+ async loadFromDisk(cwd) {
7701
+ if (!this.db) {
7702
+ throw new Error("GovernanceSqliteView not initialized. Call init() first.");
7703
+ }
7704
+ const stats = {
7705
+ tasks: 0,
7706
+ completedTasks: 0,
7707
+ handoffs: 0,
7708
+ decisions: 0,
7709
+ architecture: false
7710
+ };
7711
+ this.db.exec("DELETE FROM governance_fts; DELETE FROM architecture; DELETE FROM tasks; DELETE FROM completed_tasks; DELETE FROM handoffs; DELETE FROM decisions;");
7712
+ const archPath = join18(cwd, ARCH_PATH);
7713
+ if (existsSync18(archPath)) {
7714
+ const raw = readFileSync6(archPath, "utf-8");
7715
+ const parsed = matter3(raw);
7716
+ const data = parsed.data;
7717
+ const versionRaw = data["version"];
7718
+ const version = typeof versionRaw === "number" ? versionRaw : typeof versionRaw === "string" ? Number.parseFloat(versionRaw) : null;
7719
+ const archId = "architecture";
7720
+ const content = parsed.content.trim();
7721
+ this.db.prepare(
7722
+ `INSERT OR REPLACE INTO architecture (id, version, last_updated, updated_by, change_reason, content)
7723
+ VALUES (?, ?, ?, ?, ?, ?)`
7724
+ ).run(
7725
+ archId,
7726
+ Number.isFinite(version) ? version : null,
7727
+ typeof data["last_updated"] === "string" ? data["last_updated"] : null,
7728
+ typeof data["updated_by"] === "string" ? data["updated_by"] : null,
7729
+ typeof data["change_reason"] === "string" ? data["change_reason"] : null,
7730
+ content
7731
+ );
7732
+ this.db.prepare(
7733
+ `INSERT INTO governance_fts (source, record_id, text, timestamp)
7734
+ VALUES (?, ?, ?, ?)`
7735
+ ).run("architecture", archId, content, typeof data["last_updated"] === "string" ? data["last_updated"] : null);
7736
+ stats.architecture = true;
7737
+ }
7738
+ const tasksPath = join18(cwd, TASKS_PATH);
7739
+ if (existsSync18(tasksPath)) {
7740
+ const raw = readFileSync6(tasksPath, "utf-8");
7741
+ const tasks = JSON.parse(raw);
7742
+ const insertTask = this.db.prepare(
7743
+ `INSERT OR REPLACE INTO tasks (id, description, status, created_at, updated_at, notes)
7744
+ VALUES (?, ?, ?, ?, ?, ?)`
7745
+ );
7746
+ const insertFts = this.db.prepare(
7747
+ `INSERT INTO governance_fts (source, record_id, text, timestamp)
7748
+ VALUES (?, ?, ?, ?)`
7749
+ );
7750
+ for (const task of tasks) {
7751
+ insertTask.run(task.id, task.description, task.status, task.created_at, task.updated_at ?? null, task.notes ?? null);
7752
+ insertFts.run("task", task.id, task.description + (task.notes ? `
7753
+ ${task.notes}` : ""), task.updated_at ?? task.created_at);
7754
+ stats.tasks += 1;
7755
+ }
7756
+ }
7757
+ const completedPath = join18(cwd, COMPLETED_PATH);
7758
+ if (existsSync18(completedPath)) {
7759
+ const lines = readFileSync6(completedPath, "utf-8").split("\n").filter((line) => line.trim().length > 0);
7760
+ const insertCompleted = this.db.prepare(
7761
+ `INSERT OR REPLACE INTO completed_tasks (id, description, status, created_at, updated_at, notes)
7762
+ VALUES (?, ?, ?, ?, ?, ?)`
7763
+ );
7764
+ const insertFts = this.db.prepare(
7765
+ `INSERT INTO governance_fts (source, record_id, text, timestamp)
7766
+ VALUES (?, ?, ?, ?)`
7767
+ );
7768
+ for (const line of lines) {
7769
+ const task = JSON.parse(line);
7770
+ insertCompleted.run(task.id, task.description, task.status, task.created_at, task.updated_at ?? null, task.notes ?? null);
7771
+ insertFts.run("completed_task", task.id, task.description + (task.notes ? `
7772
+ ${task.notes}` : ""), task.updated_at ?? task.created_at);
7773
+ stats.completedTasks += 1;
7774
+ }
7775
+ }
7776
+ const handoffsPath = join18(cwd, HANDOFFS_PATH);
7777
+ if (existsSync18(handoffsPath)) {
7778
+ const lines = readFileSync6(handoffsPath, "utf-8").split("\n").filter((line) => line.trim().length > 0);
7779
+ const insertHandoff = this.db.prepare(
7780
+ `INSERT OR REPLACE INTO handoffs (id, timestamp, from_agent, reason, summary, next_actions)
7781
+ VALUES (?, ?, ?, ?, ?, ?)`
7782
+ );
7783
+ const insertFts = this.db.prepare(
7784
+ `INSERT INTO governance_fts (source, record_id, text, timestamp)
7785
+ VALUES (?, ?, ?, ?)`
7786
+ );
7787
+ for (const line of lines) {
7788
+ const entry = JSON.parse(line);
7789
+ const id = `${entry.timestamp}-${entry.from_agent ?? "unknown"}`;
7790
+ const nextActions = entry.next_actions.join("\n");
7791
+ insertHandoff.run(id, entry.timestamp, entry.from_agent ?? null, entry.reason, entry.summary, nextActions);
7792
+ insertFts.run("handoff", id, `${entry.summary}
7793
+ ${nextActions}`, entry.timestamp);
7794
+ stats.handoffs += 1;
7795
+ }
7796
+ }
7797
+ const decisionsPath = join18(cwd, DECISIONS_PATH);
7798
+ if (existsSync18(decisionsPath)) {
7799
+ const lines = readFileSync6(decisionsPath, "utf-8").split("\n").filter((line) => line.trim().length > 0);
7800
+ const insertDecision = this.db.prepare(
7801
+ `INSERT OR REPLACE INTO decisions (id, timestamp, category, change_reason, updated_by, diff_summary)
7802
+ VALUES (?, ?, ?, ?, ?, ?)`
7803
+ );
7804
+ const insertFts = this.db.prepare(
7805
+ `INSERT INTO governance_fts (source, record_id, text, timestamp)
7806
+ VALUES (?, ?, ?, ?)`
7807
+ );
7808
+ for (const line of lines) {
7809
+ const entry = JSON.parse(line);
7810
+ const id = `${entry.timestamp}-${entry.category}`;
7811
+ insertDecision.run(
7812
+ id,
7813
+ entry.timestamp,
7814
+ entry.category,
7815
+ entry.change_reason,
7816
+ entry.updated_by ?? null,
7817
+ entry.diff_summary ?? null
7818
+ );
7819
+ insertFts.run("decision", id, `${entry.change_reason}${entry.diff_summary ? `
7820
+ ${entry.diff_summary}` : ""}`, entry.timestamp);
7821
+ stats.decisions += 1;
7822
+ }
7823
+ }
7824
+ return stats;
7825
+ }
7826
+ search(query, limit = 10) {
7827
+ if (!this.db) {
7828
+ throw new Error("GovernanceSqliteView not initialized. Call init() first.");
7829
+ }
7830
+ const rows = this.db.prepare(
7831
+ `SELECT source, record_id as recordId, text, timestamp, rank
7832
+ FROM governance_fts
7833
+ WHERE governance_fts MATCH ?
7834
+ ORDER BY rank
7835
+ LIMIT ?`
7836
+ ).all(query, limit);
7837
+ return rows;
7838
+ }
7839
+ listTasks(status2) {
7840
+ if (!this.db) {
7841
+ throw new Error("GovernanceSqliteView not initialized. Call init() first.");
7842
+ }
7843
+ if (status2) {
7844
+ return this.db.prepare(
7845
+ "SELECT id, description, status, created_at, updated_at, notes FROM tasks WHERE status = ? ORDER BY created_at"
7846
+ ).all(status2);
7847
+ }
7848
+ return this.db.prepare(
7849
+ "SELECT id, description, status, created_at, updated_at, notes FROM tasks ORDER BY created_at"
7850
+ ).all();
7851
+ }
7852
+ getLatestHandoff() {
7853
+ if (!this.db) {
7854
+ throw new Error("GovernanceSqliteView not initialized. Call init() first.");
7855
+ }
7856
+ const row = this.db.prepare(
7857
+ "SELECT timestamp, from_agent as fromAgent, reason, summary, next_actions as nextActions FROM handoffs ORDER BY timestamp DESC LIMIT 1"
7858
+ ).get();
7859
+ if (!row) return null;
7860
+ return {
7861
+ timestamp: row.timestamp,
7862
+ from_agent: row.fromAgent ?? void 0,
7863
+ reason: row.reason,
7864
+ summary: row.summary,
7865
+ next_actions: row.nextActions.split("\n").filter((item) => item.trim().length > 0)
7866
+ };
7867
+ }
7868
+ getArchitecture() {
7869
+ if (!this.db) {
7870
+ throw new Error("GovernanceSqliteView not initialized. Call init() first.");
7871
+ }
7872
+ const row = this.db.prepare(
7873
+ "SELECT version, last_updated, updated_by, change_reason, content FROM architecture LIMIT 1"
7874
+ ).get();
7875
+ if (!row) return null;
7876
+ return {
7877
+ content: row.content,
7878
+ meta: {
7879
+ version: row.version,
7880
+ last_updated: row.last_updated,
7881
+ updated_by: row.updated_by,
7882
+ change_reason: row.change_reason
7883
+ }
7884
+ };
7885
+ }
7886
+ };
7887
+
7888
+ // src/cli/governance.ts
7889
+ var ACTIVE_ARCH_PATH3 = join19(".archon", "active", "architecture.md");
7890
+ var ACTIVE_TASKS_PATH2 = join19(".archon", "active", "tasks.json");
7891
+ var CURRENT_CONTEXT_PATH = join19(".archon", "current_context.md");
7892
+ var HANDOFF_HISTORY_PATH = join19(".archon", "history", "handoffs.jsonl");
7893
+ var COMPLETED_TASKS_PATH = join19(".archon", "archive", "completed_tasks.jsonl");
7894
+ var TASK_STATUSES = ["pending", "in_progress", "verification", "done"];
7895
+ function isTaskStatus(value) {
7896
+ return typeof value === "string" && TASK_STATUSES.includes(value);
7897
+ }
7898
+ function resolveArchitecturePath2(cwd) {
7899
+ const agdPath = join19(cwd, ACTIVE_ARCH_PATH3);
7900
+ if (existsSync19(agdPath)) {
7901
+ return { path: agdPath, source: "agd" };
7902
+ }
7903
+ const legacyPath = join19(cwd, "ARCHITECTURE.md");
7904
+ if (existsSync19(legacyPath)) {
7905
+ return { path: legacyPath, source: "legacy" };
7906
+ }
7907
+ return { path: null, source: null };
7908
+ }
7909
+ function parseTasks(raw) {
7910
+ if (!Array.isArray(raw)) return null;
7911
+ const tasks = [];
7912
+ for (const item of raw) {
7913
+ if (typeof item !== "object" || item === null) return null;
7914
+ const entry = item;
7915
+ if (typeof entry["id"] !== "string") return null;
7916
+ if (typeof entry["description"] !== "string") return null;
7917
+ if (!isTaskStatus(entry["status"])) return null;
7918
+ if (typeof entry["created_at"] !== "string") return null;
7919
+ tasks.push({
7920
+ id: entry["id"],
7921
+ description: entry["description"],
7922
+ status: entry["status"],
7923
+ created_at: entry["created_at"],
7924
+ parent_id: typeof entry["parent_id"] === "string" ? entry["parent_id"] : void 0,
7925
+ assigned_to: typeof entry["assigned_to"] === "string" ? entry["assigned_to"] : void 0,
7926
+ updated_at: typeof entry["updated_at"] === "string" ? entry["updated_at"] : void 0,
7927
+ notes: typeof entry["notes"] === "string" ? entry["notes"] : void 0
7928
+ });
7929
+ }
7930
+ return tasks;
7931
+ }
7932
+ function countTaskStatuses(tasks) {
7933
+ const counts = {
7934
+ pending: 0,
7935
+ in_progress: 0,
7936
+ verification: 0,
7937
+ done: 0
7938
+ };
7939
+ for (const task of tasks) {
7940
+ if (counts[task.status] === void 0) continue;
7941
+ counts[task.status] += 1;
7942
+ }
7943
+ return counts;
7944
+ }
7945
+ function parseContextMeta(content) {
7946
+ const timestampMatch = content.match(/^Timestamp:\s*(.+)$/m);
7947
+ const reasonMatch = content.match(/^Reason:\s*(.+)$/m);
7948
+ return {
7949
+ timestamp: timestampMatch?.[1]?.trim(),
7950
+ reason: reasonMatch?.[1]?.trim()
7951
+ };
7952
+ }
7953
+ function renderStatusCounts(counts) {
7954
+ const total = Object.values(counts).reduce((sum, value) => sum + value, 0);
7955
+ if (total === 0) return;
7956
+ console.log(chalk17.dim(` Tasks: ${total} total`));
7957
+ console.log(
7958
+ chalk17.dim(
7959
+ ` pending: ${counts.pending} | in_progress: ${counts.in_progress} | verification: ${counts.verification} | done: ${counts.done}`
7960
+ )
7961
+ );
7962
+ }
7963
+ function lineCount(content) {
7964
+ const trimmed = content.trim();
7965
+ if (!trimmed) return 0;
7966
+ return trimmed.split("\n").length;
7967
+ }
7968
+ function createGovernanceCommand() {
7969
+ const governance = new Command2("governance").alias("gov").description("Manage governance store (AGD)");
7970
+ governance.command("status").description("Show governance status from AGD store").action(async () => {
7971
+ const cwd = process.cwd();
7972
+ const store = new GovernanceStore(cwd);
7973
+ store.ensureStructure();
7974
+ console.log(chalk17.bold("\nGovernance Status\n"));
7975
+ const archInfo = resolveArchitecturePath2(cwd);
7976
+ if (archInfo.path) {
7977
+ const parser = new ArchitectureParser(archInfo.path);
7978
+ const parsed = await parser.parse();
7979
+ if (parsed.success && parsed.schema) {
7980
+ const posture = parsed.schema.qualityLevel?.posture ?? "unknown";
7981
+ console.log(chalk17.green(" \u2713") + ` Architecture (${archInfo.source})`);
7982
+ console.log(chalk17.dim(` posture: ${posture}`));
7983
+ console.log(chalk17.dim(` invariants: ${parsed.schema.invariants.length}`));
7984
+ console.log(chalk17.dim(` protected paths: ${parsed.schema.protectedPaths.length}`));
7985
+ } else {
7986
+ console.log(chalk17.yellow(" ! Architecture present but failed to parse"));
7987
+ }
7988
+ } else {
7989
+ console.log(chalk17.yellow(" \u25CB No architecture file found"));
7990
+ }
7991
+ const tasksPath = join19(cwd, ACTIVE_TASKS_PATH2);
7992
+ if (existsSync19(tasksPath)) {
7993
+ try {
7994
+ const tasksRaw = JSON.parse(readFileSync7(tasksPath, "utf-8"));
7995
+ const tasks2 = parseTasks(tasksRaw);
7996
+ if (tasks2) {
7997
+ renderStatusCounts(countTaskStatuses(tasks2));
7998
+ } else {
7999
+ console.log(chalk17.yellow(" ! tasks.json present but invalid"));
8000
+ }
8001
+ } catch {
8002
+ console.log(chalk17.yellow(" ! tasks.json present but unreadable"));
8003
+ }
8004
+ }
8005
+ const contextPath = join19(cwd, CURRENT_CONTEXT_PATH);
8006
+ if (existsSync19(contextPath)) {
8007
+ const content = readFileSync7(contextPath, "utf-8");
8008
+ const meta = parseContextMeta(content);
8009
+ console.log(chalk17.dim(` Handoff: ${meta.timestamp ?? "present"}`));
8010
+ if (meta.reason) {
8011
+ console.log(chalk17.dim(` reason: ${meta.reason}`));
8012
+ }
8013
+ }
8014
+ const handoffHistoryPath = join19(cwd, HANDOFF_HISTORY_PATH);
8015
+ if (existsSync19(handoffHistoryPath)) {
8016
+ const count = lineCount(readFileSync7(handoffHistoryPath, "utf-8"));
8017
+ if (count > 0) {
8018
+ console.log(chalk17.dim(` Handoff entries: ${count}`));
8019
+ }
8020
+ }
8021
+ const completedPath = join19(cwd, COMPLETED_TASKS_PATH);
8022
+ if (existsSync19(completedPath)) {
8023
+ const count = lineCount(readFileSync7(completedPath, "utf-8"));
8024
+ if (count > 0) {
8025
+ console.log(chalk17.dim(` Completed tasks archived: ${count}`));
8026
+ }
8027
+ }
8028
+ console.log("");
8029
+ });
8030
+ const architecture = governance.command("architecture").description("Read or update governance architecture");
8031
+ architecture.command("show").description("Show active architecture content").option("--raw", "Show full file including frontmatter").action(async (options) => {
8032
+ const cwd = process.cwd();
8033
+ const store = new GovernanceStore(cwd);
8034
+ const archInfo = resolveArchitecturePath2(cwd);
8035
+ if (!archInfo.path) {
8036
+ console.log(chalk17.yellow("No architecture file found."));
8037
+ return;
8038
+ }
8039
+ if (options.raw) {
8040
+ const raw = readFileSync7(archInfo.path, "utf-8");
8041
+ console.log(raw.trimEnd());
8042
+ return;
8043
+ }
8044
+ if (archInfo.source === "agd") {
8045
+ const result = await store.readArchitecture();
8046
+ if (!result.ok) {
8047
+ console.log(chalk17.red(`Failed to read architecture: ${result.error}`));
8048
+ return;
8049
+ }
8050
+ if (!result.value) {
8051
+ console.log(chalk17.yellow("Architecture file is empty."));
8052
+ return;
8053
+ }
8054
+ console.log(result.value);
8055
+ return;
8056
+ }
8057
+ const legacyRaw = readFileSync7(archInfo.path, "utf-8");
8058
+ const legacyParsed = matter4(legacyRaw);
8059
+ const legacyContent = legacyParsed.content.trim();
8060
+ if (!legacyContent) {
8061
+ console.log(chalk17.yellow("Architecture file is empty."));
8062
+ return;
8063
+ }
8064
+ console.log(legacyContent);
8065
+ });
8066
+ architecture.command("update").description("Update active architecture with change reason").requiredOption("-f, --file <path>", "Path to new architecture content").requiredOption("-r, --reason <text>", "Reason for the change (required)").option("-b, --by <name>", "Updated by (optional)").action(async (options) => {
8067
+ const cwd = process.cwd();
8068
+ const filePath = options.file;
8069
+ if (!existsSync19(filePath)) {
8070
+ console.log(chalk17.red(`File not found: ${filePath}`));
8071
+ process.exit(1);
8072
+ }
8073
+ const content = await readFile12(filePath, "utf-8");
8074
+ const store = new GovernanceStore(cwd);
8075
+ const result = await store.updateArchitecture(content, options.reason, options.by);
8076
+ if (!result.ok) {
8077
+ console.log(chalk17.red(`Failed to update architecture: ${result.error}`));
8078
+ process.exit(1);
8079
+ }
8080
+ console.log(chalk17.green("\u2713 Architecture updated"));
8081
+ });
8082
+ const tasks = governance.command("task").description("Update tasks in governance store");
8083
+ 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) => {
8084
+ const status2 = options.status;
8085
+ if (!isTaskStatus(status2)) {
8086
+ console.log(chalk17.red(`Invalid status: ${options.status}`));
8087
+ process.exit(1);
8088
+ }
8089
+ const store = new GovernanceStore(process.cwd());
8090
+ const result = await store.updateTask(taskId, status2, options.notes);
8091
+ if (!result.ok) {
8092
+ console.log(chalk17.red(`Failed to update task: ${result.error}`));
8093
+ process.exit(1);
8094
+ }
8095
+ console.log(chalk17.green(`\u2713 Task ${taskId} updated to ${status2}`));
8096
+ });
8097
+ 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) => {
8098
+ const store = new GovernanceStore(process.cwd());
8099
+ const entry = {
8100
+ timestamp: options.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
8101
+ from_agent: options.from,
8102
+ reason: options.reason,
8103
+ summary: options.summary,
8104
+ next_actions: options.next
8105
+ };
8106
+ const result = await store.logHandoff(entry);
8107
+ if (!result.ok) {
8108
+ console.log(chalk17.red(`Failed to log handoff: ${result.error}`));
8109
+ process.exit(1);
8110
+ }
8111
+ console.log(chalk17.green("\u2713 Handoff logged"));
8112
+ });
8113
+ 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) => {
8114
+ const result = await migrateLegacyGovernance({
8115
+ cwd: process.cwd(),
8116
+ removeLegacy: options.removeLegacy,
8117
+ dryRun: options.dryRun,
8118
+ updatedBy: options.by
8119
+ });
8120
+ console.log(chalk17.bold("\nMigration Summary"));
8121
+ console.log(
8122
+ result.migratedArchitecture ? chalk17.green(" \u2713 Architecture migrated") : chalk17.dim(" \u25CB Architecture migration skipped")
8123
+ );
8124
+ console.log(
8125
+ result.migratedTasks ? chalk17.green(" \u2713 Tasks migrated") : chalk17.dim(" \u25CB Tasks migration skipped")
8126
+ );
8127
+ if (result.archivedLegacyFiles.length > 0) {
8128
+ console.log(chalk17.dim(" Archived legacy files:"));
8129
+ for (const file of result.archivedLegacyFiles) {
8130
+ console.log(chalk17.dim(` - ${file}`));
8131
+ }
8132
+ }
8133
+ if (result.warnings.length > 0) {
8134
+ console.log(chalk17.yellow("\nWarnings:"));
8135
+ for (const warning of result.warnings) {
8136
+ console.log(chalk17.yellow(` - ${warning}`));
8137
+ }
8138
+ }
8139
+ console.log("");
8140
+ });
8141
+ governance.command("sqlite-init").description("Initialize or refresh local governance SQLite DB").option("--db <path>", "Override DB path (default: .archon/governance.db)").action(async (options) => {
8142
+ const cwd = process.cwd();
8143
+ const view = new GovernanceSqliteView({ dbPath: options.db ?? ".archon/governance.db" });
8144
+ view.init(cwd);
8145
+ await view.loadFromDisk(cwd);
8146
+ view.close();
8147
+ console.log(chalk17.green("\u2713 Governance SQLite DB initialized"));
8148
+ });
8149
+ return governance;
8150
+ }
8151
+
7111
8152
  // src/cli/index.ts
7112
- var program = new Command2();
8153
+ var program = new Command3();
7113
8154
  program.name("archon").description("Local-first AI-powered development governance").version(getCurrentVersion()).action(async () => {
7114
8155
  const cwd = process.cwd();
7115
8156
  const wasInitialized = isInitialized(cwd);
7116
8157
  if (!wasInitialized) {
7117
- console.log(chalk17.blue("\nArchonDev is not initialized in this folder.\n"));
8158
+ console.log(chalk18.blue("\nArchonDev is not initialized in this folder.\n"));
7118
8159
  await init({ analyze: true, git: true });
7119
8160
  }
7120
8161
  await start({ skipGovernanceBanner: !wasInitialized });
@@ -7122,7 +8163,7 @@ program.name("archon").description("Local-first AI-powered development governanc
7122
8163
  program.command("login").description("Authenticate with ArchonDev").option("-p, --provider <provider>", "OAuth provider (github or google)", "github").action(async (options) => {
7123
8164
  const provider = options.provider;
7124
8165
  if (provider !== "github" && provider !== "google") {
7125
- console.error(chalk17.red('Invalid provider. Use "github" or "google"'));
8166
+ console.error(chalk18.red('Invalid provider. Use "github" or "google"'));
7126
8167
  process.exit(1);
7127
8168
  }
7128
8169
  await login(provider);
@@ -7256,6 +8297,7 @@ reviewCommand.action(async () => {
7256
8297
  await reviewStatus();
7257
8298
  });
7258
8299
  program.addCommand(createDepsCommand());
8300
+ program.addCommand(createGovernanceCommand());
7259
8301
  var a11yCommand = program.command("a11y").description("Accessibility checking and compliance for web deployments");
7260
8302
  a11yCommand.command("check").description("Run WCAG 2.2 AA accessibility audit").option("-v, --verbose", "Show all issues including minor ones").option("-f, --format <format>", "Output format (text or json)", "text").action(async (options) => {
7261
8303
  await a11yCheck(options);
@@ -7316,7 +8358,7 @@ cleanupCmd.command("check").description("Analyze workspace for bloat and mainten
7316
8358
  cleanupCmd.command("run").description("Execute cleanup (archive old entries, remove stale files)").action(cleanupRun);
7317
8359
  cleanupCmd.command("auto").description("Enable/disable automatic cleanup checks").argument("[action]", "enable, disable, or status", "status").action(async (action) => {
7318
8360
  if (action !== "enable" && action !== "disable" && action !== "status") {
7319
- console.error(chalk17.red("Invalid action. Use: enable, disable, or status"));
8361
+ console.error(chalk18.red("Invalid action. Use: enable, disable, or status"));
7320
8362
  process.exit(1);
7321
8363
  }
7322
8364
  await cleanupAuto(action);