@codemcp/workflows 6.4.0 → 6.5.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.
Files changed (134) hide show
  1. package/package.json +2 -2
  2. package/packages/cli/dist/{chunk-D2Q6Y3QQ.js → chunk-4AZGS2GG.js} +321 -388
  3. package/packages/cli/dist/{cli-DXJJF56V.js → cli-ZCCFBQTP.js} +3 -3
  4. package/packages/cli/dist/{dist-W7PPKVFG.js → dist-I6VSREAJ.js} +11 -5
  5. package/packages/cli/dist/{dist-W7VMGB3G.js → dist-MW7THWM3.js} +875 -1136
  6. package/packages/cli/dist/index.js +2 -2
  7. package/packages/cli/package.json +1 -1
  8. package/packages/cli/resources/workflows/bugfix.yaml +14 -0
  9. package/packages/cli/resources/workflows/epcc.yaml +12 -0
  10. package/packages/cli/resources/workflows/greenfield.yaml +16 -0
  11. package/packages/cli/resources/workflows/minor.yaml +8 -0
  12. package/packages/cli/resources/workflows/tdd.yaml +10 -0
  13. package/packages/cli/resources/workflows/waterfall.yaml +16 -0
  14. package/packages/core/dist/beads-integration.d.ts +3 -5
  15. package/packages/core/dist/beads-integration.js +29 -35
  16. package/packages/core/dist/beads-integration.js.map +1 -1
  17. package/packages/core/dist/beads-state-manager.d.ts +3 -1
  18. package/packages/core/dist/beads-state-manager.js +17 -15
  19. package/packages/core/dist/beads-state-manager.js.map +1 -1
  20. package/packages/core/dist/file-detection-manager.js +15 -22
  21. package/packages/core/dist/file-detection-manager.js.map +1 -1
  22. package/packages/core/dist/index.d.ts +1 -0
  23. package/packages/core/dist/index.js +1 -0
  24. package/packages/core/dist/index.js.map +1 -1
  25. package/packages/core/dist/instruction-generator.d.ts +3 -7
  26. package/packages/core/dist/instruction-generator.js +17 -25
  27. package/packages/core/dist/instruction-generator.js.map +1 -1
  28. package/packages/core/dist/interfaces/instruction-generator.interface.d.ts +13 -4
  29. package/packages/core/dist/interfaces/plan-manager.interface.d.ts +9 -0
  30. package/packages/core/dist/logger.d.ts +49 -20
  31. package/packages/core/dist/logger.js +65 -141
  32. package/packages/core/dist/logger.js.map +1 -1
  33. package/packages/core/dist/plan-manager.d.ts +6 -4
  34. package/packages/core/dist/plan-manager.js +19 -15
  35. package/packages/core/dist/plan-manager.js.map +1 -1
  36. package/packages/core/dist/project-docs-manager.d.ts +3 -1
  37. package/packages/core/dist/project-docs-manager.js +11 -9
  38. package/packages/core/dist/project-docs-manager.js.map +1 -1
  39. package/packages/core/dist/state-machine-loader.d.ts +16 -0
  40. package/packages/core/dist/state-machine-loader.js +29 -0
  41. package/packages/core/dist/state-machine-loader.js.map +1 -1
  42. package/packages/core/dist/state-machine-types.d.ts +8 -0
  43. package/packages/core/dist/string-utils.d.ts +8 -0
  44. package/packages/core/dist/string-utils.js +14 -0
  45. package/packages/core/dist/string-utils.js.map +1 -0
  46. package/packages/core/dist/task-backend.d.ts +6 -3
  47. package/packages/core/dist/task-backend.js +10 -8
  48. package/packages/core/dist/task-backend.js.map +1 -1
  49. package/packages/core/dist/transition-engine.d.ts +3 -6
  50. package/packages/core/dist/transition-engine.js +31 -76
  51. package/packages/core/dist/transition-engine.js.map +1 -1
  52. package/packages/core/dist/workflow-manager.d.ts +2 -0
  53. package/packages/core/dist/workflow-manager.js +14 -2
  54. package/packages/core/dist/workflow-manager.js.map +1 -1
  55. package/packages/core/package.json +1 -1
  56. package/packages/core/resources/workflows/bugfix.yaml +14 -0
  57. package/packages/core/resources/workflows/epcc.yaml +12 -0
  58. package/packages/core/resources/workflows/greenfield.yaml +16 -0
  59. package/packages/core/resources/workflows/minor.yaml +8 -0
  60. package/packages/core/resources/workflows/tdd.yaml +10 -0
  61. package/packages/core/resources/workflows/waterfall.yaml +16 -0
  62. package/packages/docs/.vitepress/dist/workflows/bugfix.yaml +14 -0
  63. package/packages/docs/.vitepress/dist/workflows/epcc.yaml +12 -0
  64. package/packages/docs/.vitepress/dist/workflows/greenfield.yaml +16 -0
  65. package/packages/docs/.vitepress/dist/workflows/minor.yaml +8 -0
  66. package/packages/docs/.vitepress/dist/workflows/tdd.yaml +10 -0
  67. package/packages/docs/.vitepress/dist/workflows/waterfall.yaml +16 -0
  68. package/packages/docs/package.json +1 -1
  69. package/packages/mcp-server/dist/index.d.ts +1027 -0
  70. package/packages/mcp-server/dist/index.js +879 -1140
  71. package/packages/mcp-server/package.json +1 -1
  72. package/packages/mcp-server/resources/workflows/bugfix.yaml +14 -0
  73. package/packages/mcp-server/resources/workflows/epcc.yaml +12 -0
  74. package/packages/mcp-server/resources/workflows/greenfield.yaml +16 -0
  75. package/packages/mcp-server/resources/workflows/minor.yaml +8 -0
  76. package/packages/mcp-server/resources/workflows/tdd.yaml +10 -0
  77. package/packages/mcp-server/resources/workflows/waterfall.yaml +16 -0
  78. package/packages/opencode-plugin/dist/index.d.ts +220 -0
  79. package/packages/opencode-plugin/dist/index.js +28616 -0
  80. package/packages/opencode-plugin/package.json +55 -0
  81. package/packages/opencode-plugin/resources/agents/architect.yaml +61 -0
  82. package/packages/opencode-plugin/resources/agents/business-analyst.yaml +60 -0
  83. package/packages/opencode-plugin/resources/agents/developer.yaml +61 -0
  84. package/packages/opencode-plugin/resources/templates/architecture/arc42/arc42-template-EN.md +1077 -0
  85. package/packages/opencode-plugin/resources/templates/architecture/arc42/images/01_2_iso-25010-topics-EN.drawio-2023.png +0 -0
  86. package/packages/opencode-plugin/resources/templates/architecture/arc42/images/01_2_iso-25010-topics-EN.drawio.png +0 -0
  87. package/packages/opencode-plugin/resources/templates/architecture/arc42/images/05_building_blocks-EN.png +0 -0
  88. package/packages/opencode-plugin/resources/templates/architecture/arc42/images/08-concepts-EN.drawio.png +0 -0
  89. package/packages/opencode-plugin/resources/templates/architecture/arc42/images/arc42-logo.png +0 -0
  90. package/packages/opencode-plugin/resources/templates/architecture/c4.md +224 -0
  91. package/packages/opencode-plugin/resources/templates/architecture/freestyle.md +53 -0
  92. package/packages/opencode-plugin/resources/templates/architecture/game.md +250 -0
  93. package/packages/opencode-plugin/resources/templates/architecture/none.md +17 -0
  94. package/packages/opencode-plugin/resources/templates/design/comprehensive.md +207 -0
  95. package/packages/opencode-plugin/resources/templates/design/freestyle.md +37 -0
  96. package/packages/opencode-plugin/resources/templates/design/game.md +66 -0
  97. package/packages/opencode-plugin/resources/templates/design/none.md +17 -0
  98. package/packages/opencode-plugin/resources/templates/requirements/ears.md +90 -0
  99. package/packages/opencode-plugin/resources/templates/requirements/freestyle.md +42 -0
  100. package/packages/opencode-plugin/resources/templates/requirements/game.md +162 -0
  101. package/packages/opencode-plugin/resources/templates/requirements/none.md +17 -0
  102. package/packages/opencode-plugin/resources/templates/skills/POWER.md +23 -0
  103. package/packages/opencode-plugin/resources/templates/skills/SKILL.md +19 -0
  104. package/packages/opencode-plugin/resources/workflows/adr.yaml +157 -0
  105. package/packages/opencode-plugin/resources/workflows/big-bang-conversion.yaml +592 -0
  106. package/packages/opencode-plugin/resources/workflows/boundary-testing.yaml +376 -0
  107. package/packages/opencode-plugin/resources/workflows/bugfix.yaml +178 -0
  108. package/packages/opencode-plugin/resources/workflows/business-analysis.yaml +597 -0
  109. package/packages/opencode-plugin/resources/workflows/c4-analysis.yaml +471 -0
  110. package/packages/opencode-plugin/resources/workflows/epcc.yaml +195 -0
  111. package/packages/opencode-plugin/resources/workflows/game-beginner.yaml +434 -0
  112. package/packages/opencode-plugin/resources/workflows/greenfield.yaml +217 -0
  113. package/packages/opencode-plugin/resources/workflows/minor.yaml +146 -0
  114. package/packages/opencode-plugin/resources/workflows/posts.yaml +193 -0
  115. package/packages/opencode-plugin/resources/workflows/sdd-bugfix-crowd.yaml +608 -0
  116. package/packages/opencode-plugin/resources/workflows/sdd-bugfix.yaml +381 -0
  117. package/packages/opencode-plugin/resources/workflows/sdd-feature-crowd.yaml +713 -0
  118. package/packages/opencode-plugin/resources/workflows/sdd-feature.yaml +471 -0
  119. package/packages/opencode-plugin/resources/workflows/sdd-greenfield-crowd.yaml +336 -0
  120. package/packages/opencode-plugin/resources/workflows/sdd-greenfield.yaml +463 -0
  121. package/packages/opencode-plugin/resources/workflows/skilled-bugfix.yaml +174 -0
  122. package/packages/opencode-plugin/resources/workflows/skilled-epcc.yaml +171 -0
  123. package/packages/opencode-plugin/resources/workflows/skilled-greenfield.yaml +207 -0
  124. package/packages/opencode-plugin/resources/workflows/slides.yaml +237 -0
  125. package/packages/opencode-plugin/resources/workflows/tdd.yaml +170 -0
  126. package/packages/opencode-plugin/resources/workflows/waterfall.yaml +225 -0
  127. package/packages/opencode-tui-plugin/package.json +46 -0
  128. package/packages/visualizer/package.json +1 -1
  129. package/resources/workflows/bugfix.yaml +14 -0
  130. package/resources/workflows/epcc.yaml +12 -0
  131. package/resources/workflows/greenfield.yaml +16 -0
  132. package/resources/workflows/minor.yaml +8 -0
  133. package/resources/workflows/tdd.yaml +10 -0
  134. package/resources/workflows/waterfall.yaml +16 -0
@@ -2650,25 +2650,21 @@ var LogLevel;
2650
2650
  LogLevel2[LogLevel2["ERROR"] = 3] = "ERROR";
2651
2651
  LogLevel2[LogLevel2["SILENT"] = 4] = "SILENT";
2652
2652
  })(LogLevel || (LogLevel = {}));
2653
- var mcpServerInstance = null;
2653
+ var logSinkInstance = null;
2654
2654
  var currentLoggingLevel = null;
2655
2655
  function isTestMode() {
2656
- if (process.env.NODE_ENV === "test" || process.env.VITEST === "true") {
2656
+ if (process.env["NODE_ENV"] === "test" || process.env["VITEST"] === "true") {
2657
2657
  return true;
2658
2658
  }
2659
- const cwd = process.cwd();
2660
- if (cwd.includes("/tmp/") || cwd.includes("temp") || cwd.includes("test-")) {
2661
- return true;
2662
- }
2663
- if (process.env.LOG_LEVEL === "ERROR") {
2659
+ if (process.env["LOG_LEVEL"] === "ERROR") {
2664
2660
  return true;
2665
2661
  }
2666
2662
  return false;
2667
2663
  }
2668
- function setMcpServerForLogging(server) {
2669
- mcpServerInstance = server;
2664
+ function registerLogSink(sink) {
2665
+ logSinkInstance = sink;
2670
2666
  }
2671
- function setMcpLoggingLevel(level) {
2667
+ function setLoggingLevelFromString(level) {
2672
2668
  const levelMap = {
2673
2669
  debug: LogLevel.DEBUG,
2674
2670
  info: LogLevel.INFO,
@@ -2708,7 +2704,7 @@ var Logger = class _Logger {
2708
2704
  return LogLevel.INFO;
2709
2705
  }
2710
2706
  getLogLevelFromEnv() {
2711
- const envLevel = process.env.LOG_LEVEL?.toUpperCase();
2707
+ const envLevel = process.env["LOG_LEVEL"]?.toUpperCase();
2712
2708
  switch (envLevel) {
2713
2709
  case "DEBUG":
2714
2710
  return LogLevel.DEBUG;
@@ -2733,31 +2729,15 @@ var Logger = class _Logger {
2733
2729
  return `[${timestamp2}] ${level.toUpperCase()} [${this.component}] ${message}${contextStr}`;
2734
2730
  }
2735
2731
  /**
2736
- * Send log message to MCP client if server is available and level is appropriate
2732
+ * Send log message to registered sink if available
2737
2733
  */
2738
- async sendMcpLogMessage(level, message, context) {
2739
- if (mcpServerInstance) {
2734
+ async sendToSink(level, message, context) {
2735
+ if (logSinkInstance) {
2740
2736
  try {
2741
- let logData = message;
2742
- if (context) {
2743
- try {
2744
- const contextStr = JSON.stringify(context, null, 0);
2745
- logData = `${message} ${contextStr}`;
2746
- } catch (_error) {
2747
- logData = `${message} [context serialization failed]`;
2748
- }
2749
- }
2750
- await mcpServerInstance.server.notification({
2751
- method: "notifications/message",
2752
- params: {
2753
- level,
2754
- logger: this.component,
2755
- data: logData
2756
- }
2757
- });
2737
+ await logSinkInstance.log(level, this.component, message, context);
2758
2738
  } catch (error) {
2759
2739
  if (!isTestMode()) {
2760
- process.stderr.write(`[MCP-LOG-ERROR] Failed to send log notification: ${error}
2740
+ process.stderr.write(`[LOG-SINK-ERROR] Failed to send log to sink: ${error}
2761
2741
  `);
2762
2742
  }
2763
2743
  }
@@ -2765,85 +2745,42 @@ var Logger = class _Logger {
2765
2745
  }
2766
2746
  debug(message, context) {
2767
2747
  if (this.shouldLog(LogLevel.DEBUG)) {
2768
- const formattedMessage = this.formatMessage("debug", message, context);
2769
- process.stderr.write(formattedMessage + "\n");
2770
- this.sendMcpLogMessage("debug", message, context).catch(() => {
2748
+ if (!logSinkInstance) {
2749
+ const formattedMessage = this.formatMessage("debug", message, context);
2750
+ process.stderr.write(formattedMessage + "\n");
2751
+ }
2752
+ this.sendToSink("debug", message, context).catch(() => {
2771
2753
  });
2772
2754
  }
2773
2755
  }
2774
2756
  info(message, context) {
2775
2757
  if (this.shouldLog(LogLevel.INFO)) {
2776
- const formattedMessage = this.formatMessage("info", message, context);
2777
- process.stderr.write(formattedMessage + "\n");
2778
- this.sendEnhancedMcpNotification("info", message, context).catch(() => {
2779
- });
2780
- }
2781
- }
2782
- /**
2783
- * Send enhanced MCP notifications with better formatting for important events
2784
- */
2785
- async sendEnhancedMcpNotification(level, message, context) {
2786
- if (mcpServerInstance) {
2787
- try {
2788
- let enhancedMessage = message;
2789
- let notificationLevel = level;
2790
- if (context && (context.from || context.to) && message.includes("transition")) {
2791
- const from = context.from ? this.capitalizePhase(context.from) : "";
2792
- const to = context.to ? this.capitalizePhase(context.to) : "";
2793
- if (from && to) {
2794
- enhancedMessage = `Phase Transition: ${from} \u2192 ${to}`;
2795
- notificationLevel = "info";
2796
- }
2797
- }
2798
- if (message.includes("initialized successfully")) {
2799
- enhancedMessage = "\u{1F680} Vibe Feature MCP Server Ready";
2800
- notificationLevel = "info";
2801
- }
2802
- let logData = enhancedMessage;
2803
- if (context) {
2804
- try {
2805
- const contextStr = JSON.stringify(context, null, 0);
2806
- logData = `${enhancedMessage} ${contextStr}`;
2807
- } catch (_error) {
2808
- logData = `${enhancedMessage} [context serialization failed]`;
2809
- }
2810
- }
2811
- await mcpServerInstance.server.notification({
2812
- method: "notifications/message",
2813
- params: {
2814
- level: notificationLevel,
2815
- logger: this.component,
2816
- data: logData
2817
- }
2818
- });
2819
- } catch (error) {
2820
- if (!isTestMode()) {
2821
- process.stderr.write(`[MCP-LOG-ERROR] Failed to send log notification: ${error}
2822
- `);
2823
- }
2758
+ if (!logSinkInstance) {
2759
+ const formattedMessage = this.formatMessage("info", message, context);
2760
+ process.stderr.write(formattedMessage + "\n");
2824
2761
  }
2762
+ this.sendToSink("info", message, context).catch(() => {
2763
+ });
2825
2764
  }
2826
2765
  }
2827
- /**
2828
- * Capitalize phase name for display
2829
- */
2830
- capitalizePhase(phase) {
2831
- return phase.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
2832
- }
2833
2766
  warn(message, context) {
2834
2767
  if (this.shouldLog(LogLevel.WARN)) {
2835
- const formattedMessage = this.formatMessage("warn", message, context);
2836
- process.stderr.write(formattedMessage + "\n");
2837
- this.sendEnhancedMcpNotification("warning", message, context).catch(() => {
2768
+ if (!logSinkInstance) {
2769
+ const formattedMessage = this.formatMessage("warn", message, context);
2770
+ process.stderr.write(formattedMessage + "\n");
2771
+ }
2772
+ this.sendToSink("warning", message, context).catch(() => {
2838
2773
  });
2839
2774
  }
2840
2775
  }
2841
2776
  error(message, error, context) {
2842
2777
  if (this.shouldLog(LogLevel.ERROR)) {
2843
2778
  const errorContext = error ? { ...context, error: error.message, stack: error.stack } : context;
2844
- const formattedMessage = this.formatMessage("error", message, errorContext);
2845
- process.stderr.write(formattedMessage + "\n");
2846
- this.sendEnhancedMcpNotification("error", message, errorContext).catch(() => {
2779
+ if (!logSinkInstance) {
2780
+ const formattedMessage = this.formatMessage("error", message, errorContext);
2781
+ process.stderr.write(formattedMessage + "\n");
2782
+ }
2783
+ this.sendToSink("error", message, errorContext).catch(() => {
2847
2784
  });
2848
2785
  }
2849
2786
  }
@@ -2854,7 +2791,7 @@ var Logger = class _Logger {
2854
2791
  function createLogger(component, logLevel) {
2855
2792
  return new Logger(component, logLevel);
2856
2793
  }
2857
- var logger = createLogger("VibeFeatureMCP");
2794
+ var logger = createLogger("workflows-core");
2858
2795
 
2859
2796
  // ../core/dist/state-machine-loader.js
2860
2797
  var logger2 = createLogger("StateMachineLoader");
@@ -3080,6 +3017,35 @@ ${continueTransition.additional_instructions}`;
3080
3017
  }
3081
3018
  return stateDefinition.default_instructions;
3082
3019
  }
3020
+ /**
3021
+ * Get allowed file patterns for a specific phase.
3022
+ * Returns undefined if no restrictions are defined (all files allowed).
3023
+ *
3024
+ * @param phase - The phase/state name to get patterns for
3025
+ * @returns Array of glob patterns or undefined if all files are allowed
3026
+ */
3027
+ getAllowedFilePatterns(phase) {
3028
+ if (!this.stateMachine) {
3029
+ throw new Error("State machine not loaded");
3030
+ }
3031
+ const stateDefinition = this.stateMachine.states[phase];
3032
+ if (!stateDefinition) {
3033
+ logger2.error("Unknown phase", new Error(`Unknown phase: ${phase}`));
3034
+ throw new Error(`Unknown phase: ${phase}`);
3035
+ }
3036
+ return stateDefinition.allowed_file_patterns;
3037
+ }
3038
+ /**
3039
+ * Whether the given phase restricts which files may be edited.
3040
+ * Returns false when no allowed_file_patterns are defined (all files allowed).
3041
+ * Callers should use getAllowedFilePatterns + a glob library for actual path matching.
3042
+ *
3043
+ * @param phase - The phase/state name
3044
+ */
3045
+ hasFileRestrictions(phase) {
3046
+ const patterns = this.getAllowedFilePatterns(phase);
3047
+ return patterns !== void 0 && patterns.length > 0;
3048
+ }
3083
3049
  };
3084
3050
 
3085
3051
  // ../core/dist/workflow-manager.js
@@ -3161,13 +3127,21 @@ var WorkflowManager = class _WorkflowManager {
3161
3127
  }
3162
3128
  /**
3163
3129
  * Parse enabled domains from environment variable
3130
+ * Supports both WORKFLOW_DOMAINS and VIBE_WORKFLOW_DOMAINS (legacy)
3131
+ * WORKFLOW_DOMAINS takes precedence if both are set (modern, non-prefixed version preferred)
3164
3132
  */
3165
3133
  parseEnabledDomains() {
3166
- const domainsEnv = process.env["VIBE_WORKFLOW_DOMAINS"];
3134
+ const domainsEnv = process.env["WORKFLOW_DOMAINS"] || process.env["VIBE_WORKFLOW_DOMAINS"];
3167
3135
  if (!domainsEnv) {
3136
+ logger4.debug("No domain configuration found, using default: code");
3168
3137
  return /* @__PURE__ */ new Set(["code"]);
3169
3138
  }
3170
- return new Set(domainsEnv.split(",").map((d) => d.trim()).filter((d) => d));
3139
+ const domains = new Set(domainsEnv.split(",").map((d) => d.trim()).filter((d) => d));
3140
+ logger4.debug("Parsed enabled domains", {
3141
+ source: process.env["WORKFLOW_DOMAINS"] ? "WORKFLOW_DOMAINS" : "VIBE_WORKFLOW_DOMAINS",
3142
+ domains: Array.from(domains)
3143
+ });
3144
+ return domains;
3171
3145
  }
3172
3146
  /**
3173
3147
  * Load project-specific workflows from .vibe/workflows/
@@ -3540,16 +3514,21 @@ var WorkflowManager = class _WorkflowManager {
3540
3514
  }
3541
3515
  };
3542
3516
 
3517
+ // ../core/dist/string-utils.js
3518
+ function capitalizePhase(phase) {
3519
+ return phase.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
3520
+ }
3521
+
3543
3522
  // ../core/dist/transition-engine.js
3544
- var logger5 = createLogger("TransitionEngine");
3523
+ var defaultLogger = createLogger("TransitionEngine");
3545
3524
  var TransitionEngine = class {
3546
- stateMachineLoader;
3547
3525
  workflowManager;
3526
+ logger;
3548
3527
  conversationManager;
3549
- constructor(projectPath) {
3550
- this.stateMachineLoader = new StateMachineLoader();
3528
+ constructor(projectPath, logger24 = defaultLogger) {
3551
3529
  this.workflowManager = new WorkflowManager();
3552
- logger5.info("TransitionEngine initialized", { projectPath });
3530
+ this.logger = logger24;
3531
+ this.logger.info("TransitionEngine initialized", { projectPath });
3553
3532
  }
3554
3533
  /**
3555
3534
  * Set the conversation manager (dependency injection)
@@ -3568,11 +3547,11 @@ var TransitionEngine = class {
3568
3547
  */
3569
3548
  async isFirstCallFromInitialState(context) {
3570
3549
  if (!this.conversationManager) {
3571
- logger5.warn("ConversationManager not set, assuming first call");
3550
+ this.logger.warn("ConversationManager not set, assuming first call");
3572
3551
  return true;
3573
3552
  }
3574
3553
  const hasInteractions = await this.conversationManager.hasInteractions(context.conversationId);
3575
- logger5.debug("Checking first call from initial state", {
3554
+ this.logger.debug("Checking first call from initial state", {
3576
3555
  hasInteractions,
3577
3556
  conversationId: context.conversationId,
3578
3557
  currentPhase: context.currentPhase
@@ -3582,51 +3561,18 @@ var TransitionEngine = class {
3582
3561
  /**
3583
3562
  * Generate instructions for defining phase entrance criteria
3584
3563
  */
3585
- async generateCriteriaDefinitionInstructions(projectPath, conversationId) {
3586
- const conversationState = await this.conversationManager?.getConversationState(conversationId);
3587
- const workflowName = conversationState?.workflowName;
3588
- const stateMachine = this.workflowManager.loadWorkflowForProject(projectPath, workflowName);
3564
+ generateCriteriaDefinitionInstructions(stateMachine) {
3589
3565
  const phases = Object.keys(stateMachine.states);
3590
- let instructions = `Welcome to ${stateMachine.name}!
3591
-
3592
- Before we begin development, let's establish clear entrance criteria for each phase. This will help us make informed decisions about when to transition between phases throughout the development process.
3593
-
3594
- Please update the plan file with a "Phase Entrance Criteria" section that defines specific, measurable criteria for entering each phase:
3595
-
3596
- ## Phase Entrance Criteria
3597
-
3598
- `;
3599
- for (const phase of phases) {
3600
- if (phase === stateMachine.initial_state)
3601
- continue;
3602
- const phaseDefinition = stateMachine.states[phase];
3603
- const capitalizedPhase = this.capitalizePhase(phase);
3604
- instructions += `### ${capitalizedPhase} Phase
3605
- *${phaseDefinition.description}*
3606
-
3607
- **Enter when:**
3608
- - [ ] [Define specific criteria for entering ${phase} phase]
3609
- - [ ] [Add measurable conditions that must be met]
3610
- - [ ] [Include any deliverables or milestones required]
3611
-
3612
- `;
3613
- }
3614
- instructions += `
3615
- Once you've defined these criteria, we can begin development. Throughout the process, consult these criteria when considering phase transitions.
3616
-
3617
- **Remember**: These criteria should be specific and measurable so we can clearly determine when each phase is ready to begin.`;
3618
- return instructions;
3566
+ const phaseList = phases.filter((phase) => phase !== stateMachine.initial_state).map((phase) => capitalizePhase(phase)).join(", ");
3567
+ return `Define entrance criteria for each phase (${phaseList}) in the plan file. Criteria should be specific and measurable.`;
3619
3568
  }
3620
3569
  /**
3621
3570
  * Get phase-specific instructions for continuing work in current phase
3622
3571
  */
3623
- async getContinuePhaseInstructions(phase, projectPath, conversationId) {
3624
- const conversationState = await this.conversationManager?.getConversationState(conversationId);
3625
- const workflowName = conversationState?.workflowName;
3626
- const stateMachine = this.workflowManager.loadWorkflowForProject(projectPath, workflowName);
3572
+ getContinuePhaseInstructions(phase, stateMachine) {
3627
3573
  const stateDefinition = stateMachine.states[phase];
3628
3574
  if (!stateDefinition) {
3629
- logger5.error("Unknown phase", new Error(`Unknown phase: ${phase}`));
3575
+ this.logger.error("Unknown phase", new Error(`Unknown phase: ${phase}`));
3630
3576
  throw new Error(`Unknown phase: ${phase}`);
3631
3577
  }
3632
3578
  const continueTransition = stateDefinition.transitions.find((t) => t.to === phase);
@@ -3649,19 +3595,17 @@ ${continueTransition.additional_instructions}`;
3649
3595
  /**
3650
3596
  * Get the first development phase from the state machine
3651
3597
  */
3652
- async getFirstDevelopmentPhase(projectPath, conversationId) {
3653
- const conversationState = await this.conversationManager?.getConversationState(conversationId);
3654
- const workflowName = conversationState?.workflowName;
3655
- const stateMachine = this.workflowManager.loadWorkflowForProject(projectPath, workflowName);
3656
- const initialState = stateMachine.initial_state;
3657
- return initialState;
3598
+ getFirstDevelopmentPhase(stateMachine) {
3599
+ return stateMachine.initial_state;
3658
3600
  }
3659
3601
  /**
3660
3602
  * Analyze context and determine appropriate phase transition
3661
3603
  */
3662
3604
  async analyzePhaseTransition(context) {
3663
3605
  const { currentPhase, projectPath, conversationId, userInput, context: additionalContext, conversationSummary } = context;
3664
- logger5.debug("Analyzing phase transition", {
3606
+ const conversationState = await this.conversationManager?.getConversationState(conversationId);
3607
+ const stateMachine = this.workflowManager.loadWorkflowForProject(projectPath, conversationState?.workflowName);
3608
+ this.logger.debug("Analyzing phase transition", {
3665
3609
  currentPhase,
3666
3610
  projectPath,
3667
3611
  hasUserInput: !!userInput,
@@ -3670,14 +3614,14 @@ ${continueTransition.additional_instructions}`;
3670
3614
  userInput: userInput ? userInput.substring(0, 50) + (userInput.length > 50 ? "..." : "") : void 0
3671
3615
  });
3672
3616
  if (await this.isFirstCallFromInitialState(context)) {
3673
- const firstDevelopmentPhase = await this.getFirstDevelopmentPhase(projectPath, conversationId);
3674
- logger5.info("First call from initial state - transitioning to first development phase with criteria", {
3617
+ const firstDevelopmentPhase = this.getFirstDevelopmentPhase(stateMachine);
3618
+ this.logger.info("First call from initial state - transitioning to first development phase with criteria", {
3675
3619
  currentPhase,
3676
3620
  firstDevelopmentPhase,
3677
3621
  projectPath
3678
3622
  });
3679
- const criteriaInstructions = await this.generateCriteriaDefinitionInstructions(projectPath, conversationId);
3680
- const phaseInstructions = await this.getContinuePhaseInstructions(firstDevelopmentPhase, projectPath, conversationId);
3623
+ const criteriaInstructions = this.generateCriteriaDefinitionInstructions(stateMachine);
3624
+ const phaseInstructions = this.getContinuePhaseInstructions(firstDevelopmentPhase, stateMachine);
3681
3625
  return {
3682
3626
  newPhase: firstDevelopmentPhase,
3683
3627
  // Transition to first development phase
@@ -3686,8 +3630,8 @@ ${continueTransition.additional_instructions}`;
3686
3630
  isModeled: true
3687
3631
  };
3688
3632
  }
3689
- const continueInstructions = await this.getContinuePhaseInstructions(currentPhase, projectPath, conversationId);
3690
- logger5.debug("Continuing in current phase - LLM will evaluate transition criteria", {
3633
+ const continueInstructions = this.getContinuePhaseInstructions(currentPhase, stateMachine);
3634
+ this.logger.debug("Continuing in current phase - LLM will evaluate transition criteria", {
3691
3635
  currentPhase,
3692
3636
  projectPath
3693
3637
  });
@@ -3703,7 +3647,7 @@ ${continueTransition.additional_instructions}`;
3703
3647
  */
3704
3648
  handleExplicitTransition(currentPhase, targetPhase, projectPath, reason, workflowName) {
3705
3649
  const stateMachine = this.getStateMachine(projectPath, workflowName);
3706
- logger5.debug("Handling explicit phase transition", {
3650
+ this.logger.debug("Handling explicit phase transition", {
3707
3651
  currentPhase,
3708
3652
  targetPhase,
3709
3653
  projectPath,
@@ -3714,7 +3658,7 @@ ${continueTransition.additional_instructions}`;
3714
3658
  if (!stateMachine.states[normalizedTargetPhase]) {
3715
3659
  const validPhases = Object.keys(stateMachine.states);
3716
3660
  const errorMsg = `Invalid target phase: "${targetPhase}". Valid phases are: ${validPhases.join(", ")}`;
3717
- logger5.error("Invalid target phase", new Error(errorMsg));
3661
+ this.logger.error("Invalid target phase", new Error(errorMsg));
3718
3662
  throw new Error(errorMsg);
3719
3663
  }
3720
3664
  const targetState = stateMachine.states[normalizedTargetPhase];
@@ -3725,7 +3669,7 @@ ${continueTransition.additional_instructions}`;
3725
3669
  isModeled: false
3726
3670
  // Direct phase transitions are not modeled
3727
3671
  };
3728
- logger5.info("Explicit phase transition processed", {
3672
+ this.logger.info("Explicit phase transition processed", {
3729
3673
  fromPhase: currentPhase,
3730
3674
  toPhase: normalizedTargetPhase,
3731
3675
  reason: transitionInfo.transitionReason,
@@ -3738,12 +3682,6 @@ ${continueTransition.additional_instructions}`;
3738
3682
  isModeled: transitionInfo.isModeled
3739
3683
  };
3740
3684
  }
3741
- /**
3742
- * Capitalize phase name for display
3743
- */
3744
- capitalizePhase(phase) {
3745
- return phase.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
3746
- }
3747
3685
  /**
3748
3686
  * Filter transitions based on agent role (for crowd workflows)
3749
3687
  * Returns transitions applicable to the current agent
@@ -3759,7 +3697,7 @@ ${continueTransition.additional_instructions}`;
3759
3697
  // ../core/dist/file-storage.js
3760
3698
  import { promises as fs4 } from "fs";
3761
3699
  import { join, dirname } from "path";
3762
- var logger6 = createLogger("FileStorage");
3700
+ var logger5 = createLogger("FileStorage");
3763
3701
  var FileStorage = class {
3764
3702
  conversationsDir;
3765
3703
  basePath;
@@ -3777,11 +3715,11 @@ var FileStorage = class {
3777
3715
  async initialize() {
3778
3716
  try {
3779
3717
  await fs4.mkdir(this.conversationsDir, { recursive: true });
3780
- logger6.debug("FileStorage initialized", {
3718
+ logger5.debug("FileStorage initialized", {
3781
3719
  conversationsDir: this.conversationsDir
3782
3720
  });
3783
3721
  } catch (error) {
3784
- logger6.error("Failed to initialize FileStorage", error);
3722
+ logger5.error("Failed to initialize FileStorage", error);
3785
3723
  throw error;
3786
3724
  }
3787
3725
  }
@@ -3831,12 +3769,12 @@ var FileStorage = class {
3831
3769
  await fs4.mkdir(conversationDir, { recursive: true });
3832
3770
  const stateJson = JSON.stringify(state, null, 2);
3833
3771
  await this.writeAtomic(stateFilePath, stateJson);
3834
- logger6.debug("Conversation state saved", {
3772
+ logger5.debug("Conversation state saved", {
3835
3773
  conversationId: state.conversationId,
3836
3774
  currentPhase: state.currentPhase
3837
3775
  });
3838
3776
  } catch (error) {
3839
- logger6.error("Failed to save conversation state", error, {
3777
+ logger5.error("Failed to save conversation state", error, {
3840
3778
  conversationId: state.conversationId
3841
3779
  });
3842
3780
  throw error;
@@ -3856,7 +3794,7 @@ var FileStorage = class {
3856
3794
  if (error.code === "ENOENT") {
3857
3795
  return null;
3858
3796
  }
3859
- logger6.warn("Failed to read conversation state, returning null", {
3797
+ logger5.warn("Failed to read conversation state, returning null", {
3860
3798
  conversationId,
3861
3799
  error: error.message
3862
3800
  });
@@ -3888,7 +3826,7 @@ var FileStorage = class {
3888
3826
  if (error.code === "ENOENT") {
3889
3827
  return [];
3890
3828
  }
3891
- logger6.error("Failed to get all conversation states", error);
3829
+ logger5.error("Failed to get all conversation states", error);
3892
3830
  throw error;
3893
3831
  }
3894
3832
  }
@@ -3900,13 +3838,13 @@ var FileStorage = class {
3900
3838
  const conversationDir = this.getConversationDir(conversationId);
3901
3839
  try {
3902
3840
  await fs4.rm(conversationDir, { recursive: true, force: true });
3903
- logger6.debug("Conversation state deleted", { conversationId });
3841
+ logger5.debug("Conversation state deleted", { conversationId });
3904
3842
  return true;
3905
3843
  } catch (error) {
3906
3844
  if (error.code === "ENOENT") {
3907
3845
  return false;
3908
3846
  }
3909
- logger6.error("Failed to delete conversation state", error, {
3847
+ logger5.error("Failed to delete conversation state", error, {
3910
3848
  conversationId
3911
3849
  });
3912
3850
  throw error;
@@ -3923,12 +3861,12 @@ var FileStorage = class {
3923
3861
  await fs4.mkdir(conversationDir, { recursive: true });
3924
3862
  const logLine = JSON.stringify(log) + "\n";
3925
3863
  await fs4.appendFile(interactionsFilePath, logLine, "utf-8");
3926
- logger6.debug("Interaction logged", {
3864
+ logger5.debug("Interaction logged", {
3927
3865
  conversationId: log.conversationId,
3928
3866
  toolName: log.toolName
3929
3867
  });
3930
3868
  } catch (error) {
3931
- logger6.error("Failed to log interaction", error, {
3869
+ logger5.error("Failed to log interaction", error, {
3932
3870
  conversationId: log.conversationId,
3933
3871
  toolName: log.toolName
3934
3872
  });
@@ -3950,7 +3888,7 @@ var FileStorage = class {
3950
3888
  const log = JSON.parse(line);
3951
3889
  logs.push(log);
3952
3890
  } catch {
3953
- logger6.warn("Skipping corrupted interaction log line", {
3891
+ logger5.warn("Skipping corrupted interaction log line", {
3954
3892
  conversationId
3955
3893
  });
3956
3894
  }
@@ -3960,7 +3898,7 @@ var FileStorage = class {
3960
3898
  if (error.code === "ENOENT") {
3961
3899
  return [];
3962
3900
  }
3963
- logger6.error("Failed to get interaction logs", error, {
3901
+ logger5.error("Failed to get interaction logs", error, {
3964
3902
  conversationId
3965
3903
  });
3966
3904
  throw error;
@@ -3980,12 +3918,12 @@ var FileStorage = class {
3980
3918
  const interactionsFilePath = this.getInteractionsFilePath(conversationId);
3981
3919
  try {
3982
3920
  await fs4.unlink(interactionsFilePath);
3983
- logger6.debug("Interaction logs deleted", { conversationId });
3921
+ logger5.debug("Interaction logs deleted", { conversationId });
3984
3922
  } catch (error) {
3985
3923
  if (error.code === "ENOENT") {
3986
3924
  return;
3987
3925
  }
3988
- logger6.warn("Failed to delete interaction logs", {
3926
+ logger5.warn("Failed to delete interaction logs", {
3989
3927
  conversationId,
3990
3928
  error: error.message
3991
3929
  });
@@ -4004,13 +3942,13 @@ var FileStorage = class {
4004
3942
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
4005
3943
  };
4006
3944
  await this.saveConversationState(updatedState);
4007
- logger6.debug("Conversation state reset", { conversationId });
3945
+ logger5.debug("Conversation state reset", { conversationId });
4008
3946
  }
4009
3947
  /**
4010
3948
  * Close file storage (no-op for file-based storage)
4011
3949
  */
4012
3950
  async close() {
4013
- logger6.debug("FileStorage closed");
3951
+ logger5.debug("FileStorage closed");
4014
3952
  }
4015
3953
  };
4016
3954
 
@@ -4022,7 +3960,7 @@ import { existsSync } from "fs";
4022
3960
  // ../core/dist/path-validation-utils.js
4023
3961
  import { access, stat } from "fs/promises";
4024
3962
  import { resolve, isAbsolute, join as join2, normalize, basename } from "path";
4025
- var logger7 = createLogger("PathValidationUtils");
3963
+ var logger6 = createLogger("PathValidationUtils");
4026
3964
  var PathValidationUtils = class {
4027
3965
  /**
4028
3966
  * Validate if a string is a known template name
@@ -4050,7 +3988,7 @@ var PathValidationUtils = class {
4050
3988
  error: "Path points to a directory, not a file"
4051
3989
  };
4052
3990
  }
4053
- logger7.debug("File path validated successfully", {
3991
+ logger6.debug("File path validated successfully", {
4054
3992
  originalPath: filePath,
4055
3993
  resolvedPath
4056
3994
  });
@@ -4060,7 +3998,7 @@ var PathValidationUtils = class {
4060
3998
  };
4061
3999
  } catch (error) {
4062
4000
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
4063
- logger7.debug("File path validation failed", {
4001
+ logger6.debug("File path validation failed", {
4064
4002
  filePath,
4065
4003
  error: errorMessage
4066
4004
  });
@@ -4090,7 +4028,7 @@ var PathValidationUtils = class {
4090
4028
  error: "Path is neither a file nor a directory"
4091
4029
  };
4092
4030
  }
4093
- logger7.debug("File or directory path validated successfully", {
4031
+ logger6.debug("File or directory path validated successfully", {
4094
4032
  originalPath: filePath,
4095
4033
  resolvedPath,
4096
4034
  isFile: stats.isFile(),
@@ -4102,7 +4040,7 @@ var PathValidationUtils = class {
4102
4040
  };
4103
4041
  } catch (error) {
4104
4042
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
4105
- logger7.debug("File or directory path validation failed", {
4043
+ logger6.debug("File or directory path validation failed", {
4106
4044
  filePath,
4107
4045
  error: errorMessage
4108
4046
  });
@@ -4217,7 +4155,7 @@ function getPathBasename(filePath, fallback = "unknown") {
4217
4155
  import { writeFile, readFile, access as access2 } from "fs/promises";
4218
4156
  import { dirname as dirname2 } from "path";
4219
4157
  import { mkdir } from "fs/promises";
4220
- var logger8 = createLogger("PlanManager");
4158
+ var logger7 = createLogger("PlanManager");
4221
4159
  var PlanManager = class {
4222
4160
  stateMachine = null;
4223
4161
  /**
@@ -4225,7 +4163,7 @@ var PlanManager = class {
4225
4163
  */
4226
4164
  setStateMachine(stateMachine) {
4227
4165
  this.stateMachine = stateMachine;
4228
- logger8.debug("State machine set for plan manager", {
4166
+ logger7.debug("State machine set for plan manager", {
4229
4167
  name: stateMachine.name,
4230
4168
  phases: Object.keys(stateMachine.states)
4231
4169
  });
@@ -4234,7 +4172,7 @@ var PlanManager = class {
4234
4172
  * Set the task backend configuration
4235
4173
  */
4236
4174
  setTaskBackend(taskBackend) {
4237
- logger8.debug("Task backend set for plan manager (markdown mode)", {
4175
+ logger7.debug("Task backend set for plan manager (markdown mode)", {
4238
4176
  backend: taskBackend.backend,
4239
4177
  available: taskBackend.isAvailable
4240
4178
  });
@@ -4262,43 +4200,43 @@ var PlanManager = class {
4262
4200
  * Create initial plan file if it doesn't exist
4263
4201
  */
4264
4202
  async ensurePlanFile(planFilePath, projectPath, gitBranch) {
4265
- logger8.debug("Ensuring plan file exists", {
4203
+ logger7.debug("Ensuring plan file exists", {
4266
4204
  planFilePath,
4267
4205
  projectPath,
4268
4206
  gitBranch
4269
4207
  });
4270
4208
  const planInfo = await this.getPlanFileInfo(planFilePath);
4271
4209
  if (!planInfo.exists) {
4272
- logger8.info("Plan file not found, creating initial plan", {
4210
+ logger7.info("Plan file not found, creating initial plan", {
4273
4211
  planFilePath
4274
4212
  });
4275
4213
  await this.createInitialPlanFile(planFilePath, projectPath, gitBranch);
4276
- logger8.info("Initial plan file created successfully", { planFilePath });
4214
+ logger7.info("Initial plan file created successfully", { planFilePath });
4277
4215
  } else {
4278
- logger8.debug("Plan file already exists", { planFilePath });
4216
+ logger7.debug("Plan file already exists", { planFilePath });
4279
4217
  }
4280
4218
  }
4281
4219
  /**
4282
4220
  * Create initial plan file with template content
4283
4221
  */
4284
4222
  async createInitialPlanFile(planFilePath, projectPath, gitBranch) {
4285
- logger8.debug("Creating initial plan file", { planFilePath });
4223
+ logger7.debug("Creating initial plan file", { planFilePath });
4286
4224
  try {
4287
4225
  await mkdir(dirname2(planFilePath), { recursive: true });
4288
- logger8.debug("Plan file directory ensured", {
4226
+ logger7.debug("Plan file directory ensured", {
4289
4227
  directory: dirname2(planFilePath)
4290
4228
  });
4291
4229
  const projectName = getPathBasename(projectPath, "Unknown Project");
4292
4230
  const branchInfo = gitBranch !== "no-git" ? ` (${gitBranch} branch)` : "";
4293
4231
  const initialContent = this.generateInitialPlanContent(projectName, branchInfo);
4294
4232
  await writeFile(planFilePath, initialContent, "utf-8");
4295
- logger8.info("Initial plan file written successfully", {
4233
+ logger7.info("Initial plan file written successfully", {
4296
4234
  planFilePath,
4297
4235
  contentLength: initialContent.length,
4298
4236
  projectName
4299
4237
  });
4300
4238
  } catch (error) {
4301
- logger8.error("Failed to create initial plan file", error, {
4239
+ logger7.error("Failed to create initial plan file", error, {
4302
4240
  planFilePath
4303
4241
  });
4304
4242
  throw error;
@@ -4330,7 +4268,7 @@ var PlanManager = class {
4330
4268
  *Additional context and observations*
4331
4269
 
4332
4270
  `;
4333
- content += `## ${this.capitalizePhase(initialPhase)}
4271
+ content += `## ${capitalizePhase(initialPhase)}
4334
4272
  ### Tasks
4335
4273
  - [ ] *Tasks will be added as they are identified*
4336
4274
 
@@ -4340,7 +4278,7 @@ var PlanManager = class {
4340
4278
  `;
4341
4279
  for (const phase of phases) {
4342
4280
  if (phase !== initialPhase) {
4343
- content += `## ${this.capitalizePhase(phase)}
4281
+ content += `## ${capitalizePhase(phase)}
4344
4282
  ### Tasks
4345
4283
  - [ ] *To be added when this phase becomes active*
4346
4284
 
@@ -4392,31 +4330,31 @@ var PlanManager = class {
4392
4330
  }
4393
4331
  const phaseDefinition = this.stateMachine.states[phase];
4394
4332
  if (!phaseDefinition) {
4395
- logger8.warn("Unknown phase for plan file guidance", { phase });
4396
- return `Update the ${this.capitalizePhase(phase)} section with current progress and mark completed tasks.`;
4333
+ logger7.warn("Unknown phase for plan file guidance", { phase });
4334
+ return `Update the ${capitalizePhase(phase)} section with current progress and mark completed tasks.`;
4397
4335
  }
4398
- const capitalizedPhase = this.capitalizePhase(phase);
4336
+ const capitalizedPhase = capitalizePhase(phase);
4399
4337
  return `Update the ${capitalizedPhase} section with progress. Mark completed tasks with [x] and add new tasks as they are identified.`;
4400
4338
  }
4401
4339
  /**
4402
4340
  * Delete plan file
4403
4341
  */
4404
4342
  async deletePlanFile(planFilePath) {
4405
- logger8.debug("Deleting plan file", { planFilePath });
4343
+ logger7.debug("Deleting plan file", { planFilePath });
4406
4344
  try {
4407
4345
  await access2(planFilePath);
4408
4346
  const { unlink: unlink2 } = await import("fs/promises");
4409
4347
  await unlink2(planFilePath);
4410
- logger8.info("Plan file deleted successfully", { planFilePath });
4348
+ logger7.info("Plan file deleted successfully", { planFilePath });
4411
4349
  return true;
4412
4350
  } catch (error) {
4413
4351
  if (error.code === "ENOENT") {
4414
- logger8.debug("Plan file does not exist, nothing to delete", {
4352
+ logger7.debug("Plan file does not exist, nothing to delete", {
4415
4353
  planFilePath
4416
4354
  });
4417
4355
  return true;
4418
4356
  }
4419
- logger8.error("Failed to delete plan file", error, {
4357
+ logger7.error("Failed to delete plan file", error, {
4420
4358
  planFilePath
4421
4359
  });
4422
4360
  throw error;
@@ -4426,32 +4364,26 @@ var PlanManager = class {
4426
4364
  * Ensure plan file is deleted (verify deletion)
4427
4365
  */
4428
4366
  async ensurePlanFileDeleted(planFilePath) {
4429
- logger8.debug("Ensuring plan file is deleted", { planFilePath });
4367
+ logger7.debug("Ensuring plan file is deleted", { planFilePath });
4430
4368
  try {
4431
4369
  await access2(planFilePath);
4432
- logger8.warn("Plan file still exists after deletion attempt", {
4370
+ logger7.warn("Plan file still exists after deletion attempt", {
4433
4371
  planFilePath
4434
4372
  });
4435
4373
  return false;
4436
4374
  } catch (error) {
4437
4375
  if (error.code === "ENOENT") {
4438
- logger8.debug("Plan file successfully deleted (does not exist)", {
4376
+ logger7.debug("Plan file successfully deleted (does not exist)", {
4439
4377
  planFilePath
4440
4378
  });
4441
4379
  return true;
4442
4380
  }
4443
- logger8.error("Error checking plan file deletion", error, {
4381
+ logger7.error("Error checking plan file deletion", error, {
4444
4382
  planFilePath
4445
4383
  });
4446
4384
  throw error;
4447
4385
  }
4448
4386
  }
4449
- /**
4450
- * Capitalize phase name for display
4451
- */
4452
- capitalizePhase(phase) {
4453
- return phase.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
4454
- }
4455
4387
  /**
4456
4388
  * Generate workflow documentation URL for predefined workflows
4457
4389
  * Returns undefined for custom workflows
@@ -4462,10 +4394,24 @@ var PlanManager = class {
4462
4394
  }
4463
4395
  return `https://mrsimpson.github.io/responsible-vibe-mcp/workflows/${workflowName}`;
4464
4396
  }
4397
+ /**
4398
+ * Generate base instructions for the LLM after a workflow is started.
4399
+ * Instructs the LLM to populate the Goal section and define phase entrance
4400
+ * criteria in the freshly created plan file.
4401
+ */
4402
+ getInitialPlanGuidance(planFilePath, workflowDocUrl) {
4403
+ const docInfo = workflowDocUrl ? `
4404
+
4405
+ Inform the user about the chosen workflow. They can visit: ${workflowDocUrl} to get detailed information.` : "";
4406
+ const i18nNote = `
4407
+
4408
+ NOTE: If the user is communicating in a non-English language, translate plan file content to that language while keeping markdown headers (##, ###) in English to maintain structure parsing. Continue all interactions in the user's language.`;
4409
+ return `**Read ${planFilePath}** to understand the workflow structure. Add entrance criteria for each phase (what must be true to enter), then call \`whats_next()\`.${docInfo}${i18nNote}`;
4410
+ }
4465
4411
  };
4466
4412
 
4467
4413
  // ../core/dist/conversation-manager.js
4468
- var logger9 = createLogger("ConversationManager");
4414
+ var logger8 = createLogger("ConversationManager");
4469
4415
  var ConversationManager = class {
4470
4416
  database;
4471
4417
  projectPath;
@@ -4492,11 +4438,11 @@ var ConversationManager = class {
4492
4438
  async getConversationContext() {
4493
4439
  const projectPath = this.getProjectPath();
4494
4440
  const gitBranch = this.getGitBranch(projectPath);
4495
- logger9.debug("Getting conversation context", { projectPath, gitBranch });
4441
+ logger8.debug("Getting conversation context", { projectPath, gitBranch });
4496
4442
  const conversationId = this.generateConversationId(projectPath, gitBranch);
4497
4443
  const state = await this.database.getConversationState(conversationId);
4498
4444
  if (!state) {
4499
- logger9.warn("No conversation found for context", {
4445
+ logger8.warn("No conversation found for context", {
4500
4446
  projectPath,
4501
4447
  gitBranch,
4502
4448
  conversationId
@@ -4525,7 +4471,7 @@ var ConversationManager = class {
4525
4471
  async createConversationContext(workflowName, projectPathOverride) {
4526
4472
  const projectPath = projectPathOverride || this.getProjectPath();
4527
4473
  const gitBranch = this.getGitBranch(projectPath);
4528
- logger9.debug("Creating conversation context", {
4474
+ logger8.debug("Creating conversation context", {
4529
4475
  projectPath,
4530
4476
  gitBranch,
4531
4477
  workflowName
@@ -4535,14 +4481,14 @@ var ConversationManager = class {
4535
4481
  if (existingState) {
4536
4482
  if (existingState.workflowName !== workflowName) {
4537
4483
  const errorMessage = `Development conversation already exists with workflow '${existingState.workflowName}'. Cannot change to '${workflowName}'. Use reset_development() first to start with a new workflow.`;
4538
- logger9.error("Attempted workflow change on existing conversation", new Error(errorMessage), {
4484
+ logger8.error("Attempted workflow change on existing conversation", new Error(errorMessage), {
4539
4485
  existingWorkflow: existingState.workflowName,
4540
4486
  requestedWorkflow: workflowName,
4541
4487
  conversationId
4542
4488
  });
4543
4489
  throw new Error(errorMessage);
4544
4490
  }
4545
- logger9.debug("Conversation already exists, returning existing context", {
4491
+ logger8.debug("Conversation already exists, returning existing context", {
4546
4492
  conversationId
4547
4493
  });
4548
4494
  return {
@@ -4571,7 +4517,7 @@ var ConversationManager = class {
4571
4517
  * @param updates - Partial state updates to apply
4572
4518
  */
4573
4519
  async updateConversationState(conversationId, updates) {
4574
- logger9.debug("Updating conversation state", { conversationId, updates });
4520
+ logger8.debug("Updating conversation state", { conversationId, updates });
4575
4521
  const currentState = await this.database.getConversationState(conversationId);
4576
4522
  if (!currentState) {
4577
4523
  throw new Error(`Conversation state not found for ID: ${conversationId}`);
@@ -4582,7 +4528,7 @@ var ConversationManager = class {
4582
4528
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
4583
4529
  };
4584
4530
  await this.database.saveConversationState(updatedState);
4585
- logger9.info("Conversation state updated", {
4531
+ logger8.info("Conversation state updated", {
4586
4532
  conversationId,
4587
4533
  currentPhase: updatedState.currentPhase
4588
4534
  });
@@ -4595,7 +4541,7 @@ var ConversationManager = class {
4595
4541
  * @param gitBranch - Git branch name
4596
4542
  */
4597
4543
  async createNewConversationState(conversationId, projectPath, gitBranch, workflowName = "waterfall") {
4598
- logger9.info("Creating new conversation state", {
4544
+ logger8.info("Creating new conversation state", {
4599
4545
  conversationId,
4600
4546
  projectPath,
4601
4547
  gitBranch
@@ -4619,7 +4565,7 @@ var ConversationManager = class {
4619
4565
  updatedAt: timestamp2
4620
4566
  };
4621
4567
  await this.database.saveConversationState(newState);
4622
- logger9.info("New conversation state created", {
4568
+ logger8.info("New conversation state created", {
4623
4569
  conversationId,
4624
4570
  planFilePath,
4625
4571
  initialPhase
@@ -4662,7 +4608,7 @@ var ConversationManager = class {
4662
4608
  getGitBranch(projectPath) {
4663
4609
  try {
4664
4610
  if (!existsSync(`${projectPath}/.git`)) {
4665
- logger9.debug('Not a git repository, using "default" as branch name', {
4611
+ logger8.debug('Not a git repository, using "default" as branch name', {
4666
4612
  projectPath
4667
4613
  });
4668
4614
  return "default";
@@ -4673,10 +4619,10 @@ var ConversationManager = class {
4673
4619
  stdio: ["ignore", "pipe", "ignore"]
4674
4620
  // Suppress stderr
4675
4621
  }).trim();
4676
- logger9.debug("Detected git branch", { projectPath, branch });
4622
+ logger8.debug("Detected git branch", { projectPath, branch });
4677
4623
  return branch;
4678
4624
  } catch (_error) {
4679
- logger9.debug('Failed to get git branch, using "default" as branch name', {
4625
+ logger8.debug('Failed to get git branch, using "default" as branch name', {
4680
4626
  projectPath
4681
4627
  });
4682
4628
  return "default";
@@ -4690,13 +4636,13 @@ var ConversationManager = class {
4690
4636
  try {
4691
4637
  const interactions = await this.database.getInteractionsByConversationId(conversationId);
4692
4638
  const count = interactions.length;
4693
- logger9.debug("Checked interaction count for conversation", {
4639
+ logger8.debug("Checked interaction count for conversation", {
4694
4640
  conversationId,
4695
4641
  count
4696
4642
  });
4697
4643
  return count > 0;
4698
4644
  } catch (error) {
4699
- logger9.error("Failed to check interaction count", error, {
4645
+ logger8.error("Failed to check interaction count", error, {
4700
4646
  conversationId
4701
4647
  });
4702
4648
  return false;
@@ -4706,24 +4652,24 @@ var ConversationManager = class {
4706
4652
  * Reset conversation data (hybrid approach)
4707
4653
  */
4708
4654
  async resetConversation(confirm, reason) {
4709
- logger9.info("Starting conversation reset", { confirm, reason });
4655
+ logger8.info("Starting conversation reset", { confirm, reason });
4710
4656
  this.validateResetRequest(confirm);
4711
4657
  const context = await this.getConversationContext();
4712
4658
  const resetItems = [];
4713
4659
  try {
4714
4660
  await this.database.softDeleteInteractionLogs(context.conversationId);
4715
4661
  resetItems.push("interaction_logs");
4716
- logger9.debug("Interaction logs soft deleted");
4662
+ logger8.debug("Interaction logs soft deleted");
4717
4663
  await this.database.deleteConversationState(context.conversationId);
4718
4664
  resetItems.push("conversation_state");
4719
- logger9.debug("Conversation state hard deleted");
4665
+ logger8.debug("Conversation state hard deleted");
4720
4666
  const planManager = new PlanManager();
4721
4667
  await planManager.deletePlanFile(context.planFilePath);
4722
4668
  resetItems.push("plan_file");
4723
- logger9.debug("Plan file deleted");
4669
+ logger8.debug("Plan file deleted");
4724
4670
  await this.verifyResetCleanup(context.conversationId, context.planFilePath);
4725
4671
  const message = `Successfully reset conversation ${context.conversationId}. Reset items: ${resetItems.join(", ")}${reason ? `. Reason: ${reason}` : ""}`;
4726
- logger9.info("Conversation reset completed successfully", {
4672
+ logger8.info("Conversation reset completed successfully", {
4727
4673
  conversationId: context.conversationId,
4728
4674
  resetItems,
4729
4675
  reason
@@ -4735,7 +4681,7 @@ var ConversationManager = class {
4735
4681
  message
4736
4682
  };
4737
4683
  } catch (error) {
4738
- logger9.error("Failed to reset conversation", error, {
4684
+ logger8.error("Failed to reset conversation", error, {
4739
4685
  conversationId: context.conversationId,
4740
4686
  resetItems,
4741
4687
  reason
@@ -4755,7 +4701,7 @@ var ConversationManager = class {
4755
4701
  * Verify that reset cleanup was successful
4756
4702
  */
4757
4703
  async verifyResetCleanup(conversationId, planFilePath) {
4758
- logger9.debug("Verifying reset cleanup", { conversationId, planFilePath });
4704
+ logger8.debug("Verifying reset cleanup", { conversationId, planFilePath });
4759
4705
  try {
4760
4706
  const state = await this.database.getConversationState(conversationId);
4761
4707
  if (state) {
@@ -4766,9 +4712,9 @@ var ConversationManager = class {
4766
4712
  if (!isDeleted) {
4767
4713
  throw new Error("Plan file was not properly deleted");
4768
4714
  }
4769
- logger9.debug("Reset cleanup verification successful");
4715
+ logger8.debug("Reset cleanup verification successful");
4770
4716
  } catch (error) {
4771
- logger9.error("Reset cleanup verification failed", error);
4717
+ logger8.error("Reset cleanup verification failed", error);
4772
4718
  throw error;
4773
4719
  }
4774
4720
  }
@@ -4776,13 +4722,13 @@ var ConversationManager = class {
4776
4722
  * Clean up conversation data (used internally)
4777
4723
  */
4778
4724
  async cleanupConversationData(conversationId) {
4779
- logger9.debug("Cleaning up conversation data", { conversationId });
4725
+ logger8.debug("Cleaning up conversation data", { conversationId });
4780
4726
  try {
4781
4727
  await this.database.softDeleteInteractionLogs(conversationId);
4782
4728
  await this.database.deleteConversationState(conversationId);
4783
- logger9.debug("Conversation data cleanup completed", { conversationId });
4729
+ logger8.debug("Conversation data cleanup completed", { conversationId });
4784
4730
  } catch (error) {
4785
- logger9.error("Failed to cleanup conversation data", error, {
4731
+ logger8.error("Failed to cleanup conversation data", error, {
4786
4732
  conversationId
4787
4733
  });
4788
4734
  throw error;
@@ -4795,7 +4741,7 @@ import { readFile as readFile2, readdir, stat as stat2 } from "fs/promises";
4795
4741
  import { join as join3, dirname as dirname3 } from "path";
4796
4742
  import { fileURLToPath as fileURLToPath3 } from "url";
4797
4743
  import { createRequire as createRequire3 } from "module";
4798
- var logger10 = createLogger("TemplateManager");
4744
+ var logger9 = createLogger("TemplateManager");
4799
4745
  var TemplateManager = class {
4800
4746
  templatesPath;
4801
4747
  constructor() {
@@ -4824,13 +4770,13 @@ var TemplateManager = class {
4824
4770
  for (const strategy of strategies) {
4825
4771
  try {
4826
4772
  __require("fs").accessSync(strategy);
4827
- logger10.debug("Using templates path", { path: strategy });
4773
+ logger9.debug("Using templates path", { path: strategy });
4828
4774
  return strategy;
4829
4775
  } catch (_error) {
4830
4776
  }
4831
4777
  }
4832
4778
  const fallback = strategies[0];
4833
- logger10.warn("No templates directory found, using fallback", {
4779
+ logger9.warn("No templates directory found, using fallback", {
4834
4780
  fallback,
4835
4781
  strategies
4836
4782
  });
@@ -4884,7 +4830,7 @@ var TemplateManager = class {
4884
4830
  const content = await readFile2(templateFilePath, "utf-8");
4885
4831
  return { content };
4886
4832
  } catch (error) {
4887
- logger10.error(`Failed to load template: ${type2}/${template}`, error);
4833
+ logger9.error(`Failed to load template: ${type2}/${template}`, error);
4888
4834
  throw new Error(`Template not found: ${type2}/${template}. Tried: ${templatePath} (directory) and ${templateFilePath} (file)`);
4889
4835
  }
4890
4836
  }
@@ -4965,16 +4911,16 @@ var TemplateManager = class {
4965
4911
  }
4966
4912
  templates.sort();
4967
4913
  } catch (error) {
4968
- logger10.warn(`Failed to scan templates for type: ${type2}`, {
4914
+ logger9.warn(`Failed to scan templates for type: ${type2}`, {
4969
4915
  typePath,
4970
4916
  error: error instanceof Error ? error.message : String(error)
4971
4917
  });
4972
4918
  }
4973
4919
  }
4974
- logger10.debug("Discovered available templates", result);
4920
+ logger9.debug("Discovered available templates", result);
4975
4921
  return result;
4976
4922
  } catch (error) {
4977
- logger10.error("Failed to discover templates", error);
4923
+ logger9.error("Failed to discover templates", error);
4978
4924
  return result;
4979
4925
  }
4980
4926
  }
@@ -4983,12 +4929,14 @@ var TemplateManager = class {
4983
4929
  // ../core/dist/project-docs-manager.js
4984
4930
  import { writeFile as writeFile2, access as access3, mkdir as mkdir2, unlink, symlink, lstat, stat as stat3, readdir as readdir2 } from "fs/promises";
4985
4931
  import { join as join4, dirname as dirname4, relative, extname, basename as basename2 } from "path";
4986
- var logger11 = createLogger("ProjectDocsManager");
4932
+ var defaultLogger2 = createLogger("ProjectDocsManager");
4987
4933
  var ProjectDocsManager = class {
4988
4934
  templateManager;
4989
4935
  // Make public for access from other classes
4990
- constructor() {
4936
+ logger;
4937
+ constructor(logger24 = defaultLogger2) {
4991
4938
  this.templateManager = new TemplateManager();
4939
+ this.logger = logger24;
4992
4940
  }
4993
4941
  /**
4994
4942
  * Get project docs directory path
@@ -5159,7 +5107,7 @@ var ProjectDocsManager = class {
5159
5107
  } else {
5160
5108
  skipped.push("design.md");
5161
5109
  }
5162
- logger11.info("Project docs creation/linking completed", {
5110
+ this.logger.info("Project docs creation/linking completed", {
5163
5111
  created,
5164
5112
  linked,
5165
5113
  skipped,
@@ -5178,13 +5126,13 @@ var ProjectDocsManager = class {
5178
5126
  const targetDir = dirname4(targetPath);
5179
5127
  const relativePath = relative(targetDir, sourcePath);
5180
5128
  await symlink(relativePath, targetPath);
5181
- logger11.debug("Symlink created successfully", {
5129
+ this.logger.debug("Symlink created successfully", {
5182
5130
  sourcePath,
5183
5131
  targetPath,
5184
5132
  relativePath
5185
5133
  });
5186
5134
  } catch (error) {
5187
- logger11.error("Failed to create symlink", error, {
5135
+ this.logger.error("Failed to create symlink", error, {
5188
5136
  sourcePath,
5189
5137
  targetPath
5190
5138
  });
@@ -5198,14 +5146,14 @@ var ProjectDocsManager = class {
5198
5146
  try {
5199
5147
  const stats = await lstat(documentPath);
5200
5148
  await unlink(documentPath);
5201
- logger11.debug("Existing document removed", {
5149
+ this.logger.debug("Existing document removed", {
5202
5150
  documentPath,
5203
5151
  wasSymlink: stats.isSymbolicLink()
5204
5152
  });
5205
5153
  } catch (error) {
5206
5154
  const nodeError = error;
5207
5155
  if (error instanceof Error && "code" in nodeError && nodeError.code !== "ENOENT") {
5208
- logger11.debug("Failed to remove existing document", {
5156
+ this.logger.debug("Failed to remove existing document", {
5209
5157
  documentPath,
5210
5158
  error: nodeError.message
5211
5159
  });
@@ -5227,9 +5175,9 @@ var ProjectDocsManager = class {
5227
5175
  await writeFile2(filePath, file.content.toString());
5228
5176
  }
5229
5177
  }
5230
- logger11.debug(`Created ${type2} document`, { documentPath, template });
5178
+ this.logger.debug(`Created ${type2} document`, { documentPath, template });
5231
5179
  } catch (error) {
5232
- logger11.error(`Failed to create ${type2} document`, error, {
5180
+ this.logger.error(`Failed to create ${type2} document`, error, {
5233
5181
  documentPath,
5234
5182
  template
5235
5183
  });
@@ -5300,12 +5248,12 @@ var ProjectDocsManager = class {
5300
5248
  // ../core/dist/file-detection-manager.js
5301
5249
  import { readdir as readdir3, access as access4 } from "fs/promises";
5302
5250
  import { join as join5, basename as basename3 } from "path";
5303
- var logger12 = createLogger("FileDetectionManager");
5251
+ var logger10 = createLogger("FileDetectionManager");
5304
5252
 
5305
5253
  // ../core/dist/git-manager.js
5306
5254
  import { execSync as execSync2 } from "child_process";
5307
5255
  import { existsSync as existsSync2 } from "fs";
5308
- var logger13 = createLogger("GitManager");
5256
+ var logger11 = createLogger("GitManager");
5309
5257
  var GitManager = class {
5310
5258
  /**
5311
5259
  * Check if a directory is a git repository
@@ -5319,7 +5267,7 @@ var GitManager = class {
5319
5267
  static getCurrentBranch(projectPath) {
5320
5268
  try {
5321
5269
  if (!this.isGitRepository(projectPath)) {
5322
- logger13.debug('Not a git repository, using "default" as branch name', {
5270
+ logger11.debug('Not a git repository, using "default" as branch name', {
5323
5271
  projectPath
5324
5272
  });
5325
5273
  return "default";
@@ -5329,10 +5277,10 @@ var GitManager = class {
5329
5277
  encoding: "utf-8",
5330
5278
  stdio: ["ignore", "pipe", "ignore"]
5331
5279
  }).trim();
5332
- logger13.debug("Detected git branch", { projectPath, branch });
5280
+ logger11.debug("Detected git branch", { projectPath, branch });
5333
5281
  return branch;
5334
5282
  } catch (_error) {
5335
- logger13.debug('Failed to get git branch, using "default" as branch name', {
5283
+ logger11.debug('Failed to get git branch, using "default" as branch name', {
5336
5284
  projectPath
5337
5285
  });
5338
5286
  return "default";
@@ -5353,7 +5301,7 @@ var GitManager = class {
5353
5301
  }).trim();
5354
5302
  return hash;
5355
5303
  } catch (error) {
5356
- logger13.debug("Failed to get current commit hash", { projectPath, error });
5304
+ logger11.debug("Failed to get current commit hash", { projectPath, error });
5357
5305
  return null;
5358
5306
  }
5359
5307
  }
@@ -5363,7 +5311,7 @@ var GitManager = class {
5363
5311
  static createCommit(message, projectPath) {
5364
5312
  try {
5365
5313
  if (!this.isGitRepository(projectPath)) {
5366
- logger13.debug("Not a git repository, skipping commit", { projectPath });
5314
+ logger11.debug("Not a git repository, skipping commit", { projectPath });
5367
5315
  return false;
5368
5316
  }
5369
5317
  execSync2("git add .", {
@@ -5376,10 +5324,10 @@ var GitManager = class {
5376
5324
  encoding: "utf-8",
5377
5325
  stdio: ["ignore", "pipe", "ignore"]
5378
5326
  });
5379
- logger13.debug("Created commit successfully", { projectPath, message });
5327
+ logger11.debug("Created commit successfully", { projectPath, message });
5380
5328
  return true;
5381
5329
  } catch (error) {
5382
- logger13.debug("Failed to create commit", {
5330
+ logger11.debug("Failed to create commit", {
5383
5331
  projectPath,
5384
5332
  message,
5385
5333
  error: error instanceof Error ? error.message : String(error)
@@ -5393,7 +5341,7 @@ var GitManager = class {
5393
5341
  static hasUncommittedChanges(projectPath) {
5394
5342
  try {
5395
5343
  if (!this.isGitRepository(projectPath)) {
5396
- logger13.debug("Not a git repository, no uncommitted changes", {
5344
+ logger11.debug("Not a git repository, no uncommitted changes", {
5397
5345
  projectPath
5398
5346
  });
5399
5347
  return false;
@@ -5404,13 +5352,13 @@ var GitManager = class {
5404
5352
  stdio: ["ignore", "pipe", "ignore"]
5405
5353
  }).trim();
5406
5354
  const hasChanges = status.length > 0;
5407
- logger13.debug("Checked for uncommitted changes", {
5355
+ logger11.debug("Checked for uncommitted changes", {
5408
5356
  projectPath,
5409
5357
  hasChanges
5410
5358
  });
5411
5359
  return hasChanges;
5412
5360
  } catch (error) {
5413
- logger13.debug("Failed to check for uncommitted changes", {
5361
+ logger11.debug("Failed to check for uncommitted changes", {
5414
5362
  projectPath,
5415
5363
  error: error instanceof Error ? error.message : String(error)
5416
5364
  });
@@ -5421,7 +5369,7 @@ var GitManager = class {
5421
5369
 
5422
5370
  // ../core/dist/task-backend.js
5423
5371
  import { execSync as execSync3 } from "child_process";
5424
- var logger14 = createLogger("TaskBackend");
5372
+ var defaultLogger3 = createLogger("TaskBackend");
5425
5373
  var TaskBackendManager = class _TaskBackendManager {
5426
5374
  /**
5427
5375
  * Detect and validate the requested task backend
@@ -5433,18 +5381,19 @@ var TaskBackendManager = class _TaskBackendManager {
5433
5381
  * When TASK_BACKEND is explicitly set:
5434
5382
  * - Uses the specified backend (markdown or beads)
5435
5383
  * - For beads, validates availability and provides setup instructions if not available
5384
+ *
5436
5385
  */
5437
- static detectTaskBackend() {
5386
+ static detectTaskBackend(logger24 = defaultLogger3) {
5438
5387
  const envBackend = process.env["TASK_BACKEND"]?.toLowerCase().trim();
5439
5388
  if (envBackend && !["markdown", "beads"].includes(envBackend)) {
5440
- logger14.debug("Invalid TASK_BACKEND value, treating as not set", {
5389
+ logger24.debug("Invalid TASK_BACKEND value, treating as not set", {
5441
5390
  envBackend
5442
5391
  });
5443
5392
  }
5444
5393
  if (!envBackend || !["markdown", "beads"].includes(envBackend)) {
5445
- const beadsAvailable2 = _TaskBackendManager.checkBeadsAvailability();
5394
+ const beadsAvailable2 = _TaskBackendManager.checkBeadsAvailability(logger24);
5446
5395
  if (beadsAvailable2.isAvailable) {
5447
- logger14.info("Auto-detected beads backend (bd command available)", {
5396
+ logger24.debug("Auto-detected beads backend (bd command available)", {
5448
5397
  reason: "TASK_BACKEND not set, bd command found"
5449
5398
  });
5450
5399
  return {
@@ -5452,7 +5401,7 @@ var TaskBackendManager = class _TaskBackendManager {
5452
5401
  isAvailable: true
5453
5402
  };
5454
5403
  }
5455
- logger14.debug("Using markdown backend (bd command not available)", {
5404
+ logger24.debug("Using markdown backend (bd command not available)", {
5456
5405
  reason: "TASK_BACKEND not set, bd command not found"
5457
5406
  });
5458
5407
  return {
@@ -5462,15 +5411,15 @@ var TaskBackendManager = class _TaskBackendManager {
5462
5411
  }
5463
5412
  const backend = envBackend;
5464
5413
  if (backend === "markdown") {
5465
- logger14.debug("Using explicitly configured markdown backend");
5414
+ logger24.debug("Using explicitly configured markdown backend");
5466
5415
  return {
5467
5416
  backend: "markdown",
5468
5417
  isAvailable: true
5469
5418
  };
5470
5419
  }
5471
- const beadsAvailable = _TaskBackendManager.checkBeadsAvailability();
5420
+ const beadsAvailable = _TaskBackendManager.checkBeadsAvailability(logger24);
5472
5421
  if (beadsAvailable.isAvailable) {
5473
- logger14.debug("Using explicitly configured beads backend");
5422
+ logger24.debug("Using explicitly configured beads backend");
5474
5423
  return {
5475
5424
  backend: "beads",
5476
5425
  isAvailable: true
@@ -5485,14 +5434,14 @@ var TaskBackendManager = class _TaskBackendManager {
5485
5434
  /**
5486
5435
  * Check if beads command is available and functional
5487
5436
  */
5488
- static checkBeadsAvailability() {
5437
+ static checkBeadsAvailability(logger24 = defaultLogger3) {
5489
5438
  try {
5490
5439
  const output = execSync3("bd --version", {
5491
5440
  encoding: "utf-8",
5492
5441
  stdio: ["ignore", "pipe", "pipe"],
5493
5442
  timeout: 5e3
5494
5443
  });
5495
- logger14.debug("Beads command available", { version: output.trim() });
5444
+ logger24.debug("Beads command available", { version: output.trim() });
5496
5445
  return { isAvailable: true };
5497
5446
  } catch (error) {
5498
5447
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -5508,7 +5457,7 @@ var TaskBackendManager = class _TaskBackendManager {
5508
5457
  errorMessage: "Beads command (bd) timed out. Check if beads is properly installed and configured."
5509
5458
  };
5510
5459
  }
5511
- logger14.warn("Beads availability check failed", { errorMessage });
5460
+ logger24.warn("Beads availability check failed", { errorMessage });
5512
5461
  return {
5513
5462
  isAvailable: false,
5514
5463
  errorMessage: `Beads command (bd) check failed: ${errorMessage}`
@@ -5561,9 +5510,10 @@ export TASK_BACKEND=markdown
5561
5510
  }
5562
5511
  /**
5563
5512
  * Validate task backend configuration and throw error if invalid
5513
+ *
5564
5514
  */
5565
- static validateTaskBackend() {
5566
- const config = this.detectTaskBackend();
5515
+ static validateTaskBackend(logger24 = defaultLogger3) {
5516
+ const config = this.detectTaskBackend(logger24);
5567
5517
  if (!config.isAvailable) {
5568
5518
  const setupInstructions = config.backend === "beads" ? this.getBeadsSetupInstructions() : "Task backend validation failed";
5569
5519
  throw new Error(`Task backend '${config.backend}' is not available.
@@ -5572,7 +5522,7 @@ ${config.errorMessage || ""}
5572
5522
 
5573
5523
  ${setupInstructions}`);
5574
5524
  }
5575
- logger14.info("Task backend validated successfully", {
5525
+ logger24.info("Task backend validated successfully", {
5576
5526
  backend: config.backend,
5577
5527
  available: config.isAvailable
5578
5528
  });
@@ -5582,11 +5532,13 @@ ${setupInstructions}`);
5582
5532
 
5583
5533
  // ../core/dist/beads-integration.js
5584
5534
  import { execSync as execSync4 } from "child_process";
5585
- var logger15 = createLogger("BeadsIntegration");
5535
+ var defaultLogger4 = createLogger("BeadsIntegration");
5586
5536
  var BeadsIntegration = class {
5587
5537
  projectPath;
5588
- constructor(projectPath) {
5538
+ logger;
5539
+ constructor(projectPath, logger24 = defaultLogger4) {
5589
5540
  this.projectPath = projectPath;
5541
+ this.logger = logger24;
5590
5542
  }
5591
5543
  /**
5592
5544
  * Ensure beads is initialized in the project directory
@@ -5602,7 +5554,7 @@ var BeadsIntegration = class {
5602
5554
  } catch (error) {
5603
5555
  const errorMessage = error instanceof Error ? error.message : String(error);
5604
5556
  if (errorMessage.includes("not initialized") || errorMessage.includes("no database") || errorMessage.includes("init")) {
5605
- logger15.info("Beads not initialized, running bd init --no-db", {
5557
+ this.logger.info("Beads not initialized, running bd init --no-db", {
5606
5558
  projectPath: this.projectPath
5607
5559
  });
5608
5560
  try {
@@ -5611,12 +5563,12 @@ var BeadsIntegration = class {
5611
5563
  encoding: "utf-8",
5612
5564
  stdio: ["ignore", "pipe", "pipe"]
5613
5565
  });
5614
- logger15.info("Successfully initialized beads in project", {
5566
+ this.logger.info("Successfully initialized beads in project", {
5615
5567
  projectPath: this.projectPath
5616
5568
  });
5617
5569
  } catch (initError) {
5618
5570
  const initErrorMessage = initError instanceof Error ? initError.message : String(initError);
5619
- logger15.error("Failed to initialize beads", initError instanceof Error ? initError : new Error(initErrorMessage), { projectPath: this.projectPath });
5571
+ this.logger.error("Failed to initialize beads", initError instanceof Error ? initError : new Error(initErrorMessage), { projectPath: this.projectPath });
5620
5572
  throw new Error(`Failed to initialize beads: ${initErrorMessage}`);
5621
5573
  }
5622
5574
  } else {
@@ -5634,7 +5586,7 @@ var BeadsIntegration = class {
5634
5586
  const epicDescription = description || `Responsible vibe engineering session using ${workflowName} workflow for ${projectName}`;
5635
5587
  const priority = 2;
5636
5588
  const command = `bd create "${epicTitle}" --description "${epicDescription}" --priority ${priority}`;
5637
- logger15.debug("Creating beads project epic", {
5589
+ this.logger.debug("Creating beads project epic", {
5638
5590
  command,
5639
5591
  projectName,
5640
5592
  workflowName,
@@ -5648,7 +5600,7 @@ var BeadsIntegration = class {
5648
5600
  });
5649
5601
  const match = output.match(/✓ Created issue: ([\w\d.-]+)/) || output.match(/Created issue: ([\w\d.-]+)/) || output.match(/Created (bd-[\w\d.]+)/);
5650
5602
  if (!match) {
5651
- logger15.warn("Failed to extract task ID from beads output", {
5603
+ this.logger.warn("Failed to extract task ID from beads output", {
5652
5604
  command: `bd create "${epicTitle}" --description "${epicDescription}" --priority 2`,
5653
5605
  output: output.slice(0, 200)
5654
5606
  // Truncated for logging
@@ -5656,7 +5608,7 @@ var BeadsIntegration = class {
5656
5608
  throw new Error(`Failed to extract task ID from beads output: ${output.slice(0, 100)}...`);
5657
5609
  }
5658
5610
  const epicId = match[1] || "";
5659
- logger15.info("Created beads project epic", {
5611
+ this.logger.info("Created beads project epic", {
5660
5612
  epicId,
5661
5613
  epicTitle,
5662
5614
  projectPath: this.projectPath
@@ -5670,10 +5622,10 @@ var BeadsIntegration = class {
5670
5622
  workflowName,
5671
5623
  projectPath: this.projectPath
5672
5624
  };
5673
- logger15.error("Failed to create beads project epic", error instanceof Error ? error : new Error(errorMessage), commandInfo);
5625
+ this.logger.error("Failed to create beads project epic", error instanceof Error ? error : new Error(errorMessage), commandInfo);
5674
5626
  const execError = error;
5675
5627
  if (execError?.stderr) {
5676
- logger15.error("Beads command stderr output", new Error("Command stderr"), {
5628
+ this.logger.error("Beads command stderr output", new Error("Command stderr"), {
5677
5629
  stderr: execError.stderr.toString(),
5678
5630
  ...commandInfo
5679
5631
  });
@@ -5689,12 +5641,12 @@ var BeadsIntegration = class {
5689
5641
  const phaseTasks = [];
5690
5642
  const phaseNames = Object.keys(phases);
5691
5643
  for (const phase of phaseNames) {
5692
- const phaseTitle = `${this.capitalizePhase(phase)}`;
5644
+ const phaseTitle = capitalizePhase(phase);
5693
5645
  const priority = 3;
5694
5646
  const stateDefinition = phases[phase];
5695
5647
  const description = (stateDefinition?.default_instructions || `${workflowName} workflow ${phase} phase tasks`).replace(/"/g, '\\"').replace(/\n/g, " ").replace(/\r/g, "").trim();
5696
5648
  const command = `bd create "${phaseTitle}" --description "${description}" --parent ${epicId} --priority ${priority}`;
5697
- logger15.debug("Creating beads phase task", {
5649
+ this.logger.debug("Creating beads phase task", {
5698
5650
  command,
5699
5651
  phase,
5700
5652
  epicId,
@@ -5708,7 +5660,7 @@ var BeadsIntegration = class {
5708
5660
  });
5709
5661
  const match = output.match(/✓ Created issue: ([\w\d.-]+)/) || output.match(/Created issue: ([\w\d.-]+)/) || output.match(/Created (bd-[\w\d.]+)/);
5710
5662
  if (!match) {
5711
- logger15.warn("Failed to extract phase task ID from beads output", {
5663
+ this.logger.warn("Failed to extract phase task ID from beads output", {
5712
5664
  command,
5713
5665
  output: output.slice(0, 200)
5714
5666
  // Truncated for logging
@@ -5721,7 +5673,7 @@ var BeadsIntegration = class {
5721
5673
  phaseName: phaseTitle,
5722
5674
  taskId: phaseTaskId
5723
5675
  });
5724
- logger15.debug("Created beads phase task", {
5676
+ this.logger.debug("Created beads phase task", {
5725
5677
  phase,
5726
5678
  phaseTaskId,
5727
5679
  epicId,
@@ -5735,10 +5687,10 @@ var BeadsIntegration = class {
5735
5687
  epicId,
5736
5688
  projectPath: this.projectPath
5737
5689
  };
5738
- logger15.error("Failed to create beads phase task", error instanceof Error ? error : new Error(errorMessage), commandInfo);
5690
+ this.logger.error("Failed to create beads phase task", error instanceof Error ? error : new Error(errorMessage), commandInfo);
5739
5691
  const execError = error;
5740
5692
  if (execError?.stderr) {
5741
- logger15.error("Beads phase command stderr output", new Error("Command stderr"), {
5693
+ this.logger.error("Beads phase command stderr output", new Error("Command stderr"), {
5742
5694
  stderr: execError.stderr.toString(),
5743
5695
  ...commandInfo
5744
5696
  });
@@ -5746,7 +5698,7 @@ var BeadsIntegration = class {
5746
5698
  throw new Error(`Failed to create beads phase task for ${phase}: ${errorMessage}`);
5747
5699
  }
5748
5700
  }
5749
- logger15.info("Created all beads phase tasks", {
5701
+ this.logger.info("Created all beads phase tasks", {
5750
5702
  count: phaseTasks.length,
5751
5703
  epicId,
5752
5704
  projectPath: this.projectPath
@@ -5759,13 +5711,13 @@ var BeadsIntegration = class {
5759
5711
  */
5760
5712
  async createPhaseDependencies(phaseTasks) {
5761
5713
  if (phaseTasks.length < 2) {
5762
- logger15.debug("Skipping phase dependencies - less than 2 phases", {
5714
+ this.logger.debug("Skipping phase dependencies - less than 2 phases", {
5763
5715
  phaseCount: phaseTasks.length,
5764
5716
  projectPath: this.projectPath
5765
5717
  });
5766
5718
  return;
5767
5719
  }
5768
- logger15.info("Creating sequential phase dependencies", {
5720
+ this.logger.info("Creating sequential phase dependencies", {
5769
5721
  phaseCount: phaseTasks.length,
5770
5722
  projectPath: this.projectPath
5771
5723
  });
@@ -5774,7 +5726,7 @@ var BeadsIntegration = class {
5774
5726
  const currentPhase = phaseTasks[i];
5775
5727
  const nextPhase = phaseTasks[i + 1];
5776
5728
  if (!currentPhase || !nextPhase) {
5777
- logger15.warn("Skipping phase dependency - missing phase data", {
5729
+ this.logger.warn("Skipping phase dependency - missing phase data", {
5778
5730
  currentPhaseIndex: i,
5779
5731
  nextPhaseIndex: i + 1,
5780
5732
  totalPhases: phaseTasks.length,
@@ -5788,7 +5740,7 @@ var BeadsIntegration = class {
5788
5740
  continue;
5789
5741
  }
5790
5742
  const command = `bd dep ${currentPhase.taskId} --blocks ${nextPhase.taskId}`;
5791
- logger15.debug("Creating phase dependency", {
5743
+ this.logger.debug("Creating phase dependency", {
5792
5744
  command,
5793
5745
  currentPhase: currentPhase.phaseName,
5794
5746
  nextPhase: nextPhase.phaseName,
@@ -5802,14 +5754,14 @@ var BeadsIntegration = class {
5802
5754
  encoding: "utf-8",
5803
5755
  stdio: ["ignore", "pipe", "pipe"]
5804
5756
  });
5805
- logger15.debug("Successfully created phase dependency", {
5757
+ this.logger.debug("Successfully created phase dependency", {
5806
5758
  currentPhase: currentPhase.phaseName,
5807
5759
  nextPhase: nextPhase.phaseName,
5808
5760
  projectPath: this.projectPath
5809
5761
  });
5810
5762
  } catch (error) {
5811
5763
  const errorMessage = error instanceof Error ? error.message : String(error);
5812
- logger15.warn("Failed to create phase dependency - continuing anyway", {
5764
+ this.logger.warn("Failed to create phase dependency - continuing anyway", {
5813
5765
  error: errorMessage,
5814
5766
  command,
5815
5767
  currentPhase: currentPhase.phaseName,
@@ -5818,7 +5770,7 @@ var BeadsIntegration = class {
5818
5770
  });
5819
5771
  const execError = error;
5820
5772
  if (execError?.stderr) {
5821
- logger15.debug("Beads dependency command stderr", {
5773
+ this.logger.debug("Beads dependency command stderr", {
5822
5774
  stderr: execError.stderr.toString(),
5823
5775
  command,
5824
5776
  projectPath: this.projectPath
@@ -5832,25 +5784,19 @@ var BeadsIntegration = class {
5832
5784
  }
5833
5785
  }
5834
5786
  if (failedDependencies.length > 0) {
5835
- logger15.warn("Some phase dependencies could not be created - app continues without these dependencies", {
5787
+ this.logger.warn("Some phase dependencies could not be created - app continues without these dependencies", {
5836
5788
  failedCount: failedDependencies.length,
5837
5789
  failedDependencies,
5838
5790
  projectPath: this.projectPath
5839
5791
  });
5840
5792
  }
5841
- logger15.info("Completed phase dependency creation", {
5793
+ this.logger.info("Completed phase dependency creation", {
5842
5794
  dependencyCount: phaseTasks.length - 1,
5843
5795
  successCount: phaseTasks.length - 1 - failedDependencies.length,
5844
5796
  failedCount: failedDependencies.length,
5845
5797
  projectPath: this.projectPath
5846
5798
  });
5847
5799
  }
5848
- /**
5849
- * Capitalize phase name for display
5850
- */
5851
- capitalizePhase(phase) {
5852
- return phase.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
5853
- }
5854
5800
  /**
5855
5801
  * Validate parameters for epic creation
5856
5802
  */
@@ -5898,11 +5844,13 @@ var BeadsIntegration = class {
5898
5844
  // ../core/dist/beads-state-manager.js
5899
5845
  import { writeFile as writeFile3, readFile as readFile3, mkdir as mkdir3, access as access5 } from "fs/promises";
5900
5846
  import { join as join6, dirname as dirname5 } from "path";
5901
- var logger16 = createLogger("BeadsStateManager");
5847
+ var defaultLogger5 = createLogger("BeadsStateManager");
5902
5848
  var BeadsStateManager = class {
5903
5849
  projectPath;
5904
- constructor(projectPath) {
5850
+ logger;
5851
+ constructor(projectPath, logger24 = defaultLogger5) {
5905
5852
  this.projectPath = projectPath;
5853
+ this.logger = logger24;
5906
5854
  }
5907
5855
  /**
5908
5856
  * Get the path to the beads state file for a conversation
@@ -5923,7 +5871,7 @@ var BeadsStateManager = class {
5923
5871
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
5924
5872
  };
5925
5873
  await this.saveState(state);
5926
- logger16.info("Created beads conversation state", {
5874
+ this.logger.info("Created beads conversation state", {
5927
5875
  conversationId,
5928
5876
  epicId,
5929
5877
  phaseCount: phaseTasks.length,
@@ -5940,7 +5888,7 @@ var BeadsStateManager = class {
5940
5888
  await access5(statePath);
5941
5889
  const content = await readFile3(statePath, "utf-8");
5942
5890
  const state = JSON.parse(content);
5943
- logger16.debug("Retrieved beads conversation state", {
5891
+ this.logger.debug("Retrieved beads conversation state", {
5944
5892
  conversationId,
5945
5893
  epicId: state.epicId,
5946
5894
  phaseCount: state.phaseTasks.length,
@@ -5949,14 +5897,14 @@ var BeadsStateManager = class {
5949
5897
  return state;
5950
5898
  } catch (error) {
5951
5899
  if (error.code === "ENOENT") {
5952
- logger16.debug("No beads state found for conversation", {
5900
+ this.logger.debug("No beads state found for conversation", {
5953
5901
  conversationId,
5954
5902
  projectPath: this.projectPath
5955
5903
  });
5956
5904
  return null;
5957
5905
  }
5958
5906
  const errorMessage = error instanceof Error ? error.message : String(error);
5959
- logger16.warn("Failed to read beads state file", {
5907
+ this.logger.warn("Failed to read beads state file", {
5960
5908
  error: errorMessage,
5961
5909
  conversationId,
5962
5910
  statePath,
@@ -5975,7 +5923,7 @@ var BeadsStateManager = class {
5975
5923
  }
5976
5924
  const phaseTask = state.phaseTasks.find((task) => task.phaseId === phase);
5977
5925
  if (phaseTask) {
5978
- logger16.debug("Found phase task ID", {
5926
+ this.logger.debug("Found phase task ID", {
5979
5927
  conversationId,
5980
5928
  phase,
5981
5929
  taskId: phaseTask.taskId,
@@ -5983,7 +5931,7 @@ var BeadsStateManager = class {
5983
5931
  });
5984
5932
  return phaseTask.taskId;
5985
5933
  }
5986
- logger16.debug("No task ID found for phase", {
5934
+ this.logger.debug("No task ID found for phase", {
5987
5935
  conversationId,
5988
5936
  phase,
5989
5937
  availablePhases: state.phaseTasks.map((t) => t.phaseId),
@@ -5997,7 +5945,7 @@ var BeadsStateManager = class {
5997
5945
  async updateState(conversationId, updates) {
5998
5946
  const existingState = await this.getState(conversationId);
5999
5947
  if (!existingState) {
6000
- logger16.warn("Cannot update non-existent beads state", {
5948
+ this.logger.warn("Cannot update non-existent beads state", {
6001
5949
  conversationId,
6002
5950
  projectPath: this.projectPath
6003
5951
  });
@@ -6011,7 +5959,7 @@ var BeadsStateManager = class {
6011
5959
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
6012
5960
  };
6013
5961
  await this.saveState(updatedState);
6014
- logger16.info("Updated beads conversation state", {
5962
+ this.logger.info("Updated beads conversation state", {
6015
5963
  conversationId,
6016
5964
  updatedFields: Object.keys(updates),
6017
5965
  projectPath: this.projectPath
@@ -6026,21 +5974,21 @@ var BeadsStateManager = class {
6026
5974
  try {
6027
5975
  await access5(statePath);
6028
5976
  await writeFile3(statePath + ".backup", await readFile3(statePath));
6029
- logger16.info("Cleaned up beads conversation state", {
5977
+ this.logger.info("Cleaned up beads conversation state", {
6030
5978
  conversationId,
6031
5979
  statePath,
6032
5980
  projectPath: this.projectPath
6033
5981
  });
6034
5982
  } catch (error) {
6035
5983
  if (error.code === "ENOENT") {
6036
- logger16.debug("No beads state to clean up", {
5984
+ this.logger.debug("No beads state to clean up", {
6037
5985
  conversationId,
6038
5986
  projectPath: this.projectPath
6039
5987
  });
6040
5988
  return;
6041
5989
  }
6042
5990
  const errorMessage = error instanceof Error ? error.message : String(error);
6043
- logger16.warn("Failed to clean up beads state", {
5991
+ this.logger.warn("Failed to clean up beads state", {
6044
5992
  error: errorMessage,
6045
5993
  conversationId,
6046
5994
  statePath,
@@ -6070,7 +6018,7 @@ var BeadsStateManager = class {
6070
6018
  await mkdir3(stateDir, { recursive: true });
6071
6019
  const content = JSON.stringify(state, null, 2);
6072
6020
  await writeFile3(statePath, content, "utf-8");
6073
- logger16.debug("Saved beads state to file", {
6021
+ this.logger.debug("Saved beads state to file", {
6074
6022
  conversationId: state.conversationId,
6075
6023
  statePath,
6076
6024
  fileSize: content.length,
@@ -6078,7 +6026,7 @@ var BeadsStateManager = class {
6078
6026
  });
6079
6027
  } catch (error) {
6080
6028
  const errorMessage = error instanceof Error ? error.message : String(error);
6081
- logger16.error("Failed to save beads state", error instanceof Error ? error : new Error(errorMessage), {
6029
+ this.logger.error("Failed to save beads state", error instanceof Error ? error : new Error(errorMessage), {
6082
6030
  conversationId: state.conversationId,
6083
6031
  statePath,
6084
6032
  projectPath: this.projectPath
@@ -6089,7 +6037,7 @@ var BeadsStateManager = class {
6089
6037
  };
6090
6038
 
6091
6039
  // ../core/dist/interaction-logger.js
6092
- var logger17 = createLogger("InteractionLogger");
6040
+ var logger12 = createLogger("InteractionLogger");
6093
6041
  var InteractionLogger = class {
6094
6042
  database;
6095
6043
  /**
@@ -6099,7 +6047,7 @@ var InteractionLogger = class {
6099
6047
  */
6100
6048
  constructor(database) {
6101
6049
  this.database = database;
6102
- logger17.debug("InteractionLogger initialized");
6050
+ logger12.debug("InteractionLogger initialized");
6103
6051
  }
6104
6052
  /**
6105
6053
  * Log an interaction with a tool
@@ -6112,7 +6060,7 @@ var InteractionLogger = class {
6112
6060
  * @returns Promise that resolves when the log is saved
6113
6061
  */
6114
6062
  async logInteraction(conversationId, toolName, inputParams, responseData, currentPhase) {
6115
- logger17.debug("Logging interaction", {
6063
+ logger12.debug("Logging interaction", {
6116
6064
  conversationId,
6117
6065
  toolName,
6118
6066
  currentPhase
@@ -6128,13 +6076,13 @@ var InteractionLogger = class {
6128
6076
  timestamp: timestamp2
6129
6077
  };
6130
6078
  await this.database.logInteraction(log);
6131
- logger17.info("Interaction logged successfully", {
6079
+ logger12.info("Interaction logged successfully", {
6132
6080
  conversationId,
6133
6081
  toolName,
6134
6082
  timestamp: timestamp2
6135
6083
  });
6136
6084
  } catch (error) {
6137
- logger17.error("Failed to log interaction", error, {
6085
+ logger12.error("Failed to log interaction", error, {
6138
6086
  conversationId,
6139
6087
  toolName
6140
6088
  });
@@ -6147,16 +6095,16 @@ var InteractionLogger = class {
6147
6095
  * @returns Promise that resolves to an array of interaction logs
6148
6096
  */
6149
6097
  async getInteractionsByConversationId(conversationId) {
6150
- logger17.debug("Getting interactions by conversation ID", { conversationId });
6098
+ logger12.debug("Getting interactions by conversation ID", { conversationId });
6151
6099
  try {
6152
6100
  const logs = await this.database.getInteractionsByConversationId(conversationId);
6153
- logger17.info("Retrieved interaction logs", {
6101
+ logger12.info("Retrieved interaction logs", {
6154
6102
  conversationId,
6155
6103
  count: logs.length
6156
6104
  });
6157
6105
  return logs;
6158
6106
  } catch (error) {
6159
- logger17.error("Failed to get interaction logs", error, {
6107
+ logger12.error("Failed to get interaction logs", error, {
6160
6108
  conversationId
6161
6109
  });
6162
6110
  throw error;
@@ -6167,11 +6115,11 @@ var InteractionLogger = class {
6167
6115
  // ../core/dist/instruction-generator.js
6168
6116
  var InstructionGenerator = class {
6169
6117
  projectDocsManager;
6170
- constructor(_planManager) {
6171
- this.projectDocsManager = new ProjectDocsManager();
6118
+ constructor(logger24 = createLogger("InstructionGenerator")) {
6119
+ this.projectDocsManager = new ProjectDocsManager(logger24);
6172
6120
  }
6173
6121
  /**
6174
- * Set the state machine definition for dynamic instruction generation
6122
+ * No-op: all phase context is provided per-call via InstructionContext.
6175
6123
  */
6176
6124
  setStateMachine(_stateMachine) {
6177
6125
  return;
@@ -6184,7 +6132,6 @@ var InstructionGenerator = class {
6184
6132
  const enhancedInstructions = await this.enhanceInstructions(substitutedInstructions, context);
6185
6133
  return {
6186
6134
  instructions: enhancedInstructions,
6187
- planFileGuidance: "Task management guidance is now included in main instructions",
6188
6135
  metadata: {
6189
6136
  phase: context.phase,
6190
6137
  planFilePath: context.conversationContext.planFilePath,
@@ -6215,43 +6162,36 @@ var InstructionGenerator = class {
6215
6162
  * Enhance base instructions with context-specific information
6216
6163
  */
6217
6164
  async enhanceInstructions(baseInstructions, context) {
6218
- const { phase, conversationContext, planFileExists } = context;
6219
- const phaseName = this.capitalizePhase(phase);
6165
+ const { phase, conversationContext, allowedFilePatterns } = context;
6166
+ const phaseName = capitalizePhase(phase);
6220
6167
  let workflowSection = `---
6221
- **Workflow Continuity:**
6222
- Maintain \`${conversationContext.planFilePath}\`:
6223
- - Work through tasks in the "${phaseName}" section; Focus on those tasks!
6224
- - Add newly discovered tasks; log decisions in "Key Decisions"
6225
- - DO NOT maintain tasks in other tools or documents than explicitly stated in this plan file!`;
6226
- if (!planFileExists) {
6227
- workflowSection += "\n- Note: plan file will be created on first update";
6228
- }
6229
- workflowSection += "\n\nCall `whats_next()` after each user message.";
6168
+ **Read \`${conversationContext.planFilePath}\`** for context.
6169
+ - Focus on "${phaseName}" tasks, log decisions in "Key Decisions"
6170
+ - Do NOT use other task/todo tools - use only the plan file for task tracking`;
6171
+ if (allowedFilePatterns && allowedFilePatterns.length > 0 && !allowedFilePatterns.includes("**/*") && !allowedFilePatterns.includes("*")) {
6172
+ workflowSection += `
6173
+ - Files allowed: \`${allowedFilePatterns.join("`, `")}\``;
6174
+ }
6175
+ workflowSection += "\n\nCall `whats_next()` after user messages.";
6230
6176
  return `## ${phaseName} Phase
6231
6177
 
6232
6178
  ${baseInstructions}
6233
6179
 
6234
6180
  ${workflowSection}`;
6235
6181
  }
6236
- /**
6237
- * Capitalize phase name for display
6238
- */
6239
- capitalizePhase(phase) {
6240
- return phase.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
6241
- }
6242
6182
  };
6243
6183
 
6244
6184
  // ../core/dist/system-prompt-generator.js
6245
- var logger18 = createLogger("SystemPromptGenerator");
6185
+ var logger13 = createLogger("SystemPromptGenerator");
6246
6186
  function generateSystemPrompt(stateMachine) {
6247
- logger18.debug("Generating system prompt from state machine definition", {
6187
+ logger13.debug("Generating system prompt from state machine definition", {
6248
6188
  stateMachineName: stateMachine.name,
6249
6189
  phaseCount: Object.keys(stateMachine.states).length
6250
6190
  });
6251
6191
  return generateSimpleSystemPrompt(stateMachine);
6252
6192
  }
6253
6193
  function generateSimpleSystemPrompt(_stateMachine) {
6254
- logger18.debug("Generating system prompt");
6194
+ logger13.debug("Generating system prompt");
6255
6195
  const systemPrompt = `
6256
6196
  You are an AI assistant that helps users develop software features using the workflows server.
6257
6197
 
@@ -6262,7 +6202,7 @@ Each tool call returns a JSON response with an "instructions" field. Follow thes
6262
6202
  Use the development plan which you will retrieve via whats_next() to record important insights and decisions as per the structure of the plan.
6263
6203
 
6264
6204
  Do not use your own task management tools.`;
6265
- logger18.info("System prompt generated successfully", {
6205
+ logger13.info("System prompt generated successfully", {
6266
6206
  promptLength: systemPrompt.length
6267
6207
  });
6268
6208
  return systemPrompt;
@@ -6277,12 +6217,13 @@ import * as path4 from "path";
6277
6217
 
6278
6218
  // src/server-helpers.ts
6279
6219
  import { homedir } from "os";
6280
- var logger19 = createLogger("ServerHelpers");
6281
- function normalizeProjectPath(projectPath) {
6220
+ var defaultLogger6 = createLogger("ServerHelpers");
6221
+ function normalizeProjectPath(projectPath, logger24) {
6222
+ const log = logger24 ?? defaultLogger6;
6282
6223
  const path6 = projectPath || process.cwd();
6283
6224
  if (path6 === "/" || path6 === "") {
6284
6225
  const homePath = homedir();
6285
- logger19.info("Invalid project path detected, using home directory", {
6226
+ log.info("Invalid project path detected, using home directory", {
6286
6227
  originalPath: path6,
6287
6228
  normalizedPath: homePath
6288
6229
  });
@@ -6305,14 +6246,18 @@ function createErrorResult(error, metadata) {
6305
6246
  metadata
6306
6247
  };
6307
6248
  }
6308
- async function safeExecute(operation, errorContext) {
6249
+ async function safeExecute(operation, errorContext, logger24) {
6250
+ const log = logger24 ?? defaultLogger6;
6309
6251
  try {
6310
6252
  const result = await operation();
6311
6253
  return createSuccessResult(result);
6312
6254
  } catch (error) {
6313
6255
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
6314
6256
  const contextualError = errorContext ? `${errorContext}: ${errorMessage}` : errorMessage;
6315
- logger19.error("Operation failed", error, { errorContext });
6257
+ const isExpectedError = errorMessage.includes("CONVERSATION_NOT_FOUND") || errorMessage.includes("Invalid workflow:");
6258
+ if (!isExpectedError) {
6259
+ log.error("Operation failed", error, { errorContext });
6260
+ }
6316
6261
  return createErrorResult(contextualError);
6317
6262
  }
6318
6263
  }
@@ -6376,14 +6321,16 @@ function generateWorkflowDescription(workflows) {
6376
6321
  description += "\u2022 **custom**: Use custom workflow from .vibe/workflows in your project\n\n";
6377
6322
  return description;
6378
6323
  }
6379
- function logHandlerExecution(handlerName, args) {
6380
- logger19.debug(`Executing ${handlerName} handler`, {
6324
+ function logHandlerExecution(handlerName, args, logger24) {
6325
+ const log = logger24 ?? defaultLogger6;
6326
+ log.debug(`Executing ${handlerName} handler`, {
6381
6327
  handlerName,
6382
6328
  argsKeys: Object.keys(args || {})
6383
6329
  });
6384
6330
  }
6385
- function logHandlerCompletion(handlerName, result) {
6386
- logger19.debug(`Completed ${handlerName} handler`, {
6331
+ function logHandlerCompletion(handlerName, result, logger24) {
6332
+ const log = logger24 ?? defaultLogger6;
6333
+ log.debug(`Completed ${handlerName} handler`, {
6387
6334
  handlerName,
6388
6335
  success: result.success,
6389
6336
  hasData: !!result.data,
@@ -6415,12 +6362,14 @@ var notificationService = new NotificationService();
6415
6362
  var PluginRegistry = class {
6416
6363
  plugins = /* @__PURE__ */ new Map();
6417
6364
  /**
6418
- * Register a plugin if it's enabled
6365
+ * Register a plugin.
6366
+ *
6367
+ * Note: Plugins are always registered regardless of isEnabled() state.
6368
+ * The isEnabled() check happens at hook execution time in getEnabledPlugins().
6369
+ * This allows plugins to activate/deactivate dynamically based on conditions
6370
+ * that may change after registration (e.g., backend availability).
6419
6371
  */
6420
6372
  registerPlugin(plugin) {
6421
- if (!plugin.isEnabled()) {
6422
- return;
6423
- }
6424
6373
  const name = plugin.getName();
6425
6374
  if (this.plugins.has(name)) {
6426
6375
  throw new Error(`Plugin with name '${name}' is already registered`);
@@ -6535,11 +6484,13 @@ var PluginRegistry = class {
6535
6484
 
6536
6485
  // src/components/beads/beads-task-backend-client.ts
6537
6486
  import { execSync as execSync5 } from "child_process";
6538
- var logger20 = createLogger("BeadsTaskBackendClient");
6487
+ var defaultLogger7 = createLogger("BeadsTaskBackendClient");
6539
6488
  var BeadsTaskBackendClient = class {
6540
6489
  projectPath;
6541
- constructor(projectPath) {
6490
+ logger;
6491
+ constructor(projectPath, logger24) {
6542
6492
  this.projectPath = projectPath;
6493
+ this.logger = logger24 ?? defaultLogger7;
6543
6494
  }
6544
6495
  /**
6545
6496
  * Execute a beads command safely
@@ -6547,7 +6498,7 @@ var BeadsTaskBackendClient = class {
6547
6498
  async executeBeadsCommand(args) {
6548
6499
  try {
6549
6500
  const command = `bd ${args.join(" ")}`;
6550
- logger20.debug("Executing beads command", {
6501
+ this.logger.debug("Executing beads command", {
6551
6502
  command,
6552
6503
  projectPath: this.projectPath
6553
6504
  });
@@ -6559,7 +6510,7 @@ var BeadsTaskBackendClient = class {
6559
6510
  return { success: true, stdout };
6560
6511
  } catch (error) {
6561
6512
  const execError = error;
6562
- logger20.warn("Beads command failed", {
6513
+ this.logger.warn("Beads command failed", {
6563
6514
  args,
6564
6515
  error: error instanceof Error ? error.message : String(error),
6565
6516
  stderr: execError.stderr,
@@ -6692,18 +6643,29 @@ var BeadsTaskBackendClient = class {
6692
6643
  };
6693
6644
 
6694
6645
  // src/plugin-system/beads-plugin.ts
6695
- var logger21 = createLogger("BeadsPlugin");
6696
6646
  var BeadsPlugin = class {
6697
6647
  projectPath;
6698
6648
  beadsStateManager;
6699
6649
  beadsTaskBackendClient;
6700
6650
  planManager;
6651
+ logger;
6652
+ loggerFactory;
6701
6653
  constructor(options) {
6702
6654
  this.projectPath = options.projectPath;
6703
- this.beadsStateManager = new BeadsStateManager(this.projectPath);
6704
- this.beadsTaskBackendClient = new BeadsTaskBackendClient(this.projectPath);
6655
+ this.loggerFactory = options.loggerFactory;
6656
+ this.logger = options.loggerFactory ? options.loggerFactory("BeadsPlugin") : createLogger("BeadsPlugin");
6657
+ this.beadsStateManager = new BeadsStateManager(
6658
+ this.projectPath,
6659
+ options.loggerFactory ? options.loggerFactory("BeadsStateManager") : void 0
6660
+ );
6661
+ this.beadsTaskBackendClient = new BeadsTaskBackendClient(
6662
+ this.projectPath,
6663
+ options.loggerFactory ? options.loggerFactory("BeadsTaskBackendClient") : void 0
6664
+ );
6705
6665
  this.planManager = new PlanManager();
6706
- logger21.debug("BeadsPlugin initialized", { projectPath: this.projectPath });
6666
+ this.logger.debug("BeadsPlugin initialized", {
6667
+ projectPath: this.projectPath
6668
+ });
6707
6669
  }
6708
6670
  getName() {
6709
6671
  return "BeadsPlugin";
@@ -6712,9 +6674,9 @@ var BeadsPlugin = class {
6712
6674
  return 100;
6713
6675
  }
6714
6676
  isEnabled() {
6715
- const taskBackendConfig = TaskBackendManager.detectTaskBackend();
6677
+ const taskBackendConfig = TaskBackendManager.detectTaskBackend(this.logger);
6716
6678
  const enabled = taskBackendConfig.backend === "beads" && taskBackendConfig.isAvailable;
6717
- logger21.debug("BeadsPlugin enablement check", {
6679
+ this.logger.debug("BeadsPlugin enablement check", {
6718
6680
  backend: taskBackendConfig.backend,
6719
6681
  isAvailable: taskBackendConfig.isAvailable,
6720
6682
  autoDetected: !process.env["TASK_BACKEND"],
@@ -6726,7 +6688,8 @@ var BeadsPlugin = class {
6726
6688
  return {
6727
6689
  afterStartDevelopment: this.handleAfterStartDevelopment.bind(this),
6728
6690
  beforePhaseTransition: this.handleBeforePhaseTransition.bind(this),
6729
- afterPlanFileCreated: this.handleAfterPlanFileCreated.bind(this)
6691
+ afterPlanFileCreated: this.handleAfterPlanFileCreated.bind(this),
6692
+ afterInstructionsGenerated: this.handleAfterInstructionsGenerated.bind(this)
6730
6693
  };
6731
6694
  }
6732
6695
  /**
@@ -6734,7 +6697,7 @@ var BeadsPlugin = class {
6734
6697
  * Replaces validateBeadsTaskCompletion() method from proceed-to-phase.ts
6735
6698
  */
6736
6699
  async handleBeforePhaseTransition(context, currentPhase, targetPhase) {
6737
- logger21.info(
6700
+ this.logger.info(
6738
6701
  "BeadsPlugin: Validating task completion before phase transition",
6739
6702
  {
6740
6703
  conversationId: context.conversationId,
@@ -6749,7 +6712,7 @@ var BeadsPlugin = class {
6749
6712
  targetPhase,
6750
6713
  context.projectPath
6751
6714
  );
6752
- logger21.info(
6715
+ this.logger.info(
6753
6716
  "BeadsPlugin: Task validation passed, allowing phase transition",
6754
6717
  {
6755
6718
  conversationId: context.conversationId,
@@ -6758,7 +6721,7 @@ var BeadsPlugin = class {
6758
6721
  }
6759
6722
  );
6760
6723
  } catch (error) {
6761
- logger21.info(
6724
+ this.logger.info(
6762
6725
  "BeadsPlugin: Task validation failed, blocking phase transition",
6763
6726
  {
6764
6727
  conversationId: context.conversationId,
@@ -6776,20 +6739,25 @@ var BeadsPlugin = class {
6776
6739
  * Implements graceful degradation: continues app operation even if beads operations fail
6777
6740
  */
6778
6741
  async handleAfterStartDevelopment(context, args, _result) {
6779
- logger21.info("BeadsPlugin: Setting up beads integration", {
6742
+ this.logger.info("BeadsPlugin: Setting up beads integration", {
6780
6743
  conversationId: context.conversationId,
6781
6744
  workflow: args.workflow,
6782
6745
  projectPath: context.projectPath
6783
6746
  });
6784
6747
  if (!context.stateMachine) {
6785
- logger21.error("BeadsPlugin: State machine not provided in plugin context");
6786
- logger21.warn(
6748
+ this.logger.error(
6749
+ "BeadsPlugin: State machine not provided in plugin context"
6750
+ );
6751
+ this.logger.warn(
6787
6752
  "BeadsPlugin: Beads integration disabled - continuing without beads"
6788
6753
  );
6789
6754
  return;
6790
6755
  }
6791
6756
  try {
6792
- const beadsIntegration = new BeadsIntegration(context.projectPath);
6757
+ const beadsIntegration = new BeadsIntegration(
6758
+ context.projectPath,
6759
+ this.loggerFactory ? this.loggerFactory("BeadsIntegration") : void 0
6760
+ );
6793
6761
  const projectName = getPathBasename(
6794
6762
  context.projectPath,
6795
6763
  "Unknown Project"
@@ -6801,7 +6769,7 @@ var BeadsPlugin = class {
6801
6769
  );
6802
6770
  goalDescription = this.extractGoalFromPlan(planFileContent);
6803
6771
  } catch (error) {
6804
- logger21.warn("BeadsPlugin: Could not extract goal from plan file", {
6772
+ this.logger.warn("BeadsPlugin: Could not extract goal from plan file", {
6805
6773
  error: error instanceof Error ? error.message : String(error),
6806
6774
  planFilePath: context.planFilePath
6807
6775
  });
@@ -6817,7 +6785,7 @@ var BeadsPlugin = class {
6817
6785
  );
6818
6786
  } catch (error) {
6819
6787
  const errorMsg = error instanceof Error ? error.message : String(error);
6820
- logger21.warn(
6788
+ this.logger.warn(
6821
6789
  "BeadsPlugin: Failed to create beads project epic - continuing without beads integration",
6822
6790
  {
6823
6791
  error: errorMsg,
@@ -6835,7 +6803,7 @@ var BeadsPlugin = class {
6835
6803
  );
6836
6804
  } catch (error) {
6837
6805
  const errorMsg = error instanceof Error ? error.message : String(error);
6838
- logger21.warn(
6806
+ this.logger.warn(
6839
6807
  "BeadsPlugin: Failed to create beads phase tasks - continuing without phase tracking",
6840
6808
  {
6841
6809
  error: errorMsg,
@@ -6848,7 +6816,7 @@ var BeadsPlugin = class {
6848
6816
  await beadsIntegration.createPhaseDependencies(phaseTasks);
6849
6817
  } catch (error) {
6850
6818
  const errorMsg = error instanceof Error ? error.message : String(error);
6851
- logger21.warn(
6819
+ this.logger.warn(
6852
6820
  "BeadsPlugin: Failed to create phase dependencies - continuing without dependencies",
6853
6821
  {
6854
6822
  error: errorMsg,
@@ -6863,7 +6831,7 @@ var BeadsPlugin = class {
6863
6831
  );
6864
6832
  } catch (error) {
6865
6833
  const errorMsg = error instanceof Error ? error.message : String(error);
6866
- logger21.warn(
6834
+ this.logger.warn(
6867
6835
  "BeadsPlugin: Failed to update plan file with beads task IDs - continuing without plan file updates",
6868
6836
  {
6869
6837
  error: errorMsg,
@@ -6879,7 +6847,7 @@ var BeadsPlugin = class {
6879
6847
  );
6880
6848
  } catch (error) {
6881
6849
  const errorMsg = error instanceof Error ? error.message : String(error);
6882
- logger21.warn(
6850
+ this.logger.warn(
6883
6851
  "BeadsPlugin: Failed to create beads state - continuing without state persistence",
6884
6852
  {
6885
6853
  error: errorMsg,
@@ -6887,7 +6855,7 @@ var BeadsPlugin = class {
6887
6855
  }
6888
6856
  );
6889
6857
  }
6890
- logger21.info("BeadsPlugin: Beads integration setup complete", {
6858
+ this.logger.info("BeadsPlugin: Beads integration setup complete", {
6891
6859
  conversationId: context.conversationId,
6892
6860
  epicId,
6893
6861
  phaseCount: phaseTasks?.length || 0,
@@ -6895,7 +6863,7 @@ var BeadsPlugin = class {
6895
6863
  });
6896
6864
  } catch (error) {
6897
6865
  const errorMsg = error instanceof Error ? error.message : String(error);
6898
- logger21.warn(
6866
+ this.logger.warn(
6899
6867
  "BeadsPlugin: Unexpected error during beads integration setup - continuing application without beads",
6900
6868
  {
6901
6869
  error: errorMsg,
@@ -6916,11 +6884,127 @@ var BeadsPlugin = class {
6916
6884
  * This hook ensures the plan has the proper structure to receive them.
6917
6885
  */
6918
6886
  async handleAfterPlanFileCreated(_context, planFilePath, content) {
6919
- logger21.debug("BeadsPlugin: afterPlanFileCreated hook invoked", {
6887
+ this.logger.debug("BeadsPlugin: afterPlanFileCreated hook invoked", {
6920
6888
  planFilePath,
6921
6889
  contentLength: content.length
6922
6890
  });
6923
- return content;
6891
+ let transformed = content;
6892
+ transformed = transformed.replace(
6893
+ /### Tasks\n- \[ \] \*Tasks will be added as they are identified\*\n\n### Completed\n- \[x\] Created development plan file/g,
6894
+ "<!-- beads-phase-id: TBD -->\n### Tasks\n\n*Tasks managed via `bd` CLI*"
6895
+ );
6896
+ transformed = transformed.replace(
6897
+ /### Tasks\n- \[ \] \*To be added when this phase becomes active\*\n\n### Completed\n\*None yet\*/g,
6898
+ "<!-- beads-phase-id: TBD -->\n### Tasks\n\n*Tasks managed via `bd` CLI*"
6899
+ );
6900
+ transformed = transformed.replace(
6901
+ /\*This plan is maintained by the LLM\. Tool responses provide guidance on which section to focus on and what tasks to work on\.\*/,
6902
+ "*This plan is maintained by the LLM and uses beads CLI for task management. Tool responses provide guidance on which bd commands to use for task management.*"
6903
+ );
6904
+ this.logger.debug("BeadsPlugin: Plan file transformed for beads", {
6905
+ planFilePath,
6906
+ originalLength: content.length,
6907
+ transformedLength: transformed.length,
6908
+ wasModified: content !== transformed
6909
+ });
6910
+ return transformed;
6911
+ }
6912
+ /**
6913
+ * Handle afterInstructionsGenerated hook
6914
+ * Enriches instructions with beads-specific task management guidance
6915
+ */
6916
+ async handleAfterInstructionsGenerated(context, instructions) {
6917
+ this.logger.debug("BeadsPlugin: afterInstructionsGenerated hook invoked", {
6918
+ phase: instructions.phase,
6919
+ instructionSource: instructions.instructionSource,
6920
+ planFilePath: instructions.planFilePath
6921
+ });
6922
+ const beadsGuidance = await this.generateBeadsGuidance(
6923
+ context,
6924
+ instructions
6925
+ );
6926
+ let enhanced = instructions.instructions;
6927
+ enhanced += `
6928
+
6929
+ Log decisions in plan file. Use ONLY \`bd\` CLI for tasks (not your own todo tools).${beadsGuidance}`;
6930
+ if (context.planFileExists === false) {
6931
+ enhanced += "\n\n**Note**: Plan file will be created when you first update it.";
6932
+ }
6933
+ enhanced += "\n\nCall `whats_next()` after user messages.";
6934
+ this.logger.debug(
6935
+ "BeadsPlugin: Instructions enriched with beads guidance",
6936
+ {
6937
+ originalLength: instructions.instructions.length,
6938
+ enrichedLength: enhanced.length
6939
+ }
6940
+ );
6941
+ return {
6942
+ ...instructions,
6943
+ instructions: enhanced
6944
+ };
6945
+ }
6946
+ /**
6947
+ * Generate beads-specific task management guidance
6948
+ */
6949
+ async generateBeadsGuidance(_context, instructions) {
6950
+ if (instructions.instructionSource === "whats_next" || instructions.instructionSource === "start_development") {
6951
+ const phaseTaskId = await this.extractPhaseTaskIdFromPlanFile(
6952
+ instructions.planFilePath,
6953
+ instructions.phase
6954
+ );
6955
+ if (!phaseTaskId) {
6956
+ return `
6957
+
6958
+ **Task Management (bd CLI):**
6959
+ Create tasks as sub-tasks of phase task: \`bd create 'title' --parent <phase-task-id>\`
6960
+ List open tasks: \`bd list --parent <phase-task-id> --status open\`
6961
+ Complete tasks: \`bd close <id>\``;
6962
+ }
6963
+ return `
6964
+
6965
+ **Task Management (bd CLI) - Phase: ${phaseTaskId}**
6966
+ Create tasks as sub-tasks: \`bd create 'title' --parent ${phaseTaskId}\`
6967
+ List open tasks: \`bd list --parent ${phaseTaskId} --status open\`
6968
+ Complete tasks: \`bd close <id>\``;
6969
+ }
6970
+ return "";
6971
+ }
6972
+ /**
6973
+ * Extract phase task ID from plan file
6974
+ */
6975
+ async extractPhaseTaskIdFromPlanFile(planFilePath, phase) {
6976
+ try {
6977
+ const { readFile: readFile5 } = await import("fs/promises");
6978
+ const content = await readFile5(planFilePath, "utf-8");
6979
+ const phaseName = this.capitalizePhase(phase);
6980
+ const phaseHeader = `## ${phaseName}`;
6981
+ const lines = content.split("\n");
6982
+ let foundPhaseHeader = false;
6983
+ for (const line of lines) {
6984
+ if (line.trim() === phaseHeader) {
6985
+ foundPhaseHeader = true;
6986
+ continue;
6987
+ }
6988
+ if (foundPhaseHeader && line.includes("beads-phase-id:")) {
6989
+ const match = line.match(/beads-phase-id:\s*([\w\d.-]+)/);
6990
+ if (match && match[1] && match[1] !== "TBD") {
6991
+ return match[1];
6992
+ }
6993
+ }
6994
+ if (foundPhaseHeader && line.startsWith("##") && line !== phaseHeader) {
6995
+ break;
6996
+ }
6997
+ }
6998
+ return null;
6999
+ } catch (_error) {
7000
+ return null;
7001
+ }
7002
+ }
7003
+ /**
7004
+ * Capitalize phase name for display
7005
+ */
7006
+ capitalizePhase(phase) {
7007
+ return phase.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
6924
7008
  }
6925
7009
  /**
6926
7010
  * Validate beads task completion before phase transition
@@ -6933,14 +7017,14 @@ var BeadsPlugin = class {
6933
7017
  isAvailable = await this.beadsTaskBackendClient.isAvailable();
6934
7018
  } catch (error) {
6935
7019
  const errorMsg = error instanceof Error ? error.message : String(error);
6936
- logger21.warn("BeadsPlugin: Failed to check beads availability", {
7020
+ this.logger.warn("BeadsPlugin: Failed to check beads availability", {
6937
7021
  error: errorMsg,
6938
7022
  conversationId
6939
7023
  });
6940
7024
  return;
6941
7025
  }
6942
7026
  if (!isAvailable) {
6943
- logger21.debug(
7027
+ this.logger.debug(
6944
7028
  "BeadsPlugin: Skipping beads task validation - beads CLI not available",
6945
7029
  {
6946
7030
  conversationId,
@@ -6958,7 +7042,7 @@ var BeadsPlugin = class {
6958
7042
  );
6959
7043
  } catch (error) {
6960
7044
  const errorMsg = error instanceof Error ? error.message : String(error);
6961
- logger21.warn("BeadsPlugin: Failed to get beads phase task ID", {
7045
+ this.logger.warn("BeadsPlugin: Failed to get beads phase task ID", {
6962
7046
  error: errorMsg,
6963
7047
  conversationId,
6964
7048
  currentPhase
@@ -6966,7 +7050,7 @@ var BeadsPlugin = class {
6966
7050
  return;
6967
7051
  }
6968
7052
  if (!currentPhaseTaskId) {
6969
- logger21.debug(
7053
+ this.logger.debug(
6970
7054
  "BeadsPlugin: No beads phase task ID found for current phase",
6971
7055
  {
6972
7056
  conversationId,
@@ -6977,7 +7061,7 @@ var BeadsPlugin = class {
6977
7061
  );
6978
7062
  return;
6979
7063
  }
6980
- logger21.debug(
7064
+ this.logger.debug(
6981
7065
  "BeadsPlugin: Checking for incomplete beads tasks using task backend client",
6982
7066
  {
6983
7067
  conversationId,
@@ -6992,7 +7076,7 @@ var BeadsPlugin = class {
6992
7076
  );
6993
7077
  } catch (error) {
6994
7078
  const errorMsg = error instanceof Error ? error.message : String(error);
6995
- logger21.warn(
7079
+ this.logger.warn(
6996
7080
  "BeadsPlugin: Failed to validate tasks with beads backend",
6997
7081
  {
6998
7082
  error: errorMsg,
@@ -7004,18 +7088,9 @@ var BeadsPlugin = class {
7004
7088
  }
7005
7089
  if (!validationResult.valid) {
7006
7090
  const incompleteTasks = validationResult.openTasks || [];
7007
- const taskDetails = incompleteTasks.map((task) => ` \u2022 ${task.id} - ${task.title || "Untitled task"}`).join("\n");
7008
- const errorMessage = `Cannot proceed to ${targetPhase} - ${incompleteTasks.length} incomplete task(s) in current phase "${currentPhase}":
7009
-
7010
- ${taskDetails}
7011
-
7012
- To proceed, check the in-progress-tasks using:
7013
-
7014
- bd list --parent ${currentPhaseTaskId} --status open
7015
-
7016
- You can also defer tasks if they're no longer needed:
7017
- bd defer <task-id> --until tomorrow`;
7018
- logger21.info(
7091
+ const taskIds = incompleteTasks.map((t) => t.id).join(", ");
7092
+ const errorMessage = `${incompleteTasks.length} incomplete task(s) in ${currentPhase}: ${taskIds}. Complete or defer (\`bd defer <id>\`) before proceeding.`;
7093
+ this.logger.info(
7019
7094
  "BeadsPlugin: Blocking phase transition due to incomplete beads tasks",
7020
7095
  {
7021
7096
  conversationId,
@@ -7028,7 +7103,7 @@ You can also defer tasks if they're no longer needed:
7028
7103
  );
7029
7104
  throw new Error(errorMessage);
7030
7105
  }
7031
- logger21.info(
7106
+ this.logger.info(
7032
7107
  "BeadsPlugin: All beads tasks completed in current phase, allowing transition",
7033
7108
  {
7034
7109
  conversationId,
@@ -7042,7 +7117,7 @@ You can also defer tasks if they're no longer needed:
7042
7117
  throw error;
7043
7118
  }
7044
7119
  const errorMessage = error instanceof Error ? error.message : String(error);
7045
- logger21.warn(
7120
+ this.logger.warn(
7046
7121
  "BeadsPlugin: Beads task validation failed, allowing transition to proceed",
7047
7122
  {
7048
7123
  error: errorMessage,
@@ -7095,13 +7170,13 @@ You can also defer tasks if they're no longer needed:
7095
7170
  */
7096
7171
  async updatePlanFileWithPhaseTaskIds(planFilePath, phaseTasks) {
7097
7172
  try {
7098
- const { readFile: readFile6, writeFile: writeFile6 } = await import("fs/promises");
7173
+ const { readFile: readFile5, writeFile: writeFile5 } = await import("fs/promises");
7099
7174
  let content;
7100
7175
  try {
7101
- content = await readFile6(planFilePath, "utf-8");
7176
+ content = await readFile5(planFilePath, "utf-8");
7102
7177
  } catch (error) {
7103
7178
  const errorMsg = error instanceof Error ? error.message : String(error);
7104
- logger21.warn("BeadsPlugin: Failed to read plan file for update", {
7179
+ this.logger.warn("BeadsPlugin: Failed to read plan file for update", {
7105
7180
  error: errorMsg,
7106
7181
  planFilePath
7107
7182
  });
@@ -7121,7 +7196,7 @@ You can also defer tasks if they're no longer needed:
7121
7196
  }
7122
7197
  const remainingTBDs = content.match(/<!-- beads-phase-id: TBD -->/g);
7123
7198
  if (remainingTBDs && remainingTBDs.length > 0) {
7124
- logger21.warn(
7199
+ this.logger.warn(
7125
7200
  "BeadsPlugin: Failed to replace all TBD placeholders in plan file",
7126
7201
  {
7127
7202
  planFilePath,
@@ -7131,16 +7206,16 @@ You can also defer tasks if they're no longer needed:
7131
7206
  );
7132
7207
  }
7133
7208
  try {
7134
- await writeFile6(planFilePath, content, "utf-8");
7209
+ await writeFile5(planFilePath, content, "utf-8");
7135
7210
  } catch (error) {
7136
7211
  const errorMsg = error instanceof Error ? error.message : String(error);
7137
- logger21.warn("BeadsPlugin: Failed to write updated plan file", {
7212
+ this.logger.warn("BeadsPlugin: Failed to write updated plan file", {
7138
7213
  error: errorMsg,
7139
7214
  planFilePath
7140
7215
  });
7141
7216
  return;
7142
7217
  }
7143
- logger21.info(
7218
+ this.logger.info(
7144
7219
  "BeadsPlugin: Successfully updated plan file with beads phase task IDs",
7145
7220
  {
7146
7221
  planFilePath,
@@ -7152,7 +7227,7 @@ You can also defer tasks if they're no longer needed:
7152
7227
  );
7153
7228
  } catch (error) {
7154
7229
  const errorMsg = error instanceof Error ? error.message : String(error);
7155
- logger21.warn(
7230
+ this.logger.warn(
7156
7231
  "BeadsPlugin: Unexpected error while updating plan file with phase task IDs",
7157
7232
  {
7158
7233
  error: errorMsg,
@@ -7164,13 +7239,13 @@ You can also defer tasks if they're no longer needed:
7164
7239
  };
7165
7240
 
7166
7241
  // src/plugin-system/commit-plugin.ts
7167
- var logger22 = createLogger("CommitPlugin");
7242
+ var logger14 = createLogger("CommitPlugin");
7168
7243
  var CommitPlugin = class {
7169
7244
  projectPath;
7170
7245
  initialCommitHash;
7171
7246
  constructor(options) {
7172
7247
  this.projectPath = options.projectPath;
7173
- logger22.debug("CommitPlugin initialized", { projectPath: this.projectPath });
7248
+ logger14.debug("CommitPlugin initialized", { projectPath: this.projectPath });
7174
7249
  }
7175
7250
  getName() {
7176
7251
  return "CommitPlugin";
@@ -7181,7 +7256,7 @@ var CommitPlugin = class {
7181
7256
  isEnabled() {
7182
7257
  const behavior = process.env.COMMIT_BEHAVIOR;
7183
7258
  const enabled = behavior && ["step", "phase", "end", "none"].includes(behavior);
7184
- logger22.debug("CommitPlugin enablement check", {
7259
+ logger14.debug("CommitPlugin enablement check", {
7185
7260
  COMMIT_BEHAVIOR: behavior,
7186
7261
  enabled: !!enabled
7187
7262
  });
@@ -7199,7 +7274,7 @@ var CommitPlugin = class {
7199
7274
  * Store initial commit hash for potential squashing later
7200
7275
  */
7201
7276
  async handleAfterStartDevelopment(context, _args, _result) {
7202
- logger22.info("CommitPlugin: Setting up commit behavior", {
7277
+ logger14.info("CommitPlugin: Setting up commit behavior", {
7203
7278
  conversationId: context.conversationId,
7204
7279
  behavior: process.env.COMMIT_BEHAVIOR,
7205
7280
  projectPath: context.projectPath
@@ -7207,13 +7282,13 @@ var CommitPlugin = class {
7207
7282
  try {
7208
7283
  if (GitManager.isGitRepository(context.projectPath)) {
7209
7284
  this.initialCommitHash = GitManager.getCurrentCommitHash(context.projectPath) || void 0;
7210
- logger22.debug("CommitPlugin: Stored initial commit hash", {
7285
+ logger14.debug("CommitPlugin: Stored initial commit hash", {
7211
7286
  conversationId: context.conversationId,
7212
7287
  initialCommitHash: this.initialCommitHash
7213
7288
  });
7214
7289
  }
7215
7290
  } catch (error) {
7216
- logger22.warn("CommitPlugin: Failed to get initial commit hash", {
7291
+ logger14.warn("CommitPlugin: Failed to get initial commit hash", {
7217
7292
  error: error instanceof Error ? error.message : String(error),
7218
7293
  conversationId: context.conversationId
7219
7294
  });
@@ -7228,7 +7303,7 @@ var CommitPlugin = class {
7228
7303
  if (behavior !== "phase" && behavior !== "step") {
7229
7304
  return;
7230
7305
  }
7231
- logger22.info("CommitPlugin: Creating WIP commit before phase transition", {
7306
+ logger14.info("CommitPlugin: Creating WIP commit before phase transition", {
7232
7307
  conversationId: context.conversationId,
7233
7308
  currentPhase,
7234
7309
  targetPhase,
@@ -7236,28 +7311,28 @@ var CommitPlugin = class {
7236
7311
  });
7237
7312
  try {
7238
7313
  if (!GitManager.isGitRepository(context.projectPath)) {
7239
- logger22.debug("CommitPlugin: Not a git repository, skipping commit");
7314
+ logger14.debug("CommitPlugin: Not a git repository, skipping commit");
7240
7315
  return;
7241
7316
  }
7242
7317
  if (!GitManager.hasUncommittedChanges(context.projectPath)) {
7243
- logger22.debug("CommitPlugin: No uncommitted changes, skipping commit");
7318
+ logger14.debug("CommitPlugin: No uncommitted changes, skipping commit");
7244
7319
  return;
7245
7320
  }
7246
7321
  const message = `WIP: transition to ${targetPhase}`;
7247
7322
  const success = GitManager.createCommit(message, context.projectPath);
7248
7323
  if (success) {
7249
- logger22.info("CommitPlugin: Created WIP commit successfully", {
7324
+ logger14.info("CommitPlugin: Created WIP commit successfully", {
7250
7325
  conversationId: context.conversationId,
7251
7326
  message
7252
7327
  });
7253
7328
  } else {
7254
- logger22.warn("CommitPlugin: Failed to create WIP commit", {
7329
+ logger14.warn("CommitPlugin: Failed to create WIP commit", {
7255
7330
  conversationId: context.conversationId,
7256
7331
  message
7257
7332
  });
7258
7333
  }
7259
7334
  } catch (error) {
7260
- logger22.warn("CommitPlugin: Error during phase transition commit", {
7335
+ logger14.warn("CommitPlugin: Error during phase transition commit", {
7261
7336
  error: error instanceof Error ? error.message : String(error),
7262
7337
  conversationId: context.conversationId
7263
7338
  });
@@ -7272,7 +7347,7 @@ var CommitPlugin = class {
7272
7347
  if (!behavior || behavior === "none") {
7273
7348
  return content;
7274
7349
  }
7275
- logger22.debug("CommitPlugin: Adding final commit task to plan file", {
7350
+ logger14.debug("CommitPlugin: Adding final commit task to plan file", {
7276
7351
  conversationId: context.conversationId,
7277
7352
  behavior,
7278
7353
  planFilePath
@@ -7296,7 +7371,7 @@ var CommitPlugin = class {
7296
7371
  }
7297
7372
  }
7298
7373
  if (finalPhaseIndex === -1) {
7299
- logger22.warn(
7374
+ logger14.warn(
7300
7375
  "CommitPlugin: Could not find final phase to add commit task"
7301
7376
  );
7302
7377
  return content;
@@ -7322,14 +7397,14 @@ var CommitPlugin = class {
7322
7397
  lines.splice(finalPhaseIndex + 1, 0, "", "### Tasks", commitTask);
7323
7398
  }
7324
7399
  const updatedContent = lines.join("\n");
7325
- logger22.info("CommitPlugin: Added final commit task to plan file", {
7400
+ logger14.info("CommitPlugin: Added final commit task to plan file", {
7326
7401
  conversationId: context.conversationId,
7327
7402
  behavior,
7328
7403
  commitTask
7329
7404
  });
7330
7405
  return updatedContent;
7331
7406
  } catch (error) {
7332
- logger22.warn("CommitPlugin: Failed to add commit task to plan file", {
7407
+ logger14.warn("CommitPlugin: Failed to add commit task to plan file", {
7333
7408
  error: error instanceof Error ? error.message : String(error),
7334
7409
  conversationId: context.conversationId
7335
7410
  });
@@ -7338,416 +7413,16 @@ var CommitPlugin = class {
7338
7413
  }
7339
7414
  };
7340
7415
 
7341
- // src/components/beads/beads-plan-manager.ts
7342
- import { writeFile as writeFile4, readFile as readFile4, access as access6 } from "fs/promises";
7343
- import { dirname as dirname6 } from "path";
7344
- import { mkdir as mkdir4 } from "fs/promises";
7345
- var logger23 = createLogger("BeadsPlanManager");
7346
- var BeadsPlanManager = class {
7347
- stateMachine = null;
7348
- /**
7349
- * Set the state machine definition for dynamic plan generation
7350
- */
7351
- setStateMachine(stateMachine) {
7352
- this.stateMachine = stateMachine;
7353
- logger23.debug("State machine set for beads plan manager", {
7354
- name: stateMachine.name,
7355
- phases: Object.keys(stateMachine.states)
7356
- });
7357
- }
7358
- /**
7359
- * Set the task backend configuration
7360
- */
7361
- setTaskBackend(taskBackend) {
7362
- logger23.debug("Task backend set for beads plan manager", {
7363
- backend: taskBackend.backend,
7364
- available: taskBackend.isAvailable
7365
- });
7366
- }
7367
- /**
7368
- * Get plan file information
7369
- */
7370
- async getPlanFileInfo(planFilePath) {
7371
- try {
7372
- await access6(planFilePath);
7373
- const content = await readFile4(planFilePath, "utf-8");
7374
- return {
7375
- path: planFilePath,
7376
- exists: true,
7377
- content
7378
- };
7379
- } catch (_error) {
7380
- return {
7381
- path: planFilePath,
7382
- exists: false
7383
- };
7384
- }
7385
- }
7386
- /**
7387
- * Create initial plan file if it doesn't exist
7388
- */
7389
- async ensurePlanFile(planFilePath, projectPath, gitBranch) {
7390
- logger23.debug("Ensuring beads plan file exists", {
7391
- planFilePath,
7392
- projectPath,
7393
- gitBranch
7394
- });
7395
- const planInfo = await this.getPlanFileInfo(planFilePath);
7396
- if (!planInfo.exists) {
7397
- logger23.info("Plan file not found, creating beads-optimized plan", {
7398
- planFilePath
7399
- });
7400
- await this.createInitialBeadsPlanFile(
7401
- planFilePath,
7402
- projectPath,
7403
- gitBranch
7404
- );
7405
- logger23.info("Beads plan file created successfully", { planFilePath });
7406
- } else {
7407
- logger23.debug("Plan file already exists", { planFilePath });
7408
- }
7409
- }
7410
- /**
7411
- * Create initial plan file optimized for beads workflow
7412
- */
7413
- async createInitialBeadsPlanFile(planFilePath, projectPath, gitBranch) {
7414
- logger23.debug("Creating beads-optimized plan file", { planFilePath });
7415
- try {
7416
- await mkdir4(dirname6(planFilePath), { recursive: true });
7417
- logger23.debug("Plan file directory ensured", {
7418
- directory: dirname6(planFilePath)
7419
- });
7420
- const projectName = getPathBasename(projectPath, "Unknown Project");
7421
- const branchInfo = gitBranch !== "no-git" ? ` (${gitBranch} branch)` : "";
7422
- const initialContent = this.generateBeadsInitialPlanContent(
7423
- projectName,
7424
- branchInfo
7425
- );
7426
- await writeFile4(planFilePath, initialContent, "utf-8");
7427
- logger23.info("Beads plan file written successfully", {
7428
- planFilePath,
7429
- contentLength: initialContent.length,
7430
- projectName
7431
- });
7432
- } catch (error) {
7433
- logger23.error("Failed to create beads plan file", error, {
7434
- planFilePath
7435
- });
7436
- throw error;
7437
- }
7438
- }
7439
- /**
7440
- * Generate initial plan file content optimized for beads workflow
7441
- */
7442
- generateBeadsInitialPlanContent(projectName, branchInfo) {
7443
- const timestamp2 = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
7444
- if (!this.stateMachine) {
7445
- throw new Error(
7446
- "State machine not set. This should not happen as state machine is always loaded."
7447
- );
7448
- }
7449
- const phases = Object.keys(this.stateMachine.states);
7450
- const initialPhase = this.stateMachine.initial_state;
7451
- const documentationUrl = this.generateWorkflowDocumentationUrl(
7452
- this.stateMachine.name
7453
- );
7454
- let content = `# Development Plan: ${projectName}${branchInfo}
7455
-
7456
- *Generated on ${timestamp2} by Vibe Feature MCP*
7457
- *Workflow: ${documentationUrl ? "[" + this.stateMachine.name + "](" + documentationUrl + ")" : this.stateMachine.name}*
7458
-
7459
- ## Goal
7460
- *Define what you're building or fixing - this will be updated as requirements are gathered*
7461
-
7462
- ## ${this.capitalizePhase(initialPhase)}
7463
- <!-- beads-phase-id: TBD -->
7464
- ### Tasks
7465
-
7466
- *Tasks managed via \`bd\` CLI*
7467
-
7468
- `;
7469
- for (const phase of phases) {
7470
- if (phase !== initialPhase) {
7471
- content += `## ${this.capitalizePhase(phase)}
7472
- <!-- beads-phase-id: TBD -->
7473
- ### Tasks
7474
-
7475
- *Tasks managed via \`bd\` CLI*
7476
-
7477
- `;
7478
- }
7479
- }
7480
- content += `## Key Decisions
7481
- *Important decisions will be documented here as they are made*
7482
-
7483
- ## Notes
7484
- *Additional context and observations*
7485
-
7486
- ---
7487
- *This plan is maintained by the LLM and uses beads CLI for task management. Tool responses provide guidance on which bd commands to use for task management.*
7488
- `;
7489
- return content;
7490
- }
7491
- /**
7492
- * Update plan file with new content
7493
- */
7494
- async updatePlanFile(planFilePath, content) {
7495
- await mkdir4(dirname6(planFilePath), { recursive: true });
7496
- await writeFile4(planFilePath, content, "utf-8");
7497
- }
7498
- /**
7499
- * Get plan file content for LLM context
7500
- */
7501
- async getPlanFileContent(planFilePath) {
7502
- const planInfo = await this.getPlanFileInfo(planFilePath);
7503
- if (!planInfo.exists) {
7504
- return "Plan file does not exist yet. It will be created when the LLM updates it.";
7505
- }
7506
- return planInfo.content || "";
7507
- }
7508
- /**
7509
- * Generate phase-specific plan file guidance optimized for beads
7510
- */
7511
- generatePlanFileGuidance(phase) {
7512
- if (!this.stateMachine) {
7513
- throw new Error(
7514
- "State machine not set. This should not happen as state machine is always loaded."
7515
- );
7516
- }
7517
- const phaseDefinition = this.stateMachine.states[phase];
7518
- if (!phaseDefinition) {
7519
- logger23.warn("Unknown phase for beads plan file guidance", { phase });
7520
- return `Track key decisions and take notes in the plan file. Use bd CLI for all task management.`;
7521
- }
7522
- return `Track key decisions and take notes in the plan file. Use bd CLI exclusively for task management - never use checkboxes. Document important decisions in the Key Decisions section.`;
7523
- }
7524
- /**
7525
- * Delete plan file
7526
- */
7527
- async deletePlanFile(planFilePath) {
7528
- logger23.debug("Deleting beads plan file", { planFilePath });
7529
- try {
7530
- await access6(planFilePath);
7531
- const { unlink: unlink2 } = await import("fs/promises");
7532
- await unlink2(planFilePath);
7533
- logger23.info("Beads plan file deleted successfully", { planFilePath });
7534
- return true;
7535
- } catch (error) {
7536
- if (error.code === "ENOENT") {
7537
- logger23.debug("Beads plan file does not exist, nothing to delete", {
7538
- planFilePath
7539
- });
7540
- return true;
7541
- }
7542
- logger23.error("Failed to delete beads plan file", error, {
7543
- planFilePath
7544
- });
7545
- throw error;
7546
- }
7547
- }
7548
- /**
7549
- * Ensure plan file is deleted (verify deletion)
7550
- */
7551
- async ensurePlanFileDeleted(planFilePath) {
7552
- logger23.debug("Ensuring beads plan file is deleted", { planFilePath });
7553
- try {
7554
- await access6(planFilePath);
7555
- logger23.warn("Beads plan file still exists after deletion attempt", {
7556
- planFilePath
7557
- });
7558
- return false;
7559
- } catch (error) {
7560
- if (error.code === "ENOENT") {
7561
- logger23.debug("Beads plan file successfully deleted (does not exist)", {
7562
- planFilePath
7563
- });
7564
- return true;
7565
- }
7566
- logger23.error("Error checking beads plan file deletion", error, {
7567
- planFilePath
7568
- });
7569
- throw error;
7570
- }
7571
- }
7572
- /**
7573
- * Capitalize phase name for display
7574
- */
7575
- capitalizePhase(phase) {
7576
- return phase.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
7577
- }
7578
- /**
7579
- * Generate workflow documentation URL for predefined workflows
7580
- */
7581
- generateWorkflowDocumentationUrl(workflowName) {
7582
- if (workflowName === "custom") {
7583
- return void 0;
7584
- }
7585
- return `https://mrsimpson.github.io/responsible-vibe-mcp/workflows/${workflowName}`;
7586
- }
7587
- };
7588
-
7589
- // src/components/beads/beads-instruction-generator.ts
7590
- var BeadsInstructionGenerator = class {
7591
- projectDocsManager;
7592
- constructor() {
7593
- this.projectDocsManager = new ProjectDocsManager();
7594
- }
7595
- /**
7596
- * Set the state machine definition (interface requirement)
7597
- */
7598
- setStateMachine(_stateMachine) {
7599
- }
7600
- /**
7601
- * Generate comprehensive instructions optimized for beads workflow
7602
- */
7603
- async generateInstructions(baseInstructions, context) {
7604
- const substitutedInstructions = this.applyVariableSubstitution(
7605
- baseInstructions,
7606
- context.conversationContext.projectPath,
7607
- context.conversationContext.gitBranch
7608
- );
7609
- const enhancedInstructions = await this.enhanceBeadsInstructions(
7610
- substitutedInstructions,
7611
- context
7612
- );
7613
- return {
7614
- instructions: enhancedInstructions,
7615
- planFileGuidance: "Using beads CLI for task management - plan file serves as context only",
7616
- metadata: {
7617
- phase: context.phase,
7618
- planFilePath: context.conversationContext.planFilePath,
7619
- transitionReason: context.transitionReason,
7620
- isModeled: context.isModeled
7621
- }
7622
- };
7623
- }
7624
- /**
7625
- * Apply variable substitution to instructions
7626
- */
7627
- applyVariableSubstitution(instructions, projectPath, gitBranch) {
7628
- const substitutions = this.projectDocsManager.getVariableSubstitutions(
7629
- projectPath,
7630
- gitBranch
7631
- );
7632
- let result = instructions;
7633
- for (const [variable, value] of Object.entries(substitutions)) {
7634
- result = result.replace(
7635
- new RegExp(this.escapeRegExp(variable), "g"),
7636
- value
7637
- );
7638
- }
7639
- return result;
7640
- }
7641
- /**
7642
- * Escape special regex characters in variable names
7643
- */
7644
- escapeRegExp(string) {
7645
- return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
7646
- }
7647
- /**
7648
- * Enhance instructions with beads-specific guidance
7649
- */
7650
- async enhanceBeadsInstructions(baseInstructions, context) {
7651
- const { planFileExists } = context;
7652
- const beadsTaskGuidance = await this.generateBeadsCLIGuidance(context);
7653
- let enhanced = `${baseInstructions}
7654
-
7655
- **Plan File Guidance:**
7656
- Use the plan file as memory for the current objective
7657
- - Update the "Key Decisions" section with important choices made
7658
- - Add relevant notes to help maintain context
7659
- - Do NOT enter tasks in the plan file, use beads CLI exclusively for task management
7660
-
7661
- ${beadsTaskGuidance}`;
7662
- if (!planFileExists) {
7663
- enhanced += "\n\n**Note**: Plan file will be created when you first update it.";
7664
- }
7665
- enhanced += `
7666
-
7667
- **Important Reminders:**
7668
- - Use ONLY bd CLI tool for task management - do not use your own task management tools
7669
- - Call whats_next() after the next user message to maintain the development workflow`;
7670
- return enhanced;
7671
- }
7672
- /**
7673
- * Generate beads-specific task management guidance
7674
- */
7675
- async generateBeadsCLIGuidance(context) {
7676
- const { instructionSource } = context;
7677
- if (instructionSource === "whats_next") {
7678
- let additionalInstructions = `**bd Task Management:**
7679
- `;
7680
- const phaseTaskId = await this.extractPhaseTaskId(context);
7681
- if (!phaseTaskId) {
7682
- return additionalInstructions + `- Use bd CLI tool exclusively
7683
- - **Start by listing ready tasks**: \`bd list --parent <phase-task-id> --status open\`
7684
- - **Create new tasks**: \`bd create 'Task title' --parent <phase-task-id> -p <priority>\`
7685
- - **Update status when working**: \`bd update <task-id> --status in_progress\`
7686
- - **Complete tasks**: \`bd close <task-id>\`
7687
- - **Focus on ready tasks first** - let beads handle dependencies
7688
- - Add new tasks as they are identified during your work with the user`;
7689
- }
7690
- return additionalInstructions + `
7691
- **Focus on subtasks of \`${phaseTaskId}\`**:
7692
- \u2022 \`bd list --parent ${phaseTaskId} --status open\` - List ready work items
7693
- \u2022 \`bd update <task-id> --status in_progress\` - Start working on a specific task
7694
- \u2022 \`bd close <task-id>\` - Mark task complete when finished
7695
-
7696
- **New Tasks for Current Phase**:
7697
- \u2022 \`bd create 'Task description' --parent ${phaseTaskId} -p <priority>\` - Create work item under current phase
7698
- \u2022 \`bd dep add <task-id> <depends-on-id>\` - Define dependencies for a task:`;
7699
- }
7700
- return "";
7701
- }
7702
- async extractPhaseTaskId(context) {
7703
- try {
7704
- const { readFile: readFile6 } = await import("fs/promises");
7705
- const content = await readFile6(
7706
- context.conversationContext.planFilePath,
7707
- "utf-8"
7708
- );
7709
- const phaseName = this.capitalizePhase(context.phase);
7710
- const phaseHeader = `## ${phaseName}`;
7711
- const phaseSection = content.split("\n");
7712
- let foundPhaseHeader = false;
7713
- for (const line of phaseSection) {
7714
- if (line.trim() === phaseHeader) {
7715
- foundPhaseHeader = true;
7716
- continue;
7717
- }
7718
- if (foundPhaseHeader && line.includes("beads-phase-id:")) {
7719
- const match = line.match(/beads-phase-id:\s*([\w\d.-]+)/);
7720
- if (match) {
7721
- return match[1] || null;
7722
- }
7723
- }
7724
- if (foundPhaseHeader && line.startsWith("##") && line !== phaseHeader) {
7725
- break;
7726
- }
7727
- }
7728
- return null;
7729
- } catch (_error) {
7730
- return null;
7731
- }
7732
- }
7733
- /**
7734
- * Capitalize phase name for display
7735
- */
7736
- capitalizePhase(phase) {
7737
- return phase.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
7738
- }
7739
- };
7740
-
7741
7416
  // src/server-config.ts
7742
- var logger24 = createLogger("ServerConfig");
7417
+ var logger15 = createLogger("ServerConfig");
7743
7418
  async function initializeServerComponents(config = {}) {
7744
- logger24.debug("Initializing server components", {
7419
+ logger15.debug("Initializing server components", {
7745
7420
  config: JSON.stringify(config)
7746
7421
  });
7747
7422
  const projectPath = normalizeProjectPath(
7748
7423
  config.projectPath || process.env.PROJECT_PATH
7749
7424
  );
7750
- logger24.info("Using project path", {
7425
+ logger15.info("Using project path", {
7751
7426
  projectPath,
7752
7427
  source: config.projectPath ? "config" : process.env.PROJECT_PATH ? "env" : "default"
7753
7428
  });
@@ -7764,11 +7439,11 @@ async function initializeServerComponents(config = {}) {
7764
7439
  );
7765
7440
  mcpServer.server.setRequestHandler(SetLevelRequestSchema, async (request) => {
7766
7441
  const level = request.params.level;
7767
- logger24.info("Setting logging level from MCP client", { level });
7768
- setMcpLoggingLevel(level);
7442
+ logger15.info("Setting logging level from MCP client", { level });
7443
+ setLoggingLevelFromString(level);
7769
7444
  return {};
7770
7445
  });
7771
- logger24.debug("Initializing core components");
7446
+ logger15.debug("Initializing core components");
7772
7447
  const database = new FileStorage(
7773
7448
  path4.join(projectPath, ".vibe", "conversation.sqlite")
7774
7449
  );
@@ -7781,38 +7456,31 @@ async function initializeServerComponents(config = {}) {
7781
7456
  const transitionEngine = new TransitionEngine(projectPath);
7782
7457
  transitionEngine.setConversationManager(conversationManager);
7783
7458
  const taskBackendConfig = TaskBackendManager.detectTaskBackend();
7784
- const isBeadsBackend = taskBackendConfig.backend === "beads" && taskBackendConfig.isAvailable;
7785
- logger24.info("Task backend configuration", {
7459
+ logger15.info("Task backend configuration", {
7786
7460
  backend: taskBackendConfig.backend,
7787
7461
  isAvailable: taskBackendConfig.isAvailable,
7788
7462
  autoDetected: !process.env["TASK_BACKEND"]
7789
7463
  });
7790
- const planManager = isBeadsBackend ? new BeadsPlanManager() : new PlanManager();
7791
- const instructionGenerator = isBeadsBackend ? new BeadsInstructionGenerator() : new InstructionGenerator(planManager);
7464
+ const planManager = new PlanManager();
7465
+ const instructionGenerator = new InstructionGenerator();
7792
7466
  const interactionLogger = new InteractionLogger(database);
7793
7467
  const pluginRegistry = new PluginRegistry();
7794
- if (process.env.COMMIT_BEHAVIOR) {
7795
- const commitPlugin = new CommitPlugin({ projectPath });
7796
- if (commitPlugin.isEnabled()) {
7797
- pluginRegistry.registerPlugin(commitPlugin);
7798
- logger24.info("CommitPlugin registered successfully", {
7799
- enabled: commitPlugin.isEnabled(),
7800
- sequence: commitPlugin.getSequence(),
7801
- behavior: process.env.COMMIT_BEHAVIOR
7802
- });
7803
- }
7804
- }
7805
- if (isBeadsBackend) {
7806
- const beadsPlugin = new BeadsPlugin({ projectPath });
7807
- if (beadsPlugin.isEnabled()) {
7808
- pluginRegistry.registerPlugin(beadsPlugin);
7809
- logger24.info("BeadsPlugin registered successfully", {
7810
- enabled: beadsPlugin.isEnabled(),
7811
- sequence: beadsPlugin.getSequence(),
7812
- autoDetected: !process.env["TASK_BACKEND"]
7813
- });
7814
- }
7815
- }
7468
+ const commitPlugin = new CommitPlugin({ projectPath });
7469
+ pluginRegistry.registerPlugin(commitPlugin);
7470
+ logger15.info("CommitPlugin registered", {
7471
+ enabled: commitPlugin.isEnabled(),
7472
+ sequence: commitPlugin.getSequence(),
7473
+ behavior: process.env.COMMIT_BEHAVIOR || "(not set)"
7474
+ });
7475
+ const beadsPlugin = new BeadsPlugin({ projectPath });
7476
+ pluginRegistry.registerPlugin(beadsPlugin);
7477
+ logger15.info("BeadsPlugin registered", {
7478
+ enabled: beadsPlugin.isEnabled(),
7479
+ sequence: beadsPlugin.getSequence(),
7480
+ backend: taskBackendConfig.backend,
7481
+ isAvailable: taskBackendConfig.isAvailable,
7482
+ autoDetected: !process.env["TASK_BACKEND"]
7483
+ });
7816
7484
  const context = {
7817
7485
  conversationManager,
7818
7486
  transitionEngine,
@@ -7825,7 +7493,7 @@ async function initializeServerComponents(config = {}) {
7825
7493
  };
7826
7494
  await database.initialize();
7827
7495
  workflowManager.loadProjectWorkflows(projectPath);
7828
- logger24.info("Server components initialized successfully");
7496
+ logger15.info("Server components initialized successfully");
7829
7497
  return {
7830
7498
  mcpServer,
7831
7499
  database,
@@ -7848,7 +7516,7 @@ function createToolHandler(toolName, toolRegistry, responseRenderer, context) {
7848
7516
  };
7849
7517
  }
7850
7518
  async function registerMcpTools(mcpServer, toolRegistry, responseRenderer, context) {
7851
- logger24.debug("Registering MCP tools");
7519
+ logger15.debug("Registering MCP tools");
7852
7520
  notificationService.setMcpServer(mcpServer);
7853
7521
  mcpServer.registerTool(
7854
7522
  "whats_next",
@@ -8048,7 +7716,7 @@ async function registerMcpTools(mcpServer, toolRegistry, responseRenderer, conte
8048
7716
  mcpServer.registerTool(
8049
7717
  "setup_project_docs",
8050
7718
  {
8051
- description: 'Create project documentation artifacts (architecture.md, requirements.md, design.md) using configurable templates OR by linking existing files via symlinks. **Linking existing documents Examples:**\n- `README.md` (project root)\n- `docs/architecture.md` (relative path)\n- `/absolute/path/to/requirements.txt`\n\n**Using "none" Option:**\n- Use `"none"` to create a placeholder that instructs LLM to use plan file instead\n- Useful when you prefer plan-file-only workflows\n\n**Mixed Usage Examples:**\n- `setup_project_docs({ architecture: "README.md", requirements: "none", design: "comprehensive" })`\n- `setup_project_docs({ architecture: "arc42", requirements: "ears", design: "none" })`',
7719
+ description: "Create or link project docs (architecture.md, requirements.md, design.md). Use template names or file paths.",
8052
7720
  inputSchema: {
8053
7721
  architecture: z.string().default("freestyle").describe(
8054
7722
  `Architecture documentation: template name (${availableTemplates.architecture.join(", ")}, none) OR file path to existing document`
@@ -8095,12 +7763,12 @@ async function registerMcpTools(mcpServer, toolRegistry, responseRenderer, conte
8095
7763
  },
8096
7764
  createToolHandler("no_idea", toolRegistry, responseRenderer, context)
8097
7765
  );
8098
- logger24.info("MCP tools registered successfully", {
7766
+ logger15.info("MCP tools registered successfully", {
8099
7767
  tools: toolRegistry.list()
8100
7768
  });
8101
7769
  }
8102
7770
  function registerMcpResources(mcpServer, resourceRegistry, responseRenderer, context) {
8103
- logger24.debug("Registering MCP resources");
7771
+ logger15.debug("Registering MCP resources");
8104
7772
  mcpServer.resource(
8105
7773
  "Current Development Plan",
8106
7774
  "plan://current",
@@ -8233,7 +7901,7 @@ function registerMcpResources(mcpServer, resourceRegistry, responseRenderer, con
8233
7901
  };
8234
7902
  }
8235
7903
  );
8236
- logger24.info("MCP resources registered successfully", {
7904
+ logger15.info("MCP resources registered successfully", {
8237
7905
  resources: ["plan://current", "state://current", "system-prompt://"],
8238
7906
  resourceTemplates: ["workflow://{name}"]
8239
7907
  });
@@ -8250,18 +7918,22 @@ var BaseToolHandler = class {
8250
7918
  */
8251
7919
  async handle(args, context) {
8252
7920
  const handlerName = this.constructor.name;
8253
- logHandlerExecution(handlerName, args);
7921
+ if (context.loggerFactory) {
7922
+ this.logger = context.loggerFactory(handlerName);
7923
+ }
7924
+ logHandlerExecution(handlerName, args, this.logger);
8254
7925
  const result = await safeExecute(
8255
7926
  () => this.executeHandler(args, context),
8256
- `${handlerName} execution failed`
7927
+ `${handlerName} execution failed`,
7928
+ this.logger
8257
7929
  );
8258
7930
  if (!result.success && result.error?.includes("CONVERSATION_NOT_FOUND")) {
8259
7931
  const availableWorkflows = context.workflowManager.getWorkflowNames();
8260
7932
  const helpfulError = createConversationNotFoundResult(availableWorkflows);
8261
- logHandlerCompletion(handlerName, helpfulError);
7933
+ logHandlerCompletion(handlerName, helpfulError, this.logger);
8262
7934
  return helpfulError;
8263
7935
  }
8264
- logHandlerCompletion(handlerName, result);
7936
+ logHandlerCompletion(handlerName, result, this.logger);
8265
7937
  return result;
8266
7938
  }
8267
7939
  /**
@@ -8397,6 +8069,12 @@ var WhatsNextHandler = class extends ConversationRequiredToolHandler {
8397
8069
  const planInfo = await context.planManager.getPlanFileInfo(
8398
8070
  conversationContext.planFilePath
8399
8071
  );
8072
+ const stateMachine = context.workflowManager.loadWorkflowForProject(
8073
+ conversationContext.projectPath,
8074
+ conversationContext.workflowName
8075
+ );
8076
+ const phaseState = stateMachine.states[transitionResult.newPhase];
8077
+ const allowedFilePatterns = phaseState?.allowed_file_patterns ?? ["**/*"];
8400
8078
  const instructions = await context.instructionGenerator.generateInstructions(
8401
8079
  transitionResult.instructions,
8402
8080
  {
@@ -8407,14 +8085,40 @@ var WhatsNextHandler = class extends ConversationRequiredToolHandler {
8407
8085
  },
8408
8086
  transitionReason: transitionResult.transitionReason,
8409
8087
  isModeled: transitionResult.isModeled,
8410
- planFileExists: planInfo.exists,
8411
- instructionSource: "whats_next"
8088
+ instructionSource: "whats_next",
8089
+ allowedFilePatterns
8412
8090
  }
8413
8091
  );
8092
+ let finalInstructions = instructions.instructions;
8093
+ if (context.pluginRegistry?.hasHook("afterInstructionsGenerated")) {
8094
+ const hookContext = {
8095
+ conversationId,
8096
+ planFilePath: conversationContext.planFilePath,
8097
+ currentPhase: transitionResult.newPhase,
8098
+ workflow: conversationContext.workflowName,
8099
+ projectPath: conversationContext.projectPath,
8100
+ gitBranch: conversationContext.gitBranch,
8101
+ planFileExists: planInfo.exists
8102
+ };
8103
+ const enriched = await context.pluginRegistry.executeHook(
8104
+ "afterInstructionsGenerated",
8105
+ hookContext,
8106
+ {
8107
+ instructions: instructions.instructions,
8108
+ planFilePath: conversationContext.planFilePath,
8109
+ phase: transitionResult.newPhase,
8110
+ instructionSource: "whats_next"
8111
+ }
8112
+ );
8113
+ if (enriched && typeof enriched === "object" && "instructions" in enriched) {
8114
+ finalInstructions = enriched.instructions;
8115
+ }
8116
+ }
8414
8117
  const response = {
8415
8118
  phase: transitionResult.newPhase,
8416
- instructions: instructions.instructions,
8417
- plan_file_path: conversationContext.planFilePath
8119
+ instructions: finalInstructions,
8120
+ plan_file_path: conversationContext.planFilePath,
8121
+ allowed_file_patterns: allowedFilePatterns
8418
8122
  };
8419
8123
  await this.logInteraction(
8420
8124
  context,
@@ -8459,8 +8163,6 @@ var WhatsNextHandler = class extends ConversationRequiredToolHandler {
8459
8163
  }
8460
8164
  return true;
8461
8165
  }
8462
- // Beads-specific instruction logic has been moved to BeadsInstructionGenerator strategy
8463
- // Utility methods moved to strategy implementations where needed
8464
8166
  };
8465
8167
 
8466
8168
  // src/tool-handlers/proceed-to-phase.ts
@@ -8494,6 +8196,9 @@ var ProceedToPhaseHandler = class extends ConversationRequiredToolHandler {
8494
8196
  conversationContext.projectPath,
8495
8197
  context
8496
8198
  );
8199
+ const prePlanInfo = await context.planManager.getPlanFileInfo(
8200
+ conversationContext.planFilePath
8201
+ );
8497
8202
  const pluginContext = {
8498
8203
  conversationId,
8499
8204
  planFilePath: conversationContext.planFilePath,
@@ -8501,6 +8206,7 @@ var ProceedToPhaseHandler = class extends ConversationRequiredToolHandler {
8501
8206
  workflow: conversationContext.workflowName,
8502
8207
  projectPath: conversationContext.projectPath,
8503
8208
  gitBranch: conversationContext.gitBranch,
8209
+ planFileExists: prePlanInfo.exists,
8504
8210
  targetPhase: target_phase
8505
8211
  };
8506
8212
  if (context.pluginRegistry) {
@@ -8535,6 +8241,12 @@ var ProceedToPhaseHandler = class extends ConversationRequiredToolHandler {
8535
8241
  const planInfo = await context.planManager.getPlanFileInfo(
8536
8242
  conversationContext.planFilePath
8537
8243
  );
8244
+ const stateMachine = context.workflowManager.loadWorkflowForProject(
8245
+ conversationContext.projectPath,
8246
+ conversationContext.workflowName
8247
+ );
8248
+ const phaseState = stateMachine.states[transitionResult.newPhase];
8249
+ const allowedFilePatterns = phaseState?.allowed_file_patterns ?? ["**/*"];
8538
8250
  const instructions = await context.instructionGenerator.generateInstructions(
8539
8251
  transitionResult.instructions,
8540
8252
  {
@@ -8545,20 +8257,42 @@ var ProceedToPhaseHandler = class extends ConversationRequiredToolHandler {
8545
8257
  },
8546
8258
  transitionReason: transitionResult.transitionReason,
8547
8259
  isModeled: transitionResult.isModeled,
8548
- planFileExists: planInfo.exists,
8549
- instructionSource: "proceed_to_phase"
8260
+ instructionSource: "proceed_to_phase",
8261
+ allowedFilePatterns
8550
8262
  }
8551
8263
  );
8552
- instructions.instructions += `
8553
-
8554
- After transitioning to the ${transitionResult.newPhase} phase, check the already created tasks and add those that are missing based on the key decisions noted in the plan file.
8555
- While doing this, also denote dependencies for each task.
8556
- `;
8264
+ let finalInstructions = instructions.instructions;
8265
+ if (context.pluginRegistry?.hasHook("afterInstructionsGenerated")) {
8266
+ const hookContext = {
8267
+ conversationId,
8268
+ planFilePath: conversationContext.planFilePath,
8269
+ currentPhase: transitionResult.newPhase,
8270
+ workflow: conversationContext.workflowName,
8271
+ projectPath: conversationContext.projectPath,
8272
+ gitBranch: conversationContext.gitBranch,
8273
+ planFileExists: planInfo.exists
8274
+ };
8275
+ const enriched = await context.pluginRegistry.executeHook(
8276
+ "afterInstructionsGenerated",
8277
+ hookContext,
8278
+ {
8279
+ instructions: instructions.instructions,
8280
+ planFilePath: conversationContext.planFilePath,
8281
+ phase: transitionResult.newPhase,
8282
+ instructionSource: "proceed_to_phase"
8283
+ }
8284
+ );
8285
+ if (enriched && typeof enriched === "object" && "instructions" in enriched) {
8286
+ finalInstructions = enriched.instructions;
8287
+ }
8288
+ }
8289
+ finalInstructions += ` Review tasks for ${transitionResult.newPhase} phase, add missing ones based on key decisions.`;
8557
8290
  const response = {
8558
8291
  phase: transitionResult.newPhase,
8559
- instructions: instructions.instructions,
8292
+ instructions: finalInstructions,
8560
8293
  plan_file_path: conversationContext.planFilePath,
8561
- transition_reason: transitionResult.transitionReason
8294
+ transition_reason: transitionResult.transitionReason,
8295
+ allowed_file_patterns: allowedFilePatterns
8562
8296
  };
8563
8297
  await this.logInteraction(
8564
8298
  context,
@@ -8725,23 +8459,17 @@ var ConductReviewHandler = class extends ConversationRequiredToolHandler {
8725
8459
  * Generate instructions for LLM to conduct guided review
8726
8460
  */
8727
8461
  async generateReviewInstructions(perspectives, currentPhase, targetPhase) {
8728
- const instructions = `Conduct a review of the ${currentPhase} phase before proceeding to ${targetPhase}.
8462
+ const perspectiveDetails = perspectives.map(
8463
+ (p, i) => `${i + 1}. **${p.perspective.toUpperCase()}**: ${p.prompt}`
8464
+ ).join("\n");
8465
+ const instructions = `Review ${currentPhase} phase before proceeding to ${targetPhase}.
8729
8466
 
8730
- First, identify the artifacts and decisions from the ${currentPhase} phase by:
8731
- 1. Reviewing the plan file to see completed tasks and key decisions
8732
- 2. Using git status/diff to see what files were changed (if in a git repository)
8733
- 3. Analyzing recent conversation history for important decisions
8467
+ **Check:** plan file (tasks/decisions), git diff (changes), conversation history.
8734
8468
 
8735
- Then, for each perspective below, analyze these artifacts and provide feedback:
8469
+ **Perspectives:**
8470
+ ${perspectiveDetails}
8736
8471
 
8737
- ${perspectives.map(
8738
- (p, i) => `**${i + 1}. ${p.perspective.toUpperCase()} PERSPECTIVE:**
8739
- ${p.prompt}
8740
-
8741
- `
8742
- ).join("")}
8743
-
8744
- After completing all perspective reviews, summarize your findings and ask the user if they're ready to proceed to the ${targetPhase} phase.`;
8472
+ Summarize findings and ask user if ready to proceed.`;
8745
8473
  return {
8746
8474
  instructions,
8747
8475
  perspectives: perspectives.map((p) => ({
@@ -8755,18 +8483,21 @@ After completing all perspective reviews, summarize your findings and ask the us
8755
8483
  // src/tool-handlers/start-development.ts
8756
8484
  import { basename as basename4 } from "path";
8757
8485
  import { readFileSync, writeFileSync, existsSync as existsSync3, mkdirSync } from "fs";
8758
- import { readFile as readFile5, writeFile as writeFile5 } from "fs/promises";
8486
+ import { readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
8759
8487
  import { resolve as resolve3 } from "path";
8760
- var logger25 = createLogger("StartDevelopmentHandler");
8761
8488
  var StartDevelopmentHandler = class extends BaseToolHandler {
8762
- projectDocsManager;
8763
- constructor() {
8764
- super();
8765
- this.projectDocsManager = new ProjectDocsManager();
8489
+ projectDocsManager = null;
8490
+ getProjectDocsManager() {
8491
+ if (!this.projectDocsManager) {
8492
+ this.projectDocsManager = new ProjectDocsManager(this.logger);
8493
+ }
8494
+ return this.projectDocsManager;
8766
8495
  }
8767
8496
  async executeHandler(args, context) {
8768
8497
  validateRequiredArgs(args, ["workflow"]);
8769
- const taskBackendConfig = TaskBackendManager.validateTaskBackend();
8498
+ const taskBackendConfig = TaskBackendManager.validateTaskBackend(
8499
+ this.logger
8500
+ );
8770
8501
  const selectedWorkflow = args.workflow;
8771
8502
  const requireReviews = args.require_reviews ?? false;
8772
8503
  const projectPath = stripVibePathSuffix(
@@ -8800,12 +8531,10 @@ var StartDevelopmentHandler = class extends BaseToolHandler {
8800
8531
  const suggestedBranchName = this.generateBranchSuggestion();
8801
8532
  const branchPromptResponse = {
8802
8533
  phase: "branch-prompt",
8803
- instructions: `You're currently on the ${currentBranch} branch. It's recommended to create a feature branch for development. Propose a branch creation by suggesting a branch command to the user call start_development again.
8804
-
8805
- Suggested command: \`git checkout -b ${suggestedBranchName}\`
8806
-
8807
- Please create a new branch and then call start_development again to begin development.`,
8808
- plan_file_path: ""
8534
+ instructions: `On ${currentBranch}. Create feature branch: \`git checkout -b ${suggestedBranchName}\`, then retry \`start_development\`.`,
8535
+ plan_file_path: "",
8536
+ allowed_file_patterns: ["**/*"]
8537
+ // Allow all files during branch prompt
8809
8538
  };
8810
8539
  this.logger.debug(
8811
8540
  "User on main/master branch, prompting for branch creation",
@@ -8863,6 +8592,8 @@ Please create a new branch and then call start_development again to begin develo
8863
8592
  workflow: selectedWorkflow,
8864
8593
  projectPath,
8865
8594
  gitBranch: conversationContext.gitBranch,
8595
+ planFileExists: true,
8596
+ // we just created/ensured the plan file exists
8866
8597
  stateMachine: {
8867
8598
  name: stateMachine.name,
8868
8599
  description: stateMachine.description,
@@ -8872,7 +8603,7 @@ Please create a new branch and then call start_development again to begin develo
8872
8603
  };
8873
8604
  if (context.pluginRegistry) {
8874
8605
  try {
8875
- const originalContent = await readFile5(
8606
+ const originalContent = await readFile4(
8876
8607
  conversationContext.planFilePath,
8877
8608
  "utf-8"
8878
8609
  );
@@ -8883,14 +8614,14 @@ Please create a new branch and then call start_development again to begin develo
8883
8614
  originalContent
8884
8615
  );
8885
8616
  if (modifiedContent && modifiedContent !== originalContent) {
8886
- await writeFile5(
8617
+ await writeFile4(
8887
8618
  conversationContext.planFilePath,
8888
8619
  modifiedContent,
8889
8620
  "utf-8"
8890
8621
  );
8891
8622
  }
8892
8623
  } catch (error) {
8893
- logger25.debug("Could not execute afterPlanFileCreated hook", {
8624
+ this.logger.debug("Could not execute afterPlanFileCreated hook", {
8894
8625
  error: error instanceof Error ? error.message : String(error),
8895
8626
  planFilePath: conversationContext.planFilePath
8896
8627
  });
@@ -8915,30 +8646,33 @@ Please create a new branch and then call start_development again to begin develo
8915
8646
  }
8916
8647
  this.ensureGitignoreEntry(projectPath);
8917
8648
  const workflowDocumentationUrl = this.generateWorkflowDocumentationUrl(selectedWorkflow);
8918
- const baseInstructions = `Look at the plan file (${conversationContext.planFilePath}). Define entrance criteria for each phase of the workflow except the initial phase. Those criteria shall be based on the contents of the previous phase.
8919
- Example:
8920
- \`\`\`
8921
- ## Design
8922
-
8923
- ### Phase Entrance Criteria:
8924
- - [ ] The requirements have been thoroughly defined.
8925
- - [ ] Alternatives have been evaluated and are documented.
8926
- - [ ] It's clear what's in scope and out of scope
8927
- \`\`\`
8928
-
8929
- IMPORTANT: Once you added reasonable entrance call the whats_next() tool to get guided instructions for the next current phase.`;
8930
- const i18nGuidance = `
8931
-
8932
- NOTE: If the user is communicating in a non-English language, please translate the plan file content to that language while keeping the structure intact, and continue all interactions in the user's language.`;
8933
- const workflowDocumentationInfo = workflowDocumentationUrl ? `
8934
-
8935
- Inform the user about the chose workflow: He can visit: ${workflowDocumentationUrl} to get detailed information.` : "";
8936
- const finalInstructions = baseInstructions + workflowDocumentationInfo + i18nGuidance;
8649
+ let finalInstructions = context.planManager.getInitialPlanGuidance(
8650
+ conversationContext.planFilePath,
8651
+ workflowDocumentationUrl
8652
+ );
8653
+ const phaseState = stateMachine.states[transitionResult.newPhase];
8654
+ const allowedFilePatterns = phaseState?.allowed_file_patterns ?? ["**/*"];
8655
+ if (context.pluginRegistry?.hasHook("afterInstructionsGenerated")) {
8656
+ const enriched = await context.pluginRegistry.executeHook(
8657
+ "afterInstructionsGenerated",
8658
+ pluginContext,
8659
+ {
8660
+ instructions: finalInstructions,
8661
+ planFilePath: conversationContext.planFilePath,
8662
+ phase: transitionResult.newPhase,
8663
+ instructionSource: "start_development"
8664
+ }
8665
+ );
8666
+ if (enriched && typeof enriched === "object" && "instructions" in enriched) {
8667
+ finalInstructions = enriched.instructions;
8668
+ }
8669
+ }
8937
8670
  const response = {
8938
8671
  phase: transitionResult.newPhase,
8939
8672
  instructions: finalInstructions,
8940
8673
  plan_file_path: conversationContext.planFilePath,
8941
- workflowDocumentationUrl
8674
+ workflowDocumentationUrl,
8675
+ allowed_file_patterns: allowedFilePatterns
8942
8676
  };
8943
8677
  await this.logInteraction(
8944
8678
  context,
@@ -8980,7 +8714,7 @@ Inform the user about the chose workflow: He can visit: ${workflowDocumentationU
8980
8714
  );
8981
8715
  return null;
8982
8716
  }
8983
- const docsInfo = await this.projectDocsManager.getProjectDocsInfo(projectPath);
8717
+ const docsInfo = await this.getProjectDocsManager().getProjectDocsInfo(projectPath);
8984
8718
  const missingDocs = this.getMissingReferencedDocuments(
8985
8719
  referencedVariables,
8986
8720
  docsInfo,
@@ -8998,9 +8732,7 @@ Inform the user about the chose workflow: He can visit: ${workflowDocumentationU
8998
8732
  }
8999
8733
  const setupGuidance = await this.generateArtifactSetupGuidance(
9000
8734
  missingDocs,
9001
- workflowName,
9002
- docsInfo,
9003
- referencedVariables
8735
+ workflowName
9004
8736
  );
9005
8737
  this.logger.info(
9006
8738
  "Missing required project artifacts detected for workflow that requires documentation",
@@ -9012,10 +8744,17 @@ Inform the user about the chose workflow: He can visit: ${workflowDocumentationU
9012
8744
  projectPath
9013
8745
  }
9014
8746
  );
8747
+ const initialPhase = stateMachine.initial_state;
8748
+ const initialPhaseState = stateMachine.states[initialPhase];
8749
+ const allowedFilePatterns = initialPhaseState?.allowed_file_patterns ?? [
8750
+ "**/*"
8751
+ ];
9015
8752
  return {
9016
8753
  phase: "artifact-setup",
9017
8754
  instructions: setupGuidance,
9018
- plan_file_path: ""
8755
+ plan_file_path: "",
8756
+ // Use the initial phase's file restrictions during artifact setup
8757
+ allowed_file_patterns: allowedFilePatterns
9019
8758
  };
9020
8759
  } catch (error) {
9021
8760
  this.logger.warn(
@@ -9032,7 +8771,7 @@ Inform the user about the chose workflow: He can visit: ${workflowDocumentationU
9032
8771
  * Analyze workflow content to detect document variable references
9033
8772
  */
9034
8773
  analyzeWorkflowDocumentReferences(stateMachine, projectPath) {
9035
- const variableSubstitutions = this.projectDocsManager.getVariableSubstitutions(projectPath);
8774
+ const variableSubstitutions = this.getProjectDocsManager().getVariableSubstitutions(projectPath);
9036
8775
  const documentVariables = Object.keys(variableSubstitutions);
9037
8776
  const referencedVariables = /* @__PURE__ */ new Set();
9038
8777
  const workflowContent = JSON.stringify(stateMachine);
@@ -9053,7 +8792,10 @@ Inform the user about the chose workflow: He can visit: ${workflowDocumentationU
9053
8792
  */
9054
8793
  getMissingReferencedDocuments(referencedVariables, docsInfo, projectPath) {
9055
8794
  const missingDocs = [];
9056
- const variableSubstitutions = this.projectDocsManager.getVariableSubstitutions(projectPath, void 0);
8795
+ const variableSubstitutions = this.getProjectDocsManager().getVariableSubstitutions(
8796
+ projectPath,
8797
+ void 0
8798
+ );
9057
8799
  const variableToDocMap = {};
9058
8800
  for (const [variable, path6] of Object.entries(variableSubstitutions)) {
9059
8801
  const filename = basename4(path6);
@@ -9074,115 +8816,15 @@ Inform the user about the chose workflow: He can visit: ${workflowDocumentationU
9074
8816
  /**
9075
8817
  * Generate guidance for setting up missing project artifacts
9076
8818
  */
9077
- async generateArtifactSetupGuidance(missingDocs, workflowName, docsInfo, referencedVariables) {
9078
- const missingList = missingDocs.map((doc) => `- ${doc}`).join("\n");
9079
- const existingDocs = [];
9080
- if (docsInfo.architecture.exists) {
9081
- const fileName = basename4(docsInfo.architecture.path);
9082
- existingDocs.push(`\u2705 ${fileName}`);
9083
- }
9084
- if (docsInfo.requirements.exists) {
9085
- const fileName = basename4(docsInfo.requirements.path);
9086
- existingDocs.push(`\u2705 ${fileName}`);
9087
- }
9088
- if (docsInfo.design.exists) {
9089
- const fileName = basename4(docsInfo.design.path);
9090
- existingDocs.push(`\u2705 ${fileName}`);
9091
- }
9092
- const existingList = existingDocs.length > 0 ? `
9093
-
9094
- **Existing Documents:**
9095
- ${existingDocs.join("\n")}` : "";
9096
- const referencedVariablesList = referencedVariables.map((v) => `\`${v}\``).join(", ");
9097
- const availableTemplates = await this.projectDocsManager.templateManager.getAvailableTemplates();
9098
- const defaults = await this.projectDocsManager.templateManager.getDefaults();
9099
- const templateOptionsText = this.generateTemplateOptionsText(availableTemplates);
9100
- return `## Project Documentation Setup Required
8819
+ async generateArtifactSetupGuidance(missingDocs, workflowName) {
8820
+ const availableTemplates = await this.getProjectDocsManager().templateManager.getAvailableTemplates();
8821
+ return `Missing docs for **${workflowName}**: ${missingDocs.join(", ")}
9101
8822
 
9102
- The **${workflowName}** workflow references project documentation that doesn't exist yet.
8823
+ Run \`setup_project_docs()\` with templates: ${Object.entries(
8824
+ availableTemplates
8825
+ ).map(([type2, templates]) => `${type2}: ${templates.join("/")}`).join("; ")}
9103
8826
 
9104
- **Referenced Variables:** ${referencedVariablesList}
9105
-
9106
- **Missing Documents:**
9107
- ${missingList}${existingList}
9108
-
9109
- ## \u{1F680} **Quick Setup**
9110
-
9111
- Use the \`setup_project_docs\` tool to create these documents with templates:
9112
-
9113
- \`\`\`
9114
- setup_project_docs({
9115
- architecture: "${defaults.architecture}", // or other available options
9116
- requirements: "${defaults.requirements}", // or other available options
9117
- design: "${defaults.design}" // or other available options
9118
- })
9119
- \`\`\`
9120
-
9121
- ${templateOptionsText}
9122
-
9123
- ## \u26A1 **Next Steps**
9124
-
9125
- 1. **Call \`setup_project_docs\`** with your preferred templates
9126
- 2. **Call \`start_development\`** again to begin the ${workflowName} workflow
9127
- 3. The workflow will reference these documents using the detected variables: ${referencedVariablesList}
9128
-
9129
- **Note:** You can also proceed without structured docs, but the workflow instructions will reference missing files.`;
9130
- }
9131
- /**
9132
- * Generate template options text dynamically
9133
- */
9134
- generateTemplateOptionsText(availableTemplates) {
9135
- const sections = [];
9136
- if (availableTemplates.architecture.length > 0) {
9137
- const archOptions = availableTemplates.architecture.map((template) => {
9138
- const description = this.getTemplateDescription(
9139
- template,
9140
- "architecture"
9141
- );
9142
- return `- **${template}**: ${description}`;
9143
- }).join("\n");
9144
- sections.push(`**Architecture Templates:**
9145
- ${archOptions}`);
9146
- }
9147
- if (availableTemplates.requirements.length > 0) {
9148
- const reqOptions = availableTemplates.requirements.map((template) => {
9149
- const description = this.getTemplateDescription(
9150
- template,
9151
- "requirements"
9152
- );
9153
- return `- **${template}**: ${description}`;
9154
- }).join("\n");
9155
- sections.push(`**Requirements Templates:**
9156
- ${reqOptions}`);
9157
- }
9158
- if (availableTemplates.design.length > 0) {
9159
- const designOptions = availableTemplates.design.map((template) => {
9160
- const description = this.getTemplateDescription(template, "design");
9161
- return `- **${template}**: ${description}`;
9162
- }).join("\n");
9163
- sections.push(`**Design Templates:**
9164
- ${designOptions}`);
9165
- }
9166
- return sections.length > 0 ? `## \u{1F4CB} **Template Options**
9167
-
9168
- ${sections.join("\n\n")}` : "";
9169
- }
9170
- /**
9171
- * Get description for a template based on its name and type
9172
- */
9173
- getTemplateDescription(template, type2) {
9174
- switch (template) {
9175
- case "arc42":
9176
- return "Comprehensive software architecture template with diagrams";
9177
- case "ears":
9178
- return "WHEN...THEN format for clear, testable requirements";
9179
- case "comprehensive":
9180
- return "Full implementation guide with testing strategy";
9181
- case "freestyle":
9182
- return `Simple, flexible ${type2} documentation`;
9183
- default:
9184
- return `${template} format for ${type2} documentation`;
9185
- }
8827
+ Then retry \`start_development\`.`;
9186
8828
  }
9187
8829
  /**
9188
8830
  * Generate workflow documentation URL for predefined workflows
@@ -9544,12 +9186,12 @@ var ResetDevelopmentHandler = class extends BaseToolHandler {
9544
9186
 
9545
9187
  // src/tool-handlers/list-workflows.ts
9546
9188
  import { z as z2 } from "zod";
9547
- var logger26 = createLogger("ListWorkflowsHandler");
9189
+ var logger16 = createLogger("ListWorkflowsHandler");
9548
9190
  var ListWorkflowsArgsSchema = z2.object({});
9549
9191
  var ListWorkflowsHandler = class extends BaseToolHandler {
9550
9192
  argsSchema = ListWorkflowsArgsSchema;
9551
9193
  async executeHandler(_args, context) {
9552
- logger26.info("Listing available workflows", {
9194
+ logger16.info("Listing available workflows", {
9553
9195
  projectPath: context.projectPath
9554
9196
  });
9555
9197
  const availableWorkflows = context.workflowManager.getAvailableWorkflowsForProject(
@@ -9564,7 +9206,7 @@ var ListWorkflowsHandler = class extends BaseToolHandler {
9564
9206
  const response = {
9565
9207
  workflows
9566
9208
  };
9567
- logger26.info("Successfully listed workflows", {
9209
+ logger16.info("Successfully listed workflows", {
9568
9210
  count: workflows.length,
9569
9211
  workflows: workflows.map((w) => w.name)
9570
9212
  });
@@ -9578,13 +9220,13 @@ import { z as z3 } from "zod";
9578
9220
  // src/version-info.ts
9579
9221
  import { execSync as execSync6 } from "child_process";
9580
9222
  import { readFileSync as readFileSync2 } from "fs";
9581
- import { join as join8, dirname as dirname7 } from "path";
9223
+ import { join as join8, dirname as dirname6 } from "path";
9582
9224
  import { fileURLToPath as fileURLToPath4 } from "url";
9583
- var logger27 = createLogger("VersionInfo");
9225
+ var logger17 = createLogger("VersionInfo");
9584
9226
  var BUILD_TIME_VERSION = null;
9585
9227
  function getVersionFromPackageJson() {
9586
9228
  try {
9587
- const currentDir = dirname7(fileURLToPath4(import.meta.url));
9229
+ const currentDir = dirname6(fileURLToPath4(import.meta.url));
9588
9230
  const packageJsonPaths = [
9589
9231
  join8(currentDir, "..", "package.json"),
9590
9232
  join8(currentDir, "..", "..", "..", "package.json")
@@ -9593,7 +9235,7 @@ function getVersionFromPackageJson() {
9593
9235
  try {
9594
9236
  const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
9595
9237
  if (packageJson.version) {
9596
- logger27.debug("Found version in package.json", {
9238
+ logger17.debug("Found version in package.json", {
9597
9239
  path: packageJsonPath,
9598
9240
  version: packageJson.version
9599
9241
  });
@@ -9603,7 +9245,7 @@ function getVersionFromPackageJson() {
9603
9245
  };
9604
9246
  }
9605
9247
  } catch (error) {
9606
- logger27.debug("Could not read package.json", {
9248
+ logger17.debug("Could not read package.json", {
9607
9249
  path: packageJsonPath,
9608
9250
  error: error instanceof Error ? error.message : String(error)
9609
9251
  });
@@ -9611,7 +9253,7 @@ function getVersionFromPackageJson() {
9611
9253
  }
9612
9254
  return null;
9613
9255
  } catch (error) {
9614
- logger27.debug("Error getting version from package.json", { error });
9256
+ logger17.debug("Error getting version from package.json", { error });
9615
9257
  return null;
9616
9258
  }
9617
9259
  }
@@ -9621,7 +9263,7 @@ function getVersionFromGit() {
9621
9263
  encoding: "utf-8",
9622
9264
  stdio: "pipe"
9623
9265
  }).trim();
9624
- logger27.debug("Git describe output", { gitDescribe });
9266
+ logger17.debug("Git describe output", { gitDescribe });
9625
9267
  const isDirty = gitDescribe.endsWith("-dirty");
9626
9268
  const cleanDescribe = isDirty ? gitDescribe.slice(0, -6) : gitDescribe;
9627
9269
  const parts = cleanDescribe.split("-");
@@ -9646,16 +9288,16 @@ function getVersionFromGit() {
9646
9288
  source: "git"
9647
9289
  };
9648
9290
  } catch (error) {
9649
- logger27.debug("Error getting version from git", {
9291
+ logger17.debug("Error getting version from git", {
9650
9292
  error: error instanceof Error ? error.message : String(error)
9651
9293
  });
9652
9294
  return null;
9653
9295
  }
9654
9296
  }
9655
9297
  function getVersionInfo() {
9656
- logger27.debug("Determining version information");
9298
+ logger17.debug("Determining version information");
9657
9299
  if (BUILD_TIME_VERSION) {
9658
- logger27.info("Using build-time version information", {
9300
+ logger17.info("Using build-time version information", {
9659
9301
  version: BUILD_TIME_VERSION.version,
9660
9302
  source: BUILD_TIME_VERSION.source
9661
9303
  });
@@ -9665,7 +9307,7 @@ function getVersionInfo() {
9665
9307
  if (gitVersion) {
9666
9308
  const packageVersion2 = getVersionFromPackageJson();
9667
9309
  if (packageVersion2 && gitVersion.version === "unknown") {
9668
- logger27.info("Using package.json version with git commit info", {
9310
+ logger17.info("Using package.json version with git commit info", {
9669
9311
  version: packageVersion2.version,
9670
9312
  commit: gitVersion.commit || "unknown",
9671
9313
  isDirty: String(gitVersion.isDirty || false)
@@ -9676,7 +9318,7 @@ function getVersionInfo() {
9676
9318
  source: "git"
9677
9319
  };
9678
9320
  }
9679
- logger27.info("Using git version information", {
9321
+ logger17.info("Using git version information", {
9680
9322
  version: gitVersion.version,
9681
9323
  source: gitVersion.source,
9682
9324
  commit: gitVersion.commit || "none",
@@ -9686,13 +9328,13 @@ function getVersionInfo() {
9686
9328
  }
9687
9329
  const packageVersion = getVersionFromPackageJson();
9688
9330
  if (packageVersion) {
9689
- logger27.info("Using package.json version information", {
9331
+ logger17.info("Using package.json version information", {
9690
9332
  version: packageVersion.version,
9691
9333
  source: packageVersion.source
9692
9334
  });
9693
9335
  return packageVersion;
9694
9336
  }
9695
- logger27.warn("Could not determine version information, using fallback");
9337
+ logger17.warn("Could not determine version information, using fallback");
9696
9338
  return {
9697
9339
  version: "unknown",
9698
9340
  source: "fallback"
@@ -9711,14 +9353,14 @@ function getFormattedVersion() {
9711
9353
  }
9712
9354
 
9713
9355
  // src/tool-handlers/get-tool-info.ts
9714
- var logger28 = createLogger("GetToolInfoHandler");
9356
+ var logger18 = createLogger("GetToolInfoHandler");
9715
9357
  var GetToolInfoArgsSchema = z3.object({
9716
9358
  // No input parameters needed
9717
9359
  });
9718
9360
  var GetToolInfoHandler = class extends BaseToolHandler {
9719
9361
  argsSchema = GetToolInfoArgsSchema;
9720
9362
  async executeHandler(_args, context) {
9721
- logger28.info("Generating comprehensive tool information", {
9363
+ logger18.info("Generating comprehensive tool information", {
9722
9364
  projectPath: context.projectPath
9723
9365
  });
9724
9366
  const availableWorkflows = context.workflowManager.getAvailableWorkflowsForProject(
@@ -9808,7 +9450,7 @@ var GetToolInfoHandler = class extends BaseToolHandler {
9808
9450
  plan_file_path: conversationContext.planFilePath
9809
9451
  };
9810
9452
  } catch (error) {
9811
- logger28.debug("No active conversation found for workflow state", {
9453
+ logger18.debug("No active conversation found for workflow state", {
9812
9454
  error
9813
9455
  });
9814
9456
  }
@@ -9835,7 +9477,7 @@ var GetToolInfoHandler = class extends BaseToolHandler {
9835
9477
  if (workflowState) {
9836
9478
  response.workflow_states = workflowState;
9837
9479
  }
9838
- logger28.info("Successfully generated tool information", {
9480
+ logger18.info("Successfully generated tool information", {
9839
9481
  toolCount: tools.length,
9840
9482
  workflowCount: workflows.length,
9841
9483
  hasWorkflowState: !!workflowState
@@ -9855,22 +9497,25 @@ var GetToolInfoHandler = class extends BaseToolHandler {
9855
9497
 
9856
9498
  // src/tool-handlers/setup-project-docs.ts
9857
9499
  var SetupProjectDocsHandler = class extends BaseToolHandler {
9858
- projectDocsManager;
9859
- constructor() {
9860
- super();
9861
- this.projectDocsManager = new ProjectDocsManager();
9500
+ projectDocsManager = null;
9501
+ getProjectDocsManager() {
9502
+ if (!this.projectDocsManager) {
9503
+ this.projectDocsManager = new ProjectDocsManager(this.logger);
9504
+ }
9505
+ return this.projectDocsManager;
9862
9506
  }
9863
9507
  async executeHandler(args, context) {
9864
9508
  const projectPath = stripVibePathSuffix(
9865
9509
  args.project_path,
9866
9510
  context.projectPath || process.cwd()
9867
9511
  );
9512
+ const projectDocsManager = this.getProjectDocsManager();
9868
9513
  this.logger.info(
9869
9514
  "Setting up project docs with enhanced file linking support",
9870
9515
  { args, projectPath }
9871
9516
  );
9872
9517
  try {
9873
- const availableTemplates = await this.projectDocsManager.templateManager.getAvailableTemplates();
9518
+ const availableTemplates = await projectDocsManager.templateManager.getAvailableTemplates();
9874
9519
  const processedArgs = await this.validateAndProcessArgs(
9875
9520
  args,
9876
9521
  availableTemplates,
@@ -9882,7 +9527,7 @@ var SetupProjectDocsHandler = class extends BaseToolHandler {
9882
9527
  created: [],
9883
9528
  linked: [],
9884
9529
  skipped: [],
9885
- paths: this.projectDocsManager.getDocumentPaths(projectPath),
9530
+ paths: projectDocsManager.getDocumentPaths(projectPath),
9886
9531
  message: processedArgs.error || "Unknown error during validation"
9887
9532
  };
9888
9533
  }
@@ -9891,12 +9536,12 @@ var SetupProjectDocsHandler = class extends BaseToolHandler {
9891
9536
  "Invalid processed args: missing templateOptions or filePaths"
9892
9537
  );
9893
9538
  }
9894
- const result = await this.projectDocsManager.createOrLinkProjectDocs(
9539
+ const result = await projectDocsManager.createOrLinkProjectDocs(
9895
9540
  projectPath,
9896
9541
  processedArgs.templateOptions,
9897
9542
  processedArgs.filePaths
9898
9543
  );
9899
- const paths = this.projectDocsManager.getDocumentPaths(projectPath);
9544
+ const paths = projectDocsManager.getDocumentPaths(projectPath);
9900
9545
  let message = "Project documentation setup completed.";
9901
9546
  if (result.created.length > 0) {
9902
9547
  message += ` Created: ${result.created.join(", ")}.`;
@@ -9931,7 +9576,7 @@ var SetupProjectDocsHandler = class extends BaseToolHandler {
9931
9576
  created: [],
9932
9577
  linked: [],
9933
9578
  skipped: [],
9934
- paths: this.projectDocsManager.getDocumentPaths(projectPath),
9579
+ paths: projectDocsManager.getDocumentPaths(projectPath),
9935
9580
  message: `Failed to setup project docs: ${error instanceof Error ? error.message : "Unknown error"}`
9936
9581
  };
9937
9582
  }
@@ -10009,11 +9654,11 @@ var NoIdeaHandler = class extends BaseToolHandler {
10009
9654
  };
10010
9655
 
10011
9656
  // src/tool-handlers/index.ts
10012
- var logger29 = createLogger("ToolRegistry");
9657
+ var logger19 = createLogger("ToolRegistry");
10013
9658
  var DefaultToolRegistry = class {
10014
9659
  handlers = /* @__PURE__ */ new Map();
10015
9660
  register(name, handler) {
10016
- logger29.debug("Registering tool handler", {
9661
+ logger19.debug("Registering tool handler", {
10017
9662
  name,
10018
9663
  handlerType: handler.constructor.name
10019
9664
  });
@@ -10038,17 +9683,24 @@ function createToolRegistry() {
10038
9683
  registry.register("get_tool_info", new GetToolInfoHandler());
10039
9684
  registry.register("setup_project_docs", new SetupProjectDocsHandler());
10040
9685
  registry.register("no_idea", new NoIdeaHandler());
10041
- logger29.info("Tool registry created with handlers", {
9686
+ logger19.info("Tool registry created with handlers", {
10042
9687
  handlers: registry.list()
10043
9688
  });
10044
9689
  return registry;
10045
9690
  }
10046
9691
 
10047
9692
  // src/resource-handlers/development-plan.ts
10048
- var logger30 = createLogger("DevelopmentPlanResourceHandler");
9693
+ var defaultLogger8 = createLogger("DevelopmentPlanResourceHandler");
10049
9694
  var DevelopmentPlanResourceHandler = class {
9695
+ logger;
9696
+ constructor(logger24) {
9697
+ this.logger = logger24 ?? defaultLogger8;
9698
+ }
10050
9699
  async handle(uri, context) {
10051
- logger30.debug("Processing development plan resource request", {
9700
+ if (context.loggerFactory) {
9701
+ this.logger = context.loggerFactory("DevelopmentPlanResourceHandler");
9702
+ }
9703
+ this.logger.debug("Processing development plan resource request", {
10052
9704
  uri: uri.href
10053
9705
  });
10054
9706
  return safeExecute(async () => {
@@ -10066,10 +9718,17 @@ var DevelopmentPlanResourceHandler = class {
10066
9718
  };
10067
9719
 
10068
9720
  // src/resource-handlers/conversation-state.ts
10069
- var logger31 = createLogger("ConversationStateResourceHandler");
9721
+ var defaultLogger9 = createLogger("ConversationStateResourceHandler");
10070
9722
  var ConversationStateResourceHandler = class {
9723
+ logger;
9724
+ constructor(logger24) {
9725
+ this.logger = logger24 ?? defaultLogger9;
9726
+ }
10071
9727
  async handle(uri, context) {
10072
- logger31.debug("Processing conversation state resource request", {
9728
+ if (context.loggerFactory) {
9729
+ this.logger = context.loggerFactory("ConversationStateResourceHandler");
9730
+ }
9731
+ this.logger.debug("Processing conversation state resource request", {
10073
9732
  uri: uri.href
10074
9733
  });
10075
9734
  return safeExecute(async () => {
@@ -10096,10 +9755,19 @@ var ConversationStateResourceHandler = class {
10096
9755
  import fs5 from "fs";
10097
9756
  import path5 from "path";
10098
9757
  import { fileURLToPath as fileURLToPath5 } from "url";
10099
- var logger32 = createLogger("WorkflowResourceHandler");
9758
+ var defaultLogger10 = createLogger("WorkflowResourceHandler");
10100
9759
  var WorkflowResourceHandler = class {
9760
+ logger;
9761
+ constructor(logger24) {
9762
+ this.logger = logger24 ?? defaultLogger10;
9763
+ }
10101
9764
  async handle(uri, context) {
10102
- logger32.debug("Processing workflow resource request", { uri: uri.href });
9765
+ if (context.loggerFactory) {
9766
+ this.logger = context.loggerFactory("WorkflowResourceHandler");
9767
+ }
9768
+ this.logger.debug("Processing workflow resource request", {
9769
+ uri: uri.href
9770
+ });
10103
9771
  return safeExecute(async () => {
10104
9772
  const workflowName = uri.hostname;
10105
9773
  if (!workflowName) {
@@ -10107,7 +9775,10 @@ var WorkflowResourceHandler = class {
10107
9775
  "Invalid workflow URI: missing workflow name. Expected: workflow://workflow-name"
10108
9776
  );
10109
9777
  }
10110
- logger32.info("Loading workflow resource", { workflowName, uri: uri.href });
9778
+ this.logger.info("Loading workflow resource", {
9779
+ workflowName,
9780
+ uri: uri.href
9781
+ });
10111
9782
  let yamlContent;
10112
9783
  let filePath;
10113
9784
  const workflow = context.workflowManager.getWorkflow(workflowName);
@@ -10137,7 +9808,7 @@ var WorkflowResourceHandler = class {
10137
9808
  `${workflowName}.yml`
10138
9809
  );
10139
9810
  if (!fs5.existsSync(workflowFileYml)) {
10140
- logger32.error(
9811
+ this.logger.error(
10141
9812
  "Workflow file not found",
10142
9813
  new Error(`Workflow '${workflowName}' not found`),
10143
9814
  {
@@ -10161,7 +9832,7 @@ var WorkflowResourceHandler = class {
10161
9832
  filePath = workflowFile;
10162
9833
  }
10163
9834
  yamlContent = fs5.readFileSync(filePath, "utf-8");
10164
- logger32.info("Successfully loaded workflow resource", {
9835
+ this.logger.info("Successfully loaded workflow resource", {
10165
9836
  workflowName,
10166
9837
  filePath,
10167
9838
  contentLength: yamlContent.length
@@ -10176,17 +9847,24 @@ var WorkflowResourceHandler = class {
10176
9847
  };
10177
9848
 
10178
9849
  // src/resource-handlers/system-prompt.ts
10179
- var logger33 = createLogger("SystemPromptResourceHandler");
9850
+ var defaultLogger11 = createLogger("SystemPromptResourceHandler");
10180
9851
  var SystemPromptResourceHandler = class {
10181
- async handle(uri, _context) {
10182
- logger33.debug("Processing system prompt resource request", {
9852
+ logger;
9853
+ constructor(logger24) {
9854
+ this.logger = logger24 ?? defaultLogger11;
9855
+ }
9856
+ async handle(uri, context) {
9857
+ if (context.loggerFactory) {
9858
+ this.logger = context.loggerFactory("SystemPromptResourceHandler");
9859
+ }
9860
+ this.logger.debug("Processing system prompt resource request", {
10183
9861
  uri: uri.href
10184
9862
  });
10185
9863
  return safeExecute(async () => {
10186
9864
  const loader2 = new StateMachineLoader();
10187
9865
  const stateMachine = loader2.loadStateMachine(process.cwd());
10188
9866
  const systemPrompt = generateSystemPrompt(stateMachine);
10189
- logger33.debug("Generated system prompt for resource", {
9867
+ this.logger.debug("Generated system prompt for resource", {
10190
9868
  promptLength: systemPrompt.length,
10191
9869
  workflowName: stateMachine.name
10192
9870
  });
@@ -10200,11 +9878,11 @@ var SystemPromptResourceHandler = class {
10200
9878
  };
10201
9879
 
10202
9880
  // src/resource-handlers/index.ts
10203
- var logger34 = createLogger("ResourceRegistry");
9881
+ var logger20 = createLogger("ResourceRegistry");
10204
9882
  var DefaultResourceRegistry = class {
10205
9883
  handlers = /* @__PURE__ */ new Map();
10206
9884
  register(pattern, handler) {
10207
- logger34.debug("Registering resource handler", {
9885
+ logger20.debug("Registering resource handler", {
10208
9886
  pattern,
10209
9887
  handlerType: handler.constructor.name
10210
9888
  });
@@ -10213,11 +9891,11 @@ var DefaultResourceRegistry = class {
10213
9891
  resolve(uri) {
10214
9892
  for (const [pattern, handler] of this.handlers.entries()) {
10215
9893
  if (uri.includes(pattern)) {
10216
- logger34.debug("Resolved resource handler", { uri, pattern });
9894
+ logger20.debug("Resolved resource handler", { uri, pattern });
10217
9895
  return handler;
10218
9896
  }
10219
9897
  }
10220
- logger34.debug("No resource handler found for URI", { uri });
9898
+ logger20.debug("No resource handler found for URI", { uri });
10221
9899
  return void 0;
10222
9900
  }
10223
9901
  };
@@ -10227,7 +9905,7 @@ function createResourceRegistry() {
10227
9905
  registry.register("state://current", new ConversationStateResourceHandler());
10228
9906
  registry.register("workflow://", new WorkflowResourceHandler());
10229
9907
  registry.register("system-prompt://", new SystemPromptResourceHandler());
10230
- logger34.info("Resource registry created with handlers", {
9908
+ logger20.info("Resource registry created with handlers", {
10231
9909
  patterns: [
10232
9910
  "plan://current",
10233
9911
  "state://current",
@@ -10239,13 +9917,13 @@ function createResourceRegistry() {
10239
9917
  }
10240
9918
 
10241
9919
  // src/response-renderer.ts
10242
- var logger35 = createLogger("ResponseRenderer");
9920
+ var logger21 = createLogger("ResponseRenderer");
10243
9921
  var DefaultResponseRenderer = class {
10244
9922
  /**
10245
9923
  * Render a tool handler result as an MCP tool response
10246
9924
  */
10247
9925
  renderToolResponse(result) {
10248
- logger35.debug("Rendering tool response", {
9926
+ logger21.debug("Rendering tool response", {
10249
9927
  success: result.success,
10250
9928
  hasData: !!result.data,
10251
9929
  hasError: !!result.error
@@ -10267,7 +9945,7 @@ var DefaultResponseRenderer = class {
10267
9945
  * Render a resource handler result as an MCP resource response
10268
9946
  */
10269
9947
  renderResourceResponse(result) {
10270
- logger35.debug("Rendering resource response", {
9948
+ logger21.debug("Rendering resource response", {
10271
9949
  success: result.success,
10272
9950
  hasData: !!result.data
10273
9951
  });
@@ -10298,7 +9976,7 @@ var DefaultResponseRenderer = class {
10298
9976
  */
10299
9977
  renderError(error) {
10300
9978
  const errorMessage = error instanceof Error ? error.message : error;
10301
- logger35.debug("Rendering error response", { errorMessage });
9979
+ logger21.debug("Rendering error response", { errorMessage });
10302
9980
  return {
10303
9981
  content: [
10304
9982
  {
@@ -10314,8 +9992,53 @@ function createResponseRenderer() {
10314
9992
  return new DefaultResponseRenderer();
10315
9993
  }
10316
9994
 
9995
+ // src/mcp-log-sink.ts
9996
+ function capitalizePhase2(phase) {
9997
+ return phase.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
9998
+ }
9999
+ function createMcpLogSink(mcpServer) {
10000
+ return {
10001
+ async log(level, logger24, message, context) {
10002
+ try {
10003
+ let enhancedMessage = message;
10004
+ let notificationLevel = level;
10005
+ if (context && (context["from"] || context["to"]) && message.includes("transition")) {
10006
+ const from = context["from"] ? capitalizePhase2(context["from"]) : "";
10007
+ const to = context["to"] ? capitalizePhase2(context["to"]) : "";
10008
+ if (from && to) {
10009
+ enhancedMessage = `Phase Transition: ${from} \u2192 ${to}`;
10010
+ notificationLevel = "info";
10011
+ }
10012
+ }
10013
+ if (message.includes("initialized successfully")) {
10014
+ enhancedMessage = "\u{1F680} Vibe Feature MCP Server Ready";
10015
+ notificationLevel = "info";
10016
+ }
10017
+ let logData = enhancedMessage;
10018
+ if (context) {
10019
+ try {
10020
+ const contextStr = JSON.stringify(context, null, 0);
10021
+ logData = `${enhancedMessage} ${contextStr}`;
10022
+ } catch (_error) {
10023
+ logData = `${enhancedMessage} [context serialization failed]`;
10024
+ }
10025
+ }
10026
+ await mcpServer.server.notification({
10027
+ method: "notifications/message",
10028
+ params: {
10029
+ level: notificationLevel,
10030
+ logger: logger24,
10031
+ data: logData
10032
+ }
10033
+ });
10034
+ } catch (_error) {
10035
+ }
10036
+ }
10037
+ };
10038
+ }
10039
+
10317
10040
  // src/server-implementation.ts
10318
- var logger36 = createLogger("ResponsibleVibeMCPServer");
10041
+ var logger22 = createLogger("ResponsibleVibeMCPServer");
10319
10042
  async function createResponsibleVibeMCPServer(config = {}) {
10320
10043
  const components = await initializeServerComponents(config);
10321
10044
  return new ResponsibleVibeMCPServer(config, components);
@@ -10324,7 +10047,7 @@ var ResponsibleVibeMCPServer = class {
10324
10047
  constructor(config, serverComponents) {
10325
10048
  this.config = config;
10326
10049
  this.serverComponents = serverComponents;
10327
- logger36.debug("ResponsibleVibeMCPServer created", {
10050
+ logger22.debug("ResponsibleVibeMCPServer created", {
10328
10051
  config: JSON.stringify(this.config)
10329
10052
  });
10330
10053
  }
@@ -10333,7 +10056,7 @@ var ResponsibleVibeMCPServer = class {
10333
10056
  * Initialize the server and all its components
10334
10057
  */
10335
10058
  async initialize() {
10336
- logger36.debug("Initializing ResponsibleVibeMCPServer");
10059
+ logger22.debug("Initializing ResponsibleVibeMCPServer");
10337
10060
  try {
10338
10061
  this.components = this.serverComponents;
10339
10062
  const toolRegistry = createToolRegistry();
@@ -10342,7 +10065,7 @@ var ResponsibleVibeMCPServer = class {
10342
10065
  this.components.toolRegistry = toolRegistry;
10343
10066
  this.components.resourceRegistry = resourceRegistry;
10344
10067
  this.components.responseRenderer = responseRenderer;
10345
- setMcpServerForLogging(this.components.mcpServer);
10068
+ registerLogSink(createMcpLogSink(this.components.mcpServer));
10346
10069
  await registerMcpTools(
10347
10070
  this.components.mcpServer,
10348
10071
  toolRegistry,
@@ -10356,7 +10079,7 @@ var ResponsibleVibeMCPServer = class {
10356
10079
  this.components.context
10357
10080
  );
10358
10081
  } catch (error) {
10359
- logger36.error(
10082
+ logger22.error(
10360
10083
  "Failed to initialize ResponsibleVibeMCPServer",
10361
10084
  error
10362
10085
  );
@@ -10489,16 +10212,16 @@ var ResponsibleVibeMCPServer = class {
10489
10212
  * Cleanup server resources
10490
10213
  */
10491
10214
  async cleanup() {
10492
- logger36.debug("Cleaning up server resources");
10215
+ logger22.debug("Cleaning up server resources");
10493
10216
  if (this.components?.database) {
10494
10217
  await this.components.database.close();
10495
10218
  }
10496
- logger36.info("Server cleanup completed");
10219
+ logger22.info("Server cleanup completed");
10497
10220
  }
10498
10221
  };
10499
10222
 
10500
10223
  // src/index.ts
10501
- var logger37 = createLogger("Main");
10224
+ var logger23 = createLogger("Main");
10502
10225
  function parseCliArgs() {
10503
10226
  return { shouldStartServer: true };
10504
10227
  }
@@ -10516,30 +10239,46 @@ async function main() {
10516
10239
  const transport = new StdioServerTransport();
10517
10240
  await server.getMcpServer().connect(transport);
10518
10241
  process.on("SIGINT", async () => {
10519
- logger37.info("Shutting down Vibe Feature MCP Server...");
10242
+ logger23.info("Shutting down Vibe Feature MCP Server...");
10520
10243
  await server.cleanup();
10521
10244
  process.exit(0);
10522
10245
  });
10523
10246
  process.on("SIGTERM", async () => {
10524
- logger37.info("Shutting down Vibe Feature MCP Server...");
10247
+ logger23.info("Shutting down Vibe Feature MCP Server...");
10525
10248
  await server.cleanup();
10526
10249
  process.exit(0);
10527
10250
  });
10528
10251
  } catch (error) {
10529
- logger37.error("Failed to start server", error);
10252
+ logger23.error("Failed to start server", error);
10530
10253
  process.exit(1);
10531
10254
  }
10532
10255
  }
10533
10256
  var isMainModule = import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith("ade-workflows-server") || process.argv[1]?.endsWith("index.js");
10534
10257
  if (isMainModule) {
10535
10258
  await main().catch((error) => {
10536
- logger37.error("Unhandled error in main", error);
10259
+ logger23.error("Unhandled error in main", error);
10537
10260
  process.exit(1);
10538
10261
  });
10539
10262
  }
10540
10263
  export {
10264
+ BaseToolHandler,
10265
+ BeadsPlugin,
10266
+ ConductReviewHandler,
10267
+ ConversationRequiredToolHandler,
10268
+ DefaultToolRegistry,
10269
+ GetToolInfoHandler,
10270
+ ListWorkflowsHandler,
10271
+ NoIdeaHandler,
10272
+ PluginRegistry,
10273
+ ProceedToPhaseHandler,
10274
+ ResetDevelopmentHandler,
10541
10275
  ResponsibleVibeMCPServer,
10276
+ ResumeWorkflowHandler,
10277
+ SetupProjectDocsHandler,
10278
+ StartDevelopmentHandler,
10279
+ WhatsNextHandler,
10542
10280
  createResponsibleVibeMCPServer,
10281
+ createToolRegistry,
10543
10282
  main as startMcpServer
10544
10283
  };
10545
10284
  /*! Bundled license information: