opencode-sdlc-plugin 0.3.2 → 1.0.0-alpha.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 (48) hide show
  1. package/README.md +90 -17
  2. package/config/presets/copilot-only.json +12 -5
  3. package/config/presets/enterprise.json +7 -7
  4. package/config/presets/event-modeling.json +6 -6
  5. package/config/presets/minimal.json +2 -2
  6. package/config/presets/solo-quick.json +2 -2
  7. package/config/presets/standard.json +6 -6
  8. package/config/presets/strict-tdd.json +7 -7
  9. package/config/schemas/athena.schema.json +4 -4
  10. package/config/schemas/sdlc.schema.json +101 -5
  11. package/dist/cli/index.js +781 -279
  12. package/dist/cli/index.js.map +1 -1
  13. package/dist/index.d.ts +427 -65
  14. package/dist/index.js +5239 -1924
  15. package/dist/index.js.map +1 -1
  16. package/dist/plugin/index.js +5206 -1930
  17. package/dist/plugin/index.js.map +1 -1
  18. package/package.json +1 -1
  19. package/prompts/agents/adr.md +234 -0
  20. package/prompts/agents/architect.md +204 -0
  21. package/prompts/agents/design-facilitator.md +237 -0
  22. package/prompts/agents/discovery.md +260 -0
  23. package/prompts/agents/domain.md +148 -34
  24. package/prompts/agents/file-updater.md +132 -0
  25. package/prompts/agents/green.md +119 -40
  26. package/prompts/agents/gwt.md +352 -0
  27. package/prompts/agents/model-checker.md +332 -0
  28. package/prompts/agents/red.md +112 -21
  29. package/prompts/agents/story.md +196 -0
  30. package/prompts/agents/ux.md +239 -0
  31. package/prompts/agents/workflow-designer.md +386 -0
  32. package/prompts/modes/architect.md +219 -0
  33. package/prompts/modes/build.md +150 -0
  34. package/prompts/modes/model.md +211 -0
  35. package/prompts/modes/plan.md +186 -0
  36. package/prompts/modes/pm.md +269 -0
  37. package/prompts/modes/prd.md +238 -0
  38. package/commands/sdlc-adr.md +0 -265
  39. package/commands/sdlc-debug.md +0 -376
  40. package/commands/sdlc-design.md +0 -246
  41. package/commands/sdlc-dev.md +0 -544
  42. package/commands/sdlc-info.md +0 -325
  43. package/commands/sdlc-parallel.md +0 -283
  44. package/commands/sdlc-recall.md +0 -213
  45. package/commands/sdlc-remember.md +0 -136
  46. package/commands/sdlc-research.md +0 -343
  47. package/commands/sdlc-review.md +0 -265
  48. package/commands/sdlc-status.md +0 -297
package/dist/cli/index.js CHANGED
@@ -2,13 +2,13 @@
2
2
  import { join, dirname } from 'path';
3
3
  import { fileURLToPath } from 'url';
4
4
  import { confirm, select, input, number, checkbox } from '@inquirer/prompts';
5
- import chalk4 from 'chalk';
5
+ import chalk6 from 'chalk';
6
6
  import { Command } from 'commander';
7
7
  import { existsSync, readFileSync, mkdirSync, copyFileSync, unlinkSync, readdirSync, renameSync, writeFileSync } from 'fs';
8
8
  import { homedir } from 'os';
9
9
  import { exec, execSync } from 'child_process';
10
10
  import ora5 from 'ora';
11
- import { mkdir, writeFile, readdir, copyFile, rm } from 'fs/promises';
11
+ import { mkdir, writeFile, copyFile, readdir, rm } from 'fs/promises';
12
12
  import { promisify } from 'util';
13
13
  import { z } from 'zod';
14
14
  import * as semver from 'semver';
@@ -122,59 +122,65 @@ function createModelChoices(models) {
122
122
  }
123
123
  function getSuggestedModel(role, _subscriptions, availableModels) {
124
124
  const suggestions = {
125
- sisyphus: [
125
+ marvin: [
126
+ "openai/gpt-5.2-codex",
126
127
  "anthropic/claude-sonnet-4-5-thinking",
127
128
  "anthropic/claude-opus-4-5-thinking",
128
129
  "openai/gpt-5.1-high",
129
- "google/gemini-2.5-pro",
130
+ "google/gemini-3-pro-preview",
131
+ "github-copilot/gpt-5.2-codex",
130
132
  "github-copilot/claude-sonnet-4.5",
131
- "github-copilot/gpt-5.1",
132
- "github-copilot/gemini-2.5-pro"
133
+ "github-copilot/gpt-5.1"
133
134
  ],
134
135
  oracle: [
136
+ "openai/gpt-5.2",
135
137
  "openai/gpt-5.1-high",
136
138
  "anthropic/claude-opus-4-5-thinking",
137
139
  "anthropic/claude-sonnet-4-5-thinking",
138
- "google/gemini-2.5-pro",
140
+ "google/gemini-3-pro-preview",
141
+ "github-copilot/gpt-5.2",
139
142
  "github-copilot/gpt-5.1",
140
- "github-copilot/claude-opus-4.5",
141
- "github-copilot/claude-sonnet-4.5"
143
+ "github-copilot/claude-opus-4.5"
142
144
  ],
143
145
  librarian: [
144
146
  "anthropic/claude-sonnet-4-5",
145
147
  "openai/gpt-4o",
146
148
  "google/gemini-2.5-flash",
149
+ "google/gemini-3-flash-preview",
147
150
  "github-copilot/claude-haiku-4.5",
148
151
  "github-copilot/gpt-5-mini"
149
152
  ],
150
153
  frontend: [
151
154
  "anthropic/claude-sonnet-4-5",
152
- "google/gemini-2.5-pro",
155
+ "openai/gpt-5.2-codex",
156
+ "google/gemini-3-pro-preview",
153
157
  "openai/gpt-4o",
154
158
  "github-copilot/claude-sonnet-4.5",
155
- "github-copilot/gemini-2.5-pro"
159
+ "github-copilot/gpt-5.2-codex"
156
160
  ],
157
161
  documentWriter: [
162
+ "google/gemini-3-pro-preview",
158
163
  "google/gemini-2.5-pro",
159
164
  "anthropic/claude-sonnet-4-5",
160
165
  "openai/gpt-4o",
161
- "github-copilot/gemini-2.5-pro",
166
+ "github-copilot/gemini-3-pro",
162
167
  "github-copilot/claude-sonnet-4.5"
163
168
  ],
164
169
  multimodalLooker: [
170
+ "google/gemini-3-flash-preview",
165
171
  "google/gemini-2.5-flash",
166
172
  "openai/gpt-4o",
167
173
  "anthropic/claude-sonnet-4-5",
168
- "github-copilot/gemini-3-flash",
174
+ "github-copilot/gemini-3-flash-preview",
169
175
  "github-copilot/gpt-5-mini"
170
176
  ],
171
177
  explore: [
178
+ "google/gemini-3-flash-preview",
172
179
  "google/gemini-2.5-flash",
173
180
  "anthropic/claude-sonnet-4-5",
174
181
  "openai/gpt-4o",
175
- "github-copilot/claude-haiku-4.5",
176
- "github-copilot/gpt-5-mini",
177
- "github-copilot/gemini-3-flash"
182
+ "github-copilot/gemini-3-flash-preview",
183
+ "github-copilot/claude-haiku-4.5"
178
184
  ]
179
185
  };
180
186
  const roleDefaults = suggestions[role] || [];
@@ -194,9 +200,9 @@ async function gatherModels(subscriptions, defaults, customModels) {
194
200
  );
195
201
  }
196
202
  const choices = createModelChoices(availableModels);
197
- const sisyphusDefault = getValidModelOrFallback(
198
- defaults?.sisyphus,
199
- "sisyphus",
203
+ const marvinDefault = getValidModelOrFallback(
204
+ defaults?.marvin,
205
+ "marvin",
200
206
  subscriptions,
201
207
  availableModels
202
208
  );
@@ -212,10 +218,10 @@ async function gatherModels(subscriptions, defaults, customModels) {
212
218
  subscriptions,
213
219
  availableModels
214
220
  );
215
- const sisyphus = await select({
216
- message: "Model for Sisyphus (main orchestrator - implements stories)?",
221
+ const marvin = await select({
222
+ message: "Model for Marvin (main orchestrator - implements stories)?",
217
223
  choices,
218
- default: sisyphusDefault
224
+ default: marvinDefault
219
225
  });
220
226
  const oracle = await select({
221
227
  message: "Model for Oracle (debugging and complex reasoning)?",
@@ -246,7 +252,7 @@ async function gatherModels(subscriptions, defaults, customModels) {
246
252
  availableModels
247
253
  );
248
254
  return {
249
- sisyphus,
255
+ marvin,
250
256
  oracle,
251
257
  librarian,
252
258
  frontend,
@@ -267,7 +273,7 @@ function validatePresetModels(presetModels, subscriptions, customModels) {
267
273
  );
268
274
  }
269
275
  };
270
- checkModel(presetModels.sisyphus, "Sisyphus");
276
+ checkModel(presetModels.marvin, "Marvin");
271
277
  checkModel(presetModels.oracle, "Oracle");
272
278
  checkModel(presetModels.librarian, "Librarian");
273
279
  checkModel(presetModels.frontend, "Frontend");
@@ -317,7 +323,7 @@ var init_models = __esm({
317
323
  id: "openai/gpt-5.1",
318
324
  name: "GPT-5.1",
319
325
  provider: "openai",
320
- description: "Latest GPT model"
326
+ description: "GPT-5.1 base model"
321
327
  },
322
328
  {
323
329
  id: "openai/gpt-5.1-high",
@@ -325,12 +331,24 @@ var init_models = __esm({
325
331
  provider: "openai",
326
332
  description: "GPT-5.1 with high reasoning effort"
327
333
  },
334
+ {
335
+ id: "openai/gpt-5.2",
336
+ name: "GPT-5.2",
337
+ provider: "openai",
338
+ description: "Latest GPT model"
339
+ },
340
+ {
341
+ id: "openai/gpt-5.2-codex",
342
+ name: "GPT-5.2 Codex",
343
+ provider: "openai",
344
+ description: "Code-optimized GPT-5.2"
345
+ },
328
346
  // Google models
329
347
  {
330
348
  id: "google/gemini-2.5-pro",
331
349
  name: "Gemini 2.5 Pro",
332
350
  provider: "google",
333
- description: "Latest Gemini Pro model"
351
+ description: "Gemini 2.5 Pro model"
334
352
  },
335
353
  {
336
354
  id: "google/gemini-2.5-flash",
@@ -339,10 +357,16 @@ var init_models = __esm({
339
357
  description: "Fast Gemini model"
340
358
  },
341
359
  {
342
- id: "google/gemini-2.0-flash",
343
- name: "Gemini 2.0 Flash",
360
+ id: "google/gemini-3-flash-preview",
361
+ name: "Gemini 3 Flash (Preview)",
344
362
  provider: "google",
345
- description: "Previous generation fast model"
363
+ description: "Gemini 3 Flash preview - fast and efficient"
364
+ },
365
+ {
366
+ id: "google/gemini-3-pro-preview",
367
+ name: "Gemini 3 Pro (Preview)",
368
+ provider: "google",
369
+ description: "Latest Gemini 3 Pro preview"
346
370
  },
347
371
  // GitHub Copilot models (routed through Copilot - smaller context, no thinking)
348
372
  // Free tier models
@@ -401,6 +425,12 @@ var init_models = __esm({
401
425
  provider: "github-copilot",
402
426
  description: "Latest GPT through GitHub Copilot"
403
427
  },
428
+ {
429
+ id: "github-copilot/gpt-5.2-codex",
430
+ name: "GPT-5.2 Codex (via Copilot)",
431
+ provider: "github-copilot",
432
+ description: "Code-optimized GPT-5.2 through GitHub Copilot"
433
+ },
404
434
  {
405
435
  id: "github-copilot/gemini-2.5-pro",
406
436
  name: "Gemini 2.5 Pro (via Copilot)",
@@ -507,11 +537,11 @@ var execAsync = promisify(exec);
507
537
  function getPackageRoot() {
508
538
  const currentFileDir = dirname(fileURLToPath(import.meta.url));
509
539
  const bundledRoot = join(currentFileDir, "..", "..");
510
- if (existsSync(join(bundledRoot, "commands"))) {
540
+ if (existsSync(join(bundledRoot, "prompts"))) {
511
541
  return bundledRoot;
512
542
  }
513
543
  const devRoot = join(currentFileDir, "..", "..", "..");
514
- if (existsSync(join(devRoot, "commands"))) {
544
+ if (existsSync(join(devRoot, "prompts"))) {
515
545
  return devRoot;
516
546
  }
517
547
  return bundledRoot;
@@ -616,26 +646,73 @@ var FileManager = class {
616
646
  }
617
647
  /**
618
648
  * Copy bridge commands from package to config directory
649
+ *
650
+ * @deprecated Bridge commands have been removed in v1.0.
651
+ * This method now returns an empty array for backwards compatibility.
652
+ * Use mode-based workflow instead.
619
653
  */
620
654
  async copyCommands() {
621
- const commandsDir = CONFIG_PATHS.commandsDir;
622
- await this.ensureDir(commandsDir);
655
+ return [];
656
+ }
657
+ /**
658
+ * Copy Marvin mode agent files to project .opencode/agent directory
659
+ *
660
+ * @param projectDir - The project directory to copy to
661
+ * @param enabledModes - Array of enabled modes to copy
662
+ * @returns Array of copied file names
663
+ */
664
+ async copyAgentModes(projectDir, enabledModes) {
665
+ const agentDir = join(projectDir, ".opencode", "agent");
666
+ await this.ensureDir(agentDir);
623
667
  const packageRoot = getPackageRoot();
624
- const sourceCommandsDir = join(packageRoot, "commands");
668
+ const sourceModesDir = join(packageRoot, "prompts", "modes");
625
669
  const copiedFiles = [];
626
- if (existsSync(sourceCommandsDir)) {
627
- const files = await readdir(sourceCommandsDir);
628
- for (const file of files) {
629
- if (file.endsWith(".md")) {
630
- const sourcePath = join(sourceCommandsDir, file);
631
- const destPath = join(commandsDir, file);
670
+ const modeFileMap = {
671
+ build: "build.md",
672
+ discover: "plan.md",
673
+ // Discover mode overrides Plan agent
674
+ model: "model.md",
675
+ prd: "prd.md",
676
+ architect: "architect.md",
677
+ pm: "pm.md"
678
+ };
679
+ if (existsSync(sourceModesDir)) {
680
+ for (const mode of enabledModes) {
681
+ const sourceFile = modeFileMap[mode];
682
+ if (!sourceFile) continue;
683
+ const sourcePath = join(sourceModesDir, sourceFile);
684
+ if (existsSync(sourcePath)) {
685
+ const destPath = join(agentDir, sourceFile);
632
686
  await copyFile(sourcePath, destPath);
633
- copiedFiles.push(file);
687
+ copiedFiles.push(sourceFile);
634
688
  }
635
689
  }
636
690
  }
637
691
  return copiedFiles;
638
692
  }
693
+ /**
694
+ * Remove agent mode files from project .opencode/agent directory
695
+ *
696
+ * @param projectDir - The project directory to remove from
697
+ * @returns Array of removed file names
698
+ */
699
+ async removeAgentModes(projectDir) {
700
+ const agentDir = join(projectDir, ".opencode", "agent");
701
+ const removedFiles = [];
702
+ if (!existsSync(agentDir)) {
703
+ return removedFiles;
704
+ }
705
+ const modeFiles = ["build.md", "plan.md", "model.md", "prd.md", "architect.md", "pm.md"];
706
+ const files = await readdir(agentDir);
707
+ for (const file of files) {
708
+ if (modeFiles.includes(file)) {
709
+ const filePath = join(agentDir, file);
710
+ await rm(filePath);
711
+ removedFiles.push(file);
712
+ }
713
+ }
714
+ return removedFiles;
715
+ }
639
716
  /**
640
717
  * Remove bridge commands from config directory
641
718
  */
@@ -727,39 +804,39 @@ var logger = {
727
804
  * Log an informational message
728
805
  */
729
806
  info: (message) => {
730
- console.log(chalk4.blue("i"), message);
807
+ console.log(chalk6.blue("i"), message);
731
808
  },
732
809
  /**
733
810
  * Log a success message
734
811
  */
735
812
  success: (message) => {
736
- console.log(chalk4.green("\u2713"), message);
813
+ console.log(chalk6.green("\u2713"), message);
737
814
  },
738
815
  /**
739
816
  * Log a warning message
740
817
  */
741
818
  warn: (message) => {
742
- console.log(chalk4.yellow("!"), message);
819
+ console.log(chalk6.yellow("!"), message);
743
820
  },
744
821
  /**
745
822
  * Log an error message
746
823
  */
747
824
  error: (message) => {
748
- console.log(chalk4.red("\u2716"), message);
825
+ console.log(chalk6.red("\u2716"), message);
749
826
  },
750
827
  /**
751
828
  * Log a debug message (only when DEBUG env var is set)
752
829
  */
753
830
  debug: (message) => {
754
831
  if (process.env.DEBUG) {
755
- console.log(chalk4.gray("[debug]"), message);
832
+ console.log(chalk6.gray("[debug]"), message);
756
833
  }
757
834
  },
758
835
  /**
759
836
  * Log a step in a process
760
837
  */
761
838
  step: (step, total, message) => {
762
- console.log(chalk4.cyan(`[${step}/${total}]`), message);
839
+ console.log(chalk6.cyan(`[${step}/${total}]`), message);
763
840
  },
764
841
  /**
765
842
  * Log a blank line
@@ -772,7 +849,7 @@ var logger = {
772
849
  */
773
850
  section: (title) => {
774
851
  console.log();
775
- console.log(chalk4.bold(title));
852
+ console.log(chalk6.bold(title));
776
853
  console.log();
777
854
  },
778
855
  /**
@@ -780,21 +857,21 @@ var logger = {
780
857
  */
781
858
  keyValue: (key, value, indent = 0) => {
782
859
  const padding = " ".repeat(indent);
783
- console.log(`${padding}${chalk4.gray(`${key}:`)} ${value}`);
860
+ console.log(`${padding}${chalk6.gray(`${key}:`)} ${value}`);
784
861
  },
785
862
  /**
786
863
  * Log a list item
787
864
  */
788
865
  listItem: (item, indent = 0) => {
789
866
  const padding = " ".repeat(indent);
790
- console.log(`${padding}${chalk4.gray("-")} ${item}`);
867
+ console.log(`${padding}${chalk6.gray("-")} ${item}`);
791
868
  },
792
869
  /**
793
870
  * Display the Sdlc banner
794
871
  */
795
872
  banner: () => {
796
873
  console.log(
797
- chalk4.cyan(`
874
+ chalk6.cyan(`
798
875
  \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
799
876
  \u2551 OPENCODE ATHENA \u2551
800
877
  \u2551 Strategic Wisdom Meets Practical Execution \u2551
@@ -810,7 +887,7 @@ var logger = {
810
887
  successBanner: (message) => {
811
888
  const line = "\u2550".repeat(message.length + 4);
812
889
  console.log(
813
- chalk4.green(`
890
+ chalk6.green(`
814
891
  \u2554${line}\u2557
815
892
  \u2551 ${message} \u2551
816
893
  \u255A${line}\u255D
@@ -938,13 +1015,16 @@ init_esm_shims();
938
1015
 
939
1016
  // src/shared/schemas.ts
940
1017
  init_esm_shims();
1018
+ var ProviderAuthMethodSchema = z.enum(["subscription", "api", "none"]);
941
1019
  var SubscriptionSchema = z.object({
942
1020
  claude: z.object({
943
1021
  enabled: z.boolean(),
1022
+ authMethod: ProviderAuthMethodSchema.default("subscription"),
944
1023
  tier: z.enum(["max5x", "max20x", "pro", "none"])
945
1024
  }),
946
1025
  openai: z.object({
947
- enabled: z.boolean()
1026
+ enabled: z.boolean(),
1027
+ authMethod: ProviderAuthMethodSchema.default("subscription")
948
1028
  }),
949
1029
  google: z.object({
950
1030
  enabled: z.boolean(),
@@ -956,6 +1036,17 @@ var SubscriptionSchema = z.object({
956
1036
  enabledModels: z.array(z.string()).optional()
957
1037
  })
958
1038
  });
1039
+ var SdlcModeSchema = z.enum(["discover", "model", "architect", "pm", "build"]);
1040
+ var ModesConfigSchema = z.object({
1041
+ default: SdlcModeSchema.default("build").describe("Default mode on startup"),
1042
+ eventModeling: z.boolean().default(true).describe("true=Model mode, false=PRD mode"),
1043
+ enabled: z.array(SdlcModeSchema).default(["discover", "model", "architect", "pm", "build"]).describe("Array of enabled modes")
1044
+ });
1045
+ var MemoryBackendSchema = z.enum(["memento", "stateless"]);
1046
+ var MemoryConfigSchema = z.object({
1047
+ backend: MemoryBackendSchema.default("stateless").describe("Memory backend type"),
1048
+ checkpointTtl: z.number().int().positive().default(86400).describe("How long to keep checkpoints in seconds")
1049
+ });
959
1050
  var GitHubStatusSchema = z.enum(["Backlog", "Ready", "In progress", "In review", "Done"]);
960
1051
  var GitHubConfigSchema = z.object({
961
1052
  owner: z.string().describe("GitHub repository owner (user or org)"),
@@ -975,7 +1066,11 @@ var TddConfigSchema = z.object({
975
1066
  mutationTesting: MutationTestingConfigSchema.default({
976
1067
  enabled: false,
977
1068
  requiredScore: 80
978
- })
1069
+ }),
1070
+ // New v1.0.0 fields
1071
+ domainVetoEnabled: z.boolean().default(true).describe("Enable domain agent veto power over type changes"),
1072
+ debateRounds: z.number().int().min(1).max(5).default(2).describe("Max debate rounds before escalation to user"),
1073
+ requireVerification: z.boolean().default(true).describe("Require test output evidence before phase transitions")
979
1074
  });
980
1075
  var EventModelingConfigSchema = z.object({
981
1076
  enabled: z.boolean().default(false).describe("Enable Event Modeling workflow"),
@@ -1040,7 +1135,7 @@ var RoutingConfigSchema = z.object({
1040
1135
  gemini: z.array(LLMProviderSchema).optional()
1041
1136
  }),
1042
1137
  agentOverrides: z.object({
1043
- sisyphus: AgentRoutingSchema.optional(),
1138
+ marvin: AgentRoutingSchema.optional(),
1044
1139
  oracle: AgentRoutingSchema.optional(),
1045
1140
  librarian: AgentRoutingSchema.optional(),
1046
1141
  frontend: AgentRoutingSchema.optional(),
@@ -1051,7 +1146,9 @@ var RoutingConfigSchema = z.object({
1051
1146
  autoFallback: z.boolean(),
1052
1147
  retryPeriodMs: z.number().min(0),
1053
1148
  notifyOnRateLimit: z.boolean()
1054
- })
1149
+ }),
1150
+ // New v1.0.0 field
1151
+ classifierModel: z.string().default("anthropic/claude-haiku").describe("Model for sdlc_classify_request tool (use cheapest available)")
1055
1152
  });
1056
1153
  var ThinkingLevelSchema = z.enum(["off", "low", "medium", "high"]);
1057
1154
  var AgentSettingsSchema = z.object({
@@ -1069,15 +1166,75 @@ var CustomModelDefinitionSchema = z.object({
1069
1166
  supportsTemperature: z.boolean().optional()
1070
1167
  }).optional()
1071
1168
  });
1169
+ var SubagentModelSchema = z.union([
1170
+ z.string().describe("Full model identifier (e.g., 'anthropic/claude-sonnet-4-20250514')"),
1171
+ z.literal("inherit").describe("Inherit model from marvin")
1172
+ ]);
1173
+ z.enum([
1174
+ // TDD agents
1175
+ "red",
1176
+ "green",
1177
+ "domain",
1178
+ "refactor",
1179
+ // Event modeling agents
1180
+ "discovery",
1181
+ "workflow",
1182
+ "gwt",
1183
+ "model-checker",
1184
+ // Architecture agents
1185
+ "architect",
1186
+ "adr",
1187
+ "design-facilitator",
1188
+ // Planning agents
1189
+ "story",
1190
+ "pm",
1191
+ "analyst",
1192
+ // Review agents
1193
+ "reviewer",
1194
+ "ux",
1195
+ "mutation"
1196
+ ]);
1197
+ var SubagentModelsSchema = z.object({
1198
+ // TDD agents
1199
+ red: SubagentModelSchema.optional().describe("Model for TDD red phase agent"),
1200
+ green: SubagentModelSchema.optional().describe("Model for TDD green phase agent"),
1201
+ domain: SubagentModelSchema.optional().describe("Model for domain modeling agent"),
1202
+ refactor: SubagentModelSchema.optional().describe("Model for refactoring agent"),
1203
+ // Event modeling agents
1204
+ discovery: SubagentModelSchema.optional().describe(
1205
+ "Model for discovery/domain exploration agent"
1206
+ ),
1207
+ workflow: SubagentModelSchema.optional().describe("Model for workflow design agent"),
1208
+ gwt: SubagentModelSchema.optional().describe("Model for GWT specification agent"),
1209
+ "model-checker": SubagentModelSchema.optional().describe(
1210
+ "Model for event model validation agent"
1211
+ ),
1212
+ // Architecture agents
1213
+ architect: SubagentModelSchema.optional().describe("Model for architect agent"),
1214
+ adr: SubagentModelSchema.optional().describe("Model for ADR creation agent"),
1215
+ "design-facilitator": SubagentModelSchema.optional().describe(
1216
+ "Model for design facilitation agent"
1217
+ ),
1218
+ // Planning agents
1219
+ story: SubagentModelSchema.optional().describe("Model for story/issue planning agent"),
1220
+ pm: SubagentModelSchema.optional().describe("Model for PM agent"),
1221
+ analyst: SubagentModelSchema.optional().describe("Model for business analyst agent"),
1222
+ // Review agents
1223
+ reviewer: SubagentModelSchema.optional().describe("Model for code reviewer agent"),
1224
+ ux: SubagentModelSchema.optional().describe("Model for UX review agent"),
1225
+ mutation: SubagentModelSchema.optional().describe("Model for mutation testing agent")
1226
+ });
1072
1227
  var ModelsSchema = z.object({
1073
- sisyphus: z.string().describe("Model for main orchestrator agent"),
1228
+ marvin: z.string().describe("Model for main orchestrator agent"),
1074
1229
  oracle: z.string().describe("Model for debugging/reasoning agent"),
1075
1230
  librarian: z.string().describe("Model for research/documentation agent"),
1076
1231
  frontend: z.string().optional().describe("Model for UI/UX agent"),
1077
1232
  documentWriter: z.string().optional().describe("Model for documentation generation agent"),
1078
1233
  multimodalLooker: z.string().optional().describe("Model for image analysis agent"),
1234
+ // New v1.0.0 field for subagent models
1235
+ subagents: SubagentModelsSchema.optional().describe("Per-subagent model overrides"),
1079
1236
  settings: z.object({
1080
- sisyphus: AgentSettingsSchema.optional(),
1237
+ marvin: AgentSettingsSchema.optional(),
1081
1238
  oracle: AgentSettingsSchema.optional(),
1082
1239
  librarian: AgentSettingsSchema.optional(),
1083
1240
  frontend: AgentSettingsSchema.optional(),
@@ -1092,6 +1249,9 @@ var SdlcConfigSchema = z.object({
1092
1249
  version: z.string(),
1093
1250
  subscriptions: SubscriptionSchema,
1094
1251
  models: ModelsSchema,
1252
+ // New v1.0.0 configuration
1253
+ modes: ModesConfigSchema.optional(),
1254
+ memory: MemoryConfigSchema.optional(),
1095
1255
  // New v0.3.0+ configuration (optional during migration)
1096
1256
  github: GitHubConfigSchema.optional(),
1097
1257
  tdd: TddConfigSchema.optional(),
@@ -1278,23 +1438,6 @@ async function doctor(options) {
1278
1438
  }
1279
1439
  }
1280
1440
  });
1281
- const commandsDirExists = fileManager.exists(CONFIG_PATHS.commandsDir);
1282
- results.push({
1283
- name: "Commands Directory",
1284
- status: commandsDirExists ? "pass" : "warn",
1285
- message: commandsDirExists ? "Exists" : "Not found",
1286
- fix: async () => {
1287
- const spinner = ora5("Creating commands directory...").start();
1288
- try {
1289
- await fileManager.ensureDir(CONFIG_PATHS.commandsDir);
1290
- await fileManager.copyCommands();
1291
- spinner.succeed("Commands directory created and populated");
1292
- } catch (err) {
1293
- spinner.fail("Failed to create commands directory");
1294
- throw err;
1295
- }
1296
- }
1297
- });
1298
1441
  if (sdlcConfigValid.valid) {
1299
1442
  const config = fileManager.readJsonFile(CONFIG_PATHS.globalSdlcConfig);
1300
1443
  const configVersion = config.version || "0.0.0";
@@ -1374,16 +1517,16 @@ async function doctor(options) {
1374
1517
  switch (result.status) {
1375
1518
  case "pass":
1376
1519
  icon = "\u2713";
1377
- color = chalk4.green;
1520
+ color = chalk6.green;
1378
1521
  break;
1379
1522
  case "warn":
1380
1523
  icon = "!";
1381
- color = chalk4.yellow;
1524
+ color = chalk6.yellow;
1382
1525
  hasWarnings = true;
1383
1526
  break;
1384
1527
  case "fail":
1385
1528
  icon = "\u2716";
1386
- color = chalk4.red;
1529
+ color = chalk6.red;
1387
1530
  hasFailures = true;
1388
1531
  if (result.fix) {
1389
1532
  fixableIssues.push(result);
@@ -1411,7 +1554,7 @@ async function doctor(options) {
1411
1554
  logger.blank();
1412
1555
  logger.info("Run 'opencode-sdlc doctor' again to verify fixes.");
1413
1556
  } else if (fixableIssues.length > 0) {
1414
- logger.info(`Run ${chalk4.cyan("opencode-sdlc doctor --fix")} to attempt automatic fixes.`);
1557
+ logger.info(`Run ${chalk6.cyan("opencode-sdlc doctor --fix")} to attempt automatic fixes.`);
1415
1558
  }
1416
1559
  } else if (hasWarnings) {
1417
1560
  logger.warn("Some checks have warnings, but Sdlc should work.");
@@ -1428,32 +1571,32 @@ async function info() {
1428
1571
  const sdlcConfig = fileManager.readJsonFile(CONFIG_PATHS.globalSdlcConfig);
1429
1572
  if (!sdlcConfig) {
1430
1573
  logger.warn("OpenCode SDLC is not installed.");
1431
- logger.info(`Run ${chalk4.cyan("opencode-sdlc install")} to get started.`);
1574
+ logger.info(`Run ${chalk6.cyan("opencode-sdlc install")} to get started.`);
1432
1575
  return;
1433
1576
  }
1434
1577
  logger.section("Version Information");
1435
1578
  logger.keyValue("Sdlc Version", sdlcConfig.version || VERSION);
1436
1579
  logger.section("Prerequisites");
1437
1580
  const prereqs = await checkPrerequisites();
1438
- const nodeStatus = prereqs.node.installed ? prereqs.node.compatible ? chalk4.green("\u2713") : chalk4.yellow("!") : chalk4.red("\u2716");
1581
+ const nodeStatus = prereqs.node.installed ? prereqs.node.compatible ? chalk6.green("\u2713") : chalk6.yellow("!") : chalk6.red("\u2716");
1439
1582
  logger.keyValue("Node.js", `${nodeStatus} ${prereqs.node.version || "not found"}`);
1440
- const opencodeStatus = prereqs.opencode.installed ? prereqs.opencode.compatible ? chalk4.green("\u2713") : chalk4.yellow("!") : chalk4.red("\u2716");
1583
+ const opencodeStatus = prereqs.opencode.installed ? prereqs.opencode.compatible ? chalk6.green("\u2713") : chalk6.yellow("!") : chalk6.red("\u2716");
1441
1584
  logger.keyValue("OpenCode", `${opencodeStatus} ${prereqs.opencode.version || "not found"}`);
1442
1585
  logger.section("Configured Providers");
1443
- const claudeStatus = sdlcConfig.subscriptions.claude.enabled ? chalk4.green("enabled") : chalk4.gray("disabled");
1586
+ const claudeStatus = sdlcConfig.subscriptions.claude.enabled ? chalk6.green("enabled") : chalk6.gray("disabled");
1444
1587
  logger.keyValue(
1445
1588
  "Claude",
1446
1589
  `${claudeStatus}${sdlcConfig.subscriptions.claude.tier !== "none" ? ` (${sdlcConfig.subscriptions.claude.tier})` : ""}`
1447
1590
  );
1448
- const openaiStatus = sdlcConfig.subscriptions.openai.enabled ? chalk4.green("enabled") : chalk4.gray("disabled");
1591
+ const openaiStatus = sdlcConfig.subscriptions.openai.enabled ? chalk6.green("enabled") : chalk6.gray("disabled");
1449
1592
  logger.keyValue("OpenAI", openaiStatus);
1450
- const googleStatus = sdlcConfig.subscriptions.google.enabled ? chalk4.green("enabled") : chalk4.gray("disabled");
1593
+ const googleStatus = sdlcConfig.subscriptions.google.enabled ? chalk6.green("enabled") : chalk6.gray("disabled");
1451
1594
  logger.keyValue(
1452
1595
  "Google",
1453
1596
  `${googleStatus}${sdlcConfig.subscriptions.google.authMethod !== "none" ? ` (${sdlcConfig.subscriptions.google.authMethod})` : ""}`
1454
1597
  );
1455
1598
  logger.section("Agent Models");
1456
- logger.keyValue("Sisyphus", sdlcConfig.models.sisyphus);
1599
+ logger.keyValue("Marvin", sdlcConfig.models.marvin);
1457
1600
  logger.keyValue("Oracle", sdlcConfig.models.oracle);
1458
1601
  logger.keyValue("Librarian", sdlcConfig.models.librarian);
1459
1602
  if (sdlcConfig.models.frontend) {
@@ -1565,18 +1708,18 @@ async function info() {
1565
1708
  }
1566
1709
  ];
1567
1710
  for (const feature of featureList) {
1568
- const status = feature.enabled ? chalk4.green("on") : chalk4.gray("off");
1711
+ const status = feature.enabled ? chalk6.green("on") : chalk6.gray("off");
1569
1712
  logger.keyValue(feature.name, status);
1570
1713
  }
1571
1714
  logger.section("MCP Servers");
1572
1715
  const mcps = sdlcConfig.mcps;
1573
- logger.keyValue("context7", mcps.context7 ? chalk4.green("on") : chalk4.gray("off"));
1574
- logger.keyValue("exa", mcps.exa ? chalk4.green("on") : chalk4.gray("off"));
1575
- logger.keyValue("grep_app", mcps.grepApp ? chalk4.green("on") : chalk4.gray("off"));
1716
+ logger.keyValue("context7", mcps.context7 ? chalk6.green("on") : chalk6.gray("off"));
1717
+ logger.keyValue("exa", mcps.exa ? chalk6.green("on") : chalk6.gray("off"));
1718
+ logger.keyValue("grep_app", mcps.grepApp ? chalk6.green("on") : chalk6.gray("off"));
1576
1719
  if ("memento" in mcps) {
1577
1720
  logger.keyValue(
1578
1721
  "memento",
1579
- mcps.memento ? chalk4.green("on") : chalk4.gray("off")
1722
+ mcps.memento ? chalk6.green("on") : chalk6.gray("off")
1580
1723
  );
1581
1724
  }
1582
1725
  logger.section("Installed Plugins");
@@ -1591,7 +1734,6 @@ async function info() {
1591
1734
  logger.section("Configuration Paths");
1592
1735
  logger.keyValue("Config Dir", CONFIG_PATHS.globalConfigDir);
1593
1736
  logger.keyValue("Sdlc Config", CONFIG_PATHS.globalSdlcConfig);
1594
- logger.keyValue("Commands Dir", CONFIG_PATHS.commandsDir);
1595
1737
  console.log();
1596
1738
  }
1597
1739
 
@@ -1616,7 +1758,7 @@ var MODEL_FAMILY_BASE_TEMPS = {
1616
1758
  };
1617
1759
  var ROLE_TEMP_ADJUSTMENTS = {
1618
1760
  oracle: -0.1,
1619
- sisyphus: 0,
1761
+ marvin: 0,
1620
1762
  librarian: 0.1,
1621
1763
  frontend: 0.2,
1622
1764
  documentWriter: 0.1,
@@ -1625,7 +1767,7 @@ var ROLE_TEMP_ADJUSTMENTS = {
1625
1767
  };
1626
1768
  var ROLE_DEFAULT_THINKING = {
1627
1769
  oracle: "high",
1628
- sisyphus: "medium",
1770
+ marvin: "medium",
1629
1771
  librarian: "low",
1630
1772
  frontend: "low",
1631
1773
  documentWriter: "low",
@@ -1788,10 +1930,12 @@ function buildMinimalConfig(answers) {
1788
1930
  subscriptions: {
1789
1931
  claude: {
1790
1932
  enabled: subscriptions.hasClaude,
1933
+ authMethod: subscriptions.claudeAuth || "none",
1791
1934
  tier: subscriptions.claudeTier || "none"
1792
1935
  },
1793
1936
  openai: {
1794
- enabled: subscriptions.hasOpenAI
1937
+ enabled: subscriptions.hasOpenAI,
1938
+ authMethod: subscriptions.openaiAuth || "none"
1795
1939
  },
1796
1940
  google: {
1797
1941
  enabled: subscriptions.hasGoogle,
@@ -1804,7 +1948,7 @@ function buildMinimalConfig(answers) {
1804
1948
  }
1805
1949
  },
1806
1950
  models: {
1807
- sisyphus: models.sisyphus,
1951
+ marvin: models.marvin,
1808
1952
  oracle: models.oracle,
1809
1953
  librarian: models.librarian,
1810
1954
  frontend: models.frontend,
@@ -1864,13 +2008,13 @@ function generateOmoConfig(answers) {
1864
2008
  omoConfig.google_auth = false;
1865
2009
  }
1866
2010
  const agentConfigs = [
1867
- { role: "sisyphus", omoName: "Sisyphus", modelId: models.sisyphus },
2011
+ { role: "marvin", omoName: "Marvin", modelId: models.marvin },
1868
2012
  { role: "oracle", omoName: "oracle", modelId: models.oracle },
1869
2013
  { role: "librarian", omoName: "librarian", modelId: models.librarian },
1870
2014
  {
1871
2015
  role: "frontend",
1872
2016
  omoName: "frontend-ui-ux-engineer",
1873
- modelId: models.frontend || models.sisyphus
2017
+ modelId: models.frontend || models.marvin
1874
2018
  },
1875
2019
  {
1876
2020
  role: "documentWriter",
@@ -2273,10 +2417,12 @@ function generateSdlcConfig(answers) {
2273
2417
  subscriptions: {
2274
2418
  claude: {
2275
2419
  enabled: subscriptions.hasClaude,
2420
+ authMethod: subscriptions.claudeAuth,
2276
2421
  tier: subscriptions.claudeTier
2277
2422
  },
2278
2423
  openai: {
2279
- enabled: subscriptions.hasOpenAI
2424
+ enabled: subscriptions.hasOpenAI,
2425
+ authMethod: subscriptions.openaiAuth
2280
2426
  },
2281
2427
  google: {
2282
2428
  enabled: subscriptions.hasGoogle,
@@ -2288,12 +2434,23 @@ function generateSdlcConfig(answers) {
2288
2434
  }
2289
2435
  },
2290
2436
  models: {
2291
- sisyphus: models.sisyphus,
2437
+ marvin: models.marvin,
2292
2438
  oracle: models.oracle,
2293
2439
  librarian: models.librarian,
2294
2440
  frontend: models.frontend,
2295
2441
  documentWriter: models.documentWriter,
2296
- multimodalLooker: models.multimodalLooker
2442
+ multimodalLooker: models.multimodalLooker,
2443
+ // v1.0.0: subagent model configuration
2444
+ subagents: {
2445
+ red: "inherit",
2446
+ green: "inherit",
2447
+ domain: "inherit",
2448
+ refactor: "inherit",
2449
+ architect: "inherit",
2450
+ pm: "inherit",
2451
+ analyst: "inherit",
2452
+ reviewer: "inherit"
2453
+ }
2297
2454
  },
2298
2455
  // Features and MCPs - use new format if new features selected, otherwise legacy
2299
2456
  features: useNewFeatures ? generateNewFeatures(features.enabledFeatures) : featuresToFlags(features.enabledFeatures),
@@ -2318,7 +2475,9 @@ function generateSdlcConfig(answers) {
2318
2475
  autoFallback: advanced.autoFallback ?? false,
2319
2476
  retryPeriodMs: 3e5,
2320
2477
  notifyOnRateLimit: true
2321
- }
2478
+ },
2479
+ // v1.0.0: classifier model for mode detection
2480
+ classifierModel: "anthropic/claude-haiku"
2322
2481
  }
2323
2482
  };
2324
2483
  if (!useNewFeatures) {
@@ -2340,6 +2499,22 @@ function generateSdlcConfig(answers) {
2340
2499
  statuses: answers.github.statuses
2341
2500
  };
2342
2501
  }
2502
+ config.modes = answers.modes ? {
2503
+ default: answers.modes.default,
2504
+ eventModeling: answers.modes.eventModeling,
2505
+ enabled: answers.modes.enabled
2506
+ } : {
2507
+ default: "build",
2508
+ eventModeling: true,
2509
+ enabled: ["discover", "model", "architect", "pm", "build"]
2510
+ };
2511
+ config.memory = answers.memory ? {
2512
+ backend: answers.memory.backend,
2513
+ checkpointTtl: answers.memory.checkpointTtl
2514
+ } : {
2515
+ backend: "stateless",
2516
+ checkpointTtl: 86400
2517
+ };
2343
2518
  config.tdd = answers.tdd ? {
2344
2519
  enabled: answers.tdd.enabled,
2345
2520
  verbosity: answers.tdd.verbosity,
@@ -2347,7 +2522,11 @@ function generateSdlcConfig(answers) {
2347
2522
  mutationTesting: {
2348
2523
  enabled: answers.tdd.mutationTesting.enabled,
2349
2524
  requiredScore: answers.tdd.mutationTesting.requiredScore
2350
- }
2525
+ },
2526
+ // v1.0.0 fields
2527
+ domainVetoEnabled: answers.tdd.domainVetoEnabled ?? true,
2528
+ debateRounds: answers.tdd.debateRounds ?? 2,
2529
+ requireVerification: answers.tdd.requireVerification ?? true
2351
2530
  } : {
2352
2531
  enabled: true,
2353
2532
  verbosity: "brief",
@@ -2355,7 +2534,10 @@ function generateSdlcConfig(answers) {
2355
2534
  mutationTesting: {
2356
2535
  enabled: false,
2357
2536
  requiredScore: 80
2358
- }
2537
+ },
2538
+ domainVetoEnabled: true,
2539
+ debateRounds: 2,
2540
+ requireVerification: true
2359
2541
  };
2360
2542
  config.eventModeling = answers.eventModeling ? {
2361
2543
  enabled: answers.eventModeling.enabled,
@@ -2431,27 +2613,61 @@ init_esm_shims();
2431
2613
  init_debug_logger();
2432
2614
  async function gatherSubscriptions() {
2433
2615
  const hasClaude = await confirm({
2434
- message: "Do you have a Claude Pro/Max subscription?",
2616
+ message: "Will you use Anthropic/Claude models?",
2435
2617
  default: false
2436
2618
  });
2437
2619
  debugLog("subscription.hasClaude", hasClaude);
2620
+ let claudeAuth = "none";
2438
2621
  let claudeTier = "none";
2439
2622
  if (hasClaude) {
2440
- claudeTier = await select({
2441
- message: "Which Claude tier?",
2623
+ claudeAuth = await select({
2624
+ message: "How will you authenticate with Anthropic?",
2442
2625
  choices: [
2443
- { name: "Max 5x - 5x more usage than Pro", value: "max5x" },
2444
- { name: "Max 20x - 20x more usage than Pro", value: "max20x" },
2445
- { name: "Pro - Standard Pro subscription", value: "pro" }
2626
+ {
2627
+ name: "API Key - Direct API access (pay per use)",
2628
+ value: "api"
2629
+ },
2630
+ {
2631
+ name: "Claude Pro/Max Subscription - OAuth login",
2632
+ value: "subscription"
2633
+ }
2446
2634
  ]
2447
2635
  });
2448
- debugLog("subscription.claudeTier", claudeTier);
2636
+ debugLog("subscription.claudeAuth", claudeAuth);
2637
+ if (claudeAuth === "subscription") {
2638
+ claudeTier = await select({
2639
+ message: "Which Claude subscription tier?",
2640
+ choices: [
2641
+ { name: "Max 5x - 5x more usage than Pro", value: "max5x" },
2642
+ { name: "Max 20x - 20x more usage than Pro", value: "max20x" },
2643
+ { name: "Pro - Standard Pro subscription", value: "pro" }
2644
+ ]
2645
+ });
2646
+ debugLog("subscription.claudeTier", claudeTier);
2647
+ }
2449
2648
  }
2450
2649
  const hasOpenAI = await confirm({
2451
- message: "Do you have a ChatGPT Plus/Pro subscription?",
2650
+ message: "Will you use OpenAI models?",
2452
2651
  default: false
2453
2652
  });
2454
2653
  debugLog("subscription.hasOpenAI", hasOpenAI);
2654
+ let openaiAuth = "none";
2655
+ if (hasOpenAI) {
2656
+ openaiAuth = await select({
2657
+ message: "How will you authenticate with OpenAI?",
2658
+ choices: [
2659
+ {
2660
+ name: "API Key - Direct API access (pay per use)",
2661
+ value: "api"
2662
+ },
2663
+ {
2664
+ name: "ChatGPT Plus/Pro Subscription - OAuth login",
2665
+ value: "subscription"
2666
+ }
2667
+ ]
2668
+ });
2669
+ debugLog("subscription.openaiAuth", openaiAuth);
2670
+ }
2455
2671
  const hasGoogle = await confirm({
2456
2672
  message: "Will you use Google/Gemini models?",
2457
2673
  default: false
@@ -2499,8 +2715,10 @@ async function gatherSubscriptions() {
2499
2715
  }
2500
2716
  const result = {
2501
2717
  hasClaude,
2718
+ claudeAuth,
2502
2719
  claudeTier,
2503
2720
  hasOpenAI,
2721
+ openaiAuth,
2504
2722
  hasGoogle,
2505
2723
  googleAuth,
2506
2724
  hasGitHubCopilot,
@@ -2666,7 +2884,10 @@ async function gatherTdd(defaults) {
2666
2884
  mutationTesting: {
2667
2885
  enabled: false,
2668
2886
  requiredScore: 80
2669
- }
2887
+ },
2888
+ domainVetoEnabled: true,
2889
+ debateRounds: 2,
2890
+ requireVerification: true
2670
2891
  };
2671
2892
  }
2672
2893
  const verbosity = await select({
@@ -2717,6 +2938,24 @@ async function gatherTdd(defaults) {
2717
2938
  });
2718
2939
  requiredScore = scoreChoice;
2719
2940
  }
2941
+ const domainVetoEnabled = await confirm({
2942
+ message: "Enable domain agent veto power? (Can block cycle for type violations)",
2943
+ default: defaults?.domainVetoEnabled ?? true
2944
+ });
2945
+ const debateRounds = await select({
2946
+ message: "Max debate rounds before escalation to user:",
2947
+ choices: [
2948
+ { name: "1 round - Quick decisions", value: 1 },
2949
+ { name: "2 rounds - Balanced (recommended)", value: 2 },
2950
+ { name: "3 rounds - Thorough discussion", value: 3 },
2951
+ { name: "5 rounds - Extended debate", value: 5 }
2952
+ ],
2953
+ default: defaults?.debateRounds ?? 2
2954
+ });
2955
+ const requireVerification = await confirm({
2956
+ message: "Require test output evidence before phase transitions?",
2957
+ default: defaults?.requireVerification ?? true
2958
+ });
2720
2959
  return {
2721
2960
  enabled,
2722
2961
  verbosity,
@@ -2724,7 +2963,10 @@ async function gatherTdd(defaults) {
2724
2963
  mutationTesting: {
2725
2964
  enabled: mutationEnabled,
2726
2965
  requiredScore
2727
- }
2966
+ },
2967
+ domainVetoEnabled,
2968
+ debateRounds,
2969
+ requireVerification
2728
2970
  };
2729
2971
  }
2730
2972
 
@@ -2793,6 +3035,135 @@ async function gatherGitWorkflow(defaults) {
2793
3035
  };
2794
3036
  }
2795
3037
 
3038
+ // src/cli/questions/modes.ts
3039
+ init_esm_shims();
3040
+ var MODE_OPTIONS = [
3041
+ {
3042
+ value: "build",
3043
+ name: "Build",
3044
+ description: "TDD implementation (RED \u2192 DOMAIN \u2192 GREEN \u2192 DOMAIN)"
3045
+ },
3046
+ {
3047
+ value: "discover",
3048
+ name: "Discover",
3049
+ description: "Problem space exploration, stakeholder mapping"
3050
+ },
3051
+ {
3052
+ value: "model",
3053
+ name: "Model",
3054
+ description: "Event Modeling (commands, events, views)"
3055
+ },
3056
+ {
3057
+ value: "architect",
3058
+ name: "Architect",
3059
+ description: "System design, ADRs, technology decisions"
3060
+ },
3061
+ {
3062
+ value: "pm",
3063
+ name: "PM",
3064
+ description: "Project management, git workflow, PRs"
3065
+ }
3066
+ ];
3067
+ async function gatherModes(defaults) {
3068
+ console.log(chalk6.gray("\nMarvin operates in different modes depending on your work focus."));
3069
+ console.log(chalk6.gray("Build mode (TDD) is always enabled.\n"));
3070
+ const enabledChoices = MODE_OPTIONS.filter((m) => m.value !== "build").map((m) => ({
3071
+ name: `${m.name} - ${m.description}`,
3072
+ value: m.value,
3073
+ checked: true
3074
+ }));
3075
+ const selectedModes = await checkbox({
3076
+ message: "Which additional modes do you want to enable?",
3077
+ choices: enabledChoices
3078
+ });
3079
+ const enabled = ["build", ...selectedModes];
3080
+ const useEventModeling = await confirm({
3081
+ message: "Use Event Modeling for system design? (No = use PRD-style specifications)",
3082
+ default: true
3083
+ });
3084
+ let finalEnabled = enabled;
3085
+ if (!useEventModeling) {
3086
+ finalEnabled = enabled.filter((m) => m !== "model");
3087
+ }
3088
+ const defaultModeChoices = finalEnabled.map((mode) => {
3089
+ const option = MODE_OPTIONS.find((m) => m.value === mode);
3090
+ return {
3091
+ name: `${option?.name || mode} - ${option?.description || ""}`,
3092
+ value: mode
3093
+ };
3094
+ });
3095
+ const defaultMode = await select({
3096
+ message: "Which mode should be active when you start OpenCode?",
3097
+ choices: defaultModeChoices,
3098
+ default: "build"
3099
+ });
3100
+ return {
3101
+ default: defaultMode,
3102
+ eventModeling: useEventModeling,
3103
+ enabled: finalEnabled
3104
+ };
3105
+ }
3106
+
3107
+ // src/cli/questions/memory.ts
3108
+ init_esm_shims();
3109
+ async function gatherMemory(defaults) {
3110
+ console.log(
3111
+ chalk6.gray("\nMemory backend determines how Marvin remembers context across sessions.\n")
3112
+ );
3113
+ const backend = await select({
3114
+ message: "Choose memory backend:",
3115
+ choices: [
3116
+ {
3117
+ name: "Stateless - No persistent memory (simpler, no setup required)",
3118
+ value: "stateless"
3119
+ },
3120
+ {
3121
+ name: "Memento - Persistent memory via Memento MCP (requires setup)",
3122
+ value: "memento"
3123
+ }
3124
+ ],
3125
+ default: "stateless"
3126
+ });
3127
+ let checkpointTtl = defaults?.checkpointTtl ?? 86400;
3128
+ if (backend === "memento") {
3129
+ console.log(chalk6.gray("\nMemento stores checkpoints of conversation state."));
3130
+ console.log(chalk6.gray("Set how long to keep checkpoints before they expire.\n"));
3131
+ const ttlChoice = await select({
3132
+ message: "Checkpoint retention period:",
3133
+ choices: [
3134
+ { name: "1 hour (3600 seconds)", value: 3600 },
3135
+ { name: "6 hours (21600 seconds)", value: 21600 },
3136
+ { name: "24 hours (86400 seconds) - Recommended", value: 86400 },
3137
+ { name: "7 days (604800 seconds)", value: 604800 },
3138
+ { name: "Custom", value: -1 }
3139
+ ],
3140
+ default: 86400
3141
+ });
3142
+ if (ttlChoice === -1) {
3143
+ const customTtl = await input({
3144
+ message: "Enter checkpoint TTL in seconds:",
3145
+ default: String(checkpointTtl),
3146
+ validate: (value) => {
3147
+ const num = Number.parseInt(value, 10);
3148
+ if (Number.isNaN(num) || num < 60) {
3149
+ return "Please enter a number >= 60 seconds";
3150
+ }
3151
+ return true;
3152
+ }
3153
+ });
3154
+ checkpointTtl = Number.parseInt(customTtl, 10);
3155
+ } else {
3156
+ checkpointTtl = ttlChoice;
3157
+ }
3158
+ console.log(chalk6.yellow("\nNote: You'll need to configure Memento MCP separately."));
3159
+ console.log(chalk6.gray("See: https://github.com/gannonh/memento\n"));
3160
+ }
3161
+ return {
3162
+ backend,
3163
+ checkpointTtl
3164
+ };
3165
+ }
3166
+
2796
3167
  // src/cli/utils/config-loader.ts
2797
3168
  init_esm_shims();
2798
3169
  function loadExistingConfigs() {
@@ -2840,10 +3211,15 @@ function extractSubscriptions(sdlc) {
2840
3211
  const openai = subs.openai;
2841
3212
  const google = subs.google;
2842
3213
  const copilot = subs.githubCopilot;
3214
+ const claudeTier = claude?.tier || "none";
3215
+ const claudeAuth = claude?.authMethod || (claudeTier !== "none" ? "subscription" : "none");
3216
+ const openaiAuth = openai?.authMethod || (openai?.enabled === true ? "subscription" : "none");
2843
3217
  return {
2844
3218
  hasClaude: claude?.enabled === true,
2845
- claudeTier: claude?.tier || "none",
3219
+ claudeAuth,
3220
+ claudeTier,
2846
3221
  hasOpenAI: openai?.enabled === true,
3222
+ openaiAuth,
2847
3223
  hasGoogle: google?.enabled === true,
2848
3224
  googleAuth: google?.authMethod || "none",
2849
3225
  hasGitHubCopilot: copilot?.enabled === true,
@@ -2859,7 +3235,7 @@ function extractModels(sdlc) {
2859
3235
  const models = sdlc.models;
2860
3236
  if (!models) return null;
2861
3237
  return {
2862
- sisyphus: models.sisyphus || "",
3238
+ marvin: models.marvin || "",
2863
3239
  oracle: models.oracle || "",
2864
3240
  librarian: models.librarian || "",
2865
3241
  frontend: models.frontend,
@@ -3012,8 +3388,63 @@ var MIGRATIONS = [
3012
3388
  {
3013
3389
  fromVersion: "0.0.1",
3014
3390
  toVersion: "0.3.0",
3015
- description: "Initial SDLC plugin version",
3391
+ description: "Initial SDLC plugin version with Marvin agent and API key auth options",
3016
3392
  migrateSdlc: (config) => config
3393
+ },
3394
+ {
3395
+ fromVersion: "0.3.0",
3396
+ toVersion: "1.0.0",
3397
+ description: "Add v1.0 config: modes, memory, TDD updates, classifier model, subagent models",
3398
+ migrateSdlc: (config) => {
3399
+ const migrated = { ...config };
3400
+ if (!migrated.modes) {
3401
+ migrated.modes = {
3402
+ default: "build",
3403
+ eventModeling: true,
3404
+ enabled: ["discover", "model", "architect", "pm", "build"]
3405
+ };
3406
+ }
3407
+ if (!migrated.memory) {
3408
+ migrated.memory = {
3409
+ backend: "stateless",
3410
+ checkpointTtl: 86400
3411
+ };
3412
+ }
3413
+ if (migrated.tdd) {
3414
+ const tdd = migrated.tdd;
3415
+ if (tdd.domainVetoEnabled === void 0) {
3416
+ tdd.domainVetoEnabled = true;
3417
+ }
3418
+ if (tdd.debateRounds === void 0) {
3419
+ tdd.debateRounds = 2;
3420
+ }
3421
+ if (tdd.requireVerification === void 0) {
3422
+ tdd.requireVerification = true;
3423
+ }
3424
+ }
3425
+ if (migrated.routing) {
3426
+ const routing = migrated.routing;
3427
+ if (routing.classifierModel === void 0) {
3428
+ routing.classifierModel = "anthropic/claude-haiku";
3429
+ }
3430
+ }
3431
+ if (migrated.models) {
3432
+ const models = migrated.models;
3433
+ if (!models.subagents) {
3434
+ models.subagents = {
3435
+ red: "inherit",
3436
+ green: "inherit",
3437
+ domain: "inherit",
3438
+ refactor: "inherit",
3439
+ architect: "inherit",
3440
+ pm: "inherit",
3441
+ analyst: "inherit",
3442
+ reviewer: "inherit"
3443
+ };
3444
+ }
3445
+ }
3446
+ return migrated;
3447
+ }
3017
3448
  }
3018
3449
  ];
3019
3450
  function migrateLegacyFiles() {
@@ -3214,7 +3645,7 @@ function presetToDefaults(preset) {
3214
3645
  const isLegacy = "bmad" in preset && preset.bmad !== void 0;
3215
3646
  return {
3216
3647
  models: {
3217
- sisyphus: preset.models.sisyphus,
3648
+ marvin: preset.models.marvin || "",
3218
3649
  oracle: preset.models.oracle,
3219
3650
  librarian: preset.models.librarian,
3220
3651
  frontend: preset.models.frontend,
@@ -3279,7 +3710,7 @@ function formatPresetSummary(preset, name) {
3279
3710
  lines.push(`Description: ${preset.description}`);
3280
3711
  lines.push("");
3281
3712
  lines.push("Models:");
3282
- lines.push(` Sisyphus: ${preset.models.sisyphus}`);
3713
+ lines.push(` Marvin: ${preset.models.marvin}`);
3283
3714
  lines.push(` Oracle: ${preset.models.oracle}`);
3284
3715
  lines.push(` Librarian: ${preset.models.librarian}`);
3285
3716
  if (preset.bmad) {
@@ -3339,9 +3770,9 @@ function detectInstallMode(options, configs) {
3339
3770
  async function runUpgradeFlow(configs, existingVersion, options) {
3340
3771
  const { sdlc, omo, opencode } = configs;
3341
3772
  logger.section("Upgrading Configuration");
3342
- console.log(chalk4.cyan(`
3773
+ console.log(chalk6.cyan(`
3343
3774
  Current version: ${existingVersion}`));
3344
- console.log(chalk4.cyan(`New version: ${VERSION}
3775
+ console.log(chalk6.cyan(`New version: ${VERSION}
3345
3776
  `));
3346
3777
  if (!options.yes) {
3347
3778
  const proceed = await confirm({
@@ -3365,22 +3796,22 @@ Current version: ${existingVersion}`));
3365
3796
  if (fileMigrationResult.stateFileMoved) moved.push("state file");
3366
3797
  if (fileMigrationResult.backupsMoved > 0)
3367
3798
  moved.push(`${fileMigrationResult.backupsMoved} backup(s)`);
3368
- console.log(chalk4.gray(` Migrated ${moved.join(", ")} to new sdlc/ directory`));
3799
+ console.log(chalk6.gray(` Migrated ${moved.join(", ")} to new sdlc/ directory`));
3369
3800
  }
3370
3801
  const migrationSpinner = ora5("Applying migrations...").start();
3371
3802
  const migrationResult = migrateConfigs(sdlc || {}, omo || {}, existingVersion, opencode || {});
3372
3803
  if (migrationResult.migrationsApplied.length > 0) {
3373
3804
  migrationSpinner.succeed(`Applied ${migrationResult.migrationsApplied.length} migration(s)`);
3374
3805
  for (const migration of migrationResult.migrationsApplied) {
3375
- console.log(chalk4.gray(` \u2022 ${migration}`));
3806
+ console.log(chalk6.gray(` \u2022 ${migration}`));
3376
3807
  }
3377
3808
  } else {
3378
3809
  migrationSpinner.succeed("No migrations needed");
3379
3810
  }
3380
3811
  if (migrationResult.hasBreakingChanges && !options.yes) {
3381
- console.log(chalk4.yellow("\nBreaking changes detected:"));
3812
+ console.log(chalk6.yellow("\nBreaking changes detected:"));
3382
3813
  for (const warning of migrationResult.breakingChangeWarnings) {
3383
- console.log(chalk4.yellow(` \u26A0 ${warning}`));
3814
+ console.log(chalk6.yellow(` \u26A0 ${warning}`));
3384
3815
  }
3385
3816
  const continueUpgrade = await confirm({
3386
3817
  message: "Continue with upgrade despite breaking changes?",
@@ -3398,20 +3829,25 @@ Current version: ${existingVersion}`));
3398
3829
  const existingAdvanced = extractAdvanced(migrationResult.sdlcConfig);
3399
3830
  logger.section("Preserved Configuration");
3400
3831
  if (existingSubscriptions) {
3401
- console.log(chalk4.bold("Subscriptions:"));
3402
- if (existingSubscriptions.hasClaude)
3403
- console.log(chalk4.green(` \u2713 Claude (${existingSubscriptions.claudeTier})`));
3404
- if (existingSubscriptions.hasOpenAI) console.log(chalk4.green(" \u2713 OpenAI"));
3832
+ console.log(chalk6.bold("Subscriptions:"));
3833
+ if (existingSubscriptions.hasClaude) {
3834
+ const claudeInfo = existingSubscriptions.claudeAuth === "api" ? "API Key" : existingSubscriptions.claudeTier;
3835
+ console.log(chalk6.green(` \u2713 Claude (${claudeInfo})`));
3836
+ }
3837
+ if (existingSubscriptions.hasOpenAI) {
3838
+ const openaiInfo = existingSubscriptions.openaiAuth === "api" ? "API Key" : "Subscription";
3839
+ console.log(chalk6.green(` \u2713 OpenAI (${openaiInfo})`));
3840
+ }
3405
3841
  if (existingSubscriptions.hasGoogle)
3406
- console.log(chalk4.green(` \u2713 Google (${existingSubscriptions.googleAuth})`));
3842
+ console.log(chalk6.green(` \u2713 Google (${existingSubscriptions.googleAuth})`));
3407
3843
  if (existingSubscriptions.hasGitHubCopilot)
3408
- console.log(chalk4.green(` \u2713 GitHub Copilot (${existingSubscriptions.copilotPlan})`));
3844
+ console.log(chalk6.green(` \u2713 GitHub Copilot (${existingSubscriptions.copilotPlan})`));
3409
3845
  }
3410
3846
  if (existingModels) {
3411
- console.log(chalk4.bold("\nModel Assignments:"));
3412
- console.log(chalk4.green(` \u2713 Sisyphus: ${existingModels.sisyphus}`));
3413
- console.log(chalk4.green(` \u2713 Oracle: ${existingModels.oracle}`));
3414
- console.log(chalk4.green(` \u2713 Librarian: ${existingModels.librarian}`));
3847
+ console.log(chalk6.bold("\nModel Assignments:"));
3848
+ console.log(chalk6.green(` \u2713 Marvin: ${existingModels.marvin}`));
3849
+ console.log(chalk6.green(` \u2713 Oracle: ${existingModels.oracle}`));
3850
+ console.log(chalk6.green(` \u2713 Librarian: ${existingModels.librarian}`));
3415
3851
  }
3416
3852
  console.log();
3417
3853
  const newFeatures = detectNewFeatures(migrationResult.sdlcConfig);
@@ -3450,7 +3886,7 @@ Current version: ${existingVersion}`));
3450
3886
  const fullAnswers = {
3451
3887
  subscriptions: finalSubscriptions,
3452
3888
  models: existingModels || {
3453
- sisyphus: "",
3889
+ marvin: "",
3454
3890
  oracle: "",
3455
3891
  librarian: ""
3456
3892
  },
@@ -3486,17 +3922,14 @@ Current version: ${existingVersion}`));
3486
3922
  await fileManager.installDependencies(packages);
3487
3923
  installSpinner.succeed(`Installed ${packages.length} package(s)`);
3488
3924
  }
3489
- const commandsSpinner = ora5("Updating bridge commands...").start();
3490
- const copiedCommands = await fileManager.copyCommands();
3491
- commandsSpinner.succeed(`Updated ${copiedCommands.length} bridge commands`);
3492
3925
  logger.successBanner(`UPGRADED TO OPENCODE ATHENA ${VERSION}!`);
3493
3926
  if (backups.sdlcBackup || backups.omoBackup || backups.opencodeBackup) {
3494
- console.log(chalk4.gray("\nBackups saved:"));
3495
- if (backups.sdlcBackup) console.log(chalk4.gray(` \u2022 ${backups.sdlcBackup}`));
3496
- if (backups.omoBackup) console.log(chalk4.gray(` \u2022 ${backups.omoBackup}`));
3497
- if (backups.opencodeBackup) console.log(chalk4.gray(` \u2022 ${backups.opencodeBackup}`));
3927
+ console.log(chalk6.gray("\nBackups saved:"));
3928
+ if (backups.sdlcBackup) console.log(chalk6.gray(` \u2022 ${backups.sdlcBackup}`));
3929
+ if (backups.omoBackup) console.log(chalk6.gray(` \u2022 ${backups.omoBackup}`));
3930
+ if (backups.opencodeBackup) console.log(chalk6.gray(` \u2022 ${backups.opencodeBackup}`));
3498
3931
  }
3499
- console.log(chalk4.gray("\nRestart OpenCode to use the upgraded configuration."));
3932
+ console.log(chalk6.gray("\nRestart OpenCode to use the upgraded configuration."));
3500
3933
  console.log();
3501
3934
  }
3502
3935
  async function install(options) {
@@ -3550,6 +3983,7 @@ async function install(options) {
3550
3983
  }
3551
3984
  }
3552
3985
  if (!preset && !options.yes) {
3986
+ logger.section("Configuration Profile");
3553
3987
  const selectedPreset = await askForPreset();
3554
3988
  if (selectedPreset) {
3555
3989
  preset = selectedPreset.preset;
@@ -3557,64 +3991,89 @@ async function install(options) {
3557
3991
  presetName = selectedPreset.name;
3558
3992
  }
3559
3993
  }
3560
- logger.section("LLM Subscriptions");
3561
- const subscriptions = await gatherSubscriptions();
3562
- if (!options.yes) {
3563
- logger.section("Confirm Provider Selection");
3564
- console.log(chalk4.bold("You selected:\n"));
3565
- console.log(
3566
- ` Claude: ${subscriptions.hasClaude ? chalk4.green("\u2713 Yes") : chalk4.gray("\u2717 No")}`
3567
- );
3568
- if (subscriptions.hasClaude) {
3569
- console.log(` Tier: ${subscriptions.claudeTier}`);
3570
- }
3571
- console.log(
3572
- ` OpenAI: ${subscriptions.hasOpenAI ? chalk4.green("\u2713 Yes") : chalk4.gray("\u2717 No")}`
3573
- );
3574
- console.log(
3575
- ` Google: ${subscriptions.hasGoogle ? chalk4.green("\u2713 Yes") : chalk4.gray("\u2717 No")}`
3576
- );
3577
- if (subscriptions.hasGoogle) {
3578
- console.log(` Auth Method: ${subscriptions.googleAuth}`);
3579
- }
3580
- console.log(
3581
- ` GitHub Copilot: ${subscriptions.hasGitHubCopilot ? chalk4.green("\u2713 Yes") : chalk4.gray("\u2717 No")}`
3582
- );
3583
- if (subscriptions.hasGitHubCopilot) {
3584
- console.log(` Plan: ${subscriptions.copilotPlan}`);
3585
- }
3994
+ let shouldCustomize = true;
3995
+ if (preset && presetDefaults && presetName && !options.yes) {
3996
+ console.log(chalk6.bold("\nProfile Configuration:\n"));
3997
+ console.log(chalk6.gray(formatPresetSummary(preset, presetName)));
3586
3998
  console.log();
3587
- const confirmed = await confirm({
3588
- message: "Is this correct?",
3589
- default: true
3999
+ shouldCustomize = await confirm({
4000
+ message: "Would you like to customize these settings?",
4001
+ default: false
3590
4002
  });
3591
- if (!confirmed) {
3592
- logger.info("Please restart installation with correct provider selections.");
3593
- process.exit(0);
3594
- }
3595
- }
3596
- let shouldCustomize = true;
3597
- if (preset && presetDefaults && presetName) {
3598
- const modelWarnings = validatePresetModels(presetDefaults.models, subscriptions);
3599
- if (modelWarnings.length > 0) {
3600
- console.log(chalk4.yellow("\nPreset model compatibility warnings:"));
3601
- for (const warning of modelWarnings) {
3602
- console.log(chalk4.yellow(` - ${warning}`));
4003
+ } else if (options.yes && preset) {
4004
+ shouldCustomize = false;
4005
+ logger.info("Using preset defaults (--yes flag)");
4006
+ }
4007
+ let subscriptions;
4008
+ if (shouldCustomize || !preset) {
4009
+ logger.section("LLM Subscriptions");
4010
+ subscriptions = await gatherSubscriptions();
4011
+ if (!options.yes) {
4012
+ logger.section("Confirm Provider Selection");
4013
+ console.log(chalk6.bold("You selected:\n"));
4014
+ console.log(
4015
+ ` Claude: ${subscriptions.hasClaude ? chalk6.green("\u2713 Yes") : chalk6.gray("\u2717 No")}`
4016
+ );
4017
+ if (subscriptions.hasClaude) {
4018
+ console.log(
4019
+ ` Auth Method: ${subscriptions.claudeAuth === "api" ? "API Key" : "Subscription"}`
4020
+ );
4021
+ if (subscriptions.claudeAuth === "subscription") {
4022
+ console.log(` Tier: ${subscriptions.claudeTier}`);
4023
+ }
4024
+ }
4025
+ console.log(
4026
+ ` OpenAI: ${subscriptions.hasOpenAI ? chalk6.green("\u2713 Yes") : chalk6.gray("\u2717 No")}`
4027
+ );
4028
+ if (subscriptions.hasOpenAI) {
4029
+ console.log(
4030
+ ` Auth Method: ${subscriptions.openaiAuth === "api" ? "API Key" : "Subscription"}`
4031
+ );
4032
+ }
4033
+ console.log(
4034
+ ` Google: ${subscriptions.hasGoogle ? chalk6.green("\u2713 Yes") : chalk6.gray("\u2717 No")}`
4035
+ );
4036
+ if (subscriptions.hasGoogle) {
4037
+ console.log(` Auth Method: ${subscriptions.googleAuth}`);
4038
+ }
4039
+ console.log(
4040
+ ` GitHub Copilot: ${subscriptions.hasGitHubCopilot ? chalk6.green("\u2713 Yes") : chalk6.gray("\u2717 No")}`
4041
+ );
4042
+ if (subscriptions.hasGitHubCopilot) {
4043
+ console.log(` Plan: ${subscriptions.copilotPlan}`);
3603
4044
  }
3604
4045
  console.log();
3605
- }
3606
- console.log(chalk4.bold("\nPreset Configuration:\n"));
3607
- console.log(chalk4.gray(formatPresetSummary(preset, presetName)));
3608
- console.log();
3609
- if (options.yes) {
3610
- shouldCustomize = false;
3611
- logger.info("Using preset defaults (--yes flag)");
3612
- } else {
3613
- shouldCustomize = await confirm({
3614
- message: "Would you like to customize these settings?",
3615
- default: false
4046
+ const confirmed = await confirm({
4047
+ message: "Is this correct?",
4048
+ default: true
3616
4049
  });
4050
+ if (!confirmed) {
4051
+ logger.info("Please restart installation with correct provider selections.");
4052
+ process.exit(0);
4053
+ }
3617
4054
  }
4055
+ if (preset && presetDefaults) {
4056
+ const modelWarnings = validatePresetModels(presetDefaults.models, subscriptions);
4057
+ if (modelWarnings.length > 0) {
4058
+ console.log(chalk6.yellow("\nPreset model compatibility warnings:"));
4059
+ for (const warning of modelWarnings) {
4060
+ console.log(chalk6.yellow(` - ${warning}`));
4061
+ }
4062
+ console.log();
4063
+ }
4064
+ }
4065
+ } else {
4066
+ subscriptions = {
4067
+ hasClaude: preset.subscriptions.claude.enabled,
4068
+ claudeAuth: "subscription",
4069
+ claudeTier: preset.subscriptions.claude.tier,
4070
+ hasOpenAI: preset.subscriptions.openai.enabled,
4071
+ openaiAuth: "subscription",
4072
+ hasGoogle: preset.subscriptions.google.enabled,
4073
+ googleAuth: preset.subscriptions.google.authMethod,
4074
+ hasGitHubCopilot: preset.subscriptions.githubCopilot?.enabled ?? false,
4075
+ copilotPlan: preset.subscriptions.githubCopilot?.plan ?? "none"
4076
+ };
3618
4077
  }
3619
4078
  let models;
3620
4079
  let methodology;
@@ -3624,6 +4083,8 @@ async function install(options) {
3624
4083
  let tdd;
3625
4084
  let eventModeling;
3626
4085
  let gitWorkflow;
4086
+ let modes;
4087
+ let memory;
3627
4088
  if (!shouldCustomize && presetDefaults) {
3628
4089
  logger.section("Applying Preset Configuration");
3629
4090
  const availableModels = await Promise.resolve().then(() => (init_models(), models_exports)).then(
@@ -3636,7 +4097,7 @@ async function install(options) {
3636
4097
  process.exit(1);
3637
4098
  }
3638
4099
  models = {
3639
- sisyphus: getValidModelOrFirst(presetDefaults.models.sisyphus, availableModels),
4100
+ marvin: getValidModelOrFirst(presetDefaults.models.marvin, availableModels),
3640
4101
  oracle: getValidModelOrFirst(presetDefaults.models.oracle, availableModels),
3641
4102
  librarian: getValidModelOrFirst(presetDefaults.models.librarian, availableModels),
3642
4103
  frontend: getValidModelOrFirst(presetDefaults.models.frontend, availableModels),
@@ -3651,12 +4112,19 @@ async function install(options) {
3651
4112
  advanced = presetDefaults.advanced;
3652
4113
  logger.section("GitHub Integration");
3653
4114
  github = await gatherGitHub();
4115
+ logger.section("Marvin Modes");
4116
+ modes = await gatherModes();
4117
+ logger.section("Memory Configuration");
4118
+ memory = await gatherMemory();
3654
4119
  if (preset?.tdd) {
3655
4120
  tdd = {
3656
4121
  enabled: preset.tdd.enabled,
3657
4122
  verbosity: preset.tdd.verbosity,
3658
4123
  bypassPatterns: preset.tdd.bypassPatterns,
3659
- mutationTesting: preset.tdd.mutationTesting
4124
+ mutationTesting: preset.tdd.mutationTesting,
4125
+ domainVetoEnabled: true,
4126
+ debateRounds: 2,
4127
+ requireVerification: true
3660
4128
  };
3661
4129
  }
3662
4130
  if (preset?.eventModeling) {
@@ -3674,6 +4142,10 @@ async function install(options) {
3674
4142
  }
3675
4143
  logger.success("Preset configuration applied");
3676
4144
  } else {
4145
+ logger.section("Marvin Modes");
4146
+ modes = await gatherModes();
4147
+ logger.section("Memory Configuration");
4148
+ memory = await gatherMemory();
3677
4149
  logger.section("Model Selection");
3678
4150
  models = await gatherModels(subscriptions, presetDefaults?.models);
3679
4151
  logger.section("Methodology Preferences");
@@ -3727,14 +4199,17 @@ async function install(options) {
3727
4199
  github,
3728
4200
  tdd,
3729
4201
  eventModeling,
3730
- gitWorkflow
4202
+ gitWorkflow,
4203
+ // v1.0.0 additions
4204
+ modes,
4205
+ memory
3731
4206
  };
3732
4207
  const generator = new ConfigGenerator(answers);
3733
4208
  const files = await generator.generate();
3734
- console.log(chalk4.bold("Files to be created/modified:\n"));
4209
+ console.log(chalk6.bold("Files to be created/modified:\n"));
3735
4210
  for (const file of files) {
3736
- const action = file.exists ? chalk4.yellow("update") : chalk4.green("create");
3737
- console.log(chalk4.gray(` [${action}] ${file.path}`));
4211
+ const action = file.exists ? chalk6.yellow("update") : chalk6.green("create");
4212
+ console.log(chalk6.gray(` [${action}] ${file.path}`));
3738
4213
  }
3739
4214
  console.log();
3740
4215
  if (!options.yes) {
@@ -3757,12 +4232,15 @@ async function install(options) {
3757
4232
  installSpinner.text = `Installing dependencies: ${packages.join(", ")}...`;
3758
4233
  await fileManager.installDependencies(packages);
3759
4234
  }
3760
- installSpinner.text = "Installing commands...";
3761
- const copiedCommands = await fileManager.copyCommands();
3762
- installSpinner.succeed("Installation complete!");
3763
- if (copiedCommands.length > 0) {
3764
- logger.info(`Installed ${copiedCommands.length} bridge commands`);
4235
+ if (modes?.enabled && modes.enabled.length > 0) {
4236
+ installSpinner.text = "Installing Marvin mode agents...";
4237
+ const projectDir = process.cwd();
4238
+ const copiedAgents = await fileManager.copyAgentModes(projectDir, modes.enabled);
4239
+ if (copiedAgents.length > 0) {
4240
+ logger.info(`Installed ${copiedAgents.length} Marvin mode agents to .opencode/agent/`);
4241
+ }
3765
4242
  }
4243
+ installSpinner.succeed("Installation complete!");
3766
4244
  } catch (error) {
3767
4245
  installSpinner.fail("Installation failed");
3768
4246
  logger.error(error instanceof Error ? error.message : String(error));
@@ -3773,16 +4251,16 @@ async function install(options) {
3773
4251
  async function askForPreset() {
3774
4252
  const presets = listPresets();
3775
4253
  const choices = [
3776
- { name: "No preset - Configure everything manually", value: "none" },
3777
4254
  ...presets.map((p) => ({
3778
4255
  name: `${p.name} - ${p.description}`,
3779
4256
  value: p.name
3780
- }))
4257
+ })),
4258
+ { name: "No preset - Configure everything manually", value: "none" }
3781
4259
  ];
3782
4260
  const selected = await select({
3783
- message: "Start from a preset?",
4261
+ message: "Choose a configuration profile:",
3784
4262
  choices,
3785
- default: "standard"
4263
+ default: "event-modeling"
3786
4264
  });
3787
4265
  if (selected === "none") {
3788
4266
  return null;
@@ -3804,29 +4282,41 @@ function getValidModelOrFirst(modelId, availableModels) {
3804
4282
  function printNextSteps(subscriptions) {
3805
4283
  const steps = [];
3806
4284
  if (subscriptions.hasClaude) {
3807
- steps.push(`Run: ${chalk4.cyan("opencode auth login")} -> Select Anthropic -> Claude Pro/Max`);
4285
+ if (subscriptions.claudeAuth === "api") {
4286
+ steps.push(`Set ${chalk6.cyan("ANTHROPIC_API_KEY")} environment variable with your API key`);
4287
+ } else {
4288
+ steps.push(`Run: ${chalk6.cyan("opencode auth login")} -> Select Anthropic -> Claude Pro/Max`);
4289
+ }
3808
4290
  }
3809
4291
  if (subscriptions.hasOpenAI) {
3810
- steps.push(`Run: ${chalk4.cyan("opencode auth login")} -> Select OpenAI -> ChatGPT Plus/Pro`);
4292
+ if (subscriptions.openaiAuth === "api") {
4293
+ steps.push(`Set ${chalk6.cyan("OPENAI_API_KEY")} environment variable with your API key`);
4294
+ } else {
4295
+ steps.push(`Run: ${chalk6.cyan("opencode auth login")} -> Select OpenAI -> ChatGPT Plus/Pro`);
4296
+ }
3811
4297
  }
3812
4298
  if (subscriptions.hasGoogle) {
3813
- steps.push(`Run: ${chalk4.cyan("opencode auth login")} -> Select Google -> OAuth with Google`);
4299
+ if (subscriptions.googleAuth === "api") {
4300
+ steps.push(`Set ${chalk6.cyan("GOOGLE_API_KEY")} environment variable with your API key`);
4301
+ } else {
4302
+ steps.push(`Run: ${chalk6.cyan("opencode auth login")} -> Select Google -> OAuth with Google`);
4303
+ }
3814
4304
  }
3815
4305
  if (subscriptions.hasGitHubCopilot) {
3816
- steps.push(`Run: ${chalk4.cyan("opencode auth login")} -> Select GitHub Copilot`);
4306
+ steps.push(`Run: ${chalk6.cyan("opencode auth login")} -> Select GitHub Copilot`);
3817
4307
  }
3818
4308
  logger.successBanner("OPENCODE ATHENA INSTALLED SUCCESSFULLY!");
3819
- console.log(chalk4.bold("Next Steps:\n"));
4309
+ console.log(chalk6.bold("Next Steps:\n"));
3820
4310
  steps.forEach((step, i) => {
3821
4311
  console.log(` ${i + 1}. ${step}`);
3822
4312
  });
3823
- console.log(chalk4.bold("\nThen start OpenCode and try:\n"));
3824
- console.log(` ${chalk4.cyan("/sdlc-dev")} Implement the next issue with Sisyphus`);
3825
- console.log(` ${chalk4.cyan("/sdlc-status")} Check issue status`);
3826
- console.log(` ${chalk4.cyan("/sdlc-info")} View toolkit configuration`);
3827
- console.log(
3828
- chalk4.gray("\nDocumentation: https://github.com/ZebulonRouseFrantzich/opencode-sdlc")
3829
- );
4313
+ console.log(chalk6.bold("\nThen start OpenCode in your project directory.\n"));
4314
+ console.log(chalk6.gray("The SDLC plugin will automatically:"));
4315
+ console.log(chalk6.gray(" \u2022 Enforce TDD cycles (RED \u2192 DOMAIN \u2192 GREEN \u2192 DOMAIN)"));
4316
+ console.log(chalk6.gray(" \u2022 Track work via GitHub Issues"));
4317
+ console.log(chalk6.gray(" \u2022 Apply file ownership rules"));
4318
+ console.log(chalk6.gray("\nUse Tab to switch between Marvin modes (Build, Discover, etc.)"));
4319
+ console.log(chalk6.gray("\nDocumentation: https://github.com/jwilger/opencode-sdlc-plugin"));
3830
4320
  console.log();
3831
4321
  }
3832
4322
 
@@ -3907,7 +4397,7 @@ async function showStatus() {
3907
4397
  const spinner = ora5("Checking authentication status...").start();
3908
4398
  const authStatus = await detectAuthStatus();
3909
4399
  spinner.stop();
3910
- console.log(chalk4.bold("\nConfigured Providers:\n"));
4400
+ console.log(chalk6.bold("\nConfigured Providers:\n"));
3911
4401
  displayProvider(
3912
4402
  "Claude",
3913
4403
  subscriptions.hasClaude,
@@ -3924,32 +4414,32 @@ async function showStatus() {
3924
4414
  );
3925
4415
  const models = configs.sdlc.models;
3926
4416
  if (models) {
3927
- console.log(chalk4.bold("\nCurrent Model Assignments:\n"));
3928
- console.log(` ${chalk4.cyan("Sisyphus:")} ${models.sisyphus || "not set"}`);
3929
- console.log(` ${chalk4.cyan("Oracle:")} ${models.oracle || "not set"}`);
3930
- console.log(` ${chalk4.cyan("Librarian:")} ${models.librarian || "not set"}`);
3931
- console.log(` ${chalk4.cyan("Frontend:")} ${models.frontend || "not set"}`);
3932
- console.log(` ${chalk4.cyan("Doc Writer:")} ${models.documentWriter || "not set"}`);
3933
- console.log(` ${chalk4.cyan("Multimodal:")} ${models.multimodalLooker || "not set"}`);
4417
+ console.log(chalk6.bold("\nCurrent Model Assignments:\n"));
4418
+ console.log(` ${chalk6.cyan("Marvin:")} ${models.marvin || "not set"}`);
4419
+ console.log(` ${chalk6.cyan("Oracle:")} ${models.oracle || "not set"}`);
4420
+ console.log(` ${chalk6.cyan("Librarian:")} ${models.librarian || "not set"}`);
4421
+ console.log(` ${chalk6.cyan("Frontend:")} ${models.frontend || "not set"}`);
4422
+ console.log(` ${chalk6.cyan("Doc Writer:")} ${models.documentWriter || "not set"}`);
4423
+ console.log(` ${chalk6.cyan("Multimodal:")} ${models.multimodalLooker || "not set"}`);
3934
4424
  }
3935
4425
  if (!authStatus.anthropic && subscriptions.hasClaude) {
3936
- console.log(chalk4.yellow("\n\u26A0 Tip: Run 'opencode auth login' to authenticate Claude"));
4426
+ console.log(chalk6.yellow("\n\u26A0 Tip: Run 'opencode auth login' to authenticate Claude"));
3937
4427
  }
3938
4428
  if (!authStatus.openai && subscriptions.hasOpenAI) {
3939
- console.log(chalk4.yellow("\u26A0 Tip: Run 'opencode auth login' to authenticate OpenAI"));
4429
+ console.log(chalk6.yellow("\u26A0 Tip: Run 'opencode auth login' to authenticate OpenAI"));
3940
4430
  }
3941
4431
  if (!authStatus.google && subscriptions.hasGoogle) {
3942
- console.log(chalk4.yellow("\u26A0 Tip: Run 'opencode auth login' to authenticate Google"));
4432
+ console.log(chalk6.yellow("\u26A0 Tip: Run 'opencode auth login' to authenticate Google"));
3943
4433
  }
3944
4434
  if (!authStatus.githubCopilot && subscriptions.hasGitHubCopilot) {
3945
- console.log(chalk4.yellow("\u26A0 Tip: Run 'opencode auth login' to authenticate GitHub Copilot"));
4435
+ console.log(chalk6.yellow("\u26A0 Tip: Run 'opencode auth login' to authenticate GitHub Copilot"));
3946
4436
  }
3947
4437
  console.log();
3948
4438
  }
3949
4439
  function displayProvider(name, enabled, tier, authenticated) {
3950
- const status = enabled ? chalk4.green("\u2713 Enabled") : chalk4.gray("\u2717 Disabled");
3951
- const auth = enabled ? authenticated ? chalk4.green("\u2713 Authenticated") : chalk4.yellow("\u26A0 Not authenticated") : chalk4.gray("(disabled)");
3952
- const tierText = tier && tier !== "none" ? chalk4.gray(` (${tier})`) : "";
4440
+ const status = enabled ? chalk6.green("\u2713 Enabled") : chalk6.gray("\u2717 Disabled");
4441
+ const auth = enabled ? authenticated ? chalk6.green("\u2713 Authenticated") : chalk6.yellow("\u26A0 Not authenticated") : chalk6.gray("(disabled)");
4442
+ const tierText = tier && tier !== "none" ? chalk6.gray(` (${tier})`) : "";
3953
4443
  console.log(` ${status.padEnd(30)} ${name}${tierText}`);
3954
4444
  console.log(` ${" ".repeat(30)} Auth: ${auth}`);
3955
4445
  }
@@ -4011,7 +4501,7 @@ async function addProvider() {
4011
4501
  });
4012
4502
  }
4013
4503
  logger.success(`Provider added: ${provider}`);
4014
- console.log(chalk4.gray("\nRun 'opencode-sdlc providers refresh' to update model defaults."));
4504
+ console.log(chalk6.gray("\nRun 'opencode-sdlc providers refresh' to update model defaults."));
4015
4505
  }
4016
4506
  async function removeProvider() {
4017
4507
  logger.banner();
@@ -4045,16 +4535,16 @@ async function uninstall(options) {
4045
4535
  }
4046
4536
  logger.section("Uninstalling OpenCode SDLC");
4047
4537
  const fileManager = new FileManager();
4048
- const commandsSpinner = ora5("Removing bridge commands...").start();
4538
+ const commandsSpinner = ora5("Cleaning up legacy bridge commands...").start();
4049
4539
  try {
4050
4540
  const removedCommands = await fileManager.removeCommands();
4051
4541
  if (removedCommands.length > 0) {
4052
- commandsSpinner.succeed(`Removed ${removedCommands.length} bridge command(s)`);
4542
+ commandsSpinner.succeed(`Removed ${removedCommands.length} legacy command(s)`);
4053
4543
  } else {
4054
- commandsSpinner.info("No bridge commands found");
4544
+ commandsSpinner.info("No legacy bridge commands found");
4055
4545
  }
4056
4546
  } catch (err) {
4057
- commandsSpinner.fail("Failed to remove bridge commands");
4547
+ commandsSpinner.fail("Failed to remove legacy commands");
4058
4548
  logger.error(err instanceof Error ? err.message : String(err));
4059
4549
  }
4060
4550
  if (!options.keepConfig) {
@@ -4105,7 +4595,7 @@ async function uninstall(options) {
4105
4595
  logger.success("OpenCode SDLC has been uninstalled.");
4106
4596
  if (options.keepConfig) {
4107
4597
  logger.info("Configuration files were preserved.");
4108
- logger.info(`Run ${chalk4.cyan("opencode-sdlc install")} to reinstall with existing config.`);
4598
+ logger.info(`Run ${chalk6.cyan("opencode-sdlc install")} to reinstall with existing config.`);
4109
4599
  }
4110
4600
  console.log();
4111
4601
  }
@@ -4141,7 +4631,7 @@ async function upgrade(options) {
4141
4631
  const configs = loadExistingConfigs();
4142
4632
  if (!configs.sdlc) {
4143
4633
  logger.error("No existing Sdlc installation found.");
4144
- logger.info(`Run ${chalk4.cyan("opencode-sdlc install")} to install for the first time.`);
4634
+ logger.info(`Run ${chalk6.cyan("opencode-sdlc install")} to install for the first time.`);
4145
4635
  process.exit(1);
4146
4636
  }
4147
4637
  const existingVersion = configs.sdlcVersion || "0.0.1";
@@ -4176,7 +4666,7 @@ async function upgrade(options) {
4176
4666
  logger.section("Package Versions");
4177
4667
  const updatesAvailable = updates.filter((u) => u.updateAvailable);
4178
4668
  for (const pkg of updates) {
4179
- const status = pkg.updateAvailable ? chalk4.yellow(`${pkg.current} -> ${pkg.latest}`) : chalk4.green(pkg.current);
4669
+ const status = pkg.updateAvailable ? chalk6.yellow(`${pkg.current} -> ${pkg.latest}`) : chalk6.green(pkg.current);
4180
4670
  logger.keyValue(pkg.name, status);
4181
4671
  }
4182
4672
  console.log();
@@ -4194,7 +4684,7 @@ async function upgrade(options) {
4194
4684
  }
4195
4685
  if (options.check) {
4196
4686
  console.log();
4197
- logger.info(`Run ${chalk4.cyan("opencode-sdlc upgrade")} (without --check) to apply upgrades.`);
4687
+ logger.info(`Run ${chalk6.cyan("opencode-sdlc upgrade")} (without --check) to apply upgrades.`);
4198
4688
  return;
4199
4689
  }
4200
4690
  const actionCount = updatesAvailable.length + (existingVersion !== VERSION ? 1 : 0);
@@ -4213,9 +4703,9 @@ async function upgrade(options) {
4213
4703
  }
4214
4704
  }
4215
4705
  logger.section("Upgrading Configuration");
4216
- console.log(chalk4.cyan(`
4706
+ console.log(chalk6.cyan(`
4217
4707
  Current version: ${existingVersion}`));
4218
- console.log(chalk4.cyan(`New version: ${VERSION}
4708
+ console.log(chalk6.cyan(`New version: ${VERSION}
4219
4709
  `));
4220
4710
  const backupSpinner = ora5("Creating backup...").start();
4221
4711
  const backups = createBackups();
@@ -4229,7 +4719,7 @@ Current version: ${existingVersion}`));
4229
4719
  if (fileMigrationResult.stateFileMoved) moved.push("state file");
4230
4720
  if (fileMigrationResult.backupsMoved > 0)
4231
4721
  moved.push(`${fileMigrationResult.backupsMoved} backup(s)`);
4232
- console.log(chalk4.gray(` Migrated ${moved.join(", ")} to new sdlc/ directory`));
4722
+ console.log(chalk6.gray(` Migrated ${moved.join(", ")} to new sdlc/ directory`));
4233
4723
  }
4234
4724
  const migrationSpinner = ora5("Applying migrations...").start();
4235
4725
  const migrationResult = migrateConfigs(
@@ -4241,15 +4731,15 @@ Current version: ${existingVersion}`));
4241
4731
  if (migrationResult.migrationsApplied.length > 0) {
4242
4732
  migrationSpinner.succeed(`Applied ${migrationResult.migrationsApplied.length} migration(s)`);
4243
4733
  for (const migration of migrationResult.migrationsApplied) {
4244
- console.log(chalk4.gray(` \u2022 ${migration}`));
4734
+ console.log(chalk6.gray(` \u2022 ${migration}`));
4245
4735
  }
4246
4736
  } else {
4247
4737
  migrationSpinner.succeed("No migrations needed");
4248
4738
  }
4249
4739
  if (migrationResult.hasBreakingChanges && !options.yes) {
4250
- console.log(chalk4.yellow("\nBreaking changes detected:"));
4740
+ console.log(chalk6.yellow("\nBreaking changes detected:"));
4251
4741
  for (const warning of migrationResult.breakingChangeWarnings) {
4252
- console.log(chalk4.yellow(` \u26A0 ${warning}`));
4742
+ console.log(chalk6.yellow(` \u26A0 ${warning}`));
4253
4743
  }
4254
4744
  const continueUpgrade = await confirm({
4255
4745
  message: "Continue with upgrade despite breaking changes?",
@@ -4267,20 +4757,20 @@ Current version: ${existingVersion}`));
4267
4757
  const existingAdvanced = extractAdvanced(migrationResult.sdlcConfig);
4268
4758
  logger.section("Preserved Configuration");
4269
4759
  if (existingSubscriptions) {
4270
- console.log(chalk4.bold("Subscriptions:"));
4760
+ console.log(chalk6.bold("Subscriptions:"));
4271
4761
  if (existingSubscriptions.hasClaude)
4272
- console.log(chalk4.green(` \u2713 Claude (${existingSubscriptions.claudeTier})`));
4273
- if (existingSubscriptions.hasOpenAI) console.log(chalk4.green(" \u2713 OpenAI"));
4762
+ console.log(chalk6.green(` \u2713 Claude (${existingSubscriptions.claudeTier})`));
4763
+ if (existingSubscriptions.hasOpenAI) console.log(chalk6.green(" \u2713 OpenAI"));
4274
4764
  if (existingSubscriptions.hasGoogle)
4275
- console.log(chalk4.green(` \u2713 Google (${existingSubscriptions.googleAuth})`));
4765
+ console.log(chalk6.green(` \u2713 Google (${existingSubscriptions.googleAuth})`));
4276
4766
  if (existingSubscriptions.hasGitHubCopilot)
4277
- console.log(chalk4.green(` \u2713 GitHub Copilot (${existingSubscriptions.copilotPlan})`));
4767
+ console.log(chalk6.green(` \u2713 GitHub Copilot (${existingSubscriptions.copilotPlan})`));
4278
4768
  }
4279
4769
  if (existingModels) {
4280
- console.log(chalk4.bold("\nModel Assignments:"));
4281
- console.log(chalk4.green(` \u2713 Sisyphus: ${existingModels.sisyphus}`));
4282
- console.log(chalk4.green(` \u2713 Oracle: ${existingModels.oracle}`));
4283
- console.log(chalk4.green(` \u2713 Librarian: ${existingModels.librarian}`));
4770
+ console.log(chalk6.bold("\nModel Assignments:"));
4771
+ console.log(chalk6.green(` \u2713 Marvin: ${existingModels.marvin}`));
4772
+ console.log(chalk6.green(` \u2713 Oracle: ${existingModels.oracle}`));
4773
+ console.log(chalk6.green(` \u2713 Librarian: ${existingModels.librarian}`));
4284
4774
  }
4285
4775
  console.log();
4286
4776
  const newFeatures = detectNewFeatures(migrationResult.sdlcConfig);
@@ -4307,7 +4797,7 @@ Current version: ${existingVersion}`));
4307
4797
  const fullAnswers = {
4308
4798
  subscriptions: existingSubscriptions,
4309
4799
  models: existingModels || {
4310
- sisyphus: "",
4800
+ marvin: "",
4311
4801
  oracle: "",
4312
4802
  librarian: ""
4313
4803
  },
@@ -4390,28 +4880,40 @@ Current version: ${existingVersion}`));
4390
4880
  }
4391
4881
  }
4392
4882
  }
4393
- const commandsSpinner = ora5("Updating bridge commands...").start();
4394
4883
  try {
4395
- const copiedCommands = await fileManager.copyCommands();
4396
- commandsSpinner.succeed(`Updated ${copiedCommands.length} bridge commands`);
4397
- } catch (_err) {
4398
- commandsSpinner.warn("Could not update bridge commands");
4884
+ await fileManager.removeCommands();
4885
+ } catch {
4886
+ }
4887
+ const modesConfig = migrationResult.sdlcConfig.modes;
4888
+ if (modesConfig?.enabled && modesConfig.enabled.length > 0) {
4889
+ const agentSpinner = ora5("Updating Marvin mode agents...").start();
4890
+ try {
4891
+ const projectDir = process.cwd();
4892
+ const copiedAgents = await fileManager.copyAgentModes(projectDir, modesConfig.enabled);
4893
+ if (copiedAgents.length > 0) {
4894
+ agentSpinner.succeed(`Updated ${copiedAgents.length} Marvin mode agents`);
4895
+ } else {
4896
+ agentSpinner.succeed("Marvin mode agents up to date");
4897
+ }
4898
+ } catch (_err) {
4899
+ agentSpinner.warn("Could not update Marvin mode agents");
4900
+ }
4399
4901
  }
4400
4902
  logger.successBanner(`UPGRADED TO OPENCODE ATHENA ${VERSION}!`);
4401
4903
  if (backups.sdlcBackup || backups.omoBackup || backups.opencodeBackup) {
4402
- console.log(chalk4.gray("\nBackups saved:"));
4403
- if (backups.sdlcBackup) console.log(chalk4.gray(` \u2022 ${backups.sdlcBackup}`));
4404
- if (backups.omoBackup) console.log(chalk4.gray(` \u2022 ${backups.omoBackup}`));
4405
- if (backups.opencodeBackup) console.log(chalk4.gray(` \u2022 ${backups.opencodeBackup}`));
4904
+ console.log(chalk6.gray("\nBackups saved:"));
4905
+ if (backups.sdlcBackup) console.log(chalk6.gray(` \u2022 ${backups.sdlcBackup}`));
4906
+ if (backups.omoBackup) console.log(chalk6.gray(` \u2022 ${backups.omoBackup}`));
4907
+ if (backups.opencodeBackup) console.log(chalk6.gray(` \u2022 ${backups.opencodeBackup}`));
4406
4908
  }
4407
- console.log(chalk4.gray("\nRestart OpenCode to use the upgraded configuration."));
4909
+ console.log(chalk6.gray("\nRestart OpenCode to use the upgraded configuration."));
4408
4910
  console.log();
4409
4911
  }
4410
4912
 
4411
4913
  // src/cli/index.ts
4412
4914
  var program = new Command();
4413
4915
  program.name("opencode-sdlc").description(
4414
- `${chalk4.cyan(DISPLAY_NAME)} - ${TAGLINE}
4916
+ `${chalk6.cyan(DISPLAY_NAME)} - ${TAGLINE}
4415
4917
  TDD-driven development toolkit with GitHub Issues integration for OpenCode`
4416
4918
  ).version(VERSION);
4417
4919
  program.command("install").description("Install and configure OpenCode SDLC").option(
@@ -4433,15 +4935,15 @@ program.command("providers [action]").description("Manage LLM provider subscript
4433
4935
  await providers({ action });
4434
4936
  });
4435
4937
  function displayPresets() {
4436
- console.log(chalk4.bold.cyan("\nAvailable Presets:\n"));
4938
+ console.log(chalk6.bold.cyan("\nAvailable Presets:\n"));
4437
4939
  const presets = listPresets();
4438
4940
  for (const preset of presets) {
4439
- console.log(chalk4.bold(` ${preset.name}`));
4440
- console.log(chalk4.gray(` ${preset.description}`));
4941
+ console.log(chalk6.bold(` ${preset.name}`));
4942
+ console.log(chalk6.gray(` ${preset.description}`));
4441
4943
  console.log();
4442
4944
  }
4443
- console.log(chalk4.gray("Usage: opencode-sdlc install --preset <name>"));
4444
- console.log(chalk4.gray(" opencode-sdlc install --preset standard --yes\n"));
4945
+ console.log(chalk6.gray("Usage: opencode-sdlc install --preset <name>"));
4946
+ console.log(chalk6.gray(" opencode-sdlc install --preset standard --yes\n"));
4445
4947
  }
4446
4948
  program.parse();
4447
4949
  //# sourceMappingURL=index.js.map